OSDN Git Service

* config/arm/arm-protots.h (vfp_mem_operand): Rename ...
[pf3gnuchains/gcc-fork.git] / gcc / config / arm / arm.md
1 ;;- Machine description for ARM for GNU compiler
2 ;;  Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;;  2001, 2002, 2003 2004  Free Software Foundation, Inc.
4 ;;  Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
5 ;;  and Martin Simmons (@harleqn.co.uk).
6 ;;  More major hacks by Richard Earnshaw (rearnsha@arm.com).
7
8 ;; This file is part of GCC.
9
10 ;; GCC is free software; you can redistribute it and/or modify it
11 ;; under the terms of the GNU General Public License as published
12 ;; by the Free Software Foundation; either version 2, or (at your
13 ;; option) any later version.
14
15 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
16 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
18 ;; License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GCC; see the file COPYING.  If not, write to
22 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
24
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26
27 \f
28 ;;---------------------------------------------------------------------------
29 ;; Constants
30
31 ;; Register numbers
32 (define_constants
33   [(IP_REGNUM       12)         ; Scratch register
34    (SP_REGNUM       13)         ; Stack pointer
35    (LR_REGNUM       14)         ; Return address register
36    (PC_REGNUM       15)         ; Program counter
37    (CC_REGNUM       24)         ; Condition code pseudo register
38    (LAST_ARM_REGNUM 15)
39   ]
40 )
41 ;; 3rd operand to select_dominance_cc_mode
42 (define_constants
43   [(DOM_CC_X_AND_Y  0)
44    (DOM_CC_NX_OR_Y  1)
45    (DOM_CC_X_OR_Y   2)
46   ]
47 )
48
49 ;; UNSPEC Usage:
50 ;; Note: sin and cos are no-longer used.
51
52 (define_constants
53   [(UNSPEC_SIN       0) ; `sin' operation (MODE_FLOAT):
54                         ;   operand 0 is the result,
55                         ;   operand 1 the parameter.
56    (UNPSEC_COS       1) ; `cos' operation (MODE_FLOAT):
57                         ;   operand 0 is the result,
58                         ;   operand 1 the parameter.
59    (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
60                         ;   operand 0 is the first register,
61                         ;   subsequent registers are in parallel (use ...)
62                         ;   expressions.
63    (UNSPEC_PIC_SYM   3) ; A symbol that has been treated properly for pic
64                         ;   usage, that is, we will add the pic_register
65                         ;   value to it before trying to dereference it.
66    (UNSPEC_PIC_BASE  4) ; Adding the PC value to the offset to the
67                         ;   GLOBAL_OFFSET_TABLE.  The operation is fully
68                         ;   described by the RTL but must be wrapped to
69                         ;   prevent combine from trying to rip it apart.
70    (UNSPEC_PRLG_STK  5) ; A special barrier that prevents frame accesses 
71                         ;   being scheduled before the stack adjustment insn.
72    (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
73                         ; this unspec is used to prevent the deletion of
74                         ; instructions setting registers for EH handling
75                         ; and stack frame generation.  Operand 0 is the
76                         ; register to "use".
77    (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
78    (UNSPEC_WSHUFH    8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
79    (UNSPEC_WACC      9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
80    (UNSPEC_TMOVMSK  10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
81    (UNSPEC_WSAD     11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
82    (UNSPEC_WSADZ    12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
83    (UNSPEC_WMACS    13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
84    (UNSPEC_WMACU    14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
85    (UNSPEC_WMACSZ   15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
86    (UNSPEC_WMACUZ   16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
87    (UNSPEC_CLRDI    17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
88    (UNSPEC_WMADDS   18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
89    (UNSPEC_WMADDU   19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
90   ]
91 )
92
93 ;; UNSPEC_VOLATILE Usage:
94
95 (define_constants
96   [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
97                         ;   insn in the code.
98    (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
99                         ;   instruction epilogue sequence that isn't expanded
100                         ;   into normal RTL.  Used for both normal and sibcall
101                         ;   epilogues.
102    (VUNSPEC_ALIGN    2) ; `align' insn.  Used at the head of a minipool table 
103                         ;   for inlined constants.
104    (VUNSPEC_POOL_END 3) ; `end-of-table'.  Used to mark the end of a minipool
105                         ;   table.
106    (VUNSPEC_POOL_1   4) ; `pool-entry(1)'.  An entry in the constant pool for
107                         ;   an 8-bit object.
108    (VUNSPEC_POOL_2   5) ; `pool-entry(2)'.  An entry in the constant pool for
109                         ;   a 16-bit object.
110    (VUNSPEC_POOL_4   6) ; `pool-entry(4)'.  An entry in the constant pool for
111                         ;   a 32-bit object.
112    (VUNSPEC_POOL_8   7) ; `pool-entry(8)'.  An entry in the constant pool for
113                         ;   a 64-bit object.
114    (VUNSPEC_TMRC     8) ; Used by the iWMMXt TMRC instruction.
115    (VUNSPEC_TMCR     9) ; Used by the iWMMXt TMCR instruction.
116    (VUNSPEC_ALIGN8   10) ; 8-byte alignment version of VUNSPEC_ALIGN
117    (VUNSPEC_WCMP_EQ  11) ; Used by the iWMMXt WCMPEQ instructions
118    (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
119    (VUNSPEC_WCMP_GT  13) ; Used by the iwMMXT WCMPGT instructions
120   ]
121 )
122 \f
123 ;;---------------------------------------------------------------------------
124 ;; Attributes
125
126 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
127 ; generating ARM code.  This is used to control the length of some insn
128 ; patterns that share the same RTL in both ARM and Thumb code.
129 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
130
131 ; PROG_MODE attribute is used to determine whether condition codes are
132 ; clobbered by a call insn: they are if in prog32 mode.  This is controlled
133 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
134 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
135
136 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
137 ; scheduling decisions for the load unit and the multiplier.
138 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
139
140 ; IS_XSCALE is set to 'yes' when compiling for XScale.
141 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
142
143 ;; Operand number of an input operand that is shifted.  Zero if the
144 ;; given instruction does not shift one of its input operands.
145 (define_attr "shift" "" (const_int 0))
146
147 ; Floating Point Unit.  If we only have floating point emulation, then there
148 ; is no point in scheduling the floating point insns.  (Well, for best
149 ; performance we should try and group them together).
150 (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
151   (const (symbol_ref "arm_fpu_attr")))
152
153 ; LENGTH of an instruction (in bytes)
154 (define_attr "length" "" (const_int 4))
155
156 ; POOL_RANGE is how far away from a constant pool entry that this insn
157 ; can be placed.  If the distance is zero, then this insn will never
158 ; reference the pool.
159 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
160 ; before its address.
161 (define_attr "pool_range" "" (const_int 0))
162 (define_attr "neg_pool_range" "" (const_int 0))
163
164 ; An assembler sequence may clobber the condition codes without us knowing.
165 ; If such an insn references the pool, then we have no way of knowing how,
166 ; so use the most conservative value for pool_range.
167 (define_asm_attributes
168  [(set_attr "conds" "clob")
169   (set_attr "length" "4")
170   (set_attr "pool_range" "250")])
171
172 ;; The instruction used to implement a particular pattern.  This
173 ;; information is used by pipeline descriptions to provide accurate
174 ;; scheduling information.
175
176 (define_attr "insn"
177         "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"
178         (const_string "other"))
179
180 ; TYPE attribute is used to detect floating point instructions which, if
181 ; running on a co-processor can run in parallel with other, basic instructions
182 ; If write-buffer scheduling is enabled then it can also be used in the
183 ; scheduling of writes.
184
185 ; Classification of each insn
186 ; alu           any alu  instruction that doesn't hit memory or fp
187 ;               regs or have a shifted source operand
188 ; alu_shift     any data instruction that doesn't hit memory or fp
189 ;               regs, but has a source operand shifted by a constant
190 ; alu_shift_reg any data instruction that doesn't hit memory or fp
191 ;               regs, but has a source operand shifted by a register value
192 ; mult          a multiply instruction
193 ; block         blockage insn, this blocks all functional units
194 ; float         a floating point arithmetic operation (subject to expansion)
195 ; fdivd         DFmode floating point division
196 ; fdivs         SFmode floating point division
197 ; fmul          Floating point multiply
198 ; ffmul         Fast floating point multiply
199 ; farith        Floating point arithmetic (4 cycle)
200 ; ffarith       Fast floating point arithmetic (2 cycle)
201 ; float_em      a floating point arithmetic operation that is normally emulated
202 ;               even on a machine with an fpa.
203 ; f_load        a floating point load from memory
204 ; f_store       a floating point store to memory
205 ; f_mem_r       a transfer of a floating point register to a real reg via mem
206 ; r_mem_f       the reverse of f_mem_r
207 ; f_2_r         fast transfer float to arm (no memory needed)
208 ; r_2_f         fast transfer arm to float
209 ; branch        a branch
210 ; call          a subroutine call
211 ; load_byte     load byte(s) from memory to arm registers
212 ; load1         load 1 word from memory to arm registers
213 ; load2         load 2 words from memory to arm registers
214 ; load3         load 3 words from memory to arm registers
215 ; load4         load 4 words from memory to arm registers
216 ; store         store 1 word to memory from arm registers
217 ; store2        store 2 words
218 ; store3        store 3 words
219 ; store4        store 4 (or more) words
220 ;  Additions for Cirrus Maverick co-processor:
221 ; mav_farith    Floating point arithmetic (4 cycle)
222 ; mav_dmult     Double multiplies (7 cycle)
223 ;
224 (define_attr "type"
225         "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,float_em,f_load,f_store,f_mem_r,r_mem_f,f_2_r,r_2_f,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult" 
226         (if_then_else 
227          (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
228          (const_string "mult")
229          (const_string "alu")))
230
231 ; Load scheduling, set from the arm_ld_sched variable
232 ; initialized by arm_override_options() 
233 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
234
235 ; condition codes: this one is used by final_prescan_insn to speed up
236 ; conditionalizing instructions.  It saves having to scan the rtl to see if
237 ; it uses or alters the condition codes.
238
239 ; USE means that the condition codes are used by the insn in the process of
240 ;   outputting code, this means (at present) that we can't use the insn in
241 ;   inlined branches
242 ;
243 ; SET means that the purpose of the insn is to set the condition codes in a
244 ;   well defined manner.
245 ;
246 ; CLOB means that the condition codes are altered in an undefined manner, if
247 ;   they are altered at all
248 ;
249 ; JUMP_CLOB is used when the condition cannot be represented by a single
250 ;   instruction (UNEQ and LTGT).  These cannot be predicated.
251 ;
252 ; NOCOND means that the condition codes are neither altered nor affect the
253 ;   output of this insn
254
255 (define_attr "conds" "use,set,clob,jump_clob,nocond"
256         (if_then_else (eq_attr "type" "call")
257          (if_then_else (eq_attr "prog_mode" "prog32")
258           (const_string "clob") (const_string "nocond"))
259          (const_string "nocond")))
260
261 ; Predicable means that the insn can be conditionally executed based on
262 ; an automatically added predicate (additional patterns are generated by 
263 ; gen...).  We default to 'no' because no Thumb patterns match this rule
264 ; and not all ARM patterns do.
265 (define_attr "predicable" "no,yes" (const_string "no"))
266
267 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
268 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
269 ; suffer blockages enough to warrant modelling this (and it can adversely
270 ; affect the schedule).
271 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
272
273 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
274 ; to stall the processor.  Used with model_wbuf above.
275 (define_attr "write_conflict" "no,yes"
276   (if_then_else (eq_attr "type"
277                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
278                 (const_string "yes")
279                 (const_string "no")))
280
281 ; Classify the insns into those that take one cycle and those that take more
282 ; than one on the main cpu execution unit.
283 (define_attr "core_cycles" "single,multi"
284   (if_then_else (eq_attr "type"
285                  "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
286                 (const_string "single")
287                 (const_string "multi")))
288
289 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
290 ;; distant label.  Only applicable to Thumb code.
291 (define_attr "far_jump" "yes,no" (const_string "no"))
292
293 ;;---------------------------------------------------------------------------
294 ;; Pipeline descriptions
295
296 ;; Processor type.  This attribute must exactly match the table in 
297 ;; arm-cores.def.
298 (define_attr "tune" 
299              "arm2,arm250,arm3,arm6,arm60,arm600,arm610,arm620,arm7,arm7m,arm7d,arm7dm,arm7di,arm7dmi,arm70,arm700,arm700i,arm710,arm720,arm710c,arm7100,arm7500,arm7500fe,arm7tdmi,arm710t,arm720t,arm740t,arm8,arm810,arm9,arm920,arm920t,arm940t,arm9tdmi,arm9e,ep9312,strongarm,strongarm110,strongarm1100,strongarm1110,arm10tdmi,arm1020t,arm926ejs,arm1026ejs,xscale,iwmmxt,arm1136js,arm1136jfs"
300              (const (symbol_ref "arm_tune")))
301
302 ;; True if the generic scheduling description should be used.
303
304 (define_attr "generic_sched" "yes,no"
305         (if_then_else 
306          (eq_attr "tune" "arm926ejs,arm1026ejs,arm1136js,arm1136jfs") 
307          (const_string "no")
308          (const_string "yes")))
309         
310 (include "arm-generic.md")
311 (include "arm926ejs.md")
312 (include "arm1026ejs.md")
313 (include "arm1136jfs.md")
314
315 \f
316 ;;---------------------------------------------------------------------------
317 ;; Insn patterns
318 ;;
319 ;; Addition insns.
320
321 ;; Note: For DImode insns, there is normally no reason why operands should
322 ;; not be in the same register, what we don't want is for something being
323 ;; written to partially overlap something that is an input.
324 ;; Cirrus 64bit additions should not be split because we have a native
325 ;; 64bit addition instructions.
326
327 (define_expand "adddi3"
328  [(parallel
329    [(set (match_operand:DI           0 "s_register_operand" "")
330           (plus:DI (match_operand:DI 1 "s_register_operand" "")
331                    (match_operand:DI 2 "s_register_operand" "")))
332     (clobber (reg:CC CC_REGNUM))])]
333   "TARGET_EITHER"
334   "
335   if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
336     {
337       if (!cirrus_fp_register (operands[0], DImode))
338         operands[0] = force_reg (DImode, operands[0]);
339       if (!cirrus_fp_register (operands[1], DImode))
340         operands[1] = force_reg (DImode, operands[1]);
341       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
342       DONE;
343     }
344
345   if (TARGET_THUMB)
346     {
347       if (GET_CODE (operands[1]) != REG)
348         operands[1] = force_reg (SImode, operands[1]);
349       if (GET_CODE (operands[2]) != REG)
350         operands[2] = force_reg (SImode, operands[2]);
351      }
352   "
353 )
354
355 (define_insn "*thumb_adddi3"
356   [(set (match_operand:DI          0 "register_operand" "=l")
357         (plus:DI (match_operand:DI 1 "register_operand" "%0")
358                  (match_operand:DI 2 "register_operand" "l")))
359    (clobber (reg:CC CC_REGNUM))
360   ]
361   "TARGET_THUMB"
362   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
363   [(set_attr "length" "4")]
364 )
365
366 (define_insn_and_split "*arm_adddi3"
367   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
368         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
369                  (match_operand:DI 2 "s_register_operand" "r,  0")))
370    (clobber (reg:CC CC_REGNUM))]
371   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
372   "#"
373   "TARGET_ARM && reload_completed"
374   [(parallel [(set (reg:CC_C CC_REGNUM)
375                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
376                                  (match_dup 1)))
377               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
378    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
379                                (plus:SI (match_dup 4) (match_dup 5))))]
380   "
381   {
382     operands[3] = gen_highpart (SImode, operands[0]);
383     operands[0] = gen_lowpart (SImode, operands[0]);
384     operands[4] = gen_highpart (SImode, operands[1]);
385     operands[1] = gen_lowpart (SImode, operands[1]);
386     operands[5] = gen_highpart (SImode, operands[2]);
387     operands[2] = gen_lowpart (SImode, operands[2]);
388   }"
389   [(set_attr "conds" "clob")
390    (set_attr "length" "8")]
391 )
392
393 (define_insn_and_split "*adddi_sesidi_di"
394   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
395         (plus:DI (sign_extend:DI
396                   (match_operand:SI 2 "s_register_operand" "r,r"))
397                  (match_operand:DI 1 "s_register_operand" "r,0")))
398    (clobber (reg:CC CC_REGNUM))]
399   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
400   "#"
401   "TARGET_ARM && reload_completed"
402   [(parallel [(set (reg:CC_C CC_REGNUM)
403                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
404                                  (match_dup 1)))
405               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
406    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
407                                (plus:SI (ashiftrt:SI (match_dup 2)
408                                                      (const_int 31))
409                                         (match_dup 4))))]
410   "
411   {
412     operands[3] = gen_highpart (SImode, operands[0]);
413     operands[0] = gen_lowpart (SImode, operands[0]);
414     operands[4] = gen_highpart (SImode, operands[1]);
415     operands[1] = gen_lowpart (SImode, operands[1]);
416     operands[2] = gen_lowpart (SImode, operands[2]);
417   }"
418   [(set_attr "conds" "clob")
419    (set_attr "length" "8")]
420 )
421
422 (define_insn_and_split "*adddi_zesidi_di"
423   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
424         (plus:DI (zero_extend:DI
425                   (match_operand:SI 2 "s_register_operand" "r,r"))
426                  (match_operand:DI 1 "s_register_operand" "r,0")))
427    (clobber (reg:CC CC_REGNUM))]
428   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
429   "#"
430   "TARGET_ARM && reload_completed"
431   [(parallel [(set (reg:CC_C CC_REGNUM)
432                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
433                                  (match_dup 1)))
434               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
435    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
436                                (plus:SI (match_dup 4) (const_int 0))))]
437   "
438   {
439     operands[3] = gen_highpart (SImode, operands[0]);
440     operands[0] = gen_lowpart (SImode, operands[0]);
441     operands[4] = gen_highpart (SImode, operands[1]);
442     operands[1] = gen_lowpart (SImode, operands[1]);
443     operands[2] = gen_lowpart (SImode, operands[2]);
444   }"
445   [(set_attr "conds" "clob")
446    (set_attr "length" "8")]
447 )
448
449 (define_expand "addsi3"
450   [(set (match_operand:SI          0 "s_register_operand" "")
451         (plus:SI (match_operand:SI 1 "s_register_operand" "")
452                  (match_operand:SI 2 "reg_or_int_operand" "")))]
453   "TARGET_EITHER"
454   "
455   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
456     {
457       arm_split_constant (PLUS, SImode, NULL_RTX,
458                           INTVAL (operands[2]), operands[0], operands[1],
459                           (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
460       DONE;
461     }
462   "
463 )
464
465 ; If there is a scratch available, this will be faster than synthesizing the
466 ; addition.
467 (define_peephole2
468   [(match_scratch:SI 3 "r")
469    (set (match_operand:SI          0 "s_register_operand" "")
470         (plus:SI (match_operand:SI 1 "s_register_operand" "")
471                  (match_operand:SI 2 "const_int_operand"  "")))]
472   "TARGET_ARM &&
473    !(const_ok_for_arm (INTVAL (operands[2]))
474      || const_ok_for_arm (-INTVAL (operands[2])))
475     && const_ok_for_arm (~INTVAL (operands[2]))"
476   [(set (match_dup 3) (match_dup 2))
477    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
478   ""
479 )
480
481 (define_insn_and_split "*arm_addsi3"
482   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
483         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
484                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
485   "TARGET_ARM"
486   "@
487    add%?\\t%0, %1, %2
488    sub%?\\t%0, %1, #%n2
489    #"
490   "TARGET_ARM &&
491    GET_CODE (operands[2]) == CONST_INT
492    && !(const_ok_for_arm (INTVAL (operands[2]))
493         || const_ok_for_arm (-INTVAL (operands[2])))"
494   [(clobber (const_int 0))]
495   "
496   arm_split_constant (PLUS, SImode, curr_insn,
497                       INTVAL (operands[2]), operands[0],
498                       operands[1], 0);
499   DONE;
500   "
501   [(set_attr "length" "4,4,16")
502    (set_attr "predicable" "yes")]
503 )
504
505 ;; Register group 'k' is a single register group containing only the stack
506 ;; register.  Trying to reload it will always fail catastrophically,
507 ;; so never allow those alternatives to match if reloading is needed.
508
509 (define_insn "*thumb_addsi3"
510   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
511         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
512                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
513   "TARGET_THUMB"
514   "*
515    static const char * const asms[] = 
516    {
517      \"add\\t%0, %0, %2\",
518      \"sub\\t%0, %0, #%n2\",
519      \"add\\t%0, %1, %2\",
520      \"add\\t%0, %0, %2\",
521      \"add\\t%0, %0, %2\",
522      \"add\\t%0, %1, %2\",
523      \"add\\t%0, %1, %2\"
524    };
525    if ((which_alternative == 2 || which_alternative == 6)
526        && GET_CODE (operands[2]) == CONST_INT
527        && INTVAL (operands[2]) < 0)
528      return \"sub\\t%0, %1, #%n2\";
529    return asms[which_alternative];
530   "
531   [(set_attr "length" "2")]
532 )
533
534 ;; Reloading and elimination of the frame pointer can
535 ;; sometimes cause this optimization to be missed.
536 (define_peephole2
537   [(set (match_operand:SI 0 "register_operand" "")
538         (match_operand:SI 1 "const_int_operand" ""))
539    (set (match_dup 0)
540         (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))]
541   "TARGET_THUMB
542    && REGNO (operands[2]) == STACK_POINTER_REGNUM 
543    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
544    && (INTVAL (operands[1]) & 3) == 0"
545   [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
546   ""
547 )
548
549 (define_insn "*addsi3_compare0"
550   [(set (reg:CC_NOOV CC_REGNUM)
551         (compare:CC_NOOV
552          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
553                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
554          (const_int 0)))
555    (set (match_operand:SI 0 "s_register_operand" "=r,r")
556         (plus:SI (match_dup 1) (match_dup 2)))]
557   "TARGET_ARM"
558   "@
559    add%?s\\t%0, %1, %2
560    sub%?s\\t%0, %1, #%n2"
561   [(set_attr "conds" "set")]
562 )
563
564 (define_insn "*addsi3_compare0_scratch"
565   [(set (reg:CC_NOOV CC_REGNUM)
566         (compare:CC_NOOV
567          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
568                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
569          (const_int 0)))]
570   "TARGET_ARM"
571   "@
572    cmn%?\\t%0, %1
573    cmp%?\\t%0, #%n1"
574   [(set_attr "conds" "set")]
575 )
576
577 ;; These patterns are the same ones as the two regular addsi3_compare0
578 ;; patterns, except we write them slightly different - the combiner
579 ;; tends to generate them this way.
580 (define_insn "*addsi3_compare0_for_combiner"
581   [(set (reg:CC CC_REGNUM)
582         (compare:CC
583          (match_operand:SI 1 "s_register_operand" "r,r")
584          (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
585    (set (match_operand:SI 0 "s_register_operand" "=r,r")
586         (plus:SI (match_dup 1) (match_dup 2)))]
587   "TARGET_ARM"
588   "@
589    add%?s\\t%0, %1, %2
590    sub%?s\\t%0, %1, #%n2"
591   [(set_attr "conds" "set")]
592 )
593
594 (define_insn "*addsi3_compare0_scratch_for_combiner"
595   [(set (reg:CC CC_REGNUM)
596         (compare:CC
597          (match_operand:SI 0 "s_register_operand" "r,r")
598          (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
599   "TARGET_ARM"
600   "@
601    cmn%?\\t%0, %1
602    cmp%?\\t%0, #%n1"
603   [(set_attr "conds" "set")]
604 )
605
606 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
607 ;; addend is a constant.
608 (define_insn "*cmpsi2_addneg"
609   [(set (reg:CC CC_REGNUM)
610         (compare:CC
611          (match_operand:SI 1 "s_register_operand" "r,r")
612          (match_operand:SI 2 "arm_addimm_operand" "I,L")))
613    (set (match_operand:SI 0 "s_register_operand" "=r,r")
614         (plus:SI (match_dup 1)
615                  (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
616   "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
617   "@
618    sub%?s\\t%0, %1, %2
619    add%?s\\t%0, %1, #%n2"
620   [(set_attr "conds" "set")]
621 )
622
623 ;; Convert the sequence
624 ;;  sub  rd, rn, #1
625 ;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
626 ;;  bne  dest
627 ;; into
628 ;;  subs rd, rn, #1
629 ;;  bcs  dest   ((unsigned)rn >= 1)
630 ;; similarly for the beq variant using bcc.
631 ;; This is a common looping idiom (while (n--))
632 (define_peephole2
633   [(set (match_operand:SI 0 "s_register_operand" "")
634         (plus:SI (match_operand:SI 1 "s_register_operand" "")
635                  (const_int -1)))
636    (set (match_operand 2 "cc_register" "")
637         (compare (match_dup 0) (const_int -1)))
638    (set (pc)
639         (if_then_else (match_operator 3 "equality_operator"
640                        [(match_dup 2) (const_int 0)])
641                       (match_operand 4 "" "")
642                       (match_operand 5 "" "")))]
643   "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
644   [(parallel[
645     (set (match_dup 2)
646          (compare:CC
647           (match_dup 1) (const_int 1)))
648     (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
649    (set (pc)
650         (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
651                       (match_dup 4)
652                       (match_dup 5)))]
653   "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
654    operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
655                                   ? GEU : LTU),
656                                  VOIDmode, 
657                                  operands[2], const0_rtx);"
658 )
659
660 ;; The next four insns work because they compare the result with one of
661 ;; the operands, and we know that the use of the condition code is
662 ;; either GEU or LTU, so we can use the carry flag from the addition
663 ;; instead of doing the compare a second time.
664 (define_insn "*addsi3_compare_op1"
665   [(set (reg:CC_C CC_REGNUM)
666         (compare:CC_C
667          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
668                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
669          (match_dup 1)))
670    (set (match_operand:SI 0 "s_register_operand" "=r,r")
671         (plus:SI (match_dup 1) (match_dup 2)))]
672   "TARGET_ARM"
673   "@
674    add%?s\\t%0, %1, %2
675    sub%?s\\t%0, %1, #%n2"
676   [(set_attr "conds" "set")]
677 )
678
679 (define_insn "*addsi3_compare_op2"
680   [(set (reg:CC_C CC_REGNUM)
681         (compare:CC_C
682          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
683                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
684          (match_dup 2)))
685    (set (match_operand:SI 0 "s_register_operand" "=r,r")
686         (plus:SI (match_dup 1) (match_dup 2)))]
687   "TARGET_ARM"
688   "@
689    add%?s\\t%0, %1, %2
690    sub%?s\\t%0, %1, #%n2"
691   [(set_attr "conds" "set")]
692 )
693
694 (define_insn "*compare_addsi2_op0"
695   [(set (reg:CC_C CC_REGNUM)
696         (compare:CC_C
697          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
698                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
699          (match_dup 0)))]
700   "TARGET_ARM"
701   "@
702    cmn%?\\t%0, %1
703    cmp%?\\t%0, #%n1"
704   [(set_attr "conds" "set")]
705 )
706
707 (define_insn "*compare_addsi2_op1"
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 1)))]
713   "TARGET_ARM"
714   "@
715    cmn%?\\t%0, %1
716    cmp%?\\t%0, #%n1"
717   [(set_attr "conds" "set")]
718 )
719
720 (define_insn "*addsi3_carryin"
721   [(set (match_operand:SI 0 "s_register_operand" "=r")
722         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
723                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
724                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
725   "TARGET_ARM"
726   "adc%?\\t%0, %1, %2"
727   [(set_attr "conds" "use")]
728 )
729
730 (define_insn "*addsi3_carryin_shift"
731   [(set (match_operand:SI 0 "s_register_operand" "=r")
732         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
733                  (plus:SI
734                    (match_operator:SI 2 "shift_operator"
735                       [(match_operand:SI 3 "s_register_operand" "r")
736                        (match_operand:SI 4 "reg_or_int_operand" "rM")])
737                     (match_operand:SI 1 "s_register_operand" "r"))))]
738   "TARGET_ARM"
739   "adc%?\\t%0, %1, %3%S2"
740   [(set_attr "conds" "use")
741    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
742                       (const_string "alu_shift")
743                       (const_string "alu_shift_reg")))]
744 )
745
746 (define_insn "*addsi3_carryin_alt1"
747   [(set (match_operand:SI 0 "s_register_operand" "=r")
748         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
749                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
750                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
751   "TARGET_ARM"
752   "adc%?\\t%0, %1, %2"
753   [(set_attr "conds" "use")]
754 )
755
756 (define_insn "*addsi3_carryin_alt2"
757   [(set (match_operand:SI 0 "s_register_operand" "=r")
758         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
759                           (match_operand:SI 1 "s_register_operand" "r"))
760                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
761   "TARGET_ARM"
762   "adc%?\\t%0, %1, %2"
763   [(set_attr "conds" "use")]
764 )
765
766 (define_insn "*addsi3_carryin_alt3"
767   [(set (match_operand:SI 0 "s_register_operand" "=r")
768         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
769                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
770                  (match_operand:SI 1 "s_register_operand" "r")))]
771   "TARGET_ARM"
772   "adc%?\\t%0, %1, %2"
773   [(set_attr "conds" "use")]
774 )
775
776 (define_insn "incscc"
777   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
778         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
779                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
780                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
781   "TARGET_ARM"
782   "@
783   add%d2\\t%0, %1, #1
784   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
785   [(set_attr "conds" "use")
786    (set_attr "length" "4,8")]
787 )
788
789 ; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
790 (define_split
791   [(set (match_operand:SI 0 "s_register_operand" "")
792         (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
793                             (match_operand:SI 2 "s_register_operand" ""))
794                  (const_int -1)))
795    (clobber (match_operand:SI 3 "s_register_operand" ""))]
796   "TARGET_ARM"
797   [(set (match_dup 3) (match_dup 1))
798    (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
799   "
800   operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
801 ")
802
803 (define_expand "addsf3"
804   [(set (match_operand:SF          0 "s_register_operand" "")
805         (plus:SF (match_operand:SF 1 "s_register_operand" "")
806                  (match_operand:SF 2 "arm_float_add_operand" "")))]
807   "TARGET_ARM && TARGET_HARD_FLOAT"
808   "
809   if (TARGET_MAVERICK
810       && !cirrus_fp_register (operands[2], SFmode))
811     operands[2] = force_reg (SFmode, operands[2]);
812 ")
813
814 (define_expand "adddf3"
815   [(set (match_operand:DF          0 "s_register_operand" "")
816         (plus:DF (match_operand:DF 1 "s_register_operand" "")
817                  (match_operand:DF 2 "arm_float_add_operand" "")))]
818   "TARGET_ARM && TARGET_HARD_FLOAT"
819   "
820   if (TARGET_MAVERICK
821       && !cirrus_fp_register (operands[2], DFmode))
822     operands[2] = force_reg (DFmode, operands[2]);
823 ")
824
825 (define_expand "subdi3"
826  [(parallel
827    [(set (match_operand:DI            0 "s_register_operand" "")
828           (minus:DI (match_operand:DI 1 "s_register_operand" "")
829                     (match_operand:DI 2 "s_register_operand" "")))
830     (clobber (reg:CC CC_REGNUM))])]
831   "TARGET_EITHER"
832   "
833   if (TARGET_HARD_FLOAT && TARGET_MAVERICK
834       && TARGET_ARM
835       && cirrus_fp_register (operands[0], DImode)
836       && cirrus_fp_register (operands[1], DImode))
837     {
838       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
839       DONE;
840     }
841
842   if (TARGET_THUMB)
843     {
844       if (GET_CODE (operands[1]) != REG)
845         operands[1] = force_reg (SImode, operands[1]);
846       if (GET_CODE (operands[2]) != REG)
847         operands[2] = force_reg (SImode, operands[2]);
848      }  
849   "
850 )
851
852 (define_insn "*arm_subdi3"
853   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
854         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
855                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
856    (clobber (reg:CC CC_REGNUM))]
857   "TARGET_ARM"
858   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
859   [(set_attr "conds" "clob")
860    (set_attr "length" "8")]
861 )
862
863 (define_insn "*thumb_subdi3"
864   [(set (match_operand:DI           0 "register_operand" "=l")
865         (minus:DI (match_operand:DI 1 "register_operand"  "0")
866                   (match_operand:DI 2 "register_operand"  "l")))
867    (clobber (reg:CC CC_REGNUM))]
868   "TARGET_THUMB"
869   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
870   [(set_attr "length" "4")]
871 )
872
873 (define_insn "*subdi_di_zesidi"
874   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
875         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
876                   (zero_extend:DI
877                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
878    (clobber (reg:CC CC_REGNUM))]
879   "TARGET_ARM"
880   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
881   [(set_attr "conds" "clob")
882    (set_attr "length" "8")]
883 )
884
885 (define_insn "*subdi_di_sesidi"
886   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
887         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
888                   (sign_extend:DI
889                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
890    (clobber (reg:CC CC_REGNUM))]
891   "TARGET_ARM"
892   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
893   [(set_attr "conds" "clob")
894    (set_attr "length" "8")]
895 )
896
897 (define_insn "*subdi_zesidi_di"
898   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
899         (minus:DI (zero_extend:DI
900                    (match_operand:SI 2 "s_register_operand"  "r,r"))
901                   (match_operand:DI  1 "s_register_operand" "?r,0")))
902    (clobber (reg:CC CC_REGNUM))]
903   "TARGET_ARM"
904   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
905   [(set_attr "conds" "clob")
906    (set_attr "length" "8")]
907 )
908
909 (define_insn "*subdi_sesidi_di"
910   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
911         (minus:DI (sign_extend:DI
912                    (match_operand:SI 2 "s_register_operand"   "r,r"))
913                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
914    (clobber (reg:CC CC_REGNUM))]
915   "TARGET_ARM"
916   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
917   [(set_attr "conds" "clob")
918    (set_attr "length" "8")]
919 )
920
921 (define_insn "*subdi_zesidi_zesidi"
922   [(set (match_operand:DI            0 "s_register_operand" "=r")
923         (minus:DI (zero_extend:DI
924                    (match_operand:SI 1 "s_register_operand"  "r"))
925                   (zero_extend:DI
926                    (match_operand:SI 2 "s_register_operand"  "r"))))
927    (clobber (reg:CC CC_REGNUM))]
928   "TARGET_ARM"
929   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
930   [(set_attr "conds" "clob")
931    (set_attr "length" "8")]
932 )
933
934 (define_expand "subsi3"
935   [(set (match_operand:SI           0 "s_register_operand" "")
936         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
937                   (match_operand:SI 2 "s_register_operand" "")))]
938   "TARGET_EITHER"
939   "
940   if (GET_CODE (operands[1]) == CONST_INT)
941     {
942       if (TARGET_ARM)
943         {
944           arm_split_constant (MINUS, SImode, NULL_RTX,
945                               INTVAL (operands[1]), operands[0],
946                               operands[2],
947                               (no_new_pseudos ? 0
948                                :  preserve_subexpressions_p ()));
949           DONE;
950         }
951       else /* TARGET_THUMB */
952         operands[1] = force_reg (SImode, operands[1]);
953     }
954   "
955 )
956
957 (define_insn "*thumb_subsi3_insn"
958   [(set (match_operand:SI           0 "register_operand" "=l")
959         (minus:SI (match_operand:SI 1 "register_operand" "l")
960                   (match_operand:SI 2 "register_operand" "l")))]
961   "TARGET_THUMB"
962   "sub\\t%0, %1, %2"
963   [(set_attr "length" "2")]
964 )
965
966 (define_insn_and_split "*arm_subsi3_insn"
967   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
968         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
969                   (match_operand:SI 2 "s_register_operand" "r,r")))]
970   "TARGET_ARM"
971   "@
972    rsb%?\\t%0, %2, %1
973    #"
974   "TARGET_ARM
975    && GET_CODE (operands[1]) == CONST_INT
976    && !const_ok_for_arm (INTVAL (operands[1]))"
977   [(clobber (const_int 0))]
978   "
979   arm_split_constant (MINUS, SImode, curr_insn,
980                       INTVAL (operands[1]), operands[0], operands[2], 0);
981   DONE;
982   "
983   [(set_attr "length" "4,16")
984    (set_attr "predicable" "yes")]
985 )
986
987 (define_peephole2
988   [(match_scratch:SI 3 "r")
989    (set (match_operand:SI           0 "s_register_operand" "")
990         (minus:SI (match_operand:SI 1 "const_int_operand" "")
991                   (match_operand:SI 2 "s_register_operand" "")))]
992   "TARGET_ARM
993    && !const_ok_for_arm (INTVAL (operands[1]))
994    && const_ok_for_arm (~INTVAL (operands[1]))"
995   [(set (match_dup 3) (match_dup 1))
996    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
997   ""
998 )
999
1000 (define_insn "*subsi3_compare0"
1001   [(set (reg:CC_NOOV CC_REGNUM)
1002         (compare:CC_NOOV
1003          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1004                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1005          (const_int 0)))
1006    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1007         (minus:SI (match_dup 1) (match_dup 2)))]
1008   "TARGET_ARM"
1009   "@
1010    sub%?s\\t%0, %1, %2
1011    rsb%?s\\t%0, %2, %1"
1012   [(set_attr "conds" "set")]
1013 )
1014
1015 (define_insn "decscc"
1016   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1017         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1018                   (match_operator:SI 2 "arm_comparison_operator"
1019                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1020   "TARGET_ARM"
1021   "@
1022    sub%d2\\t%0, %1, #1
1023    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1024   [(set_attr "conds" "use")
1025    (set_attr "length" "*,8")]
1026 )
1027
1028 (define_expand "subsf3"
1029   [(set (match_operand:SF           0 "s_register_operand" "")
1030         (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1031                   (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1032   "TARGET_ARM && TARGET_HARD_FLOAT"
1033   "
1034   if (TARGET_MAVERICK)
1035     {
1036       if (!cirrus_fp_register (operands[1], SFmode))
1037         operands[1] = force_reg (SFmode, operands[1]);
1038       if (!cirrus_fp_register (operands[2], SFmode))
1039         operands[2] = force_reg (SFmode, operands[2]);
1040     }
1041 ")
1042
1043 (define_expand "subdf3"
1044   [(set (match_operand:DF           0 "s_register_operand" "")
1045         (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1046                   (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1047   "TARGET_ARM && TARGET_HARD_FLOAT"
1048   "
1049   if (TARGET_MAVERICK)
1050     {
1051        if (!cirrus_fp_register (operands[1], DFmode))
1052          operands[1] = force_reg (DFmode, operands[1]);
1053        if (!cirrus_fp_register (operands[2], DFmode))
1054          operands[2] = force_reg (DFmode, operands[2]);
1055     }
1056 ")
1057
1058 \f
1059 ;; Multiplication insns
1060
1061 (define_expand "mulsi3"
1062   [(set (match_operand:SI          0 "s_register_operand" "")
1063         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1064                  (match_operand:SI 1 "s_register_operand" "")))]
1065   "TARGET_EITHER"
1066   ""
1067 )
1068
1069 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1070 (define_insn "*arm_mulsi3"
1071   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1072         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1073                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1074   "TARGET_ARM"
1075   "mul%?\\t%0, %2, %1"
1076   [(set_attr "insn" "mul")
1077    (set_attr "predicable" "yes")]
1078 )
1079
1080 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1081 ; 1 and 2; are the same, because reload will make operand 0 match 
1082 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1083 ; this by adding another alternative to match this case, and then `reload' 
1084 ; it ourselves.  This alternative must come first.
1085 (define_insn "*thumb_mulsi3"
1086   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1087         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1088                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1089   "TARGET_THUMB"
1090   "*
1091   if (which_alternative < 2)
1092     return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1093   else
1094     return \"mul\\t%0, %0, %2\";
1095   "
1096   [(set_attr "length" "4,4,2")
1097    (set_attr "insn" "mul")]
1098 )
1099
1100 (define_insn "*mulsi3_compare0"
1101   [(set (reg:CC_NOOV CC_REGNUM)
1102         (compare:CC_NOOV (mult:SI
1103                           (match_operand:SI 2 "s_register_operand" "r,r")
1104                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1105                          (const_int 0)))
1106    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1107         (mult:SI (match_dup 2) (match_dup 1)))]
1108   "TARGET_ARM && !arm_arch_xscale"
1109   "mul%?s\\t%0, %2, %1"
1110   [(set_attr "conds" "set")
1111    (set_attr "insn" "muls")]
1112 )
1113
1114 (define_insn "*mulsi_compare0_scratch"
1115   [(set (reg:CC_NOOV CC_REGNUM)
1116         (compare:CC_NOOV (mult:SI
1117                           (match_operand:SI 2 "s_register_operand" "r,r")
1118                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1119                          (const_int 0)))
1120    (clobber (match_scratch:SI 0 "=&r,&r"))]
1121   "TARGET_ARM && !arm_arch_xscale"
1122   "mul%?s\\t%0, %2, %1"
1123   [(set_attr "conds" "set")
1124    (set_attr "insn" "muls")]
1125 )
1126
1127 ;; Unnamed templates to match MLA instruction.
1128
1129 (define_insn "*mulsi3addsi"
1130   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1131         (plus:SI
1132           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1133                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1134           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1135   "TARGET_ARM"
1136   "mla%?\\t%0, %2, %1, %3"
1137   [(set_attr "insn" "mla")
1138    (set_attr "predicable" "yes")]
1139 )
1140
1141 (define_insn "*mulsi3addsi_compare0"
1142   [(set (reg:CC_NOOV CC_REGNUM)
1143         (compare:CC_NOOV
1144          (plus:SI (mult:SI
1145                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1146                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1147                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1148          (const_int 0)))
1149    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1150         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1151                  (match_dup 3)))]
1152   "TARGET_ARM && !arm_arch_xscale"
1153   "mla%?s\\t%0, %2, %1, %3"
1154   [(set_attr "conds" "set")
1155    (set_attr "insn" "mlas")]
1156 )
1157
1158 (define_insn "*mulsi3addsi_compare0_scratch"
1159   [(set (reg:CC_NOOV CC_REGNUM)
1160         (compare:CC_NOOV
1161          (plus:SI (mult:SI
1162                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1163                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1164                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1165          (const_int 0)))
1166    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1167   "TARGET_ARM && !arm_arch_xscale"
1168   "mla%?s\\t%0, %2, %1, %3"
1169   [(set_attr "conds" "set")
1170    (set_attr "insn" "mlas")]
1171 )
1172
1173 ;; Unnamed template to match long long multiply-accumulate (smlal)
1174
1175 (define_insn "*mulsidi3adddi"
1176   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1177         (plus:DI
1178          (mult:DI
1179           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1180           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1181          (match_operand:DI 1 "s_register_operand" "0")))]
1182   "TARGET_ARM && arm_arch3m"
1183   "smlal%?\\t%Q0, %R0, %3, %2"
1184   [(set_attr "insn" "smlal")
1185    (set_attr "predicable" "yes")]
1186 )
1187
1188 (define_insn "mulsidi3"
1189   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1190         (mult:DI
1191          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1192          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1193   "TARGET_ARM && arm_arch3m"
1194   "smull%?\\t%Q0, %R0, %1, %2"
1195   [(set_attr "insn" "smull")
1196    (set_attr "predicable" "yes")]
1197 )
1198
1199 (define_insn "umulsidi3"
1200   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1201         (mult:DI
1202          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1203          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1204   "TARGET_ARM && arm_arch3m"
1205   "umull%?\\t%Q0, %R0, %1, %2"
1206   [(set_attr "insn" "umull")
1207    (set_attr "predicable" "yes")]
1208 )
1209
1210 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1211
1212 (define_insn "*umulsidi3adddi"
1213   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1214         (plus:DI
1215          (mult:DI
1216           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1217           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1218          (match_operand:DI 1 "s_register_operand" "0")))]
1219   "TARGET_ARM && arm_arch3m"
1220   "umlal%?\\t%Q0, %R0, %3, %2"
1221   [(set_attr "insn" "umlal")
1222    (set_attr "predicable" "yes")]
1223 )
1224
1225 (define_insn "smulsi3_highpart"
1226   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1227         (truncate:SI
1228          (lshiftrt:DI
1229           (mult:DI
1230            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1231            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1232           (const_int 32))))
1233    (clobber (match_scratch:SI 3 "=&r,&r"))]
1234   "TARGET_ARM && arm_arch3m"
1235   "smull%?\\t%3, %0, %2, %1"
1236   [(set_attr "insn" "smull")
1237    (set_attr "predicable" "yes")]
1238 )
1239
1240 (define_insn "umulsi3_highpart"
1241   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1242         (truncate:SI
1243          (lshiftrt:DI
1244           (mult:DI
1245            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1246            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1247           (const_int 32))))
1248    (clobber (match_scratch:SI 3 "=&r,&r"))]
1249   "TARGET_ARM && arm_arch3m"
1250   "umull%?\\t%3, %0, %2, %1"
1251   [(set_attr "insn" "umull")
1252    (set_attr "predicable" "yes")]
1253 )
1254
1255 (define_insn "mulhisi3"
1256   [(set (match_operand:SI 0 "s_register_operand" "=r")
1257         (mult:SI (sign_extend:SI
1258                   (match_operand:HI 1 "s_register_operand" "%r"))
1259                  (sign_extend:SI
1260                   (match_operand:HI 2 "s_register_operand" "r"))))]
1261   "TARGET_ARM && arm_arch5e"
1262   "smulbb%?\\t%0, %1, %2"
1263   [(set_attr "insn" "smulxy")
1264    (set_attr "predicable" "yes")]
1265 )
1266
1267 (define_insn "*mulhisi3tb"
1268   [(set (match_operand:SI 0 "s_register_operand" "=r")
1269         (mult:SI (ashiftrt:SI
1270                   (match_operand:SI 1 "s_register_operand" "r")
1271                   (const_int 16))
1272                  (sign_extend:SI
1273                   (match_operand:HI 2 "s_register_operand" "r"))))]
1274   "TARGET_ARM && arm_arch5e"
1275   "smultb%?\\t%0, %1, %2"
1276   [(set_attr "insn" "smulxy")
1277    (set_attr "predicable" "yes")]
1278 )
1279
1280 (define_insn "*mulhisi3bt"
1281   [(set (match_operand:SI 0 "s_register_operand" "=r")
1282         (mult:SI (sign_extend:SI
1283                   (match_operand:HI 1 "s_register_operand" "r"))
1284                  (ashiftrt:SI
1285                   (match_operand:SI 2 "s_register_operand" "r")
1286                   (const_int 16))))]
1287   "TARGET_ARM && arm_arch5e"
1288   "smulbt%?\\t%0, %1, %2"
1289   [(set_attr "insn" "smulxy")
1290    (set_attr "predicable" "yes")]
1291 )
1292
1293 (define_insn "*mulhisi3tt"
1294   [(set (match_operand:SI 0 "s_register_operand" "=r")
1295         (mult:SI (ashiftrt:SI
1296                   (match_operand:SI 1 "s_register_operand" "r")
1297                   (const_int 16))
1298                  (ashiftrt:SI
1299                   (match_operand:SI 2 "s_register_operand" "r")
1300                   (const_int 16))))]
1301   "TARGET_ARM && arm_arch5e"
1302   "smultt%?\\t%0, %1, %2"
1303   [(set_attr "insn" "smulxy")
1304    (set_attr "predicable" "yes")]
1305 )
1306
1307 (define_insn "*mulhisi3addsi"
1308   [(set (match_operand:SI 0 "s_register_operand" "=r")
1309         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1310                  (mult:SI (sign_extend:SI
1311                            (match_operand:HI 2 "s_register_operand" "%r"))
1312                           (sign_extend:SI
1313                            (match_operand:HI 3 "s_register_operand" "r")))))]
1314   "TARGET_ARM && arm_arch5e"
1315   "smlabb%?\\t%0, %2, %3, %1"
1316   [(set_attr "insn" "smlaxy")
1317    (set_attr "predicable" "yes")]
1318 )
1319
1320 (define_insn "*mulhidi3adddi"
1321   [(set (match_operand:DI 0 "s_register_operand" "=r")
1322         (plus:DI
1323           (match_operand:DI 1 "s_register_operand" "0")
1324           (mult:DI (sign_extend:DI
1325                     (match_operand:HI 2 "s_register_operand" "%r"))
1326                    (sign_extend:DI
1327                     (match_operand:HI 3 "s_register_operand" "r")))))]
1328   "TARGET_ARM && arm_arch5e"
1329   "smlalbb%?\\t%Q0, %R0, %2, %3"
1330   [(set_attr "insn" "smlalxy")
1331    (set_attr "predicable" "yes")])
1332
1333 (define_expand "mulsf3"
1334   [(set (match_operand:SF          0 "s_register_operand" "")
1335         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1336                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1337   "TARGET_ARM && TARGET_HARD_FLOAT"
1338   "
1339   if (TARGET_MAVERICK
1340       && !cirrus_fp_register (operands[2], SFmode))
1341     operands[2] = force_reg (SFmode, operands[2]);
1342 ")
1343
1344 (define_expand "muldf3"
1345   [(set (match_operand:DF          0 "s_register_operand" "")
1346         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1347                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1348   "TARGET_ARM && TARGET_HARD_FLOAT"
1349   "
1350   if (TARGET_MAVERICK
1351       && !cirrus_fp_register (operands[2], DFmode))
1352     operands[2] = force_reg (DFmode, operands[2]);
1353 ")
1354 \f
1355 ;; Division insns
1356
1357 (define_expand "divsf3"
1358   [(set (match_operand:SF 0 "s_register_operand" "")
1359         (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1360                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1361   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1362   "")
1363
1364 (define_expand "divdf3"
1365   [(set (match_operand:DF 0 "s_register_operand" "")
1366         (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1367                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1368   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1369   "")
1370 \f
1371 ;; Modulo insns
1372
1373 (define_expand "modsf3"
1374   [(set (match_operand:SF 0 "s_register_operand" "")
1375         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1376                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1377   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1378   "")
1379
1380 (define_expand "moddf3"
1381   [(set (match_operand:DF 0 "s_register_operand" "")
1382         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1383                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1384   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1385   "")
1386 \f
1387 ;; Boolean and,ior,xor insns
1388
1389 ;; Split up double word logical operations
1390
1391 ;; Split up simple DImode logical operations.  Simply perform the logical
1392 ;; operation on the upper and lower halves of the registers.
1393 (define_split
1394   [(set (match_operand:DI 0 "s_register_operand" "")
1395         (match_operator:DI 6 "logical_binary_operator"
1396           [(match_operand:DI 1 "s_register_operand" "")
1397            (match_operand:DI 2 "s_register_operand" "")]))]
1398   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1399   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1400    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1401   "
1402   {
1403     operands[3] = gen_highpart (SImode, operands[0]);
1404     operands[0] = gen_lowpart (SImode, operands[0]);
1405     operands[4] = gen_highpart (SImode, operands[1]);
1406     operands[1] = gen_lowpart (SImode, operands[1]);
1407     operands[5] = gen_highpart (SImode, operands[2]);
1408     operands[2] = gen_lowpart (SImode, operands[2]);
1409   }"
1410 )
1411
1412 (define_split
1413   [(set (match_operand:DI 0 "s_register_operand" "")
1414         (match_operator:DI 6 "logical_binary_operator"
1415           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1416            (match_operand:DI 1 "s_register_operand" "")]))]
1417   "TARGET_ARM && reload_completed"
1418   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1419    (set (match_dup 3) (match_op_dup:SI 6
1420                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1421                          (match_dup 4)]))]
1422   "
1423   {
1424     operands[3] = gen_highpart (SImode, operands[0]);
1425     operands[0] = gen_lowpart (SImode, operands[0]);
1426     operands[4] = gen_highpart (SImode, operands[1]);
1427     operands[1] = gen_lowpart (SImode, operands[1]);
1428     operands[5] = gen_highpart (SImode, operands[2]);
1429     operands[2] = gen_lowpart (SImode, operands[2]);
1430   }"
1431 )
1432
1433 ;; The zero extend of operand 2 means we can just copy the high part of
1434 ;; operand1 into operand0.
1435 (define_split
1436   [(set (match_operand:DI 0 "s_register_operand" "")
1437         (ior:DI
1438           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1439           (match_operand:DI 1 "s_register_operand" "")))]
1440   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1441   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1442    (set (match_dup 3) (match_dup 4))]
1443   "
1444   {
1445     operands[4] = gen_highpart (SImode, operands[1]);
1446     operands[3] = gen_highpart (SImode, operands[0]);
1447     operands[0] = gen_lowpart (SImode, operands[0]);
1448     operands[1] = gen_lowpart (SImode, operands[1]);
1449   }"
1450 )
1451
1452 ;; The zero extend of operand 2 means we can just copy the high part of
1453 ;; operand1 into operand0.
1454 (define_split
1455   [(set (match_operand:DI 0 "s_register_operand" "")
1456         (xor:DI
1457           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1458           (match_operand:DI 1 "s_register_operand" "")))]
1459   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1460   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1461    (set (match_dup 3) (match_dup 4))]
1462   "
1463   {
1464     operands[4] = gen_highpart (SImode, operands[1]);
1465     operands[3] = gen_highpart (SImode, operands[0]);
1466     operands[0] = gen_lowpart (SImode, operands[0]);
1467     operands[1] = gen_lowpart (SImode, operands[1]);
1468   }"
1469 )
1470
1471 (define_insn "anddi3"
1472   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1473         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1474                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1475   "TARGET_ARM && ! TARGET_IWMMXT"
1476   "#"
1477   [(set_attr "length" "8")]
1478 )
1479
1480 (define_insn_and_split "*anddi_zesidi_di"
1481   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1482         (and:DI (zero_extend:DI
1483                  (match_operand:SI 2 "s_register_operand" "r,r"))
1484                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1485   "TARGET_ARM"
1486   "#"
1487   "TARGET_ARM && reload_completed"
1488   ; The zero extend of operand 2 clears the high word of the output
1489   ; operand.
1490   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1491    (set (match_dup 3) (const_int 0))]
1492   "
1493   {
1494     operands[3] = gen_highpart (SImode, operands[0]);
1495     operands[0] = gen_lowpart (SImode, operands[0]);
1496     operands[1] = gen_lowpart (SImode, operands[1]);
1497   }"
1498   [(set_attr "length" "8")]
1499 )
1500
1501 (define_insn "*anddi_sesdi_di"
1502   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1503         (and:DI (sign_extend:DI
1504                  (match_operand:SI 2 "s_register_operand" "r,r"))
1505                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1506   "TARGET_ARM"
1507   "#"
1508   [(set_attr "length" "8")]
1509 )
1510
1511 (define_expand "andsi3"
1512   [(set (match_operand:SI         0 "s_register_operand" "")
1513         (and:SI (match_operand:SI 1 "s_register_operand" "")
1514                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1515   "TARGET_EITHER"
1516   "
1517   if (TARGET_ARM)
1518     {
1519       if (GET_CODE (operands[2]) == CONST_INT)
1520         {
1521           arm_split_constant (AND, SImode, NULL_RTX,
1522                               INTVAL (operands[2]), operands[0],
1523                               operands[1],
1524                               (no_new_pseudos
1525                                ? 0 : preserve_subexpressions_p ()));
1526           DONE;
1527         }
1528     }
1529   else /* TARGET_THUMB */
1530     {
1531       if (GET_CODE (operands[2]) != CONST_INT)
1532         operands[2] = force_reg (SImode, operands[2]);
1533       else
1534         {
1535           int i;
1536           
1537           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1538             {
1539               operands[2] = force_reg (SImode,
1540                                        GEN_INT (~INTVAL (operands[2])));
1541               
1542               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1543               
1544               DONE;
1545             }
1546
1547           for (i = 9; i <= 31; i++)
1548             {
1549               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1550                 {
1551                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1552                                         const0_rtx));
1553                   DONE;
1554                 }
1555               else if ((((HOST_WIDE_INT) 1) << i) - 1
1556                        == ~INTVAL (operands[2]))
1557                 {
1558                   rtx shift = GEN_INT (i);
1559                   rtx reg = gen_reg_rtx (SImode);
1560                 
1561                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1562                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1563                   
1564                   DONE;
1565                 }
1566             }
1567
1568           operands[2] = force_reg (SImode, operands[2]);
1569         }
1570     }
1571   "
1572 )
1573
1574 (define_insn_and_split "*arm_andsi3_insn"
1575   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1576         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1577                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1578   "TARGET_ARM"
1579   "@
1580    and%?\\t%0, %1, %2
1581    bic%?\\t%0, %1, #%B2
1582    #"
1583   "TARGET_ARM
1584    && GET_CODE (operands[2]) == CONST_INT
1585    && !(const_ok_for_arm (INTVAL (operands[2]))
1586         || const_ok_for_arm (~INTVAL (operands[2])))"
1587   [(clobber (const_int 0))]
1588   "
1589   arm_split_constant  (AND, SImode, curr_insn, 
1590                        INTVAL (operands[2]), operands[0], operands[1], 0);
1591   DONE;
1592   "
1593   [(set_attr "length" "4,4,16")
1594    (set_attr "predicable" "yes")]
1595 )
1596
1597 (define_insn "*thumb_andsi3_insn"
1598   [(set (match_operand:SI         0 "register_operand" "=l")
1599         (and:SI (match_operand:SI 1 "register_operand" "%0")
1600                 (match_operand:SI 2 "register_operand" "l")))]
1601   "TARGET_THUMB"
1602   "and\\t%0, %0, %2"
1603   [(set_attr "length" "2")]
1604 )
1605
1606 (define_insn "*andsi3_compare0"
1607   [(set (reg:CC_NOOV CC_REGNUM)
1608         (compare:CC_NOOV
1609          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1610                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1611          (const_int 0)))
1612    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1613         (and:SI (match_dup 1) (match_dup 2)))]
1614   "TARGET_ARM"
1615   "@
1616    and%?s\\t%0, %1, %2
1617    bic%?s\\t%0, %1, #%B2"
1618   [(set_attr "conds" "set")]
1619 )
1620
1621 (define_insn "*andsi3_compare0_scratch"
1622   [(set (reg:CC_NOOV CC_REGNUM)
1623         (compare:CC_NOOV
1624          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1625                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1626          (const_int 0)))
1627    (clobber (match_scratch:SI 2 "=X,r"))]
1628   "TARGET_ARM"
1629   "@
1630    tst%?\\t%0, %1
1631    bic%?s\\t%2, %0, #%B1"
1632   [(set_attr "conds" "set")]
1633 )
1634
1635 (define_insn "*zeroextractsi_compare0_scratch"
1636   [(set (reg:CC_NOOV CC_REGNUM)
1637         (compare:CC_NOOV (zero_extract:SI
1638                           (match_operand:SI 0 "s_register_operand" "r")
1639                           (match_operand 1 "const_int_operand" "n")
1640                           (match_operand 2 "const_int_operand" "n"))
1641                          (const_int 0)))]
1642   "TARGET_ARM
1643   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1644       && INTVAL (operands[1]) > 0 
1645       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1646       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1647   "*
1648   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1649                          << INTVAL (operands[2]));
1650   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1651   return \"\";
1652   "
1653   [(set_attr "conds" "set")]
1654 )
1655
1656 (define_insn "*ne_zeroextractsi"
1657   [(set (match_operand:SI 0 "s_register_operand" "=r")
1658         (ne:SI (zero_extract:SI
1659                 (match_operand:SI 1 "s_register_operand" "r")
1660                 (match_operand:SI 2 "const_int_operand" "n")
1661                 (match_operand:SI 3 "const_int_operand" "n"))
1662                (const_int 0)))
1663    (clobber (reg:CC CC_REGNUM))]
1664   "TARGET_ARM
1665    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1666        && INTVAL (operands[2]) > 0 
1667        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1668        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1669   "*
1670   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1671                          << INTVAL (operands[3]));
1672   output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1673   return \"movne\\t%0, #1\";
1674   "
1675   [(set_attr "conds" "clob")
1676    (set_attr "length" "8")]
1677 )
1678
1679 (define_split
1680   [(set (match_operand:SI 0 "s_register_operand" "")
1681         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1682                          (match_operand:SI 2 "const_int_operand" "")
1683                          (match_operand:SI 3 "const_int_operand" "")))
1684    (clobber (match_operand:SI 4 "s_register_operand" ""))]
1685   "TARGET_THUMB"
1686   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1687    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1688   "{
1689      HOST_WIDE_INT temp = INTVAL (operands[2]);
1690
1691      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1692      operands[3] = GEN_INT (32 - temp);
1693    }"
1694 )
1695
1696 (define_split
1697   [(set (match_operand:SI 0 "s_register_operand" "")
1698         (match_operator:SI 1 "shiftable_operator"
1699          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1700                            (match_operand:SI 3 "const_int_operand" "")
1701                            (match_operand:SI 4 "const_int_operand" ""))
1702           (match_operand:SI 5 "s_register_operand" "")]))
1703    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1704   "TARGET_ARM"
1705   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1706    (set (match_dup 0)
1707         (match_op_dup 1
1708          [(lshiftrt:SI (match_dup 6) (match_dup 4))
1709           (match_dup 5)]))]
1710   "{
1711      HOST_WIDE_INT temp = INTVAL (operands[3]);
1712
1713      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1714      operands[4] = GEN_INT (32 - temp);
1715    }"
1716 )
1717   
1718 (define_split
1719   [(set (match_operand:SI 0 "s_register_operand" "")
1720         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1721                          (match_operand:SI 2 "const_int_operand" "")
1722                          (match_operand:SI 3 "const_int_operand" "")))]
1723   "TARGET_THUMB"
1724   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1725    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1726   "{
1727      HOST_WIDE_INT temp = INTVAL (operands[2]);
1728
1729      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1730      operands[3] = GEN_INT (32 - temp);
1731    }"
1732 )
1733
1734 (define_split
1735   [(set (match_operand:SI 0 "s_register_operand" "")
1736         (match_operator:SI 1 "shiftable_operator"
1737          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1738                            (match_operand:SI 3 "const_int_operand" "")
1739                            (match_operand:SI 4 "const_int_operand" ""))
1740           (match_operand:SI 5 "s_register_operand" "")]))
1741    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1742   "TARGET_ARM"
1743   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1744    (set (match_dup 0)
1745         (match_op_dup 1
1746          [(ashiftrt:SI (match_dup 6) (match_dup 4))
1747           (match_dup 5)]))]
1748   "{
1749      HOST_WIDE_INT temp = INTVAL (operands[3]);
1750
1751      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1752      operands[4] = GEN_INT (32 - temp);
1753    }"
1754 )
1755   
1756 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1757 ;;; represented by the bitfield, then this will produce incorrect results.
1758 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1759 ;;; which have a real bit-field insert instruction, the truncation happens
1760 ;;; in the bit-field insert instruction itself.  Since arm does not have a
1761 ;;; bit-field insert instruction, we would have to emit code here to truncate
1762 ;;; the value before we insert.  This loses some of the advantage of having
1763 ;;; this insv pattern, so this pattern needs to be reevalutated.
1764
1765 (define_expand "insv"
1766   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1767                          (match_operand:SI 1 "general_operand" "")
1768                          (match_operand:SI 2 "general_operand" ""))
1769         (match_operand:SI 3 "reg_or_int_operand" ""))]
1770   "TARGET_ARM"
1771   "
1772   {
1773     int start_bit = INTVAL (operands[2]);
1774     int width = INTVAL (operands[1]);
1775     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1776     rtx target, subtarget;
1777
1778     target = operands[0];
1779     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1780        subreg as the final target.  */
1781     if (GET_CODE (target) == SUBREG)
1782       {
1783         subtarget = gen_reg_rtx (SImode);
1784         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1785             < GET_MODE_SIZE (SImode))
1786           target = SUBREG_REG (target);
1787       }
1788     else
1789       subtarget = target;    
1790
1791     if (GET_CODE (operands[3]) == CONST_INT)
1792       {
1793         /* Since we are inserting a known constant, we may be able to
1794            reduce the number of bits that we have to clear so that
1795            the mask becomes simple.  */
1796         /* ??? This code does not check to see if the new mask is actually
1797            simpler.  It may not be.  */
1798         rtx op1 = gen_reg_rtx (SImode);
1799         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1800            start of this pattern.  */
1801         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1802         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1803
1804         emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1805         emit_insn (gen_iorsi3 (subtarget, op1,
1806                                GEN_INT (op3_value << start_bit)));
1807       }
1808     else if (start_bit == 0
1809              && !(const_ok_for_arm (mask)
1810                   || const_ok_for_arm (~mask)))
1811       {
1812         /* A Trick, since we are setting the bottom bits in the word,
1813            we can shift operand[3] up, operand[0] down, OR them together
1814            and rotate the result back again.  This takes 3 insns, and
1815            the third might be mergeable into another op.  */
1816         /* The shift up copes with the possibility that operand[3] is
1817            wider than the bitfield.  */
1818         rtx op0 = gen_reg_rtx (SImode);
1819         rtx op1 = gen_reg_rtx (SImode);
1820
1821         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1822         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1823         emit_insn (gen_iorsi3  (op1, op1, op0));
1824         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1825       }
1826     else if ((width + start_bit == 32)
1827              && !(const_ok_for_arm (mask)
1828                   || const_ok_for_arm (~mask)))
1829       {
1830         /* Similar trick, but slightly less efficient.  */
1831
1832         rtx op0 = gen_reg_rtx (SImode);
1833         rtx op1 = gen_reg_rtx (SImode);
1834
1835         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1836         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1837         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1838         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1839       }
1840     else
1841       {
1842         rtx op0 = GEN_INT (mask);
1843         rtx op1 = gen_reg_rtx (SImode);
1844         rtx op2 = gen_reg_rtx (SImode);
1845
1846         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1847           {
1848             rtx tmp = gen_reg_rtx (SImode);
1849
1850             emit_insn (gen_movsi (tmp, op0));
1851             op0 = tmp;
1852           }
1853
1854         /* Mask out any bits in operand[3] that are not needed.  */
1855            emit_insn (gen_andsi3 (op1, operands[3], op0));
1856
1857         if (GET_CODE (op0) == CONST_INT
1858             && (const_ok_for_arm (mask << start_bit)
1859                 || const_ok_for_arm (~(mask << start_bit))))
1860           {
1861             op0 = GEN_INT (~(mask << start_bit));
1862             emit_insn (gen_andsi3 (op2, operands[0], op0));
1863           }
1864         else
1865           {
1866             if (GET_CODE (op0) == CONST_INT)
1867               {
1868                 rtx tmp = gen_reg_rtx (SImode);
1869
1870                 emit_insn (gen_movsi (tmp, op0));
1871                 op0 = tmp;
1872               }
1873
1874             if (start_bit != 0)
1875               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1876             
1877             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1878           }
1879
1880         if (start_bit != 0)
1881           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1882
1883         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1884       }
1885
1886     if (subtarget != target)
1887       {
1888         /* If TARGET is still a SUBREG, then it must be wider than a word,
1889            so we must be careful only to set the subword we were asked to.  */
1890         if (GET_CODE (target) == SUBREG)
1891           emit_move_insn (target, subtarget);
1892         else
1893           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1894       }
1895
1896     DONE;
1897   }"
1898 )
1899
1900 ; constants for op 2 will never be given to these patterns.
1901 (define_insn_and_split "*anddi_notdi_di"
1902   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1903         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1904                 (match_operand:DI 2 "s_register_operand" "0,r")))]
1905   "TARGET_ARM"
1906   "#"
1907   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1908   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1909    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
1910   "
1911   {
1912     operands[3] = gen_highpart (SImode, operands[0]);
1913     operands[0] = gen_lowpart (SImode, operands[0]);
1914     operands[4] = gen_highpart (SImode, operands[1]);
1915     operands[1] = gen_lowpart (SImode, operands[1]);
1916     operands[5] = gen_highpart (SImode, operands[2]);
1917     operands[2] = gen_lowpart (SImode, operands[2]);
1918   }"
1919   [(set_attr "length" "8")
1920    (set_attr "predicable" "yes")]
1921 )
1922   
1923 (define_insn_and_split "*anddi_notzesidi_di"
1924   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1925         (and:DI (not:DI (zero_extend:DI
1926                          (match_operand:SI 2 "s_register_operand" "r,r")))
1927                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1928   "TARGET_ARM"
1929   "@
1930    bic%?\\t%Q0, %Q1, %2
1931    #"
1932   ; (not (zero_extend ...)) allows us to just copy the high word from
1933   ; operand1 to operand0.
1934   "TARGET_ARM
1935    && reload_completed
1936    && operands[0] != operands[1]"
1937   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1938    (set (match_dup 3) (match_dup 4))]
1939   "
1940   {
1941     operands[3] = gen_highpart (SImode, operands[0]);
1942     operands[0] = gen_lowpart (SImode, operands[0]);
1943     operands[4] = gen_highpart (SImode, operands[1]);
1944     operands[1] = gen_lowpart (SImode, operands[1]);
1945   }"
1946   [(set_attr "length" "4,8")
1947    (set_attr "predicable" "yes")]
1948 )
1949   
1950 (define_insn_and_split "*anddi_notsesidi_di"
1951   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1952         (and:DI (not:DI (sign_extend:DI
1953                          (match_operand:SI 2 "s_register_operand" "r,r")))
1954                 (match_operand:DI 1 "s_register_operand" "0,r")))]
1955   "TARGET_ARM"
1956   "#"
1957   "TARGET_ARM && reload_completed"
1958   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1959    (set (match_dup 3) (and:SI (not:SI
1960                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
1961                                (match_dup 4)))]
1962   "
1963   {
1964     operands[3] = gen_highpart (SImode, operands[0]);
1965     operands[0] = gen_lowpart (SImode, operands[0]);
1966     operands[4] = gen_highpart (SImode, operands[1]);
1967     operands[1] = gen_lowpart (SImode, operands[1]);
1968   }"
1969   [(set_attr "length" "8")
1970    (set_attr "predicable" "yes")]
1971 )
1972   
1973 (define_insn "andsi_notsi_si"
1974   [(set (match_operand:SI 0 "s_register_operand" "=r")
1975         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1976                 (match_operand:SI 1 "s_register_operand" "r")))]
1977   "TARGET_ARM"
1978   "bic%?\\t%0, %1, %2"
1979   [(set_attr "predicable" "yes")]
1980 )
1981
1982 (define_insn "bicsi3"
1983   [(set (match_operand:SI                 0 "register_operand" "=l")
1984         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
1985                 (match_operand:SI         2 "register_operand" "0")))]
1986   "TARGET_THUMB"
1987   "bic\\t%0, %0, %1"
1988   [(set_attr "length" "2")]
1989 )
1990
1991 (define_insn "andsi_not_shiftsi_si"
1992   [(set (match_operand:SI 0 "s_register_operand" "=r")
1993         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
1994                          [(match_operand:SI 2 "s_register_operand" "r")
1995                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
1996                 (match_operand:SI 1 "s_register_operand" "r")))]
1997   "TARGET_ARM"
1998   "bic%?\\t%0, %1, %2%S4"
1999   [(set_attr "predicable" "yes")
2000    (set_attr "shift" "2")
2001    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2002                       (const_string "alu_shift")
2003                       (const_string "alu_shift_reg")))]
2004 )
2005
2006 (define_insn "*andsi_notsi_si_compare0"
2007   [(set (reg:CC_NOOV CC_REGNUM)
2008         (compare:CC_NOOV
2009          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2010                  (match_operand:SI 1 "s_register_operand" "r"))
2011          (const_int 0)))
2012    (set (match_operand:SI 0 "s_register_operand" "=r")
2013         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2014   "TARGET_ARM"
2015   "bic%?s\\t%0, %1, %2"
2016   [(set_attr "conds" "set")]
2017 )
2018
2019 (define_insn "*andsi_notsi_si_compare0_scratch"
2020   [(set (reg:CC_NOOV CC_REGNUM)
2021         (compare:CC_NOOV
2022          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2023                  (match_operand:SI 1 "s_register_operand" "r"))
2024          (const_int 0)))
2025    (clobber (match_scratch:SI 0 "=r"))]
2026   "TARGET_ARM"
2027   "bic%?s\\t%0, %1, %2"
2028   [(set_attr "conds" "set")]
2029 )
2030
2031 (define_insn "iordi3"
2032   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2033         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2034                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2035   "TARGET_ARM && ! TARGET_IWMMXT"
2036   "#"
2037   [(set_attr "length" "8")
2038    (set_attr "predicable" "yes")]
2039 )
2040
2041 (define_insn "*iordi_zesidi_di"
2042   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2043         (ior:DI (zero_extend:DI
2044                  (match_operand:SI 2 "s_register_operand" "r,r"))
2045                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2046   "TARGET_ARM"
2047   "@
2048    orr%?\\t%Q0, %Q1, %2
2049    #"
2050   [(set_attr "length" "4,8")
2051    (set_attr "predicable" "yes")]
2052 )
2053
2054 (define_insn "*iordi_sesidi_di"
2055   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2056         (ior:DI (sign_extend:DI
2057                  (match_operand:SI 2 "s_register_operand" "r,r"))
2058                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2059   "TARGET_ARM"
2060   "#"
2061   [(set_attr "length" "8")
2062    (set_attr "predicable" "yes")]
2063 )
2064
2065 (define_expand "iorsi3"
2066   [(set (match_operand:SI         0 "s_register_operand" "")
2067         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2068                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2069   "TARGET_EITHER"
2070   "
2071   if (GET_CODE (operands[2]) == CONST_INT)
2072     {
2073       if (TARGET_ARM)
2074         {
2075           arm_split_constant (IOR, SImode, NULL_RTX,
2076                               INTVAL (operands[2]), operands[0], operands[1],
2077                               (no_new_pseudos
2078                               ? 0 : preserve_subexpressions_p ()));
2079           DONE;
2080         }
2081       else /* TARGET_THUMB */
2082         operands [2] = force_reg (SImode, operands [2]);
2083     }
2084   "
2085 )
2086
2087 (define_insn_and_split "*arm_iorsi3"
2088   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2089         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2090                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2091   "TARGET_ARM"
2092   "@
2093    orr%?\\t%0, %1, %2
2094    #"
2095   "TARGET_ARM
2096    && GET_CODE (operands[2]) == CONST_INT
2097    && !const_ok_for_arm (INTVAL (operands[2]))"
2098   [(clobber (const_int 0))]
2099   "
2100   arm_split_constant (IOR, SImode, curr_insn, 
2101                       INTVAL (operands[2]), operands[0], operands[1], 0);
2102   DONE;
2103   "
2104   [(set_attr "length" "4,16")
2105    (set_attr "predicable" "yes")]
2106 )
2107
2108 (define_insn "*thumb_iorsi3"
2109   [(set (match_operand:SI         0 "register_operand" "=l")
2110         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2111                 (match_operand:SI 2 "register_operand" "l")))]
2112   "TARGET_THUMB"
2113   "orr\\t%0, %0, %2"
2114   [(set_attr "length" "2")]
2115 )
2116
2117 (define_peephole2
2118   [(match_scratch:SI 3 "r")
2119    (set (match_operand:SI         0 "s_register_operand" "")
2120         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2121                 (match_operand:SI 2 "const_int_operand" "")))]
2122   "TARGET_ARM
2123    && !const_ok_for_arm (INTVAL (operands[2]))
2124    && const_ok_for_arm (~INTVAL (operands[2]))"
2125   [(set (match_dup 3) (match_dup 2))
2126    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2127   ""
2128 )
2129
2130 (define_insn "*iorsi3_compare0"
2131   [(set (reg:CC_NOOV CC_REGNUM)
2132         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2133                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2134                          (const_int 0)))
2135    (set (match_operand:SI 0 "s_register_operand" "=r")
2136         (ior:SI (match_dup 1) (match_dup 2)))]
2137   "TARGET_ARM"
2138   "orr%?s\\t%0, %1, %2"
2139   [(set_attr "conds" "set")]
2140 )
2141
2142 (define_insn "*iorsi3_compare0_scratch"
2143   [(set (reg:CC_NOOV CC_REGNUM)
2144         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2145                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2146                          (const_int 0)))
2147    (clobber (match_scratch:SI 0 "=r"))]
2148   "TARGET_ARM"
2149   "orr%?s\\t%0, %1, %2"
2150   [(set_attr "conds" "set")]
2151 )
2152
2153 (define_insn "xordi3"
2154   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2155         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2156                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2157   "TARGET_ARM && !TARGET_IWMMXT"
2158   "#"
2159   [(set_attr "length" "8")
2160    (set_attr "predicable" "yes")]
2161 )
2162
2163 (define_insn "*xordi_zesidi_di"
2164   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2165         (xor:DI (zero_extend:DI
2166                  (match_operand:SI 2 "s_register_operand" "r,r"))
2167                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2168   "TARGET_ARM"
2169   "@
2170    eor%?\\t%Q0, %Q1, %2
2171    #"
2172   [(set_attr "length" "4,8")
2173    (set_attr "predicable" "yes")]
2174 )
2175
2176 (define_insn "*xordi_sesidi_di"
2177   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2178         (xor:DI (sign_extend:DI
2179                  (match_operand:SI 2 "s_register_operand" "r,r"))
2180                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2181   "TARGET_ARM"
2182   "#"
2183   [(set_attr "length" "8")
2184    (set_attr "predicable" "yes")]
2185 )
2186
2187 (define_expand "xorsi3"
2188   [(set (match_operand:SI         0 "s_register_operand" "")
2189         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2190                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2191   "TARGET_EITHER"
2192   "if (TARGET_THUMB)
2193      if (GET_CODE (operands[2]) == CONST_INT)
2194        operands[2] = force_reg (SImode, operands[2]);
2195   "
2196 )
2197
2198 (define_insn "*arm_xorsi3"
2199   [(set (match_operand:SI         0 "s_register_operand" "=r")
2200         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2201                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2202   "TARGET_ARM"
2203   "eor%?\\t%0, %1, %2"
2204   [(set_attr "predicable" "yes")]
2205 )
2206
2207 (define_insn "*thumb_xorsi3"
2208   [(set (match_operand:SI         0 "register_operand" "=l")
2209         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2210                 (match_operand:SI 2 "register_operand" "l")))]
2211   "TARGET_THUMB"
2212   "eor\\t%0, %0, %2"
2213   [(set_attr "length" "2")]
2214 )
2215
2216 (define_insn "*xorsi3_compare0"
2217   [(set (reg:CC_NOOV CC_REGNUM)
2218         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2219                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2220                          (const_int 0)))
2221    (set (match_operand:SI 0 "s_register_operand" "=r")
2222         (xor:SI (match_dup 1) (match_dup 2)))]
2223   "TARGET_ARM"
2224   "eor%?s\\t%0, %1, %2"
2225   [(set_attr "conds" "set")]
2226 )
2227
2228 (define_insn "*xorsi3_compare0_scratch"
2229   [(set (reg:CC_NOOV CC_REGNUM)
2230         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2231                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2232                          (const_int 0)))]
2233   "TARGET_ARM"
2234   "teq%?\\t%0, %1"
2235   [(set_attr "conds" "set")]
2236 )
2237
2238 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2239 ; (NOT D) we can sometimes merge the final NOT into one of the following
2240 ; insns.
2241
2242 (define_split
2243   [(set (match_operand:SI 0 "s_register_operand" "")
2244         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2245                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2246                 (match_operand:SI 3 "arm_rhs_operand" "")))
2247    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2248   "TARGET_ARM"
2249   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2250                               (not:SI (match_dup 3))))
2251    (set (match_dup 0) (not:SI (match_dup 4)))]
2252   ""
2253 )
2254
2255 (define_insn "*andsi_iorsi3_notsi"
2256   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2257         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2258                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2259                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2260   "TARGET_ARM"
2261   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2262   [(set_attr "length" "8")
2263    (set_attr "predicable" "yes")]
2264 )
2265
2266 (define_split
2267   [(set (match_operand:SI 0 "s_register_operand" "")
2268         (match_operator:SI 1 "logical_binary_operator"
2269          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2270                            (match_operand:SI 3 "const_int_operand" "")
2271                            (match_operand:SI 4 "const_int_operand" ""))
2272           (match_operator:SI 9 "logical_binary_operator"
2273            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2274                          (match_operand:SI 6 "const_int_operand" ""))
2275             (match_operand:SI 7 "s_register_operand" "")])]))
2276    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2277   "TARGET_ARM
2278    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2279    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2280   [(set (match_dup 8)
2281         (match_op_dup 1
2282          [(ashift:SI (match_dup 2) (match_dup 4))
2283           (match_dup 5)]))
2284    (set (match_dup 0)
2285         (match_op_dup 1
2286          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2287           (match_dup 7)]))]
2288   "
2289   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2290 ")
2291
2292 (define_split
2293   [(set (match_operand:SI 0 "s_register_operand" "")
2294         (match_operator:SI 1 "logical_binary_operator"
2295          [(match_operator:SI 9 "logical_binary_operator"
2296            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2297                          (match_operand:SI 6 "const_int_operand" ""))
2298             (match_operand:SI 7 "s_register_operand" "")])
2299           (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2300                            (match_operand:SI 3 "const_int_operand" "")
2301                            (match_operand:SI 4 "const_int_operand" ""))]))
2302    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2303   "TARGET_ARM
2304    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2305    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2306   [(set (match_dup 8)
2307         (match_op_dup 1
2308          [(ashift:SI (match_dup 2) (match_dup 4))
2309           (match_dup 5)]))
2310    (set (match_dup 0)
2311         (match_op_dup 1
2312          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2313           (match_dup 7)]))]
2314   "
2315   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2316 ")
2317
2318 (define_split
2319   [(set (match_operand:SI 0 "s_register_operand" "")
2320         (match_operator:SI 1 "logical_binary_operator"
2321          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2322                            (match_operand:SI 3 "const_int_operand" "")
2323                            (match_operand:SI 4 "const_int_operand" ""))
2324           (match_operator:SI 9 "logical_binary_operator"
2325            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2326                          (match_operand:SI 6 "const_int_operand" ""))
2327             (match_operand:SI 7 "s_register_operand" "")])]))
2328    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2329   "TARGET_ARM
2330    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2331    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2332   [(set (match_dup 8)
2333         (match_op_dup 1
2334          [(ashift:SI (match_dup 2) (match_dup 4))
2335           (match_dup 5)]))
2336    (set (match_dup 0)
2337         (match_op_dup 1
2338          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2339           (match_dup 7)]))]
2340   "
2341   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2342 ")
2343
2344 (define_split
2345   [(set (match_operand:SI 0 "s_register_operand" "")
2346         (match_operator:SI 1 "logical_binary_operator"
2347          [(match_operator:SI 9 "logical_binary_operator"
2348            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2349                          (match_operand:SI 6 "const_int_operand" ""))
2350             (match_operand:SI 7 "s_register_operand" "")])
2351           (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2352                            (match_operand:SI 3 "const_int_operand" "")
2353                            (match_operand:SI 4 "const_int_operand" ""))]))
2354    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2355   "TARGET_ARM
2356    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2357    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2358   [(set (match_dup 8)
2359         (match_op_dup 1
2360          [(ashift:SI (match_dup 2) (match_dup 4))
2361           (match_dup 5)]))
2362    (set (match_dup 0)
2363         (match_op_dup 1
2364          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2365           (match_dup 7)]))]
2366   "
2367   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2368 ")
2369 \f
2370
2371 ;; Minimum and maximum insns
2372
2373 (define_insn "smaxsi3"
2374   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2375         (smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2376                  (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2377    (clobber (reg:CC CC_REGNUM))]
2378   "TARGET_ARM"
2379   "@
2380    cmp\\t%1, %2\;movlt\\t%0, %2
2381    cmp\\t%1, %2\;movge\\t%0, %1
2382    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2383   [(set_attr "conds" "clob")
2384    (set_attr "length" "8,8,12")]
2385 )
2386
2387 (define_insn "sminsi3"
2388   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2389         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2390                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2391    (clobber (reg:CC CC_REGNUM))]
2392   "TARGET_ARM"
2393   "@
2394    cmp\\t%1, %2\;movge\\t%0, %2
2395    cmp\\t%1, %2\;movlt\\t%0, %1
2396    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2397   [(set_attr "conds" "clob")
2398    (set_attr "length" "8,8,12")]
2399 )
2400
2401 (define_insn "umaxsi3"
2402   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2403         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2404                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2405    (clobber (reg:CC CC_REGNUM))]
2406   "TARGET_ARM"
2407   "@
2408    cmp\\t%1, %2\;movcc\\t%0, %2
2409    cmp\\t%1, %2\;movcs\\t%0, %1
2410    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2411   [(set_attr "conds" "clob")
2412    (set_attr "length" "8,8,12")]
2413 )
2414
2415 (define_insn "uminsi3"
2416   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2417         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2418                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2419    (clobber (reg:CC CC_REGNUM))]
2420   "TARGET_ARM"
2421   "@
2422    cmp\\t%1, %2\;movcs\\t%0, %2
2423    cmp\\t%1, %2\;movcc\\t%0, %1
2424    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2425   [(set_attr "conds" "clob")
2426    (set_attr "length" "8,8,12")]
2427 )
2428
2429 (define_insn "*store_minmaxsi"
2430   [(set (match_operand:SI 0 "memory_operand" "=m")
2431         (match_operator:SI 3 "minmax_operator"
2432          [(match_operand:SI 1 "s_register_operand" "r")
2433           (match_operand:SI 2 "s_register_operand" "r")]))
2434    (clobber (reg:CC CC_REGNUM))]
2435   "TARGET_ARM"
2436   "*
2437   operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2438                                 operands[1], operands[2]);
2439   output_asm_insn (\"cmp\\t%1, %2\", operands);
2440   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2441   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2442   return \"\";
2443   "
2444   [(set_attr "conds" "clob")
2445    (set_attr "length" "12")
2446    (set_attr "type" "store1")]
2447 )
2448
2449 ; Reject the frame pointer in operand[1], since reloading this after
2450 ; it has been eliminated can cause carnage.
2451 (define_insn "*minmax_arithsi"
2452   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2453         (match_operator:SI 4 "shiftable_operator"
2454          [(match_operator:SI 5 "minmax_operator"
2455            [(match_operand:SI 2 "s_register_operand" "r,r")
2456             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2457           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2458    (clobber (reg:CC CC_REGNUM))]
2459   "TARGET_ARM
2460    && (GET_CODE (operands[1]) != REG
2461        || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2462            && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2463   "*
2464   {
2465     enum rtx_code code = GET_CODE (operands[4]);
2466
2467     operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2468                                   operands[2], operands[3]);
2469     output_asm_insn (\"cmp\\t%2, %3\", operands);
2470     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2471     if (which_alternative != 0 || operands[3] != const0_rtx
2472         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2473       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2474     return \"\";
2475   }"
2476   [(set_attr "conds" "clob")
2477    (set_attr "length" "12")]
2478 )
2479
2480 \f
2481 ;; Shift and rotation insns
2482
2483 (define_expand "ashldi3"
2484   [(set (match_operand:DI            0 "s_register_operand" "")
2485         (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2486                    (match_operand:SI 2 "reg_or_int_operand" "")))]
2487   "TARGET_ARM"
2488   "
2489   if (GET_CODE (operands[2]) == CONST_INT)
2490     {
2491       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2492         {
2493           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2494           DONE;
2495         }
2496         /* Ideally we shouldn't fail here if we could know that operands[1] 
2497            ends up already living in an iwmmxt register. Otherwise it's
2498            cheaper to have the alternate code being generated than moving
2499            values to iwmmxt regs and back.  */
2500         FAIL;
2501     }
2502   else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2503     FAIL;
2504   "
2505 )
2506
2507 (define_insn "arm_ashldi3_1bit"
2508   [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
2509         (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2510                    (const_int 1)))
2511    (clobber (reg:CC CC_REGNUM))]
2512   "TARGET_ARM"
2513   "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2514   [(set_attr "conds" "clob")
2515    (set_attr "length" "8")]
2516 )
2517
2518 (define_expand "ashlsi3"
2519   [(set (match_operand:SI            0 "s_register_operand" "")
2520         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2521                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2522   "TARGET_EITHER"
2523   "
2524   if (GET_CODE (operands[2]) == CONST_INT
2525       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2526     {
2527       emit_insn (gen_movsi (operands[0], const0_rtx));
2528       DONE;
2529     }
2530   "
2531 )
2532
2533 (define_insn "*thumb_ashlsi3"
2534   [(set (match_operand:SI            0 "register_operand" "=l,l")
2535         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2536                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2537   "TARGET_THUMB"
2538   "lsl\\t%0, %1, %2"
2539   [(set_attr "length" "2")]
2540 )
2541
2542 (define_expand "ashrdi3"
2543   [(set (match_operand:DI              0 "s_register_operand" "")
2544         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2545                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2546   "TARGET_ARM"
2547   "
2548   if (GET_CODE (operands[2]) == CONST_INT)
2549     {
2550       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2551         {
2552           emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2553           DONE;
2554         }
2555         /* Ideally we shouldn't fail here if we could know that operands[1] 
2556            ends up already living in an iwmmxt register. Otherwise it's
2557            cheaper to have the alternate code being generated than moving
2558            values to iwmmxt regs and back.  */
2559         FAIL;
2560     }
2561   else if (!TARGET_REALLY_IWMMXT)
2562     FAIL;
2563   "
2564 )
2565
2566 (define_insn "arm_ashrdi3_1bit"
2567   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2568         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2569                      (const_int 1)))
2570    (clobber (reg:CC CC_REGNUM))]
2571   "TARGET_ARM"
2572   "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2573   [(set_attr "conds" "clob")
2574    (set_attr "length" "8")]
2575 )
2576
2577 (define_expand "ashrsi3"
2578   [(set (match_operand:SI              0 "s_register_operand" "")
2579         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2580                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2581   "TARGET_EITHER"
2582   "
2583   if (GET_CODE (operands[2]) == CONST_INT
2584       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2585     operands[2] = GEN_INT (31);
2586   "
2587 )
2588
2589 (define_insn "*thumb_ashrsi3"
2590   [(set (match_operand:SI              0 "register_operand" "=l,l")
2591         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2592                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2593   "TARGET_THUMB"
2594   "asr\\t%0, %1, %2"
2595   [(set_attr "length" "2")]
2596 )
2597
2598 (define_expand "lshrdi3"
2599   [(set (match_operand:DI              0 "s_register_operand" "")
2600         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2601                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2602   "TARGET_ARM"
2603   "
2604   if (GET_CODE (operands[2]) == CONST_INT)
2605     {
2606       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2607         {
2608           emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2609           DONE;
2610         }
2611         /* Ideally we shouldn't fail here if we could know that operands[1] 
2612            ends up already living in an iwmmxt register. Otherwise it's
2613            cheaper to have the alternate code being generated than moving
2614            values to iwmmxt regs and back.  */
2615         FAIL;
2616     }
2617   else if (!TARGET_REALLY_IWMMXT)
2618     FAIL;
2619   "
2620 )
2621
2622 (define_insn "arm_lshrdi3_1bit"
2623   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2624         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2625                      (const_int 1)))
2626    (clobber (reg:CC CC_REGNUM))]
2627   "TARGET_ARM"
2628   "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2629   [(set_attr "conds" "clob")
2630    (set_attr "length" "8")]
2631 )
2632
2633 (define_expand "lshrsi3"
2634   [(set (match_operand:SI              0 "s_register_operand" "")
2635         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2636                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2637   "TARGET_EITHER"
2638   "
2639   if (GET_CODE (operands[2]) == CONST_INT
2640       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2641     {
2642       emit_insn (gen_movsi (operands[0], const0_rtx));
2643       DONE;
2644     }
2645   "
2646 )
2647
2648 (define_insn "*thumb_lshrsi3"
2649   [(set (match_operand:SI              0 "register_operand" "=l,l")
2650         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2651                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2652   "TARGET_THUMB"
2653   "lsr\\t%0, %1, %2"
2654   [(set_attr "length" "2")]
2655 )
2656
2657 (define_expand "rotlsi3"
2658   [(set (match_operand:SI              0 "s_register_operand" "")
2659         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2660                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2661   "TARGET_ARM"
2662   "
2663   if (GET_CODE (operands[2]) == CONST_INT)
2664     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2665   else
2666     {
2667       rtx reg = gen_reg_rtx (SImode);
2668       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2669       operands[2] = reg;
2670     }
2671   "
2672 )
2673
2674 (define_expand "rotrsi3"
2675   [(set (match_operand:SI              0 "s_register_operand" "")
2676         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2677                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2678   "TARGET_EITHER"
2679   "
2680   if (TARGET_ARM)
2681     {
2682       if (GET_CODE (operands[2]) == CONST_INT
2683           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2684         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2685     }
2686   else /* TARGET_THUMB */
2687     {
2688       if (GET_CODE (operands [2]) == CONST_INT)
2689         operands [2] = force_reg (SImode, operands[2]);
2690     }
2691   "
2692 )
2693
2694 (define_insn "*thumb_rotrsi3"
2695   [(set (match_operand:SI              0 "register_operand" "=l")
2696         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2697                      (match_operand:SI 2 "register_operand" "l")))]
2698   "TARGET_THUMB"
2699   "ror\\t%0, %0, %2"
2700   [(set_attr "length" "2")]
2701 )
2702
2703 (define_insn "*arm_shiftsi3"
2704   [(set (match_operand:SI   0 "s_register_operand" "=r")
2705         (match_operator:SI  3 "shift_operator"
2706          [(match_operand:SI 1 "s_register_operand"  "r")
2707           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2708   "TARGET_ARM"
2709   "mov%?\\t%0, %1%S3"
2710   [(set_attr "predicable" "yes")
2711    (set_attr "shift" "1")
2712    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2713                       (const_string "alu_shift")
2714                       (const_string "alu_shift_reg")))]
2715 )
2716
2717 (define_insn "*shiftsi3_compare0"
2718   [(set (reg:CC_NOOV CC_REGNUM)
2719         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2720                           [(match_operand:SI 1 "s_register_operand" "r")
2721                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2722                          (const_int 0)))
2723    (set (match_operand:SI 0 "s_register_operand" "=r")
2724         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2725   "TARGET_ARM"
2726   "mov%?s\\t%0, %1%S3"
2727   [(set_attr "conds" "set")
2728    (set_attr "shift" "1")
2729    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2730                       (const_string "alu_shift")
2731                       (const_string "alu_shift_reg")))]
2732 )
2733
2734 (define_insn "*shiftsi3_compare0_scratch"
2735   [(set (reg:CC_NOOV CC_REGNUM)
2736         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2737                           [(match_operand:SI 1 "s_register_operand" "r")
2738                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2739                          (const_int 0)))
2740    (clobber (match_scratch:SI 0 "=r"))]
2741   "TARGET_ARM"
2742   "mov%?s\\t%0, %1%S3"
2743   [(set_attr "conds" "set")
2744    (set_attr "shift" "1")]
2745 )
2746
2747 (define_insn "*notsi_shiftsi"
2748   [(set (match_operand:SI 0 "s_register_operand" "=r")
2749         (not:SI (match_operator:SI 3 "shift_operator"
2750                  [(match_operand:SI 1 "s_register_operand" "r")
2751                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2752   "TARGET_ARM"
2753   "mvn%?\\t%0, %1%S3"
2754   [(set_attr "predicable" "yes")
2755    (set_attr "shift" "1")
2756    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2757                       (const_string "alu_shift")
2758                       (const_string "alu_shift_reg")))]
2759 )
2760
2761 (define_insn "*notsi_shiftsi_compare0"
2762   [(set (reg:CC_NOOV CC_REGNUM)
2763         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2764                           [(match_operand:SI 1 "s_register_operand" "r")
2765                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2766                          (const_int 0)))
2767    (set (match_operand:SI 0 "s_register_operand" "=r")
2768         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2769   "TARGET_ARM"
2770   "mvn%?s\\t%0, %1%S3"
2771   [(set_attr "conds" "set")
2772    (set_attr "shift" "1")
2773    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2774                       (const_string "alu_shift")
2775                       (const_string "alu_shift_reg")))]
2776 )
2777
2778 (define_insn "*not_shiftsi_compare0_scratch"
2779   [(set (reg:CC_NOOV CC_REGNUM)
2780         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2781                           [(match_operand:SI 1 "s_register_operand" "r")
2782                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2783                          (const_int 0)))
2784    (clobber (match_scratch:SI 0 "=r"))]
2785   "TARGET_ARM"
2786   "mvn%?s\\t%0, %1%S3"
2787   [(set_attr "conds" "set")
2788    (set_attr "shift" "1")
2789    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2790                       (const_string "alu_shift")
2791                       (const_string "alu_shift_reg")))]
2792 )
2793
2794 ;; We don't really have extzv, but defining this using shifts helps
2795 ;; to reduce register pressure later on.
2796
2797 (define_expand "extzv"
2798   [(set (match_dup 4)
2799         (ashift:SI (match_operand:SI   1 "register_operand" "")
2800                    (match_operand:SI   2 "const_int_operand" "")))
2801    (set (match_operand:SI              0 "register_operand" "")
2802         (lshiftrt:SI (match_dup 4)
2803                      (match_operand:SI 3 "const_int_operand" "")))]
2804   "TARGET_THUMB"
2805   "
2806   {
2807     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2808     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2809     
2810     operands[3] = GEN_INT (rshift);
2811     
2812     if (lshift == 0)
2813       {
2814         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2815         DONE;
2816       }
2817       
2818     operands[2] = GEN_INT (lshift);
2819     operands[4] = gen_reg_rtx (SImode);
2820   }"
2821 )
2822
2823 \f
2824 ;; Unary arithmetic insns
2825
2826 (define_expand "negdi2"
2827  [(parallel
2828    [(set (match_operand:DI          0 "s_register_operand" "")
2829           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2830     (clobber (reg:CC CC_REGNUM))])]
2831   "TARGET_EITHER"
2832   "
2833   if (TARGET_THUMB)
2834     {
2835       if (GET_CODE (operands[1]) != REG)
2836         operands[1] = force_reg (SImode, operands[1]);
2837      }
2838   "
2839 )
2840
2841 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2842 ;; The second alternative is to allow the common case of a *full* overlap.
2843 (define_insn "*arm_negdi2"
2844   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2845         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2846    (clobber (reg:CC CC_REGNUM))]
2847   "TARGET_ARM"
2848   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2849   [(set_attr "conds" "clob")
2850    (set_attr "length" "8")]
2851 )
2852
2853 (define_insn "*thumb_negdi2"
2854   [(set (match_operand:DI         0 "register_operand" "=&l")
2855         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
2856    (clobber (reg:CC CC_REGNUM))]
2857   "TARGET_THUMB"
2858   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2859   [(set_attr "length" "6")]
2860 )
2861
2862 (define_expand "negsi2"
2863   [(set (match_operand:SI         0 "s_register_operand" "")
2864         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2865   "TARGET_EITHER"
2866   ""
2867 )
2868
2869 (define_insn "*arm_negsi2"
2870   [(set (match_operand:SI         0 "s_register_operand" "=r")
2871         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2872   "TARGET_ARM"
2873   "rsb%?\\t%0, %1, #0"
2874   [(set_attr "predicable" "yes")]
2875 )
2876
2877 (define_insn "*thumb_negsi2"
2878   [(set (match_operand:SI         0 "register_operand" "=l")
2879         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2880   "TARGET_THUMB"
2881   "neg\\t%0, %1"
2882   [(set_attr "length" "2")]
2883 )
2884
2885 (define_expand "negsf2"
2886   [(set (match_operand:SF         0 "s_register_operand" "")
2887         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2888   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2889   ""
2890 )
2891
2892 (define_expand "negdf2"
2893   [(set (match_operand:DF         0 "s_register_operand" "")
2894         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2895   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2896   "")
2897
2898 ;; abssi2 doesn't really clobber the condition codes if a different register
2899 ;; is being set.  To keep things simple, assume during rtl manipulations that
2900 ;; it does, but tell the final scan operator the truth.  Similarly for
2901 ;; (neg (abs...))
2902
2903 (define_expand "abssi2"
2904   [(parallel
2905     [(set (match_operand:SI         0 "s_register_operand" "")
2906           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
2907      (clobber (reg:CC CC_REGNUM))])]
2908   "TARGET_ARM"
2909   "")
2910
2911 (define_insn "*arm_abssi2"
2912   [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
2913         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2914    (clobber (reg:CC CC_REGNUM))]
2915   "TARGET_ARM"
2916   "@
2917    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2918    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2919   [(set_attr "conds" "clob,*")
2920    (set_attr "shift" "1")
2921    ;; predicable can't be set based on the variant, so left as no
2922    (set_attr "length" "8")]
2923 )
2924
2925 (define_insn "*neg_abssi2"
2926   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2927         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2928    (clobber (reg:CC CC_REGNUM))]
2929   "TARGET_ARM"
2930   "@
2931    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2932    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2933   [(set_attr "conds" "clob,*")
2934    (set_attr "shift" "1")
2935    ;; predicable can't be set based on the variant, so left as no
2936    (set_attr "length" "8")]
2937 )
2938
2939 (define_expand "abssf2"
2940   [(set (match_operand:SF         0 "s_register_operand" "")
2941         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
2942   "TARGET_ARM && TARGET_HARD_FLOAT"
2943   "")
2944
2945 (define_expand "absdf2"
2946   [(set (match_operand:DF         0 "s_register_operand" "")
2947         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
2948   "TARGET_ARM && TARGET_HARD_FLOAT"
2949   "")
2950
2951 (define_expand "sqrtsf2"
2952   [(set (match_operand:SF 0 "s_register_operand" "")
2953         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
2954   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
2955   "")
2956
2957 (define_expand "sqrtdf2"
2958   [(set (match_operand:DF 0 "s_register_operand" "")
2959         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
2960   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
2961   "")
2962
2963 (define_insn_and_split "one_cmpldi2"
2964   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2965         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2966   "TARGET_ARM"
2967   "#"
2968   "TARGET_ARM && reload_completed"
2969   [(set (match_dup 0) (not:SI (match_dup 1)))
2970    (set (match_dup 2) (not:SI (match_dup 3)))]
2971   "
2972   {
2973     operands[2] = gen_highpart (SImode, operands[0]);
2974     operands[0] = gen_lowpart (SImode, operands[0]);
2975     operands[3] = gen_highpart (SImode, operands[1]);
2976     operands[1] = gen_lowpart (SImode, operands[1]);
2977   }"
2978   [(set_attr "length" "8")
2979    (set_attr "predicable" "yes")]
2980 )
2981
2982 (define_expand "one_cmplsi2"
2983   [(set (match_operand:SI         0 "s_register_operand" "")
2984         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
2985   "TARGET_EITHER"
2986   ""
2987 )
2988
2989 (define_insn "*arm_one_cmplsi2"
2990   [(set (match_operand:SI         0 "s_register_operand" "=r")
2991         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
2992   "TARGET_ARM"
2993   "mvn%?\\t%0, %1"
2994   [(set_attr "predicable" "yes")]
2995 )
2996
2997 (define_insn "*thumb_one_cmplsi2"
2998   [(set (match_operand:SI         0 "register_operand" "=l")
2999         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3000   "TARGET_THUMB"
3001   "mvn\\t%0, %1"
3002   [(set_attr "length" "2")]
3003 )
3004
3005 (define_insn "*notsi_compare0"
3006   [(set (reg:CC_NOOV CC_REGNUM)
3007         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3008                          (const_int 0)))
3009    (set (match_operand:SI 0 "s_register_operand" "=r")
3010         (not:SI (match_dup 1)))]
3011   "TARGET_ARM"
3012   "mvn%?s\\t%0, %1"
3013   [(set_attr "conds" "set")]
3014 )
3015
3016 (define_insn "*notsi_compare0_scratch"
3017   [(set (reg:CC_NOOV CC_REGNUM)
3018         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3019                          (const_int 0)))
3020    (clobber (match_scratch:SI 0 "=r"))]
3021   "TARGET_ARM"
3022   "mvn%?s\\t%0, %1"
3023   [(set_attr "conds" "set")]
3024 )
3025 \f
3026 ;; Fixed <--> Floating conversion insns
3027
3028 (define_expand "floatsisf2"
3029   [(set (match_operand:SF           0 "s_register_operand" "")
3030         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3031   "TARGET_ARM && TARGET_HARD_FLOAT"
3032   "
3033   if (TARGET_MAVERICK)
3034     {
3035       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3036       DONE;
3037     }
3038 ")
3039
3040 (define_expand "floatsidf2"
3041   [(set (match_operand:DF           0 "s_register_operand" "")
3042         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3043   "TARGET_ARM && TARGET_HARD_FLOAT"
3044   "
3045   if (TARGET_MAVERICK)
3046     {
3047       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3048       DONE;
3049     }
3050 ")
3051
3052 (define_expand "fix_truncsfsi2"
3053   [(set (match_operand:SI         0 "s_register_operand" "")
3054         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3055   "TARGET_ARM && TARGET_HARD_FLOAT"
3056   "
3057   if (TARGET_MAVERICK)
3058     {
3059       if (!cirrus_fp_register (operands[0], SImode))
3060         operands[0] = force_reg (SImode, operands[0]);
3061       if (!cirrus_fp_register (operands[1], SFmode))
3062         operands[1] = force_reg (SFmode, operands[0]);
3063       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3064       DONE;
3065     }
3066 ")
3067
3068 (define_expand "fix_truncdfsi2"
3069   [(set (match_operand:SI         0 "s_register_operand" "")
3070         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3071   "TARGET_ARM && TARGET_HARD_FLOAT"
3072   "
3073   if (TARGET_MAVERICK)
3074     {
3075       if (!cirrus_fp_register (operands[1], DFmode))
3076         operands[1] = force_reg (DFmode, operands[0]);
3077       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3078       DONE;
3079     }
3080 ")
3081
3082 ;; Truncation insns
3083
3084 (define_expand "truncdfsf2"
3085   [(set (match_operand:SF  0 "s_register_operand" "")
3086         (float_truncate:SF
3087          (match_operand:DF 1 "s_register_operand" "")))]
3088   "TARGET_ARM && TARGET_HARD_FLOAT"
3089   ""
3090 )
3091 \f
3092 ;; Zero and sign extension instructions.
3093
3094 (define_insn "zero_extendsidi2"
3095   [(set (match_operand:DI 0 "s_register_operand" "=r")
3096         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3097   "TARGET_ARM"
3098   "*
3099     if (REGNO (operands[1])
3100         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3101       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3102     return \"mov%?\\t%R0, #0\";
3103   "
3104   [(set_attr "length" "8")
3105    (set_attr "predicable" "yes")]
3106 )
3107
3108 (define_insn "zero_extendqidi2"
3109   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3110         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3111   "TARGET_ARM"
3112   "@
3113    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3114    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3115   [(set_attr "length" "8")
3116    (set_attr "predicable" "yes")
3117    (set_attr "type" "*,load_byte")
3118    (set_attr "pool_range" "*,4092")
3119    (set_attr "neg_pool_range" "*,4084")]
3120 )
3121
3122 (define_insn "extendsidi2"
3123   [(set (match_operand:DI 0 "s_register_operand" "=r")
3124         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3125   "TARGET_ARM"
3126   "*
3127     if (REGNO (operands[1])
3128         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3129       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3130     return \"mov%?\\t%R0, %Q0, asr #31\";
3131   "
3132   [(set_attr "length" "8")
3133    (set_attr "shift" "1")
3134    (set_attr "predicable" "yes")]
3135 )
3136
3137 (define_expand "zero_extendhisi2"
3138   [(set (match_dup 2)
3139         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3140                    (const_int 16)))
3141    (set (match_operand:SI 0 "s_register_operand" "")
3142         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3143   "TARGET_EITHER"
3144   "
3145   {
3146     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3147       {
3148        /* Note: We do not have to worry about TARGET_MMU_TRAPS
3149           here because the insn below will generate an LDRH instruction
3150           rather than an LDR instruction, so we cannot get an unaligned
3151           word access.  */
3152         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3153                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3154         DONE;
3155       }
3156
3157     if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3158       {
3159         emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3160         DONE;
3161       }
3162
3163     if (!s_register_operand (operands[1], HImode))
3164       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3165
3166     if (arm_arch6)
3167       {
3168         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3169                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3170         DONE;
3171       }
3172
3173     operands[1] = gen_lowpart (SImode, operands[1]);
3174     operands[2] = gen_reg_rtx (SImode);
3175   }"
3176 )
3177
3178 (define_insn "*thumb_zero_extendhisi2"
3179   [(set (match_operand:SI 0 "register_operand" "=l")
3180         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3181   "TARGET_THUMB && !arm_arch6"
3182   "*
3183   rtx mem = XEXP (operands[1], 0);
3184
3185   if (GET_CODE (mem) == CONST)
3186     mem = XEXP (mem, 0);
3187     
3188   if (GET_CODE (mem) == LABEL_REF)
3189     return \"ldr\\t%0, %1\";
3190     
3191   if (GET_CODE (mem) == PLUS)
3192     {
3193       rtx a = XEXP (mem, 0);
3194       rtx b = XEXP (mem, 1);
3195
3196       /* This can happen due to bugs in reload.  */
3197       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3198         {
3199           rtx ops[2];
3200           ops[0] = operands[0];
3201           ops[1] = a;
3202       
3203           output_asm_insn (\"mov        %0, %1\", ops);
3204
3205           XEXP (mem, 0) = operands[0];
3206        }
3207
3208       else if (   GET_CODE (a) == LABEL_REF
3209                && GET_CODE (b) == CONST_INT)
3210         return \"ldr\\t%0, %1\";
3211     }
3212     
3213   return \"ldrh\\t%0, %1\";
3214   "
3215   [(set_attr "length" "4")
3216    (set_attr "type" "load_byte")
3217    (set_attr "pool_range" "60")]
3218 )
3219
3220 (define_insn "*thumb_zero_extendhisi2_v6"
3221   [(set (match_operand:SI 0 "register_operand" "=l,l")
3222         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3223   "TARGET_THUMB && arm_arch6"
3224   "*
3225   rtx mem;
3226
3227   if (which_alternative == 0)
3228     return \"uxth\\t%0, %1\";
3229
3230   mem = XEXP (operands[1], 0);
3231
3232   if (GET_CODE (mem) == CONST)
3233     mem = XEXP (mem, 0);
3234     
3235   if (GET_CODE (mem) == LABEL_REF)
3236     return \"ldr\\t%0, %1\";
3237     
3238   if (GET_CODE (mem) == PLUS)
3239     {
3240       rtx a = XEXP (mem, 0);
3241       rtx b = XEXP (mem, 1);
3242
3243       /* This can happen due to bugs in reload.  */
3244       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3245         {
3246           rtx ops[2];
3247           ops[0] = operands[0];
3248           ops[1] = a;
3249       
3250           output_asm_insn (\"mov        %0, %1\", ops);
3251
3252           XEXP (mem, 0) = operands[0];
3253        }
3254
3255       else if (   GET_CODE (a) == LABEL_REF
3256                && GET_CODE (b) == CONST_INT)
3257         return \"ldr\\t%0, %1\";
3258     }
3259     
3260   return \"ldrh\\t%0, %1\";
3261   "
3262   [(set_attr "length" "2,4")
3263    (set_attr "type" "alu_shift,load_byte")
3264    (set_attr "pool_range" "*,60")]
3265 )
3266
3267 (define_insn "*arm_zero_extendhisi2"
3268   [(set (match_operand:SI 0 "s_register_operand" "=r")
3269         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3270   "TARGET_ARM && arm_arch4 && !arm_arch6"
3271   "ldr%?h\\t%0, %1"
3272   [(set_attr "type" "load_byte")
3273    (set_attr "predicable" "yes")
3274    (set_attr "pool_range" "256")
3275    (set_attr "neg_pool_range" "244")]
3276 )
3277
3278 (define_insn "*arm_zero_extendhisi2_v6"
3279   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3280         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3281   "TARGET_ARM && arm_arch6"
3282   "@
3283    uxth%?\\t%0, %1
3284    ldr%?h\\t%0, %1"
3285   [(set_attr "type" "alu_shift,load_byte")
3286    (set_attr "predicable" "yes")
3287    (set_attr "pool_range" "*,256")
3288    (set_attr "neg_pool_range" "*,244")]
3289 )
3290
3291 (define_insn "*arm_zero_extendhisi2addsi"
3292   [(set (match_operand:SI 0 "s_register_operand" "=r")
3293         (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3294                  (match_operand:SI 2 "s_register_operand" "r")))]
3295   "TARGET_ARM && arm_arch6"
3296   "uxtah%?\\t%0, %2, %1"
3297   [(set_attr "type" "alu_shift")
3298    (set_attr "predicable" "yes")]
3299 )
3300
3301 (define_split
3302   [(set (match_operand:SI 0 "s_register_operand" "")
3303         (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3304    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3305   "TARGET_ARM && (!arm_arch4)"
3306   [(set (match_dup 2) (match_dup 1))
3307    (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3308   "
3309   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3310     FAIL;
3311   "
3312 )
3313
3314 (define_split
3315   [(set (match_operand:SI 0 "s_register_operand" "")
3316         (match_operator:SI 3 "shiftable_operator"
3317          [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3318           (match_operand:SI 4 "s_register_operand" "")]))
3319    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3320   "TARGET_ARM && (!arm_arch4)"
3321   [(set (match_dup 2) (match_dup 1))
3322    (set (match_dup 0)
3323         (match_op_dup 3
3324          [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3325   "
3326   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3327     FAIL;
3328   "
3329 )
3330
3331 (define_expand "zero_extendqisi2"
3332   [(set (match_operand:SI 0 "s_register_operand" "")
3333         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3334   "TARGET_EITHER"
3335   "
3336   if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3337     {
3338       if (TARGET_ARM)
3339         {
3340           emit_insn (gen_andsi3 (operands[0],
3341                                  gen_lowpart (SImode, operands[1]),
3342                                  GEN_INT (255)));
3343         }
3344       else /* TARGET_THUMB */
3345         {
3346           rtx temp = gen_reg_rtx (SImode);
3347           rtx ops[3];
3348           
3349           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3350           operands[1] = gen_lowpart (SImode, operands[1]);
3351
3352           ops[0] = temp;
3353           ops[1] = operands[1];
3354           ops[2] = GEN_INT (24);
3355
3356           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3357                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3358           
3359           ops[0] = operands[0];
3360           ops[1] = temp;
3361           ops[2] = GEN_INT (24);
3362
3363           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3364                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3365         }
3366       DONE;
3367     }
3368   "
3369 )
3370
3371 (define_insn "*thumb_zero_extendqisi2"
3372   [(set (match_operand:SI 0 "register_operand" "=l")
3373         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3374   "TARGET_THUMB && !arm_arch6"
3375   "ldrb\\t%0, %1"
3376   [(set_attr "length" "2")
3377    (set_attr "type" "load_byte")
3378    (set_attr "pool_range" "32")]
3379 )
3380
3381 (define_insn "*thumb_zero_extendqisi2_v6"
3382   [(set (match_operand:SI 0 "register_operand" "=l,l")
3383         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3384   "TARGET_THUMB && arm_arch6"
3385   "@
3386    uxtb\\t%0, %1
3387    ldrb\\t%0, %1"
3388   [(set_attr "length" "2,2")
3389    (set_attr "type" "alu_shift,load_byte")
3390    (set_attr "pool_range" "*,32")]
3391 )
3392
3393 (define_insn "*arm_zero_extendqisi2"
3394   [(set (match_operand:SI 0 "s_register_operand" "=r")
3395         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3396   "TARGET_ARM && !arm_arch6"
3397   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3398   [(set_attr "type" "load_byte")
3399    (set_attr "predicable" "yes")
3400    (set_attr "pool_range" "4096")
3401    (set_attr "neg_pool_range" "4084")]
3402 )
3403
3404 (define_insn "*arm_zero_extendqisi2_v6"
3405   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3406         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3407   "TARGET_ARM && arm_arch6"
3408   "@
3409    uxtb%?\\t%0, %1
3410    ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3411   [(set_attr "type" "alu_shift,load_byte")
3412    (set_attr "predicable" "yes")
3413    (set_attr "pool_range" "*,4096")
3414    (set_attr "neg_pool_range" "*,4084")]
3415 )
3416
3417 (define_insn "*arm_zero_extendqisi2addsi"
3418   [(set (match_operand:SI 0 "s_register_operand" "=r")
3419         (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3420                  (match_operand:SI 2 "s_register_operand" "r")))]
3421   "TARGET_ARM && arm_arch6"
3422   "uxtab%?\\t%0, %2, %1"
3423   [(set_attr "predicable" "yes")
3424    (set_attr "type" "alu_shift")]
3425 )
3426
3427 (define_split
3428   [(set (match_operand:SI 0 "s_register_operand" "")
3429         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3430    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3431   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3432   [(set (match_dup 2) (match_dup 1))
3433    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3434   ""
3435 )
3436
3437 (define_insn "*compareqi_eq0"
3438   [(set (reg:CC_Z CC_REGNUM)
3439         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3440                          (const_int 0)))]
3441   "TARGET_ARM"
3442   "tst\\t%0, #255"
3443   [(set_attr "conds" "set")]
3444 )
3445
3446 (define_expand "extendhisi2"
3447   [(set (match_dup 2)
3448         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3449                    (const_int 16)))
3450    (set (match_operand:SI 0 "s_register_operand" "")
3451         (ashiftrt:SI (match_dup 2)
3452                      (const_int 16)))]
3453   "TARGET_EITHER"
3454   "
3455   {
3456     if (GET_CODE (operands[1]) == MEM)
3457       {
3458         if (TARGET_THUMB)
3459           {
3460             emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3461             DONE;
3462           }
3463         else if (arm_arch4)
3464           {
3465             /* Note: We do not have to worry about TARGET_MMU_TRAPS
3466                here because the insn below will generate an LDRH instruction
3467                rather than an LDR instruction, so we cannot get an unaligned
3468                word access.  */
3469             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3470                        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3471             DONE;
3472           }
3473       }
3474
3475     if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3476       {
3477         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3478         DONE;
3479       }
3480
3481     if (!s_register_operand (operands[1], HImode))
3482       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3483
3484     if (arm_arch6)
3485       {
3486         if (TARGET_THUMB)
3487           emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3488         else
3489           emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3490                      gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3491
3492         DONE;
3493       }
3494
3495     operands[1] = gen_lowpart (SImode, operands[1]);
3496     operands[2] = gen_reg_rtx (SImode);
3497   }"
3498 )
3499
3500 (define_insn "thumb_extendhisi2"
3501   [(set (match_operand:SI 0 "register_operand" "=l")
3502         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3503    (clobber (match_scratch:SI 2 "=&l"))]
3504   "TARGET_THUMB && !arm_arch6"
3505   "*
3506   {
3507     rtx ops[4];
3508     rtx mem = XEXP (operands[1], 0);
3509
3510     /* This code used to try to use 'V', and fix the address only if it was
3511        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3512        range of QImode offsets, and offsettable_address_p does a QImode
3513        address check.  */
3514        
3515     if (GET_CODE (mem) == CONST)
3516       mem = XEXP (mem, 0);
3517     
3518     if (GET_CODE (mem) == LABEL_REF)
3519       return \"ldr\\t%0, %1\";
3520     
3521     if (GET_CODE (mem) == PLUS)
3522       {
3523         rtx a = XEXP (mem, 0);
3524         rtx b = XEXP (mem, 1);
3525
3526         if (GET_CODE (a) == LABEL_REF
3527             && GET_CODE (b) == CONST_INT)
3528           return \"ldr\\t%0, %1\";
3529
3530         if (GET_CODE (b) == REG)
3531           return \"ldrsh\\t%0, %1\";
3532           
3533         ops[1] = a;
3534         ops[2] = b;
3535       }
3536     else
3537       {
3538         ops[1] = mem;
3539         ops[2] = const0_rtx;
3540       }
3541       
3542     if (GET_CODE (ops[1]) != REG)
3543       {
3544         debug_rtx (ops[1]);
3545         abort ();
3546       }
3547
3548     ops[0] = operands[0];
3549     ops[3] = operands[2];
3550     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3551     return \"\";
3552   }"
3553   [(set_attr "length" "4")
3554    (set_attr "type" "load_byte")
3555    (set_attr "pool_range" "1020")]
3556 )
3557
3558 ;; We used to have an early-clobber on the scratch register here.
3559 ;; However, there's a bug somewhere in reload which means that this
3560 ;; can be partially ignored during spill allocation if the memory
3561 ;; address also needs reloading; this causes an abort later on when
3562 ;; we try to verify the operands.  Fortunately, we don't really need
3563 ;; the early-clobber: we can always use operand 0 if operand 2
3564 ;; overlaps the address.
3565 (define_insn "*thumb_extendhisi2_insn_v6"
3566   [(set (match_operand:SI 0 "register_operand" "=l,l")
3567         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3568    (clobber (match_scratch:SI 2 "=X,l"))]
3569   "TARGET_THUMB && arm_arch6"
3570   "*
3571   {
3572     rtx ops[4];
3573     rtx mem;
3574
3575     if (which_alternative == 0)
3576       return \"sxth\\t%0, %1\";
3577
3578     mem = XEXP (operands[1], 0);
3579
3580     /* This code used to try to use 'V', and fix the address only if it was
3581        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3582        range of QImode offsets, and offsettable_address_p does a QImode
3583        address check.  */
3584        
3585     if (GET_CODE (mem) == CONST)
3586       mem = XEXP (mem, 0);
3587     
3588     if (GET_CODE (mem) == LABEL_REF)
3589       return \"ldr\\t%0, %1\";
3590     
3591     if (GET_CODE (mem) == PLUS)
3592       {
3593         rtx a = XEXP (mem, 0);
3594         rtx b = XEXP (mem, 1);
3595
3596         if (GET_CODE (a) == LABEL_REF
3597             && GET_CODE (b) == CONST_INT)
3598           return \"ldr\\t%0, %1\";
3599
3600         if (GET_CODE (b) == REG)
3601           return \"ldrsh\\t%0, %1\";
3602           
3603         ops[1] = a;
3604         ops[2] = b;
3605       }
3606     else
3607       {
3608         ops[1] = mem;
3609         ops[2] = const0_rtx;
3610       }
3611       
3612     if (GET_CODE (ops[1]) != REG)
3613       {
3614         debug_rtx (ops[1]);
3615         abort ();
3616       }
3617
3618     ops[0] = operands[0];
3619     if (reg_mentioned_p (operands[2], ops[1]))
3620       ops[3] = ops[0];
3621     else
3622       ops[3] = operands[2];
3623     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3624     return \"\";
3625   }"
3626   [(set_attr "length" "2,4")
3627    (set_attr "type" "alu_shift,load_byte")
3628    (set_attr "pool_range" "*,1020")]
3629 )
3630
3631 (define_expand "extendhisi2_mem"
3632   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3633    (set (match_dup 3)
3634         (zero_extend:SI (match_dup 7)))
3635    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3636    (set (match_operand:SI 0 "" "")
3637         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3638   "TARGET_ARM"
3639   "
3640   {
3641     rtx mem1, mem2;
3642     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3643
3644     mem1 = gen_rtx_MEM (QImode, addr);
3645     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3646     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3647     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3648     operands[0] = gen_lowpart (SImode, operands[0]);
3649     operands[1] = mem1;
3650     operands[2] = gen_reg_rtx (SImode);
3651     operands[3] = gen_reg_rtx (SImode);
3652     operands[6] = gen_reg_rtx (SImode);
3653     operands[7] = mem2;
3654
3655     if (BYTES_BIG_ENDIAN)
3656       {
3657         operands[4] = operands[2];
3658         operands[5] = operands[3];
3659       }
3660     else
3661       {
3662         operands[4] = operands[3];
3663         operands[5] = operands[2];
3664       }
3665   }"
3666 )
3667
3668 (define_insn "*arm_extendhisi2"
3669   [(set (match_operand:SI 0 "s_register_operand" "=r")
3670         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3671   "TARGET_ARM && arm_arch4 && !arm_arch6"
3672   "ldr%?sh\\t%0, %1"
3673   [(set_attr "type" "load_byte")
3674    (set_attr "predicable" "yes")
3675    (set_attr "pool_range" "256")
3676    (set_attr "neg_pool_range" "244")]
3677 )
3678
3679 (define_insn "*arm_extendhisi2_v6"
3680   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3681         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3682   "TARGET_ARM && arm_arch6"
3683   "@
3684    sxth%?\\t%0, %1
3685    ldr%?sh\\t%0, %1"
3686   [(set_attr "type" "alu_shift,load_byte")
3687    (set_attr "predicable" "yes")
3688    (set_attr "pool_range" "*,256")
3689    (set_attr "neg_pool_range" "*,244")]
3690 )
3691
3692 (define_insn "*arm_extendhisi2addsi"
3693   [(set (match_operand:SI 0 "s_register_operand" "=r")
3694         (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3695                  (match_operand:SI 2 "s_register_operand" "r")))]
3696   "TARGET_ARM && arm_arch6"
3697   "sxtah%?\\t%0, %2, %1"
3698 )
3699
3700 (define_split
3701   [(set (match_operand:SI                 0 "s_register_operand" "")
3702         (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3703    (clobber (match_operand:SI             2 "s_register_operand" ""))]
3704   "TARGET_ARM && (!arm_arch4)"
3705   [(set (match_dup 2) (match_dup 1))
3706    (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3707   "
3708   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3709     FAIL;
3710   "
3711 )
3712
3713 (define_split
3714   [(set (match_operand:SI                   0 "s_register_operand" "")
3715         (match_operator:SI                  3 "shiftable_operator"
3716          [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3717           (match_operand:SI                 4 "s_register_operand" "")]))
3718    (clobber (match_operand:SI               2 "s_register_operand" ""))]
3719   "TARGET_ARM && (!arm_arch4)"
3720   [(set (match_dup 2) (match_dup 1))
3721    (set (match_dup 0)
3722         (match_op_dup 3
3723          [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3724   "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3725      FAIL;
3726   "
3727 )
3728
3729 (define_expand "extendqihi2"
3730   [(set (match_dup 2)
3731         (ashift:SI (match_operand:QI 1 "general_operand" "")
3732                    (const_int 24)))
3733    (set (match_operand:HI 0 "s_register_operand" "")
3734         (ashiftrt:SI (match_dup 2)
3735                      (const_int 24)))]
3736   "TARGET_ARM"
3737   "
3738   {
3739     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3740       {
3741         emit_insn (gen_rtx_SET (VOIDmode,
3742                                 operands[0],
3743                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3744         DONE;
3745       }
3746     if (!s_register_operand (operands[1], QImode))
3747       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3748     operands[0] = gen_lowpart (SImode, operands[0]);
3749     operands[1] = gen_lowpart (SImode, operands[1]);
3750     operands[2] = gen_reg_rtx (SImode);
3751   }"
3752 )
3753
3754 (define_insn "*extendqihi_insn"
3755   [(set (match_operand:HI 0 "s_register_operand" "=r")
3756         (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3757   "TARGET_ARM && arm_arch4"
3758   "ldr%?sb\\t%0, %1"
3759   [(set_attr "type" "load_byte")
3760    (set_attr "predicable" "yes")
3761    (set_attr "pool_range" "256")
3762    (set_attr "neg_pool_range" "244")]
3763 )
3764
3765 (define_expand "extendqisi2"
3766   [(set (match_dup 2)
3767         (ashift:SI (match_operand:QI 1 "general_operand" "")
3768                    (const_int 24)))
3769    (set (match_operand:SI 0 "s_register_operand" "")
3770         (ashiftrt:SI (match_dup 2)
3771                      (const_int 24)))]
3772   "TARGET_EITHER"
3773   "
3774   {
3775     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3776       {
3777         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3778                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3779         DONE;
3780       }
3781
3782     if (!s_register_operand (operands[1], QImode))
3783       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3784
3785     if (arm_arch6)
3786       {
3787         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3788                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3789         DONE;
3790       }
3791
3792     operands[1] = gen_lowpart (SImode, operands[1]);
3793     operands[2] = gen_reg_rtx (SImode);
3794   }"
3795 )
3796
3797 (define_insn "*arm_extendqisi"
3798   [(set (match_operand:SI 0 "s_register_operand" "=r")
3799         (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3800   "TARGET_ARM && arm_arch4 && !arm_arch6"
3801   "ldr%?sb\\t%0, %1"
3802   [(set_attr "type" "load_byte")
3803    (set_attr "predicable" "yes")
3804    (set_attr "pool_range" "256")
3805    (set_attr "neg_pool_range" "244")]
3806 )
3807
3808 (define_insn "*arm_extendqisi_v6"
3809   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3810         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3811   "TARGET_ARM && arm_arch6"
3812   "@
3813    sxtb%?\\t%0, %1
3814    ldr%?sb\\t%0, %1"
3815   [(set_attr "type" "alu_shift,load_byte")
3816    (set_attr "predicable" "yes")
3817    (set_attr "pool_range" "*,256")
3818    (set_attr "neg_pool_range" "*,244")]
3819 )
3820
3821 (define_insn "*arm_extendqisi2addsi"
3822   [(set (match_operand:SI 0 "s_register_operand" "=r")
3823         (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3824                  (match_operand:SI 2 "s_register_operand" "r")))]
3825   "TARGET_ARM && arm_arch6"
3826   "sxtab%?\\t%0, %2, %1"
3827   [(set_attr "type" "alu_shift")
3828    (set_attr "predicable" "yes")]
3829 )
3830
3831 (define_insn "*thumb_extendqisi2"
3832   [(set (match_operand:SI 0 "register_operand" "=l,l")
3833         (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3834   "TARGET_THUMB && !arm_arch6"
3835   "*
3836   {
3837     rtx ops[3];
3838     rtx mem = XEXP (operands[1], 0);
3839     
3840     if (GET_CODE (mem) == CONST)
3841       mem = XEXP (mem, 0);
3842     
3843     if (GET_CODE (mem) == LABEL_REF)
3844       return \"ldr\\t%0, %1\";
3845
3846     if (GET_CODE (mem) == PLUS
3847         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3848       return \"ldr\\t%0, %1\";
3849       
3850     if (which_alternative == 0)
3851       return \"ldrsb\\t%0, %1\";
3852       
3853     ops[0] = operands[0];
3854     
3855     if (GET_CODE (mem) == PLUS)
3856       {
3857         rtx a = XEXP (mem, 0);
3858         rtx b = XEXP (mem, 1);
3859         
3860         ops[1] = a;
3861         ops[2] = b;
3862
3863         if (GET_CODE (a) == REG)
3864           {
3865             if (GET_CODE (b) == REG)
3866               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3867             else if (REGNO (a) == REGNO (ops[0]))
3868               {
3869                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3870                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3871                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3872               }
3873             else
3874               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3875           }
3876         else if (GET_CODE (b) != REG)
3877           abort ();
3878         else
3879           {
3880             if (REGNO (b) == REGNO (ops[0]))
3881               {
3882                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3883                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3884                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3885               }
3886             else
3887               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3888           }
3889       }
3890     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3891       {
3892         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3893         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3894         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3895       }
3896     else
3897       {
3898         ops[1] = mem;
3899         ops[2] = const0_rtx;
3900         
3901         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3902       }
3903     return \"\";
3904   }"
3905   [(set_attr "length" "2,6")
3906    (set_attr "type" "load_byte,load_byte")
3907    (set_attr "pool_range" "32,32")]
3908 )
3909
3910 (define_insn "*thumb_extendqisi2_v6"
3911   [(set (match_operand:SI 0 "register_operand" "=l,l,l")
3912         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
3913   "TARGET_THUMB && arm_arch6"
3914   "*
3915   {
3916     rtx ops[3];
3917     rtx mem;
3918
3919     if (which_alternative == 0)
3920       return \"sxtb\\t%0, %1\";
3921
3922     mem = XEXP (operands[1], 0);
3923     
3924     if (GET_CODE (mem) == CONST)
3925       mem = XEXP (mem, 0);
3926     
3927     if (GET_CODE (mem) == LABEL_REF)
3928       return \"ldr\\t%0, %1\";
3929
3930     if (GET_CODE (mem) == PLUS
3931         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3932       return \"ldr\\t%0, %1\";
3933       
3934     if (which_alternative == 0)
3935       return \"ldrsb\\t%0, %1\";
3936       
3937     ops[0] = operands[0];
3938     
3939     if (GET_CODE (mem) == PLUS)
3940       {
3941         rtx a = XEXP (mem, 0);
3942         rtx b = XEXP (mem, 1);
3943         
3944         ops[1] = a;
3945         ops[2] = b;
3946
3947         if (GET_CODE (a) == REG)
3948           {
3949             if (GET_CODE (b) == REG)
3950               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3951             else if (REGNO (a) == REGNO (ops[0]))
3952               {
3953                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3954                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
3955               }
3956             else
3957               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3958           }
3959         else if (GET_CODE (b) != REG)
3960           abort ();
3961         else
3962           {
3963             if (REGNO (b) == REGNO (ops[0]))
3964               {
3965                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3966                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
3967               }
3968             else
3969               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3970           }
3971       }
3972     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3973       {
3974         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3975         output_asm_insn (\"sxtb\\t%0, %0\", ops);
3976       }
3977     else
3978       {
3979         ops[1] = mem;
3980         ops[2] = const0_rtx;
3981         
3982         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3983       }
3984     return \"\";
3985   }"
3986   [(set_attr "length" "2,2,4")
3987    (set_attr "type" "alu_shift,load_byte,load_byte")
3988    (set_attr "pool_range" "*,32,32")]
3989 )
3990
3991 (define_expand "extendsfdf2"
3992   [(set (match_operand:DF                  0 "s_register_operand" "")
3993         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
3994   "TARGET_ARM && TARGET_HARD_FLOAT"
3995   ""
3996 )
3997 \f
3998 ;; Move insns (including loads and stores)
3999
4000 ;; XXX Just some ideas about movti.
4001 ;; I don't think these are a good idea on the arm, there just aren't enough
4002 ;; registers
4003 ;;(define_expand "loadti"
4004 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
4005 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
4006 ;;  "" "")
4007
4008 ;;(define_expand "storeti"
4009 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4010 ;;      (match_operand:TI 1 "s_register_operand" ""))]
4011 ;;  "" "")
4012
4013 ;;(define_expand "movti"
4014 ;;  [(set (match_operand:TI 0 "general_operand" "")
4015 ;;      (match_operand:TI 1 "general_operand" ""))]
4016 ;;  ""
4017 ;;  "
4018 ;;{
4019 ;;  rtx insn;
4020 ;;
4021 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4022 ;;    operands[1] = copy_to_reg (operands[1]);
4023 ;;  if (GET_CODE (operands[0]) == MEM)
4024 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4025 ;;  else if (GET_CODE (operands[1]) == MEM)
4026 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4027 ;;  else
4028 ;;    FAIL;
4029 ;;
4030 ;;  emit_insn (insn);
4031 ;;  DONE;
4032 ;;}")
4033
4034 ;; Recognize garbage generated above.
4035
4036 ;;(define_insn ""
4037 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4038 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4039 ;;  ""
4040 ;;  "*
4041 ;;  {
4042 ;;    register mem = (which_alternative < 3);
4043 ;;    register const char *template;
4044 ;;
4045 ;;    operands[mem] = XEXP (operands[mem], 0);
4046 ;;    switch (which_alternative)
4047 ;;      {
4048 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4049 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
4050 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
4051 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
4052 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
4053 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
4054 ;;      }
4055 ;;    output_asm_insn (template, operands);
4056 ;;    return \"\";
4057 ;;  }")
4058
4059 (define_expand "movdi"
4060   [(set (match_operand:DI 0 "general_operand" "")
4061         (match_operand:DI 1 "general_operand" ""))]
4062   "TARGET_EITHER"
4063   "
4064   if (TARGET_THUMB)
4065     {
4066       if (!no_new_pseudos)
4067         {
4068           if (GET_CODE (operands[0]) != REG)
4069             operands[1] = force_reg (DImode, operands[1]);
4070         }
4071     }
4072   "
4073 )
4074
4075 (define_insn "*arm_movdi"
4076   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r ,m")
4077         (match_operand:DI 1 "di_operand"              "rIK,mi,r"))]
4078   "TARGET_ARM
4079   && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4080   && !TARGET_IWMMXT"
4081   "*
4082   return (output_move_double (operands));
4083   "
4084   [(set_attr "length" "8")
4085    (set_attr "type" "*,load2,store2")
4086    (set_attr "pool_range" "*,1020,*")
4087    (set_attr "neg_pool_range" "*,1008,*")]
4088 )
4089
4090 ;; We can't actually do base+index doubleword loads if the index and
4091 ;; destination overlap.  Split here so that we at least have chance to
4092 ;; schedule.
4093 (define_split
4094   [(set (match_operand:DI 0 "s_register_operand" "")
4095         (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4096                          (match_operand:SI 2 "s_register_operand" ""))))]
4097   "TARGET_LDRD
4098   && reg_overlap_mentioned_p (operands[0], operands[1])
4099   && reg_overlap_mentioned_p (operands[0], operands[2])"
4100   [(set (match_dup 4)
4101         (plus:SI (match_dup 1)
4102                  (match_dup 2)))
4103    (set (match_dup 0)
4104         (mem:DI (match_dup 4)))]
4105   "
4106   operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4107   "
4108 )
4109
4110 ;;; ??? This should have alternatives for constants.
4111 ;;; ??? This was originally identical to the movdf_insn pattern.
4112 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4113 ;;; thumb_reorg with a memory reference.
4114 (define_insn "*thumb_movdi_insn"
4115   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4116         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
4117   "TARGET_THUMB
4118    && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4119    && (   register_operand (operands[0], DImode)
4120        || register_operand (operands[1], DImode))"
4121   "*
4122   {
4123   switch (which_alternative)
4124     {
4125     default:
4126     case 0:
4127       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4128         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
4129       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
4130     case 1:
4131       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4132     case 2:
4133       operands[1] = GEN_INT (- INTVAL (operands[1]));
4134       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4135     case 3:
4136       return \"ldmia\\t%1, {%0, %H0}\";
4137     case 4:
4138       return \"stmia\\t%0, {%1, %H1}\";
4139     case 5:
4140       return thumb_load_double_from_address (operands);
4141     case 6:
4142       operands[2] = gen_rtx_MEM (SImode,
4143                              plus_constant (XEXP (operands[0], 0), 4));
4144       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4145       return \"\";
4146     case 7:
4147       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4148         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4149       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4150     }
4151   }"
4152   [(set_attr "length" "4,4,6,2,2,6,4,4")
4153    (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4154    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4155 )
4156
4157 (define_expand "movsi"
4158   [(set (match_operand:SI 0 "general_operand" "")
4159         (match_operand:SI 1 "general_operand" ""))]
4160   "TARGET_EITHER"
4161   "
4162   if (TARGET_ARM)
4163     {
4164       /* Everything except mem = const or mem = mem can be done easily.  */
4165       if (GET_CODE (operands[0]) == MEM)
4166         operands[1] = force_reg (SImode, operands[1]);
4167       if (arm_general_register_operand (operands[0], SImode)
4168           && GET_CODE (operands[1]) == CONST_INT
4169           && !(const_ok_for_arm (INTVAL (operands[1]))
4170                || const_ok_for_arm (~INTVAL (operands[1]))))
4171         {
4172            arm_split_constant (SET, SImode, NULL_RTX,
4173                                INTVAL (operands[1]), operands[0], NULL_RTX,
4174                               (no_new_pseudos ? 0
4175                                : preserve_subexpressions_p ()));
4176           DONE;
4177         }
4178     }
4179   else /* TARGET_THUMB....  */
4180     {
4181       if (!no_new_pseudos)
4182         {
4183           if (GET_CODE (operands[0]) != REG)
4184             operands[1] = force_reg (SImode, operands[1]);
4185         }
4186     }
4187     
4188   if (flag_pic
4189       && (CONSTANT_P (operands[1])
4190          || symbol_mentioned_p (operands[1])
4191          || label_mentioned_p (operands[1])))
4192     operands[1] = legitimize_pic_address (operands[1], SImode,
4193                                           (no_new_pseudos ? operands[0] : 0));
4194   "
4195 )
4196
4197 (define_insn "*arm_movsi_insn"
4198   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4199         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
4200   "TARGET_ARM && ! TARGET_IWMMXT
4201    && !(TARGET_HARD_FLOAT && TARGET_VFP)
4202    && (   register_operand (operands[0], SImode)
4203        || register_operand (operands[1], SImode))"
4204   "@
4205    mov%?\\t%0, %1
4206    mvn%?\\t%0, #%B1
4207    ldr%?\\t%0, %1
4208    str%?\\t%1, %0"
4209   [(set_attr "type" "*,*,load1,store1")
4210    (set_attr "predicable" "yes")
4211    (set_attr "pool_range" "*,*,4096,*")
4212    (set_attr "neg_pool_range" "*,*,4084,*")]
4213 )
4214
4215 (define_split
4216   [(set (match_operand:SI 0 "arm_general_register_operand" "")
4217         (match_operand:SI 1 "const_int_operand" ""))]
4218   "TARGET_ARM
4219   && (!(const_ok_for_arm (INTVAL (operands[1]))
4220         || const_ok_for_arm (~INTVAL (operands[1]))))"
4221   [(clobber (const_int 0))]
4222   "
4223   arm_split_constant (SET, SImode, NULL_RTX, 
4224                       INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4225   DONE;
4226   "
4227 )
4228
4229 (define_insn "*thumb_movsi_insn"
4230   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4231         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4232   "TARGET_THUMB
4233    && (   register_operand (operands[0], SImode) 
4234        || register_operand (operands[1], SImode))"
4235   "@
4236    mov  %0, %1
4237    mov  %0, %1
4238    #
4239    #
4240    ldmia\\t%1, {%0}
4241    stmia\\t%0, {%1}
4242    ldr\\t%0, %1
4243    str\\t%1, %0
4244    mov\\t%0, %1"
4245   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4246    (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4247    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4248 )
4249
4250 (define_split 
4251   [(set (match_operand:SI 0 "register_operand" "")
4252         (match_operand:SI 1 "const_int_operand" ""))]
4253   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4254   [(set (match_dup 0) (match_dup 1))
4255    (set (match_dup 0) (neg:SI (match_dup 0)))]
4256   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4257 )
4258
4259 (define_split 
4260   [(set (match_operand:SI 0 "register_operand" "")
4261         (match_operand:SI 1 "const_int_operand" ""))]
4262   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4263   [(set (match_dup 0) (match_dup 1))
4264    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4265   "
4266   {
4267     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4268     unsigned HOST_WIDE_INT mask = 0xff;
4269     int i;
4270     
4271     for (i = 0; i < 25; i++)
4272       if ((val & (mask << i)) == val)
4273         break;
4274
4275     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4276     if (i == 0)
4277       FAIL;
4278
4279     operands[1] = GEN_INT (val >> i);
4280     operands[2] = GEN_INT (i);
4281   }"
4282 )
4283
4284 ;; When generating pic, we need to load the symbol offset into a register.
4285 ;; So that the optimizer does not confuse this with a normal symbol load
4286 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
4287 ;; since that is the only type of relocation we can use.
4288
4289 ;; The rather odd constraints on the following are to force reload to leave
4290 ;; the insn alone, and to force the minipool generation pass to then move
4291 ;; the GOT symbol to memory.
4292
4293 (define_insn "pic_load_addr_arm"
4294   [(set (match_operand:SI 0 "s_register_operand" "=r")
4295         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4296   "TARGET_ARM && flag_pic"
4297   "ldr%?\\t%0, %1"
4298   [(set_attr "type" "load1")
4299    (set (attr "pool_range")     (const_int 4096))
4300    (set (attr "neg_pool_range") (const_int 4084))]
4301 )
4302
4303 (define_insn "pic_load_addr_thumb"
4304   [(set (match_operand:SI 0 "s_register_operand" "=l")
4305         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4306   "TARGET_THUMB && flag_pic"
4307   "ldr\\t%0, %1"
4308   [(set_attr "type" "load1")
4309    (set (attr "pool_range") (const_int 1024))]
4310 )
4311
4312 ;; This variant is used for AOF assembly, since it needs to mention the
4313 ;; pic register in the rtl.
4314 (define_expand "pic_load_addr_based"
4315   [(set (match_operand:SI 0 "s_register_operand" "")
4316         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4317   "TARGET_ARM && flag_pic"
4318   "operands[2] = pic_offset_table_rtx;"
4319 )
4320
4321 (define_insn "*pic_load_addr_based_insn"
4322   [(set (match_operand:SI 0 "s_register_operand" "=r")
4323         (unspec:SI [(match_operand 1 "" "")
4324                     (match_operand 2 "s_register_operand" "r")]
4325                    UNSPEC_PIC_SYM))]
4326   "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4327   "*
4328 #ifdef AOF_ASSEMBLER
4329   operands[1] = aof_pic_entry (operands[1]);
4330 #endif
4331   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4332   return \"\";
4333   "
4334   [(set_attr "type" "load1")
4335    (set (attr "pool_range")
4336         (if_then_else (eq_attr "is_thumb" "yes")
4337                       (const_int 1024)
4338                       (const_int 4096)))
4339    (set (attr "neg_pool_range")
4340         (if_then_else (eq_attr "is_thumb" "yes")
4341                       (const_int 0)
4342                       (const_int 4084)))]
4343 )
4344
4345 (define_insn "pic_add_dot_plus_four"
4346   [(set (match_operand:SI 0 "register_operand" "+r")
4347         (unspec:SI [(plus:SI (match_dup 0)
4348                              (const (plus:SI (pc) (const_int 4))))]
4349                    UNSPEC_PIC_BASE))
4350    (use (label_ref (match_operand 1 "" "")))]
4351   "TARGET_THUMB && flag_pic"
4352   "*
4353   (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4354                              CODE_LABEL_NUMBER (operands[1]));
4355   return \"add\\t%0, %|pc\";
4356   "
4357   [(set_attr "length" "2")]
4358 )
4359
4360 (define_insn "pic_add_dot_plus_eight"
4361   [(set (match_operand:SI 0 "register_operand" "+r")
4362         (unspec:SI [(plus:SI (match_dup 0)
4363                              (const (plus:SI (pc) (const_int 8))))]
4364                    UNSPEC_PIC_BASE))
4365    (use (label_ref (match_operand 1 "" "")))]
4366   "TARGET_ARM && flag_pic"
4367   "*
4368     (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4369                                CODE_LABEL_NUMBER (operands[1]));
4370     return \"add%?\\t%0, %|pc, %0\";
4371   "
4372   [(set_attr "predicable" "yes")]
4373 )
4374
4375 (define_expand "builtin_setjmp_receiver"
4376   [(label_ref (match_operand 0 "" ""))]
4377   "flag_pic"
4378   "
4379 {
4380   arm_finalize_pic (0);
4381   DONE;
4382 }")
4383
4384 ;; If copying one reg to another we can set the condition codes according to
4385 ;; its value.  Such a move is common after a return from subroutine and the
4386 ;; result is being tested against zero.
4387
4388 (define_insn "*movsi_compare0"
4389   [(set (reg:CC CC_REGNUM)
4390         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4391                     (const_int 0)))
4392    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4393         (match_dup 1))]
4394   "TARGET_ARM"
4395   "@
4396    cmp%?\\t%0, #0
4397    sub%?s\\t%0, %1, #0"
4398   [(set_attr "conds" "set")]
4399 )
4400
4401 ;; Subroutine to store a half word from a register into memory.
4402 ;; Operand 0 is the source register (HImode)
4403 ;; Operand 1 is the destination address in a register (SImode)
4404
4405 ;; In both this routine and the next, we must be careful not to spill
4406 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4407 ;; can generate unrecognizable rtl.
4408
4409 (define_expand "storehi"
4410   [;; store the low byte
4411    (set (match_operand 1 "" "") (match_dup 3))
4412    ;; extract the high byte
4413    (set (match_dup 2)
4414         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4415    ;; store the high byte
4416    (set (match_dup 4) (match_dup 5))]
4417   "TARGET_ARM"
4418   "
4419   {
4420     rtx op1 = operands[1];
4421     rtx addr = XEXP (op1, 0);
4422     enum rtx_code code = GET_CODE (addr);
4423
4424     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4425         || code == MINUS)
4426       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4427
4428     operands[4] = adjust_address (op1, QImode, 1);
4429     operands[1] = adjust_address (operands[1], QImode, 0);
4430     operands[3] = gen_lowpart (QImode, operands[0]);
4431     operands[0] = gen_lowpart (SImode, operands[0]);
4432     operands[2] = gen_reg_rtx (SImode);
4433     operands[5] = gen_lowpart (QImode, operands[2]);
4434   }"
4435 )
4436
4437 (define_expand "storehi_bigend"
4438   [(set (match_dup 4) (match_dup 3))
4439    (set (match_dup 2)
4440         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4441    (set (match_operand 1 "" "") (match_dup 5))]
4442   "TARGET_ARM"
4443   "
4444   {
4445     rtx op1 = operands[1];
4446     rtx addr = XEXP (op1, 0);
4447     enum rtx_code code = GET_CODE (addr);
4448
4449     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4450         || code == MINUS)
4451       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4452
4453     operands[4] = adjust_address (op1, QImode, 1);
4454     operands[1] = adjust_address (operands[1], QImode, 0);
4455     operands[3] = gen_lowpart (QImode, operands[0]);
4456     operands[0] = gen_lowpart (SImode, operands[0]);
4457     operands[2] = gen_reg_rtx (SImode);
4458     operands[5] = gen_lowpart (QImode, operands[2]);
4459   }"
4460 )
4461
4462 ;; Subroutine to store a half word integer constant into memory.
4463 (define_expand "storeinthi"
4464   [(set (match_operand 0 "" "")
4465         (match_operand 1 "" ""))
4466    (set (match_dup 3) (match_dup 2))]
4467   "TARGET_ARM"
4468   "
4469   {
4470     HOST_WIDE_INT value = INTVAL (operands[1]);
4471     rtx addr = XEXP (operands[0], 0);
4472     rtx op0 = operands[0];
4473     enum rtx_code code = GET_CODE (addr);
4474
4475     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4476         || code == MINUS)
4477       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4478
4479     operands[1] = gen_reg_rtx (SImode);
4480     if (BYTES_BIG_ENDIAN)
4481       {
4482         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4483         if ((value & 255) == ((value >> 8) & 255))
4484           operands[2] = operands[1];
4485         else
4486           {
4487             operands[2] = gen_reg_rtx (SImode);
4488             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4489           }
4490       }
4491     else
4492       {
4493         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4494         if ((value & 255) == ((value >> 8) & 255))
4495           operands[2] = operands[1];
4496         else
4497           {
4498             operands[2] = gen_reg_rtx (SImode);
4499             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4500           }
4501       }
4502
4503     operands[3] = adjust_address (op0, QImode, 1);
4504     operands[0] = adjust_address (operands[0], QImode, 0);
4505     operands[2] = gen_lowpart (QImode, operands[2]);
4506     operands[1] = gen_lowpart (QImode, operands[1]);
4507   }"
4508 )
4509
4510 (define_expand "storehi_single_op"
4511   [(set (match_operand:HI 0 "memory_operand" "")
4512         (match_operand:HI 1 "general_operand" ""))]
4513   "TARGET_ARM && arm_arch4"
4514   "
4515   if (!s_register_operand (operands[1], HImode))
4516     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4517   "
4518 )
4519
4520 (define_expand "movhi"
4521   [(set (match_operand:HI 0 "general_operand" "")
4522         (match_operand:HI 1 "general_operand" ""))]
4523   "TARGET_EITHER"
4524   "
4525   if (TARGET_ARM)
4526     {
4527       if (!no_new_pseudos)
4528         {
4529           if (GET_CODE (operands[0]) == MEM)
4530             {
4531               if (arm_arch4)
4532                 {
4533                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4534                   DONE;
4535                 }
4536               if (GET_CODE (operands[1]) == CONST_INT)
4537                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4538               else
4539                 {
4540                   if (GET_CODE (operands[1]) == MEM)
4541                     operands[1] = force_reg (HImode, operands[1]);
4542                   if (BYTES_BIG_ENDIAN)
4543                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4544                   else
4545                    emit_insn (gen_storehi (operands[1], operands[0]));
4546                 }
4547               DONE;
4548             }
4549           /* Sign extend a constant, and keep it in an SImode reg.  */
4550           else if (GET_CODE (operands[1]) == CONST_INT)
4551             {
4552               rtx reg = gen_reg_rtx (SImode);
4553               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4554
4555               /* If the constant is already valid, leave it alone.  */
4556               if (!const_ok_for_arm (val))
4557                 {
4558                   /* If setting all the top bits will make the constant 
4559                      loadable in a single instruction, then set them.  
4560                      Otherwise, sign extend the number.  */
4561
4562                   if (const_ok_for_arm (~(val | ~0xffff)))
4563                     val |= ~0xffff;
4564                   else if (val & 0x8000)
4565                     val |= ~0xffff;
4566                 }
4567
4568               emit_insn (gen_movsi (reg, GEN_INT (val)));
4569               operands[1] = gen_lowpart (HImode, reg);
4570             }
4571           else if (arm_arch4 && !no_new_pseudos && optimize > 0
4572                    && GET_CODE (operands[1]) == MEM)
4573             {
4574               rtx reg = gen_reg_rtx (SImode);
4575
4576               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4577               operands[1] = gen_lowpart (HImode, reg);
4578             }
4579           else if (!arm_arch4)
4580             {
4581              /* Note: We do not have to worry about TARGET_MMU_TRAPS
4582                 for v4 and up architectures because LDRH instructions will
4583                 be used to access the HI values, and these cannot generate
4584                 unaligned word access faults in the MMU.  */
4585               if (GET_CODE (operands[1]) == MEM)
4586                 {
4587                   if (TARGET_MMU_TRAPS)
4588                     {
4589                       rtx base;
4590                       rtx offset = const0_rtx;
4591                       rtx reg = gen_reg_rtx (SImode);
4592
4593                       if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4594                            || (GET_CODE (base) == PLUS
4595                                && (GET_CODE (offset = XEXP (base, 1))
4596                                    == CONST_INT)
4597                                && ((INTVAL(offset) & 1) != 1)
4598                                && GET_CODE (base = XEXP (base, 0)) == REG))
4599                           && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4600                         {
4601                           HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4602                           rtx new;
4603
4604                           new = gen_rtx_MEM (SImode,
4605                                              plus_constant (base, new_offset));
4606                           MEM_COPY_ATTRIBUTES (new, operands[1]);
4607                           emit_insn (gen_movsi (reg, new));
4608                           if (((INTVAL (offset) & 2) != 0)
4609                               ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4610                             {
4611                               rtx reg2 = gen_reg_rtx (SImode);
4612
4613                               emit_insn (gen_lshrsi3 (reg2, reg,
4614                                          GEN_INT (16)));
4615                               reg = reg2;
4616                             }
4617                         }
4618                       else
4619                         emit_insn (gen_movhi_bytes (reg, operands[1]));
4620
4621                       operands[1] = gen_lowpart (HImode, reg);
4622                     }
4623                   else if (BYTES_BIG_ENDIAN)
4624                     {
4625                       rtx base;
4626                       rtx offset = const0_rtx;
4627
4628                       if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4629                            || (GET_CODE (base) == PLUS
4630                               && (GET_CODE (offset = XEXP (base, 1))
4631                                   == CONST_INT)
4632                               && GET_CODE (base = XEXP (base, 0)) == REG))
4633                           && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4634                         {
4635                           rtx reg = gen_reg_rtx (SImode);
4636                           rtx new;
4637
4638                           if ((INTVAL (offset) & 2) == 2)
4639                             {
4640                               HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4641                               new = gen_rtx_MEM (SImode,
4642                                                  plus_constant (base,
4643                                                                 new_offset));
4644                               MEM_COPY_ATTRIBUTES (new, operands[1]);
4645                               emit_insn (gen_movsi (reg, new));
4646                             }
4647                           else
4648                             {
4649                               new = gen_rtx_MEM (SImode,
4650                                                  XEXP (operands[1], 0));
4651                               MEM_COPY_ATTRIBUTES (new, operands[1]);
4652                               emit_insn (gen_rotated_loadsi (reg, new));
4653                             }
4654
4655                           operands[1] = gen_lowpart (HImode, reg);
4656                         }
4657                       else
4658                         {
4659                           emit_insn (gen_movhi_bigend (operands[0],
4660                                                        operands[1]));
4661                           DONE;
4662                         }
4663                     }
4664                }
4665            }
4666         }
4667       /* Handle loading a large integer during reload.  */
4668       else if (GET_CODE (operands[1]) == CONST_INT
4669                && !const_ok_for_arm (INTVAL (operands[1]))
4670                && !const_ok_for_arm (~INTVAL (operands[1])))
4671         {
4672           /* Writing a constant to memory needs a scratch, which should
4673              be handled with SECONDARY_RELOADs.  */
4674           if (GET_CODE (operands[0]) != REG)
4675             abort ();
4676
4677           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4678           emit_insn (gen_movsi (operands[0], operands[1]));
4679           DONE;
4680        }
4681     }
4682   else /* TARGET_THUMB */
4683     {
4684       if (!no_new_pseudos)
4685         {
4686           if (GET_CODE (operands[0]) != REG)
4687             operands[1] = force_reg (HImode, operands[1]);
4688
4689           /* ??? We shouldn't really get invalid addresses here, but this can
4690              happen if we are passed a SP (never OK for HImode/QImode) or 
4691              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4692              HImode/QImode) relative address.  */
4693           /* ??? This should perhaps be fixed elsewhere, for instance, in
4694              fixup_stack_1, by checking for other kinds of invalid addresses,
4695              e.g. a bare reference to a virtual register.  This may confuse the
4696              alpha though, which must handle this case differently.  */
4697           if (GET_CODE (operands[0]) == MEM
4698               && !memory_address_p (GET_MODE (operands[0]),
4699                                     XEXP (operands[0], 0)))
4700             operands[0]
4701               = replace_equiv_address (operands[0],
4702                                        copy_to_reg (XEXP (operands[0], 0)));
4703    
4704           if (GET_CODE (operands[1]) == MEM
4705               && !memory_address_p (GET_MODE (operands[1]),
4706                                     XEXP (operands[1], 0)))
4707             operands[1]
4708               = replace_equiv_address (operands[1],
4709                                        copy_to_reg (XEXP (operands[1], 0)));
4710         }
4711       /* Handle loading a large integer during reload.  */
4712       else if (GET_CODE (operands[1]) == CONST_INT
4713                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4714         {
4715           /* Writing a constant to memory needs a scratch, which should
4716              be handled with SECONDARY_RELOADs.  */
4717           if (GET_CODE (operands[0]) != REG)
4718             abort ();
4719
4720           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4721           emit_insn (gen_movsi (operands[0], operands[1]));
4722           DONE;
4723         }
4724     }
4725   "
4726 )
4727
4728 (define_insn "*thumb_movhi_insn"
4729   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4730         (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
4731   "TARGET_THUMB
4732    && (   register_operand (operands[0], HImode)
4733        || register_operand (operands[1], HImode))"
4734   "*
4735   switch (which_alternative)
4736     {
4737     case 0: return \"add        %0, %1, #0\";
4738     case 2: return \"strh       %1, %0\";
4739     case 3: return \"mov        %0, %1\";
4740     case 4: return \"mov        %0, %1\";
4741     case 5: return \"mov        %0, %1\";
4742     default: abort ();
4743     case 1:
4744       /* The stack pointer can end up being taken as an index register.
4745           Catch this case here and deal with it.  */
4746       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4747           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4748           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4749         {
4750           rtx ops[2];
4751           ops[0] = operands[0];
4752           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4753       
4754           output_asm_insn (\"mov        %0, %1\", ops);
4755
4756           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4757     
4758         }
4759       return \"ldrh     %0, %1\";
4760     }"
4761   [(set_attr "length" "2,4,2,2,2,2")
4762    (set_attr "type" "*,load1,store1,*,*,*")]
4763 )
4764
4765
4766 (define_insn "rotated_loadsi"
4767   [(set (match_operand:SI            0 "s_register_operand"        "=r")
4768         (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4769                    (const_int 16)))]
4770   "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4771   "*
4772   {
4773     rtx ops[2];
4774
4775     ops[0] = operands[0];
4776     ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4777     output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4778     return \"\";
4779   }"
4780   [(set_attr "type" "load1")
4781    (set_attr "predicable" "yes")]
4782 )
4783
4784 (define_expand "movhi_bytes"
4785   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4786    (set (match_dup 3)
4787         (zero_extend:SI (match_dup 6)))
4788    (set (match_operand:SI 0 "" "")
4789          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4790   "TARGET_ARM"
4791   "
4792   {
4793     rtx mem1, mem2;
4794     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4795
4796     mem1 = gen_rtx_MEM (QImode, addr);
4797     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4798     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4799     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4800     operands[0] = gen_lowpart (SImode, operands[0]);
4801     operands[1] = mem1;
4802     operands[2] = gen_reg_rtx (SImode);
4803     operands[3] = gen_reg_rtx (SImode);
4804     operands[6] = mem2;
4805
4806     if (BYTES_BIG_ENDIAN)
4807       {
4808         operands[4] = operands[2];
4809         operands[5] = operands[3];
4810       }
4811     else
4812       {
4813         operands[4] = operands[3];
4814         operands[5] = operands[2];
4815       }
4816   }"
4817 )
4818
4819 (define_expand "movhi_bigend"
4820   [(set (match_dup 2)
4821         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4822                    (const_int 16)))
4823    (set (match_dup 3)
4824         (ashiftrt:SI (match_dup 2) (const_int 16)))
4825    (set (match_operand:HI 0 "s_register_operand" "")
4826         (match_dup 4))]
4827   "TARGET_ARM"
4828   "
4829   operands[2] = gen_reg_rtx (SImode);
4830   operands[3] = gen_reg_rtx (SImode);
4831   operands[4] = gen_lowpart (HImode, operands[3]);
4832   "
4833 )
4834
4835 ;; Pattern to recognize insn generated default case above
4836 (define_insn "*movhi_insn_arch4"
4837   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4838         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4839   "TARGET_ARM
4840    && arm_arch4
4841    && (GET_CODE (operands[1]) != CONST_INT
4842        || const_ok_for_arm (INTVAL (operands[1]))
4843        || const_ok_for_arm (~INTVAL (operands[1])))"
4844   "@
4845    mov%?\\t%0, %1\\t%@ movhi
4846    mvn%?\\t%0, #%B1\\t%@ movhi
4847    str%?h\\t%1, %0\\t%@ movhi 
4848    ldr%?h\\t%0, %1\\t%@ movhi"
4849   [(set_attr "type" "*,*,store1,load1")
4850    (set_attr "predicable" "yes")
4851    (set_attr "pool_range" "*,*,*,256")
4852    (set_attr "neg_pool_range" "*,*,*,244")]
4853 )
4854
4855 (define_insn "*movhi_insn_littleend"
4856   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4857         (match_operand:HI 1 "general_operand"  "rI,K,m"))]
4858   "TARGET_ARM
4859    && !arm_arch4
4860    && !BYTES_BIG_ENDIAN
4861    && !TARGET_MMU_TRAPS
4862    && (GET_CODE (operands[1]) != CONST_INT
4863        || const_ok_for_arm (INTVAL (operands[1]))
4864        || const_ok_for_arm (~INTVAL (operands[1])))"
4865   "@
4866    mov%?\\t%0, %1\\t%@ movhi
4867    mvn%?\\t%0, #%B1\\t%@ movhi
4868    ldr%?\\t%0, %1\\t%@ movhi"
4869   [(set_attr "type" "*,*,load1")
4870    (set_attr "predicable" "yes")
4871    (set_attr "pool_range" "4096")
4872    (set_attr "neg_pool_range" "4084")]
4873 )
4874
4875 (define_insn "*movhi_insn_bigend"
4876   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4877         (match_operand:HI 1 "general_operand"    "rI,K,m"))]
4878   "TARGET_ARM
4879    && !arm_arch4
4880    && BYTES_BIG_ENDIAN
4881    && !TARGET_MMU_TRAPS
4882    && (GET_CODE (operands[1]) != CONST_INT
4883        || const_ok_for_arm (INTVAL (operands[1]))
4884        || const_ok_for_arm (~INTVAL (operands[1])))"
4885   "@
4886    mov%?\\t%0, %1\\t%@ movhi
4887    mvn%?\\t%0, #%B1\\t%@ movhi
4888    ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4889   [(set_attr "type" "*,*,load1")
4890    (set_attr "predicable" "yes")
4891    (set_attr "length" "4,4,8")
4892    (set_attr "pool_range" "*,*,4092")
4893    (set_attr "neg_pool_range" "*,*,4084")]
4894 )
4895
4896 (define_insn "*loadhi_si_bigend"
4897   [(set (match_operand:SI                       0 "s_register_operand" "=r")
4898         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand"      "m") 0)
4899                    (const_int 16)))]
4900   "TARGET_ARM
4901    && BYTES_BIG_ENDIAN
4902    && !TARGET_MMU_TRAPS"
4903   "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4904   [(set_attr "type" "load1")
4905    (set_attr "predicable" "yes")
4906    (set_attr "pool_range" "4096")
4907    (set_attr "neg_pool_range" "4084")]
4908 )
4909
4910 (define_insn "*movhi_bytes"
4911   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4912         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4913   "TARGET_ARM && TARGET_MMU_TRAPS"
4914   "@
4915    mov%?\\t%0, %1\\t%@ movhi
4916    mvn%?\\t%0, #%B1\\t%@ movhi"
4917   [(set_attr "predicable" "yes")]
4918 )
4919
4920 (define_insn "thumb_movhi_clobber"
4921   [(set (match_operand:HI     0 "memory_operand"   "=m")
4922         (match_operand:HI     1 "register_operand" "l"))
4923    (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4924   "TARGET_THUMB"
4925   "*
4926   abort ();"
4927 )
4928         
4929 ;; We use a DImode scratch because we may occasionally need an additional
4930 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4931 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4932 (define_expand "reload_outhi"
4933   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4934               (match_operand:HI 1 "s_register_operand"        "r")
4935               (match_operand:DI 2 "s_register_operand"        "=&l")])]
4936   "TARGET_EITHER"
4937   "if (TARGET_ARM)
4938      arm_reload_out_hi (operands);
4939    else
4940      thumb_reload_out_hi (operands);
4941   DONE;
4942   "
4943 )
4944
4945 (define_expand "reload_inhi"
4946   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4947               (match_operand:HI 1 "arm_reload_memory_operand" "o")
4948               (match_operand:DI 2 "s_register_operand" "=&r")])]
4949   "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4950   "
4951   if (TARGET_ARM)
4952     arm_reload_in_hi (operands);
4953   else
4954     thumb_reload_out_hi (operands);
4955   DONE;
4956 ")
4957
4958 (define_expand "movqi"
4959   [(set (match_operand:QI 0 "general_operand" "")
4960         (match_operand:QI 1 "general_operand" ""))]
4961   "TARGET_EITHER"
4962   "
4963   if (TARGET_ARM)
4964     {
4965       /* Everything except mem = const or mem = mem can be done easily */
4966
4967       if (!no_new_pseudos)
4968         {
4969           if (GET_CODE (operands[1]) == CONST_INT)
4970             {
4971               rtx reg = gen_reg_rtx (SImode);
4972
4973               emit_insn (gen_movsi (reg, operands[1]));
4974               operands[1] = gen_lowpart (QImode, reg);
4975             }
4976           if (GET_CODE (operands[1]) == MEM && optimize > 0)
4977             {
4978               rtx reg = gen_reg_rtx (SImode);
4979
4980               emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4981               operands[1] = gen_lowpart (QImode, reg);
4982             }
4983           if (GET_CODE (operands[0]) == MEM)
4984             operands[1] = force_reg (QImode, operands[1]);
4985         }
4986     }
4987   else /* TARGET_THUMB */
4988     {
4989       if (!no_new_pseudos)
4990         {
4991           if (GET_CODE (operands[0]) != REG)
4992             operands[1] = force_reg (QImode, operands[1]);
4993
4994           /* ??? We shouldn't really get invalid addresses here, but this can
4995              happen if we are passed a SP (never OK for HImode/QImode) or
4996              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4997              HImode/QImode) relative address.  */
4998           /* ??? This should perhaps be fixed elsewhere, for instance, in
4999              fixup_stack_1, by checking for other kinds of invalid addresses,
5000              e.g. a bare reference to a virtual register.  This may confuse the
5001              alpha though, which must handle this case differently.  */
5002           if (GET_CODE (operands[0]) == MEM
5003               && !memory_address_p (GET_MODE (operands[0]),
5004                                      XEXP (operands[0], 0)))
5005             operands[0]
5006               = replace_equiv_address (operands[0],
5007                                        copy_to_reg (XEXP (operands[0], 0)));
5008           if (GET_CODE (operands[1]) == MEM
5009               && !memory_address_p (GET_MODE (operands[1]),
5010                                     XEXP (operands[1], 0)))
5011              operands[1]
5012                = replace_equiv_address (operands[1],
5013                                         copy_to_reg (XEXP (operands[1], 0)));
5014         }
5015       /* Handle loading a large integer during reload.  */
5016       else if (GET_CODE (operands[1]) == CONST_INT
5017                && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
5018         {
5019           /* Writing a constant to memory needs a scratch, which should
5020              be handled with SECONDARY_RELOADs.  */
5021           if (GET_CODE (operands[0]) != REG)
5022             abort ();
5023
5024           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5025           emit_insn (gen_movsi (operands[0], operands[1]));
5026           DONE;
5027        }
5028     }
5029   "
5030 )
5031
5032
5033 (define_insn "*arm_movqi_insn"
5034   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5035         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5036   "TARGET_ARM
5037    && (   register_operand (operands[0], QImode)
5038        || register_operand (operands[1], QImode))"
5039   "@
5040    mov%?\\t%0, %1
5041    mvn%?\\t%0, #%B1
5042    ldr%?b\\t%0, %1
5043    str%?b\\t%1, %0"
5044   [(set_attr "type" "*,*,load1,store1")
5045    (set_attr "predicable" "yes")]
5046 )
5047
5048 (define_insn "*thumb_movqi_insn"
5049   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5050         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
5051   "TARGET_THUMB
5052    && (   register_operand (operands[0], QImode)
5053        || register_operand (operands[1], QImode))"
5054   "@
5055    add\\t%0, %1, #0
5056    ldrb\\t%0, %1
5057    strb\\t%1, %0
5058    mov\\t%0, %1
5059    mov\\t%0, %1
5060    mov\\t%0, %1"
5061   [(set_attr "length" "2")
5062    (set_attr "type" "*,load1,store1,*,*,*")
5063    (set_attr "pool_range" "*,32,*,*,*,*")]
5064 )
5065
5066 (define_expand "movsf"
5067   [(set (match_operand:SF 0 "general_operand" "")
5068         (match_operand:SF 1 "general_operand" ""))]
5069   "TARGET_EITHER"
5070   "
5071   if (TARGET_ARM)
5072     {
5073       if (GET_CODE (operands[0]) == MEM)
5074         operands[1] = force_reg (SFmode, operands[1]);
5075     }
5076   else /* TARGET_THUMB */
5077     {
5078       if (!no_new_pseudos)
5079         {
5080            if (GET_CODE (operands[0]) != REG)
5081              operands[1] = force_reg (SFmode, operands[1]);
5082         }
5083     }
5084   "
5085 )
5086
5087 (define_split
5088   [(set (match_operand:SF 0 "nonimmediate_operand" "")
5089         (match_operand:SF 1 "immediate_operand" ""))]
5090   "TARGET_ARM
5091    && !(TARGET_HARD_FLOAT && TARGET_FPA)
5092    && reload_completed
5093    && GET_CODE (operands[1]) == CONST_DOUBLE"
5094   [(set (match_dup 2) (match_dup 3))]
5095   "
5096   operands[2] = gen_lowpart (SImode, operands[0]);
5097   operands[3] = gen_lowpart (SImode, operands[1]);
5098   if (operands[2] == 0 || operands[3] == 0)
5099     FAIL;
5100   "
5101 )
5102
5103 (define_insn "*arm_movsf_soft_insn"
5104   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5105         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
5106   "TARGET_ARM
5107    && TARGET_SOFT_FLOAT
5108    && (GET_CODE (operands[0]) != MEM
5109        || register_operand (operands[1], SFmode))"
5110   "@
5111    mov%?\\t%0, %1
5112    ldr%?\\t%0, %1\\t%@ float
5113    str%?\\t%1, %0\\t%@ float"
5114   [(set_attr "length" "4,4,4")
5115    (set_attr "predicable" "yes")
5116    (set_attr "type" "*,load1,store1")
5117    (set_attr "pool_range" "*,4096,*")
5118    (set_attr "neg_pool_range" "*,4084,*")]
5119 )
5120
5121 ;;; ??? This should have alternatives for constants.
5122 (define_insn "*thumb_movsf_insn"
5123   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5124         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5125   "TARGET_THUMB
5126    && (   register_operand (operands[0], SFmode) 
5127        || register_operand (operands[1], SFmode))"
5128   "@
5129    add\\t%0, %1, #0
5130    ldmia\\t%1, {%0}
5131    stmia\\t%0, {%1}
5132    ldr\\t%0, %1
5133    str\\t%1, %0
5134    mov\\t%0, %1
5135    mov\\t%0, %1"
5136   [(set_attr "length" "2")
5137    (set_attr "type" "*,load1,store1,load1,store1,*,*")
5138    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5139 )
5140
5141 (define_expand "movdf"
5142   [(set (match_operand:DF 0 "general_operand" "")
5143         (match_operand:DF 1 "general_operand" ""))]
5144   "TARGET_EITHER"
5145   "
5146   if (TARGET_ARM)
5147     {
5148       if (GET_CODE (operands[0]) == MEM)
5149         operands[1] = force_reg (DFmode, operands[1]);
5150     }
5151   else /* TARGET_THUMB */
5152     {
5153       if (!no_new_pseudos)
5154         {
5155           if (GET_CODE (operands[0]) != REG)
5156             operands[1] = force_reg (DFmode, operands[1]);
5157         }
5158     }
5159   "
5160 )
5161
5162 ;; Reloading a df mode value stored in integer regs to memory can require a
5163 ;; scratch reg.
5164 (define_expand "reload_outdf"
5165   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5166    (match_operand:DF 1 "s_register_operand" "r")
5167    (match_operand:SI 2 "s_register_operand" "=&r")]
5168   "TARGET_ARM"
5169   "
5170   {
5171     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5172
5173     if (code == REG)
5174       operands[2] = XEXP (operands[0], 0);
5175     else if (code == POST_INC || code == PRE_DEC)
5176       {
5177         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5178         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5179         emit_insn (gen_movdi (operands[0], operands[1]));
5180         DONE;
5181       }
5182     else if (code == PRE_INC)
5183       {
5184         rtx reg = XEXP (XEXP (operands[0], 0), 0);
5185
5186         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5187         operands[2] = reg;
5188       }
5189     else if (code == POST_DEC)
5190       operands[2] = XEXP (XEXP (operands[0], 0), 0);
5191     else
5192       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5193                              XEXP (XEXP (operands[0], 0), 1)));
5194
5195     emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5196                             operands[1]));
5197
5198     if (code == POST_DEC)
5199       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5200
5201     DONE;
5202   }"
5203 )
5204
5205 (define_insn "*movdf_soft_insn"
5206   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
5207         (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
5208   "TARGET_ARM && TARGET_SOFT_FLOAT
5209   "
5210   "* return output_move_double (operands);"
5211   [(set_attr "length" "8,8,8")
5212    (set_attr "type" "*,load2,store2")
5213    (set_attr "pool_range" "1020")
5214    (set_attr "neg_pool_range" "1008")]
5215 )
5216
5217 ;;; ??? This should have alternatives for constants.
5218 ;;; ??? This was originally identical to the movdi_insn pattern.
5219 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5220 ;;; thumb_reorg with a memory reference.
5221 (define_insn "*thumb_movdf_insn"
5222   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5223         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5224   "TARGET_THUMB
5225    && (   register_operand (operands[0], DFmode)
5226        || register_operand (operands[1], DFmode))"
5227   "*
5228   switch (which_alternative)
5229     {
5230     default:
5231     case 0:
5232       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5233         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5234       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5235     case 1:
5236       return \"ldmia\\t%1, {%0, %H0}\";
5237     case 2:
5238       return \"stmia\\t%0, {%1, %H1}\";
5239     case 3:
5240       return thumb_load_double_from_address (operands);
5241     case 4:
5242       operands[2] = gen_rtx_MEM (SImode,
5243                                  plus_constant (XEXP (operands[0], 0), 4));
5244       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5245       return \"\";
5246     case 5:
5247       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5248         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5249       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5250     }
5251   "
5252   [(set_attr "length" "4,2,2,6,4,4")
5253    (set_attr "type" "*,load2,store2,load2,store2,*")
5254    (set_attr "pool_range" "*,*,*,1020,*,*")]
5255 )
5256
5257 ;; Vector Moves
5258 (define_expand "movv2si"
5259   [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5260         (match_operand:V2SI 1 "general_operand" ""))]
5261   "TARGET_REALLY_IWMMXT"
5262 {
5263 })
5264
5265 (define_expand "movv4hi"
5266   [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5267         (match_operand:V4HI 1 "general_operand" ""))]
5268   "TARGET_REALLY_IWMMXT"
5269 {
5270 })
5271
5272 (define_expand "movv8qi"
5273   [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5274         (match_operand:V8QI 1 "general_operand" ""))]
5275   "TARGET_REALLY_IWMMXT"
5276 {
5277 })
5278 \f
5279
5280 ;; load- and store-multiple insns
5281 ;; The arm can load/store any set of registers, provided that they are in
5282 ;; ascending order; but that is beyond GCC so stick with what it knows.
5283
5284 (define_expand "load_multiple"
5285   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5286                           (match_operand:SI 1 "" ""))
5287                      (use (match_operand:SI 2 "" ""))])]
5288   "TARGET_ARM"
5289   "
5290   /* Support only fixed point registers.  */
5291   if (GET_CODE (operands[2]) != CONST_INT
5292       || INTVAL (operands[2]) > 14
5293       || INTVAL (operands[2]) < 2
5294       || GET_CODE (operands[1]) != MEM
5295       || GET_CODE (operands[0]) != REG
5296       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5297       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5298     FAIL;
5299
5300   operands[3]
5301     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5302                              force_reg (SImode, XEXP (operands[1], 0)),
5303                              TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5304                              MEM_IN_STRUCT_P(operands[1]),
5305                              MEM_SCALAR_P (operands[1]));
5306   "
5307 )
5308
5309 ;; Load multiple with write-back
5310
5311 (define_insn "*ldmsi_postinc4"
5312   [(match_parallel 0 "load_multiple_operation"
5313     [(set (match_operand:SI 1 "s_register_operand" "=r")
5314           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5315                    (const_int 16)))
5316      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5317           (mem:SI (match_dup 2)))
5318      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5319           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5320      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5321           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5322      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5323           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5324   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5325   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5326   [(set_attr "type" "load4")
5327    (set_attr "predicable" "yes")]
5328 )
5329
5330 (define_insn "*ldmsi_postinc3"
5331   [(match_parallel 0 "load_multiple_operation"
5332     [(set (match_operand:SI 1 "s_register_operand" "=r")
5333           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5334                    (const_int 12)))
5335      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5336           (mem:SI (match_dup 2)))
5337      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5338           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5339      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5340           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5341   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5342   "ldm%?ia\\t%1!, {%3, %4, %5}"
5343   [(set_attr "type" "load3")
5344    (set_attr "predicable" "yes")]
5345 )
5346
5347 (define_insn "*ldmsi_postinc2"
5348   [(match_parallel 0 "load_multiple_operation"
5349     [(set (match_operand:SI 1 "s_register_operand" "=r")
5350           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5351                    (const_int 8)))
5352      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5353           (mem:SI (match_dup 2)))
5354      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5355           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5356   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5357   "ldm%?ia\\t%1!, {%3, %4}"
5358   [(set_attr "type" "load2")
5359    (set_attr "predicable" "yes")]
5360 )
5361
5362 ;; Ordinary load multiple
5363
5364 (define_insn "*ldmsi4"
5365   [(match_parallel 0 "load_multiple_operation"
5366     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5367           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5368      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5369           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5370      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5371           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5372      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5373           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5374   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5375   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5376   [(set_attr "type" "load4")
5377    (set_attr "predicable" "yes")]
5378 )
5379
5380 (define_insn "*ldmsi3"
5381   [(match_parallel 0 "load_multiple_operation"
5382     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5383           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5384      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5385           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5386      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5387           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5388   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5389   "ldm%?ia\\t%1, {%2, %3, %4}"
5390   [(set_attr "type" "load3")
5391    (set_attr "predicable" "yes")]
5392 )
5393
5394 (define_insn "*ldmsi2"
5395   [(match_parallel 0 "load_multiple_operation"
5396     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5397           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5398      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5399           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5400   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5401   "ldm%?ia\\t%1, {%2, %3}"
5402   [(set_attr "type" "load2")
5403    (set_attr "predicable" "yes")]
5404 )
5405
5406 (define_expand "store_multiple"
5407   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5408                           (match_operand:SI 1 "" ""))
5409                      (use (match_operand:SI 2 "" ""))])]
5410   "TARGET_ARM"
5411   "
5412   /* Support only fixed point registers.  */
5413   if (GET_CODE (operands[2]) != CONST_INT
5414       || INTVAL (operands[2]) > 14
5415       || INTVAL (operands[2]) < 2
5416       || GET_CODE (operands[1]) != REG
5417       || GET_CODE (operands[0]) != MEM
5418       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5419       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5420     FAIL;
5421
5422   operands[3]
5423     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5424                               force_reg (SImode, XEXP (operands[0], 0)),
5425                               TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5426                               MEM_IN_STRUCT_P(operands[0]), 
5427                               MEM_SCALAR_P (operands[0]));
5428   "
5429 )
5430
5431 ;; Store multiple with write-back
5432
5433 (define_insn "*stmsi_postinc4"
5434   [(match_parallel 0 "store_multiple_operation"
5435     [(set (match_operand:SI 1 "s_register_operand" "=r")
5436           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5437                    (const_int 16)))
5438      (set (mem:SI (match_dup 2))
5439           (match_operand:SI 3 "arm_hard_register_operand" ""))
5440      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5441           (match_operand:SI 4 "arm_hard_register_operand" ""))
5442      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5443           (match_operand:SI 5 "arm_hard_register_operand" ""))
5444      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5445           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5446   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5447   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5448   [(set_attr "predicable" "yes")
5449    (set_attr "type" "store4")]
5450 )
5451
5452 (define_insn "*stmsi_postinc3"
5453   [(match_parallel 0 "store_multiple_operation"
5454     [(set (match_operand:SI 1 "s_register_operand" "=r")
5455           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5456                    (const_int 12)))
5457      (set (mem:SI (match_dup 2))
5458           (match_operand:SI 3 "arm_hard_register_operand" ""))
5459      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5460           (match_operand:SI 4 "arm_hard_register_operand" ""))
5461      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5462           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5463   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5464   "stm%?ia\\t%1!, {%3, %4, %5}"
5465   [(set_attr "predicable" "yes")
5466    (set_attr "type" "store3")]
5467 )
5468
5469 (define_insn "*stmsi_postinc2"
5470   [(match_parallel 0 "store_multiple_operation"
5471     [(set (match_operand:SI 1 "s_register_operand" "=r")
5472           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5473                    (const_int 8)))
5474      (set (mem:SI (match_dup 2))
5475           (match_operand:SI 3 "arm_hard_register_operand" ""))
5476      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5477           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5478   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5479   "stm%?ia\\t%1!, {%3, %4}"
5480   [(set_attr "predicable" "yes")
5481    (set_attr "type" "store2")]
5482 )
5483
5484 ;; Ordinary store multiple
5485
5486 (define_insn "*stmsi4"
5487   [(match_parallel 0 "store_multiple_operation"
5488     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5489           (match_operand:SI 2 "arm_hard_register_operand" ""))
5490      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5491           (match_operand:SI 3 "arm_hard_register_operand" ""))
5492      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5493           (match_operand:SI 4 "arm_hard_register_operand" ""))
5494      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5495           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5496   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5497   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5498   [(set_attr "predicable" "yes")
5499    (set_attr "type" "store4")]
5500 )
5501
5502 (define_insn "*stmsi3"
5503   [(match_parallel 0 "store_multiple_operation"
5504     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5505           (match_operand:SI 2 "arm_hard_register_operand" ""))
5506      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5507           (match_operand:SI 3 "arm_hard_register_operand" ""))
5508      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5509           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5510   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5511   "stm%?ia\\t%1, {%2, %3, %4}"
5512   [(set_attr "predicable" "yes")
5513    (set_attr "type" "store3")]
5514 )
5515
5516 (define_insn "*stmsi2"
5517   [(match_parallel 0 "store_multiple_operation"
5518     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5519           (match_operand:SI 2 "arm_hard_register_operand" ""))
5520      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5521           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5522   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5523   "stm%?ia\\t%1, {%2, %3}"
5524   [(set_attr "predicable" "yes")
5525    (set_attr "type" "store2")]
5526 )
5527
5528 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5529 ;; We could let this apply for blocks of less than this, but it clobbers so
5530 ;; many registers that there is then probably a better way.
5531
5532 (define_expand "movstrqi"
5533   [(match_operand:BLK 0 "general_operand" "")
5534    (match_operand:BLK 1 "general_operand" "")
5535    (match_operand:SI 2 "const_int_operand" "")
5536    (match_operand:SI 3 "const_int_operand" "")]
5537   "TARGET_EITHER"
5538   "
5539   if (TARGET_ARM)
5540     {
5541       if (arm_gen_movstrqi (operands))
5542         DONE;
5543       FAIL;
5544     }
5545   else /* TARGET_THUMB */
5546     {
5547       if (   INTVAL (operands[3]) != 4
5548           || INTVAL (operands[2]) > 48)
5549         FAIL;
5550
5551       thumb_expand_movstrqi (operands);
5552       DONE;
5553     }
5554   "
5555 )
5556
5557 ;; Thumb block-move insns
5558
5559 (define_insn "movmem12b"
5560   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5561         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5562    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5563         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5564    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5565         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5566    (set (match_operand:SI 0 "register_operand" "=l")
5567         (plus:SI (match_dup 2) (const_int 12)))
5568    (set (match_operand:SI 1 "register_operand" "=l")
5569         (plus:SI (match_dup 3) (const_int 12)))
5570    (clobber (match_scratch:SI 4 "=&l"))
5571    (clobber (match_scratch:SI 5 "=&l"))
5572    (clobber (match_scratch:SI 6 "=&l"))]
5573   "TARGET_THUMB"
5574   "* return thumb_output_move_mem_multiple (3, operands);"
5575   [(set_attr "length" "4")
5576    ; This isn't entirely accurate...  It loads as well, but in terms of
5577    ; scheduling the following insn it is better to consider it as a store
5578    (set_attr "type" "store3")]
5579 )
5580
5581 (define_insn "movmem8b"
5582   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5583         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5584    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5585         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5586    (set (match_operand:SI 0 "register_operand" "=l")
5587         (plus:SI (match_dup 2) (const_int 8)))
5588    (set (match_operand:SI 1 "register_operand" "=l")
5589         (plus:SI (match_dup 3) (const_int 8)))
5590    (clobber (match_scratch:SI 4 "=&l"))
5591    (clobber (match_scratch:SI 5 "=&l"))]
5592   "TARGET_THUMB"
5593   "* return thumb_output_move_mem_multiple (2, operands);"
5594   [(set_attr "length" "4")
5595    ; This isn't entirely accurate...  It loads as well, but in terms of
5596    ; scheduling the following insn it is better to consider it as a store
5597    (set_attr "type" "store2")]
5598 )
5599
5600 \f
5601
5602 ;; Compare & branch insns
5603 ;; The range calculations are based as follows:
5604 ;; For forward branches, the address calculation returns the address of
5605 ;; the next instruction.  This is 2 beyond the branch instruction.
5606 ;; For backward branches, the address calculation returns the address of
5607 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5608 ;; instruction for the shortest sequence, and 4 before the branch instruction
5609 ;; if we have to jump around an unconditional branch.
5610 ;; To the basic branch range the PC offset must be added (this is +4).
5611 ;; So for forward branches we have 
5612 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5613 ;; And for backward branches we have 
5614 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5615 ;;
5616 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5617 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5618
5619 (define_expand "cbranchsi4"
5620   [(set (pc) (if_then_else
5621               (match_operator 0 "arm_comparison_operator"
5622                [(match_operand:SI 1 "s_register_operand" "")
5623                 (match_operand:SI 2 "nonmemory_operand" "")])
5624               (label_ref (match_operand 3 "" ""))
5625               (pc)))]
5626   "TARGET_THUMB"
5627   "
5628   if (thumb_cmpneg_operand (operands[2], SImode))
5629     {
5630       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5631                                               operands[3], operands[0]));
5632       DONE;
5633     }
5634   if (!thumb_cmp_operand (operands[2], SImode))
5635     operands[2] = force_reg (SImode, operands[2]);
5636   ")
5637
5638 (define_insn "*cbranchsi4_insn"
5639   [(set (pc) (if_then_else
5640               (match_operator 0 "arm_comparison_operator"
5641                [(match_operand:SI 1 "s_register_operand" "l,*h")
5642                 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5643               (label_ref (match_operand 3 "" ""))
5644               (pc)))]
5645   "TARGET_THUMB"
5646   "*
5647   output_asm_insn (\"cmp\\t%1, %2\", operands);
5648
5649   switch (get_attr_length (insn))
5650     {
5651     case 4:  return \"b%d0\\t%l3\";
5652     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5653     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5654     }
5655   "
5656   [(set (attr "far_jump")
5657         (if_then_else
5658             (eq_attr "length" "8")
5659             (const_string "yes")
5660             (const_string "no")))
5661    (set (attr "length") 
5662         (if_then_else
5663             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5664                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5665             (const_int 4)
5666             (if_then_else
5667                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5668                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5669                 (const_int 6)
5670                 (const_int 8))))]
5671 )
5672
5673 (define_insn "cbranchsi4_scratch"
5674   [(set (pc) (if_then_else
5675               (match_operator 4 "arm_comparison_operator"
5676                [(match_operand:SI 1 "s_register_operand" "l,0")
5677                 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5678               (label_ref (match_operand 3 "" ""))
5679               (pc)))
5680    (clobber (match_scratch:SI 0 "=l,l"))]
5681   "TARGET_THUMB"
5682   "*
5683   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5684
5685   switch (get_attr_length (insn))
5686     {
5687     case 4:  return \"b%d4\\t%l3\";
5688     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5689     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5690     }
5691   "
5692   [(set (attr "far_jump")
5693         (if_then_else
5694             (eq_attr "length" "8")
5695             (const_string "yes")
5696             (const_string "no")))
5697    (set (attr "length") 
5698         (if_then_else
5699             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5700                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5701             (const_int 4)
5702             (if_then_else
5703                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5704                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5705                 (const_int 6)
5706                 (const_int 8))))]
5707 )
5708 (define_insn "*movsi_cbranchsi4"
5709   [(set (pc)
5710         (if_then_else
5711          (match_operator 3 "arm_comparison_operator"
5712           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5713            (const_int 0)])
5714          (label_ref (match_operand 2 "" ""))
5715          (pc)))
5716    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5717         (match_dup 1))]
5718   "TARGET_THUMB"
5719   "*{
5720   if (which_alternative == 0)
5721     output_asm_insn (\"cmp\t%0, #0\", operands);
5722   else if (which_alternative == 1)
5723     output_asm_insn (\"sub\t%0, %1, #0\", operands);
5724   else
5725     {
5726       output_asm_insn (\"cmp\t%1, #0\", operands);
5727       if (which_alternative == 2)
5728         output_asm_insn (\"mov\t%0, %1\", operands);
5729       else
5730         output_asm_insn (\"str\t%1, %0\", operands);
5731     }
5732   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5733     {
5734     case 4:  return \"b%d3\\t%l2\";
5735     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5736     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5737     }
5738   }"
5739   [(set (attr "far_jump")
5740         (if_then_else
5741             (ior (and (gt (symbol_ref ("which_alternative"))
5742                           (const_int 1))
5743                       (eq_attr "length" "8"))
5744                  (eq_attr "length" "10"))
5745             (const_string "yes")
5746             (const_string "no")))
5747    (set (attr "length")
5748      (if_then_else
5749        (le (symbol_ref ("which_alternative"))
5750                        (const_int 1))
5751        (if_then_else
5752          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5753               (le (minus (match_dup 2) (pc)) (const_int 256)))
5754          (const_int 4)
5755          (if_then_else
5756            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5757                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5758            (const_int 6)
5759            (const_int 8)))
5760        (if_then_else
5761          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5762               (le (minus (match_dup 2) (pc)) (const_int 256)))
5763          (const_int 6)
5764          (if_then_else
5765            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5766                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5767            (const_int 8)
5768            (const_int 10)))))]
5769 )
5770
5771 (define_insn "*negated_cbranchsi4"
5772   [(set (pc)
5773         (if_then_else
5774          (match_operator 0 "arm_comparison_operator"
5775           [(match_operand:SI 1 "s_register_operand" "l")
5776            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5777          (label_ref (match_operand 3 "" ""))
5778          (pc)))]
5779   "TARGET_THUMB"
5780   "*
5781   output_asm_insn (\"cmn\\t%1, %2\", operands);
5782   switch (get_attr_length (insn))
5783     {
5784     case 4:  return \"b%d0\\t%l3\";
5785     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5786     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5787     }
5788   "
5789   [(set (attr "far_jump")
5790         (if_then_else
5791             (eq_attr "length" "8")
5792             (const_string "yes")
5793             (const_string "no")))
5794    (set (attr "length") 
5795         (if_then_else
5796             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5797                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5798             (const_int 4)
5799             (if_then_else
5800                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5801                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5802                 (const_int 6)
5803                 (const_int 8))))]
5804 )
5805
5806 (define_insn "*tbit_cbranch"
5807   [(set (pc)
5808         (if_then_else
5809          (match_operator 0 "equality_operator"
5810           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5811                             (const_int 1)
5812                             (match_operand:SI 2 "const_int_operand" "i"))
5813            (const_int 0)])
5814          (label_ref (match_operand 3 "" ""))
5815          (pc)))
5816    (clobber (match_scratch:SI 4 "=l"))]
5817   "TARGET_THUMB"
5818   "*
5819   {
5820   rtx op[3];
5821   op[0] = operands[4];
5822   op[1] = operands[1];
5823   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5824
5825   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5826   switch (get_attr_length (insn))
5827     {
5828     case 4:  return \"b%d0\\t%l3\";
5829     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5830     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5831     }
5832   }"
5833   [(set (attr "far_jump")
5834         (if_then_else
5835             (eq_attr "length" "8")
5836             (const_string "yes")
5837             (const_string "no")))
5838    (set (attr "length") 
5839         (if_then_else
5840             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5841                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5842             (const_int 4)
5843             (if_then_else
5844                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5845                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5846                 (const_int 6)
5847                 (const_int 8))))]
5848 )
5849   
5850 (define_insn "*tstsi3_cbranch"
5851   [(set (pc)
5852         (if_then_else
5853          (match_operator 3 "equality_operator"
5854           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5855                    (match_operand:SI 1 "s_register_operand" "l"))
5856            (const_int 0)])
5857          (label_ref (match_operand 2 "" ""))
5858          (pc)))]
5859   "TARGET_THUMB"
5860   "*
5861   {
5862   output_asm_insn (\"tst\\t%0, %1\", operands);
5863   switch (get_attr_length (insn))
5864     {
5865     case 4:  return \"b%d3\\t%l2\";
5866     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5867     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5868     }
5869   }"
5870   [(set (attr "far_jump")
5871         (if_then_else
5872             (eq_attr "length" "8")
5873             (const_string "yes")
5874             (const_string "no")))
5875    (set (attr "length") 
5876         (if_then_else
5877             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5878                  (le (minus (match_dup 2) (pc)) (const_int 256)))
5879             (const_int 4)
5880             (if_then_else
5881                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5882                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
5883                 (const_int 6)
5884                 (const_int 8))))]
5885 )
5886   
5887 (define_insn "*andsi3_cbranch"
5888   [(set (pc)
5889         (if_then_else
5890          (match_operator 5 "equality_operator"
5891           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5892                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5893            (const_int 0)])
5894          (label_ref (match_operand 4 "" ""))
5895          (pc)))
5896    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5897         (and:SI (match_dup 2) (match_dup 3)))
5898    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5899   "TARGET_THUMB"
5900   "*
5901   {
5902   if (which_alternative == 0)
5903     output_asm_insn (\"and\\t%0, %3\", operands);
5904   else if (which_alternative == 1)
5905     {
5906       output_asm_insn (\"and\\t%1, %3\", operands);
5907       output_asm_insn (\"mov\\t%0, %1\", operands);
5908     }
5909   else
5910     {
5911       output_asm_insn (\"and\\t%1, %3\", operands);
5912       output_asm_insn (\"str\\t%1, %0\", operands);
5913     }
5914
5915   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5916     {
5917     case 4:  return \"b%d5\\t%l4\";
5918     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5919     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5920     }
5921   }"
5922   [(set (attr "far_jump")
5923         (if_then_else
5924             (ior (and (eq (symbol_ref ("which_alternative"))
5925                           (const_int 0))
5926                       (eq_attr "length" "8"))
5927                  (eq_attr "length" "10"))
5928             (const_string "yes")
5929             (const_string "no")))
5930    (set (attr "length")
5931      (if_then_else
5932        (eq (symbol_ref ("which_alternative"))
5933                        (const_int 0))
5934        (if_then_else
5935          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5936               (le (minus (match_dup 4) (pc)) (const_int 256)))
5937          (const_int 4)
5938          (if_then_else
5939            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5940                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5941            (const_int 6)
5942            (const_int 8)))
5943        (if_then_else
5944          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5945               (le (minus (match_dup 4) (pc)) (const_int 256)))
5946          (const_int 6)
5947          (if_then_else
5948            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5949                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5950            (const_int 8)
5951            (const_int 10)))))]
5952 )
5953
5954 (define_insn "*orrsi3_cbranch_scratch"
5955   [(set (pc)
5956         (if_then_else
5957          (match_operator 4 "equality_operator"
5958           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
5959                    (match_operand:SI 2 "s_register_operand" "l"))
5960            (const_int 0)])
5961          (label_ref (match_operand 3 "" ""))
5962          (pc)))
5963    (clobber (match_scratch:SI 0 "=l"))]
5964   "TARGET_THUMB"
5965   "*
5966   {
5967   output_asm_insn (\"orr\\t%0, %2\", operands);
5968   switch (get_attr_length (insn))
5969     {
5970     case 4:  return \"b%d4\\t%l3\";
5971     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5972     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5973     }
5974   }"
5975   [(set (attr "far_jump")
5976         (if_then_else
5977             (eq_attr "length" "8")
5978             (const_string "yes")
5979             (const_string "no")))
5980    (set (attr "length") 
5981         (if_then_else
5982             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5983                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5984             (const_int 4)
5985             (if_then_else
5986                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5987                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5988                 (const_int 6)
5989                 (const_int 8))))]
5990 )
5991   
5992 (define_insn "*orrsi3_cbranch"
5993   [(set (pc)
5994         (if_then_else
5995          (match_operator 5 "equality_operator"
5996           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5997                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5998            (const_int 0)])
5999          (label_ref (match_operand 4 "" ""))
6000          (pc)))
6001    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6002         (ior:SI (match_dup 2) (match_dup 3)))
6003    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6004   "TARGET_THUMB"
6005   "*
6006   {
6007   if (which_alternative == 0)
6008     output_asm_insn (\"orr\\t%0, %3\", operands);
6009   else if (which_alternative == 1)
6010     {
6011       output_asm_insn (\"orr\\t%1, %3\", operands);
6012       output_asm_insn (\"mov\\t%0, %1\", operands);
6013     }
6014   else
6015     {
6016       output_asm_insn (\"orr\\t%1, %3\", operands);
6017       output_asm_insn (\"str\\t%1, %0\", operands);
6018     }
6019
6020   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6021     {
6022     case 4:  return \"b%d5\\t%l4\";
6023     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6024     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6025     }
6026   }"
6027   [(set (attr "far_jump")
6028         (if_then_else
6029             (ior (and (eq (symbol_ref ("which_alternative"))
6030                           (const_int 0))
6031                       (eq_attr "length" "8"))
6032                  (eq_attr "length" "10"))
6033             (const_string "yes")
6034             (const_string "no")))
6035    (set (attr "length")
6036      (if_then_else
6037        (eq (symbol_ref ("which_alternative"))
6038                        (const_int 0))
6039        (if_then_else
6040          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6041               (le (minus (match_dup 4) (pc)) (const_int 256)))
6042          (const_int 4)
6043          (if_then_else
6044            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6045                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6046            (const_int 6)
6047            (const_int 8)))
6048        (if_then_else
6049          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6050               (le (minus (match_dup 4) (pc)) (const_int 256)))
6051          (const_int 6)
6052          (if_then_else
6053            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6054                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6055            (const_int 8)
6056            (const_int 10)))))]
6057 )
6058
6059 (define_insn "*xorsi3_cbranch_scratch"
6060   [(set (pc)
6061         (if_then_else
6062          (match_operator 4 "equality_operator"
6063           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6064                    (match_operand:SI 2 "s_register_operand" "l"))
6065            (const_int 0)])
6066          (label_ref (match_operand 3 "" ""))
6067          (pc)))
6068    (clobber (match_scratch:SI 0 "=l"))]
6069   "TARGET_THUMB"
6070   "*
6071   {
6072   output_asm_insn (\"eor\\t%0, %2\", operands);
6073   switch (get_attr_length (insn))
6074     {
6075     case 4:  return \"b%d4\\t%l3\";
6076     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6077     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6078     }
6079   }"
6080   [(set (attr "far_jump")
6081         (if_then_else
6082             (eq_attr "length" "8")
6083             (const_string "yes")
6084             (const_string "no")))
6085    (set (attr "length") 
6086         (if_then_else
6087             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6088                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6089             (const_int 4)
6090             (if_then_else
6091                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6092                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6093                 (const_int 6)
6094                 (const_int 8))))]
6095 )
6096   
6097 (define_insn "*xorsi3_cbranch"
6098   [(set (pc)
6099         (if_then_else
6100          (match_operator 5 "equality_operator"
6101           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6102                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6103            (const_int 0)])
6104          (label_ref (match_operand 4 "" ""))
6105          (pc)))
6106    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6107         (xor:SI (match_dup 2) (match_dup 3)))
6108    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6109   "TARGET_THUMB"
6110   "*
6111   {
6112   if (which_alternative == 0)
6113     output_asm_insn (\"eor\\t%0, %3\", operands);
6114   else if (which_alternative == 1)
6115     {
6116       output_asm_insn (\"eor\\t%1, %3\", operands);
6117       output_asm_insn (\"mov\\t%0, %1\", operands);
6118     }
6119   else
6120     {
6121       output_asm_insn (\"eor\\t%1, %3\", operands);
6122       output_asm_insn (\"str\\t%1, %0\", operands);
6123     }
6124
6125   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6126     {
6127     case 4:  return \"b%d5\\t%l4\";
6128     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6129     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6130     }
6131   }"
6132   [(set (attr "far_jump")
6133         (if_then_else
6134             (ior (and (eq (symbol_ref ("which_alternative"))
6135                           (const_int 0))
6136                       (eq_attr "length" "8"))
6137                  (eq_attr "length" "10"))
6138             (const_string "yes")
6139             (const_string "no")))
6140    (set (attr "length")
6141      (if_then_else
6142        (eq (symbol_ref ("which_alternative"))
6143                        (const_int 0))
6144        (if_then_else
6145          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6146               (le (minus (match_dup 4) (pc)) (const_int 256)))
6147          (const_int 4)
6148          (if_then_else
6149            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6150                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6151            (const_int 6)
6152            (const_int 8)))
6153        (if_then_else
6154          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6155               (le (minus (match_dup 4) (pc)) (const_int 256)))
6156          (const_int 6)
6157          (if_then_else
6158            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6159                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6160            (const_int 8)
6161            (const_int 10)))))]
6162 )
6163
6164 (define_insn "*bicsi3_cbranch_scratch"
6165   [(set (pc)
6166         (if_then_else
6167          (match_operator 4 "equality_operator"
6168           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6169                    (match_operand:SI 1 "s_register_operand" "0"))
6170            (const_int 0)])
6171          (label_ref (match_operand 3 "" ""))
6172          (pc)))
6173    (clobber (match_scratch:SI 0 "=l"))]
6174   "TARGET_THUMB"
6175   "*
6176   {
6177   output_asm_insn (\"bic\\t%0, %2\", operands);
6178   switch (get_attr_length (insn))
6179     {
6180     case 4:  return \"b%d4\\t%l3\";
6181     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6182     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6183     }
6184   }"
6185   [(set (attr "far_jump")
6186         (if_then_else
6187             (eq_attr "length" "8")
6188             (const_string "yes")
6189             (const_string "no")))
6190    (set (attr "length") 
6191         (if_then_else
6192             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6193                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6194             (const_int 4)
6195             (if_then_else
6196                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6197                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6198                 (const_int 6)
6199                 (const_int 8))))]
6200 )
6201   
6202 (define_insn "*bicsi3_cbranch"
6203   [(set (pc)
6204         (if_then_else
6205          (match_operator 5 "equality_operator"
6206           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6207                    (match_operand:SI 2 "s_register_operand" "0,1,1,1"))
6208            (const_int 0)])
6209          (label_ref (match_operand 4 "" ""))
6210          (pc)))
6211    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6212         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6213    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6214   "TARGET_THUMB"
6215   "*
6216   {
6217   if (which_alternative == 0)
6218     output_asm_insn (\"bic\\t%0, %3\", operands);
6219   else if (which_alternative == 1)
6220     {
6221       output_asm_insn (\"bic\\t%1, %3\", operands);
6222       output_asm_insn (\"mov\\t%0, %1\", operands);
6223     }
6224   else
6225     {
6226       output_asm_insn (\"bic\\t%1, %3\", operands);
6227       output_asm_insn (\"str\\t%1, %0\", operands);
6228     }
6229
6230   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6231     {
6232     case 4:  return \"b%d5\\t%l4\";
6233     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6234     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6235     }
6236   }"
6237   [(set (attr "far_jump")
6238         (if_then_else
6239             (ior (and (eq (symbol_ref ("which_alternative"))
6240                           (const_int 0))
6241                       (eq_attr "length" "8"))
6242                  (eq_attr "length" "10"))
6243             (const_string "yes")
6244             (const_string "no")))
6245    (set (attr "length")
6246      (if_then_else
6247        (eq (symbol_ref ("which_alternative"))
6248                        (const_int 0))
6249        (if_then_else
6250          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6251               (le (minus (match_dup 4) (pc)) (const_int 256)))
6252          (const_int 4)
6253          (if_then_else
6254            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6255                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6256            (const_int 6)
6257            (const_int 8)))
6258        (if_then_else
6259          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6260               (le (minus (match_dup 4) (pc)) (const_int 256)))
6261          (const_int 6)
6262          (if_then_else
6263            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6264                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6265            (const_int 8)
6266            (const_int 10)))))]
6267 )
6268
6269 (define_insn "*cbranchne_decr1"
6270   [(set (pc)
6271         (if_then_else (match_operator 3 "equality_operator"
6272                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6273                         (const_int 0)])
6274                       (label_ref (match_operand 4 "" ""))
6275                       (pc)))
6276    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6277         (plus:SI (match_dup 2) (const_int -1)))
6278    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6279   "TARGET_THUMB"
6280   "*
6281    {
6282      rtx cond[2];
6283      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6284                                 ? GEU : LTU),
6285                                VOIDmode, operands[2], const1_rtx);
6286      cond[1] = operands[4];
6287
6288      if (which_alternative == 0)
6289        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6290      else if (which_alternative == 1)
6291        {
6292          /* We must provide an alternative for a hi reg because reload 
6293             cannot handle output reloads on a jump instruction, but we
6294             can't subtract into that.  Fortunately a mov from lo to hi
6295             does not clobber the condition codes.  */
6296          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6297          output_asm_insn (\"mov\\t%0, %1\", operands);
6298        }
6299      else
6300        {
6301          /* Similarly, but the target is memory.  */
6302          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6303          output_asm_insn (\"str\\t%1, %0\", operands);
6304        }
6305
6306      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6307        {
6308          case 4:
6309            output_asm_insn (\"b%d0\\t%l1\", cond);
6310            return \"\";
6311          case 6:
6312            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6313            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6314          default:
6315            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6316            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6317        }
6318    }
6319   "
6320   [(set (attr "far_jump")
6321         (if_then_else
6322             (ior (and (eq (symbol_ref ("which_alternative"))
6323                           (const_int 0))
6324                       (eq_attr "length" "8"))
6325                  (eq_attr "length" "10"))
6326             (const_string "yes")
6327             (const_string "no")))
6328    (set_attr_alternative "length"
6329       [
6330        ;; Alternative 0
6331        (if_then_else
6332          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6333               (le (minus (match_dup 4) (pc)) (const_int 256)))
6334          (const_int 4)
6335          (if_then_else
6336            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6337                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6338            (const_int 6)
6339            (const_int 8)))
6340        ;; Alternative 1
6341        (if_then_else
6342          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6343               (le (minus (match_dup 4) (pc)) (const_int 256)))
6344          (const_int 6)
6345          (if_then_else
6346            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6347                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6348            (const_int 8)
6349            (const_int 10)))
6350        ;; Alternative 2
6351        (if_then_else
6352          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6353               (le (minus (match_dup 4) (pc)) (const_int 256)))
6354          (const_int 6)
6355          (if_then_else
6356            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6357                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6358            (const_int 8)
6359            (const_int 10)))
6360        ;; Alternative 3
6361        (if_then_else
6362          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6363               (le (minus (match_dup 4) (pc)) (const_int 256)))
6364          (const_int 6)
6365          (if_then_else
6366            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6367                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6368            (const_int 8)
6369            (const_int 10)))])]
6370 )
6371
6372 (define_insn "*addsi3_cbranch"
6373   [(set (pc)
6374         (if_then_else
6375          (match_operator 4 "comparison_operator"
6376           [(plus:SI
6377             (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6378             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6379            (const_int 0)])
6380          (label_ref (match_operand 5 "" ""))
6381          (pc)))
6382    (set
6383     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6384     (plus:SI (match_dup 2) (match_dup 3)))
6385    (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6386   "TARGET_THUMB
6387    && (GET_CODE (operands[4]) == EQ
6388        || GET_CODE (operands[4]) == NE
6389        || GET_CODE (operands[4]) == GE
6390        || GET_CODE (operands[4]) == LT)"
6391   "*
6392    {
6393      rtx cond[3];
6394
6395      
6396      cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6397      cond[1] = operands[2];
6398      cond[2] = operands[3];
6399
6400      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6401        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6402      else
6403        output_asm_insn (\"add\\t%0, %1, %2\", cond);
6404
6405      if (which_alternative >= 3
6406          && which_alternative < 4)
6407        output_asm_insn (\"mov\\t%0, %1\", operands);
6408      else if (which_alternative >= 4)
6409        output_asm_insn (\"str\\t%1, %0\", operands);
6410
6411      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6412        {
6413          case 4:
6414            return \"b%d4\\t%l5\";
6415          case 6:
6416            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6417          default:
6418            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6419        }
6420    }
6421   "
6422   [(set (attr "far_jump")
6423         (if_then_else
6424             (ior (and (lt (symbol_ref ("which_alternative"))
6425                           (const_int 3))
6426                       (eq_attr "length" "8"))
6427                  (eq_attr "length" "10"))
6428             (const_string "yes")
6429             (const_string "no")))
6430    (set (attr "length")
6431      (if_then_else
6432        (lt (symbol_ref ("which_alternative"))
6433                        (const_int 3))
6434        (if_then_else
6435          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6436               (le (minus (match_dup 5) (pc)) (const_int 256)))
6437          (const_int 4)
6438          (if_then_else
6439            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6440                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6441            (const_int 6)
6442            (const_int 8)))
6443        (if_then_else
6444          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6445               (le (minus (match_dup 5) (pc)) (const_int 256)))
6446          (const_int 6)
6447          (if_then_else
6448            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6449                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6450            (const_int 8)
6451            (const_int 10)))))]
6452 )
6453
6454 (define_insn "*addsi3_cbranch_scratch"
6455   [(set (pc)
6456         (if_then_else
6457          (match_operator 3 "comparison_operator"
6458           [(plus:SI
6459             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6460             (match_operand:SI 2 "reg_or_int_operand" "J,l,I,L"))
6461            (const_int 0)])
6462          (label_ref (match_operand 4 "" ""))
6463          (pc)))
6464    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6465   "TARGET_THUMB
6466    && (GET_CODE (operands[3]) == EQ
6467        || GET_CODE (operands[3]) == NE
6468        || GET_CODE (operands[3]) == GE
6469        || GET_CODE (operands[3]) == LT)"
6470   "*
6471    {
6472      switch (which_alternative)
6473        {
6474        case 0:
6475          output_asm_insn (\"cmp\t%1, #%n2\", operands);
6476          break;
6477        case 1:
6478          output_asm_insn (\"cmn\t%1, %2\", operands);
6479          break;
6480        case 3:
6481          output_asm_insn (\"add\t%0, %1, %2\", operands);
6482          break;
6483        case 4:
6484          output_asm_insn (\"add\t%0, %0, %2\", operands);
6485          break;
6486        }
6487
6488      switch (get_attr_length (insn))
6489        {
6490          case 4:
6491            return \"b%d3\\t%l4\";
6492          case 6:
6493            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6494          default:
6495            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6496        }
6497    }
6498   "
6499   [(set (attr "far_jump")
6500         (if_then_else
6501             (eq_attr "length" "8")
6502             (const_string "yes")
6503             (const_string "no")))
6504    (set (attr "length")
6505        (if_then_else
6506          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6507               (le (minus (match_dup 4) (pc)) (const_int 256)))
6508          (const_int 4)
6509          (if_then_else
6510            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6511                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6512            (const_int 6)
6513            (const_int 8))))]
6514 )
6515
6516 (define_insn "*subsi3_cbranch"
6517   [(set (pc)
6518         (if_then_else
6519          (match_operator 4 "comparison_operator"
6520           [(minus:SI
6521             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6522             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6523            (const_int 0)])
6524          (label_ref (match_operand 5 "" ""))
6525          (pc)))
6526    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6527         (minus:SI (match_dup 2) (match_dup 3)))
6528    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6529   "TARGET_THUMB
6530    && (GET_CODE (operands[4]) == EQ
6531        || GET_CODE (operands[4]) == NE
6532        || GET_CODE (operands[4]) == GE
6533        || GET_CODE (operands[4]) == LT)"
6534   "*
6535    {
6536      if (which_alternative == 0)
6537        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6538      else if (which_alternative == 1)
6539        {
6540          /* We must provide an alternative for a hi reg because reload 
6541             cannot handle output reloads on a jump instruction, but we
6542             can't subtract into that.  Fortunately a mov from lo to hi
6543             does not clobber the condition codes.  */
6544          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6545          output_asm_insn (\"mov\\t%0, %1\", operands);
6546        }
6547      else
6548        {
6549          /* Similarly, but the target is memory.  */
6550          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6551          output_asm_insn (\"str\\t%1, %0\", operands);
6552        }
6553
6554      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6555        {
6556          case 4:
6557            return \"b%d4\\t%l5\";
6558          case 6:
6559            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6560          default:
6561            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6562        }
6563    }
6564   "
6565   [(set (attr "far_jump")
6566         (if_then_else
6567             (ior (and (eq (symbol_ref ("which_alternative"))
6568                           (const_int 0))
6569                       (eq_attr "length" "8"))
6570                  (eq_attr "length" "10"))
6571             (const_string "yes")
6572             (const_string "no")))
6573    (set (attr "length")
6574      (if_then_else
6575        (eq (symbol_ref ("which_alternative"))
6576                        (const_int 0))
6577        (if_then_else
6578          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6579               (le (minus (match_dup 5) (pc)) (const_int 256)))
6580          (const_int 4)
6581          (if_then_else
6582            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6583                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6584            (const_int 6)
6585            (const_int 8)))
6586        (if_then_else
6587          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6588               (le (minus (match_dup 5) (pc)) (const_int 256)))
6589          (const_int 6)
6590          (if_then_else
6591            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6592                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6593            (const_int 8)
6594            (const_int 10)))))]
6595 )
6596
6597 (define_insn "*subsi3_cbranch_scratch"
6598   [(set (pc)
6599         (if_then_else
6600          (match_operator 0 "arm_comparison_operator"
6601           [(minus:SI (match_operand:SI 1 "register_operand" "l")
6602                      (match_operand:SI 2 "nonmemory_operand" "l"))
6603            (const_int 0)])
6604          (label_ref (match_operand 3 "" ""))
6605          (pc)))]
6606   "TARGET_THUMB
6607    && (GET_CODE (operands[0]) == EQ
6608        || GET_CODE (operands[0]) == NE
6609        || GET_CODE (operands[0]) == GE
6610        || GET_CODE (operands[0]) == LT)"
6611   "*
6612   output_asm_insn (\"cmp\\t%1, %2\", operands);
6613   switch (get_attr_length (insn))
6614     {
6615     case 4:  return \"b%d0\\t%l3\";
6616     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6617     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6618     }
6619   "
6620   [(set (attr "far_jump")
6621         (if_then_else
6622             (eq_attr "length" "8")
6623             (const_string "yes")
6624             (const_string "no")))
6625    (set (attr "length") 
6626         (if_then_else
6627             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6628                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6629             (const_int 4)
6630             (if_then_else
6631                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6632                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6633                 (const_int 6)
6634                 (const_int 8))))]
6635 )
6636
6637 ;; Comparison and test insns
6638
6639 (define_expand "cmpsi"
6640   [(match_operand:SI 0 "s_register_operand" "")
6641    (match_operand:SI 1 "arm_add_operand" "")]
6642   "TARGET_ARM"
6643   "{
6644     arm_compare_op0 = operands[0];
6645     arm_compare_op1 = operands[1];
6646     DONE;
6647   }"
6648 )
6649
6650 (define_expand "cmpsf"
6651   [(match_operand:SF 0 "s_register_operand" "")
6652    (match_operand:SF 1 "arm_float_compare_operand" "")]
6653   "TARGET_ARM && TARGET_HARD_FLOAT"
6654   "
6655   arm_compare_op0 = operands[0];
6656   arm_compare_op1 = operands[1];
6657   DONE;
6658   "
6659 )
6660
6661 (define_expand "cmpdf"
6662   [(match_operand:DF 0 "s_register_operand" "")
6663    (match_operand:DF 1 "arm_float_compare_operand" "")]
6664   "TARGET_ARM && TARGET_HARD_FLOAT"
6665   "
6666   arm_compare_op0 = operands[0];
6667   arm_compare_op1 = operands[1];
6668   DONE;
6669   "
6670 )
6671
6672 (define_insn "*arm_cmpsi_insn"
6673   [(set (reg:CC CC_REGNUM)
6674         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6675                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
6676   "TARGET_ARM"
6677   "@
6678    cmp%?\\t%0, %1
6679    cmn%?\\t%0, #%n1"
6680   [(set_attr "conds" "set")]
6681 )
6682
6683 (define_insn "*cmpsi_shiftsi"
6684   [(set (reg:CC CC_REGNUM)
6685         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
6686                     (match_operator:SI  3 "shift_operator"
6687                      [(match_operand:SI 1 "s_register_operand" "r")
6688                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
6689   "TARGET_ARM"
6690   "cmp%?\\t%0, %1%S3"
6691   [(set_attr "conds" "set")
6692    (set_attr "shift" "1")
6693    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6694                       (const_string "alu_shift")
6695                       (const_string "alu_shift_reg")))]
6696 )
6697
6698 (define_insn "*cmpsi_shiftsi_swp"
6699   [(set (reg:CC_SWP CC_REGNUM)
6700         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6701                          [(match_operand:SI 1 "s_register_operand" "r")
6702                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
6703                         (match_operand:SI 0 "s_register_operand" "r")))]
6704   "TARGET_ARM"
6705   "cmp%?\\t%0, %1%S3"
6706   [(set_attr "conds" "set")
6707    (set_attr "shift" "1")
6708    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6709                       (const_string "alu_shift")
6710                       (const_string "alu_shift_reg")))]
6711 )
6712
6713 (define_insn "*cmpsi_neg_shiftsi"
6714   [(set (reg:CC CC_REGNUM)
6715         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6716                     (neg:SI (match_operator:SI 3 "shift_operator"
6717                              [(match_operand:SI 1 "s_register_operand" "r")
6718                               (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
6719   "TARGET_ARM"
6720   "cmn%?\\t%0, %1%S3"
6721   [(set_attr "conds" "set")
6722    (set_attr "shift" "1")
6723    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6724                       (const_string "alu_shift")
6725                       (const_string "alu_shift_reg")))]
6726 )
6727
6728 ;; Cirrus SF compare instruction
6729 (define_insn "*cirrus_cmpsf"
6730   [(set (reg:CCFP CC_REGNUM)
6731         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6732                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
6733   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6734   "cfcmps%?\\tr15, %V0, %V1"
6735   [(set_attr "type"   "mav_farith")
6736    (set_attr "cirrus" "compare")]
6737 )
6738
6739 ;; Cirrus DF compare instruction
6740 (define_insn "*cirrus_cmpdf"
6741   [(set (reg:CCFP CC_REGNUM)
6742         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6743                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
6744   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6745   "cfcmpd%?\\tr15, %V0, %V1"
6746   [(set_attr "type"   "mav_farith")
6747    (set_attr "cirrus" "compare")]
6748 )
6749
6750 ;; Cirrus DI compare instruction
6751 (define_expand "cmpdi"
6752   [(match_operand:DI 0 "cirrus_fp_register" "")
6753    (match_operand:DI 1 "cirrus_fp_register" "")]
6754   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6755   "{
6756      arm_compare_op0 = operands[0];
6757      arm_compare_op1 = operands[1];
6758      DONE;
6759    }")
6760
6761 (define_insn "*cirrus_cmpdi"
6762   [(set (reg:CC CC_REGNUM)
6763         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6764                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
6765   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6766   "cfcmp64%?\\tr15, %V0, %V1"
6767   [(set_attr "type"   "mav_farith")
6768    (set_attr "cirrus" "compare")]
6769 )
6770
6771 ; This insn allows redundant compares to be removed by cse, nothing should
6772 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6773 ; is deleted later on. The match_dup will match the mode here, so that
6774 ; mode changes of the condition codes aren't lost by this even though we don't
6775 ; specify what they are.
6776
6777 (define_insn "*deleted_compare"
6778   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6779   "TARGET_ARM"
6780   "\\t%@ deleted compare"
6781   [(set_attr "conds" "set")
6782    (set_attr "length" "0")]
6783 )
6784
6785 \f
6786 ;; Conditional branch insns
6787
6788 (define_expand "beq"
6789   [(set (pc)
6790         (if_then_else (eq (match_dup 1) (const_int 0))
6791                       (label_ref (match_operand 0 "" ""))
6792                       (pc)))]
6793   "TARGET_ARM"
6794   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6795 )
6796
6797 (define_expand "bne"
6798   [(set (pc)
6799         (if_then_else (ne (match_dup 1) (const_int 0))
6800                       (label_ref (match_operand 0 "" ""))
6801                       (pc)))]
6802   "TARGET_ARM"
6803   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6804 )
6805
6806 (define_expand "bgt"
6807   [(set (pc)
6808         (if_then_else (gt (match_dup 1) (const_int 0))
6809                       (label_ref (match_operand 0 "" ""))
6810                       (pc)))]
6811   "TARGET_ARM"
6812   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6813 )
6814
6815 (define_expand "ble"
6816   [(set (pc)
6817         (if_then_else (le (match_dup 1) (const_int 0))
6818                       (label_ref (match_operand 0 "" ""))
6819                       (pc)))]
6820   "TARGET_ARM"
6821   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6822 )
6823
6824 (define_expand "bge"
6825   [(set (pc)
6826         (if_then_else (ge (match_dup 1) (const_int 0))
6827                       (label_ref (match_operand 0 "" ""))
6828                       (pc)))]
6829   "TARGET_ARM"
6830   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6831 )
6832
6833 (define_expand "blt"
6834   [(set (pc)
6835         (if_then_else (lt (match_dup 1) (const_int 0))
6836                       (label_ref (match_operand 0 "" ""))
6837                       (pc)))]
6838   "TARGET_ARM"
6839   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6840 )
6841
6842 (define_expand "bgtu"
6843   [(set (pc)
6844         (if_then_else (gtu (match_dup 1) (const_int 0))
6845                       (label_ref (match_operand 0 "" ""))
6846                       (pc)))]
6847   "TARGET_ARM"
6848   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6849 )
6850
6851 (define_expand "bleu"
6852   [(set (pc)
6853         (if_then_else (leu (match_dup 1) (const_int 0))
6854                       (label_ref (match_operand 0 "" ""))
6855                       (pc)))]
6856   "TARGET_ARM"
6857   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6858 )
6859
6860 (define_expand "bgeu"
6861   [(set (pc)
6862         (if_then_else (geu (match_dup 1) (const_int 0))
6863                       (label_ref (match_operand 0 "" ""))
6864                       (pc)))]
6865   "TARGET_ARM"
6866   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6867 )
6868
6869 (define_expand "bltu"
6870   [(set (pc)
6871         (if_then_else (ltu (match_dup 1) (const_int 0))
6872                       (label_ref (match_operand 0 "" ""))
6873                       (pc)))]
6874   "TARGET_ARM"
6875   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6876 )
6877
6878 (define_expand "bunordered"
6879   [(set (pc)
6880         (if_then_else (unordered (match_dup 1) (const_int 0))
6881                       (label_ref (match_operand 0 "" ""))
6882                       (pc)))]
6883   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6884   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6885                                       arm_compare_op1);"
6886 )
6887
6888 (define_expand "bordered"
6889   [(set (pc)
6890         (if_then_else (ordered (match_dup 1) (const_int 0))
6891                       (label_ref (match_operand 0 "" ""))
6892                       (pc)))]
6893   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6894   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6895                                       arm_compare_op1);"
6896 )
6897
6898 (define_expand "bungt"
6899   [(set (pc)
6900         (if_then_else (ungt (match_dup 1) (const_int 0))
6901                       (label_ref (match_operand 0 "" ""))
6902                       (pc)))]
6903   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6904   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
6905 )
6906
6907 (define_expand "bunlt"
6908   [(set (pc)
6909         (if_then_else (unlt (match_dup 1) (const_int 0))
6910                       (label_ref (match_operand 0 "" ""))
6911                       (pc)))]
6912   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6913   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
6914 )
6915
6916 (define_expand "bunge"
6917   [(set (pc)
6918         (if_then_else (unge (match_dup 1) (const_int 0))
6919                       (label_ref (match_operand 0 "" ""))
6920                       (pc)))]
6921   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6922   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
6923 )
6924
6925 (define_expand "bunle"
6926   [(set (pc)
6927         (if_then_else (unle (match_dup 1) (const_int 0))
6928                       (label_ref (match_operand 0 "" ""))
6929                       (pc)))]
6930   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6931   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
6932 )
6933
6934 ;; The following two patterns need two branch instructions, since there is
6935 ;; no single instruction that will handle all cases.
6936 (define_expand "buneq"
6937   [(set (pc)
6938         (if_then_else (uneq (match_dup 1) (const_int 0))
6939                       (label_ref (match_operand 0 "" ""))
6940                       (pc)))]
6941   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6942   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6943 )
6944
6945 (define_expand "bltgt"
6946   [(set (pc)
6947         (if_then_else (ltgt (match_dup 1) (const_int 0))
6948                       (label_ref (match_operand 0 "" ""))
6949                       (pc)))]
6950   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6951   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6952 )
6953
6954 ;;
6955 ;; Patterns to match conditional branch insns.
6956 ;;
6957
6958 ; Special pattern to match UNEQ.
6959 (define_insn "*arm_buneq"
6960   [(set (pc)
6961         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6962                       (label_ref (match_operand 0 "" ""))
6963                       (pc)))]
6964   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6965   "*
6966   if (arm_ccfsm_state != 0)
6967     abort ();
6968
6969   return \"bvs\\t%l0\;beq\\t%l0\";
6970   "
6971   [(set_attr "conds" "jump_clob")
6972    (set_attr "length" "8")]
6973 )
6974
6975 ; Special pattern to match LTGT.
6976 (define_insn "*arm_bltgt"
6977   [(set (pc)
6978         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6979                       (label_ref (match_operand 0 "" ""))
6980                       (pc)))]
6981   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6982   "*
6983   if (arm_ccfsm_state != 0)
6984     abort ();
6985
6986   return \"bmi\\t%l0\;bgt\\t%l0\";
6987   "
6988   [(set_attr "conds" "jump_clob")
6989    (set_attr "length" "8")]
6990 )
6991
6992 (define_insn "*arm_cond_branch"
6993   [(set (pc)
6994         (if_then_else (match_operator 1 "arm_comparison_operator"
6995                        [(match_operand 2 "cc_register" "") (const_int 0)])
6996                       (label_ref (match_operand 0 "" ""))
6997                       (pc)))]
6998   "TARGET_ARM"
6999   "*
7000   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7001     {
7002       arm_ccfsm_state += 2;
7003       return \"\";
7004     }
7005   return \"b%d1\\t%l0\";
7006   "
7007   [(set_attr "conds" "use")
7008    (set_attr "type" "branch")]
7009 )
7010
7011 ; Special pattern to match reversed UNEQ.
7012 (define_insn "*arm_buneq_reversed"
7013   [(set (pc)
7014         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7015                       (pc)
7016                       (label_ref (match_operand 0 "" ""))))]
7017   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7018   "*
7019   if (arm_ccfsm_state != 0)
7020     abort ();
7021
7022   return \"bmi\\t%l0\;bgt\\t%l0\";
7023   "
7024   [(set_attr "conds" "jump_clob")
7025    (set_attr "length" "8")]
7026 )
7027
7028 ; Special pattern to match reversed LTGT.
7029 (define_insn "*arm_bltgt_reversed"
7030   [(set (pc)
7031         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7032                       (pc)
7033                       (label_ref (match_operand 0 "" ""))))]
7034   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7035   "*
7036   if (arm_ccfsm_state != 0)
7037     abort ();
7038
7039   return \"bvs\\t%l0\;beq\\t%l0\";
7040   "
7041   [(set_attr "conds" "jump_clob")
7042    (set_attr "length" "8")]
7043 )
7044
7045 (define_insn "*arm_cond_branch_reversed"
7046   [(set (pc)
7047         (if_then_else (match_operator 1 "arm_comparison_operator"
7048                        [(match_operand 2 "cc_register" "") (const_int 0)])
7049                       (pc)
7050                       (label_ref (match_operand 0 "" ""))))]
7051   "TARGET_ARM"
7052   "*
7053   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7054     {
7055       arm_ccfsm_state += 2;
7056       return \"\";
7057     }
7058   return \"b%D1\\t%l0\";
7059   "
7060   [(set_attr "conds" "use")
7061    (set_attr "type" "branch")]
7062 )
7063
7064 \f
7065
7066 ; scc insns
7067
7068 (define_expand "seq"
7069   [(set (match_operand:SI 0 "s_register_operand" "")
7070         (eq:SI (match_dup 1) (const_int 0)))]
7071   "TARGET_ARM"
7072   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7073 )
7074
7075 (define_expand "sne"
7076   [(set (match_operand:SI 0 "s_register_operand" "")
7077         (ne:SI (match_dup 1) (const_int 0)))]
7078   "TARGET_ARM"
7079   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7080 )
7081
7082 (define_expand "sgt"
7083   [(set (match_operand:SI 0 "s_register_operand" "")
7084         (gt:SI (match_dup 1) (const_int 0)))]
7085   "TARGET_ARM"
7086   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7087 )
7088
7089 (define_expand "sle"
7090   [(set (match_operand:SI 0 "s_register_operand" "")
7091         (le:SI (match_dup 1) (const_int 0)))]
7092   "TARGET_ARM"
7093   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7094 )
7095
7096 (define_expand "sge"
7097   [(set (match_operand:SI 0 "s_register_operand" "")
7098         (ge:SI (match_dup 1) (const_int 0)))]
7099   "TARGET_ARM"
7100   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7101 )
7102
7103 (define_expand "slt"
7104   [(set (match_operand:SI 0 "s_register_operand" "")
7105         (lt:SI (match_dup 1) (const_int 0)))]
7106   "TARGET_ARM"
7107   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7108 )
7109
7110 (define_expand "sgtu"
7111   [(set (match_operand:SI 0 "s_register_operand" "")
7112         (gtu:SI (match_dup 1) (const_int 0)))]
7113   "TARGET_ARM"
7114   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7115 )
7116
7117 (define_expand "sleu"
7118   [(set (match_operand:SI 0 "s_register_operand" "")
7119         (leu:SI (match_dup 1) (const_int 0)))]
7120   "TARGET_ARM"
7121   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7122 )
7123
7124 (define_expand "sgeu"
7125   [(set (match_operand:SI 0 "s_register_operand" "")
7126         (geu:SI (match_dup 1) (const_int 0)))]
7127   "TARGET_ARM"
7128   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7129 )
7130
7131 (define_expand "sltu"
7132   [(set (match_operand:SI 0 "s_register_operand" "")
7133         (ltu:SI (match_dup 1) (const_int 0)))]
7134   "TARGET_ARM"
7135   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7136 )
7137
7138 (define_expand "sunordered"
7139   [(set (match_operand:SI 0 "s_register_operand" "")
7140         (unordered:SI (match_dup 1) (const_int 0)))]
7141   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7142   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7143                                       arm_compare_op1);"
7144 )
7145
7146 (define_expand "sordered"
7147   [(set (match_operand:SI 0 "s_register_operand" "")
7148         (ordered:SI (match_dup 1) (const_int 0)))]
7149   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7150   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7151                                       arm_compare_op1);"
7152 )
7153
7154 (define_expand "sungt"
7155   [(set (match_operand:SI 0 "s_register_operand" "")
7156         (ungt:SI (match_dup 1) (const_int 0)))]
7157   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7158   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7159                                       arm_compare_op1);"
7160 )
7161
7162 (define_expand "sunge"
7163   [(set (match_operand:SI 0 "s_register_operand" "")
7164         (unge:SI (match_dup 1) (const_int 0)))]
7165   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7166   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7167                                       arm_compare_op1);"
7168 )
7169
7170 (define_expand "sunlt"
7171   [(set (match_operand:SI 0 "s_register_operand" "")
7172         (unlt:SI (match_dup 1) (const_int 0)))]
7173   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7174   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7175                                       arm_compare_op1);"
7176 )
7177
7178 (define_expand "sunle"
7179   [(set (match_operand:SI 0 "s_register_operand" "")
7180         (unle:SI (match_dup 1) (const_int 0)))]
7181   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7182   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7183                                       arm_compare_op1);"
7184 )
7185
7186 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7187 ;;; simple ARM instructions. 
7188 ;
7189 ; (define_expand "suneq"
7190 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7191 ;       (uneq:SI (match_dup 1) (const_int 0)))]
7192 ;   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7193 ;   "abort ();"
7194 ; )
7195 ;
7196 ; (define_expand "sltgt"
7197 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7198 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
7199 ;   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7200 ;   "abort ();"
7201 ; )
7202
7203 (define_insn "*mov_scc"
7204   [(set (match_operand:SI 0 "s_register_operand" "=r")
7205         (match_operator:SI 1 "arm_comparison_operator"
7206          [(match_operand 2 "cc_register" "") (const_int 0)]))]
7207   "TARGET_ARM"
7208   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7209   [(set_attr "conds" "use")
7210    (set_attr "length" "8")]
7211 )
7212
7213 (define_insn "*mov_negscc"
7214   [(set (match_operand:SI 0 "s_register_operand" "=r")
7215         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7216                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7217   "TARGET_ARM"
7218   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7219   [(set_attr "conds" "use")
7220    (set_attr "length" "8")]
7221 )
7222
7223 (define_insn "*mov_notscc"
7224   [(set (match_operand:SI 0 "s_register_operand" "=r")
7225         (not:SI (match_operator:SI 1 "arm_comparison_operator"
7226                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7227   "TARGET_ARM"
7228   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7229   [(set_attr "conds" "use")
7230    (set_attr "length" "8")]
7231 )
7232
7233 \f
7234 ;; Conditional move insns
7235
7236 (define_expand "movsicc"
7237   [(set (match_operand:SI 0 "s_register_operand" "")
7238         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7239                          (match_operand:SI 2 "arm_not_operand" "")
7240                          (match_operand:SI 3 "arm_not_operand" "")))]
7241   "TARGET_ARM"
7242   "
7243   {
7244     enum rtx_code code = GET_CODE (operands[1]);
7245     rtx ccreg;
7246
7247     if (code == UNEQ || code == LTGT)
7248       FAIL;
7249
7250     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7251     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7252   }"
7253 )
7254
7255 (define_expand "movsfcc"
7256   [(set (match_operand:SF 0 "s_register_operand" "")
7257         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7258                          (match_operand:SF 2 "s_register_operand" "")
7259                          (match_operand:SF 3 "nonmemory_operand" "")))]
7260   "TARGET_ARM"
7261   "
7262   {
7263     enum rtx_code code = GET_CODE (operands[1]);
7264     rtx ccreg;
7265
7266     if (code == UNEQ || code == LTGT)
7267       FAIL;
7268
7269     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
7270        Otherwise, ensure it is a valid FP add operand */
7271     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7272         || (!arm_float_add_operand (operands[3], SFmode)))
7273       operands[3] = force_reg (SFmode, operands[3]);
7274
7275     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7276     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7277   }"
7278 )
7279
7280 (define_expand "movdfcc"
7281   [(set (match_operand:DF 0 "s_register_operand" "")
7282         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7283                          (match_operand:DF 2 "s_register_operand" "")
7284                          (match_operand:DF 3 "arm_float_add_operand" "")))]
7285   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7286   "
7287   {
7288     enum rtx_code code = GET_CODE (operands[1]);
7289     rtx ccreg;
7290
7291     if (code == UNEQ || code == LTGT)
7292       FAIL;
7293
7294     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7295     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7296   }"
7297 )
7298
7299 (define_insn "*movsicc_insn"
7300   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7301         (if_then_else:SI
7302          (match_operator 3 "arm_comparison_operator"
7303           [(match_operand 4 "cc_register" "") (const_int 0)])
7304          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7305          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7306   "TARGET_ARM"
7307   "@
7308    mov%D3\\t%0, %2
7309    mvn%D3\\t%0, #%B2
7310    mov%d3\\t%0, %1
7311    mvn%d3\\t%0, #%B1
7312    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7313    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7314    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7315    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7316   [(set_attr "length" "4,4,4,4,8,8,8,8")
7317    (set_attr "conds" "use")]
7318 )
7319
7320 (define_insn "*movsfcc_soft_insn"
7321   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7322         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7323                           [(match_operand 4 "cc_register" "") (const_int 0)])
7324                          (match_operand:SF 1 "s_register_operand" "0,r")
7325                          (match_operand:SF 2 "s_register_operand" "r,0")))]
7326   "TARGET_ARM && TARGET_SOFT_FLOAT"
7327   "@
7328    mov%D3\\t%0, %2
7329    mov%d3\\t%0, %1"
7330   [(set_attr "conds" "use")]
7331 )
7332
7333 \f
7334 ;; Jump and linkage insns
7335
7336 (define_expand "jump"
7337   [(set (pc)
7338         (label_ref (match_operand 0 "" "")))]
7339   "TARGET_EITHER"
7340   ""
7341 )
7342
7343 (define_insn "*arm_jump"
7344   [(set (pc)
7345         (label_ref (match_operand 0 "" "")))]
7346   "TARGET_ARM"
7347   "*
7348   {
7349     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7350       {
7351         arm_ccfsm_state += 2;
7352         return \"\";
7353       }
7354     return \"b%?\\t%l0\";
7355   }
7356   "
7357   [(set_attr "predicable" "yes")]
7358 )
7359
7360 (define_insn "*thumb_jump"
7361   [(set (pc)
7362         (label_ref (match_operand 0 "" "")))]
7363   "TARGET_THUMB"
7364   "*
7365   if (get_attr_length (insn) == 2)
7366     return \"b\\t%l0\";
7367   return \"bl\\t%l0\\t%@ far jump\";
7368   "
7369   [(set (attr "far_jump")
7370         (if_then_else
7371             (eq_attr "length" "4")
7372             (const_string "yes")
7373             (const_string "no")))
7374    (set (attr "length") 
7375         (if_then_else
7376             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7377                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
7378             (const_int 2)
7379             (const_int 4)))]
7380 )
7381
7382 (define_expand "call"
7383   [(parallel [(call (match_operand 0 "memory_operand" "")
7384                     (match_operand 1 "general_operand" ""))
7385               (use (match_operand 2 "" ""))
7386               (clobber (reg:SI LR_REGNUM))])]
7387   "TARGET_EITHER"
7388   "
7389   {
7390     rtx callee;
7391     
7392     /* In an untyped call, we can get NULL for operand 2.  */
7393     if (operands[2] == NULL_RTX)
7394       operands[2] = const0_rtx;
7395       
7396     /* This is to decide if we should generate indirect calls by loading the
7397        32 bit address of the callee into a register before performing the
7398        branch and link.  operand[2] encodes the long_call/short_call
7399        attribute of the function being called.  This attribute is set whenever
7400        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7401        is used, and the short_call attribute can also be set if function is
7402        declared as static or if it has already been defined in the current
7403        compilation unit.  See arm.c and arm.h for info about this.  The third
7404        parameter to arm_is_longcall_p is used to tell it which pattern
7405        invoked it.  */
7406     callee  = XEXP (operands[0], 0);
7407     
7408     if (GET_CODE (callee) != REG
7409        && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7410       XEXP (operands[0], 0) = force_reg (Pmode, callee);
7411   }"
7412 )
7413
7414 (define_insn "*call_reg"
7415   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7416          (match_operand 1 "" ""))
7417    (use (match_operand 2 "" ""))
7418    (clobber (reg:SI LR_REGNUM))]
7419   "TARGET_ARM"
7420   "*
7421   return output_call (operands);
7422   "
7423   ;; length is worst case, normally it is only two
7424   [(set_attr "length" "12")
7425    (set_attr "type" "call")]
7426 )
7427
7428 (define_insn "*call_mem"
7429   [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7430          (match_operand 1 "" ""))
7431    (use (match_operand 2 "" ""))
7432    (clobber (reg:SI LR_REGNUM))]
7433   "TARGET_ARM"
7434   "*
7435   return output_call_mem (operands);
7436   "
7437   [(set_attr "length" "12")
7438    (set_attr "type" "call")]
7439 )
7440
7441 (define_insn "*call_indirect"
7442   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7443          (match_operand 1 "" ""))
7444    (use (match_operand 2 "" ""))
7445    (clobber (reg:SI LR_REGNUM))]
7446   "TARGET_THUMB"
7447   "*
7448   {
7449     if (TARGET_CALLER_INTERWORKING)
7450       return \"bl\\t%__interwork_call_via_%0\";
7451     else
7452       return \"bl\\t%__call_via_%0\";
7453   }"
7454   [(set_attr "type" "call")]
7455 )
7456
7457 (define_insn "*call_value_indirect"
7458   [(set (match_operand 0 "" "")
7459         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7460               (match_operand 2 "" "")))
7461    (use (match_operand 3 "" ""))
7462    (clobber (reg:SI LR_REGNUM))]
7463   "TARGET_THUMB"
7464   "*
7465   {
7466     if (TARGET_CALLER_INTERWORKING)
7467       return \"bl\\t%__interwork_call_via_%1\";
7468     else
7469       return \"bl\\t%__call_via_%1\";
7470   }"
7471   [(set_attr "type" "call")]
7472 )
7473
7474 (define_expand "call_value"
7475   [(parallel [(set (match_operand       0 "" "")
7476                    (call (match_operand 1 "memory_operand" "")
7477                          (match_operand 2 "general_operand" "")))
7478               (use (match_operand 3 "" ""))
7479               (clobber (reg:SI LR_REGNUM))])]
7480   "TARGET_EITHER"
7481   "
7482   {
7483     rtx callee = XEXP (operands[1], 0);
7484     
7485     /* In an untyped call, we can get NULL for operand 2.  */
7486     if (operands[3] == 0)
7487       operands[3] = const0_rtx;
7488       
7489     /* See the comment in define_expand \"call\".  */
7490     if (GET_CODE (callee) != REG
7491         && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7492       XEXP (operands[1], 0) = force_reg (Pmode, callee);
7493   }"
7494 )
7495
7496 (define_insn "*call_value_reg"
7497   [(set (match_operand 0 "" "")
7498         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7499               (match_operand 2 "" "")))
7500    (use (match_operand 3 "" ""))
7501    (clobber (reg:SI LR_REGNUM))]
7502   "TARGET_ARM"
7503   "*
7504   return output_call (&operands[1]);
7505   "
7506   [(set_attr "length" "12")
7507    (set_attr "type" "call")]
7508 )
7509
7510 (define_insn "*call_value_mem"
7511   [(set (match_operand 0 "" "")
7512         (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7513               (match_operand 2 "" "")))
7514    (use (match_operand 3 "" ""))
7515    (clobber (reg:SI LR_REGNUM))]
7516   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7517   "*
7518   return output_call_mem (&operands[1]);
7519   "
7520   [(set_attr "length" "12")
7521    (set_attr "type" "call")]
7522 )
7523
7524 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7525 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7526
7527 (define_insn "*call_symbol"
7528   [(call (mem:SI (match_operand:SI 0 "" ""))
7529          (match_operand 1 "" ""))
7530    (use (match_operand 2 "" ""))
7531    (clobber (reg:SI LR_REGNUM))]
7532   "TARGET_ARM
7533    && (GET_CODE (operands[0]) == SYMBOL_REF)
7534    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7535   "*
7536   {
7537     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7538   }"
7539   [(set_attr "type" "call")]
7540 )
7541
7542 (define_insn "*call_value_symbol"
7543   [(set (match_operand 0 "s_register_operand" "")
7544         (call (mem:SI (match_operand:SI 1 "" ""))
7545         (match_operand:SI 2 "" "")))
7546    (use (match_operand 3 "" ""))
7547    (clobber (reg:SI LR_REGNUM))]
7548   "TARGET_ARM
7549    && (GET_CODE (operands[1]) == SYMBOL_REF)
7550    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7551   "*
7552   {
7553     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7554   }"
7555   [(set_attr "type" "call")]
7556 )
7557
7558 (define_insn "*call_insn"
7559   [(call (mem:SI (match_operand:SI 0 "" ""))
7560          (match_operand:SI 1 "" ""))
7561    (use (match_operand 2 "" ""))
7562    (clobber (reg:SI LR_REGNUM))]
7563   "TARGET_THUMB
7564    && GET_CODE (operands[0]) == SYMBOL_REF
7565    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7566   "bl\\t%a0"
7567   [(set_attr "length" "4")
7568    (set_attr "type" "call")]
7569 )
7570
7571 (define_insn "*call_value_insn"
7572   [(set (match_operand 0 "register_operand" "")
7573         (call (mem:SI (match_operand 1 "" ""))
7574               (match_operand 2 "" "")))
7575    (use (match_operand 3 "" ""))
7576    (clobber (reg:SI LR_REGNUM))]
7577   "TARGET_THUMB
7578    && GET_CODE (operands[1]) == SYMBOL_REF
7579    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7580   "bl\\t%a1"
7581   [(set_attr "length" "4")
7582    (set_attr "type" "call")]
7583 )
7584
7585 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7586 (define_expand "sibcall"
7587   [(parallel [(call (match_operand 0 "memory_operand" "")
7588                     (match_operand 1 "general_operand" ""))
7589               (return)
7590               (use (match_operand 2 "" ""))])]
7591   "TARGET_ARM"
7592   "
7593   {
7594     if (operands[2] == NULL_RTX)
7595       operands[2] = const0_rtx;
7596   }"
7597 )
7598
7599 (define_expand "sibcall_value"
7600   [(parallel [(set (match_operand 0 "register_operand" "")
7601                    (call (match_operand 1 "memory_operand" "")
7602                          (match_operand 2 "general_operand" "")))
7603               (return)
7604               (use (match_operand 3 "" ""))])]
7605   "TARGET_ARM"
7606   "
7607   {
7608     if (operands[3] == NULL_RTX)
7609       operands[3] = const0_rtx;
7610   }"
7611 )
7612
7613 (define_insn "*sibcall_insn"
7614  [(call (mem:SI (match_operand:SI 0 "" "X"))
7615         (match_operand 1 "" ""))
7616   (return)
7617   (use (match_operand 2 "" ""))]
7618   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7619   "*
7620   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7621   "
7622   [(set_attr "type" "call")]
7623 )
7624
7625 (define_insn "*sibcall_value_insn"
7626  [(set (match_operand 0 "s_register_operand" "")
7627        (call (mem:SI (match_operand:SI 1 "" "X"))
7628              (match_operand 2 "" "")))
7629   (return)
7630   (use (match_operand 3 "" ""))]
7631   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7632   "*
7633   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7634   "
7635   [(set_attr "type" "call")]
7636 )
7637
7638 ;; Often the return insn will be the same as loading from memory, so set attr
7639 (define_insn "return"
7640   [(return)]
7641   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7642   "*
7643   {
7644     if (arm_ccfsm_state == 2)
7645       {
7646         arm_ccfsm_state += 2;
7647         return \"\";
7648       }
7649     return output_return_instruction (const_true_rtx, TRUE, FALSE);
7650   }"
7651   [(set_attr "type" "load1")
7652    (set_attr "length" "12")
7653    (set_attr "predicable" "yes")]
7654 )
7655
7656 (define_insn "*cond_return"
7657   [(set (pc)
7658         (if_then_else (match_operator 0 "arm_comparison_operator"
7659                        [(match_operand 1 "cc_register" "") (const_int 0)])
7660                       (return)
7661                       (pc)))]
7662   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7663   "*
7664   {
7665     if (arm_ccfsm_state == 2)
7666       {
7667         arm_ccfsm_state += 2;
7668         return \"\";
7669       }
7670     return output_return_instruction (operands[0], TRUE, FALSE);
7671   }"
7672   [(set_attr "conds" "use")
7673    (set_attr "length" "12")
7674    (set_attr "type" "load1")]
7675 )
7676
7677 (define_insn "*cond_return_inverted"
7678   [(set (pc)
7679         (if_then_else (match_operator 0 "arm_comparison_operator"
7680                        [(match_operand 1 "cc_register" "") (const_int 0)])
7681                       (pc)
7682                       (return)))]
7683   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7684   "*
7685   {
7686     if (arm_ccfsm_state == 2)
7687       {
7688         arm_ccfsm_state += 2;
7689         return \"\";
7690       }
7691     return output_return_instruction (operands[0], TRUE, TRUE);
7692   }"
7693   [(set_attr "conds" "use")
7694    (set_attr "type" "load1")]
7695 )
7696
7697 ;; Generate a sequence of instructions to determine if the processor is
7698 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7699 ;; mask.
7700
7701 (define_expand "return_addr_mask"
7702   [(set (match_dup 1)
7703       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7704                        (const_int 0)))
7705    (set (match_operand:SI 0 "s_register_operand" "")
7706       (if_then_else:SI (eq (match_dup 1) (const_int 0))
7707                        (const_int -1)
7708                        (const_int 67108860)))] ; 0x03fffffc
7709   "TARGET_ARM"
7710   "
7711   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7712   ")
7713
7714 (define_insn "*check_arch2"
7715   [(set (match_operand:CC_NOOV 0 "cc_register" "")
7716       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7717                        (const_int 0)))]
7718   "TARGET_ARM"
7719   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7720   [(set_attr "length" "8")
7721    (set_attr "conds" "set")]
7722 )
7723
7724 ;; Call subroutine returning any type.
7725
7726 (define_expand "untyped_call"
7727   [(parallel [(call (match_operand 0 "" "")
7728                     (const_int 0))
7729               (match_operand 1 "" "")
7730               (match_operand 2 "" "")])]
7731   "TARGET_ARM"
7732   "
7733   {
7734     int i;
7735
7736     emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
7737
7738     for (i = 0; i < XVECLEN (operands[2], 0); i++)
7739       {
7740         rtx set = XVECEXP (operands[2], 0, i);
7741
7742         emit_move_insn (SET_DEST (set), SET_SRC (set));
7743       }
7744
7745     /* The optimizer does not know that the call sets the function value
7746        registers we stored in the result block.  We avoid problems by
7747        claiming that all hard registers are used and clobbered at this
7748        point.  */
7749     emit_insn (gen_blockage ());
7750
7751     DONE;
7752   }"
7753 )
7754
7755 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7756 ;; all of memory.  This blocks insns from being moved across this point.
7757
7758 (define_insn "blockage"
7759   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
7760   "TARGET_EITHER"
7761   ""
7762   [(set_attr "length" "0")
7763    (set_attr "type" "block")]
7764 )
7765
7766 (define_expand "casesi"
7767   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
7768    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
7769    (match_operand:SI 2 "const_int_operand" "")  ; total range
7770    (match_operand:SI 3 "" "")                   ; table label
7771    (match_operand:SI 4 "" "")]                  ; Out of range label
7772   "TARGET_ARM"
7773   "
7774   {
7775     rtx reg;
7776     if (operands[1] != const0_rtx)
7777       {
7778         reg = gen_reg_rtx (SImode);
7779
7780         emit_insn (gen_addsi3 (reg, operands[0],
7781                                GEN_INT (-INTVAL (operands[1]))));
7782         operands[0] = reg;
7783       }
7784
7785     if (!const_ok_for_arm (INTVAL (operands[2])))
7786       operands[2] = force_reg (SImode, operands[2]);
7787
7788     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
7789                                          operands[4]));
7790     DONE;
7791   }"
7792 )
7793
7794 ;; The USE in this pattern is needed to tell flow analysis that this is
7795 ;; a CASESI insn.  It has no other purpose.
7796 (define_insn "casesi_internal"
7797   [(parallel [(set (pc)
7798                (if_then_else
7799                 (leu (match_operand:SI 0 "s_register_operand" "r")
7800                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
7801                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
7802                                  (label_ref (match_operand 2 "" ""))))
7803                 (label_ref (match_operand 3 "" ""))))
7804               (clobber (reg:CC CC_REGNUM))
7805               (use (label_ref (match_dup 2)))])]
7806   "TARGET_ARM"
7807   "*
7808     if (flag_pic)
7809       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
7810     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
7811   "
7812   [(set_attr "conds" "clob")
7813    (set_attr "length" "12")]
7814 )
7815
7816 (define_expand "indirect_jump"
7817   [(set (pc)
7818         (match_operand:SI 0 "s_register_operand" ""))]
7819   "TARGET_EITHER"
7820   ""
7821 )
7822
7823 (define_insn "*arm_indirect_jump"
7824   [(set (pc)
7825         (match_operand:SI 0 "s_register_operand" "r"))]
7826   "TARGET_ARM"
7827   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
7828   [(set_attr "predicable" "yes")]
7829 )
7830
7831 ;; Although not supported by the define_expand above,
7832 ;; cse/combine may generate this form.
7833 (define_insn "*load_indirect_jump"
7834   [(set (pc)
7835         (match_operand:SI 0 "memory_operand" "m"))]
7836   "TARGET_ARM"
7837   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
7838   [(set_attr "type" "load1")
7839    (set_attr "pool_range" "4096")
7840    (set_attr "neg_pool_range" "4084")
7841    (set_attr "predicable" "yes")]
7842 )
7843
7844 (define_insn "*thumb_indirect_jump"
7845   [(set (pc)
7846         (match_operand:SI 0 "register_operand" "l*r"))]
7847   "TARGET_THUMB"
7848   "mov\\tpc, %0"
7849   [(set_attr "conds" "clob")
7850    (set_attr "length" "2")]
7851 )
7852
7853 \f
7854 ;; Misc insns
7855
7856 (define_insn "nop"
7857   [(const_int 0)]
7858   "TARGET_EITHER"
7859   "*
7860   if (TARGET_ARM)
7861     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
7862   return  \"mov\\tr8, r8\";
7863   "
7864   [(set (attr "length")
7865         (if_then_else (eq_attr "is_thumb" "yes")
7866                       (const_int 2)
7867                       (const_int 4)))]
7868 )
7869
7870 \f
7871 ;; Patterns to allow combination of arithmetic, cond code and shifts
7872
7873 (define_insn "*arith_shiftsi"
7874   [(set (match_operand:SI 0 "s_register_operand" "=r")
7875         (match_operator:SI 1 "shiftable_operator"
7876           [(match_operator:SI 3 "shift_operator"
7877              [(match_operand:SI 4 "s_register_operand" "r")
7878               (match_operand:SI 5 "reg_or_int_operand" "rI")])
7879            (match_operand:SI 2 "s_register_operand" "r")]))]
7880   "TARGET_ARM"
7881   "%i1%?\\t%0, %2, %4%S3"
7882   [(set_attr "predicable" "yes")
7883    (set_attr "shift" "4")
7884    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7885                       (const_string "alu_shift")
7886                       (const_string "alu_shift_reg")))]
7887 )
7888
7889 (define_split
7890   [(set (match_operand:SI 0 "s_register_operand" "")
7891         (match_operator:SI 1 "shiftable_operator"
7892          [(match_operator:SI 2 "shiftable_operator"
7893            [(match_operator:SI 3 "shift_operator"
7894              [(match_operand:SI 4 "s_register_operand" "")
7895               (match_operand:SI 5 "reg_or_int_operand" "")])
7896             (match_operand:SI 6 "s_register_operand" "")])
7897           (match_operand:SI 7 "arm_rhs_operand" "")]))
7898    (clobber (match_operand:SI 8 "s_register_operand" ""))]
7899   "TARGET_ARM"
7900   [(set (match_dup 8)
7901         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7902                          (match_dup 6)]))
7903    (set (match_dup 0)
7904         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
7905   "")
7906
7907 (define_insn "*arith_shiftsi_compare0"
7908   [(set (reg:CC_NOOV CC_REGNUM)
7909         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7910                           [(match_operator:SI 3 "shift_operator"
7911                             [(match_operand:SI 4 "s_register_operand" "r")
7912                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
7913                            (match_operand:SI 2 "s_register_operand" "r")])
7914                          (const_int 0)))
7915    (set (match_operand:SI 0 "s_register_operand" "=r")
7916         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7917                          (match_dup 2)]))]
7918   "TARGET_ARM"
7919   "%i1%?s\\t%0, %2, %4%S3"
7920   [(set_attr "conds" "set")
7921    (set_attr "shift" "4")
7922    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7923                       (const_string "alu_shift")
7924                       (const_string "alu_shift_reg")))]
7925 )
7926
7927 (define_insn "*arith_shiftsi_compare0_scratch"
7928   [(set (reg:CC_NOOV CC_REGNUM)
7929         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7930                           [(match_operator:SI 3 "shift_operator"
7931                             [(match_operand:SI 4 "s_register_operand" "r")
7932                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
7933                            (match_operand:SI 2 "s_register_operand" "r")])
7934                          (const_int 0)))
7935    (clobber (match_scratch:SI 0 "=r"))]
7936   "TARGET_ARM"
7937   "%i1%?s\\t%0, %2, %4%S3"
7938   [(set_attr "conds" "set")
7939    (set_attr "shift" "4")
7940    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7941                       (const_string "alu_shift")
7942                       (const_string "alu_shift_reg")))]
7943 )
7944
7945 (define_insn "*sub_shiftsi"
7946   [(set (match_operand:SI 0 "s_register_operand" "=r")
7947         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7948                   (match_operator:SI 2 "shift_operator"
7949                    [(match_operand:SI 3 "s_register_operand" "r")
7950                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
7951   "TARGET_ARM"
7952   "sub%?\\t%0, %1, %3%S2"
7953   [(set_attr "predicable" "yes")
7954    (set_attr "shift" "3")
7955    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7956                       (const_string "alu_shift")
7957                       (const_string "alu_shift_reg")))]
7958 )
7959
7960 (define_insn "*sub_shiftsi_compare0"
7961   [(set (reg:CC_NOOV CC_REGNUM)
7962         (compare:CC_NOOV
7963          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7964                    (match_operator:SI 2 "shift_operator"
7965                     [(match_operand:SI 3 "s_register_operand" "r")
7966                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7967          (const_int 0)))
7968    (set (match_operand:SI 0 "s_register_operand" "=r")
7969         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7970                                                  (match_dup 4)])))]
7971   "TARGET_ARM"
7972   "sub%?s\\t%0, %1, %3%S2"
7973   [(set_attr "conds" "set")
7974    (set_attr "shift" "3")
7975    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7976                       (const_string "alu_shift")
7977                       (const_string "alu_shift_reg")))]
7978 )
7979
7980 (define_insn "*sub_shiftsi_compare0_scratch"
7981   [(set (reg:CC_NOOV CC_REGNUM)
7982         (compare:CC_NOOV
7983          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7984                    (match_operator:SI 2 "shift_operator"
7985                     [(match_operand:SI 3 "s_register_operand" "r")
7986                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7987          (const_int 0)))
7988    (clobber (match_scratch:SI 0 "=r"))]
7989   "TARGET_ARM"
7990   "sub%?s\\t%0, %1, %3%S2"
7991   [(set_attr "conds" "set")
7992    (set_attr "shift" "3")
7993    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7994                       (const_string "alu_shift")
7995                       (const_string "alu_shift_reg")))]
7996 )
7997
7998 \f
7999
8000 (define_insn "*and_scc"
8001   [(set (match_operand:SI 0 "s_register_operand" "=r")
8002         (and:SI (match_operator:SI 1 "arm_comparison_operator"
8003                  [(match_operand 3 "cc_register" "") (const_int 0)])
8004                 (match_operand:SI 2 "s_register_operand" "r")))]
8005   "TARGET_ARM"
8006   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8007   [(set_attr "conds" "use")
8008    (set_attr "length" "8")]
8009 )
8010
8011 (define_insn "*ior_scc"
8012   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8013         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8014                  [(match_operand 3 "cc_register" "") (const_int 0)])
8015                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8016   "TARGET_ARM"
8017   "@
8018    orr%d2\\t%0, %1, #1
8019    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8020   [(set_attr "conds" "use")
8021    (set_attr "length" "4,8")]
8022 )
8023
8024 (define_insn "*compare_scc"
8025   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8026         (match_operator:SI 1 "arm_comparison_operator"
8027          [(match_operand:SI 2 "s_register_operand" "r,r")
8028           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8029    (clobber (reg:CC CC_REGNUM))]
8030   "TARGET_ARM"
8031   "*
8032     if (operands[3] == const0_rtx)
8033       {
8034         if (GET_CODE (operands[1]) == LT)
8035           return \"mov\\t%0, %2, lsr #31\";
8036
8037         if (GET_CODE (operands[1]) == GE)
8038           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8039
8040         if (GET_CODE (operands[1]) == EQ)
8041           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8042       }
8043
8044     if (GET_CODE (operands[1]) == NE)
8045       {
8046         if (which_alternative == 1)
8047           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8048         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8049       }
8050     if (which_alternative == 1)
8051       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8052     else
8053       output_asm_insn (\"cmp\\t%2, %3\", operands);
8054     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8055   "
8056   [(set_attr "conds" "clob")
8057    (set_attr "length" "12")]
8058 )
8059
8060 (define_insn "*cond_move"
8061   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8062         (if_then_else:SI (match_operator 3 "equality_operator"
8063                           [(match_operator 4 "arm_comparison_operator"
8064                             [(match_operand 5 "cc_register" "") (const_int 0)])
8065                            (const_int 0)])
8066                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8067                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8068   "TARGET_ARM"
8069   "*
8070     if (GET_CODE (operands[3]) == NE)
8071       {
8072         if (which_alternative != 1)
8073           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8074         if (which_alternative != 0)
8075           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8076         return \"\";
8077       }
8078     if (which_alternative != 0)
8079       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8080     if (which_alternative != 1)
8081       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8082     return \"\";
8083   "
8084   [(set_attr "conds" "use")
8085    (set_attr "length" "4,4,8")]
8086 )
8087
8088 (define_insn "*cond_arith"
8089   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8090         (match_operator:SI 5 "shiftable_operator" 
8091          [(match_operator:SI 4 "arm_comparison_operator"
8092            [(match_operand:SI 2 "s_register_operand" "r,r")
8093             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8094           (match_operand:SI 1 "s_register_operand" "0,?r")]))
8095    (clobber (reg:CC CC_REGNUM))]
8096   "TARGET_ARM"
8097   "*
8098     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8099       return \"%i5\\t%0, %1, %2, lsr #31\";
8100
8101     output_asm_insn (\"cmp\\t%2, %3\", operands);
8102     if (GET_CODE (operands[5]) == AND)
8103       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8104     else if (GET_CODE (operands[5]) == MINUS)
8105       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8106     else if (which_alternative != 0)
8107       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8108     return \"%i5%d4\\t%0, %1, #1\";
8109   "
8110   [(set_attr "conds" "clob")
8111    (set_attr "length" "12")]
8112 )
8113
8114 (define_insn "*cond_sub"
8115   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8116         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8117                   (match_operator:SI 4 "arm_comparison_operator"
8118                    [(match_operand:SI 2 "s_register_operand" "r,r")
8119                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8120    (clobber (reg:CC CC_REGNUM))]
8121   "TARGET_ARM"
8122   "*
8123     output_asm_insn (\"cmp\\t%2, %3\", operands);
8124     if (which_alternative != 0)
8125       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8126     return \"sub%d4\\t%0, %1, #1\";
8127   "
8128   [(set_attr "conds" "clob")
8129    (set_attr "length" "8,12")]
8130 )
8131
8132 (define_insn "*cmp_ite0"
8133   [(set (match_operand 6 "dominant_cc_register" "")
8134         (compare
8135          (if_then_else:SI
8136           (match_operator 4 "arm_comparison_operator"
8137            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8138             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8139           (match_operator:SI 5 "arm_comparison_operator"
8140            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8141             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8142           (const_int 0))
8143          (const_int 0)))]
8144   "TARGET_ARM"
8145   "*
8146   {
8147     static const char * const opcodes[4][2] =
8148     {
8149       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8150        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8151       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8152        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8153       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8154        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8155       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8156        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8157     };
8158     int swap =
8159       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8160
8161     return opcodes[which_alternative][swap];
8162   }"
8163   [(set_attr "conds" "set")
8164    (set_attr "length" "8")]
8165 )
8166
8167 (define_insn "*cmp_ite1"
8168   [(set (match_operand 6 "dominant_cc_register" "")
8169         (compare
8170          (if_then_else:SI
8171           (match_operator 4 "arm_comparison_operator"
8172            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8173             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8174           (match_operator:SI 5 "arm_comparison_operator"
8175            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8176             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8177           (const_int 1))
8178          (const_int 0)))]
8179   "TARGET_ARM"
8180   "*
8181   {
8182     static const char * const opcodes[4][2] =
8183     {
8184       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8185        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8186       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8187        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8188       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8189        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8190       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8191        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8192     };
8193     int swap =
8194       comparison_dominates_p (GET_CODE (operands[5]),
8195                               reverse_condition (GET_CODE (operands[4])));
8196
8197     return opcodes[which_alternative][swap];
8198   }"
8199   [(set_attr "conds" "set")
8200    (set_attr "length" "8")]
8201 )
8202
8203 (define_insn "*cmp_and"
8204   [(set (match_operand 6 "dominant_cc_register" "")
8205         (compare
8206          (and:SI
8207           (match_operator 4 "arm_comparison_operator"
8208            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8209             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8210           (match_operator:SI 5 "arm_comparison_operator"
8211            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8212             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8213          (const_int 0)))]
8214   "TARGET_ARM"
8215   "*
8216   {
8217     static const char *const opcodes[4][2] =
8218     {
8219       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8220        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8221       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8222        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8223       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8224        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8225       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8226        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8227     };
8228     int swap =
8229       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8230
8231     return opcodes[which_alternative][swap];
8232   }"
8233   [(set_attr "conds" "set")
8234    (set_attr "predicable" "no")
8235    (set_attr "length" "8")]
8236 )
8237
8238 (define_insn "*cmp_ior"
8239   [(set (match_operand 6 "dominant_cc_register" "")
8240         (compare
8241          (ior:SI
8242           (match_operator 4 "arm_comparison_operator"
8243            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8244             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8245           (match_operator:SI 5 "arm_comparison_operator"
8246            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8247             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8248          (const_int 0)))]
8249   "TARGET_ARM"
8250   "*
8251 {
8252   static const char *const opcodes[4][2] =
8253   {
8254     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8255      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8256     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8257      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8258     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8259      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8260     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8261      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8262   };
8263   int swap =
8264     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8265
8266   return opcodes[which_alternative][swap];
8267 }
8268 "
8269   [(set_attr "conds" "set")
8270    (set_attr "length" "8")]
8271 )
8272
8273 (define_insn_and_split "*ior_scc_scc"
8274   [(set (match_operand:SI 0 "s_register_operand" "=r")
8275         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8276                  [(match_operand:SI 1 "s_register_operand" "r")
8277                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8278                 (match_operator:SI 6 "arm_comparison_operator"
8279                  [(match_operand:SI 4 "s_register_operand" "r")
8280                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8281    (clobber (reg:CC CC_REGNUM))]
8282   "TARGET_ARM
8283    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8284        != CCmode)"
8285   "#"
8286   "TARGET_ARM && reload_completed"
8287   [(set (match_dup 7)
8288         (compare
8289          (ior:SI
8290           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8291           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8292          (const_int 0)))
8293    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8294   "operands[7]
8295      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8296                                                   DOM_CC_X_OR_Y),
8297                     CC_REGNUM);"
8298   [(set_attr "conds" "clob")
8299    (set_attr "length" "16")])
8300
8301 ; If the above pattern is followed by a CMP insn, then the compare is 
8302 ; redundant, since we can rework the conditional instruction that follows.
8303 (define_insn_and_split "*ior_scc_scc_cmp"
8304   [(set (match_operand 0 "dominant_cc_register" "")
8305         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8306                           [(match_operand:SI 1 "s_register_operand" "r")
8307                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8308                          (match_operator:SI 6 "arm_comparison_operator"
8309                           [(match_operand:SI 4 "s_register_operand" "r")
8310                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8311                  (const_int 0)))
8312    (set (match_operand:SI 7 "s_register_operand" "=r")
8313         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8314                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8315   "TARGET_ARM"
8316   "#"
8317   "TARGET_ARM && reload_completed"
8318   [(set (match_dup 0)
8319         (compare
8320          (ior:SI
8321           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8322           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8323          (const_int 0)))
8324    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8325   ""
8326   [(set_attr "conds" "set")
8327    (set_attr "length" "16")])
8328
8329 (define_insn_and_split "*and_scc_scc"
8330   [(set (match_operand:SI 0 "s_register_operand" "=r")
8331         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8332                  [(match_operand:SI 1 "s_register_operand" "r")
8333                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8334                 (match_operator:SI 6 "arm_comparison_operator"
8335                  [(match_operand:SI 4 "s_register_operand" "r")
8336                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8337    (clobber (reg:CC CC_REGNUM))]
8338   "TARGET_ARM
8339    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8340        != CCmode)"
8341   "#"
8342   "TARGET_ARM && reload_completed
8343    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8344        != CCmode)"
8345   [(set (match_dup 7)
8346         (compare
8347          (and:SI
8348           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8349           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8350          (const_int 0)))
8351    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8352   "operands[7]
8353      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8354                                                   DOM_CC_X_AND_Y),
8355                     CC_REGNUM);"
8356   [(set_attr "conds" "clob")
8357    (set_attr "length" "16")])
8358
8359 ; If the above pattern is followed by a CMP insn, then the compare is 
8360 ; redundant, since we can rework the conditional instruction that follows.
8361 (define_insn_and_split "*and_scc_scc_cmp"
8362   [(set (match_operand 0 "dominant_cc_register" "")
8363         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8364                           [(match_operand:SI 1 "s_register_operand" "r")
8365                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8366                          (match_operator:SI 6 "arm_comparison_operator"
8367                           [(match_operand:SI 4 "s_register_operand" "r")
8368                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8369                  (const_int 0)))
8370    (set (match_operand:SI 7 "s_register_operand" "=r")
8371         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8372                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8373   "TARGET_ARM"
8374   "#"
8375   "TARGET_ARM && reload_completed"
8376   [(set (match_dup 0)
8377         (compare
8378          (and:SI
8379           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8380           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8381          (const_int 0)))
8382    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8383   ""
8384   [(set_attr "conds" "set")
8385    (set_attr "length" "16")])
8386
8387 ;; If there is no dominance in the comparison, then we can still save an
8388 ;; instruction in the AND case, since we can know that the second compare
8389 ;; need only zero the value if false (if true, then the value is already
8390 ;; correct).
8391 (define_insn_and_split "*and_scc_scc_nodom"
8392   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8393         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8394                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
8395                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8396                 (match_operator:SI 6 "arm_comparison_operator"
8397                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
8398                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8399    (clobber (reg:CC CC_REGNUM))]
8400   "TARGET_ARM
8401    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8402        == CCmode)"
8403   "#"
8404   "TARGET_ARM && reload_completed"
8405   [(parallel [(set (match_dup 0)
8406                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8407               (clobber (reg:CC CC_REGNUM))])
8408    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8409    (set (match_dup 0)
8410         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8411                          (match_dup 0)
8412                          (const_int 0)))]
8413   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8414                                               operands[4], operands[5]),
8415                               CC_REGNUM);
8416    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8417                                   operands[5]);"
8418   [(set_attr "conds" "clob")
8419    (set_attr "length" "20")])
8420
8421 (define_split
8422   [(set (reg:CC_NOOV CC_REGNUM)
8423         (compare:CC_NOOV (ior:SI
8424                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8425                                   (const_int 1))
8426                           (match_operator:SI 1 "comparison_operator"
8427                            [(match_operand:SI 2 "s_register_operand" "")
8428                             (match_operand:SI 3 "arm_add_operand" "")]))
8429                          (const_int 0)))
8430    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8431   "TARGET_ARM"
8432   [(set (match_dup 4)
8433         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8434                 (match_dup 0)))
8435    (set (reg:CC_NOOV CC_REGNUM)
8436         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8437                          (const_int 0)))]
8438   "")
8439
8440 (define_split
8441   [(set (reg:CC_NOOV CC_REGNUM)
8442         (compare:CC_NOOV (ior:SI
8443                           (match_operator:SI 1 "comparison_operator"
8444                            [(match_operand:SI 2 "s_register_operand" "")
8445                             (match_operand:SI 3 "arm_add_operand" "")])
8446                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8447                                   (const_int 1)))
8448                          (const_int 0)))
8449    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8450   "TARGET_ARM"
8451   [(set (match_dup 4)
8452         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8453                 (match_dup 0)))
8454    (set (reg:CC_NOOV CC_REGNUM)
8455         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8456                          (const_int 0)))]
8457   "")
8458
8459 (define_insn "*negscc"
8460   [(set (match_operand:SI 0 "s_register_operand" "=r")
8461         (neg:SI (match_operator 3 "arm_comparison_operator"
8462                  [(match_operand:SI 1 "s_register_operand" "r")
8463                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8464    (clobber (reg:CC CC_REGNUM))]
8465   "TARGET_ARM"
8466   "*
8467   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8468     return \"mov\\t%0, %1, asr #31\";
8469
8470   if (GET_CODE (operands[3]) == NE)
8471     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8472
8473   if (GET_CODE (operands[3]) == GT)
8474     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8475
8476   output_asm_insn (\"cmp\\t%1, %2\", operands);
8477   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8478   return \"mvn%d3\\t%0, #0\";
8479   "
8480   [(set_attr "conds" "clob")
8481    (set_attr "length" "12")]
8482 )
8483
8484 (define_insn "movcond"
8485   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8486         (if_then_else:SI
8487          (match_operator 5 "arm_comparison_operator"
8488           [(match_operand:SI 3 "s_register_operand" "r,r,r")
8489            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8490          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8491          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8492    (clobber (reg:CC CC_REGNUM))]
8493   "TARGET_ARM"
8494   "*
8495   if (GET_CODE (operands[5]) == LT
8496       && (operands[4] == const0_rtx))
8497     {
8498       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8499         {
8500           if (operands[2] == const0_rtx)
8501             return \"and\\t%0, %1, %3, asr #31\";
8502           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8503         }
8504       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8505         {
8506           if (operands[1] == const0_rtx)
8507             return \"bic\\t%0, %2, %3, asr #31\";
8508           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8509         }
8510       /* The only case that falls through to here is when both ops 1 & 2
8511          are constants.  */
8512     }
8513
8514   if (GET_CODE (operands[5]) == GE
8515       && (operands[4] == const0_rtx))
8516     {
8517       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8518         {
8519           if (operands[2] == const0_rtx)
8520             return \"bic\\t%0, %1, %3, asr #31\";
8521           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8522         }
8523       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8524         {
8525           if (operands[1] == const0_rtx)
8526             return \"and\\t%0, %2, %3, asr #31\";
8527           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8528         }
8529       /* The only case that falls through to here is when both ops 1 & 2
8530          are constants.  */
8531     }
8532   if (GET_CODE (operands[4]) == CONST_INT
8533       && !const_ok_for_arm (INTVAL (operands[4])))
8534     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8535   else
8536     output_asm_insn (\"cmp\\t%3, %4\", operands);
8537   if (which_alternative != 0)
8538     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8539   if (which_alternative != 1)
8540     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8541   return \"\";
8542   "
8543   [(set_attr "conds" "clob")
8544    (set_attr "length" "8,8,12")]
8545 )
8546
8547 (define_insn "*ifcompare_plus_move"
8548   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8549         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8550                           [(match_operand:SI 4 "s_register_operand" "r,r")
8551                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8552                          (plus:SI
8553                           (match_operand:SI 2 "s_register_operand" "r,r")
8554                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8555                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8556    (clobber (reg:CC CC_REGNUM))]
8557   "TARGET_ARM"
8558   "#"
8559   [(set_attr "conds" "clob")
8560    (set_attr "length" "8,12")]
8561 )
8562
8563 (define_insn "*if_plus_move"
8564   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8565         (if_then_else:SI
8566          (match_operator 4 "arm_comparison_operator"
8567           [(match_operand 5 "cc_register" "") (const_int 0)])
8568          (plus:SI
8569           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8570           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8571          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8572   "TARGET_ARM"
8573   "@
8574    add%d4\\t%0, %2, %3
8575    sub%d4\\t%0, %2, #%n3
8576    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8577    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8578   [(set_attr "conds" "use")
8579    (set_attr "length" "4,4,8,8")
8580    (set_attr "type" "*,*,*,*")]
8581 )
8582
8583 (define_insn "*ifcompare_move_plus"
8584   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8585         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8586                           [(match_operand:SI 4 "s_register_operand" "r,r")
8587                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8588                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8589                          (plus:SI
8590                           (match_operand:SI 2 "s_register_operand" "r,r")
8591                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8592    (clobber (reg:CC CC_REGNUM))]
8593   "TARGET_ARM"
8594   "#"
8595   [(set_attr "conds" "clob")
8596    (set_attr "length" "8,12")]
8597 )
8598
8599 (define_insn "*if_move_plus"
8600   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8601         (if_then_else:SI
8602          (match_operator 4 "arm_comparison_operator"
8603           [(match_operand 5 "cc_register" "") (const_int 0)])
8604          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8605          (plus:SI
8606           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8607           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8608   "TARGET_ARM"
8609   "@
8610    add%D4\\t%0, %2, %3
8611    sub%D4\\t%0, %2, #%n3
8612    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8613    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8614   [(set_attr "conds" "use")
8615    (set_attr "length" "4,4,8,8")
8616    (set_attr "type" "*,*,*,*")]
8617 )
8618
8619 (define_insn "*ifcompare_arith_arith"
8620   [(set (match_operand:SI 0 "s_register_operand" "=r")
8621         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8622                           [(match_operand:SI 5 "s_register_operand" "r")
8623                            (match_operand:SI 6 "arm_add_operand" "rIL")])
8624                          (match_operator:SI 8 "shiftable_operator"
8625                           [(match_operand:SI 1 "s_register_operand" "r")
8626                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8627                          (match_operator:SI 7 "shiftable_operator"
8628                           [(match_operand:SI 3 "s_register_operand" "r")
8629                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8630    (clobber (reg:CC CC_REGNUM))]
8631   "TARGET_ARM"
8632   "#"
8633   [(set_attr "conds" "clob")
8634    (set_attr "length" "12")]
8635 )
8636
8637 (define_insn "*if_arith_arith"
8638   [(set (match_operand:SI 0 "s_register_operand" "=r")
8639         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8640                           [(match_operand 8 "cc_register" "") (const_int 0)])
8641                          (match_operator:SI 6 "shiftable_operator"
8642                           [(match_operand:SI 1 "s_register_operand" "r")
8643                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8644                          (match_operator:SI 7 "shiftable_operator"
8645                           [(match_operand:SI 3 "s_register_operand" "r")
8646                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8647   "TARGET_ARM"
8648   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8649   [(set_attr "conds" "use")
8650    (set_attr "length" "8")]
8651 )
8652
8653 (define_insn "*ifcompare_arith_move"
8654   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8655         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8656                           [(match_operand:SI 2 "s_register_operand" "r,r")
8657                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8658                          (match_operator:SI 7 "shiftable_operator"
8659                           [(match_operand:SI 4 "s_register_operand" "r,r")
8660                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8661                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8662    (clobber (reg:CC CC_REGNUM))]
8663   "TARGET_ARM"
8664   "*
8665   /* If we have an operation where (op x 0) is the identity operation and
8666      the conditional operator is LT or GE and we are comparing against zero and
8667      everything is in registers then we can do this in two instructions.  */
8668   if (operands[3] == const0_rtx
8669       && GET_CODE (operands[7]) != AND
8670       && GET_CODE (operands[5]) == REG
8671       && GET_CODE (operands[1]) == REG 
8672       && REGNO (operands[1]) == REGNO (operands[4])
8673       && REGNO (operands[4]) != REGNO (operands[0]))
8674     {
8675       if (GET_CODE (operands[6]) == LT)
8676         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8677       else if (GET_CODE (operands[6]) == GE)
8678         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8679     }
8680   if (GET_CODE (operands[3]) == CONST_INT
8681       && !const_ok_for_arm (INTVAL (operands[3])))
8682     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8683   else
8684     output_asm_insn (\"cmp\\t%2, %3\", operands);
8685   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8686   if (which_alternative != 0)
8687     return \"mov%D6\\t%0, %1\";
8688   return \"\";
8689   "
8690   [(set_attr "conds" "clob")
8691    (set_attr "length" "8,12")]
8692 )
8693
8694 (define_insn "*if_arith_move"
8695   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8696         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8697                           [(match_operand 6 "cc_register" "") (const_int 0)])
8698                          (match_operator:SI 5 "shiftable_operator"
8699                           [(match_operand:SI 2 "s_register_operand" "r,r")
8700                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8701                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8702   "TARGET_ARM"
8703   "@
8704    %I5%d4\\t%0, %2, %3
8705    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8706   [(set_attr "conds" "use")
8707    (set_attr "length" "4,8")
8708    (set_attr "type" "*,*")]
8709 )
8710
8711 (define_insn "*ifcompare_move_arith"
8712   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8713         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8714                           [(match_operand:SI 4 "s_register_operand" "r,r")
8715                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8716                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8717                          (match_operator:SI 7 "shiftable_operator"
8718                           [(match_operand:SI 2 "s_register_operand" "r,r")
8719                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8720    (clobber (reg:CC CC_REGNUM))]
8721   "TARGET_ARM"
8722   "*
8723   /* If we have an operation where (op x 0) is the identity operation and
8724      the conditional operator is LT or GE and we are comparing against zero and
8725      everything is in registers then we can do this in two instructions */
8726   if (operands[5] == const0_rtx
8727       && GET_CODE (operands[7]) != AND
8728       && GET_CODE (operands[3]) == REG
8729       && GET_CODE (operands[1]) == REG 
8730       && REGNO (operands[1]) == REGNO (operands[2])
8731       && REGNO (operands[2]) != REGNO (operands[0]))
8732     {
8733       if (GET_CODE (operands[6]) == GE)
8734         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8735       else if (GET_CODE (operands[6]) == LT)
8736         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8737     }
8738
8739   if (GET_CODE (operands[5]) == CONST_INT
8740       && !const_ok_for_arm (INTVAL (operands[5])))
8741     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
8742   else
8743     output_asm_insn (\"cmp\\t%4, %5\", operands);
8744
8745   if (which_alternative != 0)
8746     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
8747   return \"%I7%D6\\t%0, %2, %3\";
8748   "
8749   [(set_attr "conds" "clob")
8750    (set_attr "length" "8,12")]
8751 )
8752
8753 (define_insn "*if_move_arith"
8754   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8755         (if_then_else:SI
8756          (match_operator 4 "arm_comparison_operator"
8757           [(match_operand 6 "cc_register" "") (const_int 0)])
8758          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8759          (match_operator:SI 5 "shiftable_operator"
8760           [(match_operand:SI 2 "s_register_operand" "r,r")
8761            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
8762   "TARGET_ARM"
8763   "@
8764    %I5%D4\\t%0, %2, %3
8765    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8766   [(set_attr "conds" "use")
8767    (set_attr "length" "4,8")
8768    (set_attr "type" "*,*")]
8769 )
8770
8771 (define_insn "*ifcompare_move_not"
8772   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8773         (if_then_else:SI
8774          (match_operator 5 "arm_comparison_operator"
8775           [(match_operand:SI 3 "s_register_operand" "r,r")
8776            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8777          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8778          (not:SI
8779           (match_operand:SI 2 "s_register_operand" "r,r"))))
8780    (clobber (reg:CC CC_REGNUM))]
8781   "TARGET_ARM"
8782   "#"
8783   [(set_attr "conds" "clob")
8784    (set_attr "length" "8,12")]
8785 )
8786
8787 (define_insn "*if_move_not"
8788   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8789         (if_then_else:SI
8790          (match_operator 4 "arm_comparison_operator"
8791           [(match_operand 3 "cc_register" "") (const_int 0)])
8792          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8793          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8794   "TARGET_ARM"
8795   "@
8796    mvn%D4\\t%0, %2
8797    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
8798    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8799   [(set_attr "conds" "use")
8800    (set_attr "length" "4,8,8")]
8801 )
8802
8803 (define_insn "*ifcompare_not_move"
8804   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8805         (if_then_else:SI 
8806          (match_operator 5 "arm_comparison_operator"
8807           [(match_operand:SI 3 "s_register_operand" "r,r")
8808            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8809          (not:SI
8810           (match_operand:SI 2 "s_register_operand" "r,r"))
8811          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8812    (clobber (reg:CC CC_REGNUM))]
8813   "TARGET_ARM"
8814   "#"
8815   [(set_attr "conds" "clob")
8816    (set_attr "length" "8,12")]
8817 )
8818
8819 (define_insn "*if_not_move"
8820   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8821         (if_then_else:SI
8822          (match_operator 4 "arm_comparison_operator"
8823           [(match_operand 3 "cc_register" "") (const_int 0)])
8824          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8825          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8826   "TARGET_ARM"
8827   "@
8828    mvn%d4\\t%0, %2
8829    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
8830    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8831   [(set_attr "conds" "use")
8832    (set_attr "length" "4,8,8")]
8833 )
8834
8835 (define_insn "*ifcompare_shift_move"
8836   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8837         (if_then_else:SI
8838          (match_operator 6 "arm_comparison_operator"
8839           [(match_operand:SI 4 "s_register_operand" "r,r")
8840            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8841          (match_operator:SI 7 "shift_operator"
8842           [(match_operand:SI 2 "s_register_operand" "r,r")
8843            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
8844          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8845    (clobber (reg:CC CC_REGNUM))]
8846   "TARGET_ARM"
8847   "#"
8848   [(set_attr "conds" "clob")
8849    (set_attr "length" "8,12")]
8850 )
8851
8852 (define_insn "*if_shift_move"
8853   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8854         (if_then_else:SI
8855          (match_operator 5 "arm_comparison_operator"
8856           [(match_operand 6 "cc_register" "") (const_int 0)])
8857          (match_operator:SI 4 "shift_operator"
8858           [(match_operand:SI 2 "s_register_operand" "r,r,r")
8859            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
8860          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8861   "TARGET_ARM"
8862   "@
8863    mov%d5\\t%0, %2%S4
8864    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
8865    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8866   [(set_attr "conds" "use")
8867    (set_attr "shift" "2")
8868    (set_attr "length" "4,8,8")
8869    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
8870                       (const_string "alu_shift")
8871                       (const_string "alu_shift_reg")))]
8872 )
8873
8874 (define_insn "*ifcompare_move_shift"
8875   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8876         (if_then_else:SI
8877          (match_operator 6 "arm_comparison_operator"
8878           [(match_operand:SI 4 "s_register_operand" "r,r")
8879            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8880          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8881          (match_operator:SI 7 "shift_operator"
8882           [(match_operand:SI 2 "s_register_operand" "r,r")
8883            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
8884    (clobber (reg:CC CC_REGNUM))]
8885   "TARGET_ARM"
8886   "#"
8887   [(set_attr "conds" "clob")
8888    (set_attr "length" "8,12")]
8889 )
8890
8891 (define_insn "*if_move_shift"
8892   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8893         (if_then_else:SI
8894          (match_operator 5 "arm_comparison_operator"
8895           [(match_operand 6 "cc_register" "") (const_int 0)])
8896          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8897          (match_operator:SI 4 "shift_operator"
8898           [(match_operand:SI 2 "s_register_operand" "r,r,r")
8899            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
8900   "TARGET_ARM"
8901   "@
8902    mov%D5\\t%0, %2%S4
8903    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
8904    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8905   [(set_attr "conds" "use")
8906    (set_attr "shift" "2")
8907    (set_attr "length" "4,8,8")
8908    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
8909                       (const_string "alu_shift")
8910                       (const_string "alu_shift_reg")))]
8911 )
8912
8913 (define_insn "*ifcompare_shift_shift"
8914   [(set (match_operand:SI 0 "s_register_operand" "=r")
8915         (if_then_else:SI
8916          (match_operator 7 "arm_comparison_operator"
8917           [(match_operand:SI 5 "s_register_operand" "r")
8918            (match_operand:SI 6 "arm_add_operand" "rIL")])
8919          (match_operator:SI 8 "shift_operator"
8920           [(match_operand:SI 1 "s_register_operand" "r")
8921            (match_operand:SI 2 "arm_rhs_operand" "rM")])
8922          (match_operator:SI 9 "shift_operator"
8923           [(match_operand:SI 3 "s_register_operand" "r")
8924            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
8925    (clobber (reg:CC CC_REGNUM))]
8926   "TARGET_ARM"
8927   "#"
8928   [(set_attr "conds" "clob")
8929    (set_attr "length" "12")]
8930 )
8931
8932 (define_insn "*if_shift_shift"
8933   [(set (match_operand:SI 0 "s_register_operand" "=r")
8934         (if_then_else:SI
8935          (match_operator 5 "arm_comparison_operator"
8936           [(match_operand 8 "cc_register" "") (const_int 0)])
8937          (match_operator:SI 6 "shift_operator"
8938           [(match_operand:SI 1 "s_register_operand" "r")
8939            (match_operand:SI 2 "arm_rhs_operand" "rM")])
8940          (match_operator:SI 7 "shift_operator"
8941           [(match_operand:SI 3 "s_register_operand" "r")
8942            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
8943   "TARGET_ARM"
8944   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8945   [(set_attr "conds" "use")
8946    (set_attr "shift" "1")
8947    (set_attr "length" "8")
8948    (set (attr "type") (if_then_else
8949                         (and (match_operand 2 "const_int_operand" "")
8950                              (match_operand 4 "const_int_operand" ""))
8951                       (const_string "alu_shift")
8952                       (const_string "alu_shift_reg")))]
8953 )
8954
8955 (define_insn "*ifcompare_not_arith"
8956   [(set (match_operand:SI 0 "s_register_operand" "=r")
8957         (if_then_else:SI
8958          (match_operator 6 "arm_comparison_operator"
8959           [(match_operand:SI 4 "s_register_operand" "r")
8960            (match_operand:SI 5 "arm_add_operand" "rIL")])
8961          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8962          (match_operator:SI 7 "shiftable_operator"
8963           [(match_operand:SI 2 "s_register_operand" "r")
8964            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
8965    (clobber (reg:CC CC_REGNUM))]
8966   "TARGET_ARM"
8967   "#"
8968   [(set_attr "conds" "clob")
8969    (set_attr "length" "12")]
8970 )
8971
8972 (define_insn "*if_not_arith"
8973   [(set (match_operand:SI 0 "s_register_operand" "=r")
8974         (if_then_else:SI
8975          (match_operator 5 "arm_comparison_operator"
8976           [(match_operand 4 "cc_register" "") (const_int 0)])
8977          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8978          (match_operator:SI 6 "shiftable_operator"
8979           [(match_operand:SI 2 "s_register_operand" "r")
8980            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
8981   "TARGET_ARM"
8982   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8983   [(set_attr "conds" "use")
8984    (set_attr "length" "8")]
8985 )
8986
8987 (define_insn "*ifcompare_arith_not"
8988   [(set (match_operand:SI 0 "s_register_operand" "=r")
8989         (if_then_else:SI
8990          (match_operator 6 "arm_comparison_operator"
8991           [(match_operand:SI 4 "s_register_operand" "r")
8992            (match_operand:SI 5 "arm_add_operand" "rIL")])
8993          (match_operator:SI 7 "shiftable_operator"
8994           [(match_operand:SI 2 "s_register_operand" "r")
8995            (match_operand:SI 3 "arm_rhs_operand" "rI")])
8996          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
8997    (clobber (reg:CC CC_REGNUM))]
8998   "TARGET_ARM"
8999   "#"
9000   [(set_attr "conds" "clob")
9001    (set_attr "length" "12")]
9002 )
9003
9004 (define_insn "*if_arith_not"
9005   [(set (match_operand:SI 0 "s_register_operand" "=r")
9006         (if_then_else:SI
9007          (match_operator 5 "arm_comparison_operator"
9008           [(match_operand 4 "cc_register" "") (const_int 0)])
9009          (match_operator:SI 6 "shiftable_operator"
9010           [(match_operand:SI 2 "s_register_operand" "r")
9011            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9012          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9013   "TARGET_ARM"
9014   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9015   [(set_attr "conds" "use")
9016    (set_attr "length" "8")]
9017 )
9018
9019 (define_insn "*ifcompare_neg_move"
9020   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9021         (if_then_else:SI
9022          (match_operator 5 "arm_comparison_operator"
9023           [(match_operand:SI 3 "s_register_operand" "r,r")
9024            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9025          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9026          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9027    (clobber (reg:CC CC_REGNUM))]
9028   "TARGET_ARM"
9029   "#"
9030   [(set_attr "conds" "clob")
9031    (set_attr "length" "8,12")]
9032 )
9033
9034 (define_insn "*if_neg_move"
9035   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9036         (if_then_else:SI
9037          (match_operator 4 "arm_comparison_operator"
9038           [(match_operand 3 "cc_register" "") (const_int 0)])
9039          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9040          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9041   "TARGET_ARM"
9042   "@
9043    rsb%d4\\t%0, %2, #0
9044    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9045    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9046   [(set_attr "conds" "use")
9047    (set_attr "length" "4,8,8")]
9048 )
9049
9050 (define_insn "*ifcompare_move_neg"
9051   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9052         (if_then_else:SI
9053          (match_operator 5 "arm_comparison_operator"
9054           [(match_operand:SI 3 "s_register_operand" "r,r")
9055            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9056          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9057          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9058    (clobber (reg:CC CC_REGNUM))]
9059   "TARGET_ARM"
9060   "#"
9061   [(set_attr "conds" "clob")
9062    (set_attr "length" "8,12")]
9063 )
9064
9065 (define_insn "*if_move_neg"
9066   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9067         (if_then_else:SI
9068          (match_operator 4 "arm_comparison_operator"
9069           [(match_operand 3 "cc_register" "") (const_int 0)])
9070          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9071          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9072   "TARGET_ARM"
9073   "@
9074    rsb%D4\\t%0, %2, #0
9075    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9076    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9077   [(set_attr "conds" "use")
9078    (set_attr "length" "4,8,8")]
9079 )
9080
9081 (define_insn "*arith_adjacentmem"
9082   [(set (match_operand:SI 0 "s_register_operand" "=r")
9083         (match_operator:SI 1 "shiftable_operator"
9084          [(match_operand:SI 2 "memory_operand" "m")
9085           (match_operand:SI 3 "memory_operand" "m")]))
9086    (clobber (match_scratch:SI 4 "=r"))]
9087   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9088   "*
9089   {
9090     rtx ldm[3];
9091     rtx arith[4];
9092     int val1 = 0, val2 = 0;
9093
9094     if (REGNO (operands[0]) > REGNO (operands[4]))
9095       {
9096         ldm[1] = operands[4];
9097         ldm[2] = operands[0];
9098       }
9099     else
9100       {
9101         ldm[1] = operands[0];
9102         ldm[2] = operands[4];
9103       }
9104     if (GET_CODE (XEXP (operands[2], 0)) != REG)
9105       val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
9106     if (GET_CODE (XEXP (operands[3], 0)) != REG)
9107       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9108     arith[0] = operands[0];
9109     arith[3] = operands[1];
9110     if (val1 < val2)
9111       {
9112         arith[1] = ldm[1];
9113         arith[2] = ldm[2];
9114       }
9115     else
9116       {
9117         arith[1] = ldm[2];
9118         arith[2] = ldm[1];
9119       }
9120    if (val1 && val2)
9121       {
9122         rtx ops[3];
9123         ldm[0] = ops[0] = operands[4];
9124         ops[1] = XEXP (XEXP (operands[2], 0), 0);
9125         ops[2] = XEXP (XEXP (operands[2], 0), 1);
9126         output_add_immediate (ops);
9127         if (val1 < val2)
9128           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9129         else
9130           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9131       }
9132     else if (val1)
9133       {
9134         ldm[0] = XEXP (operands[3], 0);
9135         if (val1 < val2)
9136           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9137         else
9138           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9139       }
9140     else
9141       {
9142         ldm[0] = XEXP (operands[2], 0);
9143         if (val1 < val2)
9144           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9145         else
9146           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9147       }
9148     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9149     return \"\";
9150   }"
9151   [(set_attr "length" "12")
9152    (set_attr "predicable" "yes")
9153    (set_attr "type" "load1")]
9154 )
9155
9156 ;; the arm can support extended pre-inc instructions
9157
9158 ;; In all these cases, we use operands 0 and 1 for the register being
9159 ;; incremented because those are the operands that local-alloc will
9160 ;; tie and these are the pair most likely to be tieable (and the ones
9161 ;; that will benefit the most).
9162
9163 ;; We reject the frame pointer if it occurs anywhere in these patterns since
9164 ;; elimination will cause too many headaches.
9165
9166 (define_insn "*strqi_preinc"
9167   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9168                          (match_operand:SI 2 "index_operand" "rJ")))
9169         (match_operand:QI 3 "s_register_operand" "r"))
9170    (set (match_operand:SI 0 "s_register_operand" "=r")
9171         (plus:SI (match_dup 1) (match_dup 2)))]
9172   "TARGET_ARM
9173    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9174    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9175    && (GET_CODE (operands[2]) != REG
9176        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9177   "str%?b\\t%3, [%0, %2]!"
9178   [(set_attr "type" "store1")
9179    (set_attr "predicable" "yes")]
9180 )
9181
9182 (define_insn "*strqi_predec"
9183   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9184                           (match_operand:SI 2 "s_register_operand" "r")))
9185         (match_operand:QI 3 "s_register_operand" "r"))
9186    (set (match_operand:SI 0 "s_register_operand" "=r")
9187         (minus:SI (match_dup 1) (match_dup 2)))]
9188   "TARGET_ARM
9189    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9190    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9191    && (GET_CODE (operands[2]) != REG
9192        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9193   "str%?b\\t%3, [%0, -%2]!"
9194   [(set_attr "type" "store1")
9195    (set_attr "predicable" "yes")]
9196 )
9197
9198 (define_insn "*loadqi_preinc"
9199   [(set (match_operand:QI 3 "s_register_operand" "=r")
9200         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9201                          (match_operand:SI 2 "index_operand" "rJ"))))
9202    (set (match_operand:SI 0 "s_register_operand" "=r")
9203         (plus:SI (match_dup 1) (match_dup 2)))]
9204   "TARGET_ARM
9205    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9206    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9207    && (GET_CODE (operands[2]) != REG
9208        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9209   "ldr%?b\\t%3, [%0, %2]!"
9210   [(set_attr "type" "load_byte")
9211    (set_attr "predicable" "yes")]
9212 )
9213
9214 (define_insn "*loadqi_predec"
9215   [(set (match_operand:QI 3 "s_register_operand" "=r")
9216         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9217                           (match_operand:SI 2 "s_register_operand" "r"))))
9218    (set (match_operand:SI 0 "s_register_operand" "=r")
9219         (minus:SI (match_dup 1) (match_dup 2)))]
9220   "TARGET_ARM
9221    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9222    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9223    && (GET_CODE (operands[2]) != REG
9224        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9225   "ldr%?b\\t%3, [%0, -%2]!"
9226   [(set_attr "type" "load_byte")
9227    (set_attr "predicable" "yes")]
9228 )
9229
9230 (define_insn "*loadqisi_preinc"
9231   [(set (match_operand:SI 3 "s_register_operand" "=r")
9232         (zero_extend:SI
9233          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9234                           (match_operand:SI 2 "index_operand" "rJ")))))
9235    (set (match_operand:SI 0 "s_register_operand" "=r")
9236         (plus:SI (match_dup 1) (match_dup 2)))]
9237   "TARGET_ARM
9238    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9239    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9240    && (GET_CODE (operands[2]) != REG
9241        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9242   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
9243   [(set_attr "type" "load_byte")
9244    (set_attr "predicable" "yes")]
9245 )
9246
9247 (define_insn "*loadqisi_predec"
9248   [(set (match_operand:SI 3 "s_register_operand" "=r")
9249         (zero_extend:SI
9250          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9251                            (match_operand:SI 2 "s_register_operand" "r")))))
9252    (set (match_operand:SI 0 "s_register_operand" "=r")
9253         (minus:SI (match_dup 1) (match_dup 2)))]
9254   "TARGET_ARM
9255    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9256    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9257    && (GET_CODE (operands[2]) != REG
9258        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9259   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
9260   [(set_attr "type" "load_byte")
9261    (set_attr "predicable" "yes")]
9262 )
9263
9264 (define_insn "*strsi_preinc"
9265   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9266                          (match_operand:SI 2 "index_operand" "rJ")))
9267         (match_operand:SI 3 "s_register_operand" "r"))
9268    (set (match_operand:SI 0 "s_register_operand" "=r")
9269         (plus:SI (match_dup 1) (match_dup 2)))]
9270   "TARGET_ARM
9271    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9272    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9273    && (GET_CODE (operands[2]) != REG
9274        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9275   "str%?\\t%3, [%0, %2]!"
9276   [(set_attr "type" "store1")
9277    (set_attr "predicable" "yes")]
9278 )
9279
9280 (define_insn "*strsi_predec"
9281   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9282                           (match_operand:SI 2 "s_register_operand" "r")))
9283         (match_operand:SI 3 "s_register_operand" "r"))
9284    (set (match_operand:SI 0 "s_register_operand" "=r")
9285         (minus:SI (match_dup 1) (match_dup 2)))]
9286   "TARGET_ARM
9287    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9288    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9289    && (GET_CODE (operands[2]) != REG
9290        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9291   "str%?\\t%3, [%0, -%2]!"
9292   [(set_attr "type" "store1")
9293    (set_attr "predicable" "yes")]
9294 )
9295
9296 (define_insn "*loadsi_preinc"
9297   [(set (match_operand:SI 3 "s_register_operand" "=r")
9298         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9299                          (match_operand:SI 2 "index_operand" "rJ"))))
9300    (set (match_operand:SI 0 "s_register_operand" "=r")
9301         (plus:SI (match_dup 1) (match_dup 2)))]
9302   "TARGET_ARM
9303    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9304    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9305    && (GET_CODE (operands[2]) != REG
9306        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9307   "ldr%?\\t%3, [%0, %2]!"
9308   [(set_attr "type" "load1")
9309    (set_attr "predicable" "yes")]
9310 )
9311
9312 (define_insn "*loadsi_predec"
9313   [(set (match_operand:SI 3 "s_register_operand" "=r")
9314         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9315                           (match_operand:SI 2 "s_register_operand" "r"))))
9316    (set (match_operand:SI 0 "s_register_operand" "=r")
9317         (minus:SI (match_dup 1) (match_dup 2)))]
9318   "TARGET_ARM
9319    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9320    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9321    && (GET_CODE (operands[2]) != REG
9322        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9323   "ldr%?\\t%3, [%0, -%2]!"
9324   [(set_attr "type" "load1")
9325    (set_attr "predicable" "yes")]
9326 )
9327
9328 (define_insn "*loadhi_preinc"
9329   [(set (match_operand:HI 3 "s_register_operand" "=r")
9330         (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9331                          (match_operand:SI 2 "index_operand" "rJ"))))
9332    (set (match_operand:SI 0 "s_register_operand" "=r")
9333         (plus:SI (match_dup 1) (match_dup 2)))]
9334   "TARGET_ARM
9335    && !BYTES_BIG_ENDIAN
9336    && !TARGET_MMU_TRAPS
9337    && !arm_arch4
9338    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9339    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9340    && (GET_CODE (operands[2]) != REG
9341        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9342   "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
9343   [(set_attr "type" "load_byte")
9344    (set_attr "predicable" "yes")]
9345 )
9346
9347 (define_insn "*loadhi_predec"
9348   [(set (match_operand:HI 3 "s_register_operand" "=r")
9349         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9350                           (match_operand:SI 2 "s_register_operand" "r"))))
9351    (set (match_operand:SI 0 "s_register_operand" "=r")
9352         (minus:SI (match_dup 1) (match_dup 2)))]
9353   "TARGET_ARM
9354    && !BYTES_BIG_ENDIAN
9355    && !TARGET_MMU_TRAPS
9356    && !arm_arch4
9357    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9358    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9359    && (GET_CODE (operands[2]) != REG
9360        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9361   "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
9362   [(set_attr "type" "load_byte")
9363    (set_attr "predicable" "yes")]
9364 )
9365
9366 (define_insn "*strqi_shiftpreinc"
9367   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9368                           [(match_operand:SI 3 "s_register_operand" "r")
9369                            (match_operand:SI 4 "const_shift_operand" "n")])
9370                          (match_operand:SI 1 "s_register_operand" "0")))
9371         (match_operand:QI 5 "s_register_operand" "r"))
9372    (set (match_operand:SI 0 "s_register_operand" "=r")
9373         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9374                  (match_dup 1)))]
9375   "TARGET_ARM
9376    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9377    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9378    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9379   "str%?b\\t%5, [%0, %3%S2]!"
9380   [(set_attr "type" "store1")
9381    (set_attr "predicable" "yes")]
9382 )
9383
9384 (define_insn "*strqi_shiftpredec"
9385   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9386                           (match_operator:SI 2 "shift_operator"
9387                            [(match_operand:SI 3 "s_register_operand" "r")
9388                             (match_operand:SI 4 "const_shift_operand" "n")])))
9389         (match_operand:QI 5 "s_register_operand" "r"))
9390    (set (match_operand:SI 0 "s_register_operand" "=r")
9391         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9392                                                  (match_dup 4)])))]
9393   "TARGET_ARM
9394    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9395    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9396    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9397   "str%?b\\t%5, [%0, -%3%S2]!"
9398   [(set_attr "type" "store1")
9399    (set_attr "predicable" "yes")]
9400 )
9401
9402 (define_insn "*loadqi_shiftpreinc"
9403   [(set (match_operand:QI 5 "s_register_operand" "=r")
9404         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9405                           [(match_operand:SI 3 "s_register_operand" "r")
9406                            (match_operand:SI 4 "const_shift_operand" "n")])
9407                          (match_operand:SI 1 "s_register_operand" "0"))))
9408    (set (match_operand:SI 0 "s_register_operand" "=r")
9409         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9410                  (match_dup 1)))]
9411   "TARGET_ARM
9412    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9413    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9414    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9415   "ldr%?b\\t%5, [%0, %3%S2]!"
9416   [(set_attr "type" "load_byte")
9417    (set_attr "predicable" "yes")]
9418 )
9419
9420 (define_insn "*loadqi_shiftpredec"
9421   [(set (match_operand:QI 5 "s_register_operand" "=r")
9422         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9423                           (match_operator:SI 2 "shift_operator"
9424                            [(match_operand:SI 3 "s_register_operand" "r")
9425                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9426    (set (match_operand:SI 0 "s_register_operand" "=r")
9427         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9428                                                  (match_dup 4)])))]
9429   "TARGET_ARM
9430    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9431    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9432    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9433   "ldr%?b\\t%5, [%0, -%3%S2]!"
9434   [(set_attr "type" "load_byte")
9435    (set_attr "predicable" "yes")]
9436 )
9437
9438 (define_insn "*strsi_shiftpreinc"
9439   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9440                           [(match_operand:SI 3 "s_register_operand" "r")
9441                            (match_operand:SI 4 "const_shift_operand" "n")])
9442                          (match_operand:SI 1 "s_register_operand" "0")))
9443         (match_operand:SI 5 "s_register_operand" "r"))
9444    (set (match_operand:SI 0 "s_register_operand" "=r")
9445         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9446                  (match_dup 1)))]
9447   "TARGET_ARM
9448    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9449    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9450    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9451   "str%?\\t%5, [%0, %3%S2]!"
9452   [(set_attr "type" "store1")
9453    (set_attr "predicable" "yes")]
9454 )
9455
9456 (define_insn "*strsi_shiftpredec"
9457   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9458                           (match_operator:SI 2 "shift_operator"
9459                            [(match_operand:SI 3 "s_register_operand" "r")
9460                             (match_operand:SI 4 "const_shift_operand" "n")])))
9461         (match_operand:SI 5 "s_register_operand" "r"))
9462    (set (match_operand:SI 0 "s_register_operand" "=r")
9463         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9464                                                  (match_dup 4)])))]
9465   "TARGET_ARM
9466    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9467    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9468    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9469   "str%?\\t%5, [%0, -%3%S2]!"
9470   [(set_attr "type" "store1")
9471    (set_attr "predicable" "yes")]
9472 )
9473
9474 (define_insn "*loadsi_shiftpreinc"
9475   [(set (match_operand:SI 5 "s_register_operand" "=r")
9476         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9477                           [(match_operand:SI 3 "s_register_operand" "r")
9478                            (match_operand:SI 4 "const_shift_operand" "n")])
9479                          (match_operand:SI 1 "s_register_operand" "0"))))
9480    (set (match_operand:SI 0 "s_register_operand" "=r")
9481         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9482                  (match_dup 1)))]
9483   "TARGET_ARM
9484    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9485    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9486    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9487   "ldr%?\\t%5, [%0, %3%S2]!"
9488   [(set_attr "type" "load1")
9489    (set_attr "predicable" "yes")]
9490 )
9491
9492 (define_insn "*loadsi_shiftpredec"
9493   [(set (match_operand:SI 5 "s_register_operand" "=r")
9494         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9495                           (match_operator:SI 2 "shift_operator"
9496                            [(match_operand:SI 3 "s_register_operand" "r")
9497                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9498    (set (match_operand:SI 0 "s_register_operand" "=r")
9499         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9500                                                  (match_dup 4)])))]
9501   "TARGET_ARM
9502    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9503    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9504    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9505   "ldr%?\\t%5, [%0, -%3%S2]!"
9506   [(set_attr "type" "load1")
9507    (set_attr "predicable" "yes")])
9508
9509 (define_insn "*loadhi_shiftpreinc"
9510   [(set (match_operand:HI 5 "s_register_operand" "=r")
9511         (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
9512                           [(match_operand:SI 3 "s_register_operand" "r")
9513                            (match_operand:SI 4 "const_shift_operand" "n")])
9514                          (match_operand:SI 1 "s_register_operand" "0"))))
9515    (set (match_operand:SI 0 "s_register_operand" "=r")
9516         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9517                  (match_dup 1)))]
9518   "TARGET_ARM
9519    && !BYTES_BIG_ENDIAN
9520    && !TARGET_MMU_TRAPS
9521    && !arm_arch4
9522    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9523    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9524    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9525   "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
9526   [(set_attr "type" "load_byte")
9527    (set_attr "predicable" "yes")]
9528 )
9529
9530 (define_insn "*loadhi_shiftpredec"
9531   [(set (match_operand:HI 5 "s_register_operand" "=r")
9532         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9533                           (match_operator:SI 2 "shift_operator"
9534                            [(match_operand:SI 3 "s_register_operand" "r")
9535                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9536    (set (match_operand:SI 0 "s_register_operand" "=r")
9537         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9538                                                  (match_dup 4)])))]
9539   "TARGET_ARM
9540    && !BYTES_BIG_ENDIAN
9541    && !TARGET_MMU_TRAPS
9542    && !arm_arch4
9543    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9544    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9545    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9546   "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
9547   [(set_attr "type" "load_byte")
9548    (set_attr "predicable" "yes")]
9549 )
9550
9551 ; It can also support extended post-inc expressions, but combine doesn't
9552 ; try these....
9553 ; It doesn't seem worth adding peepholes for anything but the most common
9554 ; cases since, unlike combine, the increment must immediately follow the load
9555 ; for this pattern to match.
9556 ; We must watch to see that the source/destination register isn't also the
9557 ; same as the base address register, and that if the index is a register,
9558 ; that it is not the same as the base address register.  In such cases the
9559 ; instruction that we would generate would have UNPREDICTABLE behavior so 
9560 ; we cannot use it.
9561
9562 (define_peephole
9563   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9564         (match_operand:QI 2 "s_register_operand" "r"))
9565    (set (match_dup 0)
9566         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9567   "TARGET_ARM
9568    && (REGNO (operands[2]) != REGNO (operands[0]))
9569    && (GET_CODE (operands[1]) != REG
9570        || (REGNO (operands[1]) != REGNO (operands[0])))"
9571   "str%?b\\t%2, [%0], %1"
9572 )
9573
9574 (define_peephole
9575   [(set (match_operand:QI 0 "s_register_operand" "=r")
9576         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9577    (set (match_dup 1)
9578         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9579   "TARGET_ARM
9580    && REGNO (operands[0]) != REGNO(operands[1])
9581    && (GET_CODE (operands[2]) != REG
9582        || REGNO(operands[0]) != REGNO (operands[2]))"
9583   "ldr%?b\\t%0, [%1], %2"
9584 )
9585
9586 (define_peephole
9587   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9588         (match_operand:SI 2 "s_register_operand" "r"))
9589    (set (match_dup 0)
9590         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9591   "TARGET_ARM
9592    && (REGNO (operands[2]) != REGNO (operands[0]))
9593    && (GET_CODE (operands[1]) != REG
9594        || (REGNO (operands[1]) != REGNO (operands[0])))"
9595   "str%?\\t%2, [%0], %1"
9596 )
9597
9598 (define_peephole
9599   [(set (match_operand:HI 0 "s_register_operand" "=r")
9600         (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
9601    (set (match_dup 1)
9602         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9603   "TARGET_ARM
9604    && !BYTES_BIG_ENDIAN
9605    && !TARGET_MMU_TRAPS
9606    && !arm_arch4
9607    && REGNO (operands[0]) != REGNO(operands[1])
9608    && (GET_CODE (operands[2]) != REG
9609        || REGNO(operands[0]) != REGNO (operands[2]))"
9610   "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
9611 )
9612
9613 (define_peephole
9614   [(set (match_operand:SI 0 "s_register_operand" "=r")
9615         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9616    (set (match_dup 1)
9617         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9618   "TARGET_ARM
9619    && REGNO (operands[0]) != REGNO(operands[1])
9620    && (GET_CODE (operands[2]) != REG
9621        || REGNO(operands[0]) != REGNO (operands[2]))"
9622   "ldr%?\\t%0, [%1], %2"
9623 )
9624
9625 (define_peephole
9626   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9627                          (match_operand:SI 1 "index_operand" "rJ")))
9628         (match_operand:QI 2 "s_register_operand" "r"))
9629    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
9630   "TARGET_ARM
9631    && (REGNO (operands[2]) != REGNO (operands[0]))
9632    && (GET_CODE (operands[1]) != REG
9633        || (REGNO (operands[1]) != REGNO (operands[0])))"
9634   "str%?b\\t%2, [%0, %1]!"
9635 )
9636
9637 (define_peephole
9638   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9639                           [(match_operand:SI 0 "s_register_operand" "r")
9640                            (match_operand:SI 1 "const_int_operand" "n")])
9641                          (match_operand:SI 2 "s_register_operand" "+r")))
9642         (match_operand:QI 3 "s_register_operand" "r"))
9643    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9644                                (match_dup 2)))]
9645   "TARGET_ARM
9646    && (REGNO (operands[3]) != REGNO (operands[2]))
9647    && (REGNO (operands[0]) != REGNO (operands[2]))"
9648   "str%?b\\t%3, [%2, %0%S4]!"
9649 )
9650
9651 ; This pattern is never tried by combine, so do it as a peephole
9652
9653 (define_peephole2
9654   [(set (match_operand:SI 0 "s_register_operand" "")
9655         (match_operand:SI 1 "s_register_operand" ""))
9656    (set (reg:CC CC_REGNUM)
9657         (compare:CC (match_dup 1) (const_int 0)))]
9658   "TARGET_ARM
9659    && (!(TARGET_HARD_FLOAT && TARGET_MAVERICK)
9660        || (!cirrus_fp_register (operands[0], SImode)
9661            && !cirrus_fp_register (operands[1], SImode)))
9662   "
9663   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9664               (set (match_dup 0) (match_dup 1))])]
9665   ""
9666 )
9667
9668 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9669 ; reversed, check that the memory references aren't volatile.
9670
9671 (define_peephole
9672   [(set (match_operand:SI 0 "s_register_operand" "=r")
9673         (match_operand:SI 4 "memory_operand" "m"))
9674    (set (match_operand:SI 1 "s_register_operand" "=r")
9675         (match_operand:SI 5 "memory_operand" "m"))
9676    (set (match_operand:SI 2 "s_register_operand" "=r")
9677         (match_operand:SI 6 "memory_operand" "m"))
9678    (set (match_operand:SI 3 "s_register_operand" "=r")
9679         (match_operand:SI 7 "memory_operand" "m"))]
9680   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9681   "*
9682   return emit_ldm_seq (operands, 4);
9683   "
9684 )
9685
9686 (define_peephole
9687   [(set (match_operand:SI 0 "s_register_operand" "=r")
9688         (match_operand:SI 3 "memory_operand" "m"))
9689    (set (match_operand:SI 1 "s_register_operand" "=r")
9690         (match_operand:SI 4 "memory_operand" "m"))
9691    (set (match_operand:SI 2 "s_register_operand" "=r")
9692         (match_operand:SI 5 "memory_operand" "m"))]
9693   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9694   "*
9695   return emit_ldm_seq (operands, 3);
9696   "
9697 )
9698
9699 (define_peephole
9700   [(set (match_operand:SI 0 "s_register_operand" "=r")
9701         (match_operand:SI 2 "memory_operand" "m"))
9702    (set (match_operand:SI 1 "s_register_operand" "=r")
9703         (match_operand:SI 3 "memory_operand" "m"))]
9704   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9705   "*
9706   return emit_ldm_seq (operands, 2);
9707   "
9708 )
9709
9710 (define_peephole
9711   [(set (match_operand:SI 4 "memory_operand" "=m")
9712         (match_operand:SI 0 "s_register_operand" "r"))
9713    (set (match_operand:SI 5 "memory_operand" "=m")
9714         (match_operand:SI 1 "s_register_operand" "r"))
9715    (set (match_operand:SI 6 "memory_operand" "=m")
9716         (match_operand:SI 2 "s_register_operand" "r"))
9717    (set (match_operand:SI 7 "memory_operand" "=m")
9718         (match_operand:SI 3 "s_register_operand" "r"))]
9719   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9720   "*
9721   return emit_stm_seq (operands, 4);
9722   "
9723 )
9724
9725 (define_peephole
9726   [(set (match_operand:SI 3 "memory_operand" "=m")
9727         (match_operand:SI 0 "s_register_operand" "r"))
9728    (set (match_operand:SI 4 "memory_operand" "=m")
9729         (match_operand:SI 1 "s_register_operand" "r"))
9730    (set (match_operand:SI 5 "memory_operand" "=m")
9731         (match_operand:SI 2 "s_register_operand" "r"))]
9732   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9733   "*
9734   return emit_stm_seq (operands, 3);
9735   "
9736 )
9737
9738 (define_peephole
9739   [(set (match_operand:SI 2 "memory_operand" "=m")
9740         (match_operand:SI 0 "s_register_operand" "r"))
9741    (set (match_operand:SI 3 "memory_operand" "=m")
9742         (match_operand:SI 1 "s_register_operand" "r"))]
9743   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9744   "*
9745   return emit_stm_seq (operands, 2);
9746   "
9747 )
9748
9749 (define_split
9750   [(set (match_operand:SI 0 "s_register_operand" "")
9751         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9752                        (const_int 0))
9753                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9754                          [(match_operand:SI 3 "s_register_operand" "")
9755                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
9756    (clobber (match_operand:SI 5 "s_register_operand" ""))]
9757   "TARGET_ARM"
9758   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9759    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9760                               (match_dup 5)))]
9761   ""
9762 )
9763
9764 ;; This split can be used because CC_Z mode implies that the following
9765 ;; branch will be an equality, or an unsigned inequality, so the sign
9766 ;; extension is not needed.
9767
9768 (define_split
9769   [(set (reg:CC_Z CC_REGNUM)
9770         (compare:CC_Z
9771          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9772                     (const_int 24))
9773          (match_operand 1 "const_int_operand" "")))
9774    (clobber (match_scratch:SI 2 ""))]
9775   "TARGET_ARM
9776    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9777        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9778   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9779    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9780   "
9781   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9782   "
9783 )
9784
9785 (define_expand "prologue"
9786   [(clobber (const_int 0))]
9787   "TARGET_EITHER"
9788   "if (TARGET_ARM)
9789      arm_expand_prologue ();
9790    else
9791      thumb_expand_prologue ();
9792   DONE;
9793   "
9794 )
9795
9796 (define_expand "epilogue"
9797   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9798   "TARGET_EITHER"
9799   "
9800   if (TARGET_THUMB)
9801     thumb_expand_epilogue ();
9802   else if (USE_RETURN_INSN (FALSE))
9803     {
9804       emit_jump_insn (gen_return ());
9805       DONE;
9806     }
9807   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9808         gen_rtvec (1,
9809                 gen_rtx_RETURN (VOIDmode)),
9810         VUNSPEC_EPILOGUE));
9811   DONE;
9812   "
9813 )
9814
9815 ;; Note - although unspec_volatile's USE all hard registers,
9816 ;; USEs are ignored after relaod has completed.  Thus we need
9817 ;; to add an unspec of the link register to ensure that flow
9818 ;; does not think that it is unused by the sibcall branch that
9819 ;; will replace the standard function epilogue.
9820 (define_insn "sibcall_epilogue"
9821   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9822               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9823   "TARGET_ARM"
9824   "*
9825   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9826     return output_return_instruction (const_true_rtx, FALSE, FALSE);
9827   return arm_output_epilogue (next_nonnote_insn (insn));
9828   "
9829 ;; Length is absolute worst case
9830   [(set_attr "length" "44")
9831    (set_attr "type" "block")
9832    ;; We don't clobber the conditions, but the potential length of this
9833    ;; operation is sufficient to make conditionalizing the sequence 
9834    ;; unlikely to be profitable.
9835    (set_attr "conds" "clob")]
9836 )
9837
9838 (define_insn "*epilogue_insns"
9839   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9840   "TARGET_EITHER"
9841   "*
9842   if (TARGET_ARM)
9843     return arm_output_epilogue (NULL);
9844   else /* TARGET_THUMB */
9845     return thumb_unexpanded_epilogue ();
9846   "
9847   ; Length is absolute worst case
9848   [(set_attr "length" "44")
9849    (set_attr "type" "block")
9850    ;; We don't clobber the conditions, but the potential length of this
9851    ;; operation is sufficient to make conditionalizing the sequence 
9852    ;; unlikely to be profitable.
9853    (set_attr "conds" "clob")]
9854 )
9855
9856 (define_expand "eh_epilogue"
9857   [(use (match_operand:SI 0 "register_operand" ""))
9858    (use (match_operand:SI 1 "register_operand" ""))
9859    (use (match_operand:SI 2 "register_operand" ""))]
9860   "TARGET_EITHER"
9861   "
9862   {
9863     cfun->machine->eh_epilogue_sp_ofs = operands[1];
9864     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9865       {
9866         rtx ra = gen_rtx_REG (Pmode, 2);
9867
9868         emit_move_insn (ra, operands[2]);
9869         operands[2] = ra;
9870       }
9871     /* This is a hack -- we may have crystalized the function type too
9872        early.  */
9873     cfun->machine->func_type = 0;
9874   }"
9875 )
9876
9877 ;; This split is only used during output to reduce the number of patterns
9878 ;; that need assembler instructions adding to them.  We allowed the setting
9879 ;; of the conditions to be implicit during rtl generation so that
9880 ;; the conditional compare patterns would work.  However this conflicts to
9881 ;; some extent with the conditional data operations, so we have to split them
9882 ;; up again here.
9883
9884 (define_split
9885   [(set (match_operand:SI 0 "s_register_operand" "")
9886         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9887                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9888                          (match_dup 0)
9889                          (match_operand 4 "" "")))
9890    (clobber (reg:CC CC_REGNUM))]
9891   "TARGET_ARM && reload_completed"
9892   [(set (match_dup 5) (match_dup 6))
9893    (cond_exec (match_dup 7)
9894               (set (match_dup 0) (match_dup 4)))]
9895   "
9896   {
9897     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9898                                              operands[2], operands[3]);
9899     enum rtx_code rc = GET_CODE (operands[1]);
9900
9901     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9902     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9903     if (mode == CCFPmode || mode == CCFPEmode)
9904       rc = reverse_condition_maybe_unordered (rc);
9905     else
9906       rc = reverse_condition (rc);
9907
9908     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9909   }"
9910 )
9911
9912 (define_split
9913   [(set (match_operand:SI 0 "s_register_operand" "")
9914         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9915                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9916                          (match_operand 4 "" "")
9917                          (match_dup 0)))
9918    (clobber (reg:CC CC_REGNUM))]
9919   "TARGET_ARM && reload_completed"
9920   [(set (match_dup 5) (match_dup 6))
9921    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9922               (set (match_dup 0) (match_dup 4)))]
9923   "
9924   {
9925     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9926                                              operands[2], operands[3]);
9927
9928     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9929     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9930   }"
9931 )
9932
9933 (define_split
9934   [(set (match_operand:SI 0 "s_register_operand" "")
9935         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9936                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9937                          (match_operand 4 "" "")
9938                          (match_operand 5 "" "")))
9939    (clobber (reg:CC CC_REGNUM))]
9940   "TARGET_ARM && reload_completed"
9941   [(set (match_dup 6) (match_dup 7))
9942    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9943               (set (match_dup 0) (match_dup 4)))
9944    (cond_exec (match_dup 8)
9945               (set (match_dup 0) (match_dup 5)))]
9946   "
9947   {
9948     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9949                                              operands[2], operands[3]);
9950     enum rtx_code rc = GET_CODE (operands[1]);
9951
9952     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9953     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9954     if (mode == CCFPmode || mode == CCFPEmode)
9955       rc = reverse_condition_maybe_unordered (rc);
9956     else
9957       rc = reverse_condition (rc);
9958
9959     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9960   }"
9961 )
9962
9963 (define_split
9964   [(set (match_operand:SI 0 "s_register_operand" "")
9965         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9966                           [(match_operand:SI 2 "s_register_operand" "")
9967                            (match_operand:SI 3 "arm_add_operand" "")])
9968                          (match_operand:SI 4 "arm_rhs_operand" "")
9969                          (not:SI
9970                           (match_operand:SI 5 "s_register_operand" ""))))
9971    (clobber (reg:CC CC_REGNUM))]
9972   "TARGET_ARM && reload_completed"
9973   [(set (match_dup 6) (match_dup 7))
9974    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9975               (set (match_dup 0) (match_dup 4)))
9976    (cond_exec (match_dup 8)
9977               (set (match_dup 0) (not:SI (match_dup 5))))]
9978   "
9979   {
9980     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9981                                              operands[2], operands[3]);
9982     enum rtx_code rc = GET_CODE (operands[1]);
9983
9984     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9985     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9986     if (mode == CCFPmode || mode == CCFPEmode)
9987       rc = reverse_condition_maybe_unordered (rc);
9988     else
9989       rc = reverse_condition (rc);
9990
9991     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9992   }"
9993 )
9994
9995 (define_insn "*cond_move_not"
9996   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9997         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9998                           [(match_operand 3 "cc_register" "") (const_int 0)])
9999                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10000                          (not:SI
10001                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
10002   "TARGET_ARM"
10003   "@
10004    mvn%D4\\t%0, %2
10005    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
10006   [(set_attr "conds" "use")
10007    (set_attr "length" "4,8")]
10008 )
10009
10010 ;; The next two patterns occur when an AND operation is followed by a
10011 ;; scc insn sequence 
10012
10013 (define_insn "*sign_extract_onebit"
10014   [(set (match_operand:SI 0 "s_register_operand" "=r")
10015         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10016                          (const_int 1)
10017                          (match_operand:SI 2 "const_int_operand" "n")))
10018     (clobber (reg:CC CC_REGNUM))]
10019   "TARGET_ARM"
10020   "*
10021     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10022     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10023     return \"mvnne\\t%0, #0\";
10024   "
10025   [(set_attr "conds" "clob")
10026    (set_attr "length" "8")]
10027 )
10028
10029 (define_insn "*not_signextract_onebit"
10030   [(set (match_operand:SI 0 "s_register_operand" "=r")
10031         (not:SI
10032          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10033                           (const_int 1)
10034                           (match_operand:SI 2 "const_int_operand" "n"))))
10035    (clobber (reg:CC CC_REGNUM))]
10036   "TARGET_ARM"
10037   "*
10038     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10039     output_asm_insn (\"tst\\t%1, %2\", operands);
10040     output_asm_insn (\"mvneq\\t%0, #0\", operands);
10041     return \"movne\\t%0, #0\";
10042   "
10043   [(set_attr "conds" "clob")
10044    (set_attr "length" "12")]
10045 )
10046
10047 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
10048 ;; expressions.  For simplicity, the first register is also in the unspec
10049 ;; part.
10050 (define_insn "*push_multi"
10051   [(match_parallel 2 "multi_register_push"
10052     [(set (match_operand:BLK 0 "memory_operand" "=m")
10053           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
10054                       UNSPEC_PUSH_MULT))])]
10055   "TARGET_ARM"
10056   "*
10057   {
10058     int num_saves = XVECLEN (operands[2], 0);
10059      
10060     /* For the StrongARM at least it is faster to
10061        use STR to store only a single register.  */
10062     if (num_saves == 1)
10063       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10064     else
10065       {
10066         int i;
10067         char pattern[100];
10068
10069         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10070
10071         for (i = 1; i < num_saves; i++)
10072           {
10073             strcat (pattern, \", %|\");
10074             strcat (pattern,
10075                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10076           }
10077
10078         strcat (pattern, \"}\");
10079         output_asm_insn (pattern, operands);
10080       }
10081
10082     return \"\";
10083   }"
10084   [(set_attr "type" "store4")]
10085 )
10086
10087 (define_insn "stack_tie"
10088   [(set (mem:BLK (scratch))
10089         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
10090                      (match_operand:SI 1 "s_register_operand" "r")]
10091                     UNSPEC_PRLG_STK))]
10092   ""
10093   ""
10094   [(set_attr "length" "0")]
10095 )
10096
10097 ;; Similarly for the floating point registers
10098 (define_insn "*push_fp_multi"
10099   [(match_parallel 2 "multi_register_push"
10100     [(set (match_operand:BLK 0 "memory_operand" "=m")
10101           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10102                       UNSPEC_PUSH_MULT))])]
10103   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
10104   "*
10105   {
10106     char pattern[100];
10107
10108     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10109     output_asm_insn (pattern, operands);
10110     return \"\";
10111   }"
10112   [(set_attr "type" "f_store")]
10113 )
10114
10115 ;; Special patterns for dealing with the constant pool
10116
10117 (define_insn "align_4"
10118   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10119   "TARGET_EITHER"
10120   "*
10121   assemble_align (32);
10122   return \"\";
10123   "
10124 )
10125
10126 (define_insn "align_8"
10127   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10128   "TARGET_EITHER"
10129   "*
10130   assemble_align (64);
10131   return \"\";
10132   "
10133 )
10134
10135 (define_insn "consttable_end"
10136   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10137   "TARGET_EITHER"
10138   "*
10139   making_const_table = FALSE;
10140   return \"\";
10141   "
10142 )
10143
10144 (define_insn "consttable_1"
10145   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10146   "TARGET_THUMB"
10147   "*
10148   making_const_table = TRUE;
10149   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10150   assemble_zeros (3);
10151   return \"\";
10152   "
10153   [(set_attr "length" "4")]
10154 )
10155
10156 (define_insn "consttable_2"
10157   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10158   "TARGET_THUMB"
10159   "*
10160   making_const_table = TRUE;
10161   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10162   assemble_zeros (2);
10163   return \"\";
10164   "
10165   [(set_attr "length" "4")]
10166 )
10167
10168 (define_insn "consttable_4"
10169   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10170   "TARGET_EITHER"
10171   "*
10172   {
10173     making_const_table = TRUE;
10174     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10175       {
10176       case MODE_FLOAT:
10177       {
10178         REAL_VALUE_TYPE r;
10179         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10180         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10181         break;
10182       }
10183       default:
10184         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
10185         break;
10186       }
10187     return \"\";
10188   }"
10189   [(set_attr "length" "4")]
10190 )
10191
10192 (define_insn "consttable_8"
10193   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10194   "TARGET_EITHER"
10195   "*
10196   {
10197     making_const_table = TRUE;
10198     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10199       {
10200        case MODE_FLOAT:
10201         {
10202           REAL_VALUE_TYPE r;
10203           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10204           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10205           break;
10206         }
10207       default:
10208         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10209         break;
10210       }
10211     return \"\";
10212   }"
10213   [(set_attr "length" "8")]
10214 )
10215
10216 ;; Miscellaneous Thumb patterns
10217
10218 (define_expand "tablejump"
10219   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10220               (use (label_ref (match_operand 1 "" "")))])]
10221   "TARGET_THUMB"
10222   "
10223   if (flag_pic)
10224     {
10225       /* Hopefully, CSE will eliminate this copy.  */
10226       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10227       rtx reg2 = gen_reg_rtx (SImode);
10228
10229       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10230       operands[0] = reg2;
10231     }
10232   "
10233 )
10234
10235 (define_insn "*thumb_tablejump"
10236   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10237    (use (label_ref (match_operand 1 "" "")))]
10238   "TARGET_THUMB"
10239   "mov\\t%|pc, %0"
10240   [(set_attr "length" "2")]
10241 )
10242
10243 ;; V5 Instructions,
10244
10245 (define_insn "clzsi2"
10246   [(set (match_operand:SI 0 "s_register_operand" "=r")
10247         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10248   "TARGET_ARM && arm_arch5"
10249   "clz%?\\t%0, %1"
10250   [(set_attr "predicable" "yes")])
10251
10252 (define_expand "ffssi2"
10253   [(set (match_operand:SI 0 "s_register_operand" "")
10254         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10255   "TARGET_ARM && arm_arch5"
10256   "
10257   {
10258     rtx t1, t2, t3;
10259
10260     t1 = gen_reg_rtx (SImode);
10261     t2 = gen_reg_rtx (SImode);
10262     t3 = gen_reg_rtx (SImode);
10263
10264     emit_insn (gen_negsi2 (t1, operands[1]));
10265     emit_insn (gen_andsi3 (t2, operands[1], t1));
10266     emit_insn (gen_clzsi2 (t3, t2));
10267     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10268     DONE;
10269   }"
10270 )
10271
10272 (define_expand "ctzsi2"
10273   [(set (match_operand:SI 0 "s_register_operand" "")
10274         (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10275   "TARGET_ARM && arm_arch5"
10276   "
10277   {
10278     rtx t1, t2, t3;
10279
10280     t1 = gen_reg_rtx (SImode);
10281     t2 = gen_reg_rtx (SImode);
10282     t3 = gen_reg_rtx (SImode);
10283
10284     emit_insn (gen_negsi2 (t1, operands[1]));
10285     emit_insn (gen_andsi3 (t2, operands[1], t1));
10286     emit_insn (gen_clzsi2 (t3, t2));
10287     emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10288     DONE;
10289   }"
10290 )
10291
10292 ;; V5E instructions.
10293
10294 (define_insn "prefetch"
10295   [(prefetch (match_operand:SI 0 "address_operand" "p")
10296              (match_operand:SI 1 "" "")
10297              (match_operand:SI 2 "" ""))]
10298   "TARGET_ARM && arm_arch5e"
10299   "pld\\t%a0")
10300
10301 ;; General predication pattern
10302
10303 (define_cond_exec
10304   [(match_operator 0 "arm_comparison_operator"
10305     [(match_operand 1 "cc_register" "")
10306      (const_int 0)])]
10307   "TARGET_ARM"
10308   ""
10309 )
10310
10311 (define_insn "prologue_use"
10312   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10313   ""
10314   "%@ %0 needed for prologue"
10315 )
10316
10317 ;; Load the FPA co-processor patterns
10318 (include "fpa.md")
10319 ;; Load the Maverick co-processor patterns
10320 (include "cirrus.md")
10321 ;; Load the Intel Wireless Multimedia Extension patterns
10322 (include "iwmmxt.md")
10323 ;; Load the VFP co-processor patterns
10324 (include "vfp.md")
10325