OSDN Git Service

2007-01-04 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 && !arm_arch6"
1105   "mul%?\\t%0, %2, %1"
1106   [(set_attr "insn" "mul")
1107    (set_attr "predicable" "yes")]
1108 )
1109
1110 (define_insn "*arm_mulsi3_v6"
1111   [(set (match_operand:SI          0 "s_register_operand" "=r")
1112         (mult:SI (match_operand:SI 1 "s_register_operand" "r")
1113                  (match_operand:SI 2 "s_register_operand" "r")))]
1114   "TARGET_32BIT && arm_arch6"
1115   "mul%?\\t%0, %1, %2"
1116   [(set_attr "insn" "mul")
1117    (set_attr "predicable" "yes")]
1118 )
1119
1120 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1121 ; 1 and 2; are the same, because reload will make operand 0 match 
1122 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1123 ; this by adding another alternative to match this case, and then `reload' 
1124 ; it ourselves.  This alternative must come first.
1125 (define_insn "*thumb_mulsi3"
1126   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1127         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1128                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1129   "TARGET_THUMB1 && !arm_arch6"
1130   "*
1131   if (which_alternative < 2)
1132     return \"mov\\t%0, %1\;mul\\t%0, %2\";
1133   else
1134     return \"mul\\t%0, %2\";
1135   "
1136   [(set_attr "length" "4,4,2")
1137    (set_attr "insn" "mul")]
1138 )
1139
1140 (define_insn "*thumb_mulsi3_v6"
1141   [(set (match_operand:SI          0 "register_operand" "=l,l,l")
1142         (mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
1143                  (match_operand:SI 2 "register_operand" "l,0,0")))]
1144   "TARGET_THUMB1 && arm_arch6"
1145   "@
1146    mul\\t%0, %2 
1147    mul\\t%0, %1 
1148    mul\\t%0, %1"
1149   [(set_attr "length" "2")
1150    (set_attr "insn" "mul")]
1151 )
1152
1153 (define_insn "*mulsi3_compare0"
1154   [(set (reg:CC_NOOV CC_REGNUM)
1155         (compare:CC_NOOV (mult:SI
1156                           (match_operand:SI 2 "s_register_operand" "r,r")
1157                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1158                          (const_int 0)))
1159    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1160         (mult:SI (match_dup 2) (match_dup 1)))]
1161   "TARGET_ARM && !arm_arch6"
1162   "mul%.\\t%0, %2, %1"
1163   [(set_attr "conds" "set")
1164    (set_attr "insn" "muls")]
1165 )
1166
1167 (define_insn "*mulsi3_compare0_v6"
1168   [(set (reg:CC_NOOV CC_REGNUM)
1169         (compare:CC_NOOV (mult:SI
1170                           (match_operand:SI 2 "s_register_operand" "r")
1171                           (match_operand:SI 1 "s_register_operand" "r"))
1172                          (const_int 0)))
1173    (set (match_operand:SI 0 "s_register_operand" "=r")
1174         (mult:SI (match_dup 2) (match_dup 1)))]
1175   "TARGET_ARM && arm_arch6 && optimize_size"
1176   "mul%.\\t%0, %2, %1"
1177   [(set_attr "conds" "set")
1178    (set_attr "insn" "muls")]
1179 )
1180
1181 (define_insn "*mulsi_compare0_scratch"
1182   [(set (reg:CC_NOOV CC_REGNUM)
1183         (compare:CC_NOOV (mult:SI
1184                           (match_operand:SI 2 "s_register_operand" "r,r")
1185                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1186                          (const_int 0)))
1187    (clobber (match_scratch:SI 0 "=&r,&r"))]
1188   "TARGET_ARM && !arm_arch6"
1189   "mul%.\\t%0, %2, %1"
1190   [(set_attr "conds" "set")
1191    (set_attr "insn" "muls")]
1192 )
1193
1194 (define_insn "*mulsi_compare0_scratch_v6"
1195   [(set (reg:CC_NOOV CC_REGNUM)
1196         (compare:CC_NOOV (mult:SI
1197                           (match_operand:SI 2 "s_register_operand" "r")
1198                           (match_operand:SI 1 "s_register_operand" "r"))
1199                          (const_int 0)))
1200    (clobber (match_scratch:SI 0 "=r"))]
1201   "TARGET_ARM && arm_arch6 && optimize_size"
1202   "mul%.\\t%0, %2, %1"
1203   [(set_attr "conds" "set")
1204    (set_attr "insn" "muls")]
1205 )
1206
1207 ;; Unnamed templates to match MLA instruction.
1208
1209 (define_insn "*mulsi3addsi"
1210   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1211         (plus:SI
1212           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1213                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1214           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1215   "TARGET_32BIT && !arm_arch6"
1216   "mla%?\\t%0, %2, %1, %3"
1217   [(set_attr "insn" "mla")
1218    (set_attr "predicable" "yes")]
1219 )
1220
1221 (define_insn "*mulsi3addsi_v6"
1222   [(set (match_operand:SI 0 "s_register_operand" "=r")
1223         (plus:SI
1224           (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1225                    (match_operand:SI 1 "s_register_operand" "r"))
1226           (match_operand:SI 3 "s_register_operand" "r")))]
1227   "TARGET_32BIT && arm_arch6"
1228   "mla%?\\t%0, %2, %1, %3"
1229   [(set_attr "insn" "mla")
1230    (set_attr "predicable" "yes")]
1231 )
1232
1233 (define_insn "*mulsi3addsi_compare0"
1234   [(set (reg:CC_NOOV CC_REGNUM)
1235         (compare:CC_NOOV
1236          (plus:SI (mult:SI
1237                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1238                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1239                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1240          (const_int 0)))
1241    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1242         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1243                  (match_dup 3)))]
1244   "TARGET_ARM && arm_arch6"
1245   "mla%.\\t%0, %2, %1, %3"
1246   [(set_attr "conds" "set")
1247    (set_attr "insn" "mlas")]
1248 )
1249
1250 (define_insn "*mulsi3addsi_compare0_v6"
1251   [(set (reg:CC_NOOV CC_REGNUM)
1252         (compare:CC_NOOV
1253          (plus:SI (mult:SI
1254                    (match_operand:SI 2 "s_register_operand" "r")
1255                    (match_operand:SI 1 "s_register_operand" "r"))
1256                   (match_operand:SI 3 "s_register_operand" "r"))
1257          (const_int 0)))
1258    (set (match_operand:SI 0 "s_register_operand" "=r")
1259         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1260                  (match_dup 3)))]
1261   "TARGET_ARM && arm_arch6 && optimize_size"
1262   "mla%.\\t%0, %2, %1, %3"
1263   [(set_attr "conds" "set")
1264    (set_attr "insn" "mlas")]
1265 )
1266
1267 (define_insn "*mulsi3addsi_compare0_scratch"
1268   [(set (reg:CC_NOOV CC_REGNUM)
1269         (compare:CC_NOOV
1270          (plus:SI (mult:SI
1271                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1272                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1273                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1274          (const_int 0)))
1275    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1276   "TARGET_ARM && !arm_arch6"
1277   "mla%.\\t%0, %2, %1, %3"
1278   [(set_attr "conds" "set")
1279    (set_attr "insn" "mlas")]
1280 )
1281
1282 (define_insn "*mulsi3addsi_compare0_scratch_v6"
1283   [(set (reg:CC_NOOV CC_REGNUM)
1284         (compare:CC_NOOV
1285          (plus:SI (mult:SI
1286                    (match_operand:SI 2 "s_register_operand" "r")
1287                    (match_operand:SI 1 "s_register_operand" "r"))
1288                   (match_operand:SI 3 "s_register_operand" "r"))
1289          (const_int 0)))
1290    (clobber (match_scratch:SI 0 "=r"))]
1291   "TARGET_ARM && arm_arch6 && optimize_size"
1292   "mla%.\\t%0, %2, %1, %3"
1293   [(set_attr "conds" "set")
1294    (set_attr "insn" "mlas")]
1295 )
1296
1297 ;; Unnamed template to match long long multiply-accumulate (smlal)
1298
1299 (define_insn "*mulsidi3adddi"
1300   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1301         (plus:DI
1302          (mult:DI
1303           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1304           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1305          (match_operand:DI 1 "s_register_operand" "0")))]
1306   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1307   "smlal%?\\t%Q0, %R0, %3, %2"
1308   [(set_attr "insn" "smlal")
1309    (set_attr "predicable" "yes")]
1310 )
1311
1312 (define_insn "*mulsidi3adddi_v6"
1313   [(set (match_operand:DI 0 "s_register_operand" "=r")
1314         (plus:DI
1315          (mult:DI
1316           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1317           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1318          (match_operand:DI 1 "s_register_operand" "0")))]
1319   "TARGET_32BIT && arm_arch6"
1320   "smlal%?\\t%Q0, %R0, %3, %2"
1321   [(set_attr "insn" "smlal")
1322    (set_attr "predicable" "yes")]
1323 )
1324
1325 (define_insn "mulsidi3"
1326   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1327         (mult:DI
1328          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1329          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1330   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1331   "smull%?\\t%Q0, %R0, %1, %2"
1332   [(set_attr "insn" "smull")
1333    (set_attr "predicable" "yes")]
1334 )
1335
1336 (define_insn "mulsidi3_v6"
1337   [(set (match_operand:DI 0 "s_register_operand" "=r")
1338         (mult:DI
1339          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1340          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1341   "TARGET_32BIT && arm_arch6"
1342   "smull%?\\t%Q0, %R0, %1, %2"
1343   [(set_attr "insn" "smull")
1344    (set_attr "predicable" "yes")]
1345 )
1346
1347 (define_insn "umulsidi3"
1348   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1349         (mult:DI
1350          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1351          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1352   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1353   "umull%?\\t%Q0, %R0, %1, %2"
1354   [(set_attr "insn" "umull")
1355    (set_attr "predicable" "yes")]
1356 )
1357
1358 (define_insn "umulsidi3_v6"
1359   [(set (match_operand:DI 0 "s_register_operand" "=r")
1360         (mult:DI
1361          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1362          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1363   "TARGET_32BIT && arm_arch6"
1364   "umull%?\\t%Q0, %R0, %1, %2"
1365   [(set_attr "insn" "umull")
1366    (set_attr "predicable" "yes")]
1367 )
1368
1369 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1370
1371 (define_insn "*umulsidi3adddi"
1372   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1373         (plus:DI
1374          (mult:DI
1375           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1376           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1377          (match_operand:DI 1 "s_register_operand" "0")))]
1378   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1379   "umlal%?\\t%Q0, %R0, %3, %2"
1380   [(set_attr "insn" "umlal")
1381    (set_attr "predicable" "yes")]
1382 )
1383
1384 (define_insn "*umulsidi3adddi_v6"
1385   [(set (match_operand:DI 0 "s_register_operand" "=r")
1386         (plus:DI
1387          (mult:DI
1388           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1389           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1390          (match_operand:DI 1 "s_register_operand" "0")))]
1391   "TARGET_32BIT && arm_arch6"
1392   "umlal%?\\t%Q0, %R0, %3, %2"
1393   [(set_attr "insn" "umlal")
1394    (set_attr "predicable" "yes")]
1395 )
1396
1397 (define_insn "smulsi3_highpart"
1398   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1399         (truncate:SI
1400          (lshiftrt:DI
1401           (mult:DI
1402            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1403            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1404           (const_int 32))))
1405    (clobber (match_scratch:SI 3 "=&r,&r"))]
1406   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1407   "smull%?\\t%3, %0, %2, %1"
1408   [(set_attr "insn" "smull")
1409    (set_attr "predicable" "yes")]
1410 )
1411
1412 (define_insn "smulsi3_highpart_v6"
1413   [(set (match_operand:SI 0 "s_register_operand" "=r")
1414         (truncate:SI
1415          (lshiftrt:DI
1416           (mult:DI
1417            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1418            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1419           (const_int 32))))
1420    (clobber (match_scratch:SI 3 "=r"))]
1421   "TARGET_32BIT && arm_arch6"
1422   "smull%?\\t%3, %0, %2, %1"
1423   [(set_attr "insn" "smull")
1424    (set_attr "predicable" "yes")]
1425 )
1426
1427 (define_insn "umulsi3_highpart"
1428   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1429         (truncate:SI
1430          (lshiftrt:DI
1431           (mult:DI
1432            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1433            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1434           (const_int 32))))
1435    (clobber (match_scratch:SI 3 "=&r,&r"))]
1436   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1437   "umull%?\\t%3, %0, %2, %1"
1438   [(set_attr "insn" "umull")
1439    (set_attr "predicable" "yes")]
1440 )
1441
1442 (define_insn "umulsi3_highpart_v6"
1443   [(set (match_operand:SI 0 "s_register_operand" "=r")
1444         (truncate:SI
1445          (lshiftrt:DI
1446           (mult:DI
1447            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1448            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1449           (const_int 32))))
1450    (clobber (match_scratch:SI 3 "=r"))]
1451   "TARGET_32BIT && arm_arch6"
1452   "umull%?\\t%3, %0, %2, %1"
1453   [(set_attr "insn" "umull")
1454    (set_attr "predicable" "yes")]
1455 )
1456
1457 (define_insn "mulhisi3"
1458   [(set (match_operand:SI 0 "s_register_operand" "=r")
1459         (mult:SI (sign_extend:SI
1460                   (match_operand:HI 1 "s_register_operand" "%r"))
1461                  (sign_extend:SI
1462                   (match_operand:HI 2 "s_register_operand" "r"))))]
1463   "TARGET_DSP_MULTIPLY"
1464   "smulbb%?\\t%0, %1, %2"
1465   [(set_attr "insn" "smulxy")
1466    (set_attr "predicable" "yes")]
1467 )
1468
1469 (define_insn "*mulhisi3tb"
1470   [(set (match_operand:SI 0 "s_register_operand" "=r")
1471         (mult:SI (ashiftrt:SI
1472                   (match_operand:SI 1 "s_register_operand" "r")
1473                   (const_int 16))
1474                  (sign_extend:SI
1475                   (match_operand:HI 2 "s_register_operand" "r"))))]
1476   "TARGET_DSP_MULTIPLY"
1477   "smultb%?\\t%0, %1, %2"
1478   [(set_attr "insn" "smulxy")
1479    (set_attr "predicable" "yes")]
1480 )
1481
1482 (define_insn "*mulhisi3bt"
1483   [(set (match_operand:SI 0 "s_register_operand" "=r")
1484         (mult:SI (sign_extend:SI
1485                   (match_operand:HI 1 "s_register_operand" "r"))
1486                  (ashiftrt:SI
1487                   (match_operand:SI 2 "s_register_operand" "r")
1488                   (const_int 16))))]
1489   "TARGET_DSP_MULTIPLY"
1490   "smulbt%?\\t%0, %1, %2"
1491   [(set_attr "insn" "smulxy")
1492    (set_attr "predicable" "yes")]
1493 )
1494
1495 (define_insn "*mulhisi3tt"
1496   [(set (match_operand:SI 0 "s_register_operand" "=r")
1497         (mult:SI (ashiftrt:SI
1498                   (match_operand:SI 1 "s_register_operand" "r")
1499                   (const_int 16))
1500                  (ashiftrt:SI
1501                   (match_operand:SI 2 "s_register_operand" "r")
1502                   (const_int 16))))]
1503   "TARGET_DSP_MULTIPLY"
1504   "smultt%?\\t%0, %1, %2"
1505   [(set_attr "insn" "smulxy")
1506    (set_attr "predicable" "yes")]
1507 )
1508
1509 (define_insn "*mulhisi3addsi"
1510   [(set (match_operand:SI 0 "s_register_operand" "=r")
1511         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1512                  (mult:SI (sign_extend:SI
1513                            (match_operand:HI 2 "s_register_operand" "%r"))
1514                           (sign_extend:SI
1515                            (match_operand:HI 3 "s_register_operand" "r")))))]
1516   "TARGET_DSP_MULTIPLY"
1517   "smlabb%?\\t%0, %2, %3, %1"
1518   [(set_attr "insn" "smlaxy")
1519    (set_attr "predicable" "yes")]
1520 )
1521
1522 (define_insn "*mulhidi3adddi"
1523   [(set (match_operand:DI 0 "s_register_operand" "=r")
1524         (plus:DI
1525           (match_operand:DI 1 "s_register_operand" "0")
1526           (mult:DI (sign_extend:DI
1527                     (match_operand:HI 2 "s_register_operand" "%r"))
1528                    (sign_extend:DI
1529                     (match_operand:HI 3 "s_register_operand" "r")))))]
1530   "TARGET_DSP_MULTIPLY"
1531   "smlalbb%?\\t%Q0, %R0, %2, %3"
1532   [(set_attr "insn" "smlalxy")
1533    (set_attr "predicable" "yes")])
1534
1535 (define_expand "mulsf3"
1536   [(set (match_operand:SF          0 "s_register_operand" "")
1537         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1538                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1539   "TARGET_32BIT && TARGET_HARD_FLOAT"
1540   "
1541   if (TARGET_MAVERICK
1542       && !cirrus_fp_register (operands[2], SFmode))
1543     operands[2] = force_reg (SFmode, operands[2]);
1544 ")
1545
1546 (define_expand "muldf3"
1547   [(set (match_operand:DF          0 "s_register_operand" "")
1548         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1549                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1550   "TARGET_32BIT && TARGET_HARD_FLOAT"
1551   "
1552   if (TARGET_MAVERICK
1553       && !cirrus_fp_register (operands[2], DFmode))
1554     operands[2] = force_reg (DFmode, operands[2]);
1555 ")
1556 \f
1557 ;; Division insns
1558
1559 (define_expand "divsf3"
1560   [(set (match_operand:SF 0 "s_register_operand" "")
1561         (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1562                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1563   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1564   "")
1565
1566 (define_expand "divdf3"
1567   [(set (match_operand:DF 0 "s_register_operand" "")
1568         (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1569                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1570   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1571   "")
1572 \f
1573 ;; Modulo insns
1574
1575 (define_expand "modsf3"
1576   [(set (match_operand:SF 0 "s_register_operand" "")
1577         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1578                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1579   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
1580   "")
1581
1582 (define_expand "moddf3"
1583   [(set (match_operand:DF 0 "s_register_operand" "")
1584         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1585                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1586   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
1587   "")
1588 \f
1589 ;; Boolean and,ior,xor insns
1590
1591 ;; Split up double word logical operations
1592
1593 ;; Split up simple DImode logical operations.  Simply perform the logical
1594 ;; operation on the upper and lower halves of the registers.
1595 (define_split
1596   [(set (match_operand:DI 0 "s_register_operand" "")
1597         (match_operator:DI 6 "logical_binary_operator"
1598           [(match_operand:DI 1 "s_register_operand" "")
1599            (match_operand:DI 2 "s_register_operand" "")]))]
1600   "TARGET_32BIT && reload_completed
1601    && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1602   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1603    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1604   "
1605   {
1606     operands[3] = gen_highpart (SImode, operands[0]);
1607     operands[0] = gen_lowpart (SImode, operands[0]);
1608     operands[4] = gen_highpart (SImode, operands[1]);
1609     operands[1] = gen_lowpart (SImode, operands[1]);
1610     operands[5] = gen_highpart (SImode, operands[2]);
1611     operands[2] = gen_lowpart (SImode, operands[2]);
1612   }"
1613 )
1614
1615 (define_split
1616   [(set (match_operand:DI 0 "s_register_operand" "")
1617         (match_operator:DI 6 "logical_binary_operator"
1618           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1619            (match_operand:DI 1 "s_register_operand" "")]))]
1620   "TARGET_32BIT && reload_completed"
1621   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1622    (set (match_dup 3) (match_op_dup:SI 6
1623                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1624                          (match_dup 4)]))]
1625   "
1626   {
1627     operands[3] = gen_highpart (SImode, operands[0]);
1628     operands[0] = gen_lowpart (SImode, operands[0]);
1629     operands[4] = gen_highpart (SImode, operands[1]);
1630     operands[1] = gen_lowpart (SImode, operands[1]);
1631     operands[5] = gen_highpart (SImode, operands[2]);
1632     operands[2] = gen_lowpart (SImode, operands[2]);
1633   }"
1634 )
1635
1636 ;; The zero extend of operand 2 means we can just copy the high part of
1637 ;; operand1 into operand0.
1638 (define_split
1639   [(set (match_operand:DI 0 "s_register_operand" "")
1640         (ior:DI
1641           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1642           (match_operand:DI 1 "s_register_operand" "")))]
1643   "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
1644   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1645    (set (match_dup 3) (match_dup 4))]
1646   "
1647   {
1648     operands[4] = gen_highpart (SImode, operands[1]);
1649     operands[3] = gen_highpart (SImode, operands[0]);
1650     operands[0] = gen_lowpart (SImode, operands[0]);
1651     operands[1] = gen_lowpart (SImode, operands[1]);
1652   }"
1653 )
1654
1655 ;; The zero extend of operand 2 means we can just copy the high part of
1656 ;; operand1 into operand0.
1657 (define_split
1658   [(set (match_operand:DI 0 "s_register_operand" "")
1659         (xor:DI
1660           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1661           (match_operand:DI 1 "s_register_operand" "")))]
1662   "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
1663   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1664    (set (match_dup 3) (match_dup 4))]
1665   "
1666   {
1667     operands[4] = gen_highpart (SImode, operands[1]);
1668     operands[3] = gen_highpart (SImode, operands[0]);
1669     operands[0] = gen_lowpart (SImode, operands[0]);
1670     operands[1] = gen_lowpart (SImode, operands[1]);
1671   }"
1672 )
1673
1674 (define_insn "anddi3"
1675   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1676         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1677                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1678   "TARGET_32BIT && ! TARGET_IWMMXT"
1679   "#"
1680   [(set_attr "length" "8")]
1681 )
1682
1683 (define_insn_and_split "*anddi_zesidi_di"
1684   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1685         (and:DI (zero_extend:DI
1686                  (match_operand:SI 2 "s_register_operand" "r,r"))
1687                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1688   "TARGET_32BIT"
1689   "#"
1690   "TARGET_32BIT && reload_completed"
1691   ; The zero extend of operand 2 clears the high word of the output
1692   ; operand.
1693   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1694    (set (match_dup 3) (const_int 0))]
1695   "
1696   {
1697     operands[3] = gen_highpart (SImode, operands[0]);
1698     operands[0] = gen_lowpart (SImode, operands[0]);
1699     operands[1] = gen_lowpart (SImode, operands[1]);
1700   }"
1701   [(set_attr "length" "8")]
1702 )
1703
1704 (define_insn "*anddi_sesdi_di"
1705   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1706         (and:DI (sign_extend:DI
1707                  (match_operand:SI 2 "s_register_operand" "r,r"))
1708                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1709   "TARGET_32BIT"
1710   "#"
1711   [(set_attr "length" "8")]
1712 )
1713
1714 (define_expand "andsi3"
1715   [(set (match_operand:SI         0 "s_register_operand" "")
1716         (and:SI (match_operand:SI 1 "s_register_operand" "")
1717                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1718   "TARGET_EITHER"
1719   "
1720   if (TARGET_32BIT)
1721     {
1722       if (GET_CODE (operands[2]) == CONST_INT)
1723         {
1724           arm_split_constant (AND, SImode, NULL_RTX,
1725                               INTVAL (operands[2]), operands[0],
1726                               operands[1], optimize && !no_new_pseudos);
1727
1728           DONE;
1729         }
1730     }
1731   else /* TARGET_THUMB1 */
1732     {
1733       if (GET_CODE (operands[2]) != CONST_INT)
1734         operands[2] = force_reg (SImode, operands[2]);
1735       else
1736         {
1737           int i;
1738           
1739           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1740             {
1741               operands[2] = force_reg (SImode,
1742                                        GEN_INT (~INTVAL (operands[2])));
1743               
1744               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1745               
1746               DONE;
1747             }
1748
1749           for (i = 9; i <= 31; i++)
1750             {
1751               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1752                 {
1753                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1754                                         const0_rtx));
1755                   DONE;
1756                 }
1757               else if ((((HOST_WIDE_INT) 1) << i) - 1
1758                        == ~INTVAL (operands[2]))
1759                 {
1760                   rtx shift = GEN_INT (i);
1761                   rtx reg = gen_reg_rtx (SImode);
1762                 
1763                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1764                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1765                   
1766                   DONE;
1767                 }
1768             }
1769
1770           operands[2] = force_reg (SImode, operands[2]);
1771         }
1772     }
1773   "
1774 )
1775
1776 ; ??? Check split length for Thumb-2
1777 (define_insn_and_split "*arm_andsi3_insn"
1778   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1779         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1780                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1781   "TARGET_32BIT"
1782   "@
1783    and%?\\t%0, %1, %2
1784    bic%?\\t%0, %1, #%B2
1785    #"
1786   "TARGET_32BIT
1787    && GET_CODE (operands[2]) == CONST_INT
1788    && !(const_ok_for_arm (INTVAL (operands[2]))
1789         || const_ok_for_arm (~INTVAL (operands[2])))"
1790   [(clobber (const_int 0))]
1791   "
1792   arm_split_constant  (AND, SImode, curr_insn, 
1793                        INTVAL (operands[2]), operands[0], operands[1], 0);
1794   DONE;
1795   "
1796   [(set_attr "length" "4,4,16")
1797    (set_attr "predicable" "yes")]
1798 )
1799
1800 (define_insn "*thumb1_andsi3_insn"
1801   [(set (match_operand:SI         0 "register_operand" "=l")
1802         (and:SI (match_operand:SI 1 "register_operand" "%0")
1803                 (match_operand:SI 2 "register_operand" "l")))]
1804   "TARGET_THUMB1"
1805   "and\\t%0, %0, %2"
1806   [(set_attr "length" "2")]
1807 )
1808
1809 (define_insn "*andsi3_compare0"
1810   [(set (reg:CC_NOOV CC_REGNUM)
1811         (compare:CC_NOOV
1812          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1813                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1814          (const_int 0)))
1815    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1816         (and:SI (match_dup 1) (match_dup 2)))]
1817   "TARGET_32BIT"
1818   "@
1819    and%.\\t%0, %1, %2
1820    bic%.\\t%0, %1, #%B2"
1821   [(set_attr "conds" "set")]
1822 )
1823
1824 (define_insn "*andsi3_compare0_scratch"
1825   [(set (reg:CC_NOOV CC_REGNUM)
1826         (compare:CC_NOOV
1827          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1828                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1829          (const_int 0)))
1830    (clobber (match_scratch:SI 2 "=X,r"))]
1831   "TARGET_32BIT"
1832   "@
1833    tst%?\\t%0, %1
1834    bic%.\\t%2, %0, #%B1"
1835   [(set_attr "conds" "set")]
1836 )
1837
1838 (define_insn "*zeroextractsi_compare0_scratch"
1839   [(set (reg:CC_NOOV CC_REGNUM)
1840         (compare:CC_NOOV (zero_extract:SI
1841                           (match_operand:SI 0 "s_register_operand" "r")
1842                           (match_operand 1 "const_int_operand" "n")
1843                           (match_operand 2 "const_int_operand" "n"))
1844                          (const_int 0)))]
1845   "TARGET_32BIT
1846   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1847       && INTVAL (operands[1]) > 0 
1848       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1849       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1850   "*
1851   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1852                          << INTVAL (operands[2]));
1853   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1854   return \"\";
1855   "
1856   [(set_attr "conds" "set")]
1857 )
1858
1859 (define_insn_and_split "*ne_zeroextractsi"
1860   [(set (match_operand:SI 0 "s_register_operand" "=r")
1861         (ne:SI (zero_extract:SI
1862                 (match_operand:SI 1 "s_register_operand" "r")
1863                 (match_operand:SI 2 "const_int_operand" "n")
1864                 (match_operand:SI 3 "const_int_operand" "n"))
1865                (const_int 0)))
1866    (clobber (reg:CC CC_REGNUM))]
1867   "TARGET_32BIT
1868    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1869        && INTVAL (operands[2]) > 0 
1870        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1871        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1872   "#"
1873   "TARGET_32BIT
1874    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1875        && INTVAL (operands[2]) > 0 
1876        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1877        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1878   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1879                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1880                                     (const_int 0)))
1881               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1882    (set (match_dup 0)
1883         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1884                          (match_dup 0) (const_int 1)))]
1885   "
1886   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1887                          << INTVAL (operands[3])); 
1888   "
1889   [(set_attr "conds" "clob")
1890    (set (attr "length")
1891         (if_then_else (eq_attr "is_thumb" "yes")
1892                       (const_int 12)
1893                       (const_int 8)))]
1894 )
1895
1896 (define_insn_and_split "*ne_zeroextractsi_shifted"
1897   [(set (match_operand:SI 0 "s_register_operand" "=r")
1898         (ne:SI (zero_extract:SI
1899                 (match_operand:SI 1 "s_register_operand" "r")
1900                 (match_operand:SI 2 "const_int_operand" "n")
1901                 (const_int 0))
1902                (const_int 0)))
1903    (clobber (reg:CC CC_REGNUM))]
1904   "TARGET_ARM"
1905   "#"
1906   "TARGET_ARM"
1907   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1908                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1909                                     (const_int 0)))
1910               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1911    (set (match_dup 0)
1912         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1913                          (match_dup 0) (const_int 1)))]
1914   "
1915   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1916   "
1917   [(set_attr "conds" "clob")
1918    (set_attr "length" "8")]
1919 )
1920
1921 (define_insn_and_split "*ite_ne_zeroextractsi"
1922   [(set (match_operand:SI 0 "s_register_operand" "=r")
1923         (if_then_else:SI (ne (zero_extract:SI
1924                               (match_operand:SI 1 "s_register_operand" "r")
1925                               (match_operand:SI 2 "const_int_operand" "n")
1926                               (match_operand:SI 3 "const_int_operand" "n"))
1927                              (const_int 0))
1928                          (match_operand:SI 4 "arm_not_operand" "rIK")
1929                          (const_int 0)))
1930    (clobber (reg:CC CC_REGNUM))]
1931   "TARGET_ARM
1932    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1933        && INTVAL (operands[2]) > 0 
1934        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1935        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1936    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1937   "#"
1938   "TARGET_ARM
1939    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1940        && INTVAL (operands[2]) > 0 
1941        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1942        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1943    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1944   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1945                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1946                                     (const_int 0)))
1947               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1948    (set (match_dup 0)
1949         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1950                          (match_dup 0) (match_dup 4)))]
1951   "
1952   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1953                          << INTVAL (operands[3])); 
1954   "
1955   [(set_attr "conds" "clob")
1956    (set_attr "length" "8")]
1957 )
1958
1959 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1960   [(set (match_operand:SI 0 "s_register_operand" "=r")
1961         (if_then_else:SI (ne (zero_extract:SI
1962                               (match_operand:SI 1 "s_register_operand" "r")
1963                               (match_operand:SI 2 "const_int_operand" "n")
1964                               (const_int 0))
1965                              (const_int 0))
1966                          (match_operand:SI 3 "arm_not_operand" "rIK")
1967                          (const_int 0)))
1968    (clobber (reg:CC CC_REGNUM))]
1969   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1970   "#"
1971   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1972   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1973                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1974                                     (const_int 0)))
1975               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1976    (set (match_dup 0)
1977         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1978                          (match_dup 0) (match_dup 3)))]
1979   "
1980   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1981   "
1982   [(set_attr "conds" "clob")
1983    (set_attr "length" "8")]
1984 )
1985
1986 (define_split
1987   [(set (match_operand:SI 0 "s_register_operand" "")
1988         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1989                          (match_operand:SI 2 "const_int_operand" "")
1990                          (match_operand:SI 3 "const_int_operand" "")))
1991    (clobber (match_operand:SI 4 "s_register_operand" ""))]
1992   "TARGET_THUMB1"
1993   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1994    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1995   "{
1996      HOST_WIDE_INT temp = INTVAL (operands[2]);
1997
1998      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1999      operands[3] = GEN_INT (32 - temp);
2000    }"
2001 )
2002
2003 ;; ??? Use Thumb-2 has bitfield insert/extract instructions.
2004 (define_split
2005   [(set (match_operand:SI 0 "s_register_operand" "")
2006         (match_operator:SI 1 "shiftable_operator"
2007          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2008                            (match_operand:SI 3 "const_int_operand" "")
2009                            (match_operand:SI 4 "const_int_operand" ""))
2010           (match_operand:SI 5 "s_register_operand" "")]))
2011    (clobber (match_operand:SI 6 "s_register_operand" ""))]
2012   "TARGET_ARM"
2013   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2014    (set (match_dup 0)
2015         (match_op_dup 1
2016          [(lshiftrt:SI (match_dup 6) (match_dup 4))
2017           (match_dup 5)]))]
2018   "{
2019      HOST_WIDE_INT temp = INTVAL (operands[3]);
2020
2021      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2022      operands[4] = GEN_INT (32 - temp);
2023    }"
2024 )
2025   
2026 (define_split
2027   [(set (match_operand:SI 0 "s_register_operand" "")
2028         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2029                          (match_operand:SI 2 "const_int_operand" "")
2030                          (match_operand:SI 3 "const_int_operand" "")))]
2031   "TARGET_THUMB1"
2032   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2033    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2034   "{
2035      HOST_WIDE_INT temp = INTVAL (operands[2]);
2036
2037      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2038      operands[3] = GEN_INT (32 - temp);
2039    }"
2040 )
2041
2042 (define_split
2043   [(set (match_operand:SI 0 "s_register_operand" "")
2044         (match_operator:SI 1 "shiftable_operator"
2045          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2046                            (match_operand:SI 3 "const_int_operand" "")
2047                            (match_operand:SI 4 "const_int_operand" ""))
2048           (match_operand:SI 5 "s_register_operand" "")]))
2049    (clobber (match_operand:SI 6 "s_register_operand" ""))]
2050   "TARGET_ARM"
2051   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2052    (set (match_dup 0)
2053         (match_op_dup 1
2054          [(ashiftrt:SI (match_dup 6) (match_dup 4))
2055           (match_dup 5)]))]
2056   "{
2057      HOST_WIDE_INT temp = INTVAL (operands[3]);
2058
2059      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2060      operands[4] = GEN_INT (32 - temp);
2061    }"
2062 )
2063   
2064 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
2065 ;;; represented by the bitfield, then this will produce incorrect results.
2066 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
2067 ;;; which have a real bit-field insert instruction, the truncation happens
2068 ;;; in the bit-field insert instruction itself.  Since arm does not have a
2069 ;;; bit-field insert instruction, we would have to emit code here to truncate
2070 ;;; the value before we insert.  This loses some of the advantage of having
2071 ;;; this insv pattern, so this pattern needs to be reevalutated.
2072
2073 ; ??? Use Thumb-2 bitfield insert/extract instructions
2074 (define_expand "insv"
2075   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
2076                          (match_operand:SI 1 "general_operand" "")
2077                          (match_operand:SI 2 "general_operand" ""))
2078         (match_operand:SI 3 "reg_or_int_operand" ""))]
2079   "TARGET_ARM"
2080   "
2081   {
2082     int start_bit = INTVAL (operands[2]);
2083     int width = INTVAL (operands[1]);
2084     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2085     rtx target, subtarget;
2086
2087     target = operands[0];
2088     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
2089        subreg as the final target.  */
2090     if (GET_CODE (target) == SUBREG)
2091       {
2092         subtarget = gen_reg_rtx (SImode);
2093         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2094             < GET_MODE_SIZE (SImode))
2095           target = SUBREG_REG (target);
2096       }
2097     else
2098       subtarget = target;    
2099
2100     if (GET_CODE (operands[3]) == CONST_INT)
2101       {
2102         /* Since we are inserting a known constant, we may be able to
2103            reduce the number of bits that we have to clear so that
2104            the mask becomes simple.  */
2105         /* ??? This code does not check to see if the new mask is actually
2106            simpler.  It may not be.  */
2107         rtx op1 = gen_reg_rtx (SImode);
2108         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
2109            start of this pattern.  */
2110         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2111         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2112
2113         emit_insn (gen_andsi3 (op1, operands[0],
2114                                gen_int_mode (~mask2, SImode)));
2115         emit_insn (gen_iorsi3 (subtarget, op1,
2116                                gen_int_mode (op3_value << start_bit, SImode)));
2117       }
2118     else if (start_bit == 0
2119              && !(const_ok_for_arm (mask)
2120                   || const_ok_for_arm (~mask)))
2121       {
2122         /* A Trick, since we are setting the bottom bits in the word,
2123            we can shift operand[3] up, operand[0] down, OR them together
2124            and rotate the result back again.  This takes 3 insns, and
2125            the third might be mergeable into another op.  */
2126         /* The shift up copes with the possibility that operand[3] is
2127            wider than the bitfield.  */
2128         rtx op0 = gen_reg_rtx (SImode);
2129         rtx op1 = gen_reg_rtx (SImode);
2130
2131         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2132         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2133         emit_insn (gen_iorsi3  (op1, op1, op0));
2134         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2135       }
2136     else if ((width + start_bit == 32)
2137              && !(const_ok_for_arm (mask)
2138                   || const_ok_for_arm (~mask)))
2139       {
2140         /* Similar trick, but slightly less efficient.  */
2141
2142         rtx op0 = gen_reg_rtx (SImode);
2143         rtx op1 = gen_reg_rtx (SImode);
2144
2145         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2146         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2147         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2148         emit_insn (gen_iorsi3 (subtarget, op1, op0));
2149       }
2150     else
2151       {
2152         rtx op0 = gen_int_mode (mask, SImode);
2153         rtx op1 = gen_reg_rtx (SImode);
2154         rtx op2 = gen_reg_rtx (SImode);
2155
2156         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2157           {
2158             rtx tmp = gen_reg_rtx (SImode);
2159
2160             emit_insn (gen_movsi (tmp, op0));
2161             op0 = tmp;
2162           }
2163
2164         /* Mask out any bits in operand[3] that are not needed.  */
2165            emit_insn (gen_andsi3 (op1, operands[3], op0));
2166
2167         if (GET_CODE (op0) == CONST_INT
2168             && (const_ok_for_arm (mask << start_bit)
2169                 || const_ok_for_arm (~(mask << start_bit))))
2170           {
2171             op0 = gen_int_mode (~(mask << start_bit), SImode);
2172             emit_insn (gen_andsi3 (op2, operands[0], op0));
2173           }
2174         else
2175           {
2176             if (GET_CODE (op0) == CONST_INT)
2177               {
2178                 rtx tmp = gen_reg_rtx (SImode);
2179
2180                 emit_insn (gen_movsi (tmp, op0));
2181                 op0 = tmp;
2182               }
2183
2184             if (start_bit != 0)
2185               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
2186             
2187             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2188           }
2189
2190         if (start_bit != 0)
2191           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
2192
2193         emit_insn (gen_iorsi3 (subtarget, op1, op2));
2194       }
2195
2196     if (subtarget != target)
2197       {
2198         /* If TARGET is still a SUBREG, then it must be wider than a word,
2199            so we must be careful only to set the subword we were asked to.  */
2200         if (GET_CODE (target) == SUBREG)
2201           emit_move_insn (target, subtarget);
2202         else
2203           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2204       }
2205
2206     DONE;
2207   }"
2208 )
2209
2210 ; constants for op 2 will never be given to these patterns.
2211 (define_insn_and_split "*anddi_notdi_di"
2212   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2213         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2214                 (match_operand:DI 2 "s_register_operand" "0,r")))]
2215   "TARGET_32BIT"
2216   "#"
2217   "TARGET_32BIT && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2218   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2219    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2220   "
2221   {
2222     operands[3] = gen_highpart (SImode, operands[0]);
2223     operands[0] = gen_lowpart (SImode, operands[0]);
2224     operands[4] = gen_highpart (SImode, operands[1]);
2225     operands[1] = gen_lowpart (SImode, operands[1]);
2226     operands[5] = gen_highpart (SImode, operands[2]);
2227     operands[2] = gen_lowpart (SImode, operands[2]);
2228   }"
2229   [(set_attr "length" "8")
2230    (set_attr "predicable" "yes")]
2231 )
2232   
2233 (define_insn_and_split "*anddi_notzesidi_di"
2234   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2235         (and:DI (not:DI (zero_extend:DI
2236                          (match_operand:SI 2 "s_register_operand" "r,r")))
2237                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2238   "TARGET_32BIT"
2239   "@
2240    bic%?\\t%Q0, %Q1, %2
2241    #"
2242   ; (not (zero_extend ...)) allows us to just copy the high word from
2243   ; operand1 to operand0.
2244   "TARGET_32BIT
2245    && reload_completed
2246    && operands[0] != operands[1]"
2247   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2248    (set (match_dup 3) (match_dup 4))]
2249   "
2250   {
2251     operands[3] = gen_highpart (SImode, operands[0]);
2252     operands[0] = gen_lowpart (SImode, operands[0]);
2253     operands[4] = gen_highpart (SImode, operands[1]);
2254     operands[1] = gen_lowpart (SImode, operands[1]);
2255   }"
2256   [(set_attr "length" "4,8")
2257    (set_attr "predicable" "yes")]
2258 )
2259   
2260 (define_insn_and_split "*anddi_notsesidi_di"
2261   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2262         (and:DI (not:DI (sign_extend:DI
2263                          (match_operand:SI 2 "s_register_operand" "r,r")))
2264                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2265   "TARGET_32BIT"
2266   "#"
2267   "TARGET_32BIT && reload_completed"
2268   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2269    (set (match_dup 3) (and:SI (not:SI
2270                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2271                                (match_dup 4)))]
2272   "
2273   {
2274     operands[3] = gen_highpart (SImode, operands[0]);
2275     operands[0] = gen_lowpart (SImode, operands[0]);
2276     operands[4] = gen_highpart (SImode, operands[1]);
2277     operands[1] = gen_lowpart (SImode, operands[1]);
2278   }"
2279   [(set_attr "length" "8")
2280    (set_attr "predicable" "yes")]
2281 )
2282   
2283 (define_insn "andsi_notsi_si"
2284   [(set (match_operand:SI 0 "s_register_operand" "=r")
2285         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2286                 (match_operand:SI 1 "s_register_operand" "r")))]
2287   "TARGET_32BIT"
2288   "bic%?\\t%0, %1, %2"
2289   [(set_attr "predicable" "yes")]
2290 )
2291
2292 (define_insn "bicsi3"
2293   [(set (match_operand:SI                 0 "register_operand" "=l")
2294         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2295                 (match_operand:SI         2 "register_operand" "0")))]
2296   "TARGET_THUMB1"
2297   "bic\\t%0, %0, %1"
2298   [(set_attr "length" "2")]
2299 )
2300
2301 (define_insn "andsi_not_shiftsi_si"
2302   [(set (match_operand:SI 0 "s_register_operand" "=r")
2303         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2304                          [(match_operand:SI 2 "s_register_operand" "r")
2305                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2306                 (match_operand:SI 1 "s_register_operand" "r")))]
2307   "TARGET_ARM"
2308   "bic%?\\t%0, %1, %2%S4"
2309   [(set_attr "predicable" "yes")
2310    (set_attr "shift" "2")
2311    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2312                       (const_string "alu_shift")
2313                       (const_string "alu_shift_reg")))]
2314 )
2315
2316 (define_insn "*andsi_notsi_si_compare0"
2317   [(set (reg:CC_NOOV CC_REGNUM)
2318         (compare:CC_NOOV
2319          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2320                  (match_operand:SI 1 "s_register_operand" "r"))
2321          (const_int 0)))
2322    (set (match_operand:SI 0 "s_register_operand" "=r")
2323         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2324   "TARGET_32BIT"
2325   "bic%.\\t%0, %1, %2"
2326   [(set_attr "conds" "set")]
2327 )
2328
2329 (define_insn "*andsi_notsi_si_compare0_scratch"
2330   [(set (reg:CC_NOOV CC_REGNUM)
2331         (compare:CC_NOOV
2332          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2333                  (match_operand:SI 1 "s_register_operand" "r"))
2334          (const_int 0)))
2335    (clobber (match_scratch:SI 0 "=r"))]
2336   "TARGET_32BIT"
2337   "bic%.\\t%0, %1, %2"
2338   [(set_attr "conds" "set")]
2339 )
2340
2341 (define_insn "iordi3"
2342   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2343         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2344                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2345   "TARGET_32BIT && ! TARGET_IWMMXT"
2346   "#"
2347   [(set_attr "length" "8")
2348    (set_attr "predicable" "yes")]
2349 )
2350
2351 (define_insn "*iordi_zesidi_di"
2352   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2353         (ior:DI (zero_extend:DI
2354                  (match_operand:SI 2 "s_register_operand" "r,r"))
2355                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2356   "TARGET_32BIT"
2357   "@
2358    orr%?\\t%Q0, %Q1, %2
2359    #"
2360   [(set_attr "length" "4,8")
2361    (set_attr "predicable" "yes")]
2362 )
2363
2364 (define_insn "*iordi_sesidi_di"
2365   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2366         (ior:DI (sign_extend:DI
2367                  (match_operand:SI 2 "s_register_operand" "r,r"))
2368                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2369   "TARGET_32BIT"
2370   "#"
2371   [(set_attr "length" "8")
2372    (set_attr "predicable" "yes")]
2373 )
2374
2375 (define_expand "iorsi3"
2376   [(set (match_operand:SI         0 "s_register_operand" "")
2377         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2378                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2379   "TARGET_EITHER"
2380   "
2381   if (GET_CODE (operands[2]) == CONST_INT)
2382     {
2383       if (TARGET_32BIT)
2384         {
2385           arm_split_constant (IOR, SImode, NULL_RTX,
2386                               INTVAL (operands[2]), operands[0], operands[1],
2387                               optimize && !no_new_pseudos);
2388           DONE;
2389         }
2390       else /* TARGET_THUMB1 */
2391         operands [2] = force_reg (SImode, operands [2]);
2392     }
2393   "
2394 )
2395
2396 (define_insn_and_split "*arm_iorsi3"
2397   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2398         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2399                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2400   "TARGET_32BIT"
2401   "@
2402    orr%?\\t%0, %1, %2
2403    #"
2404   "TARGET_32BIT
2405    && GET_CODE (operands[2]) == CONST_INT
2406    && !const_ok_for_arm (INTVAL (operands[2]))"
2407   [(clobber (const_int 0))]
2408   "
2409   arm_split_constant (IOR, SImode, curr_insn, 
2410                       INTVAL (operands[2]), operands[0], operands[1], 0);
2411   DONE;
2412   "
2413   [(set_attr "length" "4,16")
2414    (set_attr "predicable" "yes")]
2415 )
2416
2417 (define_insn "*thumb1_iorsi3"
2418   [(set (match_operand:SI         0 "register_operand" "=l")
2419         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2420                 (match_operand:SI 2 "register_operand" "l")))]
2421   "TARGET_THUMB1"
2422   "orr\\t%0, %0, %2"
2423   [(set_attr "length" "2")]
2424 )
2425
2426 (define_peephole2
2427   [(match_scratch:SI 3 "r")
2428    (set (match_operand:SI 0 "arm_general_register_operand" "")
2429         (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2430                 (match_operand:SI 2 "const_int_operand" "")))]
2431   "TARGET_32BIT
2432    && !const_ok_for_arm (INTVAL (operands[2]))
2433    && const_ok_for_arm (~INTVAL (operands[2]))"
2434   [(set (match_dup 3) (match_dup 2))
2435    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2436   ""
2437 )
2438
2439 (define_insn "*iorsi3_compare0"
2440   [(set (reg:CC_NOOV CC_REGNUM)
2441         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2442                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2443                          (const_int 0)))
2444    (set (match_operand:SI 0 "s_register_operand" "=r")
2445         (ior:SI (match_dup 1) (match_dup 2)))]
2446   "TARGET_32BIT"
2447   "orr%.\\t%0, %1, %2"
2448   [(set_attr "conds" "set")]
2449 )
2450
2451 (define_insn "*iorsi3_compare0_scratch"
2452   [(set (reg:CC_NOOV CC_REGNUM)
2453         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2454                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2455                          (const_int 0)))
2456    (clobber (match_scratch:SI 0 "=r"))]
2457   "TARGET_32BIT"
2458   "orr%.\\t%0, %1, %2"
2459   [(set_attr "conds" "set")]
2460 )
2461
2462 (define_insn "xordi3"
2463   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2464         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2465                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2466   "TARGET_32BIT && !TARGET_IWMMXT"
2467   "#"
2468   [(set_attr "length" "8")
2469    (set_attr "predicable" "yes")]
2470 )
2471
2472 (define_insn "*xordi_zesidi_di"
2473   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2474         (xor:DI (zero_extend:DI
2475                  (match_operand:SI 2 "s_register_operand" "r,r"))
2476                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2477   "TARGET_32BIT"
2478   "@
2479    eor%?\\t%Q0, %Q1, %2
2480    #"
2481   [(set_attr "length" "4,8")
2482    (set_attr "predicable" "yes")]
2483 )
2484
2485 (define_insn "*xordi_sesidi_di"
2486   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2487         (xor:DI (sign_extend:DI
2488                  (match_operand:SI 2 "s_register_operand" "r,r"))
2489                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2490   "TARGET_32BIT"
2491   "#"
2492   [(set_attr "length" "8")
2493    (set_attr "predicable" "yes")]
2494 )
2495
2496 (define_expand "xorsi3"
2497   [(set (match_operand:SI         0 "s_register_operand" "")
2498         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2499                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2500   "TARGET_EITHER"
2501   "if (TARGET_THUMB1)
2502      if (GET_CODE (operands[2]) == CONST_INT)
2503        operands[2] = force_reg (SImode, operands[2]);
2504   "
2505 )
2506
2507 (define_insn "*arm_xorsi3"
2508   [(set (match_operand:SI         0 "s_register_operand" "=r")
2509         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2510                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2511   "TARGET_32BIT"
2512   "eor%?\\t%0, %1, %2"
2513   [(set_attr "predicable" "yes")]
2514 )
2515
2516 (define_insn "*thumb1_xorsi3"
2517   [(set (match_operand:SI         0 "register_operand" "=l")
2518         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2519                 (match_operand:SI 2 "register_operand" "l")))]
2520   "TARGET_THUMB1"
2521   "eor\\t%0, %0, %2"
2522   [(set_attr "length" "2")]
2523 )
2524
2525 (define_insn "*xorsi3_compare0"
2526   [(set (reg:CC_NOOV CC_REGNUM)
2527         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2528                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2529                          (const_int 0)))
2530    (set (match_operand:SI 0 "s_register_operand" "=r")
2531         (xor:SI (match_dup 1) (match_dup 2)))]
2532   "TARGET_32BIT"
2533   "eor%.\\t%0, %1, %2"
2534   [(set_attr "conds" "set")]
2535 )
2536
2537 (define_insn "*xorsi3_compare0_scratch"
2538   [(set (reg:CC_NOOV CC_REGNUM)
2539         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2540                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2541                          (const_int 0)))]
2542   "TARGET_32BIT"
2543   "teq%?\\t%0, %1"
2544   [(set_attr "conds" "set")]
2545 )
2546
2547 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2548 ; (NOT D) we can sometimes merge the final NOT into one of the following
2549 ; insns.
2550
2551 (define_split
2552   [(set (match_operand:SI 0 "s_register_operand" "")
2553         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2554                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2555                 (match_operand:SI 3 "arm_rhs_operand" "")))
2556    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2557   "TARGET_32BIT"
2558   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2559                               (not:SI (match_dup 3))))
2560    (set (match_dup 0) (not:SI (match_dup 4)))]
2561   ""
2562 )
2563
2564 (define_insn "*andsi_iorsi3_notsi"
2565   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2566         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2567                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2568                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2569   "TARGET_32BIT"
2570   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2571   [(set_attr "length" "8")
2572    (set_attr "ce_count" "2")
2573    (set_attr "predicable" "yes")]
2574 )
2575
2576 ; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
2577 ; insns are available?
2578 (define_split
2579   [(set (match_operand:SI 0 "s_register_operand" "")
2580         (match_operator:SI 1 "logical_binary_operator"
2581          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2582                            (match_operand:SI 3 "const_int_operand" "")
2583                            (match_operand:SI 4 "const_int_operand" ""))
2584           (match_operator:SI 9 "logical_binary_operator"
2585            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2586                          (match_operand:SI 6 "const_int_operand" ""))
2587             (match_operand:SI 7 "s_register_operand" "")])]))
2588    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2589   "TARGET_32BIT
2590    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2591    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2592   [(set (match_dup 8)
2593         (match_op_dup 1
2594          [(ashift:SI (match_dup 2) (match_dup 4))
2595           (match_dup 5)]))
2596    (set (match_dup 0)
2597         (match_op_dup 1
2598          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2599           (match_dup 7)]))]
2600   "
2601   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2602 ")
2603
2604 (define_split
2605   [(set (match_operand:SI 0 "s_register_operand" "")
2606         (match_operator:SI 1 "logical_binary_operator"
2607          [(match_operator:SI 9 "logical_binary_operator"
2608            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2609                          (match_operand:SI 6 "const_int_operand" ""))
2610             (match_operand:SI 7 "s_register_operand" "")])
2611           (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2612                            (match_operand:SI 3 "const_int_operand" "")
2613                            (match_operand:SI 4 "const_int_operand" ""))]))
2614    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2615   "TARGET_32BIT
2616    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2617    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2618   [(set (match_dup 8)
2619         (match_op_dup 1
2620          [(ashift:SI (match_dup 2) (match_dup 4))
2621           (match_dup 5)]))
2622    (set (match_dup 0)
2623         (match_op_dup 1
2624          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2625           (match_dup 7)]))]
2626   "
2627   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2628 ")
2629
2630 (define_split
2631   [(set (match_operand:SI 0 "s_register_operand" "")
2632         (match_operator:SI 1 "logical_binary_operator"
2633          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2634                            (match_operand:SI 3 "const_int_operand" "")
2635                            (match_operand:SI 4 "const_int_operand" ""))
2636           (match_operator:SI 9 "logical_binary_operator"
2637            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2638                          (match_operand:SI 6 "const_int_operand" ""))
2639             (match_operand:SI 7 "s_register_operand" "")])]))
2640    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2641   "TARGET_32BIT
2642    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2643    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2644   [(set (match_dup 8)
2645         (match_op_dup 1
2646          [(ashift:SI (match_dup 2) (match_dup 4))
2647           (match_dup 5)]))
2648    (set (match_dup 0)
2649         (match_op_dup 1
2650          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2651           (match_dup 7)]))]
2652   "
2653   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2654 ")
2655
2656 (define_split
2657   [(set (match_operand:SI 0 "s_register_operand" "")
2658         (match_operator:SI 1 "logical_binary_operator"
2659          [(match_operator:SI 9 "logical_binary_operator"
2660            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2661                          (match_operand:SI 6 "const_int_operand" ""))
2662             (match_operand:SI 7 "s_register_operand" "")])
2663           (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2664                            (match_operand:SI 3 "const_int_operand" "")
2665                            (match_operand:SI 4 "const_int_operand" ""))]))
2666    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2667   "TARGET_32BIT
2668    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2669    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2670   [(set (match_dup 8)
2671         (match_op_dup 1
2672          [(ashift:SI (match_dup 2) (match_dup 4))
2673           (match_dup 5)]))
2674    (set (match_dup 0)
2675         (match_op_dup 1
2676          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2677           (match_dup 7)]))]
2678   "
2679   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2680 ")
2681 \f
2682
2683 ;; Minimum and maximum insns
2684
2685 (define_expand "smaxsi3"
2686   [(parallel [
2687     (set (match_operand:SI 0 "s_register_operand" "")
2688          (smax:SI (match_operand:SI 1 "s_register_operand" "")
2689                   (match_operand:SI 2 "arm_rhs_operand" "")))
2690     (clobber (reg:CC CC_REGNUM))])]
2691   "TARGET_32BIT"
2692   "
2693   if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
2694     {
2695       /* No need for a clobber of the condition code register here.  */
2696       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2697                               gen_rtx_SMAX (SImode, operands[1],
2698                                             operands[2])));
2699       DONE;
2700     }
2701 ")
2702
2703 (define_insn "*smax_0"
2704   [(set (match_operand:SI 0 "s_register_operand" "=r")
2705         (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2706                  (const_int 0)))]
2707   "TARGET_32BIT"
2708   "bic%?\\t%0, %1, %1, asr #31"
2709   [(set_attr "predicable" "yes")]
2710 )
2711
2712 (define_insn "*smax_m1"
2713   [(set (match_operand:SI 0 "s_register_operand" "=r")
2714         (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2715                  (const_int -1)))]
2716   "TARGET_32BIT"
2717   "orr%?\\t%0, %1, %1, asr #31"
2718   [(set_attr "predicable" "yes")]
2719 )
2720
2721 (define_insn "*arm_smax_insn"
2722   [(set (match_operand:SI          0 "s_register_operand" "=r,r")
2723         (smax:SI (match_operand:SI 1 "s_register_operand"  "%0,?r")
2724                  (match_operand:SI 2 "arm_rhs_operand"    "rI,rI")))
2725    (clobber (reg:CC CC_REGNUM))]
2726   "TARGET_ARM"
2727   "@
2728    cmp\\t%1, %2\;movlt\\t%0, %2
2729    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2730   [(set_attr "conds" "clob")
2731    (set_attr "length" "8,12")]
2732 )
2733
2734 (define_expand "sminsi3"
2735   [(parallel [
2736     (set (match_operand:SI 0 "s_register_operand" "")
2737          (smin:SI (match_operand:SI 1 "s_register_operand" "")
2738                   (match_operand:SI 2 "arm_rhs_operand" "")))
2739     (clobber (reg:CC CC_REGNUM))])]
2740   "TARGET_32BIT"
2741   "
2742   if (operands[2] == const0_rtx)
2743     {
2744       /* No need for a clobber of the condition code register here.  */
2745       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2746                               gen_rtx_SMIN (SImode, operands[1],
2747                                             operands[2])));
2748       DONE;
2749     }
2750 ")
2751
2752 (define_insn "*smin_0"
2753   [(set (match_operand:SI 0 "s_register_operand" "=r")
2754         (smin:SI (match_operand:SI 1 "s_register_operand" "r")
2755                  (const_int 0)))]
2756   "TARGET_32BIT"
2757   "and%?\\t%0, %1, %1, asr #31"
2758   [(set_attr "predicable" "yes")]
2759 )
2760
2761 (define_insn "*arm_smin_insn"
2762   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2763         (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
2764                  (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
2765    (clobber (reg:CC CC_REGNUM))]
2766   "TARGET_ARM"
2767   "@
2768    cmp\\t%1, %2\;movge\\t%0, %2
2769    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2770   [(set_attr "conds" "clob")
2771    (set_attr "length" "8,12")]
2772 )
2773
2774 (define_expand "umaxsi3"
2775   [(parallel [
2776     (set (match_operand:SI 0 "s_register_operand" "")
2777          (umax:SI (match_operand:SI 1 "s_register_operand" "")
2778                   (match_operand:SI 2 "arm_rhs_operand" "")))
2779     (clobber (reg:CC CC_REGNUM))])]
2780   "TARGET_32BIT"
2781   ""
2782 )
2783
2784 (define_insn "*arm_umaxsi3"
2785   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2786         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2787                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2788    (clobber (reg:CC CC_REGNUM))]
2789   "TARGET_ARM"
2790   "@
2791    cmp\\t%1, %2\;movcc\\t%0, %2
2792    cmp\\t%1, %2\;movcs\\t%0, %1
2793    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2794   [(set_attr "conds" "clob")
2795    (set_attr "length" "8,8,12")]
2796 )
2797
2798 (define_expand "uminsi3"
2799   [(parallel [
2800     (set (match_operand:SI 0 "s_register_operand" "")
2801          (umin:SI (match_operand:SI 1 "s_register_operand" "")
2802                   (match_operand:SI 2 "arm_rhs_operand" "")))
2803     (clobber (reg:CC CC_REGNUM))])]
2804   "TARGET_32BIT"
2805   ""
2806 )
2807
2808 (define_insn "*arm_uminsi3"
2809   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2810         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2811                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2812    (clobber (reg:CC CC_REGNUM))]
2813   "TARGET_ARM"
2814   "@
2815    cmp\\t%1, %2\;movcs\\t%0, %2
2816    cmp\\t%1, %2\;movcc\\t%0, %1
2817    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2818   [(set_attr "conds" "clob")
2819    (set_attr "length" "8,8,12")]
2820 )
2821
2822 (define_insn "*store_minmaxsi"
2823   [(set (match_operand:SI 0 "memory_operand" "=m")
2824         (match_operator:SI 3 "minmax_operator"
2825          [(match_operand:SI 1 "s_register_operand" "r")
2826           (match_operand:SI 2 "s_register_operand" "r")]))
2827    (clobber (reg:CC CC_REGNUM))]
2828   "TARGET_32BIT"
2829   "*
2830   operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2831                                 operands[1], operands[2]);
2832   output_asm_insn (\"cmp\\t%1, %2\", operands);
2833   if (TARGET_THUMB2)
2834     output_asm_insn (\"ite\t%d3\", operands);
2835   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2836   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2837   return \"\";
2838   "
2839   [(set_attr "conds" "clob")
2840    (set (attr "length")
2841         (if_then_else (eq_attr "is_thumb" "yes")
2842                       (const_int 14)
2843                       (const_int 12)))
2844    (set_attr "type" "store1")]
2845 )
2846
2847 ; Reject the frame pointer in operand[1], since reloading this after
2848 ; it has been eliminated can cause carnage.
2849 (define_insn "*minmax_arithsi"
2850   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2851         (match_operator:SI 4 "shiftable_operator"
2852          [(match_operator:SI 5 "minmax_operator"
2853            [(match_operand:SI 2 "s_register_operand" "r,r")
2854             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2855           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2856    (clobber (reg:CC CC_REGNUM))]
2857   "TARGET_32BIT && !arm_eliminable_register (operands[1])"
2858   "*
2859   {
2860     enum rtx_code code = GET_CODE (operands[4]);
2861     bool need_else;
2862
2863     if (which_alternative != 0 || operands[3] != const0_rtx
2864         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2865       need_else = true;
2866     else
2867       need_else = false;
2868
2869     operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2870                                   operands[2], operands[3]);
2871     output_asm_insn (\"cmp\\t%2, %3\", operands);
2872     if (TARGET_THUMB2)
2873       {
2874         if (need_else)
2875           output_asm_insn (\"ite\\t%d5\", operands);
2876         else
2877           output_asm_insn (\"it\\t%d5\", operands);
2878       }
2879     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2880     if (need_else)
2881       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2882     return \"\";
2883   }"
2884   [(set_attr "conds" "clob")
2885    (set (attr "length")
2886         (if_then_else (eq_attr "is_thumb" "yes")
2887                       (const_int 14)
2888                       (const_int 12)))]
2889 )
2890
2891 \f
2892 ;; Shift and rotation insns
2893
2894 (define_expand "ashldi3"
2895   [(set (match_operand:DI            0 "s_register_operand" "")
2896         (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2897                    (match_operand:SI 2 "reg_or_int_operand" "")))]
2898   "TARGET_32BIT"
2899   "
2900   if (GET_CODE (operands[2]) == CONST_INT)
2901     {
2902       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2903         {
2904           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2905           DONE;
2906         }
2907         /* Ideally we shouldn't fail here if we could know that operands[1] 
2908            ends up already living in an iwmmxt register. Otherwise it's
2909            cheaper to have the alternate code being generated than moving
2910            values to iwmmxt regs and back.  */
2911         FAIL;
2912     }
2913   else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2914     FAIL;
2915   "
2916 )
2917
2918 (define_insn "arm_ashldi3_1bit"
2919   [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
2920         (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2921                    (const_int 1)))
2922    (clobber (reg:CC CC_REGNUM))]
2923   "TARGET_32BIT"
2924   "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2925   [(set_attr "conds" "clob")
2926    (set_attr "length" "8")]
2927 )
2928
2929 (define_expand "ashlsi3"
2930   [(set (match_operand:SI            0 "s_register_operand" "")
2931         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2932                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2933   "TARGET_EITHER"
2934   "
2935   if (GET_CODE (operands[2]) == CONST_INT
2936       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2937     {
2938       emit_insn (gen_movsi (operands[0], const0_rtx));
2939       DONE;
2940     }
2941   "
2942 )
2943
2944 (define_insn "*thumb1_ashlsi3"
2945   [(set (match_operand:SI            0 "register_operand" "=l,l")
2946         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2947                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2948   "TARGET_THUMB1"
2949   "lsl\\t%0, %1, %2"
2950   [(set_attr "length" "2")]
2951 )
2952
2953 (define_expand "ashrdi3"
2954   [(set (match_operand:DI              0 "s_register_operand" "")
2955         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2956                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2957   "TARGET_32BIT"
2958   "
2959   if (GET_CODE (operands[2]) == CONST_INT)
2960     {
2961       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2962         {
2963           emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2964           DONE;
2965         }
2966         /* Ideally we shouldn't fail here if we could know that operands[1] 
2967            ends up already living in an iwmmxt register. Otherwise it's
2968            cheaper to have the alternate code being generated than moving
2969            values to iwmmxt regs and back.  */
2970         FAIL;
2971     }
2972   else if (!TARGET_REALLY_IWMMXT)
2973     FAIL;
2974   "
2975 )
2976
2977 (define_insn "arm_ashrdi3_1bit"
2978   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2979         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2980                      (const_int 1)))
2981    (clobber (reg:CC CC_REGNUM))]
2982   "TARGET_32BIT"
2983   "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2984   [(set_attr "conds" "clob")
2985    (set_attr "length" "8")]
2986 )
2987
2988 (define_expand "ashrsi3"
2989   [(set (match_operand:SI              0 "s_register_operand" "")
2990         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2991                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2992   "TARGET_EITHER"
2993   "
2994   if (GET_CODE (operands[2]) == CONST_INT
2995       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2996     operands[2] = GEN_INT (31);
2997   "
2998 )
2999
3000 (define_insn "*thumb1_ashrsi3"
3001   [(set (match_operand:SI              0 "register_operand" "=l,l")
3002         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3003                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
3004   "TARGET_THUMB1"
3005   "asr\\t%0, %1, %2"
3006   [(set_attr "length" "2")]
3007 )
3008
3009 (define_expand "lshrdi3"
3010   [(set (match_operand:DI              0 "s_register_operand" "")
3011         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3012                      (match_operand:SI 2 "reg_or_int_operand" "")))]
3013   "TARGET_32BIT"
3014   "
3015   if (GET_CODE (operands[2]) == CONST_INT)
3016     {
3017       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3018         {
3019           emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3020           DONE;
3021         }
3022         /* Ideally we shouldn't fail here if we could know that operands[1] 
3023            ends up already living in an iwmmxt register. Otherwise it's
3024            cheaper to have the alternate code being generated than moving
3025            values to iwmmxt regs and back.  */
3026         FAIL;
3027     }
3028   else if (!TARGET_REALLY_IWMMXT)
3029     FAIL;
3030   "
3031 )
3032
3033 (define_insn "arm_lshrdi3_1bit"
3034   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
3035         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
3036                      (const_int 1)))
3037    (clobber (reg:CC CC_REGNUM))]
3038   "TARGET_32BIT"
3039   "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
3040   [(set_attr "conds" "clob")
3041    (set_attr "length" "8")]
3042 )
3043
3044 (define_expand "lshrsi3"
3045   [(set (match_operand:SI              0 "s_register_operand" "")
3046         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3047                      (match_operand:SI 2 "arm_rhs_operand" "")))]
3048   "TARGET_EITHER"
3049   "
3050   if (GET_CODE (operands[2]) == CONST_INT
3051       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3052     {
3053       emit_insn (gen_movsi (operands[0], const0_rtx));
3054       DONE;
3055     }
3056   "
3057 )
3058
3059 (define_insn "*thumb1_lshrsi3"
3060   [(set (match_operand:SI              0 "register_operand" "=l,l")
3061         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3062                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
3063   "TARGET_THUMB1"
3064   "lsr\\t%0, %1, %2"
3065   [(set_attr "length" "2")]
3066 )
3067
3068 (define_expand "rotlsi3"
3069   [(set (match_operand:SI              0 "s_register_operand" "")
3070         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3071                      (match_operand:SI 2 "reg_or_int_operand" "")))]
3072   "TARGET_32BIT"
3073   "
3074   if (GET_CODE (operands[2]) == CONST_INT)
3075     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3076   else
3077     {
3078       rtx reg = gen_reg_rtx (SImode);
3079       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3080       operands[2] = reg;
3081     }
3082   "
3083 )
3084
3085 (define_expand "rotrsi3"
3086   [(set (match_operand:SI              0 "s_register_operand" "")
3087         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3088                      (match_operand:SI 2 "arm_rhs_operand" "")))]
3089   "TARGET_EITHER"
3090   "
3091   if (TARGET_32BIT)
3092     {
3093       if (GET_CODE (operands[2]) == CONST_INT
3094           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3095         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3096     }
3097   else /* TARGET_THUMB1 */
3098     {
3099       if (GET_CODE (operands [2]) == CONST_INT)
3100         operands [2] = force_reg (SImode, operands[2]);
3101     }
3102   "
3103 )
3104
3105 (define_insn "*thumb1_rotrsi3"
3106   [(set (match_operand:SI              0 "register_operand" "=l")
3107         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
3108                      (match_operand:SI 2 "register_operand" "l")))]
3109   "TARGET_THUMB1"
3110   "ror\\t%0, %0, %2"
3111   [(set_attr "length" "2")]
3112 )
3113
3114 (define_insn "*arm_shiftsi3"
3115   [(set (match_operand:SI   0 "s_register_operand" "=r")
3116         (match_operator:SI  3 "shift_operator"
3117          [(match_operand:SI 1 "s_register_operand"  "r")
3118           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
3119   "TARGET_32BIT"
3120   "* return arm_output_shift(operands, 0);"
3121   [(set_attr "predicable" "yes")
3122    (set_attr "shift" "1")
3123    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3124                       (const_string "alu_shift")
3125                       (const_string "alu_shift_reg")))]
3126 )
3127
3128 (define_insn "*shiftsi3_compare0"
3129   [(set (reg:CC_NOOV CC_REGNUM)
3130         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3131                           [(match_operand:SI 1 "s_register_operand" "r")
3132                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
3133                          (const_int 0)))
3134    (set (match_operand:SI 0 "s_register_operand" "=r")
3135         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
3136   "TARGET_32BIT"
3137   "* return arm_output_shift(operands, 1);"
3138   [(set_attr "conds" "set")
3139    (set_attr "shift" "1")
3140    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3141                       (const_string "alu_shift")
3142                       (const_string "alu_shift_reg")))]
3143 )
3144
3145 (define_insn "*shiftsi3_compare0_scratch"
3146   [(set (reg:CC_NOOV CC_REGNUM)
3147         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3148                           [(match_operand:SI 1 "s_register_operand" "r")
3149                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
3150                          (const_int 0)))
3151    (clobber (match_scratch:SI 0 "=r"))]
3152   "TARGET_32BIT"
3153   "* return arm_output_shift(operands, 1);"
3154   [(set_attr "conds" "set")
3155    (set_attr "shift" "1")]
3156 )
3157
3158 (define_insn "*arm_notsi_shiftsi"
3159   [(set (match_operand:SI 0 "s_register_operand" "=r")
3160         (not:SI (match_operator:SI 3 "shift_operator"
3161                  [(match_operand:SI 1 "s_register_operand" "r")
3162                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
3163   "TARGET_ARM"
3164   "mvn%?\\t%0, %1%S3"
3165   [(set_attr "predicable" "yes")
3166    (set_attr "shift" "1")
3167    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3168                       (const_string "alu_shift")
3169                       (const_string "alu_shift_reg")))]
3170 )
3171
3172 (define_insn "*arm_notsi_shiftsi_compare0"
3173   [(set (reg:CC_NOOV CC_REGNUM)
3174         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
3175                           [(match_operand:SI 1 "s_register_operand" "r")
3176                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
3177                          (const_int 0)))
3178    (set (match_operand:SI 0 "s_register_operand" "=r")
3179         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
3180   "TARGET_ARM"
3181   "mvn%.\\t%0, %1%S3"
3182   [(set_attr "conds" "set")
3183    (set_attr "shift" "1")
3184    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3185                       (const_string "alu_shift")
3186                       (const_string "alu_shift_reg")))]
3187 )
3188
3189 (define_insn "*arm_not_shiftsi_compare0_scratch"
3190   [(set (reg:CC_NOOV CC_REGNUM)
3191         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
3192                           [(match_operand:SI 1 "s_register_operand" "r")
3193                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
3194                          (const_int 0)))
3195    (clobber (match_scratch:SI 0 "=r"))]
3196   "TARGET_ARM"
3197   "mvn%.\\t%0, %1%S3"
3198   [(set_attr "conds" "set")
3199    (set_attr "shift" "1")
3200    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3201                       (const_string "alu_shift")
3202                       (const_string "alu_shift_reg")))]
3203 )
3204
3205 ;; We don't really have extzv, but defining this using shifts helps
3206 ;; to reduce register pressure later on.
3207
3208 (define_expand "extzv"
3209   [(set (match_dup 4)
3210         (ashift:SI (match_operand:SI   1 "register_operand" "")
3211                    (match_operand:SI   2 "const_int_operand" "")))
3212    (set (match_operand:SI              0 "register_operand" "")
3213         (lshiftrt:SI (match_dup 4)
3214                      (match_operand:SI 3 "const_int_operand" "")))]
3215   "TARGET_THUMB1"
3216   "
3217   {
3218     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3219     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3220     
3221     operands[3] = GEN_INT (rshift);
3222     
3223     if (lshift == 0)
3224       {
3225         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3226         DONE;
3227       }
3228       
3229     operands[2] = GEN_INT (lshift);
3230     operands[4] = gen_reg_rtx (SImode);
3231   }"
3232 )
3233
3234 \f
3235 ;; Unary arithmetic insns
3236
3237 (define_expand "negdi2"
3238  [(parallel
3239    [(set (match_operand:DI          0 "s_register_operand" "")
3240           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
3241     (clobber (reg:CC CC_REGNUM))])]
3242   "TARGET_EITHER"
3243   "
3244   if (TARGET_THUMB1)
3245     {
3246       if (GET_CODE (operands[1]) != REG)
3247         operands[1] = force_reg (SImode, operands[1]);
3248      }
3249   "
3250 )
3251
3252 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
3253 ;; The second alternative is to allow the common case of a *full* overlap.
3254 (define_insn "*arm_negdi2"
3255   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
3256         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
3257    (clobber (reg:CC CC_REGNUM))]
3258   "TARGET_ARM"
3259   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
3260   [(set_attr "conds" "clob")
3261    (set_attr "length" "8")]
3262 )
3263
3264 (define_insn "*thumb1_negdi2"
3265   [(set (match_operand:DI         0 "register_operand" "=&l")
3266         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
3267    (clobber (reg:CC CC_REGNUM))]
3268   "TARGET_THUMB1"
3269   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
3270   [(set_attr "length" "6")]
3271 )
3272
3273 (define_expand "negsi2"
3274   [(set (match_operand:SI         0 "s_register_operand" "")
3275         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
3276   "TARGET_EITHER"
3277   ""
3278 )
3279
3280 (define_insn "*arm_negsi2"
3281   [(set (match_operand:SI         0 "s_register_operand" "=r")
3282         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
3283   "TARGET_32BIT"
3284   "rsb%?\\t%0, %1, #0"
3285   [(set_attr "predicable" "yes")]
3286 )
3287
3288 (define_insn "*thumb1_negsi2"
3289   [(set (match_operand:SI         0 "register_operand" "=l")
3290         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
3291   "TARGET_THUMB1"
3292   "neg\\t%0, %1"
3293   [(set_attr "length" "2")]
3294 )
3295
3296 (define_expand "negsf2"
3297   [(set (match_operand:SF         0 "s_register_operand" "")
3298         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
3299   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3300   ""
3301 )
3302
3303 (define_expand "negdf2"
3304   [(set (match_operand:DF         0 "s_register_operand" "")
3305         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
3306   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3307   "")
3308
3309 ;; abssi2 doesn't really clobber the condition codes if a different register
3310 ;; is being set.  To keep things simple, assume during rtl manipulations that
3311 ;; it does, but tell the final scan operator the truth.  Similarly for
3312 ;; (neg (abs...))
3313
3314 (define_expand "abssi2"
3315   [(parallel
3316     [(set (match_operand:SI         0 "s_register_operand" "")
3317           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3318      (clobber (match_dup 2))])]
3319   "TARGET_EITHER"
3320   "
3321   if (TARGET_THUMB1)
3322     operands[2] = gen_rtx_SCRATCH (SImode);
3323   else
3324     operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
3325 ")
3326
3327 (define_insn "*arm_abssi2"
3328   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3329         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3330    (clobber (reg:CC CC_REGNUM))]
3331   "TARGET_ARM"
3332   "@
3333    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3334    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3335   [(set_attr "conds" "clob,*")
3336    (set_attr "shift" "1")
3337    ;; predicable can't be set based on the variant, so left as no
3338    (set_attr "length" "8")]
3339 )
3340
3341 (define_insn_and_split "*thumb1_abssi2"
3342   [(set (match_operand:SI 0 "s_register_operand" "=l")
3343         (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
3344    (clobber (match_scratch:SI 2 "=&l"))]
3345   "TARGET_THUMB1"
3346   "#"
3347   "TARGET_THUMB1 && reload_completed"
3348   [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3349    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
3350    (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3351   ""
3352   [(set_attr "length" "6")]
3353 )
3354
3355 (define_insn "*arm_neg_abssi2"
3356   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3357         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3358    (clobber (reg:CC CC_REGNUM))]
3359   "TARGET_ARM"
3360   "@
3361    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3362    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3363   [(set_attr "conds" "clob,*")
3364    (set_attr "shift" "1")
3365    ;; predicable can't be set based on the variant, so left as no
3366    (set_attr "length" "8")]
3367 )
3368
3369 (define_insn_and_split "*thumb1_neg_abssi2"
3370   [(set (match_operand:SI 0 "s_register_operand" "=l")
3371         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
3372    (clobber (match_scratch:SI 2 "=&l"))]
3373   "TARGET_THUMB1"
3374   "#"
3375   "TARGET_THUMB1 && reload_completed"
3376   [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3377    (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
3378    (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3379   ""
3380   [(set_attr "length" "6")]
3381 )
3382
3383 (define_expand "abssf2"
3384   [(set (match_operand:SF         0 "s_register_operand" "")
3385         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3386   "TARGET_32BIT && TARGET_HARD_FLOAT"
3387   "")
3388
3389 (define_expand "absdf2"
3390   [(set (match_operand:DF         0 "s_register_operand" "")
3391         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3392   "TARGET_32BIT && TARGET_HARD_FLOAT"
3393   "")
3394
3395 (define_expand "sqrtsf2"
3396   [(set (match_operand:SF 0 "s_register_operand" "")
3397         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3398   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3399   "")
3400
3401 (define_expand "sqrtdf2"
3402   [(set (match_operand:DF 0 "s_register_operand" "")
3403         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3404   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3405   "")
3406
3407 (define_insn_and_split "one_cmpldi2"
3408   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3409         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3410   "TARGET_32BIT"
3411   "#"
3412   "TARGET_32BIT && reload_completed"
3413   [(set (match_dup 0) (not:SI (match_dup 1)))
3414    (set (match_dup 2) (not:SI (match_dup 3)))]
3415   "
3416   {
3417     operands[2] = gen_highpart (SImode, operands[0]);
3418     operands[0] = gen_lowpart (SImode, operands[0]);
3419     operands[3] = gen_highpart (SImode, operands[1]);
3420     operands[1] = gen_lowpart (SImode, operands[1]);
3421   }"
3422   [(set_attr "length" "8")
3423    (set_attr "predicable" "yes")]
3424 )
3425
3426 (define_expand "one_cmplsi2"
3427   [(set (match_operand:SI         0 "s_register_operand" "")
3428         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3429   "TARGET_EITHER"
3430   ""
3431 )
3432
3433 (define_insn "*arm_one_cmplsi2"
3434   [(set (match_operand:SI         0 "s_register_operand" "=r")
3435         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3436   "TARGET_32BIT"
3437   "mvn%?\\t%0, %1"
3438   [(set_attr "predicable" "yes")]
3439 )
3440
3441 (define_insn "*thumb1_one_cmplsi2"
3442   [(set (match_operand:SI         0 "register_operand" "=l")
3443         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3444   "TARGET_THUMB1"
3445   "mvn\\t%0, %1"
3446   [(set_attr "length" "2")]
3447 )
3448
3449 (define_insn "*notsi_compare0"
3450   [(set (reg:CC_NOOV CC_REGNUM)
3451         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3452                          (const_int 0)))
3453    (set (match_operand:SI 0 "s_register_operand" "=r")
3454         (not:SI (match_dup 1)))]
3455   "TARGET_32BIT"
3456   "mvn%.\\t%0, %1"
3457   [(set_attr "conds" "set")]
3458 )
3459
3460 (define_insn "*notsi_compare0_scratch"
3461   [(set (reg:CC_NOOV CC_REGNUM)
3462         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3463                          (const_int 0)))
3464    (clobber (match_scratch:SI 0 "=r"))]
3465   "TARGET_32BIT"
3466   "mvn%.\\t%0, %1"
3467   [(set_attr "conds" "set")]
3468 )
3469 \f
3470 ;; Fixed <--> Floating conversion insns
3471
3472 (define_expand "floatsisf2"
3473   [(set (match_operand:SF           0 "s_register_operand" "")
3474         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3475   "TARGET_32BIT && TARGET_HARD_FLOAT"
3476   "
3477   if (TARGET_MAVERICK)
3478     {
3479       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3480       DONE;
3481     }
3482 ")
3483
3484 (define_expand "floatsidf2"
3485   [(set (match_operand:DF           0 "s_register_operand" "")
3486         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3487   "TARGET_32BIT && TARGET_HARD_FLOAT"
3488   "
3489   if (TARGET_MAVERICK)
3490     {
3491       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3492       DONE;
3493     }
3494 ")
3495
3496 (define_expand "fix_truncsfsi2"
3497   [(set (match_operand:SI         0 "s_register_operand" "")
3498         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3499   "TARGET_32BIT && TARGET_HARD_FLOAT"
3500   "
3501   if (TARGET_MAVERICK)
3502     {
3503       if (!cirrus_fp_register (operands[0], SImode))
3504         operands[0] = force_reg (SImode, operands[0]);
3505       if (!cirrus_fp_register (operands[1], SFmode))
3506         operands[1] = force_reg (SFmode, operands[0]);
3507       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3508       DONE;
3509     }
3510 ")
3511
3512 (define_expand "fix_truncdfsi2"
3513   [(set (match_operand:SI         0 "s_register_operand" "")
3514         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3515   "TARGET_32BIT && TARGET_HARD_FLOAT"
3516   "
3517   if (TARGET_MAVERICK)
3518     {
3519       if (!cirrus_fp_register (operands[1], DFmode))
3520         operands[1] = force_reg (DFmode, operands[0]);
3521       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3522       DONE;
3523     }
3524 ")
3525
3526 ;; Truncation insns
3527
3528 (define_expand "truncdfsf2"
3529   [(set (match_operand:SF  0 "s_register_operand" "")
3530         (float_truncate:SF
3531          (match_operand:DF 1 "s_register_operand" "")))]
3532   "TARGET_32BIT && TARGET_HARD_FLOAT"
3533   ""
3534 )
3535 \f
3536 ;; Zero and sign extension instructions.
3537
3538 (define_expand "zero_extendsidi2"
3539   [(set (match_operand:DI 0 "s_register_operand" "")
3540         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
3541   "TARGET_32BIT"
3542   ""
3543 )
3544
3545 (define_insn "*arm_zero_extendsidi2"
3546   [(set (match_operand:DI 0 "s_register_operand" "=r")
3547         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3548   "TARGET_ARM"
3549   "*
3550     if (REGNO (operands[1])
3551         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3552       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3553     return \"mov%?\\t%R0, #0\";
3554   "
3555   [(set_attr "length" "8")
3556    (set_attr "predicable" "yes")]
3557 )
3558
3559 (define_expand "zero_extendqidi2"
3560   [(set (match_operand:DI                 0 "s_register_operand"  "")
3561         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))]
3562   "TARGET_32BIT"
3563   ""
3564 )
3565
3566 (define_insn "*arm_zero_extendqidi2"
3567   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3568         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3569   "TARGET_ARM"
3570   "@
3571    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3572    ldr%(b%)\\t%Q0, %1\;mov%?\\t%R0, #0"
3573   [(set_attr "length" "8")
3574    (set_attr "predicable" "yes")
3575    (set_attr "type" "*,load_byte")
3576    (set_attr "pool_range" "*,4092")
3577    (set_attr "neg_pool_range" "*,4084")]
3578 )
3579
3580 (define_expand "extendsidi2"
3581   [(set (match_operand:DI 0 "s_register_operand" "")
3582         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
3583   "TARGET_32BIT"
3584   ""
3585 )
3586
3587 (define_insn "*arm_extendsidi2"
3588   [(set (match_operand:DI 0 "s_register_operand" "=r")
3589         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3590   "TARGET_ARM"
3591   "*
3592     if (REGNO (operands[1])
3593         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3594       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3595     return \"mov%?\\t%R0, %Q0, asr #31\";
3596   "
3597   [(set_attr "length" "8")
3598    (set_attr "shift" "1")
3599    (set_attr "predicable" "yes")]
3600 )
3601
3602 (define_expand "zero_extendhisi2"
3603   [(set (match_dup 2)
3604         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3605                    (const_int 16)))
3606    (set (match_operand:SI 0 "s_register_operand" "")
3607         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3608   "TARGET_EITHER"
3609   "
3610   {
3611     if ((TARGET_THUMB1 || arm_arch4) && GET_CODE (operands[1]) == MEM)
3612       {
3613         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3614                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3615         DONE;
3616       }
3617
3618     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3619       {
3620         emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3621         DONE;
3622       }
3623
3624     if (!s_register_operand (operands[1], HImode))
3625       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3626
3627     if (arm_arch6)
3628       {
3629         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3630                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3631         DONE;
3632       }
3633
3634     operands[1] = gen_lowpart (SImode, operands[1]);
3635     operands[2] = gen_reg_rtx (SImode);
3636   }"
3637 )
3638
3639 (define_insn "*thumb1_zero_extendhisi2"
3640   [(set (match_operand:SI 0 "register_operand" "=l")
3641         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3642   "TARGET_THUMB1 && !arm_arch6"
3643   "*
3644   rtx mem = XEXP (operands[1], 0);
3645
3646   if (GET_CODE (mem) == CONST)
3647     mem = XEXP (mem, 0);
3648     
3649   if (GET_CODE (mem) == LABEL_REF)
3650     return \"ldr\\t%0, %1\";
3651     
3652   if (GET_CODE (mem) == PLUS)
3653     {
3654       rtx a = XEXP (mem, 0);
3655       rtx b = XEXP (mem, 1);
3656
3657       /* This can happen due to bugs in reload.  */
3658       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3659         {
3660           rtx ops[2];
3661           ops[0] = operands[0];
3662           ops[1] = a;
3663       
3664           output_asm_insn (\"mov        %0, %1\", ops);
3665
3666           XEXP (mem, 0) = operands[0];
3667        }
3668
3669       else if (   GET_CODE (a) == LABEL_REF
3670                && GET_CODE (b) == CONST_INT)
3671         return \"ldr\\t%0, %1\";
3672     }
3673     
3674   return \"ldrh\\t%0, %1\";
3675   "
3676   [(set_attr "length" "4")
3677    (set_attr "type" "load_byte")
3678    (set_attr "pool_range" "60")]
3679 )
3680
3681 (define_insn "*thumb1_zero_extendhisi2_v6"
3682   [(set (match_operand:SI 0 "register_operand" "=l,l")
3683         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3684   "TARGET_THUMB1 && arm_arch6"
3685   "*
3686   rtx mem;
3687
3688   if (which_alternative == 0)
3689     return \"uxth\\t%0, %1\";
3690
3691   mem = XEXP (operands[1], 0);
3692
3693   if (GET_CODE (mem) == CONST)
3694     mem = XEXP (mem, 0);
3695     
3696   if (GET_CODE (mem) == LABEL_REF)
3697     return \"ldr\\t%0, %1\";
3698     
3699   if (GET_CODE (mem) == PLUS)
3700     {
3701       rtx a = XEXP (mem, 0);
3702       rtx b = XEXP (mem, 1);
3703
3704       /* This can happen due to bugs in reload.  */
3705       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3706         {
3707           rtx ops[2];
3708           ops[0] = operands[0];
3709           ops[1] = a;
3710       
3711           output_asm_insn (\"mov        %0, %1\", ops);
3712
3713           XEXP (mem, 0) = operands[0];
3714        }
3715
3716       else if (   GET_CODE (a) == LABEL_REF
3717                && GET_CODE (b) == CONST_INT)
3718         return \"ldr\\t%0, %1\";
3719     }
3720     
3721   return \"ldrh\\t%0, %1\";
3722   "
3723   [(set_attr "length" "2,4")
3724    (set_attr "type" "alu_shift,load_byte")
3725    (set_attr "pool_range" "*,60")]
3726 )
3727
3728 (define_insn "*arm_zero_extendhisi2"
3729   [(set (match_operand:SI 0 "s_register_operand" "=r")
3730         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3731   "TARGET_ARM && arm_arch4 && !arm_arch6"
3732   "ldr%(h%)\\t%0, %1"
3733   [(set_attr "type" "load_byte")
3734    (set_attr "predicable" "yes")
3735    (set_attr "pool_range" "256")
3736    (set_attr "neg_pool_range" "244")]
3737 )
3738
3739 (define_insn "*arm_zero_extendhisi2_v6"
3740   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3741         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3742   "TARGET_ARM && arm_arch6"
3743   "@
3744    uxth%?\\t%0, %1
3745    ldr%(h%)\\t%0, %1"
3746   [(set_attr "type" "alu_shift,load_byte")
3747    (set_attr "predicable" "yes")
3748    (set_attr "pool_range" "*,256")
3749    (set_attr "neg_pool_range" "*,244")]
3750 )
3751
3752 (define_insn "*arm_zero_extendhisi2addsi"
3753   [(set (match_operand:SI 0 "s_register_operand" "=r")
3754         (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3755                  (match_operand:SI 2 "s_register_operand" "r")))]
3756   "TARGET_INT_SIMD"
3757   "uxtah%?\\t%0, %2, %1"
3758   [(set_attr "type" "alu_shift")
3759    (set_attr "predicable" "yes")]
3760 )
3761
3762 (define_expand "zero_extendqisi2"
3763   [(set (match_operand:SI 0 "s_register_operand" "")
3764         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3765   "TARGET_EITHER"
3766   "
3767   if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3768     {
3769       if (TARGET_ARM)
3770         {
3771           emit_insn (gen_andsi3 (operands[0],
3772                                  gen_lowpart (SImode, operands[1]),
3773                                  GEN_INT (255)));
3774         }
3775       else /* TARGET_THUMB */
3776         {
3777           rtx temp = gen_reg_rtx (SImode);
3778           rtx ops[3];
3779           
3780           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3781           operands[1] = gen_lowpart (SImode, operands[1]);
3782
3783           ops[0] = temp;
3784           ops[1] = operands[1];
3785           ops[2] = GEN_INT (24);
3786
3787           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3788                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3789           
3790           ops[0] = operands[0];
3791           ops[1] = temp;
3792           ops[2] = GEN_INT (24);
3793
3794           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3795                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3796         }
3797       DONE;
3798     }
3799   "
3800 )
3801
3802 (define_insn "*thumb1_zero_extendqisi2"
3803   [(set (match_operand:SI 0 "register_operand" "=l")
3804         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3805   "TARGET_THUMB1 && !arm_arch6"
3806   "ldrb\\t%0, %1"
3807   [(set_attr "length" "2")
3808    (set_attr "type" "load_byte")
3809    (set_attr "pool_range" "32")]
3810 )
3811
3812 (define_insn "*thumb1_zero_extendqisi2_v6"
3813   [(set (match_operand:SI 0 "register_operand" "=l,l")
3814         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3815   "TARGET_THUMB1 && arm_arch6"
3816   "@
3817    uxtb\\t%0, %1
3818    ldrb\\t%0, %1"
3819   [(set_attr "length" "2,2")
3820    (set_attr "type" "alu_shift,load_byte")
3821    (set_attr "pool_range" "*,32")]
3822 )
3823
3824 (define_insn "*arm_zero_extendqisi2"
3825   [(set (match_operand:SI 0 "s_register_operand" "=r")
3826         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3827   "TARGET_ARM && !arm_arch6"
3828   "ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
3829   [(set_attr "type" "load_byte")
3830    (set_attr "predicable" "yes")
3831    (set_attr "pool_range" "4096")
3832    (set_attr "neg_pool_range" "4084")]
3833 )
3834
3835 (define_insn "*arm_zero_extendqisi2_v6"
3836   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3837         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3838   "TARGET_ARM && arm_arch6"
3839   "@
3840    uxtb%(%)\\t%0, %1
3841    ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
3842   [(set_attr "type" "alu_shift,load_byte")
3843    (set_attr "predicable" "yes")
3844    (set_attr "pool_range" "*,4096")
3845    (set_attr "neg_pool_range" "*,4084")]
3846 )
3847
3848 (define_insn "*arm_zero_extendqisi2addsi"
3849   [(set (match_operand:SI 0 "s_register_operand" "=r")
3850         (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3851                  (match_operand:SI 2 "s_register_operand" "r")))]
3852   "TARGET_INT_SIMD"
3853   "uxtab%?\\t%0, %2, %1"
3854   [(set_attr "predicable" "yes")
3855    (set_attr "type" "alu_shift")]
3856 )
3857
3858 (define_split
3859   [(set (match_operand:SI 0 "s_register_operand" "")
3860         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3861    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3862   "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3863   [(set (match_dup 2) (match_dup 1))
3864    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3865   ""
3866 )
3867
3868 (define_split
3869   [(set (match_operand:SI 0 "s_register_operand" "")
3870         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
3871    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3872   "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
3873   [(set (match_dup 2) (match_dup 1))
3874    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3875   ""
3876 )
3877
3878 (define_insn "*compareqi_eq0"
3879   [(set (reg:CC_Z CC_REGNUM)
3880         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3881                          (const_int 0)))]
3882   "TARGET_32BIT"
3883   "tst\\t%0, #255"
3884   [(set_attr "conds" "set")]
3885 )
3886
3887 (define_expand "extendhisi2"
3888   [(set (match_dup 2)
3889         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3890                    (const_int 16)))
3891    (set (match_operand:SI 0 "s_register_operand" "")
3892         (ashiftrt:SI (match_dup 2)
3893                      (const_int 16)))]
3894   "TARGET_EITHER"
3895   "
3896   {
3897     if (GET_CODE (operands[1]) == MEM)
3898       {
3899         if (TARGET_THUMB1)
3900           {
3901             emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
3902             DONE;
3903           }
3904         else if (arm_arch4)
3905           {
3906             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3907                        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3908             DONE;
3909           }
3910       }
3911
3912     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3913       {
3914         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3915         DONE;
3916       }
3917
3918     if (!s_register_operand (operands[1], HImode))
3919       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3920
3921     if (arm_arch6)
3922       {
3923         if (TARGET_THUMB1)
3924           emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
3925         else
3926           emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3927                      gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3928
3929         DONE;
3930       }
3931
3932     operands[1] = gen_lowpart (SImode, operands[1]);
3933     operands[2] = gen_reg_rtx (SImode);
3934   }"
3935 )
3936
3937 (define_insn "thumb1_extendhisi2"
3938   [(set (match_operand:SI 0 "register_operand" "=l")
3939         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3940    (clobber (match_scratch:SI 2 "=&l"))]
3941   "TARGET_THUMB1 && !arm_arch6"
3942   "*
3943   {
3944     rtx ops[4];
3945     rtx mem = XEXP (operands[1], 0);
3946
3947     /* This code used to try to use 'V', and fix the address only if it was
3948        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3949        range of QImode offsets, and offsettable_address_p does a QImode
3950        address check.  */
3951        
3952     if (GET_CODE (mem) == CONST)
3953       mem = XEXP (mem, 0);
3954     
3955     if (GET_CODE (mem) == LABEL_REF)
3956       return \"ldr\\t%0, %1\";
3957     
3958     if (GET_CODE (mem) == PLUS)
3959       {
3960         rtx a = XEXP (mem, 0);
3961         rtx b = XEXP (mem, 1);
3962
3963         if (GET_CODE (a) == LABEL_REF
3964             && GET_CODE (b) == CONST_INT)
3965           return \"ldr\\t%0, %1\";
3966
3967         if (GET_CODE (b) == REG)
3968           return \"ldrsh\\t%0, %1\";
3969           
3970         ops[1] = a;
3971         ops[2] = b;
3972       }
3973     else
3974       {
3975         ops[1] = mem;
3976         ops[2] = const0_rtx;
3977       }
3978
3979     gcc_assert (GET_CODE (ops[1]) == REG);
3980
3981     ops[0] = operands[0];
3982     ops[3] = operands[2];
3983     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3984     return \"\";
3985   }"
3986   [(set_attr "length" "4")
3987    (set_attr "type" "load_byte")
3988    (set_attr "pool_range" "1020")]
3989 )
3990
3991 ;; We used to have an early-clobber on the scratch register here.
3992 ;; However, there's a bug somewhere in reload which means that this
3993 ;; can be partially ignored during spill allocation if the memory
3994 ;; address also needs reloading; this causes us to die later on when
3995 ;; we try to verify the operands.  Fortunately, we don't really need
3996 ;; the early-clobber: we can always use operand 0 if operand 2
3997 ;; overlaps the address.
3998 (define_insn "*thumb1_extendhisi2_insn_v6"
3999   [(set (match_operand:SI 0 "register_operand" "=l,l")
4000         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
4001    (clobber (match_scratch:SI 2 "=X,l"))]
4002   "TARGET_THUMB1 && arm_arch6"
4003   "*
4004   {
4005     rtx ops[4];
4006     rtx mem;
4007
4008     if (which_alternative == 0)
4009       return \"sxth\\t%0, %1\";
4010
4011     mem = XEXP (operands[1], 0);
4012
4013     /* This code used to try to use 'V', and fix the address only if it was
4014        offsettable, but this fails for e.g. REG+48 because 48 is outside the
4015        range of QImode offsets, and offsettable_address_p does a QImode
4016        address check.  */
4017        
4018     if (GET_CODE (mem) == CONST)
4019       mem = XEXP (mem, 0);
4020     
4021     if (GET_CODE (mem) == LABEL_REF)
4022       return \"ldr\\t%0, %1\";
4023     
4024     if (GET_CODE (mem) == PLUS)
4025       {
4026         rtx a = XEXP (mem, 0);
4027         rtx b = XEXP (mem, 1);
4028
4029         if (GET_CODE (a) == LABEL_REF
4030             && GET_CODE (b) == CONST_INT)
4031           return \"ldr\\t%0, %1\";
4032
4033         if (GET_CODE (b) == REG)
4034           return \"ldrsh\\t%0, %1\";
4035           
4036         ops[1] = a;
4037         ops[2] = b;
4038       }
4039     else
4040       {
4041         ops[1] = mem;
4042         ops[2] = const0_rtx;
4043       }
4044       
4045     gcc_assert (GET_CODE (ops[1]) == REG);
4046
4047     ops[0] = operands[0];
4048     if (reg_mentioned_p (operands[2], ops[1]))
4049       ops[3] = ops[0];
4050     else
4051       ops[3] = operands[2];
4052     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4053     return \"\";
4054   }"
4055   [(set_attr "length" "2,4")
4056    (set_attr "type" "alu_shift,load_byte")
4057    (set_attr "pool_range" "*,1020")]
4058 )
4059
4060 ;; This pattern will only be used when ldsh is not available
4061 (define_expand "extendhisi2_mem"
4062   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4063    (set (match_dup 3)
4064         (zero_extend:SI (match_dup 7)))
4065    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4066    (set (match_operand:SI 0 "" "")
4067         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
4068   "TARGET_ARM"
4069   "
4070   {
4071     rtx mem1, mem2;
4072     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4073
4074     mem1 = change_address (operands[1], QImode, addr);
4075     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
4076     operands[0] = gen_lowpart (SImode, operands[0]);
4077     operands[1] = mem1;
4078     operands[2] = gen_reg_rtx (SImode);
4079     operands[3] = gen_reg_rtx (SImode);
4080     operands[6] = gen_reg_rtx (SImode);
4081     operands[7] = mem2;
4082
4083     if (BYTES_BIG_ENDIAN)
4084       {
4085         operands[4] = operands[2];
4086         operands[5] = operands[3];
4087       }
4088     else
4089       {
4090         operands[4] = operands[3];
4091         operands[5] = operands[2];
4092       }
4093   }"
4094 )
4095
4096 (define_insn "*arm_extendhisi2"
4097   [(set (match_operand:SI 0 "s_register_operand" "=r")
4098         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
4099   "TARGET_ARM && arm_arch4 && !arm_arch6"
4100   "ldr%(sh%)\\t%0, %1"
4101   [(set_attr "type" "load_byte")
4102    (set_attr "predicable" "yes")
4103    (set_attr "pool_range" "256")
4104    (set_attr "neg_pool_range" "244")]
4105 )
4106
4107 ;; ??? Check Thumb-2 pool range
4108 (define_insn "*arm_extendhisi2_v6"
4109   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4110         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4111   "TARGET_32BIT && arm_arch6"
4112   "@
4113    sxth%?\\t%0, %1
4114    ldr%(sh%)\\t%0, %1"
4115   [(set_attr "type" "alu_shift,load_byte")
4116    (set_attr "predicable" "yes")
4117    (set_attr "pool_range" "*,256")
4118    (set_attr "neg_pool_range" "*,244")]
4119 )
4120
4121 (define_insn "*arm_extendhisi2addsi"
4122   [(set (match_operand:SI 0 "s_register_operand" "=r")
4123         (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4124                  (match_operand:SI 2 "s_register_operand" "r")))]
4125   "TARGET_INT_SIMD"
4126   "sxtah%?\\t%0, %2, %1"
4127 )
4128
4129 (define_expand "extendqihi2"
4130   [(set (match_dup 2)
4131         (ashift:SI (match_operand:QI 1 "general_operand" "")
4132                    (const_int 24)))
4133    (set (match_operand:HI 0 "s_register_operand" "")
4134         (ashiftrt:SI (match_dup 2)
4135                      (const_int 24)))]
4136   "TARGET_ARM"
4137   "
4138   {
4139     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
4140       {
4141         emit_insn (gen_rtx_SET (VOIDmode,
4142                                 operands[0],
4143                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
4144         DONE;
4145       }
4146     if (!s_register_operand (operands[1], QImode))
4147       operands[1] = copy_to_mode_reg (QImode, operands[1]);
4148     operands[0] = gen_lowpart (SImode, operands[0]);
4149     operands[1] = gen_lowpart (SImode, operands[1]);
4150     operands[2] = gen_reg_rtx (SImode);
4151   }"
4152 )
4153
4154 (define_insn "*arm_extendqihi_insn"
4155   [(set (match_operand:HI 0 "s_register_operand" "=r")
4156         (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
4157   "TARGET_ARM && arm_arch4"
4158   "ldr%(sb%)\\t%0, %1"
4159   [(set_attr "type" "load_byte")
4160    (set_attr "predicable" "yes")
4161    (set_attr "pool_range" "256")
4162    (set_attr "neg_pool_range" "244")]
4163 )
4164
4165 (define_expand "extendqisi2"
4166   [(set (match_dup 2)
4167         (ashift:SI (match_operand:QI 1 "general_operand" "")
4168                    (const_int 24)))
4169    (set (match_operand:SI 0 "s_register_operand" "")
4170         (ashiftrt:SI (match_dup 2)
4171                      (const_int 24)))]
4172   "TARGET_EITHER"
4173   "
4174   {
4175     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
4176       {
4177         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4178                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4179         DONE;
4180       }
4181
4182     if (!s_register_operand (operands[1], QImode))
4183       operands[1] = copy_to_mode_reg (QImode, operands[1]);
4184
4185     if (arm_arch6)
4186       {
4187         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4188                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4189         DONE;
4190       }
4191
4192     operands[1] = gen_lowpart (SImode, operands[1]);
4193     operands[2] = gen_reg_rtx (SImode);
4194   }"
4195 )
4196
4197 (define_insn "*arm_extendqisi"
4198   [(set (match_operand:SI 0 "s_register_operand" "=r")
4199         (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
4200   "TARGET_ARM && arm_arch4 && !arm_arch6"
4201   "ldr%(sb%)\\t%0, %1"
4202   [(set_attr "type" "load_byte")
4203    (set_attr "predicable" "yes")
4204    (set_attr "pool_range" "256")
4205    (set_attr "neg_pool_range" "244")]
4206 )
4207
4208 (define_insn "*arm_extendqisi_v6"
4209   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4210         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
4211   "TARGET_ARM && arm_arch6"
4212   "@
4213    sxtb%?\\t%0, %1
4214    ldr%(sb%)\\t%0, %1"
4215   [(set_attr "type" "alu_shift,load_byte")
4216    (set_attr "predicable" "yes")
4217    (set_attr "pool_range" "*,256")
4218    (set_attr "neg_pool_range" "*,244")]
4219 )
4220
4221 (define_insn "*arm_extendqisi2addsi"
4222   [(set (match_operand:SI 0 "s_register_operand" "=r")
4223         (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4224                  (match_operand:SI 2 "s_register_operand" "r")))]
4225   "TARGET_INT_SIMD"
4226   "sxtab%?\\t%0, %2, %1"
4227   [(set_attr "type" "alu_shift")
4228    (set_attr "predicable" "yes")]
4229 )
4230
4231 (define_insn "*thumb1_extendqisi2"
4232   [(set (match_operand:SI 0 "register_operand" "=l,l")
4233         (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
4234   "TARGET_THUMB1 && !arm_arch6"
4235   "*
4236   {
4237     rtx ops[3];
4238     rtx mem = XEXP (operands[1], 0);
4239     
4240     if (GET_CODE (mem) == CONST)
4241       mem = XEXP (mem, 0);
4242     
4243     if (GET_CODE (mem) == LABEL_REF)
4244       return \"ldr\\t%0, %1\";
4245
4246     if (GET_CODE (mem) == PLUS
4247         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4248       return \"ldr\\t%0, %1\";
4249       
4250     if (which_alternative == 0)
4251       return \"ldrsb\\t%0, %1\";
4252       
4253     ops[0] = operands[0];
4254     
4255     if (GET_CODE (mem) == PLUS)
4256       {
4257         rtx a = XEXP (mem, 0);
4258         rtx b = XEXP (mem, 1);
4259         
4260         ops[1] = a;
4261         ops[2] = b;
4262
4263         if (GET_CODE (a) == REG)
4264           {
4265             if (GET_CODE (b) == REG)
4266               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4267             else if (REGNO (a) == REGNO (ops[0]))
4268               {
4269                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4270                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4271                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4272               }
4273             else
4274               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4275           }
4276         else
4277           {
4278             gcc_assert (GET_CODE (b) == REG);
4279             if (REGNO (b) == REGNO (ops[0]))
4280               {
4281                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4282                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4283                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4284               }
4285             else
4286               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4287           }
4288       }
4289     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4290       {
4291         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4292         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4293         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4294       }
4295     else
4296       {
4297         ops[1] = mem;
4298         ops[2] = const0_rtx;
4299         
4300         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4301       }
4302     return \"\";
4303   }"
4304   [(set_attr "length" "2,6")
4305    (set_attr "type" "load_byte,load_byte")
4306    (set_attr "pool_range" "32,32")]
4307 )
4308
4309 (define_insn "*thumb1_extendqisi2_v6"
4310   [(set (match_operand:SI 0 "register_operand" "=l,l,l")
4311         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
4312   "TARGET_THUMB1 && arm_arch6"
4313   "*
4314   {
4315     rtx ops[3];
4316     rtx mem;
4317
4318     if (which_alternative == 0)
4319       return \"sxtb\\t%0, %1\";
4320
4321     mem = XEXP (operands[1], 0);
4322     
4323     if (GET_CODE (mem) == CONST)
4324       mem = XEXP (mem, 0);
4325     
4326     if (GET_CODE (mem) == LABEL_REF)
4327       return \"ldr\\t%0, %1\";
4328
4329     if (GET_CODE (mem) == PLUS
4330         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4331       return \"ldr\\t%0, %1\";
4332       
4333     if (which_alternative == 0)
4334       return \"ldrsb\\t%0, %1\";
4335       
4336     ops[0] = operands[0];
4337     
4338     if (GET_CODE (mem) == PLUS)
4339       {
4340         rtx a = XEXP (mem, 0);
4341         rtx b = XEXP (mem, 1);
4342         
4343         ops[1] = a;
4344         ops[2] = b;
4345
4346         if (GET_CODE (a) == REG)
4347           {
4348             if (GET_CODE (b) == REG)
4349               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4350             else if (REGNO (a) == REGNO (ops[0]))
4351               {
4352                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4353                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4354               }
4355             else
4356               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4357           }
4358         else
4359           {
4360             gcc_assert (GET_CODE (b) == REG);
4361             if (REGNO (b) == REGNO (ops[0]))
4362               {
4363                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4364                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4365               }
4366             else
4367               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4368           }
4369       }
4370     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4371       {
4372         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4373         output_asm_insn (\"sxtb\\t%0, %0\", ops);
4374       }
4375     else
4376       {
4377         ops[1] = mem;
4378         ops[2] = const0_rtx;
4379         
4380         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4381       }
4382     return \"\";
4383   }"
4384   [(set_attr "length" "2,2,4")
4385    (set_attr "type" "alu_shift,load_byte,load_byte")
4386    (set_attr "pool_range" "*,32,32")]
4387 )
4388
4389 (define_expand "extendsfdf2"
4390   [(set (match_operand:DF                  0 "s_register_operand" "")
4391         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
4392   "TARGET_32BIT && TARGET_HARD_FLOAT"
4393   ""
4394 )
4395 \f
4396 ;; Move insns (including loads and stores)
4397
4398 ;; XXX Just some ideas about movti.
4399 ;; I don't think these are a good idea on the arm, there just aren't enough
4400 ;; registers
4401 ;;(define_expand "loadti"
4402 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
4403 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
4404 ;;  "" "")
4405
4406 ;;(define_expand "storeti"
4407 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4408 ;;      (match_operand:TI 1 "s_register_operand" ""))]
4409 ;;  "" "")
4410
4411 ;;(define_expand "movti"
4412 ;;  [(set (match_operand:TI 0 "general_operand" "")
4413 ;;      (match_operand:TI 1 "general_operand" ""))]
4414 ;;  ""
4415 ;;  "
4416 ;;{
4417 ;;  rtx insn;
4418 ;;
4419 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4420 ;;    operands[1] = copy_to_reg (operands[1]);
4421 ;;  if (GET_CODE (operands[0]) == MEM)
4422 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4423 ;;  else if (GET_CODE (operands[1]) == MEM)
4424 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4425 ;;  else
4426 ;;    FAIL;
4427 ;;
4428 ;;  emit_insn (insn);
4429 ;;  DONE;
4430 ;;}")
4431
4432 ;; Recognize garbage generated above.
4433
4434 ;;(define_insn ""
4435 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4436 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4437 ;;  ""
4438 ;;  "*
4439 ;;  {
4440 ;;    register mem = (which_alternative < 3);
4441 ;;    register const char *template;
4442 ;;
4443 ;;    operands[mem] = XEXP (operands[mem], 0);
4444 ;;    switch (which_alternative)
4445 ;;      {
4446 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4447 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
4448 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
4449 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
4450 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
4451 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
4452 ;;      }
4453 ;;    output_asm_insn (template, operands);
4454 ;;    return \"\";
4455 ;;  }")
4456
4457 (define_expand "movdi"
4458   [(set (match_operand:DI 0 "general_operand" "")
4459         (match_operand:DI 1 "general_operand" ""))]
4460   "TARGET_EITHER"
4461   "
4462   if (!no_new_pseudos)
4463     {
4464       if (GET_CODE (operands[0]) != REG)
4465         operands[1] = force_reg (DImode, operands[1]);
4466     }
4467   "
4468 )
4469
4470 (define_insn "*arm_movdi"
4471   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4472         (match_operand:DI 1 "di_operand"              "rDa,Db,Dc,mi,r"))]
4473   "TARGET_ARM
4474    && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4475    && !TARGET_IWMMXT
4476    && (   register_operand (operands[0], DImode)
4477        || register_operand (operands[1], DImode))"
4478   "*
4479   switch (which_alternative)
4480     {
4481     case 0:
4482     case 1:
4483     case 2:
4484       return \"#\";
4485     default:
4486       return output_move_double (operands);
4487     }
4488   "
4489   [(set_attr "length" "8,12,16,8,8")
4490    (set_attr "type" "*,*,*,load2,store2")
4491    (set_attr "pool_range" "*,*,*,1020,*")
4492    (set_attr "neg_pool_range" "*,*,*,1008,*")]
4493 )
4494
4495 (define_split
4496   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4497         (match_operand:ANY64 1 "const_double_operand" ""))]
4498   "TARGET_32BIT
4499    && reload_completed
4500    && (arm_const_double_inline_cost (operands[1])
4501        <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4502   [(const_int 0)]
4503   "
4504   arm_split_constant (SET, SImode, curr_insn,
4505                       INTVAL (gen_lowpart (SImode, operands[1])),
4506                       gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4507   arm_split_constant (SET, SImode, curr_insn,
4508                       INTVAL (gen_highpart_mode (SImode,
4509                                                  GET_MODE (operands[0]),
4510                                                  operands[1])),
4511                       gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4512   DONE;
4513   "
4514 )
4515
4516 ; If optimizing for size, or if we have load delay slots, then 
4517 ; we want to split the constant into two separate operations. 
4518 ; In both cases this may split a trivial part into a single data op
4519 ; leaving a single complex constant to load.  We can also get longer
4520 ; offsets in a LDR which means we get better chances of sharing the pool
4521 ; entries.  Finally, we can normally do a better job of scheduling
4522 ; LDR instructions than we can with LDM.
4523 ; This pattern will only match if the one above did not.
4524 (define_split
4525   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4526         (match_operand:ANY64 1 "const_double_operand" ""))]
4527   "TARGET_ARM && reload_completed
4528    && arm_const_double_by_parts (operands[1])"
4529   [(set (match_dup 0) (match_dup 1))
4530    (set (match_dup 2) (match_dup 3))]
4531   "
4532   operands[2] = gen_highpart (SImode, operands[0]);
4533   operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4534                                    operands[1]);
4535   operands[0] = gen_lowpart (SImode, operands[0]);
4536   operands[1] = gen_lowpart (SImode, operands[1]);
4537   "
4538 )
4539
4540 (define_split
4541   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4542         (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4543   "TARGET_EITHER && reload_completed"
4544   [(set (match_dup 0) (match_dup 1))
4545    (set (match_dup 2) (match_dup 3))]
4546   "
4547   operands[2] = gen_highpart (SImode, operands[0]);
4548   operands[3] = gen_highpart (SImode, operands[1]);
4549   operands[0] = gen_lowpart (SImode, operands[0]);
4550   operands[1] = gen_lowpart (SImode, operands[1]);
4551
4552   /* Handle a partial overlap.  */
4553   if (rtx_equal_p (operands[0], operands[3]))
4554     {
4555       rtx tmp0 = operands[0];
4556       rtx tmp1 = operands[1];
4557
4558       operands[0] = operands[2];
4559       operands[1] = operands[3];
4560       operands[2] = tmp0;
4561       operands[3] = tmp1;
4562     }
4563   "
4564 )
4565
4566 ;; We can't actually do base+index doubleword loads if the index and
4567 ;; destination overlap.  Split here so that we at least have chance to
4568 ;; schedule.
4569 (define_split
4570   [(set (match_operand:DI 0 "s_register_operand" "")
4571         (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4572                          (match_operand:SI 2 "s_register_operand" ""))))]
4573   "TARGET_LDRD
4574   && reg_overlap_mentioned_p (operands[0], operands[1])
4575   && reg_overlap_mentioned_p (operands[0], operands[2])"
4576   [(set (match_dup 4)
4577         (plus:SI (match_dup 1)
4578                  (match_dup 2)))
4579    (set (match_dup 0)
4580         (mem:DI (match_dup 4)))]
4581   "
4582   operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4583   "
4584 )
4585
4586 ;;; ??? This should have alternatives for constants.
4587 ;;; ??? This was originally identical to the movdf_insn pattern.
4588 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4589 ;;; thumb_reorg with a memory reference.
4590 (define_insn "*thumb1_movdi_insn"
4591   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4592         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
4593   "TARGET_THUMB1
4594    && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4595    && (   register_operand (operands[0], DImode)
4596        || register_operand (operands[1], DImode))"
4597   "*
4598   {
4599   switch (which_alternative)
4600     {
4601     default:
4602     case 0:
4603       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4604         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
4605       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
4606     case 1:
4607       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4608     case 2:
4609       operands[1] = GEN_INT (- INTVAL (operands[1]));
4610       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4611     case 3:
4612       return \"ldmia\\t%1, {%0, %H0}\";
4613     case 4:
4614       return \"stmia\\t%0, {%1, %H1}\";
4615     case 5:
4616       return thumb_load_double_from_address (operands);
4617     case 6:
4618       operands[2] = gen_rtx_MEM (SImode,
4619                              plus_constant (XEXP (operands[0], 0), 4));
4620       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4621       return \"\";
4622     case 7:
4623       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4624         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4625       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4626     }
4627   }"
4628   [(set_attr "length" "4,4,6,2,2,6,4,4")
4629    (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4630    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4631 )
4632
4633 (define_expand "movsi"
4634   [(set (match_operand:SI 0 "general_operand" "")
4635         (match_operand:SI 1 "general_operand" ""))]
4636   "TARGET_EITHER"
4637   "
4638   if (TARGET_32BIT)
4639     {
4640       /* Everything except mem = const or mem = mem can be done easily.  */
4641       if (GET_CODE (operands[0]) == MEM)
4642         operands[1] = force_reg (SImode, operands[1]);
4643       if (arm_general_register_operand (operands[0], SImode)
4644           && GET_CODE (operands[1]) == CONST_INT
4645           && !(const_ok_for_arm (INTVAL (operands[1]))
4646                || const_ok_for_arm (~INTVAL (operands[1]))))
4647         {
4648            arm_split_constant (SET, SImode, NULL_RTX,
4649                                INTVAL (operands[1]), operands[0], NULL_RTX,
4650                                optimize && !no_new_pseudos);
4651           DONE;
4652         }
4653     }
4654   else /* TARGET_THUMB1...  */
4655     {
4656       if (!no_new_pseudos)
4657         {
4658           if (GET_CODE (operands[0]) != REG)
4659             operands[1] = force_reg (SImode, operands[1]);
4660         }
4661     }
4662
4663   /* Recognize the case where operand[1] is a reference to thread-local
4664      data and load its address to a register.  */
4665   if (arm_tls_referenced_p (operands[1]))
4666     {
4667       rtx tmp = operands[1];
4668       rtx addend = NULL;
4669
4670       if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
4671         {
4672           addend = XEXP (XEXP (tmp, 0), 1);
4673           tmp = XEXP (XEXP (tmp, 0), 0);
4674         }
4675
4676       gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
4677       gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
4678
4679       tmp = legitimize_tls_address (tmp, no_new_pseudos ? operands[0] : 0);
4680       if (addend)
4681         {
4682           tmp = gen_rtx_PLUS (SImode, tmp, addend);
4683           tmp = force_operand (tmp, operands[0]);
4684         }
4685       operands[1] = tmp;
4686     }
4687   else if (flag_pic
4688            && (CONSTANT_P (operands[1])
4689                || symbol_mentioned_p (operands[1])
4690                || label_mentioned_p (operands[1])))
4691       operands[1] = legitimize_pic_address (operands[1], SImode,
4692                                             (no_new_pseudos ? operands[0] : 0));
4693   "
4694 )
4695
4696 (define_insn "*arm_movsi_insn"
4697   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r, m")
4698         (match_operand:SI 1 "general_operand"      "rI,K,N,mi,r"))]
4699   "TARGET_ARM && ! TARGET_IWMMXT
4700    && !(TARGET_HARD_FLOAT && TARGET_VFP)
4701    && (   register_operand (operands[0], SImode)
4702        || register_operand (operands[1], SImode))"
4703   "@
4704    mov%?\\t%0, %1
4705    mvn%?\\t%0, #%B1
4706    movw%?\\t%0, %1
4707    ldr%?\\t%0, %1
4708    str%?\\t%1, %0"
4709   [(set_attr "type" "*,*,*,load1,store1")
4710    (set_attr "predicable" "yes")
4711    (set_attr "pool_range" "*,*,*,4096,*")
4712    (set_attr "neg_pool_range" "*,*,*,4084,*")]
4713 )
4714
4715 (define_split
4716   [(set (match_operand:SI 0 "arm_general_register_operand" "")
4717         (match_operand:SI 1 "const_int_operand" ""))]
4718   "TARGET_32BIT
4719   && (!(const_ok_for_arm (INTVAL (operands[1]))
4720         || const_ok_for_arm (~INTVAL (operands[1]))))"
4721   [(clobber (const_int 0))]
4722   "
4723   arm_split_constant (SET, SImode, NULL_RTX, 
4724                       INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4725   DONE;
4726   "
4727 )
4728
4729 (define_insn "*thumb1_movsi_insn"
4730   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4731         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4732   "TARGET_THUMB1
4733    && (   register_operand (operands[0], SImode) 
4734        || register_operand (operands[1], SImode))"
4735   "@
4736    mov  %0, %1
4737    mov  %0, %1
4738    #
4739    #
4740    ldmia\\t%1, {%0}
4741    stmia\\t%0, {%1}
4742    ldr\\t%0, %1
4743    str\\t%1, %0
4744    mov\\t%0, %1"
4745   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4746    (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4747    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4748 )
4749
4750 (define_split 
4751   [(set (match_operand:SI 0 "register_operand" "")
4752         (match_operand:SI 1 "const_int_operand" ""))]
4753   "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
4754   [(set (match_dup 0) (match_dup 1))
4755    (set (match_dup 0) (neg:SI (match_dup 0)))]
4756   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4757 )
4758
4759 (define_split 
4760   [(set (match_operand:SI 0 "register_operand" "")
4761         (match_operand:SI 1 "const_int_operand" ""))]
4762   "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
4763   [(set (match_dup 0) (match_dup 1))
4764    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4765   "
4766   {
4767     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4768     unsigned HOST_WIDE_INT mask = 0xff;
4769     int i;
4770     
4771     for (i = 0; i < 25; i++)
4772       if ((val & (mask << i)) == val)
4773         break;
4774
4775     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4776     if (i == 0)
4777       FAIL;
4778
4779     operands[1] = GEN_INT (val >> i);
4780     operands[2] = GEN_INT (i);
4781   }"
4782 )
4783
4784 ;; When generating pic, we need to load the symbol offset into a register.
4785 ;; So that the optimizer does not confuse this with a normal symbol load
4786 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
4787 ;; since that is the only type of relocation we can use.
4788
4789 ;; The rather odd constraints on the following are to force reload to leave
4790 ;; the insn alone, and to force the minipool generation pass to then move
4791 ;; the GOT symbol to memory.
4792
4793 (define_insn "pic_load_addr_arm"
4794   [(set (match_operand:SI 0 "s_register_operand" "=r")
4795         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4796   "TARGET_ARM && flag_pic"
4797   "ldr%?\\t%0, %1"
4798   [(set_attr "type" "load1")
4799    (set (attr "pool_range")     (const_int 4096))
4800    (set (attr "neg_pool_range") (const_int 4084))]
4801 )
4802
4803 (define_insn "pic_load_addr_thumb1"
4804   [(set (match_operand:SI 0 "s_register_operand" "=l")
4805         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4806   "TARGET_THUMB1 && flag_pic"
4807   "ldr\\t%0, %1"
4808   [(set_attr "type" "load1")
4809    (set (attr "pool_range") (const_int 1024))]
4810 )
4811
4812 ;; This variant is used for AOF assembly, since it needs to mention the
4813 ;; pic register in the rtl.
4814 (define_expand "pic_load_addr_based"
4815   [(set (match_operand:SI 0 "s_register_operand" "")
4816         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4817   "TARGET_ARM && flag_pic"
4818   "operands[2] = cfun->machine->pic_reg;"
4819 )
4820
4821 (define_insn "*pic_load_addr_based_insn"
4822   [(set (match_operand:SI 0 "s_register_operand" "=r")
4823         (unspec:SI [(match_operand 1 "" "")
4824                     (match_operand 2 "s_register_operand" "r")]
4825                    UNSPEC_PIC_SYM))]
4826   "TARGET_EITHER && flag_pic && operands[2] == cfun->machine->pic_reg"
4827   "*
4828 #ifdef AOF_ASSEMBLER
4829   operands[1] = aof_pic_entry (operands[1]);
4830 #endif
4831   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4832   return \"\";
4833   "
4834   [(set_attr "type" "load1")
4835    (set (attr "pool_range")
4836         (if_then_else (eq_attr "is_thumb" "yes")
4837                       (const_int 1024)
4838                       (const_int 4096)))
4839    (set (attr "neg_pool_range")
4840         (if_then_else (eq_attr "is_thumb" "yes")
4841                       (const_int 0)
4842                       (const_int 4084)))]
4843 )
4844
4845 (define_insn "pic_add_dot_plus_four"
4846   [(set (match_operand:SI 0 "register_operand" "=r")
4847         (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "0")
4848                              (const (plus:SI (pc) (const_int 4))))]
4849                    UNSPEC_PIC_BASE))
4850    (use (match_operand 2 "" ""))]
4851   "TARGET_THUMB1"
4852   "*
4853   (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4854                                      INTVAL (operands[2]));
4855   return \"add\\t%0, %|pc\";
4856   "
4857   [(set_attr "length" "2")]
4858 )
4859
4860 (define_insn "pic_add_dot_plus_eight"
4861   [(set (match_operand:SI 0 "register_operand" "=r")
4862         (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
4863                              (const (plus:SI (pc) (const_int 8))))]
4864                    UNSPEC_PIC_BASE))
4865    (use (match_operand 2 "" ""))]
4866   "TARGET_ARM"
4867   "*
4868     (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4869                                        INTVAL (operands[2]));
4870     return \"add%?\\t%0, %|pc, %1\";
4871   "
4872   [(set_attr "predicable" "yes")]
4873 )
4874
4875 (define_insn "tls_load_dot_plus_eight"
4876   [(set (match_operand:SI 0 "register_operand" "+r")
4877         (mem:SI (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
4878                                      (const (plus:SI (pc) (const_int 8))))]
4879                            UNSPEC_PIC_BASE)))
4880    (use (match_operand 2 "" ""))]
4881   "TARGET_ARM"
4882   "*
4883     (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4884                                        INTVAL (operands[2]));
4885     return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
4886   "
4887   [(set_attr "predicable" "yes")]
4888 )
4889
4890 ;; PIC references to local variables can generate pic_add_dot_plus_eight
4891 ;; followed by a load.  These sequences can be crunched down to
4892 ;; tls_load_dot_plus_eight by a peephole.
4893
4894 (define_peephole2
4895   [(parallel [(set (match_operand:SI 0 "register_operand" "")
4896                    (unspec:SI [(plus:SI (match_operand:SI 3 "register_operand" "")
4897                                         (const (plus:SI (pc) (const_int 8))))]
4898                               UNSPEC_PIC_BASE))
4899               (use (label_ref (match_operand 1 "" "")))])
4900    (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
4901   "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
4902   [(parallel [(set (match_dup 2)
4903                    (mem:SI (unspec:SI [(plus:SI (match_dup 3)
4904                                                 (const (plus:SI (pc) (const_int 8))))]
4905                                       UNSPEC_PIC_BASE)))
4906               (use (label_ref (match_dup 1)))])]
4907   ""
4908 )
4909
4910 (define_expand "builtin_setjmp_receiver"
4911   [(label_ref (match_operand 0 "" ""))]
4912   "flag_pic"
4913   "
4914 {
4915   /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4916      register.  */
4917   if (arm_pic_register != INVALID_REGNUM)
4918     arm_load_pic_register (1UL << 3);
4919   DONE;
4920 }")
4921
4922 ;; If copying one reg to another we can set the condition codes according to
4923 ;; its value.  Such a move is common after a return from subroutine and the
4924 ;; result is being tested against zero.
4925
4926 (define_insn "*movsi_compare0"
4927   [(set (reg:CC CC_REGNUM)
4928         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4929                     (const_int 0)))
4930    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4931         (match_dup 1))]
4932   "TARGET_32BIT"
4933   "@
4934    cmp%?\\t%0, #0
4935    sub%.\\t%0, %1, #0"
4936   [(set_attr "conds" "set")]
4937 )
4938
4939 ;; Subroutine to store a half word from a register into memory.
4940 ;; Operand 0 is the source register (HImode)
4941 ;; Operand 1 is the destination address in a register (SImode)
4942
4943 ;; In both this routine and the next, we must be careful not to spill
4944 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4945 ;; can generate unrecognizable rtl.
4946
4947 (define_expand "storehi"
4948   [;; store the low byte
4949    (set (match_operand 1 "" "") (match_dup 3))
4950    ;; extract the high byte
4951    (set (match_dup 2)
4952         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4953    ;; store the high byte
4954    (set (match_dup 4) (match_dup 5))]
4955   "TARGET_ARM"
4956   "
4957   {
4958     rtx op1 = operands[1];
4959     rtx addr = XEXP (op1, 0);
4960     enum rtx_code code = GET_CODE (addr);
4961
4962     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4963         || code == MINUS)
4964       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4965
4966     operands[4] = adjust_address (op1, QImode, 1);
4967     operands[1] = adjust_address (operands[1], QImode, 0);
4968     operands[3] = gen_lowpart (QImode, operands[0]);
4969     operands[0] = gen_lowpart (SImode, operands[0]);
4970     operands[2] = gen_reg_rtx (SImode);
4971     operands[5] = gen_lowpart (QImode, operands[2]);
4972   }"
4973 )
4974
4975 (define_expand "storehi_bigend"
4976   [(set (match_dup 4) (match_dup 3))
4977    (set (match_dup 2)
4978         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4979    (set (match_operand 1 "" "") (match_dup 5))]
4980   "TARGET_ARM"
4981   "
4982   {
4983     rtx op1 = operands[1];
4984     rtx addr = XEXP (op1, 0);
4985     enum rtx_code code = GET_CODE (addr);
4986
4987     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4988         || code == MINUS)
4989       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4990
4991     operands[4] = adjust_address (op1, QImode, 1);
4992     operands[1] = adjust_address (operands[1], QImode, 0);
4993     operands[3] = gen_lowpart (QImode, operands[0]);
4994     operands[0] = gen_lowpart (SImode, operands[0]);
4995     operands[2] = gen_reg_rtx (SImode);
4996     operands[5] = gen_lowpart (QImode, operands[2]);
4997   }"
4998 )
4999
5000 ;; Subroutine to store a half word integer constant into memory.
5001 (define_expand "storeinthi"
5002   [(set (match_operand 0 "" "")
5003         (match_operand 1 "" ""))
5004    (set (match_dup 3) (match_dup 2))]
5005   "TARGET_ARM"
5006   "
5007   {
5008     HOST_WIDE_INT value = INTVAL (operands[1]);
5009     rtx addr = XEXP (operands[0], 0);
5010     rtx op0 = operands[0];
5011     enum rtx_code code = GET_CODE (addr);
5012
5013     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5014         || code == MINUS)
5015       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
5016
5017     operands[1] = gen_reg_rtx (SImode);
5018     if (BYTES_BIG_ENDIAN)
5019       {
5020         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5021         if ((value & 255) == ((value >> 8) & 255))
5022           operands[2] = operands[1];
5023         else
5024           {
5025             operands[2] = gen_reg_rtx (SImode);
5026             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5027           }
5028       }
5029     else
5030       {
5031         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5032         if ((value & 255) == ((value >> 8) & 255))
5033           operands[2] = operands[1];
5034         else
5035           {
5036             operands[2] = gen_reg_rtx (SImode);
5037             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5038           }
5039       }
5040
5041     operands[3] = adjust_address (op0, QImode, 1);
5042     operands[0] = adjust_address (operands[0], QImode, 0);
5043     operands[2] = gen_lowpart (QImode, operands[2]);
5044     operands[1] = gen_lowpart (QImode, operands[1]);
5045   }"
5046 )
5047
5048 (define_expand "storehi_single_op"
5049   [(set (match_operand:HI 0 "memory_operand" "")
5050         (match_operand:HI 1 "general_operand" ""))]
5051   "TARGET_32BIT && arm_arch4"
5052   "
5053   if (!s_register_operand (operands[1], HImode))
5054     operands[1] = copy_to_mode_reg (HImode, operands[1]);
5055   "
5056 )
5057
5058 (define_expand "movhi"
5059   [(set (match_operand:HI 0 "general_operand" "")
5060         (match_operand:HI 1 "general_operand" ""))]
5061   "TARGET_EITHER"
5062   "
5063   if (TARGET_ARM)
5064     {
5065       if (!no_new_pseudos)
5066         {
5067           if (GET_CODE (operands[0]) == MEM)
5068             {
5069               if (arm_arch4)
5070                 {
5071                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5072                   DONE;
5073                 }
5074               if (GET_CODE (operands[1]) == CONST_INT)
5075                 emit_insn (gen_storeinthi (operands[0], operands[1]));
5076               else
5077                 {
5078                   if (GET_CODE (operands[1]) == MEM)
5079                     operands[1] = force_reg (HImode, operands[1]);
5080                   if (BYTES_BIG_ENDIAN)
5081                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
5082                   else
5083                    emit_insn (gen_storehi (operands[1], operands[0]));
5084                 }
5085               DONE;
5086             }
5087           /* Sign extend a constant, and keep it in an SImode reg.  */
5088           else if (GET_CODE (operands[1]) == CONST_INT)
5089             {
5090               rtx reg = gen_reg_rtx (SImode);
5091               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5092
5093               /* If the constant is already valid, leave it alone.  */
5094               if (!const_ok_for_arm (val))
5095                 {
5096                   /* If setting all the top bits will make the constant 
5097                      loadable in a single instruction, then set them.  
5098                      Otherwise, sign extend the number.  */
5099
5100                   if (const_ok_for_arm (~(val | ~0xffff)))
5101                     val |= ~0xffff;
5102                   else if (val & 0x8000)
5103                     val |= ~0xffff;
5104                 }
5105
5106               emit_insn (gen_movsi (reg, GEN_INT (val)));
5107               operands[1] = gen_lowpart (HImode, reg);
5108             }
5109           else if (arm_arch4 && optimize && !no_new_pseudos
5110                    && GET_CODE (operands[1]) == MEM)
5111             {
5112               rtx reg = gen_reg_rtx (SImode);
5113
5114               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5115               operands[1] = gen_lowpart (HImode, reg);
5116             }
5117           else if (!arm_arch4)
5118             {
5119               if (GET_CODE (operands[1]) == MEM)
5120                 {
5121                   rtx base;
5122                   rtx offset = const0_rtx;
5123                   rtx reg = gen_reg_rtx (SImode);
5124
5125                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
5126                        || (GET_CODE (base) == PLUS
5127                            && (GET_CODE (offset = XEXP (base, 1))
5128                                == CONST_INT)
5129                            && ((INTVAL(offset) & 1) != 1)
5130                            && GET_CODE (base = XEXP (base, 0)) == REG))
5131                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
5132                     {
5133                       rtx new;
5134
5135                       new = widen_memory_access (operands[1], SImode,
5136                                                  ((INTVAL (offset) & ~3)
5137                                                   - INTVAL (offset)));
5138                       emit_insn (gen_movsi (reg, new));
5139                       if (((INTVAL (offset) & 2) != 0)
5140                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
5141                         {
5142                           rtx reg2 = gen_reg_rtx (SImode);
5143
5144                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
5145                           reg = reg2;
5146                         }
5147                     }
5148                   else
5149                     emit_insn (gen_movhi_bytes (reg, operands[1]));
5150
5151                   operands[1] = gen_lowpart (HImode, reg);
5152                }
5153            }
5154         }
5155       /* Handle loading a large integer during reload.  */
5156       else if (GET_CODE (operands[1]) == CONST_INT
5157                && !const_ok_for_arm (INTVAL (operands[1]))
5158                && !const_ok_for_arm (~INTVAL (operands[1])))
5159         {
5160           /* Writing a constant to memory needs a scratch, which should
5161              be handled with SECONDARY_RELOADs.  */
5162           gcc_assert (GET_CODE (operands[0]) == REG);
5163
5164           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5165           emit_insn (gen_movsi (operands[0], operands[1]));
5166           DONE;
5167        }
5168     }
5169   else if (TARGET_THUMB2)
5170     {
5171       /* Thumb-2 can do everything except mem=mem and mem=const easily.  */
5172       if (!no_new_pseudos)
5173         {
5174           if (GET_CODE (operands[0]) != REG)
5175             operands[1] = force_reg (HImode, operands[1]);
5176           /* Zero extend a constant, and keep it in an SImode reg.  */
5177           else if (GET_CODE (operands[1]) == CONST_INT)
5178             {
5179               rtx reg = gen_reg_rtx (SImode);
5180               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5181
5182               emit_insn (gen_movsi (reg, GEN_INT (val)));
5183               operands[1] = gen_lowpart (HImode, reg);
5184             }
5185         }
5186     }
5187   else /* TARGET_THUMB1 */
5188     {
5189       if (!no_new_pseudos)
5190         {
5191           if (GET_CODE (operands[1]) == CONST_INT)
5192             {
5193               rtx reg = gen_reg_rtx (SImode);
5194
5195               emit_insn (gen_movsi (reg, operands[1]));
5196               operands[1] = gen_lowpart (HImode, reg);
5197             }
5198
5199           /* ??? We shouldn't really get invalid addresses here, but this can
5200              happen if we are passed a SP (never OK for HImode/QImode) or 
5201              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
5202              HImode/QImode) relative address.  */
5203           /* ??? This should perhaps be fixed elsewhere, for instance, in
5204              fixup_stack_1, by checking for other kinds of invalid addresses,
5205              e.g. a bare reference to a virtual register.  This may confuse the
5206              alpha though, which must handle this case differently.  */
5207           if (GET_CODE (operands[0]) == MEM
5208               && !memory_address_p (GET_MODE (operands[0]),
5209                                     XEXP (operands[0], 0)))
5210             operands[0]
5211               = replace_equiv_address (operands[0],
5212                                        copy_to_reg (XEXP (operands[0], 0)));
5213    
5214           if (GET_CODE (operands[1]) == MEM
5215               && !memory_address_p (GET_MODE (operands[1]),
5216                                     XEXP (operands[1], 0)))
5217             operands[1]
5218               = replace_equiv_address (operands[1],
5219                                        copy_to_reg (XEXP (operands[1], 0)));
5220
5221           if (GET_CODE (operands[1]) == MEM && optimize > 0)
5222             {
5223               rtx reg = gen_reg_rtx (SImode);
5224
5225               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5226               operands[1] = gen_lowpart (HImode, reg);
5227             }
5228
5229           if (GET_CODE (operands[0]) == MEM)
5230             operands[1] = force_reg (HImode, operands[1]);
5231         }
5232       else if (GET_CODE (operands[1]) == CONST_INT
5233                 && !satisfies_constraint_I (operands[1]))
5234         {
5235           /* Handle loading a large integer during reload.  */
5236
5237           /* Writing a constant to memory needs a scratch, which should
5238              be handled with SECONDARY_RELOADs.  */
5239           gcc_assert (GET_CODE (operands[0]) == REG);
5240
5241           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5242           emit_insn (gen_movsi (operands[0], operands[1]));
5243           DONE;
5244         }
5245     }
5246   "
5247 )
5248
5249 (define_insn "*thumb1_movhi_insn"
5250   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5251         (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
5252   "TARGET_THUMB1
5253    && (   register_operand (operands[0], HImode)
5254        || register_operand (operands[1], HImode))"
5255   "*
5256   switch (which_alternative)
5257     {
5258     case 0: return \"add        %0, %1, #0\";
5259     case 2: return \"strh       %1, %0\";
5260     case 3: return \"mov        %0, %1\";
5261     case 4: return \"mov        %0, %1\";
5262     case 5: return \"mov        %0, %1\";
5263     default: gcc_unreachable ();
5264     case 1:
5265       /* The stack pointer can end up being taken as an index register.
5266           Catch this case here and deal with it.  */
5267       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
5268           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
5269           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
5270         {
5271           rtx ops[2];
5272           ops[0] = operands[0];
5273           ops[1] = XEXP (XEXP (operands[1], 0), 0);
5274       
5275           output_asm_insn (\"mov        %0, %1\", ops);
5276
5277           XEXP (XEXP (operands[1], 0), 0) = operands[0];
5278     
5279         }
5280       return \"ldrh     %0, %1\";
5281     }"
5282   [(set_attr "length" "2,4,2,2,2,2")
5283    (set_attr "type" "*,load1,store1,*,*,*")]
5284 )
5285
5286
5287 (define_expand "movhi_bytes"
5288   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
5289    (set (match_dup 3)
5290         (zero_extend:SI (match_dup 6)))
5291    (set (match_operand:SI 0 "" "")
5292          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
5293   "TARGET_ARM"
5294   "
5295   {
5296     rtx mem1, mem2;
5297     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5298
5299     mem1 = change_address (operands[1], QImode, addr);
5300     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
5301     operands[0] = gen_lowpart (SImode, operands[0]);
5302     operands[1] = mem1;
5303     operands[2] = gen_reg_rtx (SImode);
5304     operands[3] = gen_reg_rtx (SImode);
5305     operands[6] = mem2;
5306
5307     if (BYTES_BIG_ENDIAN)
5308       {
5309         operands[4] = operands[2];
5310         operands[5] = operands[3];
5311       }
5312     else
5313       {
5314         operands[4] = operands[3];
5315         operands[5] = operands[2];
5316       }
5317   }"
5318 )
5319
5320 (define_expand "movhi_bigend"
5321   [(set (match_dup 2)
5322         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
5323                    (const_int 16)))
5324    (set (match_dup 3)
5325         (ashiftrt:SI (match_dup 2) (const_int 16)))
5326    (set (match_operand:HI 0 "s_register_operand" "")
5327         (match_dup 4))]
5328   "TARGET_ARM"
5329   "
5330   operands[2] = gen_reg_rtx (SImode);
5331   operands[3] = gen_reg_rtx (SImode);
5332   operands[4] = gen_lowpart (HImode, operands[3]);
5333   "
5334 )
5335
5336 ;; Pattern to recognize insn generated default case above
5337 (define_insn "*movhi_insn_arch4"
5338   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
5339         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
5340   "TARGET_ARM
5341    && arm_arch4
5342    && (GET_CODE (operands[1]) != CONST_INT
5343        || const_ok_for_arm (INTVAL (operands[1]))
5344        || const_ok_for_arm (~INTVAL (operands[1])))"
5345   "@
5346    mov%?\\t%0, %1\\t%@ movhi
5347    mvn%?\\t%0, #%B1\\t%@ movhi
5348    str%(h%)\\t%1, %0\\t%@ movhi
5349    ldr%(h%)\\t%0, %1\\t%@ movhi"
5350   [(set_attr "type" "*,*,store1,load1")
5351    (set_attr "predicable" "yes")
5352    (set_attr "pool_range" "*,*,*,256")
5353    (set_attr "neg_pool_range" "*,*,*,244")]
5354 )
5355
5356 (define_insn "*movhi_bytes"
5357   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
5358         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
5359   "TARGET_ARM"
5360   "@
5361    mov%?\\t%0, %1\\t%@ movhi
5362    mvn%?\\t%0, #%B1\\t%@ movhi"
5363   [(set_attr "predicable" "yes")]
5364 )
5365
5366 (define_expand "thumb_movhi_clobber"
5367   [(set (match_operand:HI     0 "memory_operand"   "")
5368         (match_operand:HI     1 "register_operand" ""))
5369    (clobber (match_operand:DI 2 "register_operand" ""))]
5370   "TARGET_THUMB1"
5371   "
5372   if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
5373       && REGNO (operands[1]) <= LAST_LO_REGNUM)
5374     {
5375       emit_insn (gen_movhi (operands[0], operands[1]));
5376       DONE;
5377     }
5378   /* XXX Fixme, need to handle other cases here as well.  */
5379   gcc_unreachable ();
5380   "
5381 )
5382         
5383 ;; We use a DImode scratch because we may occasionally need an additional
5384 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
5385 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
5386 (define_expand "reload_outhi"
5387   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
5388               (match_operand:HI 1 "s_register_operand"        "r")
5389               (match_operand:DI 2 "s_register_operand"        "=&l")])]
5390   "TARGET_EITHER"
5391   "if (TARGET_ARM)
5392      arm_reload_out_hi (operands);
5393    else
5394      thumb_reload_out_hi (operands);
5395   DONE;
5396   "
5397 )
5398
5399 (define_expand "reload_inhi"
5400   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
5401               (match_operand:HI 1 "arm_reload_memory_operand" "o")
5402               (match_operand:DI 2 "s_register_operand" "=&r")])]
5403   "TARGET_EITHER"
5404   "
5405   if (TARGET_ARM)
5406     arm_reload_in_hi (operands);
5407   else
5408     thumb_reload_out_hi (operands);
5409   DONE;
5410 ")
5411
5412 (define_expand "movqi"
5413   [(set (match_operand:QI 0 "general_operand" "")
5414         (match_operand:QI 1 "general_operand" ""))]
5415   "TARGET_EITHER"
5416   "
5417   /* Everything except mem = const or mem = mem can be done easily */
5418
5419   if (!no_new_pseudos)
5420     {
5421       if (GET_CODE (operands[1]) == CONST_INT)
5422         {
5423           rtx reg = gen_reg_rtx (SImode);
5424
5425           emit_insn (gen_movsi (reg, operands[1]));
5426           operands[1] = gen_lowpart (QImode, reg);
5427         }
5428
5429       if (TARGET_THUMB)
5430         {
5431           /* ??? We shouldn't really get invalid addresses here, but this can
5432              happen if we are passed a SP (never OK for HImode/QImode) or
5433              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
5434              HImode/QImode) relative address.  */
5435           /* ??? This should perhaps be fixed elsewhere, for instance, in
5436              fixup_stack_1, by checking for other kinds of invalid addresses,
5437              e.g. a bare reference to a virtual register.  This may confuse the
5438              alpha though, which must handle this case differently.  */
5439           if (GET_CODE (operands[0]) == MEM
5440               && !memory_address_p (GET_MODE (operands[0]),
5441                                      XEXP (operands[0], 0)))
5442             operands[0]
5443               = replace_equiv_address (operands[0],
5444                                        copy_to_reg (XEXP (operands[0], 0)));
5445           if (GET_CODE (operands[1]) == MEM
5446               && !memory_address_p (GET_MODE (operands[1]),
5447                                     XEXP (operands[1], 0)))
5448              operands[1]
5449                = replace_equiv_address (operands[1],
5450                                         copy_to_reg (XEXP (operands[1], 0)));
5451         }
5452
5453       if (GET_CODE (operands[1]) == MEM && optimize > 0)
5454         {
5455           rtx reg = gen_reg_rtx (SImode);
5456
5457           emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5458           operands[1] = gen_lowpart (QImode, reg);
5459         }
5460
5461       if (GET_CODE (operands[0]) == MEM)
5462         operands[1] = force_reg (QImode, operands[1]);
5463     }
5464   else if (TARGET_THUMB
5465            && GET_CODE (operands[1]) == CONST_INT
5466            && !satisfies_constraint_I (operands[1]))
5467     {
5468       /* Handle loading a large integer during reload.  */
5469
5470       /* Writing a constant to memory needs a scratch, which should
5471          be handled with SECONDARY_RELOADs.  */
5472       gcc_assert (GET_CODE (operands[0]) == REG);
5473
5474       operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5475       emit_insn (gen_movsi (operands[0], operands[1]));
5476       DONE;
5477     }
5478   "
5479 )
5480
5481
5482 (define_insn "*arm_movqi_insn"
5483   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5484         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5485   "TARGET_32BIT
5486    && (   register_operand (operands[0], QImode)
5487        || register_operand (operands[1], QImode))"
5488   "@
5489    mov%?\\t%0, %1
5490    mvn%?\\t%0, #%B1
5491    ldr%(b%)\\t%0, %1
5492    str%(b%)\\t%1, %0"
5493   [(set_attr "type" "*,*,load1,store1")
5494    (set_attr "predicable" "yes")]
5495 )
5496
5497 (define_insn "*thumb1_movqi_insn"
5498   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5499         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
5500   "TARGET_THUMB1
5501    && (   register_operand (operands[0], QImode)
5502        || register_operand (operands[1], QImode))"
5503   "@
5504    add\\t%0, %1, #0
5505    ldrb\\t%0, %1
5506    strb\\t%1, %0
5507    mov\\t%0, %1
5508    mov\\t%0, %1
5509    mov\\t%0, %1"
5510   [(set_attr "length" "2")
5511    (set_attr "type" "*,load1,store1,*,*,*")
5512    (set_attr "pool_range" "*,32,*,*,*,*")]
5513 )
5514
5515 (define_expand "movsf"
5516   [(set (match_operand:SF 0 "general_operand" "")
5517         (match_operand:SF 1 "general_operand" ""))]
5518   "TARGET_EITHER"
5519   "
5520   if (TARGET_32BIT)
5521     {
5522       if (GET_CODE (operands[0]) == MEM)
5523         operands[1] = force_reg (SFmode, operands[1]);
5524     }
5525   else /* TARGET_THUMB1 */
5526     {
5527       if (!no_new_pseudos)
5528         {
5529            if (GET_CODE (operands[0]) != REG)
5530              operands[1] = force_reg (SFmode, operands[1]);
5531         }
5532     }
5533   "
5534 )
5535
5536 ;; Transform a floating-point move of a constant into a core register into
5537 ;; an SImode operation.
5538 (define_split
5539   [(set (match_operand:SF 0 "arm_general_register_operand" "")
5540         (match_operand:SF 1 "immediate_operand" ""))]
5541   "TARGET_32BIT
5542    && reload_completed
5543    && GET_CODE (operands[1]) == CONST_DOUBLE"
5544   [(set (match_dup 2) (match_dup 3))]
5545   "
5546   operands[2] = gen_lowpart (SImode, operands[0]);
5547   operands[3] = gen_lowpart (SImode, operands[1]);
5548   if (operands[2] == 0 || operands[3] == 0)
5549     FAIL;
5550   "
5551 )
5552
5553 (define_insn "*arm_movsf_soft_insn"
5554   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5555         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
5556   "TARGET_ARM
5557    && TARGET_SOFT_FLOAT
5558    && (GET_CODE (operands[0]) != MEM
5559        || register_operand (operands[1], SFmode))"
5560   "@
5561    mov%?\\t%0, %1
5562    ldr%?\\t%0, %1\\t%@ float
5563    str%?\\t%1, %0\\t%@ float"
5564   [(set_attr "length" "4,4,4")
5565    (set_attr "predicable" "yes")
5566    (set_attr "type" "*,load1,store1")
5567    (set_attr "pool_range" "*,4096,*")
5568    (set_attr "neg_pool_range" "*,4084,*")]
5569 )
5570
5571 ;;; ??? This should have alternatives for constants.
5572 (define_insn "*thumb1_movsf_insn"
5573   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5574         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5575   "TARGET_THUMB1
5576    && (   register_operand (operands[0], SFmode) 
5577        || register_operand (operands[1], SFmode))"
5578   "@
5579    add\\t%0, %1, #0
5580    ldmia\\t%1, {%0}
5581    stmia\\t%0, {%1}
5582    ldr\\t%0, %1
5583    str\\t%1, %0
5584    mov\\t%0, %1
5585    mov\\t%0, %1"
5586   [(set_attr "length" "2")
5587    (set_attr "type" "*,load1,store1,load1,store1,*,*")
5588    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5589 )
5590
5591 (define_expand "movdf"
5592   [(set (match_operand:DF 0 "general_operand" "")
5593         (match_operand:DF 1 "general_operand" ""))]
5594   "TARGET_EITHER"
5595   "
5596   if (TARGET_32BIT)
5597     {
5598       if (GET_CODE (operands[0]) == MEM)
5599         operands[1] = force_reg (DFmode, operands[1]);
5600     }
5601   else /* TARGET_THUMB */
5602     {
5603       if (!no_new_pseudos)
5604         {
5605           if (GET_CODE (operands[0]) != REG)
5606             operands[1] = force_reg (DFmode, operands[1]);
5607         }
5608     }
5609   "
5610 )
5611
5612 ;; Reloading a df mode value stored in integer regs to memory can require a
5613 ;; scratch reg.
5614 (define_expand "reload_outdf"
5615   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5616    (match_operand:DF 1 "s_register_operand" "r")
5617    (match_operand:SI 2 "s_register_operand" "=&r")]
5618   "TARGET_32BIT"
5619   "
5620   {
5621     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5622
5623     if (code == REG)
5624       operands[2] = XEXP (operands[0], 0);
5625     else if (code == POST_INC || code == PRE_DEC)
5626       {
5627         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5628         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5629         emit_insn (gen_movdi (operands[0], operands[1]));
5630         DONE;
5631       }
5632     else if (code == PRE_INC)
5633       {
5634         rtx reg = XEXP (XEXP (operands[0], 0), 0);
5635
5636         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5637         operands[2] = reg;
5638       }
5639     else if (code == POST_DEC)
5640       operands[2] = XEXP (XEXP (operands[0], 0), 0);
5641     else
5642       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5643                              XEXP (XEXP (operands[0], 0), 1)));
5644
5645     emit_insn (gen_rtx_SET (VOIDmode,
5646                             replace_equiv_address (operands[0], operands[2]),
5647                             operands[1]));
5648
5649     if (code == POST_DEC)
5650       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5651
5652     DONE;
5653   }"
5654 )
5655
5656 (define_insn "*movdf_soft_insn"
5657   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5658         (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
5659   "TARGET_ARM && TARGET_SOFT_FLOAT
5660    && (   register_operand (operands[0], DFmode)
5661        || register_operand (operands[1], DFmode))"
5662   "*
5663   switch (which_alternative)
5664     {
5665     case 0:
5666     case 1:
5667     case 2:
5668       return \"#\";
5669     default:
5670       return output_move_double (operands);
5671     }
5672   "
5673   [(set_attr "length" "8,12,16,8,8")
5674    (set_attr "type" "*,*,*,load2,store2")
5675    (set_attr "pool_range" "1020")
5676    (set_attr "neg_pool_range" "1008")]
5677 )
5678
5679 ;;; ??? This should have alternatives for constants.
5680 ;;; ??? This was originally identical to the movdi_insn pattern.
5681 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5682 ;;; thumb_reorg with a memory reference.
5683 (define_insn "*thumb_movdf_insn"
5684   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5685         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5686   "TARGET_THUMB1
5687    && (   register_operand (operands[0], DFmode)
5688        || register_operand (operands[1], DFmode))"
5689   "*
5690   switch (which_alternative)
5691     {
5692     default:
5693     case 0:
5694       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5695         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5696       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5697     case 1:
5698       return \"ldmia\\t%1, {%0, %H0}\";
5699     case 2:
5700       return \"stmia\\t%0, {%1, %H1}\";
5701     case 3:
5702       return thumb_load_double_from_address (operands);
5703     case 4:
5704       operands[2] = gen_rtx_MEM (SImode,
5705                                  plus_constant (XEXP (operands[0], 0), 4));
5706       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5707       return \"\";
5708     case 5:
5709       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5710         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5711       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5712     }
5713   "
5714   [(set_attr "length" "4,2,2,6,4,4")
5715    (set_attr "type" "*,load2,store2,load2,store2,*")
5716    (set_attr "pool_range" "*,*,*,1020,*,*")]
5717 )
5718
5719 (define_expand "movxf"
5720   [(set (match_operand:XF 0 "general_operand" "")
5721         (match_operand:XF 1 "general_operand" ""))]
5722   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
5723   "
5724   if (GET_CODE (operands[0]) == MEM)
5725     operands[1] = force_reg (XFmode, operands[1]);
5726   "
5727 )
5728
5729 ;; Vector Moves
5730 (define_expand "movv2si"
5731   [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5732         (match_operand:V2SI 1 "general_operand" ""))]
5733   "TARGET_REALLY_IWMMXT"
5734 {
5735 })
5736
5737 (define_expand "movv4hi"
5738   [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5739         (match_operand:V4HI 1 "general_operand" ""))]
5740   "TARGET_REALLY_IWMMXT"
5741 {
5742 })
5743
5744 (define_expand "movv8qi"
5745   [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5746         (match_operand:V8QI 1 "general_operand" ""))]
5747   "TARGET_REALLY_IWMMXT"
5748 {
5749 })
5750 \f
5751
5752 ;; load- and store-multiple insns
5753 ;; The arm can load/store any set of registers, provided that they are in
5754 ;; ascending order; but that is beyond GCC so stick with what it knows.
5755
5756 (define_expand "load_multiple"
5757   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5758                           (match_operand:SI 1 "" ""))
5759                      (use (match_operand:SI 2 "" ""))])]
5760   "TARGET_32BIT"
5761 {
5762   HOST_WIDE_INT offset = 0;
5763
5764   /* Support only fixed point registers.  */
5765   if (GET_CODE (operands[2]) != CONST_INT
5766       || INTVAL (operands[2]) > 14
5767       || INTVAL (operands[2]) < 2
5768       || GET_CODE (operands[1]) != MEM
5769       || GET_CODE (operands[0]) != REG
5770       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5771       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5772     FAIL;
5773
5774   operands[3]
5775     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5776                              force_reg (SImode, XEXP (operands[1], 0)),
5777                              TRUE, FALSE, operands[1], &offset);
5778 })
5779
5780 ;; Load multiple with write-back
5781
5782 (define_insn "*ldmsi_postinc4"
5783   [(match_parallel 0 "load_multiple_operation"
5784     [(set (match_operand:SI 1 "s_register_operand" "=r")
5785           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5786                    (const_int 16)))
5787      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5788           (mem:SI (match_dup 2)))
5789      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5790           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5791      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5792           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5793      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5794           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5795   "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
5796   "ldm%(ia%)\\t%1!, {%3, %4, %5, %6}"
5797   [(set_attr "type" "load4")
5798    (set_attr "predicable" "yes")]
5799 )
5800
5801 (define_insn "*ldmsi_postinc4_thumb1"
5802   [(match_parallel 0 "load_multiple_operation"
5803     [(set (match_operand:SI 1 "s_register_operand" "=l")
5804           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5805                    (const_int 16)))
5806      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5807           (mem:SI (match_dup 2)))
5808      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5809           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5810      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5811           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5812      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5813           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5814   "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
5815   "ldmia\\t%1!, {%3, %4, %5, %6}"
5816   [(set_attr "type" "load4")]
5817 )
5818
5819 (define_insn "*ldmsi_postinc3"
5820   [(match_parallel 0 "load_multiple_operation"
5821     [(set (match_operand:SI 1 "s_register_operand" "=r")
5822           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5823                    (const_int 12)))
5824      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5825           (mem:SI (match_dup 2)))
5826      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5827           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5828      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5829           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5830   "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
5831   "ldm%(ia%)\\t%1!, {%3, %4, %5}"
5832   [(set_attr "type" "load3")
5833    (set_attr "predicable" "yes")]
5834 )
5835
5836 (define_insn "*ldmsi_postinc2"
5837   [(match_parallel 0 "load_multiple_operation"
5838     [(set (match_operand:SI 1 "s_register_operand" "=r")
5839           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5840                    (const_int 8)))
5841      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5842           (mem:SI (match_dup 2)))
5843      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5844           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5845   "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
5846   "ldm%(ia%)\\t%1!, {%3, %4}"
5847   [(set_attr "type" "load2")
5848    (set_attr "predicable" "yes")]
5849 )
5850
5851 ;; Ordinary load multiple
5852
5853 (define_insn "*ldmsi4"
5854   [(match_parallel 0 "load_multiple_operation"
5855     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5856           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5857      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5858           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5859      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5860           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5861      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5862           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5863   "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
5864   "ldm%(ia%)\\t%1, {%2, %3, %4, %5}"
5865   [(set_attr "type" "load4")
5866    (set_attr "predicable" "yes")]
5867 )
5868
5869 (define_insn "*ldmsi3"
5870   [(match_parallel 0 "load_multiple_operation"
5871     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5872           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5873      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5874           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5875      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5876           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5877   "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
5878   "ldm%(ia%)\\t%1, {%2, %3, %4}"
5879   [(set_attr "type" "load3")
5880    (set_attr "predicable" "yes")]
5881 )
5882
5883 (define_insn "*ldmsi2"
5884   [(match_parallel 0 "load_multiple_operation"
5885     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5886           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5887      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5888           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5889   "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
5890   "ldm%(ia%)\\t%1, {%2, %3}"
5891   [(set_attr "type" "load2")
5892    (set_attr "predicable" "yes")]
5893 )
5894
5895 (define_expand "store_multiple"
5896   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5897                           (match_operand:SI 1 "" ""))
5898                      (use (match_operand:SI 2 "" ""))])]
5899   "TARGET_32BIT"
5900 {
5901   HOST_WIDE_INT offset = 0;
5902
5903   /* Support only fixed point registers.  */
5904   if (GET_CODE (operands[2]) != CONST_INT
5905       || INTVAL (operands[2]) > 14
5906       || INTVAL (operands[2]) < 2
5907       || GET_CODE (operands[1]) != REG
5908       || GET_CODE (operands[0]) != MEM
5909       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5910       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5911     FAIL;
5912
5913   operands[3]
5914     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5915                               force_reg (SImode, XEXP (operands[0], 0)),
5916                               TRUE, FALSE, operands[0], &offset);
5917 })
5918
5919 ;; Store multiple with write-back
5920
5921 (define_insn "*stmsi_postinc4"
5922   [(match_parallel 0 "store_multiple_operation"
5923     [(set (match_operand:SI 1 "s_register_operand" "=r")
5924           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5925                    (const_int 16)))
5926      (set (mem:SI (match_dup 2))
5927           (match_operand:SI 3 "arm_hard_register_operand" ""))
5928      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5929           (match_operand:SI 4 "arm_hard_register_operand" ""))
5930      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5931           (match_operand:SI 5 "arm_hard_register_operand" ""))
5932      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5933           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5934   "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
5935   "stm%(ia%)\\t%1!, {%3, %4, %5, %6}"
5936   [(set_attr "predicable" "yes")
5937    (set_attr "type" "store4")]
5938 )
5939
5940 (define_insn "*stmsi_postinc4_thumb1"
5941   [(match_parallel 0 "store_multiple_operation"
5942     [(set (match_operand:SI 1 "s_register_operand" "=l")
5943           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5944                    (const_int 16)))
5945      (set (mem:SI (match_dup 2))
5946           (match_operand:SI 3 "arm_hard_register_operand" ""))
5947      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5948           (match_operand:SI 4 "arm_hard_register_operand" ""))
5949      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5950           (match_operand:SI 5 "arm_hard_register_operand" ""))
5951      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5952           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5953   "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
5954   "stmia\\t%1!, {%3, %4, %5, %6}"
5955   [(set_attr "type" "store4")]
5956 )
5957
5958 (define_insn "*stmsi_postinc3"
5959   [(match_parallel 0 "store_multiple_operation"
5960     [(set (match_operand:SI 1 "s_register_operand" "=r")
5961           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5962                    (const_int 12)))
5963      (set (mem:SI (match_dup 2))
5964           (match_operand:SI 3 "arm_hard_register_operand" ""))
5965      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5966           (match_operand:SI 4 "arm_hard_register_operand" ""))
5967      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5968           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5969   "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
5970   "stm%(ia%)\\t%1!, {%3, %4, %5}"
5971   [(set_attr "predicable" "yes")
5972    (set_attr "type" "store3")]
5973 )
5974
5975 (define_insn "*stmsi_postinc2"
5976   [(match_parallel 0 "store_multiple_operation"
5977     [(set (match_operand:SI 1 "s_register_operand" "=r")
5978           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5979                    (const_int 8)))
5980      (set (mem:SI (match_dup 2))
5981           (match_operand:SI 3 "arm_hard_register_operand" ""))
5982      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5983           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5984   "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
5985   "stm%(ia%)\\t%1!, {%3, %4}"
5986   [(set_attr "predicable" "yes")
5987    (set_attr "type" "store2")]
5988 )
5989
5990 ;; Ordinary store multiple
5991
5992 (define_insn "*stmsi4"
5993   [(match_parallel 0 "store_multiple_operation"
5994     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5995           (match_operand:SI 2 "arm_hard_register_operand" ""))
5996      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5997           (match_operand:SI 3 "arm_hard_register_operand" ""))
5998      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5999           (match_operand:SI 4 "arm_hard_register_operand" ""))
6000      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
6001           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
6002   "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6003   "stm%(ia%)\\t%1, {%2, %3, %4, %5}"
6004   [(set_attr "predicable" "yes")
6005    (set_attr "type" "store4")]
6006 )
6007
6008 (define_insn "*stmsi3"
6009   [(match_parallel 0 "store_multiple_operation"
6010     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6011           (match_operand:SI 2 "arm_hard_register_operand" ""))
6012      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6013           (match_operand:SI 3 "arm_hard_register_operand" ""))
6014      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
6015           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
6016   "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6017   "stm%(ia%)\\t%1, {%2, %3, %4}"
6018   [(set_attr "predicable" "yes")
6019    (set_attr "type" "store3")]
6020 )
6021
6022 (define_insn "*stmsi2"
6023   [(match_parallel 0 "store_multiple_operation"
6024     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6025           (match_operand:SI 2 "arm_hard_register_operand" ""))
6026      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6027           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
6028   "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
6029   "stm%(ia%)\\t%1, {%2, %3}"
6030   [(set_attr "predicable" "yes")
6031    (set_attr "type" "store2")]
6032 )
6033
6034 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
6035 ;; We could let this apply for blocks of less than this, but it clobbers so
6036 ;; many registers that there is then probably a better way.
6037
6038 (define_expand "movmemqi"
6039   [(match_operand:BLK 0 "general_operand" "")
6040    (match_operand:BLK 1 "general_operand" "")
6041    (match_operand:SI 2 "const_int_operand" "")
6042    (match_operand:SI 3 "const_int_operand" "")]
6043   "TARGET_EITHER"
6044   "
6045   if (TARGET_32BIT)
6046     {
6047       if (arm_gen_movmemqi (operands))
6048         DONE;
6049       FAIL;
6050     }
6051   else /* TARGET_THUMB1 */
6052     {
6053       if (   INTVAL (operands[3]) != 4
6054           || INTVAL (operands[2]) > 48)
6055         FAIL;
6056
6057       thumb_expand_movmemqi (operands);
6058       DONE;
6059     }
6060   "
6061 )
6062
6063 ;; Thumb block-move insns
6064
6065 (define_insn "movmem12b"
6066   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6067         (mem:SI (match_operand:SI 3 "register_operand" "1")))
6068    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6069         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6070    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6071         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
6072    (set (match_operand:SI 0 "register_operand" "=l")
6073         (plus:SI (match_dup 2) (const_int 12)))
6074    (set (match_operand:SI 1 "register_operand" "=l")
6075         (plus:SI (match_dup 3) (const_int 12)))
6076    (clobber (match_scratch:SI 4 "=&l"))
6077    (clobber (match_scratch:SI 5 "=&l"))
6078    (clobber (match_scratch:SI 6 "=&l"))]
6079   "TARGET_THUMB1"
6080   "* return thumb_output_move_mem_multiple (3, operands);"
6081   [(set_attr "length" "4")
6082    ; This isn't entirely accurate...  It loads as well, but in terms of
6083    ; scheduling the following insn it is better to consider it as a store
6084    (set_attr "type" "store3")]
6085 )
6086
6087 (define_insn "movmem8b"
6088   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6089         (mem:SI (match_operand:SI 3 "register_operand" "1")))
6090    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6091         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6092    (set (match_operand:SI 0 "register_operand" "=l")
6093         (plus:SI (match_dup 2) (const_int 8)))
6094    (set (match_operand:SI 1 "register_operand" "=l")
6095         (plus:SI (match_dup 3) (const_int 8)))
6096    (clobber (match_scratch:SI 4 "=&l"))
6097    (clobber (match_scratch:SI 5 "=&l"))]
6098   "TARGET_THUMB1"
6099   "* return thumb_output_move_mem_multiple (2, operands);"
6100   [(set_attr "length" "4")
6101    ; This isn't entirely accurate...  It loads as well, but in terms of
6102    ; scheduling the following insn it is better to consider it as a store
6103    (set_attr "type" "store2")]
6104 )
6105
6106 \f
6107
6108 ;; Compare & branch insns
6109 ;; The range calculations are based as follows:
6110 ;; For forward branches, the address calculation returns the address of
6111 ;; the next instruction.  This is 2 beyond the branch instruction.
6112 ;; For backward branches, the address calculation returns the address of
6113 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
6114 ;; instruction for the shortest sequence, and 4 before the branch instruction
6115 ;; if we have to jump around an unconditional branch.
6116 ;; To the basic branch range the PC offset must be added (this is +4).
6117 ;; So for forward branches we have 
6118 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6119 ;; And for backward branches we have 
6120 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6121 ;;
6122 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6123 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
6124
6125 (define_expand "cbranchsi4"
6126   [(set (pc) (if_then_else
6127               (match_operator 0 "arm_comparison_operator"
6128                [(match_operand:SI 1 "s_register_operand" "")
6129                 (match_operand:SI 2 "nonmemory_operand" "")])
6130               (label_ref (match_operand 3 "" ""))
6131               (pc)))]
6132   "TARGET_THUMB1"
6133   "
6134   if (thumb1_cmpneg_operand (operands[2], SImode))
6135     {
6136       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6137                                               operands[3], operands[0]));
6138       DONE;
6139     }
6140   if (!thumb1_cmp_operand (operands[2], SImode))
6141     operands[2] = force_reg (SImode, operands[2]);
6142   ")
6143
6144 (define_insn "*cbranchsi4_insn"
6145   [(set (pc) (if_then_else
6146               (match_operator 0 "arm_comparison_operator"
6147                [(match_operand:SI 1 "s_register_operand" "l,*h")
6148                 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
6149               (label_ref (match_operand 3 "" ""))
6150               (pc)))]
6151   "TARGET_THUMB1"
6152   "*
6153   output_asm_insn (\"cmp\\t%1, %2\", operands);
6154
6155   switch (get_attr_length (insn))
6156     {
6157     case 4:  return \"b%d0\\t%l3\";
6158     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6159     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6160     }
6161   "
6162   [(set (attr "far_jump")
6163         (if_then_else
6164             (eq_attr "length" "8")
6165             (const_string "yes")
6166             (const_string "no")))
6167    (set (attr "length") 
6168         (if_then_else
6169             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6170                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6171             (const_int 4)
6172             (if_then_else
6173                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6174                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6175                 (const_int 6)
6176                 (const_int 8))))]
6177 )
6178
6179 (define_insn "cbranchsi4_scratch"
6180   [(set (pc) (if_then_else
6181               (match_operator 4 "arm_comparison_operator"
6182                [(match_operand:SI 1 "s_register_operand" "l,0")
6183                 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
6184               (label_ref (match_operand 3 "" ""))
6185               (pc)))
6186    (clobber (match_scratch:SI 0 "=l,l"))]
6187   "TARGET_THUMB1"
6188   "*
6189   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
6190
6191   switch (get_attr_length (insn))
6192     {
6193     case 4:  return \"b%d4\\t%l3\";
6194     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6195     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6196     }
6197   "
6198   [(set (attr "far_jump")
6199         (if_then_else
6200             (eq_attr "length" "8")
6201             (const_string "yes")
6202             (const_string "no")))
6203    (set (attr "length") 
6204         (if_then_else
6205             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6206                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6207             (const_int 4)
6208             (if_then_else
6209                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6210                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6211                 (const_int 6)
6212                 (const_int 8))))]
6213 )
6214 (define_insn "*movsi_cbranchsi4"
6215   [(set (pc)
6216         (if_then_else
6217          (match_operator 3 "arm_comparison_operator"
6218           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
6219            (const_int 0)])
6220          (label_ref (match_operand 2 "" ""))
6221          (pc)))
6222    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
6223         (match_dup 1))]
6224   "TARGET_THUMB1"
6225   "*{
6226   if (which_alternative == 0)
6227     output_asm_insn (\"cmp\t%0, #0\", operands);
6228   else if (which_alternative == 1)
6229     output_asm_insn (\"sub\t%0, %1, #0\", operands);
6230   else
6231     {
6232       output_asm_insn (\"cmp\t%1, #0\", operands);
6233       if (which_alternative == 2)
6234         output_asm_insn (\"mov\t%0, %1\", operands);
6235       else
6236         output_asm_insn (\"str\t%1, %0\", operands);
6237     }
6238   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
6239     {
6240     case 4:  return \"b%d3\\t%l2\";
6241     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6242     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
6243     }
6244   }"
6245   [(set (attr "far_jump")
6246         (if_then_else
6247             (ior (and (gt (symbol_ref ("which_alternative"))
6248                           (const_int 1))
6249                       (eq_attr "length" "8"))
6250                  (eq_attr "length" "10"))
6251             (const_string "yes")
6252             (const_string "no")))
6253    (set (attr "length")
6254      (if_then_else
6255        (le (symbol_ref ("which_alternative"))
6256                        (const_int 1))
6257        (if_then_else
6258          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6259               (le (minus (match_dup 2) (pc)) (const_int 256)))
6260          (const_int 4)
6261          (if_then_else
6262            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6263                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6264            (const_int 6)
6265            (const_int 8)))
6266        (if_then_else
6267          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
6268               (le (minus (match_dup 2) (pc)) (const_int 256)))
6269          (const_int 6)
6270          (if_then_else
6271            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
6272                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6273            (const_int 8)
6274            (const_int 10)))))]
6275 )
6276
6277 (define_insn "*negated_cbranchsi4"
6278   [(set (pc)
6279         (if_then_else
6280          (match_operator 0 "equality_operator"
6281           [(match_operand:SI 1 "s_register_operand" "l")
6282            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
6283          (label_ref (match_operand 3 "" ""))
6284          (pc)))]
6285   "TARGET_THUMB1"
6286   "*
6287   output_asm_insn (\"cmn\\t%1, %2\", operands);
6288   switch (get_attr_length (insn))
6289     {
6290     case 4:  return \"b%d0\\t%l3\";
6291     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6292     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6293     }
6294   "
6295   [(set (attr "far_jump")
6296         (if_then_else
6297             (eq_attr "length" "8")
6298             (const_string "yes")
6299             (const_string "no")))
6300    (set (attr "length") 
6301         (if_then_else
6302             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6303                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6304             (const_int 4)
6305             (if_then_else
6306                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6307                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6308                 (const_int 6)
6309                 (const_int 8))))]
6310 )
6311
6312 (define_insn "*tbit_cbranch"
6313   [(set (pc)
6314         (if_then_else
6315          (match_operator 0 "equality_operator"
6316           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6317                             (const_int 1)
6318                             (match_operand:SI 2 "const_int_operand" "i"))
6319            (const_int 0)])
6320          (label_ref (match_operand 3 "" ""))
6321          (pc)))
6322    (clobber (match_scratch:SI 4 "=l"))]
6323   "TARGET_THUMB1"
6324   "*
6325   {
6326   rtx op[3];
6327   op[0] = operands[4];
6328   op[1] = operands[1];
6329   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
6330
6331   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6332   switch (get_attr_length (insn))
6333     {
6334     case 4:  return \"b%d0\\t%l3\";
6335     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6336     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6337     }
6338   }"
6339   [(set (attr "far_jump")
6340         (if_then_else
6341             (eq_attr "length" "8")
6342             (const_string "yes")
6343             (const_string "no")))
6344    (set (attr "length") 
6345         (if_then_else
6346             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6347                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6348             (const_int 4)
6349             (if_then_else
6350                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6351                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6352                 (const_int 6)
6353                 (const_int 8))))]
6354 )
6355   
6356 (define_insn "*tlobits_cbranch"
6357   [(set (pc)
6358         (if_then_else
6359          (match_operator 0 "equality_operator"
6360           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6361                             (match_operand:SI 2 "const_int_operand" "i")
6362                             (const_int 0))
6363            (const_int 0)])
6364          (label_ref (match_operand 3 "" ""))
6365          (pc)))
6366    (clobber (match_scratch:SI 4 "=l"))]
6367   "TARGET_THUMB1"
6368   "*
6369   {
6370   rtx op[3];
6371   op[0] = operands[4];
6372   op[1] = operands[1];
6373   op[2] = GEN_INT (32 - INTVAL (operands[2]));
6374
6375   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6376   switch (get_attr_length (insn))
6377     {
6378     case 4:  return \"b%d0\\t%l3\";
6379     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6380     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6381     }
6382   }"
6383   [(set (attr "far_jump")
6384         (if_then_else
6385             (eq_attr "length" "8")
6386             (const_string "yes")
6387             (const_string "no")))
6388    (set (attr "length") 
6389         (if_then_else
6390             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6391                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6392             (const_int 4)
6393             (if_then_else
6394                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6395                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6396                 (const_int 6)
6397                 (const_int 8))))]
6398 )
6399   
6400 (define_insn "*tstsi3_cbranch"
6401   [(set (pc)
6402         (if_then_else
6403          (match_operator 3 "equality_operator"
6404           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
6405                    (match_operand:SI 1 "s_register_operand" "l"))
6406            (const_int 0)])
6407          (label_ref (match_operand 2 "" ""))
6408          (pc)))]
6409   "TARGET_THUMB1"
6410   "*
6411   {
6412   output_asm_insn (\"tst\\t%0, %1\", operands);
6413   switch (get_attr_length (insn))
6414     {
6415     case 4:  return \"b%d3\\t%l2\";
6416     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6417     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
6418     }
6419   }"
6420   [(set (attr "far_jump")
6421         (if_then_else
6422             (eq_attr "length" "8")
6423             (const_string "yes")
6424             (const_string "no")))
6425    (set (attr "length") 
6426         (if_then_else
6427             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6428                  (le (minus (match_dup 2) (pc)) (const_int 256)))
6429             (const_int 4)
6430             (if_then_else
6431                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6432                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
6433                 (const_int 6)
6434                 (const_int 8))))]
6435 )
6436   
6437 (define_insn "*andsi3_cbranch"
6438   [(set (pc)
6439         (if_then_else
6440          (match_operator 5 "equality_operator"
6441           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6442                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6443            (const_int 0)])
6444          (label_ref (match_operand 4 "" ""))
6445          (pc)))
6446    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6447         (and:SI (match_dup 2) (match_dup 3)))
6448    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6449   "TARGET_THUMB1"
6450   "*
6451   {
6452   if (which_alternative == 0)
6453     output_asm_insn (\"and\\t%0, %3\", operands);
6454   else if (which_alternative == 1)
6455     {
6456       output_asm_insn (\"and\\t%1, %3\", operands);
6457       output_asm_insn (\"mov\\t%0, %1\", operands);
6458     }
6459   else
6460     {
6461       output_asm_insn (\"and\\t%1, %3\", operands);
6462       output_asm_insn (\"str\\t%1, %0\", operands);
6463     }
6464
6465   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6466     {
6467     case 4:  return \"b%d5\\t%l4\";
6468     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6469     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6470     }
6471   }"
6472   [(set (attr "far_jump")
6473         (if_then_else
6474             (ior (and (eq (symbol_ref ("which_alternative"))
6475                           (const_int 0))
6476                       (eq_attr "length" "8"))
6477                  (eq_attr "length" "10"))
6478             (const_string "yes")
6479             (const_string "no")))
6480    (set (attr "length")
6481      (if_then_else
6482        (eq (symbol_ref ("which_alternative"))
6483                        (const_int 0))
6484        (if_then_else
6485          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6486               (le (minus (match_dup 4) (pc)) (const_int 256)))
6487          (const_int 4)
6488          (if_then_else
6489            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6490                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6491            (const_int 6)
6492            (const_int 8)))
6493        (if_then_else
6494          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6495               (le (minus (match_dup 4) (pc)) (const_int 256)))
6496          (const_int 6)
6497          (if_then_else
6498            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6499                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6500            (const_int 8)
6501            (const_int 10)))))]
6502 )
6503
6504 (define_insn "*orrsi3_cbranch_scratch"
6505   [(set (pc)
6506         (if_then_else
6507          (match_operator 4 "equality_operator"
6508           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6509                    (match_operand:SI 2 "s_register_operand" "l"))
6510            (const_int 0)])
6511          (label_ref (match_operand 3 "" ""))
6512          (pc)))
6513    (clobber (match_scratch:SI 0 "=l"))]
6514   "TARGET_THUMB1"
6515   "*
6516   {
6517   output_asm_insn (\"orr\\t%0, %2\", operands);
6518   switch (get_attr_length (insn))
6519     {
6520     case 4:  return \"b%d4\\t%l3\";
6521     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6522     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6523     }
6524   }"
6525   [(set (attr "far_jump")
6526         (if_then_else
6527             (eq_attr "length" "8")
6528             (const_string "yes")
6529             (const_string "no")))
6530    (set (attr "length") 
6531         (if_then_else
6532             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6533                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6534             (const_int 4)
6535             (if_then_else
6536                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6537                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6538                 (const_int 6)
6539                 (const_int 8))))]
6540 )
6541   
6542 (define_insn "*orrsi3_cbranch"
6543   [(set (pc)
6544         (if_then_else
6545          (match_operator 5 "equality_operator"
6546           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6547                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6548            (const_int 0)])
6549          (label_ref (match_operand 4 "" ""))
6550          (pc)))
6551    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6552         (ior:SI (match_dup 2) (match_dup 3)))
6553    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6554   "TARGET_THUMB1"
6555   "*
6556   {
6557   if (which_alternative == 0)
6558     output_asm_insn (\"orr\\t%0, %3\", operands);
6559   else if (which_alternative == 1)
6560     {
6561       output_asm_insn (\"orr\\t%1, %3\", operands);
6562       output_asm_insn (\"mov\\t%0, %1\", operands);
6563     }
6564   else
6565     {
6566       output_asm_insn (\"orr\\t%1, %3\", operands);
6567       output_asm_insn (\"str\\t%1, %0\", operands);
6568     }
6569
6570   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6571     {
6572     case 4:  return \"b%d5\\t%l4\";
6573     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6574     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6575     }
6576   }"
6577   [(set (attr "far_jump")
6578         (if_then_else
6579             (ior (and (eq (symbol_ref ("which_alternative"))
6580                           (const_int 0))
6581                       (eq_attr "length" "8"))
6582                  (eq_attr "length" "10"))
6583             (const_string "yes")
6584             (const_string "no")))
6585    (set (attr "length")
6586      (if_then_else
6587        (eq (symbol_ref ("which_alternative"))
6588                        (const_int 0))
6589        (if_then_else
6590          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6591               (le (minus (match_dup 4) (pc)) (const_int 256)))
6592          (const_int 4)
6593          (if_then_else
6594            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6595                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6596            (const_int 6)
6597            (const_int 8)))
6598        (if_then_else
6599          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6600               (le (minus (match_dup 4) (pc)) (const_int 256)))
6601          (const_int 6)
6602          (if_then_else
6603            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6604                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6605            (const_int 8)
6606            (const_int 10)))))]
6607 )
6608
6609 (define_insn "*xorsi3_cbranch_scratch"
6610   [(set (pc)
6611         (if_then_else
6612          (match_operator 4 "equality_operator"
6613           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6614                    (match_operand:SI 2 "s_register_operand" "l"))
6615            (const_int 0)])
6616          (label_ref (match_operand 3 "" ""))
6617          (pc)))
6618    (clobber (match_scratch:SI 0 "=l"))]
6619   "TARGET_THUMB1"
6620   "*
6621   {
6622   output_asm_insn (\"eor\\t%0, %2\", operands);
6623   switch (get_attr_length (insn))
6624     {
6625     case 4:  return \"b%d4\\t%l3\";
6626     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6627     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6628     }
6629   }"
6630   [(set (attr "far_jump")
6631         (if_then_else
6632             (eq_attr "length" "8")
6633             (const_string "yes")
6634             (const_string "no")))
6635    (set (attr "length") 
6636         (if_then_else
6637             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6638                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6639             (const_int 4)
6640             (if_then_else
6641                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6642                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6643                 (const_int 6)
6644                 (const_int 8))))]
6645 )
6646   
6647 (define_insn "*xorsi3_cbranch"
6648   [(set (pc)
6649         (if_then_else
6650          (match_operator 5 "equality_operator"
6651           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6652                    (match_operand:SI 3 "s_register_operand" "l,l,l,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         (xor:SI (match_dup 2) (match_dup 3)))
6658    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6659   "TARGET_THUMB1"
6660   "*
6661   {
6662   if (which_alternative == 0)
6663     output_asm_insn (\"eor\\t%0, %3\", operands);
6664   else if (which_alternative == 1)
6665     {
6666       output_asm_insn (\"eor\\t%1, %3\", operands);
6667       output_asm_insn (\"mov\\t%0, %1\", operands);
6668     }
6669   else
6670     {
6671       output_asm_insn (\"eor\\t%1, %3\", operands);
6672       output_asm_insn (\"str\\t%1, %0\", operands);
6673     }
6674
6675   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6676     {
6677     case 4:  return \"b%d5\\t%l4\";
6678     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6679     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6680     }
6681   }"
6682   [(set (attr "far_jump")
6683         (if_then_else
6684             (ior (and (eq (symbol_ref ("which_alternative"))
6685                           (const_int 0))
6686                       (eq_attr "length" "8"))
6687                  (eq_attr "length" "10"))
6688             (const_string "yes")
6689             (const_string "no")))
6690    (set (attr "length")
6691      (if_then_else
6692        (eq (symbol_ref ("which_alternative"))
6693                        (const_int 0))
6694        (if_then_else
6695          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6696               (le (minus (match_dup 4) (pc)) (const_int 256)))
6697          (const_int 4)
6698          (if_then_else
6699            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6700                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6701            (const_int 6)
6702            (const_int 8)))
6703        (if_then_else
6704          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6705               (le (minus (match_dup 4) (pc)) (const_int 256)))
6706          (const_int 6)
6707          (if_then_else
6708            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6709                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6710            (const_int 8)
6711            (const_int 10)))))]
6712 )
6713
6714 (define_insn "*bicsi3_cbranch_scratch"
6715   [(set (pc)
6716         (if_then_else
6717          (match_operator 4 "equality_operator"
6718           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6719                    (match_operand:SI 1 "s_register_operand" "0"))
6720            (const_int 0)])
6721          (label_ref (match_operand 3 "" ""))
6722          (pc)))
6723    (clobber (match_scratch:SI 0 "=l"))]
6724   "TARGET_THUMB1"
6725   "*
6726   {
6727   output_asm_insn (\"bic\\t%0, %2\", operands);
6728   switch (get_attr_length (insn))
6729     {
6730     case 4:  return \"b%d4\\t%l3\";
6731     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6732     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6733     }
6734   }"
6735   [(set (attr "far_jump")
6736         (if_then_else
6737             (eq_attr "length" "8")
6738             (const_string "yes")
6739             (const_string "no")))
6740    (set (attr "length") 
6741         (if_then_else
6742             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6743                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6744             (const_int 4)
6745             (if_then_else
6746                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6747                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6748                 (const_int 6)
6749                 (const_int 8))))]
6750 )
6751   
6752 (define_insn "*bicsi3_cbranch"
6753   [(set (pc)
6754         (if_then_else
6755          (match_operator 5 "equality_operator"
6756           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6757                    (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6758            (const_int 0)])
6759          (label_ref (match_operand 4 "" ""))
6760          (pc)))
6761    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6762         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6763    (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6764   "TARGET_THUMB1"
6765   "*
6766   {
6767   if (which_alternative == 0)
6768     output_asm_insn (\"bic\\t%0, %3\", operands);
6769   else if (which_alternative <= 2)
6770     {
6771       output_asm_insn (\"bic\\t%1, %3\", operands);
6772       /* It's ok if OP0 is a lo-reg, even though the mov will set the
6773          conditions again, since we're only testing for equality.  */
6774       output_asm_insn (\"mov\\t%0, %1\", operands);
6775     }
6776   else
6777     {
6778       output_asm_insn (\"bic\\t%1, %3\", operands);
6779       output_asm_insn (\"str\\t%1, %0\", operands);
6780     }
6781
6782   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6783     {
6784     case 4:  return \"b%d5\\t%l4\";
6785     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6786     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6787     }
6788   }"
6789   [(set (attr "far_jump")
6790         (if_then_else
6791             (ior (and (eq (symbol_ref ("which_alternative"))
6792                           (const_int 0))
6793                       (eq_attr "length" "8"))
6794                  (eq_attr "length" "10"))
6795             (const_string "yes")
6796             (const_string "no")))
6797    (set (attr "length")
6798      (if_then_else
6799        (eq (symbol_ref ("which_alternative"))
6800                        (const_int 0))
6801        (if_then_else
6802          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6803               (le (minus (match_dup 4) (pc)) (const_int 256)))
6804          (const_int 4)
6805          (if_then_else
6806            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6807                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6808            (const_int 6)
6809            (const_int 8)))
6810        (if_then_else
6811          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6812               (le (minus (match_dup 4) (pc)) (const_int 256)))
6813          (const_int 6)
6814          (if_then_else
6815            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6816                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6817            (const_int 8)
6818            (const_int 10)))))]
6819 )
6820
6821 (define_insn "*cbranchne_decr1"
6822   [(set (pc)
6823         (if_then_else (match_operator 3 "equality_operator"
6824                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6825                         (const_int 0)])
6826                       (label_ref (match_operand 4 "" ""))
6827                       (pc)))
6828    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6829         (plus:SI (match_dup 2) (const_int -1)))
6830    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6831   "TARGET_THUMB1"
6832   "*
6833    {
6834      rtx cond[2];
6835      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6836                                 ? GEU : LTU),
6837                                VOIDmode, operands[2], const1_rtx);
6838      cond[1] = operands[4];
6839
6840      if (which_alternative == 0)
6841        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6842      else if (which_alternative == 1)
6843        {
6844          /* We must provide an alternative for a hi reg because reload 
6845             cannot handle output reloads on a jump instruction, but we
6846             can't subtract into that.  Fortunately a mov from lo to hi
6847             does not clobber the condition codes.  */
6848          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6849          output_asm_insn (\"mov\\t%0, %1\", operands);
6850        }
6851      else
6852        {
6853          /* Similarly, but the target is memory.  */
6854          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6855          output_asm_insn (\"str\\t%1, %0\", operands);
6856        }
6857
6858      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6859        {
6860          case 4:
6861            output_asm_insn (\"b%d0\\t%l1\", cond);
6862            return \"\";
6863          case 6:
6864            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6865            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6866          default:
6867            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6868            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6869        }
6870    }
6871   "
6872   [(set (attr "far_jump")
6873         (if_then_else
6874             (ior (and (eq (symbol_ref ("which_alternative"))
6875                           (const_int 0))
6876                       (eq_attr "length" "8"))
6877                  (eq_attr "length" "10"))
6878             (const_string "yes")
6879             (const_string "no")))
6880    (set_attr_alternative "length"
6881       [
6882        ;; Alternative 0
6883        (if_then_else
6884          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6885               (le (minus (match_dup 4) (pc)) (const_int 256)))
6886          (const_int 4)
6887          (if_then_else
6888            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6889                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6890            (const_int 6)
6891            (const_int 8)))
6892        ;; Alternative 1
6893        (if_then_else
6894          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6895               (le (minus (match_dup 4) (pc)) (const_int 256)))
6896          (const_int 6)
6897          (if_then_else
6898            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6899                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6900            (const_int 8)
6901            (const_int 10)))
6902        ;; Alternative 2
6903        (if_then_else
6904          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6905               (le (minus (match_dup 4) (pc)) (const_int 256)))
6906          (const_int 6)
6907          (if_then_else
6908            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6909                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6910            (const_int 8)
6911            (const_int 10)))
6912        ;; Alternative 3
6913        (if_then_else
6914          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6915               (le (minus (match_dup 4) (pc)) (const_int 256)))
6916          (const_int 6)
6917          (if_then_else
6918            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6919                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6920            (const_int 8)
6921            (const_int 10)))])]
6922 )
6923
6924 (define_insn "*addsi3_cbranch"
6925   [(set (pc)
6926         (if_then_else
6927          (match_operator 4 "comparison_operator"
6928           [(plus:SI
6929             (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6930             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6931            (const_int 0)])
6932          (label_ref (match_operand 5 "" ""))
6933          (pc)))
6934    (set
6935     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6936     (plus:SI (match_dup 2) (match_dup 3)))
6937    (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6938   "TARGET_THUMB1
6939    && (GET_CODE (operands[4]) == EQ
6940        || GET_CODE (operands[4]) == NE
6941        || GET_CODE (operands[4]) == GE
6942        || GET_CODE (operands[4]) == LT)"
6943   "*
6944    {
6945      rtx cond[3];
6946
6947      
6948      cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6949      cond[1] = operands[2];
6950      cond[2] = operands[3];
6951
6952      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6953        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6954      else
6955        output_asm_insn (\"add\\t%0, %1, %2\", cond);
6956
6957      if (which_alternative >= 3
6958          && which_alternative < 4)
6959        output_asm_insn (\"mov\\t%0, %1\", operands);
6960      else if (which_alternative >= 4)
6961        output_asm_insn (\"str\\t%1, %0\", operands);
6962
6963      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6964        {
6965          case 4:
6966            return \"b%d4\\t%l5\";
6967          case 6:
6968            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6969          default:
6970            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6971        }
6972    }
6973   "
6974   [(set (attr "far_jump")
6975         (if_then_else
6976             (ior (and (lt (symbol_ref ("which_alternative"))
6977                           (const_int 3))
6978                       (eq_attr "length" "8"))
6979                  (eq_attr "length" "10"))
6980             (const_string "yes")
6981             (const_string "no")))
6982    (set (attr "length")
6983      (if_then_else
6984        (lt (symbol_ref ("which_alternative"))
6985                        (const_int 3))
6986        (if_then_else
6987          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6988               (le (minus (match_dup 5) (pc)) (const_int 256)))
6989          (const_int 4)
6990          (if_then_else
6991            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6992                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6993            (const_int 6)
6994            (const_int 8)))
6995        (if_then_else
6996          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6997               (le (minus (match_dup 5) (pc)) (const_int 256)))
6998          (const_int 6)
6999          (if_then_else
7000            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7001                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7002            (const_int 8)
7003            (const_int 10)))))]
7004 )
7005
7006 (define_insn "*addsi3_cbranch_scratch"
7007   [(set (pc)
7008         (if_then_else
7009          (match_operator 3 "comparison_operator"
7010           [(plus:SI
7011             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
7012             (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
7013            (const_int 0)])
7014          (label_ref (match_operand 4 "" ""))
7015          (pc)))
7016    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
7017   "TARGET_THUMB1
7018    && (GET_CODE (operands[3]) == EQ
7019        || GET_CODE (operands[3]) == NE
7020        || GET_CODE (operands[3]) == GE
7021        || GET_CODE (operands[3]) == LT)"
7022   "*
7023    {
7024      switch (which_alternative)
7025        {
7026        case 0:
7027          output_asm_insn (\"cmp\t%1, #%n2\", operands);
7028          break;
7029        case 1:
7030          output_asm_insn (\"cmn\t%1, %2\", operands);
7031          break;
7032        case 2:
7033          if (INTVAL (operands[2]) < 0)
7034            output_asm_insn (\"sub\t%0, %1, %2\", operands);
7035          else
7036            output_asm_insn (\"add\t%0, %1, %2\", operands);
7037          break;
7038        case 3:
7039          if (INTVAL (operands[2]) < 0)
7040            output_asm_insn (\"sub\t%0, %0, %2\", operands);
7041          else
7042            output_asm_insn (\"add\t%0, %0, %2\", operands);
7043          break;
7044        }
7045
7046      switch (get_attr_length (insn))
7047        {
7048          case 4:
7049            return \"b%d3\\t%l4\";
7050          case 6:
7051            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7052          default:
7053            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7054        }
7055    }
7056   "
7057   [(set (attr "far_jump")
7058         (if_then_else
7059             (eq_attr "length" "8")
7060             (const_string "yes")
7061             (const_string "no")))
7062    (set (attr "length")
7063        (if_then_else
7064          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7065               (le (minus (match_dup 4) (pc)) (const_int 256)))
7066          (const_int 4)
7067          (if_then_else
7068            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7069                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7070            (const_int 6)
7071            (const_int 8))))]
7072 )
7073
7074 (define_insn "*subsi3_cbranch"
7075   [(set (pc)
7076         (if_then_else
7077          (match_operator 4 "comparison_operator"
7078           [(minus:SI
7079             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
7080             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7081            (const_int 0)])
7082          (label_ref (match_operand 5 "" ""))
7083          (pc)))
7084    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
7085         (minus:SI (match_dup 2) (match_dup 3)))
7086    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
7087   "TARGET_THUMB1
7088    && (GET_CODE (operands[4]) == EQ
7089        || GET_CODE (operands[4]) == NE
7090        || GET_CODE (operands[4]) == GE
7091        || GET_CODE (operands[4]) == LT)"
7092   "*
7093    {
7094      if (which_alternative == 0)
7095        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
7096      else if (which_alternative == 1)
7097        {
7098          /* We must provide an alternative for a hi reg because reload 
7099             cannot handle output reloads on a jump instruction, but we
7100             can't subtract into that.  Fortunately a mov from lo to hi
7101             does not clobber the condition codes.  */
7102          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
7103          output_asm_insn (\"mov\\t%0, %1\", operands);
7104        }
7105      else
7106        {
7107          /* Similarly, but the target is memory.  */
7108          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
7109          output_asm_insn (\"str\\t%1, %0\", operands);
7110        }
7111
7112      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
7113        {
7114          case 4:
7115            return \"b%d4\\t%l5\";
7116          case 6:
7117            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7118          default:
7119            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7120        }
7121    }
7122   "
7123   [(set (attr "far_jump")
7124         (if_then_else
7125             (ior (and (eq (symbol_ref ("which_alternative"))
7126                           (const_int 0))
7127                       (eq_attr "length" "8"))
7128                  (eq_attr "length" "10"))
7129             (const_string "yes")
7130             (const_string "no")))
7131    (set (attr "length")
7132      (if_then_else
7133        (eq (symbol_ref ("which_alternative"))
7134                        (const_int 0))
7135        (if_then_else
7136          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7137               (le (minus (match_dup 5) (pc)) (const_int 256)))
7138          (const_int 4)
7139          (if_then_else
7140            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7141                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7142            (const_int 6)
7143            (const_int 8)))
7144        (if_then_else
7145          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7146               (le (minus (match_dup 5) (pc)) (const_int 256)))
7147          (const_int 6)
7148          (if_then_else
7149            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7150                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7151            (const_int 8)
7152            (const_int 10)))))]
7153 )
7154
7155 (define_insn "*subsi3_cbranch_scratch"
7156   [(set (pc)
7157         (if_then_else
7158          (match_operator 0 "arm_comparison_operator"
7159           [(minus:SI (match_operand:SI 1 "register_operand" "l")
7160                      (match_operand:SI 2 "nonmemory_operand" "l"))
7161            (const_int 0)])
7162          (label_ref (match_operand 3 "" ""))
7163          (pc)))]
7164   "TARGET_THUMB1
7165    && (GET_CODE (operands[0]) == EQ
7166        || GET_CODE (operands[0]) == NE
7167        || GET_CODE (operands[0]) == GE
7168        || GET_CODE (operands[0]) == LT)"
7169   "*
7170   output_asm_insn (\"cmp\\t%1, %2\", operands);
7171   switch (get_attr_length (insn))
7172     {
7173     case 4:  return \"b%d0\\t%l3\";
7174     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7175     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7176     }
7177   "
7178   [(set (attr "far_jump")
7179         (if_then_else
7180             (eq_attr "length" "8")
7181             (const_string "yes")
7182             (const_string "no")))
7183    (set (attr "length") 
7184         (if_then_else
7185             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7186                  (le (minus (match_dup 3) (pc)) (const_int 256)))
7187             (const_int 4)
7188             (if_then_else
7189                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7190                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
7191                 (const_int 6)
7192                 (const_int 8))))]
7193 )
7194
7195 ;; Comparison and test insns
7196
7197 (define_expand "cmpsi"
7198   [(match_operand:SI 0 "s_register_operand" "")
7199    (match_operand:SI 1 "arm_add_operand" "")]
7200   "TARGET_32BIT"
7201   "{
7202     arm_compare_op0 = operands[0];
7203     arm_compare_op1 = operands[1];
7204     DONE;
7205   }"
7206 )
7207
7208 (define_expand "cmpsf"
7209   [(match_operand:SF 0 "s_register_operand" "")
7210    (match_operand:SF 1 "arm_float_compare_operand" "")]
7211   "TARGET_32BIT && TARGET_HARD_FLOAT"
7212   "
7213   arm_compare_op0 = operands[0];
7214   arm_compare_op1 = operands[1];
7215   DONE;
7216   "
7217 )
7218
7219 (define_expand "cmpdf"
7220   [(match_operand:DF 0 "s_register_operand" "")
7221    (match_operand:DF 1 "arm_float_compare_operand" "")]
7222   "TARGET_32BIT && TARGET_HARD_FLOAT"
7223   "
7224   arm_compare_op0 = operands[0];
7225   arm_compare_op1 = operands[1];
7226   DONE;
7227   "
7228 )
7229
7230 (define_insn "*arm_cmpsi_insn"
7231   [(set (reg:CC CC_REGNUM)
7232         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
7233                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
7234   "TARGET_32BIT"
7235   "@
7236    cmp%?\\t%0, %1
7237    cmn%?\\t%0, #%n1"
7238   [(set_attr "conds" "set")]
7239 )
7240
7241 (define_insn "*arm_cmpsi_shiftsi"
7242   [(set (reg:CC CC_REGNUM)
7243         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
7244                     (match_operator:SI  3 "shift_operator"
7245                      [(match_operand:SI 1 "s_register_operand" "r")
7246                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
7247   "TARGET_ARM"
7248   "cmp%?\\t%0, %1%S3"
7249   [(set_attr "conds" "set")
7250    (set_attr "shift" "1")
7251    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
7252                       (const_string "alu_shift")
7253                       (const_string "alu_shift_reg")))]
7254 )
7255
7256 (define_insn "*arm_cmpsi_shiftsi_swp"
7257   [(set (reg:CC_SWP CC_REGNUM)
7258         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
7259                          [(match_operand:SI 1 "s_register_operand" "r")
7260                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
7261                         (match_operand:SI 0 "s_register_operand" "r")))]
7262   "TARGET_ARM"
7263   "cmp%?\\t%0, %1%S3"
7264   [(set_attr "conds" "set")
7265    (set_attr "shift" "1")
7266    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
7267                       (const_string "alu_shift")
7268                       (const_string "alu_shift_reg")))]
7269 )
7270
7271 (define_insn "*arm_cmpsi_negshiftsi_si"
7272   [(set (reg:CC_Z CC_REGNUM)
7273         (compare:CC_Z
7274          (neg:SI (match_operator:SI 1 "shift_operator"
7275                     [(match_operand:SI 2 "s_register_operand" "r")
7276                      (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7277          (match_operand:SI 0 "s_register_operand" "r")))]
7278   "TARGET_ARM"
7279   "cmn%?\\t%0, %2%S1"
7280   [(set_attr "conds" "set")
7281    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7282                                     (const_string "alu_shift")
7283                                     (const_string "alu_shift_reg")))]
7284 )
7285
7286 ;; Cirrus SF compare instruction
7287 (define_insn "*cirrus_cmpsf"
7288   [(set (reg:CCFP CC_REGNUM)
7289         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
7290                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
7291   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7292   "cfcmps%?\\tr15, %V0, %V1"
7293   [(set_attr "type"   "mav_farith")
7294    (set_attr "cirrus" "compare")]
7295 )
7296
7297 ;; Cirrus DF compare instruction
7298 (define_insn "*cirrus_cmpdf"
7299   [(set (reg:CCFP CC_REGNUM)
7300         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
7301                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
7302   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7303   "cfcmpd%?\\tr15, %V0, %V1"
7304   [(set_attr "type"   "mav_farith")
7305    (set_attr "cirrus" "compare")]
7306 )
7307
7308 ;; Cirrus DI compare instruction
7309 (define_expand "cmpdi"
7310   [(match_operand:DI 0 "cirrus_fp_register" "")
7311    (match_operand:DI 1 "cirrus_fp_register" "")]
7312   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7313   "{
7314      arm_compare_op0 = operands[0];
7315      arm_compare_op1 = operands[1];
7316      DONE;
7317    }")
7318
7319 (define_insn "*cirrus_cmpdi"
7320   [(set (reg:CC CC_REGNUM)
7321         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
7322                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
7323   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7324   "cfcmp64%?\\tr15, %V0, %V1"
7325   [(set_attr "type"   "mav_farith")
7326    (set_attr "cirrus" "compare")]
7327 )
7328
7329 ; This insn allows redundant compares to be removed by cse, nothing should
7330 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7331 ; is deleted later on. The match_dup will match the mode here, so that
7332 ; mode changes of the condition codes aren't lost by this even though we don't
7333 ; specify what they are.
7334
7335 (define_insn "*deleted_compare"
7336   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
7337   "TARGET_32BIT"
7338   "\\t%@ deleted compare"
7339   [(set_attr "conds" "set")
7340    (set_attr "length" "0")]
7341 )
7342
7343 \f
7344 ;; Conditional branch insns
7345
7346 (define_expand "beq"
7347   [(set (pc)
7348         (if_then_else (eq (match_dup 1) (const_int 0))
7349                       (label_ref (match_operand 0 "" ""))
7350                       (pc)))]
7351   "TARGET_32BIT"
7352   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7353 )
7354
7355 (define_expand "bne"
7356   [(set (pc)
7357         (if_then_else (ne (match_dup 1) (const_int 0))
7358                       (label_ref (match_operand 0 "" ""))
7359                       (pc)))]
7360   "TARGET_32BIT"
7361   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7362 )
7363
7364 (define_expand "bgt"
7365   [(set (pc)
7366         (if_then_else (gt (match_dup 1) (const_int 0))
7367                       (label_ref (match_operand 0 "" ""))
7368                       (pc)))]
7369   "TARGET_32BIT"
7370   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7371 )
7372
7373 (define_expand "ble"
7374   [(set (pc)
7375         (if_then_else (le (match_dup 1) (const_int 0))
7376                       (label_ref (match_operand 0 "" ""))
7377                       (pc)))]
7378   "TARGET_32BIT"
7379   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7380 )
7381
7382 (define_expand "bge"
7383   [(set (pc)
7384         (if_then_else (ge (match_dup 1) (const_int 0))
7385                       (label_ref (match_operand 0 "" ""))
7386                       (pc)))]
7387   "TARGET_32BIT"
7388   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7389 )
7390
7391 (define_expand "blt"
7392   [(set (pc)
7393         (if_then_else (lt (match_dup 1) (const_int 0))
7394                       (label_ref (match_operand 0 "" ""))
7395                       (pc)))]
7396   "TARGET_32BIT"
7397   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7398 )
7399
7400 (define_expand "bgtu"
7401   [(set (pc)
7402         (if_then_else (gtu (match_dup 1) (const_int 0))
7403                       (label_ref (match_operand 0 "" ""))
7404                       (pc)))]
7405   "TARGET_32BIT"
7406   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7407 )
7408
7409 (define_expand "bleu"
7410   [(set (pc)
7411         (if_then_else (leu (match_dup 1) (const_int 0))
7412                       (label_ref (match_operand 0 "" ""))
7413                       (pc)))]
7414   "TARGET_32BIT"
7415   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7416 )
7417
7418 (define_expand "bgeu"
7419   [(set (pc)
7420         (if_then_else (geu (match_dup 1) (const_int 0))
7421                       (label_ref (match_operand 0 "" ""))
7422                       (pc)))]
7423   "TARGET_32BIT"
7424   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7425 )
7426
7427 (define_expand "bltu"
7428   [(set (pc)
7429         (if_then_else (ltu (match_dup 1) (const_int 0))
7430                       (label_ref (match_operand 0 "" ""))
7431                       (pc)))]
7432   "TARGET_32BIT"
7433   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7434 )
7435
7436 (define_expand "bunordered"
7437   [(set (pc)
7438         (if_then_else (unordered (match_dup 1) (const_int 0))
7439                       (label_ref (match_operand 0 "" ""))
7440                       (pc)))]
7441   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7442   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7443                                       arm_compare_op1);"
7444 )
7445
7446 (define_expand "bordered"
7447   [(set (pc)
7448         (if_then_else (ordered (match_dup 1) (const_int 0))
7449                       (label_ref (match_operand 0 "" ""))
7450                       (pc)))]
7451   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7452   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7453                                       arm_compare_op1);"
7454 )
7455
7456 (define_expand "bungt"
7457   [(set (pc)
7458         (if_then_else (ungt (match_dup 1) (const_int 0))
7459                       (label_ref (match_operand 0 "" ""))
7460                       (pc)))]
7461   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7462   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
7463 )
7464
7465 (define_expand "bunlt"
7466   [(set (pc)
7467         (if_then_else (unlt (match_dup 1) (const_int 0))
7468                       (label_ref (match_operand 0 "" ""))
7469                       (pc)))]
7470   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7471   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
7472 )
7473
7474 (define_expand "bunge"
7475   [(set (pc)
7476         (if_then_else (unge (match_dup 1) (const_int 0))
7477                       (label_ref (match_operand 0 "" ""))
7478                       (pc)))]
7479   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7480   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
7481 )
7482
7483 (define_expand "bunle"
7484   [(set (pc)
7485         (if_then_else (unle (match_dup 1) (const_int 0))
7486                       (label_ref (match_operand 0 "" ""))
7487                       (pc)))]
7488   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7489   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
7490 )
7491
7492 ;; The following two patterns need two branch instructions, since there is
7493 ;; no single instruction that will handle all cases.
7494 (define_expand "buneq"
7495   [(set (pc)
7496         (if_then_else (uneq (match_dup 1) (const_int 0))
7497                       (label_ref (match_operand 0 "" ""))
7498                       (pc)))]
7499   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7500   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
7501 )
7502
7503 (define_expand "bltgt"
7504   [(set (pc)
7505         (if_then_else (ltgt (match_dup 1) (const_int 0))
7506                       (label_ref (match_operand 0 "" ""))
7507                       (pc)))]
7508   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7509   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
7510 )
7511
7512 ;;
7513 ;; Patterns to match conditional branch insns.
7514 ;;
7515
7516 ; Special pattern to match UNEQ.
7517 (define_insn "*arm_buneq"
7518   [(set (pc)
7519         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7520                       (label_ref (match_operand 0 "" ""))
7521                       (pc)))]
7522   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7523   "*
7524   gcc_assert (!arm_ccfsm_state);
7525
7526   return \"bvs\\t%l0\;beq\\t%l0\";
7527   "
7528   [(set_attr "conds" "jump_clob")
7529    (set_attr "length" "8")]
7530 )
7531
7532 ; Special pattern to match LTGT.
7533 (define_insn "*arm_bltgt"
7534   [(set (pc)
7535         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7536                       (label_ref (match_operand 0 "" ""))
7537                       (pc)))]
7538   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7539   "*
7540   gcc_assert (!arm_ccfsm_state);
7541
7542   return \"bmi\\t%l0\;bgt\\t%l0\";
7543   "
7544   [(set_attr "conds" "jump_clob")
7545    (set_attr "length" "8")]
7546 )
7547
7548 (define_insn "*arm_cond_branch"
7549   [(set (pc)
7550         (if_then_else (match_operator 1 "arm_comparison_operator"
7551                        [(match_operand 2 "cc_register" "") (const_int 0)])
7552                       (label_ref (match_operand 0 "" ""))
7553                       (pc)))]
7554   "TARGET_32BIT"
7555   "*
7556   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7557     {
7558       arm_ccfsm_state += 2;
7559       return \"\";
7560     }
7561   return \"b%d1\\t%l0\";
7562   "
7563   [(set_attr "conds" "use")
7564    (set_attr "type" "branch")]
7565 )
7566
7567 ; Special pattern to match reversed UNEQ.
7568 (define_insn "*arm_buneq_reversed"
7569   [(set (pc)
7570         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7571                       (pc)
7572                       (label_ref (match_operand 0 "" ""))))]
7573   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7574   "*
7575   gcc_assert (!arm_ccfsm_state);
7576
7577   return \"bmi\\t%l0\;bgt\\t%l0\";
7578   "
7579   [(set_attr "conds" "jump_clob")
7580    (set_attr "length" "8")]
7581 )
7582
7583 ; Special pattern to match reversed LTGT.
7584 (define_insn "*arm_bltgt_reversed"
7585   [(set (pc)
7586         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7587                       (pc)
7588                       (label_ref (match_operand 0 "" ""))))]
7589   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7590   "*
7591   gcc_assert (!arm_ccfsm_state);
7592
7593   return \"bvs\\t%l0\;beq\\t%l0\";
7594   "
7595   [(set_attr "conds" "jump_clob")
7596    (set_attr "length" "8")]
7597 )
7598
7599 (define_insn "*arm_cond_branch_reversed"
7600   [(set (pc)
7601         (if_then_else (match_operator 1 "arm_comparison_operator"
7602                        [(match_operand 2 "cc_register" "") (const_int 0)])
7603                       (pc)
7604                       (label_ref (match_operand 0 "" ""))))]
7605   "TARGET_32BIT"
7606   "*
7607   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7608     {
7609       arm_ccfsm_state += 2;
7610       return \"\";
7611     }
7612   return \"b%D1\\t%l0\";
7613   "
7614   [(set_attr "conds" "use")
7615    (set_attr "type" "branch")]
7616 )
7617
7618 \f
7619
7620 ; scc insns
7621
7622 (define_expand "seq"
7623   [(set (match_operand:SI 0 "s_register_operand" "")
7624         (eq:SI (match_dup 1) (const_int 0)))]
7625   "TARGET_32BIT"
7626   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7627 )
7628
7629 (define_expand "sne"
7630   [(set (match_operand:SI 0 "s_register_operand" "")
7631         (ne:SI (match_dup 1) (const_int 0)))]
7632   "TARGET_32BIT"
7633   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7634 )
7635
7636 (define_expand "sgt"
7637   [(set (match_operand:SI 0 "s_register_operand" "")
7638         (gt:SI (match_dup 1) (const_int 0)))]
7639   "TARGET_32BIT"
7640   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7641 )
7642
7643 (define_expand "sle"
7644   [(set (match_operand:SI 0 "s_register_operand" "")
7645         (le:SI (match_dup 1) (const_int 0)))]
7646   "TARGET_32BIT"
7647   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7648 )
7649
7650 (define_expand "sge"
7651   [(set (match_operand:SI 0 "s_register_operand" "")
7652         (ge:SI (match_dup 1) (const_int 0)))]
7653   "TARGET_32BIT"
7654   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7655 )
7656
7657 (define_expand "slt"
7658   [(set (match_operand:SI 0 "s_register_operand" "")
7659         (lt:SI (match_dup 1) (const_int 0)))]
7660   "TARGET_32BIT"
7661   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7662 )
7663
7664 (define_expand "sgtu"
7665   [(set (match_operand:SI 0 "s_register_operand" "")
7666         (gtu:SI (match_dup 1) (const_int 0)))]
7667   "TARGET_32BIT"
7668   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7669 )
7670
7671 (define_expand "sleu"
7672   [(set (match_operand:SI 0 "s_register_operand" "")
7673         (leu:SI (match_dup 1) (const_int 0)))]
7674   "TARGET_32BIT"
7675   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7676 )
7677
7678 (define_expand "sgeu"
7679   [(set (match_operand:SI 0 "s_register_operand" "")
7680         (geu:SI (match_dup 1) (const_int 0)))]
7681   "TARGET_32BIT"
7682   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7683 )
7684
7685 (define_expand "sltu"
7686   [(set (match_operand:SI 0 "s_register_operand" "")
7687         (ltu:SI (match_dup 1) (const_int 0)))]
7688   "TARGET_32BIT"
7689   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7690 )
7691
7692 (define_expand "sunordered"
7693   [(set (match_operand:SI 0 "s_register_operand" "")
7694         (unordered:SI (match_dup 1) (const_int 0)))]
7695   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7696   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7697                                       arm_compare_op1);"
7698 )
7699
7700 (define_expand "sordered"
7701   [(set (match_operand:SI 0 "s_register_operand" "")
7702         (ordered:SI (match_dup 1) (const_int 0)))]
7703   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7704   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7705                                       arm_compare_op1);"
7706 )
7707
7708 (define_expand "sungt"
7709   [(set (match_operand:SI 0 "s_register_operand" "")
7710         (ungt:SI (match_dup 1) (const_int 0)))]
7711   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7712   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7713                                       arm_compare_op1);"
7714 )
7715
7716 (define_expand "sunge"
7717   [(set (match_operand:SI 0 "s_register_operand" "")
7718         (unge:SI (match_dup 1) (const_int 0)))]
7719   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7720   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7721                                       arm_compare_op1);"
7722 )
7723
7724 (define_expand "sunlt"
7725   [(set (match_operand:SI 0 "s_register_operand" "")
7726         (unlt:SI (match_dup 1) (const_int 0)))]
7727   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7728   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7729                                       arm_compare_op1);"
7730 )
7731
7732 (define_expand "sunle"
7733   [(set (match_operand:SI 0 "s_register_operand" "")
7734         (unle:SI (match_dup 1) (const_int 0)))]
7735   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7736   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7737                                       arm_compare_op1);"
7738 )
7739
7740 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7741 ;;; simple ARM instructions. 
7742 ;
7743 ; (define_expand "suneq"
7744 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7745 ;       (uneq:SI (match_dup 1) (const_int 0)))]
7746 ;   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7747 ;   "gcc_unreachable ();"
7748 ; )
7749 ;
7750 ; (define_expand "sltgt"
7751 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7752 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
7753 ;   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7754 ;   "gcc_unreachable ();"
7755 ; )
7756
7757 (define_insn "*mov_scc"
7758   [(set (match_operand:SI 0 "s_register_operand" "=r")
7759         (match_operator:SI 1 "arm_comparison_operator"
7760          [(match_operand 2 "cc_register" "") (const_int 0)]))]
7761   "TARGET_ARM"
7762   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7763   [(set_attr "conds" "use")
7764    (set_attr "length" "8")]
7765 )
7766
7767 (define_insn "*mov_negscc"
7768   [(set (match_operand:SI 0 "s_register_operand" "=r")
7769         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7770                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7771   "TARGET_ARM"
7772   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7773   [(set_attr "conds" "use")
7774    (set_attr "length" "8")]
7775 )
7776
7777 (define_insn "*mov_notscc"
7778   [(set (match_operand:SI 0 "s_register_operand" "=r")
7779         (not:SI (match_operator:SI 1 "arm_comparison_operator"
7780                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7781   "TARGET_ARM"
7782   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7783   [(set_attr "conds" "use")
7784    (set_attr "length" "8")]
7785 )
7786
7787 (define_expand "cstoresi4"
7788   [(set (match_operand:SI 0 "s_register_operand" "")
7789         (match_operator:SI 1 "arm_comparison_operator"
7790          [(match_operand:SI 2 "s_register_operand" "")
7791           (match_operand:SI 3 "reg_or_int_operand" "")]))]
7792   "TARGET_THUMB1"
7793   "{
7794   rtx op3, scratch, scratch2;
7795
7796   if (operands[3] == const0_rtx)
7797     {
7798       switch (GET_CODE (operands[1]))
7799         {
7800         case EQ:
7801           emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
7802           break;
7803
7804         case NE:
7805           emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
7806           break;
7807
7808         case LE:
7809           scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7810                                   NULL_RTX, 0, OPTAB_WIDEN);
7811           scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7812                                   NULL_RTX, 0, OPTAB_WIDEN);
7813           expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7814                         operands[0], 1, OPTAB_WIDEN);
7815           break;
7816
7817         case GE:
7818           scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7819                                  NULL_RTX, 1);
7820           expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7821                         NULL_RTX, 1, OPTAB_WIDEN);
7822           break;
7823
7824         case GT:
7825           scratch = expand_binop (SImode, ashr_optab, operands[2],
7826                                   GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7827           scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7828                                   NULL_RTX, 0, OPTAB_WIDEN);
7829           expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7830                         0, OPTAB_WIDEN);
7831           break;
7832
7833         /* LT is handled by generic code.  No need for unsigned with 0.  */
7834         default:
7835           FAIL;
7836         }
7837       DONE;
7838     }
7839
7840   switch (GET_CODE (operands[1]))
7841     {
7842     case EQ:
7843       scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7844                               NULL_RTX, 0, OPTAB_WIDEN);
7845       emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
7846       break;
7847
7848     case NE:
7849       scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7850                               NULL_RTX, 0, OPTAB_WIDEN);
7851       emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
7852       break;
7853
7854     case LE:
7855       op3 = force_reg (SImode, operands[3]);
7856
7857       scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7858                               NULL_RTX, 1, OPTAB_WIDEN);
7859       scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7860                               NULL_RTX, 0, OPTAB_WIDEN);
7861       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
7862                                           op3, operands[2]));
7863       break;
7864
7865     case GE:
7866       op3 = operands[3];
7867       if (!thumb1_cmp_operand (op3, SImode))
7868         op3 = force_reg (SImode, op3);
7869       scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7870                               NULL_RTX, 0, OPTAB_WIDEN);
7871       scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7872                                NULL_RTX, 1, OPTAB_WIDEN);
7873       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
7874                                           operands[2], op3));
7875       break;
7876
7877     case LEU:
7878       op3 = force_reg (SImode, operands[3]);
7879       scratch = force_reg (SImode, const0_rtx);
7880       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
7881                                           op3, operands[2]));
7882       break;
7883
7884     case GEU:
7885       op3 = operands[3];
7886       if (!thumb1_cmp_operand (op3, SImode))
7887         op3 = force_reg (SImode, op3);
7888       scratch = force_reg (SImode, const0_rtx);
7889       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
7890                                           operands[2], op3));
7891       break;
7892
7893     case LTU:
7894       op3 = operands[3];
7895       if (!thumb1_cmp_operand (op3, SImode))
7896         op3 = force_reg (SImode, op3);
7897       scratch = gen_reg_rtx (SImode);
7898       emit_insn (gen_cstoresi_nltu_thumb1 (scratch, operands[2], op3));
7899       emit_insn (gen_negsi2 (operands[0], scratch));
7900       break;
7901
7902     case GTU:
7903       op3 = force_reg (SImode, operands[3]);
7904       scratch = gen_reg_rtx (SImode);
7905       emit_insn (gen_cstoresi_nltu_thumb1 (scratch, op3, operands[2]));
7906       emit_insn (gen_negsi2 (operands[0], scratch));
7907       break;
7908
7909     /* No good sequences for GT, LT.  */
7910     default:
7911       FAIL;
7912     }
7913   DONE;
7914 }")
7915
7916 (define_expand "cstoresi_eq0_thumb1"
7917   [(parallel
7918     [(set (match_operand:SI 0 "s_register_operand" "")
7919           (eq:SI (match_operand:SI 1 "s_register_operand" "")
7920                  (const_int 0)))
7921      (clobber (match_dup:SI 2))])]
7922   "TARGET_THUMB1"
7923   "operands[2] = gen_reg_rtx (SImode);"
7924 )
7925
7926 (define_expand "cstoresi_ne0_thumb1"
7927   [(parallel
7928     [(set (match_operand:SI 0 "s_register_operand" "")
7929           (ne:SI (match_operand:SI 1 "s_register_operand" "")
7930                  (const_int 0)))
7931      (clobber (match_dup:SI 2))])]
7932   "TARGET_THUMB1"
7933   "operands[2] = gen_reg_rtx (SImode);"
7934 )
7935
7936 (define_insn "*cstoresi_eq0_thumb1_insn"
7937   [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
7938         (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
7939                (const_int 0)))
7940    (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
7941   "TARGET_THUMB1"
7942   "@
7943    neg\\t%0, %1\;adc\\t%0, %0, %1
7944    neg\\t%2, %1\;adc\\t%0, %1, %2"
7945   [(set_attr "length" "4")]
7946 )
7947
7948 (define_insn "*cstoresi_ne0_thumb1_insn"
7949   [(set (match_operand:SI 0 "s_register_operand" "=l")
7950         (ne:SI (match_operand:SI 1 "s_register_operand" "0")
7951                (const_int 0)))
7952    (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
7953   "TARGET_THUMB1"
7954   "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
7955   [(set_attr "length" "4")]
7956 )
7957
7958 (define_insn "cstoresi_nltu_thumb1"
7959   [(set (match_operand:SI 0 "s_register_operand" "=l,l")
7960         (neg:SI (gtu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
7961                         (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
7962   "TARGET_THUMB1"
7963   "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
7964   [(set_attr "length" "4")]
7965 )
7966
7967 ;; Used as part of the expansion of thumb les sequence.
7968 (define_insn "thumb1_addsi3_addgeu"
7969   [(set (match_operand:SI 0 "s_register_operand" "=l")
7970         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7971                           (match_operand:SI 2 "s_register_operand" "l"))
7972                  (geu:SI (match_operand:SI 3 "s_register_operand" "l")
7973                          (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
7974   "TARGET_THUMB1"
7975   "cmp\\t%3, %4\;adc\\t%0, %1, %2"
7976   [(set_attr "length" "4")]
7977 )
7978
7979 \f
7980 ;; Conditional move insns
7981
7982 (define_expand "movsicc"
7983   [(set (match_operand:SI 0 "s_register_operand" "")
7984         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7985                          (match_operand:SI 2 "arm_not_operand" "")
7986                          (match_operand:SI 3 "arm_not_operand" "")))]
7987   "TARGET_32BIT"
7988   "
7989   {
7990     enum rtx_code code = GET_CODE (operands[1]);
7991     rtx ccreg;
7992
7993     if (code == UNEQ || code == LTGT)
7994       FAIL;
7995
7996     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7997     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7998   }"
7999 )
8000
8001 (define_expand "movsfcc"
8002   [(set (match_operand:SF 0 "s_register_operand" "")
8003         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
8004                          (match_operand:SF 2 "s_register_operand" "")
8005                          (match_operand:SF 3 "nonmemory_operand" "")))]
8006   "TARGET_32BIT"
8007   "
8008   {
8009     enum rtx_code code = GET_CODE (operands[1]);
8010     rtx ccreg;
8011
8012     if (code == UNEQ || code == LTGT)
8013       FAIL;
8014
8015     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
8016        Otherwise, ensure it is a valid FP add operand */
8017     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
8018         || (!arm_float_add_operand (operands[3], SFmode)))
8019       operands[3] = force_reg (SFmode, operands[3]);
8020
8021     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
8022     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
8023   }"
8024 )
8025
8026 (define_expand "movdfcc"
8027   [(set (match_operand:DF 0 "s_register_operand" "")
8028         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
8029                          (match_operand:DF 2 "s_register_operand" "")
8030                          (match_operand:DF 3 "arm_float_add_operand" "")))]
8031   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8032   "
8033   {
8034     enum rtx_code code = GET_CODE (operands[1]);
8035     rtx ccreg;
8036
8037     if (code == UNEQ || code == LTGT)
8038       FAIL;
8039
8040     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
8041     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
8042   }"
8043 )
8044
8045 (define_insn "*movsicc_insn"
8046   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8047         (if_then_else:SI
8048          (match_operator 3 "arm_comparison_operator"
8049           [(match_operand 4 "cc_register" "") (const_int 0)])
8050          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
8051          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
8052   "TARGET_ARM"
8053   "@
8054    mov%D3\\t%0, %2
8055    mvn%D3\\t%0, #%B2
8056    mov%d3\\t%0, %1
8057    mvn%d3\\t%0, #%B1
8058    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
8059    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
8060    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
8061    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
8062   [(set_attr "length" "4,4,4,4,8,8,8,8")
8063    (set_attr "conds" "use")]
8064 )
8065
8066 (define_insn "*movsfcc_soft_insn"
8067   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8068         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8069                           [(match_operand 4 "cc_register" "") (const_int 0)])
8070                          (match_operand:SF 1 "s_register_operand" "0,r")
8071                          (match_operand:SF 2 "s_register_operand" "r,0")))]
8072   "TARGET_ARM && TARGET_SOFT_FLOAT"
8073   "@
8074    mov%D3\\t%0, %2
8075    mov%d3\\t%0, %1"
8076   [(set_attr "conds" "use")]
8077 )
8078
8079 \f
8080 ;; Jump and linkage insns
8081
8082 (define_expand "jump"
8083   [(set (pc)
8084         (label_ref (match_operand 0 "" "")))]
8085   "TARGET_EITHER"
8086   ""
8087 )
8088
8089 (define_insn "*arm_jump"
8090   [(set (pc)
8091         (label_ref (match_operand 0 "" "")))]
8092   "TARGET_32BIT"
8093   "*
8094   {
8095     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
8096       {
8097         arm_ccfsm_state += 2;
8098         return \"\";
8099       }
8100     return \"b%?\\t%l0\";
8101   }
8102   "
8103   [(set_attr "predicable" "yes")]
8104 )
8105
8106 (define_insn "*thumb_jump"
8107   [(set (pc)
8108         (label_ref (match_operand 0 "" "")))]
8109   "TARGET_THUMB1"
8110   "*
8111   if (get_attr_length (insn) == 2)
8112     return \"b\\t%l0\";
8113   return \"bl\\t%l0\\t%@ far jump\";
8114   "
8115   [(set (attr "far_jump")
8116         (if_then_else
8117             (eq_attr "length" "4")
8118             (const_string "yes")
8119             (const_string "no")))
8120    (set (attr "length") 
8121         (if_then_else
8122             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8123                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
8124             (const_int 2)
8125             (const_int 4)))]
8126 )
8127
8128 (define_expand "call"
8129   [(parallel [(call (match_operand 0 "memory_operand" "")
8130                     (match_operand 1 "general_operand" ""))
8131               (use (match_operand 2 "" ""))
8132               (clobber (reg:SI LR_REGNUM))])]
8133   "TARGET_EITHER"
8134   "
8135   {
8136     rtx callee;
8137     
8138     /* In an untyped call, we can get NULL for operand 2.  */
8139     if (operands[2] == NULL_RTX)
8140       operands[2] = const0_rtx;
8141       
8142     /* This is to decide if we should generate indirect calls by loading the
8143        32 bit address of the callee into a register before performing the
8144        branch and link.  operand[2] encodes the long_call/short_call
8145        attribute of the function being called.  This attribute is set whenever
8146        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
8147        is used, and the short_call attribute can also be set if function is
8148        declared as static or if it has already been defined in the current
8149        compilation unit.  See arm.c and arm.h for info about this.  The third
8150        parameter to arm_is_longcall_p is used to tell it which pattern
8151        invoked it.  */
8152     callee  = XEXP (operands[0], 0);
8153     
8154     if ((GET_CODE (callee) == SYMBOL_REF
8155          && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
8156         || (GET_CODE (callee) != SYMBOL_REF
8157             && GET_CODE (callee) != REG))
8158       XEXP (operands[0], 0) = force_reg (Pmode, callee);
8159   }"
8160 )
8161
8162 (define_insn "*call_reg_armv5"
8163   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8164          (match_operand 1 "" ""))
8165    (use (match_operand 2 "" ""))
8166    (clobber (reg:SI LR_REGNUM))]
8167   "TARGET_ARM && arm_arch5"
8168   "blx%?\\t%0"
8169   [(set_attr "type" "call")]
8170 )
8171
8172 (define_insn "*call_reg_arm"
8173   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8174          (match_operand 1 "" ""))
8175    (use (match_operand 2 "" ""))
8176    (clobber (reg:SI LR_REGNUM))]
8177   "TARGET_ARM && !arm_arch5"
8178   "*
8179   return output_call (operands);
8180   "
8181   ;; length is worst case, normally it is only two
8182   [(set_attr "length" "12")
8183    (set_attr "type" "call")]
8184 )
8185
8186 (define_insn "*call_mem"
8187   [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
8188          (match_operand 1 "" ""))
8189    (use (match_operand 2 "" ""))
8190    (clobber (reg:SI LR_REGNUM))]
8191   "TARGET_ARM"
8192   "*
8193   return output_call_mem (operands);
8194   "
8195   [(set_attr "length" "12")
8196    (set_attr "type" "call")]
8197 )
8198
8199 (define_insn "*call_reg_thumb1_v5"
8200   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8201          (match_operand 1 "" ""))
8202    (use (match_operand 2 "" ""))
8203    (clobber (reg:SI LR_REGNUM))]
8204   "TARGET_THUMB1 && arm_arch5"
8205   "blx\\t%0"
8206   [(set_attr "length" "2")
8207    (set_attr "type" "call")]
8208 )
8209
8210 (define_insn "*call_reg_thumb1"
8211   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8212          (match_operand 1 "" ""))
8213    (use (match_operand 2 "" ""))
8214    (clobber (reg:SI LR_REGNUM))]
8215   "TARGET_THUMB1 && !arm_arch5"
8216   "*
8217   {
8218     if (!TARGET_CALLER_INTERWORKING)
8219       return thumb_call_via_reg (operands[0]);
8220     else if (operands[1] == const0_rtx)
8221       return \"bl\\t%__interwork_call_via_%0\";
8222     else if (frame_pointer_needed)
8223       return \"bl\\t%__interwork_r7_call_via_%0\";
8224     else
8225       return \"bl\\t%__interwork_r11_call_via_%0\";
8226   }"
8227   [(set_attr "type" "call")]
8228 )
8229
8230 (define_expand "call_value"
8231   [(parallel [(set (match_operand       0 "" "")
8232                    (call (match_operand 1 "memory_operand" "")
8233                          (match_operand 2 "general_operand" "")))
8234               (use (match_operand 3 "" ""))
8235               (clobber (reg:SI LR_REGNUM))])]
8236   "TARGET_EITHER"
8237   "
8238   {
8239     rtx callee = XEXP (operands[1], 0);
8240     
8241     /* In an untyped call, we can get NULL for operand 2.  */
8242     if (operands[3] == 0)
8243       operands[3] = const0_rtx;
8244       
8245     /* See the comment in define_expand \"call\".  */
8246     if ((GET_CODE (callee) == SYMBOL_REF
8247          && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
8248         || (GET_CODE (callee) != SYMBOL_REF
8249             && GET_CODE (callee) != REG))
8250       XEXP (operands[1], 0) = force_reg (Pmode, callee);
8251   }"
8252 )
8253
8254 (define_insn "*call_value_reg_armv5"
8255   [(set (match_operand 0 "" "")
8256         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8257               (match_operand 2 "" "")))
8258    (use (match_operand 3 "" ""))
8259    (clobber (reg:SI LR_REGNUM))]
8260   "TARGET_ARM && arm_arch5"
8261   "blx%?\\t%1"
8262   [(set_attr "type" "call")]
8263 )
8264
8265 (define_insn "*call_value_reg_arm"
8266   [(set (match_operand 0 "" "")
8267         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8268               (match_operand 2 "" "")))
8269    (use (match_operand 3 "" ""))
8270    (clobber (reg:SI LR_REGNUM))]
8271   "TARGET_ARM && !arm_arch5"
8272   "*
8273   return output_call (&operands[1]);
8274   "
8275   [(set_attr "length" "12")
8276    (set_attr "type" "call")]
8277 )
8278
8279 (define_insn "*call_value_mem"
8280   [(set (match_operand 0 "" "")
8281         (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
8282               (match_operand 2 "" "")))
8283    (use (match_operand 3 "" ""))
8284    (clobber (reg:SI LR_REGNUM))]
8285   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
8286   "*
8287   return output_call_mem (&operands[1]);
8288   "
8289   [(set_attr "length" "12")
8290    (set_attr "type" "call")]
8291 )
8292
8293 (define_insn "*call_value_reg_thumb1_v5"
8294   [(set (match_operand 0 "" "")
8295         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8296               (match_operand 2 "" "")))
8297    (use (match_operand 3 "" ""))
8298    (clobber (reg:SI LR_REGNUM))]
8299   "TARGET_THUMB1 && arm_arch5"
8300   "blx\\t%1"
8301   [(set_attr "length" "2")
8302    (set_attr "type" "call")]
8303 )
8304
8305 (define_insn "*call_value_reg_thumb1"
8306   [(set (match_operand 0 "" "")
8307         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8308               (match_operand 2 "" "")))
8309    (use (match_operand 3 "" ""))
8310    (clobber (reg:SI LR_REGNUM))]
8311   "TARGET_THUMB1 && !arm_arch5"
8312   "*
8313   {
8314     if (!TARGET_CALLER_INTERWORKING)
8315       return thumb_call_via_reg (operands[1]);
8316     else if (operands[2] == const0_rtx)
8317       return \"bl\\t%__interwork_call_via_%1\";
8318     else if (frame_pointer_needed)
8319       return \"bl\\t%__interwork_r7_call_via_%1\";
8320     else
8321       return \"bl\\t%__interwork_r11_call_via_%1\";
8322   }"
8323   [(set_attr "type" "call")]
8324 )
8325
8326 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8327 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8328
8329 (define_insn "*call_symbol"
8330   [(call (mem:SI (match_operand:SI 0 "" ""))
8331          (match_operand 1 "" ""))
8332    (use (match_operand 2 "" ""))
8333    (clobber (reg:SI LR_REGNUM))]
8334   "TARGET_ARM
8335    && (GET_CODE (operands[0]) == SYMBOL_REF)
8336    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
8337   "*
8338   {
8339     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
8340   }"
8341   [(set_attr "type" "call")]
8342 )
8343
8344 (define_insn "*call_value_symbol"
8345   [(set (match_operand 0 "" "")
8346         (call (mem:SI (match_operand:SI 1 "" ""))
8347         (match_operand:SI 2 "" "")))
8348    (use (match_operand 3 "" ""))
8349    (clobber (reg:SI LR_REGNUM))]
8350   "TARGET_ARM
8351    && (GET_CODE (operands[1]) == SYMBOL_REF)
8352    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
8353   "*
8354   {
8355     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
8356   }"
8357   [(set_attr "type" "call")]
8358 )
8359
8360 (define_insn "*call_insn"
8361   [(call (mem:SI (match_operand:SI 0 "" ""))
8362          (match_operand:SI 1 "" ""))
8363    (use (match_operand 2 "" ""))
8364    (clobber (reg:SI LR_REGNUM))]
8365   "TARGET_THUMB
8366    && GET_CODE (operands[0]) == SYMBOL_REF
8367    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
8368   "bl\\t%a0"
8369   [(set_attr "length" "4")
8370    (set_attr "type" "call")]
8371 )
8372
8373 (define_insn "*call_value_insn"
8374   [(set (match_operand 0 "" "")
8375         (call (mem:SI (match_operand 1 "" ""))
8376               (match_operand 2 "" "")))
8377    (use (match_operand 3 "" ""))
8378    (clobber (reg:SI LR_REGNUM))]
8379   "TARGET_THUMB
8380    && GET_CODE (operands[1]) == SYMBOL_REF
8381    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
8382   "bl\\t%a1"
8383   [(set_attr "length" "4")
8384    (set_attr "type" "call")]
8385 )
8386
8387 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
8388 (define_expand "sibcall"
8389   [(parallel [(call (match_operand 0 "memory_operand" "")
8390                     (match_operand 1 "general_operand" ""))
8391               (return)
8392               (use (match_operand 2 "" ""))])]
8393   "TARGET_ARM"
8394   "
8395   {
8396     if (operands[2] == NULL_RTX)
8397       operands[2] = const0_rtx;
8398   }"
8399 )
8400
8401 (define_expand "sibcall_value"
8402   [(parallel [(set (match_operand 0 "" "")
8403                    (call (match_operand 1 "memory_operand" "")
8404                          (match_operand 2 "general_operand" "")))
8405               (return)
8406               (use (match_operand 3 "" ""))])]
8407   "TARGET_ARM"
8408   "
8409   {
8410     if (operands[3] == NULL_RTX)
8411       operands[3] = const0_rtx;
8412   }"
8413 )
8414
8415 (define_insn "*sibcall_insn"
8416  [(call (mem:SI (match_operand:SI 0 "" "X"))
8417         (match_operand 1 "" ""))
8418   (return)
8419   (use (match_operand 2 "" ""))]
8420   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
8421   "*
8422   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8423   "
8424   [(set_attr "type" "call")]
8425 )
8426
8427 (define_insn "*sibcall_value_insn"
8428  [(set (match_operand 0 "" "")
8429        (call (mem:SI (match_operand:SI 1 "" "X"))
8430              (match_operand 2 "" "")))
8431   (return)
8432   (use (match_operand 3 "" ""))]
8433   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
8434   "*
8435   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8436   "
8437   [(set_attr "type" "call")]
8438 )
8439
8440 ;; Often the return insn will be the same as loading from memory, so set attr
8441 (define_insn "return"
8442   [(return)]
8443   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
8444   "*
8445   {
8446     if (arm_ccfsm_state == 2)
8447       {
8448         arm_ccfsm_state += 2;
8449         return \"\";
8450       }
8451     return output_return_instruction (const_true_rtx, TRUE, FALSE);
8452   }"
8453   [(set_attr "type" "load1")
8454    (set_attr "length" "12")
8455    (set_attr "predicable" "yes")]
8456 )
8457
8458 (define_insn "*cond_return"
8459   [(set (pc)
8460         (if_then_else (match_operator 0 "arm_comparison_operator"
8461                        [(match_operand 1 "cc_register" "") (const_int 0)])
8462                       (return)
8463                       (pc)))]
8464   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
8465   "*
8466   {
8467     if (arm_ccfsm_state == 2)
8468       {
8469         arm_ccfsm_state += 2;
8470         return \"\";
8471       }
8472     return output_return_instruction (operands[0], TRUE, FALSE);
8473   }"
8474   [(set_attr "conds" "use")
8475    (set_attr "length" "12")
8476    (set_attr "type" "load1")]
8477 )
8478
8479 (define_insn "*cond_return_inverted"
8480   [(set (pc)
8481         (if_then_else (match_operator 0 "arm_comparison_operator"
8482                        [(match_operand 1 "cc_register" "") (const_int 0)])
8483                       (pc)
8484                       (return)))]
8485   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
8486   "*
8487   {
8488     if (arm_ccfsm_state == 2)
8489       {
8490         arm_ccfsm_state += 2;
8491         return \"\";
8492       }
8493     return output_return_instruction (operands[0], TRUE, TRUE);
8494   }"
8495   [(set_attr "conds" "use")
8496    (set_attr "length" "12")
8497    (set_attr "type" "load1")]
8498 )
8499
8500 ;; Generate a sequence of instructions to determine if the processor is
8501 ;; in 26-bit or 32-bit mode, and return the appropriate return address
8502 ;; mask.
8503
8504 (define_expand "return_addr_mask"
8505   [(set (match_dup 1)
8506       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8507                        (const_int 0)))
8508    (set (match_operand:SI 0 "s_register_operand" "")
8509       (if_then_else:SI (eq (match_dup 1) (const_int 0))
8510                        (const_int -1)
8511                        (const_int 67108860)))] ; 0x03fffffc
8512   "TARGET_ARM"
8513   "
8514   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
8515   ")
8516
8517 (define_insn "*check_arch2"
8518   [(set (match_operand:CC_NOOV 0 "cc_register" "")
8519       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8520                        (const_int 0)))]
8521   "TARGET_ARM"
8522   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8523   [(set_attr "length" "8")
8524    (set_attr "conds" "set")]
8525 )
8526
8527 ;; Call subroutine returning any type.
8528
8529 (define_expand "untyped_call"
8530   [(parallel [(call (match_operand 0 "" "")
8531                     (const_int 0))
8532               (match_operand 1 "" "")
8533               (match_operand 2 "" "")])]
8534   "TARGET_EITHER"
8535   "
8536   {
8537     int i;
8538     rtx par = gen_rtx_PARALLEL (VOIDmode,
8539                                 rtvec_alloc (XVECLEN (operands[2], 0)));
8540     rtx addr = gen_reg_rtx (Pmode);
8541     rtx mem;
8542     int size = 0;
8543
8544     emit_move_insn (addr, XEXP (operands[1], 0));
8545     mem = change_address (operands[1], BLKmode, addr);
8546
8547     for (i = 0; i < XVECLEN (operands[2], 0); i++)
8548       {
8549         rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
8550
8551         /* Default code only uses r0 as a return value, but we could
8552            be using anything up to 4 registers.  */
8553         if (REGNO (src) == R0_REGNUM)
8554           src = gen_rtx_REG (TImode, R0_REGNUM);
8555
8556         XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8557                                                  GEN_INT (size));
8558         size += GET_MODE_SIZE (GET_MODE (src));
8559       }
8560
8561     emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8562                                     const0_rtx));
8563
8564     size = 0;
8565
8566     for (i = 0; i < XVECLEN (par, 0); i++)
8567       {
8568         HOST_WIDE_INT offset = 0;
8569         rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8570
8571         if (size != 0)
8572           emit_move_insn (addr, plus_constant (addr, size));
8573
8574         mem = change_address (mem, GET_MODE (reg), NULL);
8575         if (REGNO (reg) == R0_REGNUM)
8576           {
8577             /* On thumb we have to use a write-back instruction.  */
8578             emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
8579                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8580             size = TARGET_ARM ? 16 : 0;
8581           }
8582         else
8583           {
8584             emit_move_insn (mem, reg);
8585             size = GET_MODE_SIZE (GET_MODE (reg));
8586           }
8587       }
8588
8589     /* The optimizer does not know that the call sets the function value
8590        registers we stored in the result block.  We avoid problems by
8591        claiming that all hard registers are used and clobbered at this
8592        point.  */
8593     emit_insn (gen_blockage ());
8594
8595     DONE;
8596   }"
8597 )
8598
8599 (define_expand "untyped_return"
8600   [(match_operand:BLK 0 "memory_operand" "")
8601    (match_operand 1 "" "")]
8602   "TARGET_EITHER"
8603   "
8604   {
8605     int i;
8606     rtx addr = gen_reg_rtx (Pmode);
8607     rtx mem;
8608     int size = 0;
8609
8610     emit_move_insn (addr, XEXP (operands[0], 0));
8611     mem = change_address (operands[0], BLKmode, addr);
8612
8613     for (i = 0; i < XVECLEN (operands[1], 0); i++)
8614       {
8615         HOST_WIDE_INT offset = 0;
8616         rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8617
8618         if (size != 0)
8619           emit_move_insn (addr, plus_constant (addr, size));
8620
8621         mem = change_address (mem, GET_MODE (reg), NULL);
8622         if (REGNO (reg) == R0_REGNUM)
8623           {
8624             /* On thumb we have to use a write-back instruction.  */
8625             emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
8626                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8627             size = TARGET_ARM ? 16 : 0;
8628           }
8629         else
8630           {
8631             emit_move_insn (reg, mem);
8632             size = GET_MODE_SIZE (GET_MODE (reg));
8633           }
8634       }
8635
8636     /* Emit USE insns before the return.  */
8637     for (i = 0; i < XVECLEN (operands[1], 0); i++)
8638       emit_insn (gen_rtx_USE (VOIDmode,
8639                               SET_DEST (XVECEXP (operands[1], 0, i))));
8640
8641     /* Construct the return.  */
8642     expand_naked_return ();
8643
8644     DONE;
8645   }"
8646 )
8647
8648 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8649 ;; all of memory.  This blocks insns from being moved across this point.
8650
8651 (define_insn "blockage"
8652   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
8653   "TARGET_EITHER"
8654   ""
8655   [(set_attr "length" "0")
8656    (set_attr "type" "block")]
8657 )
8658
8659 (define_expand "casesi"
8660   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
8661    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
8662    (match_operand:SI 2 "const_int_operand" "")  ; total range
8663    (match_operand:SI 3 "" "")                   ; table label
8664    (match_operand:SI 4 "" "")]                  ; Out of range label
8665   "TARGET_32BIT"
8666   "
8667   {
8668     rtx reg;
8669     if (operands[1] != const0_rtx)
8670       {
8671         reg = gen_reg_rtx (SImode);
8672
8673         emit_insn (gen_addsi3 (reg, operands[0],
8674                                GEN_INT (-INTVAL (operands[1]))));
8675         operands[0] = reg;
8676       }
8677
8678     if (!const_ok_for_arm (INTVAL (operands[2])))
8679       operands[2] = force_reg (SImode, operands[2]);
8680
8681     if (TARGET_ARM)
8682       {
8683         emit_jump_insn (gen_arm_casesi_internal (operands[0], operands[2],
8684                                                  operands[3], operands[4]));
8685       }
8686     else if (flag_pic)
8687       {
8688         emit_jump_insn (gen_thumb2_casesi_internal_pic (operands[0],
8689             operands[2], operands[3], operands[4]));
8690       }
8691     else
8692       {
8693         emit_jump_insn (gen_thumb2_casesi_internal (operands[0], operands[2],
8694                                                     operands[3], operands[4]));
8695       }
8696     DONE;
8697   }"
8698 )
8699
8700 ;; The USE in this pattern is needed to tell flow analysis that this is
8701 ;; a CASESI insn.  It has no other purpose.
8702 (define_insn "arm_casesi_internal"
8703   [(parallel [(set (pc)
8704                (if_then_else
8705                 (leu (match_operand:SI 0 "s_register_operand" "r")
8706                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
8707                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8708                                  (label_ref (match_operand 2 "" ""))))
8709                 (label_ref (match_operand 3 "" ""))))
8710               (clobber (reg:CC CC_REGNUM))
8711               (use (label_ref (match_dup 2)))])]
8712   "TARGET_ARM"
8713   "*
8714     if (flag_pic)
8715       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8716     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8717   "
8718   [(set_attr "conds" "clob")
8719    (set_attr "length" "12")]
8720 )
8721
8722 (define_expand "indirect_jump"
8723   [(set (pc)
8724         (match_operand:SI 0 "s_register_operand" ""))]
8725   "TARGET_EITHER"
8726   "
8727   /* Thumb-2 doesn't have mov pc, reg.  Explicitly set the low bit of the
8728      address and use bx.  */
8729   if (TARGET_THUMB2)
8730     {
8731       rtx tmp;
8732       tmp = gen_reg_rtx (SImode);
8733       emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8734       operands[0] = tmp;
8735     }
8736   "
8737 )
8738
8739 ;; NB Never uses BX.
8740 (define_insn "*arm_indirect_jump"
8741   [(set (pc)
8742         (match_operand:SI 0 "s_register_operand" "r"))]
8743   "TARGET_ARM"
8744   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
8745   [(set_attr "predicable" "yes")]
8746 )
8747
8748 (define_insn "*load_indirect_jump"
8749   [(set (pc)
8750         (match_operand:SI 0 "memory_operand" "m"))]
8751   "TARGET_ARM"
8752   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
8753   [(set_attr "type" "load1")
8754    (set_attr "pool_range" "4096")
8755    (set_attr "neg_pool_range" "4084")
8756    (set_attr "predicable" "yes")]
8757 )
8758
8759 ;; NB Never uses BX.
8760 (define_insn "*thumb1_indirect_jump"
8761   [(set (pc)
8762         (match_operand:SI 0 "register_operand" "l*r"))]
8763   "TARGET_THUMB1"
8764   "mov\\tpc, %0"
8765   [(set_attr "conds" "clob")
8766    (set_attr "length" "2")]
8767 )
8768
8769 \f
8770 ;; Misc insns
8771
8772 (define_insn "nop"
8773   [(const_int 0)]
8774   "TARGET_EITHER"
8775   "*
8776   if (TARGET_UNIFIED_ASM)
8777     return \"nop\";
8778   if (TARGET_ARM)
8779     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8780   return  \"mov\\tr8, r8\";
8781   "
8782   [(set (attr "length")
8783         (if_then_else (eq_attr "is_thumb" "yes")
8784                       (const_int 2)
8785                       (const_int 4)))]
8786 )
8787
8788 \f
8789 ;; Patterns to allow combination of arithmetic, cond code and shifts
8790
8791 (define_insn "*arith_shiftsi"
8792   [(set (match_operand:SI 0 "s_register_operand" "=r")
8793         (match_operator:SI 1 "shiftable_operator"
8794           [(match_operator:SI 3 "shift_operator"
8795              [(match_operand:SI 4 "s_register_operand" "r")
8796               (match_operand:SI 5 "reg_or_int_operand" "rI")])
8797            (match_operand:SI 2 "s_register_operand" "r")]))]
8798   "TARGET_ARM"
8799   "%i1%?\\t%0, %2, %4%S3"
8800   [(set_attr "predicable" "yes")
8801    (set_attr "shift" "4")
8802    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8803                       (const_string "alu_shift")
8804                       (const_string "alu_shift_reg")))]
8805 )
8806
8807 (define_split
8808   [(set (match_operand:SI 0 "s_register_operand" "")
8809         (match_operator:SI 1 "shiftable_operator"
8810          [(match_operator:SI 2 "shiftable_operator"
8811            [(match_operator:SI 3 "shift_operator"
8812              [(match_operand:SI 4 "s_register_operand" "")
8813               (match_operand:SI 5 "reg_or_int_operand" "")])
8814             (match_operand:SI 6 "s_register_operand" "")])
8815           (match_operand:SI 7 "arm_rhs_operand" "")]))
8816    (clobber (match_operand:SI 8 "s_register_operand" ""))]
8817   "TARGET_ARM"
8818   [(set (match_dup 8)
8819         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8820                          (match_dup 6)]))
8821    (set (match_dup 0)
8822         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8823   "")
8824
8825 (define_insn "*arith_shiftsi_compare0"
8826   [(set (reg:CC_NOOV CC_REGNUM)
8827         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8828                           [(match_operator:SI 3 "shift_operator"
8829                             [(match_operand:SI 4 "s_register_operand" "r")
8830                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8831                            (match_operand:SI 2 "s_register_operand" "r")])
8832                          (const_int 0)))
8833    (set (match_operand:SI 0 "s_register_operand" "=r")
8834         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8835                          (match_dup 2)]))]
8836   "TARGET_ARM"
8837   "%i1%.\\t%0, %2, %4%S3"
8838   [(set_attr "conds" "set")
8839    (set_attr "shift" "4")
8840    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8841                       (const_string "alu_shift")
8842                       (const_string "alu_shift_reg")))]
8843 )
8844
8845 (define_insn "*arith_shiftsi_compare0_scratch"
8846   [(set (reg:CC_NOOV CC_REGNUM)
8847         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8848                           [(match_operator:SI 3 "shift_operator"
8849                             [(match_operand:SI 4 "s_register_operand" "r")
8850                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8851                            (match_operand:SI 2 "s_register_operand" "r")])
8852                          (const_int 0)))
8853    (clobber (match_scratch:SI 0 "=r"))]
8854   "TARGET_ARM"
8855   "%i1%.\\t%0, %2, %4%S3"
8856   [(set_attr "conds" "set")
8857    (set_attr "shift" "4")
8858    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8859                       (const_string "alu_shift")
8860                       (const_string "alu_shift_reg")))]
8861 )
8862
8863 (define_insn "*sub_shiftsi"
8864   [(set (match_operand:SI 0 "s_register_operand" "=r")
8865         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8866                   (match_operator:SI 2 "shift_operator"
8867                    [(match_operand:SI 3 "s_register_operand" "r")
8868                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
8869   "TARGET_ARM"
8870   "sub%?\\t%0, %1, %3%S2"
8871   [(set_attr "predicable" "yes")
8872    (set_attr "shift" "3")
8873    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8874                       (const_string "alu_shift")
8875                       (const_string "alu_shift_reg")))]
8876 )
8877
8878 (define_insn "*sub_shiftsi_compare0"
8879   [(set (reg:CC_NOOV CC_REGNUM)
8880         (compare:CC_NOOV
8881          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8882                    (match_operator:SI 2 "shift_operator"
8883                     [(match_operand:SI 3 "s_register_operand" "r")
8884                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8885          (const_int 0)))
8886    (set (match_operand:SI 0 "s_register_operand" "=r")
8887         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8888                                                  (match_dup 4)])))]
8889   "TARGET_ARM"
8890   "sub%.\\t%0, %1, %3%S2"
8891   [(set_attr "conds" "set")
8892    (set_attr "shift" "3")
8893    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8894                       (const_string "alu_shift")
8895                       (const_string "alu_shift_reg")))]
8896 )
8897
8898 (define_insn "*sub_shiftsi_compare0_scratch"
8899   [(set (reg:CC_NOOV CC_REGNUM)
8900         (compare:CC_NOOV
8901          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8902                    (match_operator:SI 2 "shift_operator"
8903                     [(match_operand:SI 3 "s_register_operand" "r")
8904                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8905          (const_int 0)))
8906    (clobber (match_scratch:SI 0 "=r"))]
8907   "TARGET_ARM"
8908   "sub%.\\t%0, %1, %3%S2"
8909   [(set_attr "conds" "set")
8910    (set_attr "shift" "3")
8911    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8912                       (const_string "alu_shift")
8913                       (const_string "alu_shift_reg")))]
8914 )
8915
8916 \f
8917
8918 (define_insn "*and_scc"
8919   [(set (match_operand:SI 0 "s_register_operand" "=r")
8920         (and:SI (match_operator:SI 1 "arm_comparison_operator"
8921                  [(match_operand 3 "cc_register" "") (const_int 0)])
8922                 (match_operand:SI 2 "s_register_operand" "r")))]
8923   "TARGET_ARM"
8924   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8925   [(set_attr "conds" "use")
8926    (set_attr "length" "8")]
8927 )
8928
8929 (define_insn "*ior_scc"
8930   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8931         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8932                  [(match_operand 3 "cc_register" "") (const_int 0)])
8933                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8934   "TARGET_ARM"
8935   "@
8936    orr%d2\\t%0, %1, #1
8937    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8938   [(set_attr "conds" "use")
8939    (set_attr "length" "4,8")]
8940 )
8941
8942 (define_insn "*compare_scc"
8943   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8944         (match_operator:SI 1 "arm_comparison_operator"
8945          [(match_operand:SI 2 "s_register_operand" "r,r")
8946           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8947    (clobber (reg:CC CC_REGNUM))]
8948   "TARGET_ARM"
8949   "*
8950     if (operands[3] == const0_rtx)
8951       {
8952         if (GET_CODE (operands[1]) == LT)
8953           return \"mov\\t%0, %2, lsr #31\";
8954
8955         if (GET_CODE (operands[1]) == GE)
8956           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8957
8958         if (GET_CODE (operands[1]) == EQ)
8959           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8960       }
8961
8962     if (GET_CODE (operands[1]) == NE)
8963       {
8964         if (which_alternative == 1)
8965           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8966         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8967       }
8968     if (which_alternative == 1)
8969       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8970     else
8971       output_asm_insn (\"cmp\\t%2, %3\", operands);
8972     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8973   "
8974   [(set_attr "conds" "clob")
8975    (set_attr "length" "12")]
8976 )
8977
8978 (define_insn "*cond_move"
8979   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8980         (if_then_else:SI (match_operator 3 "equality_operator"
8981                           [(match_operator 4 "arm_comparison_operator"
8982                             [(match_operand 5 "cc_register" "") (const_int 0)])
8983                            (const_int 0)])
8984                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8985                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8986   "TARGET_ARM"
8987   "*
8988     if (GET_CODE (operands[3]) == NE)
8989       {
8990         if (which_alternative != 1)
8991           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8992         if (which_alternative != 0)
8993           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8994         return \"\";
8995       }
8996     if (which_alternative != 0)
8997       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8998     if (which_alternative != 1)
8999       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
9000     return \"\";
9001   "
9002   [(set_attr "conds" "use")
9003    (set_attr "length" "4,4,8")]
9004 )
9005
9006 (define_insn "*cond_arith"
9007   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9008         (match_operator:SI 5 "shiftable_operator" 
9009          [(match_operator:SI 4 "arm_comparison_operator"
9010            [(match_operand:SI 2 "s_register_operand" "r,r")
9011             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9012           (match_operand:SI 1 "s_register_operand" "0,?r")]))
9013    (clobber (reg:CC CC_REGNUM))]
9014   "TARGET_ARM"
9015   "*
9016     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
9017       return \"%i5\\t%0, %1, %2, lsr #31\";
9018
9019     output_asm_insn (\"cmp\\t%2, %3\", operands);
9020     if (GET_CODE (operands[5]) == AND)
9021       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
9022     else if (GET_CODE (operands[5]) == MINUS)
9023       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
9024     else if (which_alternative != 0)
9025       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9026     return \"%i5%d4\\t%0, %1, #1\";
9027   "
9028   [(set_attr "conds" "clob")
9029    (set_attr "length" "12")]
9030 )
9031
9032 (define_insn "*cond_sub"
9033   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9034         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
9035                   (match_operator:SI 4 "arm_comparison_operator"
9036                    [(match_operand:SI 2 "s_register_operand" "r,r")
9037                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
9038    (clobber (reg:CC CC_REGNUM))]
9039   "TARGET_ARM"
9040   "*
9041     output_asm_insn (\"cmp\\t%2, %3\", operands);
9042     if (which_alternative != 0)
9043       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9044     return \"sub%d4\\t%0, %1, #1\";
9045   "
9046   [(set_attr "conds" "clob")
9047    (set_attr "length" "8,12")]
9048 )
9049
9050 ;; ??? Is it worth using these conditional patterns in Thumb-2 mode?
9051 (define_insn "*cmp_ite0"
9052   [(set (match_operand 6 "dominant_cc_register" "")
9053         (compare
9054          (if_then_else:SI
9055           (match_operator 4 "arm_comparison_operator"
9056            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9057             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9058           (match_operator:SI 5 "arm_comparison_operator"
9059            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9060             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
9061           (const_int 0))
9062          (const_int 0)))]
9063   "TARGET_ARM"
9064   "*
9065   {
9066     static const char * const opcodes[4][2] =
9067     {
9068       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9069        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9070       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9071        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9072       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9073        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9074       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9075        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9076     };
9077     int swap =
9078       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9079
9080     return opcodes[which_alternative][swap];
9081   }"
9082   [(set_attr "conds" "set")
9083    (set_attr "length" "8")]
9084 )
9085
9086 (define_insn "*cmp_ite1"
9087   [(set (match_operand 6 "dominant_cc_register" "")
9088         (compare
9089          (if_then_else:SI
9090           (match_operator 4 "arm_comparison_operator"
9091            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9092             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9093           (match_operator:SI 5 "arm_comparison_operator"
9094            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9095             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
9096           (const_int 1))
9097          (const_int 0)))]
9098   "TARGET_ARM"
9099   "*
9100   {
9101     static const char * const opcodes[4][2] =
9102     {
9103       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
9104        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9105       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
9106        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9107       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
9108        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9109       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
9110        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9111     };
9112     int swap =
9113       comparison_dominates_p (GET_CODE (operands[5]),
9114                               reverse_condition (GET_CODE (operands[4])));
9115
9116     return opcodes[which_alternative][swap];
9117   }"
9118   [(set_attr "conds" "set")
9119    (set_attr "length" "8")]
9120 )
9121
9122 (define_insn "*cmp_and"
9123   [(set (match_operand 6 "dominant_cc_register" "")
9124         (compare
9125          (and:SI
9126           (match_operator 4 "arm_comparison_operator"
9127            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9128             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9129           (match_operator:SI 5 "arm_comparison_operator"
9130            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9131             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9132          (const_int 0)))]
9133   "TARGET_ARM"
9134   "*
9135   {
9136     static const char *const opcodes[4][2] =
9137     {
9138       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9139        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9140       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9141        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9142       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9143        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9144       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9145        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9146     };
9147     int swap =
9148       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9149
9150     return opcodes[which_alternative][swap];
9151   }"
9152   [(set_attr "conds" "set")
9153    (set_attr "predicable" "no")
9154    (set_attr "length" "8")]
9155 )
9156
9157 (define_insn "*cmp_ior"
9158   [(set (match_operand 6 "dominant_cc_register" "")
9159         (compare
9160          (ior:SI
9161           (match_operator 4 "arm_comparison_operator"
9162            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9163             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9164           (match_operator:SI 5 "arm_comparison_operator"
9165            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9166             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9167          (const_int 0)))]
9168   "TARGET_ARM"
9169   "*
9170 {
9171   static const char *const opcodes[4][2] =
9172   {
9173     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
9174      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9175     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
9176      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9177     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
9178      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9179     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
9180      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9181   };
9182   int swap =
9183     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9184
9185   return opcodes[which_alternative][swap];
9186 }
9187 "
9188   [(set_attr "conds" "set")
9189    (set_attr "length" "8")]
9190 )
9191
9192 (define_insn_and_split "*ior_scc_scc"
9193   [(set (match_operand:SI 0 "s_register_operand" "=r")
9194         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9195                  [(match_operand:SI 1 "s_register_operand" "r")
9196                   (match_operand:SI 2 "arm_add_operand" "rIL")])
9197                 (match_operator:SI 6 "arm_comparison_operator"
9198                  [(match_operand:SI 4 "s_register_operand" "r")
9199                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
9200    (clobber (reg:CC CC_REGNUM))]
9201   "TARGET_ARM
9202    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9203        != CCmode)"
9204   "#"
9205   "TARGET_ARM && reload_completed"
9206   [(set (match_dup 7)
9207         (compare
9208          (ior:SI
9209           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9210           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9211          (const_int 0)))
9212    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9213   "operands[7]
9214      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9215                                                   DOM_CC_X_OR_Y),
9216                     CC_REGNUM);"
9217   [(set_attr "conds" "clob")
9218    (set_attr "length" "16")])
9219
9220 ; If the above pattern is followed by a CMP insn, then the compare is 
9221 ; redundant, since we can rework the conditional instruction that follows.
9222 (define_insn_and_split "*ior_scc_scc_cmp"
9223   [(set (match_operand 0 "dominant_cc_register" "")
9224         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9225                           [(match_operand:SI 1 "s_register_operand" "r")
9226                            (match_operand:SI 2 "arm_add_operand" "rIL")])
9227                          (match_operator:SI 6 "arm_comparison_operator"
9228                           [(match_operand:SI 4 "s_register_operand" "r")
9229                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
9230                  (const_int 0)))
9231    (set (match_operand:SI 7 "s_register_operand" "=r")
9232         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9233                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9234   "TARGET_ARM"
9235   "#"
9236   "TARGET_ARM && reload_completed"
9237   [(set (match_dup 0)
9238         (compare
9239          (ior:SI
9240           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9241           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9242          (const_int 0)))
9243    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9244   ""
9245   [(set_attr "conds" "set")
9246    (set_attr "length" "16")])
9247
9248 (define_insn_and_split "*and_scc_scc"
9249   [(set (match_operand:SI 0 "s_register_operand" "=r")
9250         (and:SI (match_operator:SI 3 "arm_comparison_operator"
9251                  [(match_operand:SI 1 "s_register_operand" "r")
9252                   (match_operand:SI 2 "arm_add_operand" "rIL")])
9253                 (match_operator:SI 6 "arm_comparison_operator"
9254                  [(match_operand:SI 4 "s_register_operand" "r")
9255                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
9256    (clobber (reg:CC CC_REGNUM))]
9257   "TARGET_ARM
9258    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9259        != CCmode)"
9260   "#"
9261   "TARGET_ARM && reload_completed
9262    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9263        != CCmode)"
9264   [(set (match_dup 7)
9265         (compare
9266          (and:SI
9267           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9268           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9269          (const_int 0)))
9270    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9271   "operands[7]
9272      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9273                                                   DOM_CC_X_AND_Y),
9274                     CC_REGNUM);"
9275   [(set_attr "conds" "clob")
9276    (set_attr "length" "16")])
9277
9278 ; If the above pattern is followed by a CMP insn, then the compare is 
9279 ; redundant, since we can rework the conditional instruction that follows.
9280 (define_insn_and_split "*and_scc_scc_cmp"
9281   [(set (match_operand 0 "dominant_cc_register" "")
9282         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9283                           [(match_operand:SI 1 "s_register_operand" "r")
9284                            (match_operand:SI 2 "arm_add_operand" "rIL")])
9285                          (match_operator:SI 6 "arm_comparison_operator"
9286                           [(match_operand:SI 4 "s_register_operand" "r")
9287                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
9288                  (const_int 0)))
9289    (set (match_operand:SI 7 "s_register_operand" "=r")
9290         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9291                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9292   "TARGET_ARM"
9293   "#"
9294   "TARGET_ARM && reload_completed"
9295   [(set (match_dup 0)
9296         (compare
9297          (and:SI
9298           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9299           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9300          (const_int 0)))
9301    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9302   ""
9303   [(set_attr "conds" "set")
9304    (set_attr "length" "16")])
9305
9306 ;; If there is no dominance in the comparison, then we can still save an
9307 ;; instruction in the AND case, since we can know that the second compare
9308 ;; need only zero the value if false (if true, then the value is already
9309 ;; correct).
9310 (define_insn_and_split "*and_scc_scc_nodom"
9311   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
9312         (and:SI (match_operator:SI 3 "arm_comparison_operator"
9313                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
9314                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9315                 (match_operator:SI 6 "arm_comparison_operator"
9316                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
9317                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9318    (clobber (reg:CC CC_REGNUM))]
9319   "TARGET_ARM
9320    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9321        == CCmode)"
9322   "#"
9323   "TARGET_ARM && reload_completed"
9324   [(parallel [(set (match_dup 0)
9325                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9326               (clobber (reg:CC CC_REGNUM))])
9327    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9328    (set (match_dup 0)
9329         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9330                          (match_dup 0)
9331                          (const_int 0)))]
9332   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9333                                               operands[4], operands[5]),
9334                               CC_REGNUM);
9335    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9336                                   operands[5]);"
9337   [(set_attr "conds" "clob")
9338    (set_attr "length" "20")])
9339
9340 (define_split
9341   [(set (reg:CC_NOOV CC_REGNUM)
9342         (compare:CC_NOOV (ior:SI
9343                           (and:SI (match_operand:SI 0 "s_register_operand" "")
9344                                   (const_int 1))
9345                           (match_operator:SI 1 "comparison_operator"
9346                            [(match_operand:SI 2 "s_register_operand" "")
9347                             (match_operand:SI 3 "arm_add_operand" "")]))
9348                          (const_int 0)))
9349    (clobber (match_operand:SI 4 "s_register_operand" ""))]
9350   "TARGET_ARM"
9351   [(set (match_dup 4)
9352         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9353                 (match_dup 0)))
9354    (set (reg:CC_NOOV CC_REGNUM)
9355         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9356                          (const_int 0)))]
9357   "")
9358
9359 (define_split
9360   [(set (reg:CC_NOOV CC_REGNUM)
9361         (compare:CC_NOOV (ior:SI
9362                           (match_operator:SI 1 "comparison_operator"
9363                            [(match_operand:SI 2 "s_register_operand" "")
9364                             (match_operand:SI 3 "arm_add_operand" "")])
9365                           (and:SI (match_operand:SI 0 "s_register_operand" "")
9366                                   (const_int 1)))
9367                          (const_int 0)))
9368    (clobber (match_operand:SI 4 "s_register_operand" ""))]
9369   "TARGET_ARM"
9370   [(set (match_dup 4)
9371         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9372                 (match_dup 0)))
9373    (set (reg:CC_NOOV CC_REGNUM)
9374         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9375                          (const_int 0)))]
9376   "")
9377 ;; ??? The conditional patterns above need checking for Thumb-2 usefulness
9378
9379 (define_insn "*negscc"
9380   [(set (match_operand:SI 0 "s_register_operand" "=r")
9381         (neg:SI (match_operator 3 "arm_comparison_operator"
9382                  [(match_operand:SI 1 "s_register_operand" "r")
9383                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
9384    (clobber (reg:CC CC_REGNUM))]
9385   "TARGET_ARM"
9386   "*
9387   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
9388     return \"mov\\t%0, %1, asr #31\";
9389
9390   if (GET_CODE (operands[3]) == NE)
9391     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9392
9393   if (GET_CODE (operands[3]) == GT)
9394     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
9395
9396   output_asm_insn (\"cmp\\t%1, %2\", operands);
9397   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9398   return \"mvn%d3\\t%0, #0\";
9399   "
9400   [(set_attr "conds" "clob")
9401    (set_attr "length" "12")]
9402 )
9403
9404 (define_insn "movcond"
9405   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9406         (if_then_else:SI
9407          (match_operator 5 "arm_comparison_operator"
9408           [(match_operand:SI 3 "s_register_operand" "r,r,r")
9409            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9410          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9411          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
9412    (clobber (reg:CC CC_REGNUM))]
9413   "TARGET_ARM"
9414   "*
9415   if (GET_CODE (operands[5]) == LT
9416       && (operands[4] == const0_rtx))
9417     {
9418       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9419         {
9420           if (operands[2] == const0_rtx)
9421             return \"and\\t%0, %1, %3, asr #31\";
9422           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9423         }
9424       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9425         {
9426           if (operands[1] == const0_rtx)
9427             return \"bic\\t%0, %2, %3, asr #31\";
9428           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9429         }
9430       /* The only case that falls through to here is when both ops 1 & 2
9431          are constants.  */
9432     }
9433
9434   if (GET_CODE (operands[5]) == GE
9435       && (operands[4] == const0_rtx))
9436     {
9437       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9438         {
9439           if (operands[2] == const0_rtx)
9440             return \"bic\\t%0, %1, %3, asr #31\";
9441           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9442         }
9443       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9444         {
9445           if (operands[1] == const0_rtx)
9446             return \"and\\t%0, %2, %3, asr #31\";
9447           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9448         }
9449       /* The only case that falls through to here is when both ops 1 & 2
9450          are constants.  */
9451     }
9452   if (GET_CODE (operands[4]) == CONST_INT
9453       && !const_ok_for_arm (INTVAL (operands[4])))
9454     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9455   else
9456     output_asm_insn (\"cmp\\t%3, %4\", operands);
9457   if (which_alternative != 0)
9458     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9459   if (which_alternative != 1)
9460     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9461   return \"\";
9462   "
9463   [(set_attr "conds" "clob")
9464    (set_attr "length" "8,8,12")]
9465 )
9466
9467 ;; ??? The patterns below need checking for Thumb-2 usefulness.
9468
9469 (define_insn "*ifcompare_plus_move"
9470   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9471         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9472                           [(match_operand:SI 4 "s_register_operand" "r,r")
9473                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9474                          (plus:SI
9475                           (match_operand:SI 2 "s_register_operand" "r,r")
9476                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
9477                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9478    (clobber (reg:CC CC_REGNUM))]
9479   "TARGET_ARM"
9480   "#"
9481   [(set_attr "conds" "clob")
9482    (set_attr "length" "8,12")]
9483 )
9484
9485 (define_insn "*if_plus_move"
9486   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9487         (if_then_else:SI
9488          (match_operator 4 "arm_comparison_operator"
9489           [(match_operand 5 "cc_register" "") (const_int 0)])
9490          (plus:SI
9491           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9492           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9493          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
9494   "TARGET_ARM"
9495   "@
9496    add%d4\\t%0, %2, %3
9497    sub%d4\\t%0, %2, #%n3
9498    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
9499    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
9500   [(set_attr "conds" "use")
9501    (set_attr "length" "4,4,8,8")
9502    (set_attr "type" "*,*,*,*")]
9503 )
9504
9505 (define_insn "*ifcompare_move_plus"
9506   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9507         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9508                           [(match_operand:SI 4 "s_register_operand" "r,r")
9509                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9510                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9511                          (plus:SI
9512                           (match_operand:SI 2 "s_register_operand" "r,r")
9513                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
9514    (clobber (reg:CC CC_REGNUM))]
9515   "TARGET_ARM"
9516   "#"
9517   [(set_attr "conds" "clob")
9518    (set_attr "length" "8,12")]
9519 )
9520
9521 (define_insn "*if_move_plus"
9522   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9523         (if_then_else:SI
9524          (match_operator 4 "arm_comparison_operator"
9525           [(match_operand 5 "cc_register" "") (const_int 0)])
9526          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
9527          (plus:SI
9528           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9529           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
9530   "TARGET_ARM"
9531   "@
9532    add%D4\\t%0, %2, %3
9533    sub%D4\\t%0, %2, #%n3
9534    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
9535    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
9536   [(set_attr "conds" "use")
9537    (set_attr "length" "4,4,8,8")
9538    (set_attr "type" "*,*,*,*")]
9539 )
9540
9541 (define_insn "*ifcompare_arith_arith"
9542   [(set (match_operand:SI 0 "s_register_operand" "=r")
9543         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
9544                           [(match_operand:SI 5 "s_register_operand" "r")
9545                            (match_operand:SI 6 "arm_add_operand" "rIL")])
9546                          (match_operator:SI 8 "shiftable_operator"
9547                           [(match_operand:SI 1 "s_register_operand" "r")
9548                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
9549                          (match_operator:SI 7 "shiftable_operator"
9550                           [(match_operand:SI 3 "s_register_operand" "r")
9551                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
9552    (clobber (reg:CC CC_REGNUM))]
9553   "TARGET_ARM"
9554   "#"
9555   [(set_attr "conds" "clob")
9556    (set_attr "length" "12")]
9557 )
9558
9559 (define_insn "*if_arith_arith"
9560   [(set (match_operand:SI 0 "s_register_operand" "=r")
9561         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
9562                           [(match_operand 8 "cc_register" "") (const_int 0)])
9563                          (match_operator:SI 6 "shiftable_operator"
9564                           [(match_operand:SI 1 "s_register_operand" "r")
9565                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
9566                          (match_operator:SI 7 "shiftable_operator"
9567                           [(match_operand:SI 3 "s_register_operand" "r")
9568                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
9569   "TARGET_ARM"
9570   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
9571   [(set_attr "conds" "use")
9572    (set_attr "length" "8")]
9573 )
9574
9575 (define_insn "*ifcompare_arith_move"
9576   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9577         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9578                           [(match_operand:SI 2 "s_register_operand" "r,r")
9579                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9580                          (match_operator:SI 7 "shiftable_operator"
9581                           [(match_operand:SI 4 "s_register_operand" "r,r")
9582                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
9583                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9584    (clobber (reg:CC CC_REGNUM))]
9585   "TARGET_ARM"
9586   "*
9587   /* If we have an operation where (op x 0) is the identity operation and
9588      the conditional operator is LT or GE and we are comparing against zero and
9589      everything is in registers then we can do this in two instructions.  */
9590   if (operands[3] == const0_rtx
9591       && GET_CODE (operands[7]) != AND
9592       && GET_CODE (operands[5]) == REG
9593       && GET_CODE (operands[1]) == REG 
9594       && REGNO (operands[1]) == REGNO (operands[4])
9595       && REGNO (operands[4]) != REGNO (operands[0]))
9596     {
9597       if (GET_CODE (operands[6]) == LT)
9598         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9599       else if (GET_CODE (operands[6]) == GE)
9600         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9601     }
9602   if (GET_CODE (operands[3]) == CONST_INT
9603       && !const_ok_for_arm (INTVAL (operands[3])))
9604     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9605   else
9606     output_asm_insn (\"cmp\\t%2, %3\", operands);
9607   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9608   if (which_alternative != 0)
9609     return \"mov%D6\\t%0, %1\";
9610   return \"\";
9611   "
9612   [(set_attr "conds" "clob")
9613    (set_attr "length" "8,12")]
9614 )
9615
9616 (define_insn "*if_arith_move"
9617   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9618         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9619                           [(match_operand 6 "cc_register" "") (const_int 0)])
9620                          (match_operator:SI 5 "shiftable_operator"
9621                           [(match_operand:SI 2 "s_register_operand" "r,r")
9622                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9623                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
9624   "TARGET_ARM"
9625   "@
9626    %I5%d4\\t%0, %2, %3
9627    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
9628   [(set_attr "conds" "use")
9629    (set_attr "length" "4,8")
9630    (set_attr "type" "*,*")]
9631 )
9632
9633 (define_insn "*ifcompare_move_arith"
9634   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9635         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9636                           [(match_operand:SI 4 "s_register_operand" "r,r")
9637                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9638                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9639                          (match_operator:SI 7 "shiftable_operator"
9640                           [(match_operand:SI 2 "s_register_operand" "r,r")
9641                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
9642    (clobber (reg:CC CC_REGNUM))]
9643   "TARGET_ARM"
9644   "*
9645   /* If we have an operation where (op x 0) is the identity operation and
9646      the conditional operator is LT or GE and we are comparing against zero and
9647      everything is in registers then we can do this in two instructions */
9648   if (operands[5] == const0_rtx
9649       && GET_CODE (operands[7]) != AND
9650       && GET_CODE (operands[3]) == REG
9651       && GET_CODE (operands[1]) == REG 
9652       && REGNO (operands[1]) == REGNO (operands[2])
9653       && REGNO (operands[2]) != REGNO (operands[0]))
9654     {
9655       if (GET_CODE (operands[6]) == GE)
9656         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9657       else if (GET_CODE (operands[6]) == LT)
9658         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9659     }
9660
9661   if (GET_CODE (operands[5]) == CONST_INT
9662       && !const_ok_for_arm (INTVAL (operands[5])))
9663     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9664   else
9665     output_asm_insn (\"cmp\\t%4, %5\", operands);
9666
9667   if (which_alternative != 0)
9668     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
9669   return \"%I7%D6\\t%0, %2, %3\";
9670   "
9671   [(set_attr "conds" "clob")
9672    (set_attr "length" "8,12")]
9673 )
9674
9675 (define_insn "*if_move_arith"
9676   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9677         (if_then_else:SI
9678          (match_operator 4 "arm_comparison_operator"
9679           [(match_operand 6 "cc_register" "") (const_int 0)])
9680          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9681          (match_operator:SI 5 "shiftable_operator"
9682           [(match_operand:SI 2 "s_register_operand" "r,r")
9683            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
9684   "TARGET_ARM"
9685   "@
9686    %I5%D4\\t%0, %2, %3
9687    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
9688   [(set_attr "conds" "use")
9689    (set_attr "length" "4,8")
9690    (set_attr "type" "*,*")]
9691 )
9692
9693 (define_insn "*ifcompare_move_not"
9694   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9695         (if_then_else:SI
9696          (match_operator 5 "arm_comparison_operator"
9697           [(match_operand:SI 3 "s_register_operand" "r,r")
9698            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9699          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9700          (not:SI
9701           (match_operand:SI 2 "s_register_operand" "r,r"))))
9702    (clobber (reg:CC CC_REGNUM))]
9703   "TARGET_ARM"
9704   "#"
9705   [(set_attr "conds" "clob")
9706    (set_attr "length" "8,12")]
9707 )
9708
9709 (define_insn "*if_move_not"
9710   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9711         (if_then_else:SI
9712          (match_operator 4 "arm_comparison_operator"
9713           [(match_operand 3 "cc_register" "") (const_int 0)])
9714          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9715          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9716   "TARGET_ARM"
9717   "@
9718    mvn%D4\\t%0, %2
9719    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9720    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
9721   [(set_attr "conds" "use")
9722    (set_attr "length" "4,8,8")]
9723 )
9724
9725 (define_insn "*ifcompare_not_move"
9726   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9727         (if_then_else:SI 
9728          (match_operator 5 "arm_comparison_operator"
9729           [(match_operand:SI 3 "s_register_operand" "r,r")
9730            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9731          (not:SI
9732           (match_operand:SI 2 "s_register_operand" "r,r"))
9733          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9734    (clobber (reg:CC CC_REGNUM))]
9735   "TARGET_ARM"
9736   "#"
9737   [(set_attr "conds" "clob")
9738    (set_attr "length" "8,12")]
9739 )
9740
9741 (define_insn "*if_not_move"
9742   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9743         (if_then_else:SI
9744          (match_operator 4 "arm_comparison_operator"
9745           [(match_operand 3 "cc_register" "") (const_int 0)])
9746          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9747          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9748   "TARGET_ARM"
9749   "@
9750    mvn%d4\\t%0, %2
9751    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9752    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
9753   [(set_attr "conds" "use")
9754    (set_attr "length" "4,8,8")]
9755 )
9756
9757 (define_insn "*ifcompare_shift_move"
9758   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9759         (if_then_else:SI
9760          (match_operator 6 "arm_comparison_operator"
9761           [(match_operand:SI 4 "s_register_operand" "r,r")
9762            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9763          (match_operator:SI 7 "shift_operator"
9764           [(match_operand:SI 2 "s_register_operand" "r,r")
9765            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9766          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9767    (clobber (reg:CC CC_REGNUM))]
9768   "TARGET_ARM"
9769   "#"
9770   [(set_attr "conds" "clob")
9771    (set_attr "length" "8,12")]
9772 )
9773
9774 (define_insn "*if_shift_move"
9775   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9776         (if_then_else:SI
9777          (match_operator 5 "arm_comparison_operator"
9778           [(match_operand 6 "cc_register" "") (const_int 0)])
9779          (match_operator:SI 4 "shift_operator"
9780           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9781            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9782          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9783   "TARGET_ARM"
9784   "@
9785    mov%d5\\t%0, %2%S4
9786    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9787    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
9788   [(set_attr "conds" "use")
9789    (set_attr "shift" "2")
9790    (set_attr "length" "4,8,8")
9791    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9792                       (const_string "alu_shift")
9793                       (const_string "alu_shift_reg")))]
9794 )
9795
9796 (define_insn "*ifcompare_move_shift"
9797   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9798         (if_then_else:SI
9799          (match_operator 6 "arm_comparison_operator"
9800           [(match_operand:SI 4 "s_register_operand" "r,r")
9801            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9802          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9803          (match_operator:SI 7 "shift_operator"
9804           [(match_operand:SI 2 "s_register_operand" "r,r")
9805            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
9806    (clobber (reg:CC CC_REGNUM))]
9807   "TARGET_ARM"
9808   "#"
9809   [(set_attr "conds" "clob")
9810    (set_attr "length" "8,12")]
9811 )
9812
9813 (define_insn "*if_move_shift"
9814   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9815         (if_then_else:SI
9816          (match_operator 5 "arm_comparison_operator"
9817           [(match_operand 6 "cc_register" "") (const_int 0)])
9818          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9819          (match_operator:SI 4 "shift_operator"
9820           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9821            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
9822   "TARGET_ARM"
9823   "@
9824    mov%D5\\t%0, %2%S4
9825    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9826    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
9827   [(set_attr "conds" "use")
9828    (set_attr "shift" "2")
9829    (set_attr "length" "4,8,8")
9830    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9831                       (const_string "alu_shift")
9832                       (const_string "alu_shift_reg")))]
9833 )
9834
9835 (define_insn "*ifcompare_shift_shift"
9836   [(set (match_operand:SI 0 "s_register_operand" "=r")
9837         (if_then_else:SI
9838          (match_operator 7 "arm_comparison_operator"
9839           [(match_operand:SI 5 "s_register_operand" "r")
9840            (match_operand:SI 6 "arm_add_operand" "rIL")])
9841          (match_operator:SI 8 "shift_operator"
9842           [(match_operand:SI 1 "s_register_operand" "r")
9843            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9844          (match_operator:SI 9 "shift_operator"
9845           [(match_operand:SI 3 "s_register_operand" "r")
9846            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
9847    (clobber (reg:CC CC_REGNUM))]
9848   "TARGET_ARM"
9849   "#"
9850   [(set_attr "conds" "clob")
9851    (set_attr "length" "12")]
9852 )
9853
9854 (define_insn "*if_shift_shift"
9855   [(set (match_operand:SI 0 "s_register_operand" "=r")
9856         (if_then_else:SI
9857          (match_operator 5 "arm_comparison_operator"
9858           [(match_operand 8 "cc_register" "") (const_int 0)])
9859          (match_operator:SI 6 "shift_operator"
9860           [(match_operand:SI 1 "s_register_operand" "r")
9861            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9862          (match_operator:SI 7 "shift_operator"
9863           [(match_operand:SI 3 "s_register_operand" "r")
9864            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
9865   "TARGET_ARM"
9866   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
9867   [(set_attr "conds" "use")
9868    (set_attr "shift" "1")
9869    (set_attr "length" "8")
9870    (set (attr "type") (if_then_else
9871                         (and (match_operand 2 "const_int_operand" "")
9872                              (match_operand 4 "const_int_operand" ""))
9873                       (const_string "alu_shift")
9874                       (const_string "alu_shift_reg")))]
9875 )
9876
9877 (define_insn "*ifcompare_not_arith"
9878   [(set (match_operand:SI 0 "s_register_operand" "=r")
9879         (if_then_else:SI
9880          (match_operator 6 "arm_comparison_operator"
9881           [(match_operand:SI 4 "s_register_operand" "r")
9882            (match_operand:SI 5 "arm_add_operand" "rIL")])
9883          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9884          (match_operator:SI 7 "shiftable_operator"
9885           [(match_operand:SI 2 "s_register_operand" "r")
9886            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
9887    (clobber (reg:CC CC_REGNUM))]
9888   "TARGET_ARM"
9889   "#"
9890   [(set_attr "conds" "clob")
9891    (set_attr "length" "12")]
9892 )
9893
9894 (define_insn "*if_not_arith"
9895   [(set (match_operand:SI 0 "s_register_operand" "=r")
9896         (if_then_else:SI
9897          (match_operator 5 "arm_comparison_operator"
9898           [(match_operand 4 "cc_register" "") (const_int 0)])
9899          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9900          (match_operator:SI 6 "shiftable_operator"
9901           [(match_operand:SI 2 "s_register_operand" "r")
9902            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
9903   "TARGET_ARM"
9904   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
9905   [(set_attr "conds" "use")
9906    (set_attr "length" "8")]
9907 )
9908
9909 (define_insn "*ifcompare_arith_not"
9910   [(set (match_operand:SI 0 "s_register_operand" "=r")
9911         (if_then_else:SI
9912          (match_operator 6 "arm_comparison_operator"
9913           [(match_operand:SI 4 "s_register_operand" "r")
9914            (match_operand:SI 5 "arm_add_operand" "rIL")])
9915          (match_operator:SI 7 "shiftable_operator"
9916           [(match_operand:SI 2 "s_register_operand" "r")
9917            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9918          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9919    (clobber (reg:CC CC_REGNUM))]
9920   "TARGET_ARM"
9921   "#"
9922   [(set_attr "conds" "clob")
9923    (set_attr "length" "12")]
9924 )
9925
9926 (define_insn "*if_arith_not"
9927   [(set (match_operand:SI 0 "s_register_operand" "=r")
9928         (if_then_else:SI
9929          (match_operator 5 "arm_comparison_operator"
9930           [(match_operand 4 "cc_register" "") (const_int 0)])
9931          (match_operator:SI 6 "shiftable_operator"
9932           [(match_operand:SI 2 "s_register_operand" "r")
9933            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9934          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9935   "TARGET_ARM"
9936   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9937   [(set_attr "conds" "use")
9938    (set_attr "length" "8")]
9939 )
9940
9941 (define_insn "*ifcompare_neg_move"
9942   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9943         (if_then_else:SI
9944          (match_operator 5 "arm_comparison_operator"
9945           [(match_operand:SI 3 "s_register_operand" "r,r")
9946            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9947          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9948          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9949    (clobber (reg:CC CC_REGNUM))]
9950   "TARGET_ARM"
9951   "#"
9952   [(set_attr "conds" "clob")
9953    (set_attr "length" "8,12")]
9954 )
9955
9956 (define_insn "*if_neg_move"
9957   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9958         (if_then_else:SI
9959          (match_operator 4 "arm_comparison_operator"
9960           [(match_operand 3 "cc_register" "") (const_int 0)])
9961          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9962          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9963   "TARGET_ARM"
9964   "@
9965    rsb%d4\\t%0, %2, #0
9966    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9967    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9968   [(set_attr "conds" "use")
9969    (set_attr "length" "4,8,8")]
9970 )
9971
9972 (define_insn "*ifcompare_move_neg"
9973   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9974         (if_then_else:SI
9975          (match_operator 5 "arm_comparison_operator"
9976           [(match_operand:SI 3 "s_register_operand" "r,r")
9977            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9978          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9979          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9980    (clobber (reg:CC CC_REGNUM))]
9981   "TARGET_ARM"
9982   "#"
9983   [(set_attr "conds" "clob")
9984    (set_attr "length" "8,12")]
9985 )
9986
9987 (define_insn "*if_move_neg"
9988   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9989         (if_then_else:SI
9990          (match_operator 4 "arm_comparison_operator"
9991           [(match_operand 3 "cc_register" "") (const_int 0)])
9992          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9993          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9994   "TARGET_ARM"
9995   "@
9996    rsb%D4\\t%0, %2, #0
9997    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9998    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9999   [(set_attr "conds" "use")
10000    (set_attr "length" "4,8,8")]
10001 )
10002
10003 (define_insn "*arith_adjacentmem"
10004   [(set (match_operand:SI 0 "s_register_operand" "=r")
10005         (match_operator:SI 1 "shiftable_operator"
10006          [(match_operand:SI 2 "memory_operand" "m")
10007           (match_operand:SI 3 "memory_operand" "m")]))
10008    (clobber (match_scratch:SI 4 "=r"))]
10009   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
10010   "*
10011   {
10012     rtx ldm[3];
10013     rtx arith[4];
10014     rtx base_reg;
10015     HOST_WIDE_INT val1 = 0, val2 = 0;
10016
10017     if (REGNO (operands[0]) > REGNO (operands[4]))
10018       {
10019         ldm[1] = operands[4];
10020         ldm[2] = operands[0];
10021       }
10022     else
10023       {
10024         ldm[1] = operands[0];
10025         ldm[2] = operands[4];
10026       }
10027
10028     base_reg = XEXP (operands[2], 0);
10029
10030     if (!REG_P (base_reg))
10031       {
10032         val1 = INTVAL (XEXP (base_reg, 1));
10033         base_reg = XEXP (base_reg, 0);
10034       }
10035
10036     if (!REG_P (XEXP (operands[3], 0)))
10037       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
10038
10039     arith[0] = operands[0];
10040     arith[3] = operands[1];
10041
10042     if (val1 < val2)
10043       {
10044         arith[1] = ldm[1];
10045         arith[2] = ldm[2];
10046       }
10047     else
10048       {
10049         arith[1] = ldm[2];
10050         arith[2] = ldm[1];
10051       }
10052
10053     ldm[0] = base_reg;
10054     if (val1 !=0 && val2 != 0)
10055       {
10056         rtx ops[3];
10057
10058         if (val1 == 4 || val2 == 4)
10059           /* Other val must be 8, since we know they are adjacent and neither
10060              is zero.  */
10061           output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
10062         else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
10063           {
10064             ldm[0] = ops[0] = operands[4];
10065             ops[1] = base_reg;
10066             ops[2] = GEN_INT (val1);
10067             output_add_immediate (ops);
10068             if (val1 < val2)
10069               output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
10070             else
10071               output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
10072           }
10073         else
10074           {
10075             /* Offset is out of range for a single add, so use two ldr.  */
10076             ops[0] = ldm[1];
10077             ops[1] = base_reg;
10078             ops[2] = GEN_INT (val1);
10079             output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10080             ops[0] = ldm[2];
10081             ops[2] = GEN_INT (val2);
10082             output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10083           }
10084       }
10085     else if (val1 != 0)
10086       {
10087         if (val1 < val2)
10088           output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
10089         else
10090           output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
10091       }
10092     else
10093       {
10094         if (val1 < val2)
10095           output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
10096         else
10097           output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
10098       }
10099     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10100     return \"\";
10101   }"
10102   [(set_attr "length" "12")
10103    (set_attr "predicable" "yes")
10104    (set_attr "type" "load1")]
10105 )
10106
10107 ; This pattern is never tried by combine, so do it as a peephole
10108
10109 (define_peephole2
10110   [(set (match_operand:SI 0 "arm_general_register_operand" "")
10111         (match_operand:SI 1 "arm_general_register_operand" ""))
10112    (set (reg:CC CC_REGNUM)
10113         (compare:CC (match_dup 1) (const_int 0)))]
10114   "TARGET_ARM"
10115   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10116               (set (match_dup 0) (match_dup 1))])]
10117   ""
10118 )
10119
10120 ; Peepholes to spot possible load- and store-multiples, if the ordering is
10121 ; reversed, check that the memory references aren't volatile.
10122
10123 (define_peephole
10124   [(set (match_operand:SI 0 "s_register_operand" "=r")
10125         (match_operand:SI 4 "memory_operand" "m"))
10126    (set (match_operand:SI 1 "s_register_operand" "=r")
10127         (match_operand:SI 5 "memory_operand" "m"))
10128    (set (match_operand:SI 2 "s_register_operand" "=r")
10129         (match_operand:SI 6 "memory_operand" "m"))
10130    (set (match_operand:SI 3 "s_register_operand" "=r")
10131         (match_operand:SI 7 "memory_operand" "m"))]
10132   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
10133   "*
10134   return emit_ldm_seq (operands, 4);
10135   "
10136 )
10137
10138 (define_peephole
10139   [(set (match_operand:SI 0 "s_register_operand" "=r")
10140         (match_operand:SI 3 "memory_operand" "m"))
10141    (set (match_operand:SI 1 "s_register_operand" "=r")
10142         (match_operand:SI 4 "memory_operand" "m"))
10143    (set (match_operand:SI 2 "s_register_operand" "=r")
10144         (match_operand:SI 5 "memory_operand" "m"))]
10145   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
10146   "*
10147   return emit_ldm_seq (operands, 3);
10148   "
10149 )
10150
10151 (define_peephole
10152   [(set (match_operand:SI 0 "s_register_operand" "=r")
10153         (match_operand:SI 2 "memory_operand" "m"))
10154    (set (match_operand:SI 1 "s_register_operand" "=r")
10155         (match_operand:SI 3 "memory_operand" "m"))]
10156   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
10157   "*
10158   return emit_ldm_seq (operands, 2);
10159   "
10160 )
10161
10162 (define_peephole
10163   [(set (match_operand:SI 4 "memory_operand" "=m")
10164         (match_operand:SI 0 "s_register_operand" "r"))
10165    (set (match_operand:SI 5 "memory_operand" "=m")
10166         (match_operand:SI 1 "s_register_operand" "r"))
10167    (set (match_operand:SI 6 "memory_operand" "=m")
10168         (match_operand:SI 2 "s_register_operand" "r"))
10169    (set (match_operand:SI 7 "memory_operand" "=m")
10170         (match_operand:SI 3 "s_register_operand" "r"))]
10171   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
10172   "*
10173   return emit_stm_seq (operands, 4);
10174   "
10175 )
10176
10177 (define_peephole
10178   [(set (match_operand:SI 3 "memory_operand" "=m")
10179         (match_operand:SI 0 "s_register_operand" "r"))
10180    (set (match_operand:SI 4 "memory_operand" "=m")
10181         (match_operand:SI 1 "s_register_operand" "r"))
10182    (set (match_operand:SI 5 "memory_operand" "=m")
10183         (match_operand:SI 2 "s_register_operand" "r"))]
10184   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
10185   "*
10186   return emit_stm_seq (operands, 3);
10187   "
10188 )
10189
10190 (define_peephole
10191   [(set (match_operand:SI 2 "memory_operand" "=m")
10192         (match_operand:SI 0 "s_register_operand" "r"))
10193    (set (match_operand:SI 3 "memory_operand" "=m")
10194         (match_operand:SI 1 "s_register_operand" "r"))]
10195   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
10196   "*
10197   return emit_stm_seq (operands, 2);
10198   "
10199 )
10200
10201 (define_split
10202   [(set (match_operand:SI 0 "s_register_operand" "")
10203         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10204                        (const_int 0))
10205                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
10206                          [(match_operand:SI 3 "s_register_operand" "")
10207                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
10208    (clobber (match_operand:SI 5 "s_register_operand" ""))]
10209   "TARGET_ARM"
10210   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10211    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10212                               (match_dup 5)))]
10213   ""
10214 )
10215
10216 ;; This split can be used because CC_Z mode implies that the following
10217 ;; branch will be an equality, or an unsigned inequality, so the sign
10218 ;; extension is not needed.
10219
10220 (define_split
10221   [(set (reg:CC_Z CC_REGNUM)
10222         (compare:CC_Z
10223          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
10224                     (const_int 24))
10225          (match_operand 1 "const_int_operand" "")))
10226    (clobber (match_scratch:SI 2 ""))]
10227   "TARGET_ARM
10228    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10229        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
10230   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
10231    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
10232   "
10233   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
10234   "
10235 )
10236 ;; ??? Check the patterns above for Thumb-2 usefulness
10237
10238 (define_expand "prologue"
10239   [(clobber (const_int 0))]
10240   "TARGET_EITHER"
10241   "if (TARGET_32BIT)
10242      arm_expand_prologue ();
10243    else
10244      thumb1_expand_prologue ();
10245   DONE;
10246   "
10247 )
10248
10249 (define_expand "epilogue"
10250   [(clobber (const_int 0))]
10251   "TARGET_EITHER"
10252   "
10253   if (current_function_calls_eh_return)
10254     emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
10255   if (TARGET_THUMB1)
10256     thumb1_expand_epilogue ();
10257   else if (USE_RETURN_INSN (FALSE))
10258     {
10259       emit_jump_insn (gen_return ());
10260       DONE;
10261     }
10262   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10263         gen_rtvec (1,
10264                 gen_rtx_RETURN (VOIDmode)),
10265         VUNSPEC_EPILOGUE));
10266   DONE;
10267   "
10268 )
10269
10270 ;; Note - although unspec_volatile's USE all hard registers,
10271 ;; USEs are ignored after relaod has completed.  Thus we need
10272 ;; to add an unspec of the link register to ensure that flow
10273 ;; does not think that it is unused by the sibcall branch that
10274 ;; will replace the standard function epilogue.
10275 (define_insn "sibcall_epilogue"
10276   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
10277               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10278   "TARGET_32BIT"
10279   "*
10280   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
10281     return output_return_instruction (const_true_rtx, FALSE, FALSE);
10282   return arm_output_epilogue (next_nonnote_insn (insn));
10283   "
10284 ;; Length is absolute worst case
10285   [(set_attr "length" "44")
10286    (set_attr "type" "block")
10287    ;; We don't clobber the conditions, but the potential length of this
10288    ;; operation is sufficient to make conditionalizing the sequence 
10289    ;; unlikely to be profitable.
10290    (set_attr "conds" "clob")]
10291 )
10292
10293 (define_insn "*epilogue_insns"
10294   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
10295   "TARGET_EITHER"
10296   "*
10297   if (TARGET_32BIT)
10298     return arm_output_epilogue (NULL);
10299   else /* TARGET_THUMB1 */
10300     return thumb_unexpanded_epilogue ();
10301   "
10302   ; Length is absolute worst case
10303   [(set_attr "length" "44")
10304    (set_attr "type" "block")
10305    ;; We don't clobber the conditions, but the potential length of this
10306    ;; operation is sufficient to make conditionalizing the sequence 
10307    ;; unlikely to be profitable.
10308    (set_attr "conds" "clob")]
10309 )
10310
10311 (define_expand "eh_epilogue"
10312   [(use (match_operand:SI 0 "register_operand" ""))
10313    (use (match_operand:SI 1 "register_operand" ""))
10314    (use (match_operand:SI 2 "register_operand" ""))]
10315   "TARGET_EITHER"
10316   "
10317   {
10318     cfun->machine->eh_epilogue_sp_ofs = operands[1];
10319     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10320       {
10321         rtx ra = gen_rtx_REG (Pmode, 2);
10322
10323         emit_move_insn (ra, operands[2]);
10324         operands[2] = ra;
10325       }
10326     /* This is a hack -- we may have crystalized the function type too
10327        early.  */
10328     cfun->machine->func_type = 0;
10329   }"
10330 )
10331
10332 ;; This split is only used during output to reduce the number of patterns
10333 ;; that need assembler instructions adding to them.  We allowed the setting
10334 ;; of the conditions to be implicit during rtl generation so that
10335 ;; the conditional compare patterns would work.  However this conflicts to
10336 ;; some extent with the conditional data operations, so we have to split them
10337 ;; up again here.
10338
10339 ;; ??? Need to audit these splitters for Thumb-2.  Why isn't normal
10340 ;; conditional execution sufficient?
10341
10342 (define_split
10343   [(set (match_operand:SI 0 "s_register_operand" "")
10344         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10345                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10346                          (match_dup 0)
10347                          (match_operand 4 "" "")))
10348    (clobber (reg:CC CC_REGNUM))]
10349   "TARGET_ARM && reload_completed"
10350   [(set (match_dup 5) (match_dup 6))
10351    (cond_exec (match_dup 7)
10352               (set (match_dup 0) (match_dup 4)))]
10353   "
10354   {
10355     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10356                                              operands[2], operands[3]);
10357     enum rtx_code rc = GET_CODE (operands[1]);
10358
10359     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10360     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10361     if (mode == CCFPmode || mode == CCFPEmode)
10362       rc = reverse_condition_maybe_unordered (rc);
10363     else
10364       rc = reverse_condition (rc);
10365
10366     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10367   }"
10368 )
10369
10370 (define_split
10371   [(set (match_operand:SI 0 "s_register_operand" "")
10372         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10373                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10374                          (match_operand 4 "" "")
10375                          (match_dup 0)))
10376    (clobber (reg:CC CC_REGNUM))]
10377   "TARGET_ARM && reload_completed"
10378   [(set (match_dup 5) (match_dup 6))
10379    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10380               (set (match_dup 0) (match_dup 4)))]
10381   "
10382   {
10383     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10384                                              operands[2], operands[3]);
10385
10386     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10387     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10388   }"
10389 )
10390
10391 (define_split
10392   [(set (match_operand:SI 0 "s_register_operand" "")
10393         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10394                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10395                          (match_operand 4 "" "")
10396                          (match_operand 5 "" "")))
10397    (clobber (reg:CC CC_REGNUM))]
10398   "TARGET_ARM && reload_completed"
10399   [(set (match_dup 6) (match_dup 7))
10400    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10401               (set (match_dup 0) (match_dup 4)))
10402    (cond_exec (match_dup 8)
10403               (set (match_dup 0) (match_dup 5)))]
10404   "
10405   {
10406     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10407                                              operands[2], operands[3]);
10408     enum rtx_code rc = GET_CODE (operands[1]);
10409
10410     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10411     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10412     if (mode == CCFPmode || mode == CCFPEmode)
10413       rc = reverse_condition_maybe_unordered (rc);
10414     else
10415       rc = reverse_condition (rc);
10416
10417     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10418   }"
10419 )
10420
10421 (define_split
10422   [(set (match_operand:SI 0 "s_register_operand" "")
10423         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10424                           [(match_operand:SI 2 "s_register_operand" "")
10425                            (match_operand:SI 3 "arm_add_operand" "")])
10426                          (match_operand:SI 4 "arm_rhs_operand" "")
10427                          (not:SI
10428                           (match_operand:SI 5 "s_register_operand" ""))))
10429    (clobber (reg:CC CC_REGNUM))]
10430   "TARGET_ARM && reload_completed"
10431   [(set (match_dup 6) (match_dup 7))
10432    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10433               (set (match_dup 0) (match_dup 4)))
10434    (cond_exec (match_dup 8)
10435               (set (match_dup 0) (not:SI (match_dup 5))))]
10436   "
10437   {
10438     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10439                                              operands[2], operands[3]);
10440     enum rtx_code rc = GET_CODE (operands[1]);
10441
10442     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10443     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10444     if (mode == CCFPmode || mode == CCFPEmode)
10445       rc = reverse_condition_maybe_unordered (rc);
10446     else
10447       rc = reverse_condition (rc);
10448
10449     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10450   }"
10451 )
10452
10453 (define_insn "*cond_move_not"
10454   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10455         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10456                           [(match_operand 3 "cc_register" "") (const_int 0)])
10457                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10458                          (not:SI
10459                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
10460   "TARGET_ARM"
10461   "@
10462    mvn%D4\\t%0, %2
10463    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
10464   [(set_attr "conds" "use")
10465    (set_attr "length" "4,8")]
10466 )
10467
10468 ;; The next two patterns occur when an AND operation is followed by a
10469 ;; scc insn sequence 
10470
10471 (define_insn "*sign_extract_onebit"
10472   [(set (match_operand:SI 0 "s_register_operand" "=r")
10473         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10474                          (const_int 1)
10475                          (match_operand:SI 2 "const_int_operand" "n")))
10476     (clobber (reg:CC CC_REGNUM))]
10477   "TARGET_ARM"
10478   "*
10479     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10480     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10481     return \"mvnne\\t%0, #0\";
10482   "
10483   [(set_attr "conds" "clob")
10484    (set_attr "length" "8")]
10485 )
10486
10487 (define_insn "*not_signextract_onebit"
10488   [(set (match_operand:SI 0 "s_register_operand" "=r")
10489         (not:SI
10490          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10491                           (const_int 1)
10492                           (match_operand:SI 2 "const_int_operand" "n"))))
10493    (clobber (reg:CC CC_REGNUM))]
10494   "TARGET_ARM"
10495   "*
10496     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10497     output_asm_insn (\"tst\\t%1, %2\", operands);
10498     output_asm_insn (\"mvneq\\t%0, #0\", operands);
10499     return \"movne\\t%0, #0\";
10500   "
10501   [(set_attr "conds" "clob")
10502    (set_attr "length" "12")]
10503 )
10504 ;; ??? The above patterns need auditing for Thumb-2
10505
10506 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
10507 ;; expressions.  For simplicity, the first register is also in the unspec
10508 ;; part.
10509 (define_insn "*push_multi"
10510   [(match_parallel 2 "multi_register_push"
10511     [(set (match_operand:BLK 0 "memory_operand" "=m")
10512           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
10513                       UNSPEC_PUSH_MULT))])]
10514   "TARGET_32BIT"
10515   "*
10516   {
10517     int num_saves = XVECLEN (operands[2], 0);
10518      
10519     /* For the StrongARM at least it is faster to
10520        use STR to store only a single register.
10521        In Thumb mode always use push, and the assmebler will pick
10522        something approporiate.  */
10523     if (num_saves == 1 && TARGET_ARM)
10524       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10525     else
10526       {
10527         int i;
10528         char pattern[100];
10529
10530         if (TARGET_ARM)
10531             strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10532         else
10533             strcpy (pattern, \"push\\t{%1\");
10534
10535         for (i = 1; i < num_saves; i++)
10536           {
10537             strcat (pattern, \", %|\");
10538             strcat (pattern,
10539                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10540           }
10541
10542         strcat (pattern, \"}\");
10543         output_asm_insn (pattern, operands);
10544       }
10545
10546     return \"\";
10547   }"
10548   [(set_attr "type" "store4")]
10549 )
10550
10551 (define_insn "stack_tie"
10552   [(set (mem:BLK (scratch))
10553         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
10554                      (match_operand:SI 1 "s_register_operand" "r")]
10555                     UNSPEC_PRLG_STK))]
10556   ""
10557   ""
10558   [(set_attr "length" "0")]
10559 )
10560
10561 ;; Similarly for the floating point registers
10562 (define_insn "*push_fp_multi"
10563   [(match_parallel 2 "multi_register_push"
10564     [(set (match_operand:BLK 0 "memory_operand" "=m")
10565           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10566                       UNSPEC_PUSH_MULT))])]
10567   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
10568   "*
10569   {
10570     char pattern[100];
10571
10572     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10573     output_asm_insn (pattern, operands);
10574     return \"\";
10575   }"
10576   [(set_attr "type" "f_store")]
10577 )
10578
10579 ;; Special patterns for dealing with the constant pool
10580
10581 (define_insn "align_4"
10582   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10583   "TARGET_EITHER"
10584   "*
10585   assemble_align (32);
10586   return \"\";
10587   "
10588 )
10589
10590 (define_insn "align_8"
10591   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10592   "TARGET_EITHER"
10593   "*
10594   assemble_align (64);
10595   return \"\";
10596   "
10597 )
10598
10599 (define_insn "consttable_end"
10600   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10601   "TARGET_EITHER"
10602   "*
10603   making_const_table = FALSE;
10604   return \"\";
10605   "
10606 )
10607
10608 (define_insn "consttable_1"
10609   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10610   "TARGET_THUMB1"
10611   "*
10612   making_const_table = TRUE;
10613   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10614   assemble_zeros (3);
10615   return \"\";
10616   "
10617   [(set_attr "length" "4")]
10618 )
10619
10620 (define_insn "consttable_2"
10621   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10622   "TARGET_THUMB1"
10623   "*
10624   making_const_table = TRUE;
10625   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10626   assemble_zeros (2);
10627   return \"\";
10628   "
10629   [(set_attr "length" "4")]
10630 )
10631
10632 (define_insn "consttable_4"
10633   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10634   "TARGET_EITHER"
10635   "*
10636   {
10637     making_const_table = TRUE;
10638     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10639       {
10640       case MODE_FLOAT:
10641       {
10642         REAL_VALUE_TYPE r;
10643         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10644         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10645         break;
10646       }
10647       default:
10648         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
10649         break;
10650       }
10651     return \"\";
10652   }"
10653   [(set_attr "length" "4")]
10654 )
10655
10656 (define_insn "consttable_8"
10657   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10658   "TARGET_EITHER"
10659   "*
10660   {
10661     making_const_table = TRUE;
10662     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10663       {
10664        case MODE_FLOAT:
10665         {
10666           REAL_VALUE_TYPE r;
10667           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10668           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10669           break;
10670         }
10671       default:
10672         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10673         break;
10674       }
10675     return \"\";
10676   }"
10677   [(set_attr "length" "8")]
10678 )
10679
10680 ;; Miscellaneous Thumb patterns
10681
10682 (define_expand "tablejump"
10683   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10684               (use (label_ref (match_operand 1 "" "")))])]
10685   "TARGET_THUMB1"
10686   "
10687   if (flag_pic)
10688     {
10689       /* Hopefully, CSE will eliminate this copy.  */
10690       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10691       rtx reg2 = gen_reg_rtx (SImode);
10692
10693       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10694       operands[0] = reg2;
10695     }
10696   "
10697 )
10698
10699 ;; NB never uses BX.
10700 (define_insn "*thumb1_tablejump"
10701   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10702    (use (label_ref (match_operand 1 "" "")))]
10703   "TARGET_THUMB1"
10704   "mov\\t%|pc, %0"
10705   [(set_attr "length" "2")]
10706 )
10707
10708 ;; V5 Instructions,
10709
10710 (define_insn "clzsi2"
10711   [(set (match_operand:SI 0 "s_register_operand" "=r")
10712         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10713   "TARGET_32BIT && arm_arch5"
10714   "clz%?\\t%0, %1"
10715   [(set_attr "predicable" "yes")])
10716
10717 (define_expand "ffssi2"
10718   [(set (match_operand:SI 0 "s_register_operand" "")
10719         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10720   "TARGET_32BIT && arm_arch5"
10721   "
10722   {
10723     rtx t1, t2, t3;
10724
10725     t1 = gen_reg_rtx (SImode);
10726     t2 = gen_reg_rtx (SImode);
10727     t3 = gen_reg_rtx (SImode);
10728
10729     emit_insn (gen_negsi2 (t1, operands[1]));
10730     emit_insn (gen_andsi3 (t2, operands[1], t1));
10731     emit_insn (gen_clzsi2 (t3, t2));
10732     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10733     DONE;
10734   }"
10735 )
10736
10737 (define_expand "ctzsi2"
10738   [(set (match_operand:SI 0 "s_register_operand" "")
10739         (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10740   "TARGET_32BIT && arm_arch5"
10741   "
10742   {
10743     rtx t1, t2, t3;
10744
10745     t1 = gen_reg_rtx (SImode);
10746     t2 = gen_reg_rtx (SImode);
10747     t3 = gen_reg_rtx (SImode);
10748
10749     emit_insn (gen_negsi2 (t1, operands[1]));
10750     emit_insn (gen_andsi3 (t2, operands[1], t1));
10751     emit_insn (gen_clzsi2 (t3, t2));
10752     emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10753     DONE;
10754   }"
10755 )
10756
10757 ;; V5E instructions.
10758
10759 (define_insn "prefetch"
10760   [(prefetch (match_operand:SI 0 "address_operand" "p")
10761              (match_operand:SI 1 "" "")
10762              (match_operand:SI 2 "" ""))]
10763   "TARGET_32BIT && arm_arch5e"
10764   "pld\\t%a0")
10765
10766 ;; General predication pattern
10767
10768 (define_cond_exec
10769   [(match_operator 0 "arm_comparison_operator"
10770     [(match_operand 1 "cc_register" "")
10771      (const_int 0)])]
10772   "TARGET_32BIT"
10773   ""
10774 )
10775
10776 (define_insn "prologue_use"
10777   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10778   ""
10779   "%@ %0 needed for prologue"
10780 )
10781
10782
10783 ;; Patterns for exception handling
10784
10785 (define_expand "eh_return"
10786   [(use (match_operand 0 "general_operand" ""))]
10787   "TARGET_EITHER"
10788   "
10789   {
10790     if (TARGET_32BIT)
10791       emit_insn (gen_arm_eh_return (operands[0]));
10792     else
10793       emit_insn (gen_thumb_eh_return (operands[0]));
10794     DONE;
10795   }"
10796 )
10797                                    
10798 ;; We can't expand this before we know where the link register is stored.
10799 (define_insn_and_split "arm_eh_return"
10800   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10801                     VUNSPEC_EH_RETURN)
10802    (clobber (match_scratch:SI 1 "=&r"))]
10803   "TARGET_ARM"
10804   "#"
10805   "&& reload_completed"
10806   [(const_int 0)]
10807   "
10808   {
10809     arm_set_return_address (operands[0], operands[1]);
10810     DONE;
10811   }"
10812 )
10813
10814 (define_insn_and_split "thumb_eh_return"
10815   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10816                     VUNSPEC_EH_RETURN)
10817    (clobber (match_scratch:SI 1 "=&l"))]
10818   "TARGET_THUMB1"
10819   "#"
10820   "&& reload_completed"
10821   [(const_int 0)]
10822   "
10823   {
10824     thumb_set_return_address (operands[0], operands[1]);
10825     DONE;
10826   }"
10827 )
10828
10829 \f
10830 ;; TLS support
10831
10832 (define_insn "load_tp_hard"
10833   [(set (match_operand:SI 0 "register_operand" "=r")
10834         (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10835   "TARGET_HARD_TP"
10836   "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
10837   [(set_attr "predicable" "yes")]
10838 )
10839
10840 ;; Doesn't clobber R1-R3.  Must use r0 for the first operand.
10841 (define_insn "load_tp_soft"
10842   [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10843    (clobber (reg:SI LR_REGNUM))
10844    (clobber (reg:SI IP_REGNUM))
10845    (clobber (reg:CC CC_REGNUM))]
10846   "TARGET_SOFT_TP"
10847   "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
10848   [(set_attr "conds" "clob")]
10849 )
10850
10851 ;; Load the FPA co-processor patterns
10852 (include "fpa.md")
10853 ;; Load the Maverick co-processor patterns
10854 (include "cirrus.md")
10855 ;; Load the Intel Wireless Multimedia Extension patterns
10856 (include "iwmmxt.md")
10857 ;; Load the VFP co-processor patterns
10858 (include "vfp.md")
10859 ;; Thumb-2 patterns
10860 (include "thumb2.md")
10861