OSDN Git Service

gcc/ChangeLog:
[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 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
132 ; scheduling decisions for the load unit and the multiplier.
133 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
134
135 ; IS_XSCALE is set to 'yes' when compiling for XScale.
136 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
137
138 ;; Operand number of an input operand that is shifted.  Zero if the
139 ;; given instruction does not shift one of its input operands.
140 (define_attr "shift" "" (const_int 0))
141
142 ; Floating Point Unit.  If we only have floating point emulation, then there
143 ; is no point in scheduling the floating point insns.  (Well, for best
144 ; performance we should try and group them together).
145 (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
146   (const (symbol_ref "arm_fpu_attr")))
147
148 ; LENGTH of an instruction (in bytes)
149 (define_attr "length" "" (const_int 4))
150
151 ; POOL_RANGE is how far away from a constant pool entry that this insn
152 ; can be placed.  If the distance is zero, then this insn will never
153 ; reference the pool.
154 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
155 ; before its address.
156 (define_attr "pool_range" "" (const_int 0))
157 (define_attr "neg_pool_range" "" (const_int 0))
158
159 ; An assembler sequence may clobber the condition codes without us knowing.
160 ; If such an insn references the pool, then we have no way of knowing how,
161 ; so use the most conservative value for pool_range.
162 (define_asm_attributes
163  [(set_attr "conds" "clob")
164   (set_attr "length" "4")
165   (set_attr "pool_range" "250")])
166
167 ;; The instruction used to implement a particular pattern.  This
168 ;; information is used by pipeline descriptions to provide accurate
169 ;; scheduling information.
170
171 (define_attr "insn"
172         "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"
173         (const_string "other"))
174
175 ; TYPE attribute is used to detect floating point instructions which, if
176 ; running on a co-processor can run in parallel with other, basic instructions
177 ; If write-buffer scheduling is enabled then it can also be used in the
178 ; scheduling of writes.
179
180 ; Classification of each insn
181 ; alu           any alu  instruction that doesn't hit memory or fp
182 ;               regs or have a shifted source operand
183 ; alu_shift     any data instruction that doesn't hit memory or fp
184 ;               regs, but has a source operand shifted by a constant
185 ; alu_shift_reg any data instruction that doesn't hit memory or fp
186 ;               regs, but has a source operand shifted by a register value
187 ; mult          a multiply instruction
188 ; block         blockage insn, this blocks all functional units
189 ; float         a floating point arithmetic operation (subject to expansion)
190 ; fdivd         DFmode floating point division
191 ; fdivs         SFmode floating point division
192 ; fmul          Floating point multiply
193 ; ffmul         Fast floating point multiply
194 ; farith        Floating point arithmetic (4 cycle)
195 ; ffarith       Fast floating point arithmetic (2 cycle)
196 ; float_em      a floating point arithmetic operation that is normally emulated
197 ;               even on a machine with an fpa.
198 ; f_load        a floating point load from memory
199 ; f_store       a floating point store to memory
200 ; f_mem_r       a transfer of a floating point register to a real reg via mem
201 ; r_mem_f       the reverse of f_mem_r
202 ; f_2_r         fast transfer float to arm (no memory needed)
203 ; r_2_f         fast transfer arm to float
204 ; branch        a branch
205 ; call          a subroutine call
206 ; load_byte     load byte(s) from memory to arm registers
207 ; load1         load 1 word from memory to arm registers
208 ; load2         load 2 words from memory to arm registers
209 ; load3         load 3 words from memory to arm registers
210 ; load4         load 4 words from memory to arm registers
211 ; store         store 1 word to memory from arm registers
212 ; store2        store 2 words
213 ; store3        store 3 words
214 ; store4        store 4 (or more) words
215 ;  Additions for Cirrus Maverick co-processor:
216 ; mav_farith    Floating point arithmetic (4 cycle)
217 ; mav_dmult     Double multiplies (7 cycle)
218 ;
219 (define_attr "type"
220         "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" 
221         (if_then_else 
222          (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
223          (const_string "mult")
224          (const_string "alu")))
225
226 ; Load scheduling, set from the arm_ld_sched variable
227 ; initialized by arm_override_options() 
228 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
229
230 ; condition codes: this one is used by final_prescan_insn to speed up
231 ; conditionalizing instructions.  It saves having to scan the rtl to see if
232 ; it uses or alters the condition codes.
233
234 ; USE means that the condition codes are used by the insn in the process of
235 ;   outputting code, this means (at present) that we can't use the insn in
236 ;   inlined branches
237 ;
238 ; SET means that the purpose of the insn is to set the condition codes in a
239 ;   well defined manner.
240 ;
241 ; CLOB means that the condition codes are altered in an undefined manner, if
242 ;   they are altered at all
243 ;
244 ; JUMP_CLOB is used when the condition cannot be represented by a single
245 ;   instruction (UNEQ and LTGT).  These cannot be predicated.
246 ;
247 ; NOCOND means that the condition codes are neither altered nor affect the
248 ;   output of this insn
249
250 (define_attr "conds" "use,set,clob,jump_clob,nocond"
251         (if_then_else (eq_attr "type" "call")
252          (const_string "clob")
253          (const_string "nocond")))
254
255 ; Predicable means that the insn can be conditionally executed based on
256 ; an automatically added predicate (additional patterns are generated by 
257 ; gen...).  We default to 'no' because no Thumb patterns match this rule
258 ; and not all ARM patterns do.
259 (define_attr "predicable" "no,yes" (const_string "no"))
260
261 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
262 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
263 ; suffer blockages enough to warrant modelling this (and it can adversely
264 ; affect the schedule).
265 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
266
267 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
268 ; to stall the processor.  Used with model_wbuf above.
269 (define_attr "write_conflict" "no,yes"
270   (if_then_else (eq_attr "type"
271                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
272                 (const_string "yes")
273                 (const_string "no")))
274
275 ; Classify the insns into those that take one cycle and those that take more
276 ; than one on the main cpu execution unit.
277 (define_attr "core_cycles" "single,multi"
278   (if_then_else (eq_attr "type"
279                  "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
280                 (const_string "single")
281                 (const_string "multi")))
282
283 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
284 ;; distant label.  Only applicable to Thumb code.
285 (define_attr "far_jump" "yes,no" (const_string "no"))
286
287 ;;---------------------------------------------------------------------------
288 ;; Pipeline descriptions
289
290 ;; Processor type.  This attribute must exactly match the table in 
291 ;; arm-cores.def.
292 (define_attr "tune" 
293              "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"
294              (const (symbol_ref "arm_tune")))
295
296 ;; True if the generic scheduling description should be used.
297
298 (define_attr "generic_sched" "yes,no"
299         (if_then_else 
300          (eq_attr "tune" "arm926ejs,arm1026ejs,arm1136js,arm1136jfs") 
301          (const_string "no")
302          (const_string "yes")))
303         
304 (include "arm-generic.md")
305 (include "arm926ejs.md")
306 (include "arm1026ejs.md")
307 (include "arm1136jfs.md")
308
309 \f
310 ;;---------------------------------------------------------------------------
311 ;; Insn patterns
312 ;;
313 ;; Addition insns.
314
315 ;; Note: For DImode insns, there is normally no reason why operands should
316 ;; not be in the same register, what we don't want is for something being
317 ;; written to partially overlap something that is an input.
318 ;; Cirrus 64bit additions should not be split because we have a native
319 ;; 64bit addition instructions.
320
321 (define_expand "adddi3"
322  [(parallel
323    [(set (match_operand:DI           0 "s_register_operand" "")
324           (plus:DI (match_operand:DI 1 "s_register_operand" "")
325                    (match_operand:DI 2 "s_register_operand" "")))
326     (clobber (reg:CC CC_REGNUM))])]
327   "TARGET_EITHER"
328   "
329   if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
330     {
331       if (!cirrus_fp_register (operands[0], DImode))
332         operands[0] = force_reg (DImode, operands[0]);
333       if (!cirrus_fp_register (operands[1], DImode))
334         operands[1] = force_reg (DImode, operands[1]);
335       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
336       DONE;
337     }
338
339   if (TARGET_THUMB)
340     {
341       if (GET_CODE (operands[1]) != REG)
342         operands[1] = force_reg (SImode, operands[1]);
343       if (GET_CODE (operands[2]) != REG)
344         operands[2] = force_reg (SImode, operands[2]);
345      }
346   "
347 )
348
349 (define_insn "*thumb_adddi3"
350   [(set (match_operand:DI          0 "register_operand" "=l")
351         (plus:DI (match_operand:DI 1 "register_operand" "%0")
352                  (match_operand:DI 2 "register_operand" "l")))
353    (clobber (reg:CC CC_REGNUM))
354   ]
355   "TARGET_THUMB"
356   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
357   [(set_attr "length" "4")]
358 )
359
360 (define_insn_and_split "*arm_adddi3"
361   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
362         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
363                  (match_operand:DI 2 "s_register_operand" "r,  0")))
364    (clobber (reg:CC CC_REGNUM))]
365   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
366   "#"
367   "TARGET_ARM && reload_completed"
368   [(parallel [(set (reg:CC_C CC_REGNUM)
369                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
370                                  (match_dup 1)))
371               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
372    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
373                                (plus:SI (match_dup 4) (match_dup 5))))]
374   "
375   {
376     operands[3] = gen_highpart (SImode, operands[0]);
377     operands[0] = gen_lowpart (SImode, operands[0]);
378     operands[4] = gen_highpart (SImode, operands[1]);
379     operands[1] = gen_lowpart (SImode, operands[1]);
380     operands[5] = gen_highpart (SImode, operands[2]);
381     operands[2] = gen_lowpart (SImode, operands[2]);
382   }"
383   [(set_attr "conds" "clob")
384    (set_attr "length" "8")]
385 )
386
387 (define_insn_and_split "*adddi_sesidi_di"
388   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
389         (plus:DI (sign_extend:DI
390                   (match_operand:SI 2 "s_register_operand" "r,r"))
391                  (match_operand:DI 1 "s_register_operand" "r,0")))
392    (clobber (reg:CC CC_REGNUM))]
393   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
394   "#"
395   "TARGET_ARM && reload_completed"
396   [(parallel [(set (reg:CC_C CC_REGNUM)
397                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
398                                  (match_dup 1)))
399               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
400    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
401                                (plus:SI (ashiftrt:SI (match_dup 2)
402                                                      (const_int 31))
403                                         (match_dup 4))))]
404   "
405   {
406     operands[3] = gen_highpart (SImode, operands[0]);
407     operands[0] = gen_lowpart (SImode, operands[0]);
408     operands[4] = gen_highpart (SImode, operands[1]);
409     operands[1] = gen_lowpart (SImode, operands[1]);
410     operands[2] = gen_lowpart (SImode, operands[2]);
411   }"
412   [(set_attr "conds" "clob")
413    (set_attr "length" "8")]
414 )
415
416 (define_insn_and_split "*adddi_zesidi_di"
417   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
418         (plus:DI (zero_extend:DI
419                   (match_operand:SI 2 "s_register_operand" "r,r"))
420                  (match_operand:DI 1 "s_register_operand" "r,0")))
421    (clobber (reg:CC CC_REGNUM))]
422   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
423   "#"
424   "TARGET_ARM && reload_completed"
425   [(parallel [(set (reg:CC_C CC_REGNUM)
426                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
427                                  (match_dup 1)))
428               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
429    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
430                                (plus:SI (match_dup 4) (const_int 0))))]
431   "
432   {
433     operands[3] = gen_highpart (SImode, operands[0]);
434     operands[0] = gen_lowpart (SImode, operands[0]);
435     operands[4] = gen_highpart (SImode, operands[1]);
436     operands[1] = gen_lowpart (SImode, operands[1]);
437     operands[2] = gen_lowpart (SImode, operands[2]);
438   }"
439   [(set_attr "conds" "clob")
440    (set_attr "length" "8")]
441 )
442
443 (define_expand "addsi3"
444   [(set (match_operand:SI          0 "s_register_operand" "")
445         (plus:SI (match_operand:SI 1 "s_register_operand" "")
446                  (match_operand:SI 2 "reg_or_int_operand" "")))]
447   "TARGET_EITHER"
448   "
449   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
450     {
451       arm_split_constant (PLUS, SImode, NULL_RTX,
452                           INTVAL (operands[2]), operands[0], operands[1],
453                           (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
454       DONE;
455     }
456   "
457 )
458
459 ; If there is a scratch available, this will be faster than synthesizing the
460 ; addition.
461 (define_peephole2
462   [(match_scratch:SI 3 "r")
463    (set (match_operand:SI          0 "arm_general_register_operand" "")
464         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
465                  (match_operand:SI 2 "const_int_operand"  "")))]
466   "TARGET_ARM &&
467    !(const_ok_for_arm (INTVAL (operands[2]))
468      || const_ok_for_arm (-INTVAL (operands[2])))
469     && const_ok_for_arm (~INTVAL (operands[2]))"
470   [(set (match_dup 3) (match_dup 2))
471    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
472   ""
473 )
474
475 (define_insn_and_split "*arm_addsi3"
476   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
477         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
478                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
479   "TARGET_ARM"
480   "@
481    add%?\\t%0, %1, %2
482    sub%?\\t%0, %1, #%n2
483    #"
484   "TARGET_ARM &&
485    GET_CODE (operands[2]) == CONST_INT
486    && !(const_ok_for_arm (INTVAL (operands[2]))
487         || const_ok_for_arm (-INTVAL (operands[2])))"
488   [(clobber (const_int 0))]
489   "
490   arm_split_constant (PLUS, SImode, curr_insn,
491                       INTVAL (operands[2]), operands[0],
492                       operands[1], 0);
493   DONE;
494   "
495   [(set_attr "length" "4,4,16")
496    (set_attr "predicable" "yes")]
497 )
498
499 ;; Register group 'k' is a single register group containing only the stack
500 ;; register.  Trying to reload it will always fail catastrophically,
501 ;; so never allow those alternatives to match if reloading is needed.
502
503 (define_insn "*thumb_addsi3"
504   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
505         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
506                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
507   "TARGET_THUMB"
508   "*
509    static const char * const asms[] = 
510    {
511      \"add\\t%0, %0, %2\",
512      \"sub\\t%0, %0, #%n2\",
513      \"add\\t%0, %1, %2\",
514      \"add\\t%0, %0, %2\",
515      \"add\\t%0, %0, %2\",
516      \"add\\t%0, %1, %2\",
517      \"add\\t%0, %1, %2\"
518    };
519    if ((which_alternative == 2 || which_alternative == 6)
520        && GET_CODE (operands[2]) == CONST_INT
521        && INTVAL (operands[2]) < 0)
522      return \"sub\\t%0, %1, #%n2\";
523    return asms[which_alternative];
524   "
525   [(set_attr "length" "2")]
526 )
527
528 ;; Reloading and elimination of the frame pointer can
529 ;; sometimes cause this optimization to be missed.
530 (define_peephole2
531   [(set (match_operand:SI 0 "arm_general_register_operand" "")
532         (match_operand:SI 1 "const_int_operand" ""))
533    (set (match_dup 0)
534         (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
535   "TARGET_THUMB
536    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
537    && (INTVAL (operands[1]) & 3) == 0"
538   [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
539   ""
540 )
541
542 (define_insn "*addsi3_compare0"
543   [(set (reg:CC_NOOV CC_REGNUM)
544         (compare:CC_NOOV
545          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
546                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
547          (const_int 0)))
548    (set (match_operand:SI 0 "s_register_operand" "=r,r")
549         (plus:SI (match_dup 1) (match_dup 2)))]
550   "TARGET_ARM"
551   "@
552    add%?s\\t%0, %1, %2
553    sub%?s\\t%0, %1, #%n2"
554   [(set_attr "conds" "set")]
555 )
556
557 (define_insn "*addsi3_compare0_scratch"
558   [(set (reg:CC_NOOV CC_REGNUM)
559         (compare:CC_NOOV
560          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
561                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
562          (const_int 0)))]
563   "TARGET_ARM"
564   "@
565    cmn%?\\t%0, %1
566    cmp%?\\t%0, #%n1"
567   [(set_attr "conds" "set")]
568 )
569
570 ;; These patterns are the same ones as the two regular addsi3_compare0
571 ;; patterns, except we write them slightly different - the combiner
572 ;; tends to generate them this way.
573 (define_insn "*addsi3_compare0_for_combiner"
574   [(set (reg:CC CC_REGNUM)
575         (compare:CC
576          (match_operand:SI 1 "s_register_operand" "r,r")
577          (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
578    (set (match_operand:SI 0 "s_register_operand" "=r,r")
579         (plus:SI (match_dup 1) (match_dup 2)))]
580   "TARGET_ARM"
581   "@
582    add%?s\\t%0, %1, %2
583    sub%?s\\t%0, %1, #%n2"
584   [(set_attr "conds" "set")]
585 )
586
587 (define_insn "*addsi3_compare0_scratch_for_combiner"
588   [(set (reg:CC CC_REGNUM)
589         (compare:CC
590          (match_operand:SI 0 "s_register_operand" "r,r")
591          (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
592   "TARGET_ARM"
593   "@
594    cmn%?\\t%0, %1
595    cmp%?\\t%0, #%n1"
596   [(set_attr "conds" "set")]
597 )
598
599 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
600 ;; addend is a constant.
601 (define_insn "*cmpsi2_addneg"
602   [(set (reg:CC CC_REGNUM)
603         (compare:CC
604          (match_operand:SI 1 "s_register_operand" "r,r")
605          (match_operand:SI 2 "arm_addimm_operand" "I,L")))
606    (set (match_operand:SI 0 "s_register_operand" "=r,r")
607         (plus:SI (match_dup 1)
608                  (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
609   "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
610   "@
611    sub%?s\\t%0, %1, %2
612    add%?s\\t%0, %1, #%n2"
613   [(set_attr "conds" "set")]
614 )
615
616 ;; Convert the sequence
617 ;;  sub  rd, rn, #1
618 ;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
619 ;;  bne  dest
620 ;; into
621 ;;  subs rd, rn, #1
622 ;;  bcs  dest   ((unsigned)rn >= 1)
623 ;; similarly for the beq variant using bcc.
624 ;; This is a common looping idiom (while (n--))
625 (define_peephole2
626   [(set (match_operand:SI 0 "arm_general_register_operand" "")
627         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
628                  (const_int -1)))
629    (set (match_operand 2 "cc_register" "")
630         (compare (match_dup 0) (const_int -1)))
631    (set (pc)
632         (if_then_else (match_operator 3 "equality_operator"
633                        [(match_dup 2) (const_int 0)])
634                       (match_operand 4 "" "")
635                       (match_operand 5 "" "")))]
636   "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
637   [(parallel[
638     (set (match_dup 2)
639          (compare:CC
640           (match_dup 1) (const_int 1)))
641     (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
642    (set (pc)
643         (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
644                       (match_dup 4)
645                       (match_dup 5)))]
646   "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
647    operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
648                                   ? GEU : LTU),
649                                  VOIDmode, 
650                                  operands[2], const0_rtx);"
651 )
652
653 ;; The next four insns work because they compare the result with one of
654 ;; the operands, and we know that the use of the condition code is
655 ;; either GEU or LTU, so we can use the carry flag from the addition
656 ;; instead of doing the compare a second time.
657 (define_insn "*addsi3_compare_op1"
658   [(set (reg:CC_C CC_REGNUM)
659         (compare:CC_C
660          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
661                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
662          (match_dup 1)))
663    (set (match_operand:SI 0 "s_register_operand" "=r,r")
664         (plus:SI (match_dup 1) (match_dup 2)))]
665   "TARGET_ARM"
666   "@
667    add%?s\\t%0, %1, %2
668    sub%?s\\t%0, %1, #%n2"
669   [(set_attr "conds" "set")]
670 )
671
672 (define_insn "*addsi3_compare_op2"
673   [(set (reg:CC_C CC_REGNUM)
674         (compare:CC_C
675          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
676                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
677          (match_dup 2)))
678    (set (match_operand:SI 0 "s_register_operand" "=r,r")
679         (plus:SI (match_dup 1) (match_dup 2)))]
680   "TARGET_ARM"
681   "@
682    add%?s\\t%0, %1, %2
683    sub%?s\\t%0, %1, #%n2"
684   [(set_attr "conds" "set")]
685 )
686
687 (define_insn "*compare_addsi2_op0"
688   [(set (reg:CC_C CC_REGNUM)
689         (compare:CC_C
690          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
691                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
692          (match_dup 0)))]
693   "TARGET_ARM"
694   "@
695    cmn%?\\t%0, %1
696    cmp%?\\t%0, #%n1"
697   [(set_attr "conds" "set")]
698 )
699
700 (define_insn "*compare_addsi2_op1"
701   [(set (reg:CC_C CC_REGNUM)
702         (compare:CC_C
703          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
704                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
705          (match_dup 1)))]
706   "TARGET_ARM"
707   "@
708    cmn%?\\t%0, %1
709    cmp%?\\t%0, #%n1"
710   [(set_attr "conds" "set")]
711 )
712
713 (define_insn "*addsi3_carryin"
714   [(set (match_operand:SI 0 "s_register_operand" "=r")
715         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
716                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
717                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
718   "TARGET_ARM"
719   "adc%?\\t%0, %1, %2"
720   [(set_attr "conds" "use")]
721 )
722
723 (define_insn "*addsi3_carryin_shift"
724   [(set (match_operand:SI 0 "s_register_operand" "=r")
725         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
726                  (plus:SI
727                    (match_operator:SI 2 "shift_operator"
728                       [(match_operand:SI 3 "s_register_operand" "r")
729                        (match_operand:SI 4 "reg_or_int_operand" "rM")])
730                     (match_operand:SI 1 "s_register_operand" "r"))))]
731   "TARGET_ARM"
732   "adc%?\\t%0, %1, %3%S2"
733   [(set_attr "conds" "use")
734    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
735                       (const_string "alu_shift")
736                       (const_string "alu_shift_reg")))]
737 )
738
739 (define_insn "*addsi3_carryin_alt1"
740   [(set (match_operand:SI 0 "s_register_operand" "=r")
741         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
742                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
743                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
744   "TARGET_ARM"
745   "adc%?\\t%0, %1, %2"
746   [(set_attr "conds" "use")]
747 )
748
749 (define_insn "*addsi3_carryin_alt2"
750   [(set (match_operand:SI 0 "s_register_operand" "=r")
751         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
752                           (match_operand:SI 1 "s_register_operand" "r"))
753                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
754   "TARGET_ARM"
755   "adc%?\\t%0, %1, %2"
756   [(set_attr "conds" "use")]
757 )
758
759 (define_insn "*addsi3_carryin_alt3"
760   [(set (match_operand:SI 0 "s_register_operand" "=r")
761         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
762                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
763                  (match_operand:SI 1 "s_register_operand" "r")))]
764   "TARGET_ARM"
765   "adc%?\\t%0, %1, %2"
766   [(set_attr "conds" "use")]
767 )
768
769 (define_insn "incscc"
770   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
771         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
772                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
773                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
774   "TARGET_ARM"
775   "@
776   add%d2\\t%0, %1, #1
777   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
778   [(set_attr "conds" "use")
779    (set_attr "length" "4,8")]
780 )
781
782 ; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
783 (define_split
784   [(set (match_operand:SI 0 "s_register_operand" "")
785         (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
786                             (match_operand:SI 2 "s_register_operand" ""))
787                  (const_int -1)))
788    (clobber (match_operand:SI 3 "s_register_operand" ""))]
789   "TARGET_ARM"
790   [(set (match_dup 3) (match_dup 1))
791    (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
792   "
793   operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
794 ")
795
796 (define_expand "addsf3"
797   [(set (match_operand:SF          0 "s_register_operand" "")
798         (plus:SF (match_operand:SF 1 "s_register_operand" "")
799                  (match_operand:SF 2 "arm_float_add_operand" "")))]
800   "TARGET_ARM && TARGET_HARD_FLOAT"
801   "
802   if (TARGET_MAVERICK
803       && !cirrus_fp_register (operands[2], SFmode))
804     operands[2] = force_reg (SFmode, operands[2]);
805 ")
806
807 (define_expand "adddf3"
808   [(set (match_operand:DF          0 "s_register_operand" "")
809         (plus:DF (match_operand:DF 1 "s_register_operand" "")
810                  (match_operand:DF 2 "arm_float_add_operand" "")))]
811   "TARGET_ARM && TARGET_HARD_FLOAT"
812   "
813   if (TARGET_MAVERICK
814       && !cirrus_fp_register (operands[2], DFmode))
815     operands[2] = force_reg (DFmode, operands[2]);
816 ")
817
818 (define_expand "subdi3"
819  [(parallel
820    [(set (match_operand:DI            0 "s_register_operand" "")
821           (minus:DI (match_operand:DI 1 "s_register_operand" "")
822                     (match_operand:DI 2 "s_register_operand" "")))
823     (clobber (reg:CC CC_REGNUM))])]
824   "TARGET_EITHER"
825   "
826   if (TARGET_HARD_FLOAT && TARGET_MAVERICK
827       && TARGET_ARM
828       && cirrus_fp_register (operands[0], DImode)
829       && cirrus_fp_register (operands[1], DImode))
830     {
831       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
832       DONE;
833     }
834
835   if (TARGET_THUMB)
836     {
837       if (GET_CODE (operands[1]) != REG)
838         operands[1] = force_reg (SImode, operands[1]);
839       if (GET_CODE (operands[2]) != REG)
840         operands[2] = force_reg (SImode, operands[2]);
841      }  
842   "
843 )
844
845 (define_insn "*arm_subdi3"
846   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
847         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
848                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
849    (clobber (reg:CC CC_REGNUM))]
850   "TARGET_ARM"
851   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
852   [(set_attr "conds" "clob")
853    (set_attr "length" "8")]
854 )
855
856 (define_insn "*thumb_subdi3"
857   [(set (match_operand:DI           0 "register_operand" "=l")
858         (minus:DI (match_operand:DI 1 "register_operand"  "0")
859                   (match_operand:DI 2 "register_operand"  "l")))
860    (clobber (reg:CC CC_REGNUM))]
861   "TARGET_THUMB"
862   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
863   [(set_attr "length" "4")]
864 )
865
866 (define_insn "*subdi_di_zesidi"
867   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
868         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
869                   (zero_extend:DI
870                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
871    (clobber (reg:CC CC_REGNUM))]
872   "TARGET_ARM"
873   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
874   [(set_attr "conds" "clob")
875    (set_attr "length" "8")]
876 )
877
878 (define_insn "*subdi_di_sesidi"
879   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
880         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
881                   (sign_extend:DI
882                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
883    (clobber (reg:CC CC_REGNUM))]
884   "TARGET_ARM"
885   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
886   [(set_attr "conds" "clob")
887    (set_attr "length" "8")]
888 )
889
890 (define_insn "*subdi_zesidi_di"
891   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
892         (minus:DI (zero_extend:DI
893                    (match_operand:SI 2 "s_register_operand"  "r,r"))
894                   (match_operand:DI  1 "s_register_operand" "?r,0")))
895    (clobber (reg:CC CC_REGNUM))]
896   "TARGET_ARM"
897   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
898   [(set_attr "conds" "clob")
899    (set_attr "length" "8")]
900 )
901
902 (define_insn "*subdi_sesidi_di"
903   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
904         (minus:DI (sign_extend:DI
905                    (match_operand:SI 2 "s_register_operand"   "r,r"))
906                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
907    (clobber (reg:CC CC_REGNUM))]
908   "TARGET_ARM"
909   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
910   [(set_attr "conds" "clob")
911    (set_attr "length" "8")]
912 )
913
914 (define_insn "*subdi_zesidi_zesidi"
915   [(set (match_operand:DI            0 "s_register_operand" "=r")
916         (minus:DI (zero_extend:DI
917                    (match_operand:SI 1 "s_register_operand"  "r"))
918                   (zero_extend:DI
919                    (match_operand:SI 2 "s_register_operand"  "r"))))
920    (clobber (reg:CC CC_REGNUM))]
921   "TARGET_ARM"
922   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
923   [(set_attr "conds" "clob")
924    (set_attr "length" "8")]
925 )
926
927 (define_expand "subsi3"
928   [(set (match_operand:SI           0 "s_register_operand" "")
929         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
930                   (match_operand:SI 2 "s_register_operand" "")))]
931   "TARGET_EITHER"
932   "
933   if (GET_CODE (operands[1]) == CONST_INT)
934     {
935       if (TARGET_ARM)
936         {
937           arm_split_constant (MINUS, SImode, NULL_RTX,
938                               INTVAL (operands[1]), operands[0],
939                               operands[2],
940                               (no_new_pseudos ? 0
941                                :  preserve_subexpressions_p ()));
942           DONE;
943         }
944       else /* TARGET_THUMB */
945         operands[1] = force_reg (SImode, operands[1]);
946     }
947   "
948 )
949
950 (define_insn "*thumb_subsi3_insn"
951   [(set (match_operand:SI           0 "register_operand" "=l")
952         (minus:SI (match_operand:SI 1 "register_operand" "l")
953                   (match_operand:SI 2 "register_operand" "l")))]
954   "TARGET_THUMB"
955   "sub\\t%0, %1, %2"
956   [(set_attr "length" "2")]
957 )
958
959 (define_insn_and_split "*arm_subsi3_insn"
960   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
961         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
962                   (match_operand:SI 2 "s_register_operand" "r,r")))]
963   "TARGET_ARM"
964   "@
965    rsb%?\\t%0, %2, %1
966    #"
967   "TARGET_ARM
968    && GET_CODE (operands[1]) == CONST_INT
969    && !const_ok_for_arm (INTVAL (operands[1]))"
970   [(clobber (const_int 0))]
971   "
972   arm_split_constant (MINUS, SImode, curr_insn,
973                       INTVAL (operands[1]), operands[0], operands[2], 0);
974   DONE;
975   "
976   [(set_attr "length" "4,16")
977    (set_attr "predicable" "yes")]
978 )
979
980 (define_peephole2
981   [(match_scratch:SI 3 "r")
982    (set (match_operand:SI 0 "arm_general_register_operand" "")
983         (minus:SI (match_operand:SI 1 "const_int_operand" "")
984                   (match_operand:SI 2 "arm_general_register_operand" "")))]
985   "TARGET_ARM
986    && !const_ok_for_arm (INTVAL (operands[1]))
987    && const_ok_for_arm (~INTVAL (operands[1]))"
988   [(set (match_dup 3) (match_dup 1))
989    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
990   ""
991 )
992
993 (define_insn "*subsi3_compare0"
994   [(set (reg:CC_NOOV CC_REGNUM)
995         (compare:CC_NOOV
996          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
997                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
998          (const_int 0)))
999    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1000         (minus:SI (match_dup 1) (match_dup 2)))]
1001   "TARGET_ARM"
1002   "@
1003    sub%?s\\t%0, %1, %2
1004    rsb%?s\\t%0, %2, %1"
1005   [(set_attr "conds" "set")]
1006 )
1007
1008 (define_insn "decscc"
1009   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1010         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1011                   (match_operator:SI 2 "arm_comparison_operator"
1012                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1013   "TARGET_ARM"
1014   "@
1015    sub%d2\\t%0, %1, #1
1016    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1017   [(set_attr "conds" "use")
1018    (set_attr "length" "*,8")]
1019 )
1020
1021 (define_expand "subsf3"
1022   [(set (match_operand:SF           0 "s_register_operand" "")
1023         (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1024                   (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1025   "TARGET_ARM && TARGET_HARD_FLOAT"
1026   "
1027   if (TARGET_MAVERICK)
1028     {
1029       if (!cirrus_fp_register (operands[1], SFmode))
1030         operands[1] = force_reg (SFmode, operands[1]);
1031       if (!cirrus_fp_register (operands[2], SFmode))
1032         operands[2] = force_reg (SFmode, operands[2]);
1033     }
1034 ")
1035
1036 (define_expand "subdf3"
1037   [(set (match_operand:DF           0 "s_register_operand" "")
1038         (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1039                   (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1040   "TARGET_ARM && TARGET_HARD_FLOAT"
1041   "
1042   if (TARGET_MAVERICK)
1043     {
1044        if (!cirrus_fp_register (operands[1], DFmode))
1045          operands[1] = force_reg (DFmode, operands[1]);
1046        if (!cirrus_fp_register (operands[2], DFmode))
1047          operands[2] = force_reg (DFmode, operands[2]);
1048     }
1049 ")
1050
1051 \f
1052 ;; Multiplication insns
1053
1054 (define_expand "mulsi3"
1055   [(set (match_operand:SI          0 "s_register_operand" "")
1056         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1057                  (match_operand:SI 1 "s_register_operand" "")))]
1058   "TARGET_EITHER"
1059   ""
1060 )
1061
1062 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1063 (define_insn "*arm_mulsi3"
1064   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1065         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1066                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1067   "TARGET_ARM"
1068   "mul%?\\t%0, %2, %1"
1069   [(set_attr "insn" "mul")
1070    (set_attr "predicable" "yes")]
1071 )
1072
1073 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1074 ; 1 and 2; are the same, because reload will make operand 0 match 
1075 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1076 ; this by adding another alternative to match this case, and then `reload' 
1077 ; it ourselves.  This alternative must come first.
1078 (define_insn "*thumb_mulsi3"
1079   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1080         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1081                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1082   "TARGET_THUMB"
1083   "*
1084   if (which_alternative < 2)
1085     return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1086   else
1087     return \"mul\\t%0, %0, %2\";
1088   "
1089   [(set_attr "length" "4,4,2")
1090    (set_attr "insn" "mul")]
1091 )
1092
1093 (define_insn "*mulsi3_compare0"
1094   [(set (reg:CC_NOOV CC_REGNUM)
1095         (compare:CC_NOOV (mult:SI
1096                           (match_operand:SI 2 "s_register_operand" "r,r")
1097                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1098                          (const_int 0)))
1099    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1100         (mult:SI (match_dup 2) (match_dup 1)))]
1101   "TARGET_ARM && !arm_arch_xscale"
1102   "mul%?s\\t%0, %2, %1"
1103   [(set_attr "conds" "set")
1104    (set_attr "insn" "muls")]
1105 )
1106
1107 (define_insn "*mulsi_compare0_scratch"
1108   [(set (reg:CC_NOOV CC_REGNUM)
1109         (compare:CC_NOOV (mult:SI
1110                           (match_operand:SI 2 "s_register_operand" "r,r")
1111                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1112                          (const_int 0)))
1113    (clobber (match_scratch:SI 0 "=&r,&r"))]
1114   "TARGET_ARM && !arm_arch_xscale"
1115   "mul%?s\\t%0, %2, %1"
1116   [(set_attr "conds" "set")
1117    (set_attr "insn" "muls")]
1118 )
1119
1120 ;; Unnamed templates to match MLA instruction.
1121
1122 (define_insn "*mulsi3addsi"
1123   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1124         (plus:SI
1125           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1126                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1127           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1128   "TARGET_ARM"
1129   "mla%?\\t%0, %2, %1, %3"
1130   [(set_attr "insn" "mla")
1131    (set_attr "predicable" "yes")]
1132 )
1133
1134 (define_insn "*mulsi3addsi_compare0"
1135   [(set (reg:CC_NOOV CC_REGNUM)
1136         (compare:CC_NOOV
1137          (plus:SI (mult:SI
1138                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1139                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1140                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1141          (const_int 0)))
1142    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1143         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1144                  (match_dup 3)))]
1145   "TARGET_ARM && !arm_arch_xscale"
1146   "mla%?s\\t%0, %2, %1, %3"
1147   [(set_attr "conds" "set")
1148    (set_attr "insn" "mlas")]
1149 )
1150
1151 (define_insn "*mulsi3addsi_compare0_scratch"
1152   [(set (reg:CC_NOOV CC_REGNUM)
1153         (compare:CC_NOOV
1154          (plus:SI (mult:SI
1155                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1156                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1157                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1158          (const_int 0)))
1159    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1160   "TARGET_ARM && !arm_arch_xscale"
1161   "mla%?s\\t%0, %2, %1, %3"
1162   [(set_attr "conds" "set")
1163    (set_attr "insn" "mlas")]
1164 )
1165
1166 ;; Unnamed template to match long long multiply-accumulate (smlal)
1167
1168 (define_insn "*mulsidi3adddi"
1169   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1170         (plus:DI
1171          (mult:DI
1172           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1173           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1174          (match_operand:DI 1 "s_register_operand" "0")))]
1175   "TARGET_ARM && arm_arch3m"
1176   "smlal%?\\t%Q0, %R0, %3, %2"
1177   [(set_attr "insn" "smlal")
1178    (set_attr "predicable" "yes")]
1179 )
1180
1181 (define_insn "mulsidi3"
1182   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1183         (mult:DI
1184          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1185          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1186   "TARGET_ARM && arm_arch3m"
1187   "smull%?\\t%Q0, %R0, %1, %2"
1188   [(set_attr "insn" "smull")
1189    (set_attr "predicable" "yes")]
1190 )
1191
1192 (define_insn "umulsidi3"
1193   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1194         (mult:DI
1195          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1196          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1197   "TARGET_ARM && arm_arch3m"
1198   "umull%?\\t%Q0, %R0, %1, %2"
1199   [(set_attr "insn" "umull")
1200    (set_attr "predicable" "yes")]
1201 )
1202
1203 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1204
1205 (define_insn "*umulsidi3adddi"
1206   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1207         (plus:DI
1208          (mult:DI
1209           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1210           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1211          (match_operand:DI 1 "s_register_operand" "0")))]
1212   "TARGET_ARM && arm_arch3m"
1213   "umlal%?\\t%Q0, %R0, %3, %2"
1214   [(set_attr "insn" "umlal")
1215    (set_attr "predicable" "yes")]
1216 )
1217
1218 (define_insn "smulsi3_highpart"
1219   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1220         (truncate:SI
1221          (lshiftrt:DI
1222           (mult:DI
1223            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1224            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1225           (const_int 32))))
1226    (clobber (match_scratch:SI 3 "=&r,&r"))]
1227   "TARGET_ARM && arm_arch3m"
1228   "smull%?\\t%3, %0, %2, %1"
1229   [(set_attr "insn" "smull")
1230    (set_attr "predicable" "yes")]
1231 )
1232
1233 (define_insn "umulsi3_highpart"
1234   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1235         (truncate:SI
1236          (lshiftrt:DI
1237           (mult:DI
1238            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1239            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1240           (const_int 32))))
1241    (clobber (match_scratch:SI 3 "=&r,&r"))]
1242   "TARGET_ARM && arm_arch3m"
1243   "umull%?\\t%3, %0, %2, %1"
1244   [(set_attr "insn" "umull")
1245    (set_attr "predicable" "yes")]
1246 )
1247
1248 (define_insn "mulhisi3"
1249   [(set (match_operand:SI 0 "s_register_operand" "=r")
1250         (mult:SI (sign_extend:SI
1251                   (match_operand:HI 1 "s_register_operand" "%r"))
1252                  (sign_extend:SI
1253                   (match_operand:HI 2 "s_register_operand" "r"))))]
1254   "TARGET_ARM && arm_arch5e"
1255   "smulbb%?\\t%0, %1, %2"
1256   [(set_attr "insn" "smulxy")
1257    (set_attr "predicable" "yes")]
1258 )
1259
1260 (define_insn "*mulhisi3tb"
1261   [(set (match_operand:SI 0 "s_register_operand" "=r")
1262         (mult:SI (ashiftrt:SI
1263                   (match_operand:SI 1 "s_register_operand" "r")
1264                   (const_int 16))
1265                  (sign_extend:SI
1266                   (match_operand:HI 2 "s_register_operand" "r"))))]
1267   "TARGET_ARM && arm_arch5e"
1268   "smultb%?\\t%0, %1, %2"
1269   [(set_attr "insn" "smulxy")
1270    (set_attr "predicable" "yes")]
1271 )
1272
1273 (define_insn "*mulhisi3bt"
1274   [(set (match_operand:SI 0 "s_register_operand" "=r")
1275         (mult:SI (sign_extend:SI
1276                   (match_operand:HI 1 "s_register_operand" "r"))
1277                  (ashiftrt:SI
1278                   (match_operand:SI 2 "s_register_operand" "r")
1279                   (const_int 16))))]
1280   "TARGET_ARM && arm_arch5e"
1281   "smulbt%?\\t%0, %1, %2"
1282   [(set_attr "insn" "smulxy")
1283    (set_attr "predicable" "yes")]
1284 )
1285
1286 (define_insn "*mulhisi3tt"
1287   [(set (match_operand:SI 0 "s_register_operand" "=r")
1288         (mult:SI (ashiftrt:SI
1289                   (match_operand:SI 1 "s_register_operand" "r")
1290                   (const_int 16))
1291                  (ashiftrt:SI
1292                   (match_operand:SI 2 "s_register_operand" "r")
1293                   (const_int 16))))]
1294   "TARGET_ARM && arm_arch5e"
1295   "smultt%?\\t%0, %1, %2"
1296   [(set_attr "insn" "smulxy")
1297    (set_attr "predicable" "yes")]
1298 )
1299
1300 (define_insn "*mulhisi3addsi"
1301   [(set (match_operand:SI 0 "s_register_operand" "=r")
1302         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1303                  (mult:SI (sign_extend:SI
1304                            (match_operand:HI 2 "s_register_operand" "%r"))
1305                           (sign_extend:SI
1306                            (match_operand:HI 3 "s_register_operand" "r")))))]
1307   "TARGET_ARM && arm_arch5e"
1308   "smlabb%?\\t%0, %2, %3, %1"
1309   [(set_attr "insn" "smlaxy")
1310    (set_attr "predicable" "yes")]
1311 )
1312
1313 (define_insn "*mulhidi3adddi"
1314   [(set (match_operand:DI 0 "s_register_operand" "=r")
1315         (plus:DI
1316           (match_operand:DI 1 "s_register_operand" "0")
1317           (mult:DI (sign_extend:DI
1318                     (match_operand:HI 2 "s_register_operand" "%r"))
1319                    (sign_extend:DI
1320                     (match_operand:HI 3 "s_register_operand" "r")))))]
1321   "TARGET_ARM && arm_arch5e"
1322   "smlalbb%?\\t%Q0, %R0, %2, %3"
1323   [(set_attr "insn" "smlalxy")
1324    (set_attr "predicable" "yes")])
1325
1326 (define_expand "mulsf3"
1327   [(set (match_operand:SF          0 "s_register_operand" "")
1328         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1329                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1330   "TARGET_ARM && TARGET_HARD_FLOAT"
1331   "
1332   if (TARGET_MAVERICK
1333       && !cirrus_fp_register (operands[2], SFmode))
1334     operands[2] = force_reg (SFmode, operands[2]);
1335 ")
1336
1337 (define_expand "muldf3"
1338   [(set (match_operand:DF          0 "s_register_operand" "")
1339         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1340                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1341   "TARGET_ARM && TARGET_HARD_FLOAT"
1342   "
1343   if (TARGET_MAVERICK
1344       && !cirrus_fp_register (operands[2], DFmode))
1345     operands[2] = force_reg (DFmode, operands[2]);
1346 ")
1347 \f
1348 ;; Division insns
1349
1350 (define_expand "divsf3"
1351   [(set (match_operand:SF 0 "s_register_operand" "")
1352         (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1353                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1354   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1355   "")
1356
1357 (define_expand "divdf3"
1358   [(set (match_operand:DF 0 "s_register_operand" "")
1359         (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1360                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1361   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1362   "")
1363 \f
1364 ;; Modulo insns
1365
1366 (define_expand "modsf3"
1367   [(set (match_operand:SF 0 "s_register_operand" "")
1368         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1369                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1370   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1371   "")
1372
1373 (define_expand "moddf3"
1374   [(set (match_operand:DF 0 "s_register_operand" "")
1375         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1376                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1377   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1378   "")
1379 \f
1380 ;; Boolean and,ior,xor insns
1381
1382 ;; Split up double word logical operations
1383
1384 ;; Split up simple DImode logical operations.  Simply perform the logical
1385 ;; operation on the upper and lower halves of the registers.
1386 (define_split
1387   [(set (match_operand:DI 0 "s_register_operand" "")
1388         (match_operator:DI 6 "logical_binary_operator"
1389           [(match_operand:DI 1 "s_register_operand" "")
1390            (match_operand:DI 2 "s_register_operand" "")]))]
1391   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1392   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1393    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1394   "
1395   {
1396     operands[3] = gen_highpart (SImode, operands[0]);
1397     operands[0] = gen_lowpart (SImode, operands[0]);
1398     operands[4] = gen_highpart (SImode, operands[1]);
1399     operands[1] = gen_lowpart (SImode, operands[1]);
1400     operands[5] = gen_highpart (SImode, operands[2]);
1401     operands[2] = gen_lowpart (SImode, operands[2]);
1402   }"
1403 )
1404
1405 (define_split
1406   [(set (match_operand:DI 0 "s_register_operand" "")
1407         (match_operator:DI 6 "logical_binary_operator"
1408           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1409            (match_operand:DI 1 "s_register_operand" "")]))]
1410   "TARGET_ARM && reload_completed"
1411   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1412    (set (match_dup 3) (match_op_dup:SI 6
1413                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1414                          (match_dup 4)]))]
1415   "
1416   {
1417     operands[3] = gen_highpart (SImode, operands[0]);
1418     operands[0] = gen_lowpart (SImode, operands[0]);
1419     operands[4] = gen_highpart (SImode, operands[1]);
1420     operands[1] = gen_lowpart (SImode, operands[1]);
1421     operands[5] = gen_highpart (SImode, operands[2]);
1422     operands[2] = gen_lowpart (SImode, operands[2]);
1423   }"
1424 )
1425
1426 ;; The zero extend of operand 2 means we can just copy the high part of
1427 ;; operand1 into operand0.
1428 (define_split
1429   [(set (match_operand:DI 0 "s_register_operand" "")
1430         (ior:DI
1431           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1432           (match_operand:DI 1 "s_register_operand" "")))]
1433   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1434   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1435    (set (match_dup 3) (match_dup 4))]
1436   "
1437   {
1438     operands[4] = gen_highpart (SImode, operands[1]);
1439     operands[3] = gen_highpart (SImode, operands[0]);
1440     operands[0] = gen_lowpart (SImode, operands[0]);
1441     operands[1] = gen_lowpart (SImode, operands[1]);
1442   }"
1443 )
1444
1445 ;; The zero extend of operand 2 means we can just copy the high part of
1446 ;; operand1 into operand0.
1447 (define_split
1448   [(set (match_operand:DI 0 "s_register_operand" "")
1449         (xor:DI
1450           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1451           (match_operand:DI 1 "s_register_operand" "")))]
1452   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1453   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1454    (set (match_dup 3) (match_dup 4))]
1455   "
1456   {
1457     operands[4] = gen_highpart (SImode, operands[1]);
1458     operands[3] = gen_highpart (SImode, operands[0]);
1459     operands[0] = gen_lowpart (SImode, operands[0]);
1460     operands[1] = gen_lowpart (SImode, operands[1]);
1461   }"
1462 )
1463
1464 (define_insn "anddi3"
1465   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1466         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1467                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1468   "TARGET_ARM && ! TARGET_IWMMXT"
1469   "#"
1470   [(set_attr "length" "8")]
1471 )
1472
1473 (define_insn_and_split "*anddi_zesidi_di"
1474   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1475         (and:DI (zero_extend:DI
1476                  (match_operand:SI 2 "s_register_operand" "r,r"))
1477                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1478   "TARGET_ARM"
1479   "#"
1480   "TARGET_ARM && reload_completed"
1481   ; The zero extend of operand 2 clears the high word of the output
1482   ; operand.
1483   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1484    (set (match_dup 3) (const_int 0))]
1485   "
1486   {
1487     operands[3] = gen_highpart (SImode, operands[0]);
1488     operands[0] = gen_lowpart (SImode, operands[0]);
1489     operands[1] = gen_lowpart (SImode, operands[1]);
1490   }"
1491   [(set_attr "length" "8")]
1492 )
1493
1494 (define_insn "*anddi_sesdi_di"
1495   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1496         (and:DI (sign_extend:DI
1497                  (match_operand:SI 2 "s_register_operand" "r,r"))
1498                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1499   "TARGET_ARM"
1500   "#"
1501   [(set_attr "length" "8")]
1502 )
1503
1504 (define_expand "andsi3"
1505   [(set (match_operand:SI         0 "s_register_operand" "")
1506         (and:SI (match_operand:SI 1 "s_register_operand" "")
1507                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1508   "TARGET_EITHER"
1509   "
1510   if (TARGET_ARM)
1511     {
1512       if (GET_CODE (operands[2]) == CONST_INT)
1513         {
1514           arm_split_constant (AND, SImode, NULL_RTX,
1515                               INTVAL (operands[2]), operands[0],
1516                               operands[1],
1517                               (no_new_pseudos
1518                                ? 0 : preserve_subexpressions_p ()));
1519           DONE;
1520         }
1521     }
1522   else /* TARGET_THUMB */
1523     {
1524       if (GET_CODE (operands[2]) != CONST_INT)
1525         operands[2] = force_reg (SImode, operands[2]);
1526       else
1527         {
1528           int i;
1529           
1530           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1531             {
1532               operands[2] = force_reg (SImode,
1533                                        GEN_INT (~INTVAL (operands[2])));
1534               
1535               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1536               
1537               DONE;
1538             }
1539
1540           for (i = 9; i <= 31; i++)
1541             {
1542               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1543                 {
1544                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1545                                         const0_rtx));
1546                   DONE;
1547                 }
1548               else if ((((HOST_WIDE_INT) 1) << i) - 1
1549                        == ~INTVAL (operands[2]))
1550                 {
1551                   rtx shift = GEN_INT (i);
1552                   rtx reg = gen_reg_rtx (SImode);
1553                 
1554                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1555                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1556                   
1557                   DONE;
1558                 }
1559             }
1560
1561           operands[2] = force_reg (SImode, operands[2]);
1562         }
1563     }
1564   "
1565 )
1566
1567 (define_insn_and_split "*arm_andsi3_insn"
1568   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1569         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1570                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1571   "TARGET_ARM"
1572   "@
1573    and%?\\t%0, %1, %2
1574    bic%?\\t%0, %1, #%B2
1575    #"
1576   "TARGET_ARM
1577    && GET_CODE (operands[2]) == CONST_INT
1578    && !(const_ok_for_arm (INTVAL (operands[2]))
1579         || const_ok_for_arm (~INTVAL (operands[2])))"
1580   [(clobber (const_int 0))]
1581   "
1582   arm_split_constant  (AND, SImode, curr_insn, 
1583                        INTVAL (operands[2]), operands[0], operands[1], 0);
1584   DONE;
1585   "
1586   [(set_attr "length" "4,4,16")
1587    (set_attr "predicable" "yes")]
1588 )
1589
1590 (define_insn "*thumb_andsi3_insn"
1591   [(set (match_operand:SI         0 "register_operand" "=l")
1592         (and:SI (match_operand:SI 1 "register_operand" "%0")
1593                 (match_operand:SI 2 "register_operand" "l")))]
1594   "TARGET_THUMB"
1595   "and\\t%0, %0, %2"
1596   [(set_attr "length" "2")]
1597 )
1598
1599 (define_insn "*andsi3_compare0"
1600   [(set (reg:CC_NOOV CC_REGNUM)
1601         (compare:CC_NOOV
1602          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1603                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1604          (const_int 0)))
1605    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1606         (and:SI (match_dup 1) (match_dup 2)))]
1607   "TARGET_ARM"
1608   "@
1609    and%?s\\t%0, %1, %2
1610    bic%?s\\t%0, %1, #%B2"
1611   [(set_attr "conds" "set")]
1612 )
1613
1614 (define_insn "*andsi3_compare0_scratch"
1615   [(set (reg:CC_NOOV CC_REGNUM)
1616         (compare:CC_NOOV
1617          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1618                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1619          (const_int 0)))
1620    (clobber (match_scratch:SI 2 "=X,r"))]
1621   "TARGET_ARM"
1622   "@
1623    tst%?\\t%0, %1
1624    bic%?s\\t%2, %0, #%B1"
1625   [(set_attr "conds" "set")]
1626 )
1627
1628 (define_insn "*zeroextractsi_compare0_scratch"
1629   [(set (reg:CC_NOOV CC_REGNUM)
1630         (compare:CC_NOOV (zero_extract:SI
1631                           (match_operand:SI 0 "s_register_operand" "r")
1632                           (match_operand 1 "const_int_operand" "n")
1633                           (match_operand 2 "const_int_operand" "n"))
1634                          (const_int 0)))]
1635   "TARGET_ARM
1636   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1637       && INTVAL (operands[1]) > 0 
1638       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1639       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1640   "*
1641   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1642                          << INTVAL (operands[2]));
1643   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1644   return \"\";
1645   "
1646   [(set_attr "conds" "set")]
1647 )
1648
1649 (define_insn_and_split "*ne_zeroextractsi"
1650   [(set (match_operand:SI 0 "s_register_operand" "=r")
1651         (ne:SI (zero_extract:SI
1652                 (match_operand:SI 1 "s_register_operand" "r")
1653                 (match_operand:SI 2 "const_int_operand" "n")
1654                 (match_operand:SI 3 "const_int_operand" "n"))
1655                (const_int 0)))
1656    (clobber (reg:CC CC_REGNUM))]
1657   "TARGET_ARM
1658    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1659        && INTVAL (operands[2]) > 0 
1660        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1661        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1662   "#"
1663   "TARGET_ARM
1664    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1665        && INTVAL (operands[2]) > 0 
1666        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1667        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1668   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1669                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1670                                     (const_int 0)))
1671               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1672    (set (match_dup 0)
1673         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1674                          (match_dup 0) (const_int 1)))]
1675   "
1676   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1677                          << INTVAL (operands[3])); 
1678   "
1679   [(set_attr "conds" "clob")
1680    (set_attr "length" "8")]
1681 )
1682
1683 (define_insn_and_split "*ne_zeroextractsi_shifted"
1684   [(set (match_operand:SI 0 "s_register_operand" "=r")
1685         (ne:SI (zero_extract:SI
1686                 (match_operand:SI 1 "s_register_operand" "r")
1687                 (match_operand:SI 2 "const_int_operand" "n")
1688                 (const_int 0))
1689                (const_int 0)))
1690    (clobber (reg:CC CC_REGNUM))]
1691   "TARGET_ARM"
1692   "#"
1693   "TARGET_ARM"
1694   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1695                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1696                                     (const_int 0)))
1697               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1698    (set (match_dup 0)
1699         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1700                          (match_dup 0) (const_int 1)))]
1701   "
1702   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1703   "
1704   [(set_attr "conds" "clob")
1705    (set_attr "length" "8")]
1706 )
1707
1708 (define_insn_and_split "*ite_ne_zeroextractsi"
1709   [(set (match_operand:SI 0 "s_register_operand" "=r")
1710         (if_then_else:SI (ne (zero_extract:SI
1711                               (match_operand:SI 1 "s_register_operand" "r")
1712                               (match_operand:SI 2 "const_int_operand" "n")
1713                               (match_operand:SI 3 "const_int_operand" "n"))
1714                              (const_int 0))
1715                          (match_operand:SI 4 "arm_not_operand" "rIK")
1716                          (const_int 0)))
1717    (clobber (reg:CC CC_REGNUM))]
1718   "TARGET_ARM
1719    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1720        && INTVAL (operands[2]) > 0 
1721        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1722        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1723    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1724   "#"
1725   "TARGET_ARM
1726    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1727        && INTVAL (operands[2]) > 0 
1728        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1729        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1730    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1731   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1732                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1733                                     (const_int 0)))
1734               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1735    (set (match_dup 0)
1736         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1737                          (match_dup 0) (match_dup 4)))]
1738   "
1739   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1740                          << INTVAL (operands[3])); 
1741   "
1742   [(set_attr "conds" "clob")
1743    (set_attr "length" "8")]
1744 )
1745
1746 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1747   [(set (match_operand:SI 0 "s_register_operand" "=r")
1748         (if_then_else:SI (ne (zero_extract:SI
1749                               (match_operand:SI 1 "s_register_operand" "r")
1750                               (match_operand:SI 2 "const_int_operand" "n")
1751                               (const_int 0))
1752                              (const_int 0))
1753                          (match_operand:SI 3 "arm_not_operand" "rIK")
1754                          (const_int 0)))
1755    (clobber (reg:CC CC_REGNUM))]
1756   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1757   "#"
1758   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1759   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1760                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1761                                     (const_int 0)))
1762               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1763    (set (match_dup 0)
1764         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1765                          (match_dup 0) (match_dup 3)))]
1766   "
1767   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1768   "
1769   [(set_attr "conds" "clob")
1770    (set_attr "length" "8")]
1771 )
1772
1773 (define_split
1774   [(set (match_operand:SI 0 "s_register_operand" "")
1775         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1776                          (match_operand:SI 2 "const_int_operand" "")
1777                          (match_operand:SI 3 "const_int_operand" "")))
1778    (clobber (match_operand:SI 4 "s_register_operand" ""))]
1779   "TARGET_THUMB"
1780   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1781    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1782   "{
1783      HOST_WIDE_INT temp = INTVAL (operands[2]);
1784
1785      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1786      operands[3] = GEN_INT (32 - temp);
1787    }"
1788 )
1789
1790 (define_split
1791   [(set (match_operand:SI 0 "s_register_operand" "")
1792         (match_operator:SI 1 "shiftable_operator"
1793          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1794                            (match_operand:SI 3 "const_int_operand" "")
1795                            (match_operand:SI 4 "const_int_operand" ""))
1796           (match_operand:SI 5 "s_register_operand" "")]))
1797    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1798   "TARGET_ARM"
1799   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1800    (set (match_dup 0)
1801         (match_op_dup 1
1802          [(lshiftrt:SI (match_dup 6) (match_dup 4))
1803           (match_dup 5)]))]
1804   "{
1805      HOST_WIDE_INT temp = INTVAL (operands[3]);
1806
1807      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1808      operands[4] = GEN_INT (32 - temp);
1809    }"
1810 )
1811   
1812 (define_split
1813   [(set (match_operand:SI 0 "s_register_operand" "")
1814         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1815                          (match_operand:SI 2 "const_int_operand" "")
1816                          (match_operand:SI 3 "const_int_operand" "")))]
1817   "TARGET_THUMB"
1818   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1819    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1820   "{
1821      HOST_WIDE_INT temp = INTVAL (operands[2]);
1822
1823      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1824      operands[3] = GEN_INT (32 - temp);
1825    }"
1826 )
1827
1828 (define_split
1829   [(set (match_operand:SI 0 "s_register_operand" "")
1830         (match_operator:SI 1 "shiftable_operator"
1831          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1832                            (match_operand:SI 3 "const_int_operand" "")
1833                            (match_operand:SI 4 "const_int_operand" ""))
1834           (match_operand:SI 5 "s_register_operand" "")]))
1835    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1836   "TARGET_ARM"
1837   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1838    (set (match_dup 0)
1839         (match_op_dup 1
1840          [(ashiftrt:SI (match_dup 6) (match_dup 4))
1841           (match_dup 5)]))]
1842   "{
1843      HOST_WIDE_INT temp = INTVAL (operands[3]);
1844
1845      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1846      operands[4] = GEN_INT (32 - temp);
1847    }"
1848 )
1849   
1850 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1851 ;;; represented by the bitfield, then this will produce incorrect results.
1852 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1853 ;;; which have a real bit-field insert instruction, the truncation happens
1854 ;;; in the bit-field insert instruction itself.  Since arm does not have a
1855 ;;; bit-field insert instruction, we would have to emit code here to truncate
1856 ;;; the value before we insert.  This loses some of the advantage of having
1857 ;;; this insv pattern, so this pattern needs to be reevalutated.
1858
1859 (define_expand "insv"
1860   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1861                          (match_operand:SI 1 "general_operand" "")
1862                          (match_operand:SI 2 "general_operand" ""))
1863         (match_operand:SI 3 "reg_or_int_operand" ""))]
1864   "TARGET_ARM"
1865   "
1866   {
1867     int start_bit = INTVAL (operands[2]);
1868     int width = INTVAL (operands[1]);
1869     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1870     rtx target, subtarget;
1871
1872     target = operands[0];
1873     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1874        subreg as the final target.  */
1875     if (GET_CODE (target) == SUBREG)
1876       {
1877         subtarget = gen_reg_rtx (SImode);
1878         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1879             < GET_MODE_SIZE (SImode))
1880           target = SUBREG_REG (target);
1881       }
1882     else
1883       subtarget = target;    
1884
1885     if (GET_CODE (operands[3]) == CONST_INT)
1886       {
1887         /* Since we are inserting a known constant, we may be able to
1888            reduce the number of bits that we have to clear so that
1889            the mask becomes simple.  */
1890         /* ??? This code does not check to see if the new mask is actually
1891            simpler.  It may not be.  */
1892         rtx op1 = gen_reg_rtx (SImode);
1893         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1894            start of this pattern.  */
1895         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1896         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1897
1898         emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1899         emit_insn (gen_iorsi3 (subtarget, op1,
1900                                GEN_INT (op3_value << start_bit)));
1901       }
1902     else if (start_bit == 0
1903              && !(const_ok_for_arm (mask)
1904                   || const_ok_for_arm (~mask)))
1905       {
1906         /* A Trick, since we are setting the bottom bits in the word,
1907            we can shift operand[3] up, operand[0] down, OR them together
1908            and rotate the result back again.  This takes 3 insns, and
1909            the third might be mergeable into another op.  */
1910         /* The shift up copes with the possibility that operand[3] is
1911            wider than the bitfield.  */
1912         rtx op0 = gen_reg_rtx (SImode);
1913         rtx op1 = gen_reg_rtx (SImode);
1914
1915         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1916         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1917         emit_insn (gen_iorsi3  (op1, op1, op0));
1918         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1919       }
1920     else if ((width + start_bit == 32)
1921              && !(const_ok_for_arm (mask)
1922                   || const_ok_for_arm (~mask)))
1923       {
1924         /* Similar trick, but slightly less efficient.  */
1925
1926         rtx op0 = gen_reg_rtx (SImode);
1927         rtx op1 = gen_reg_rtx (SImode);
1928
1929         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1930         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1931         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1932         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1933       }
1934     else
1935       {
1936         rtx op0 = GEN_INT (mask);
1937         rtx op1 = gen_reg_rtx (SImode);
1938         rtx op2 = gen_reg_rtx (SImode);
1939
1940         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1941           {
1942             rtx tmp = gen_reg_rtx (SImode);
1943
1944             emit_insn (gen_movsi (tmp, op0));
1945             op0 = tmp;
1946           }
1947
1948         /* Mask out any bits in operand[3] that are not needed.  */
1949            emit_insn (gen_andsi3 (op1, operands[3], op0));
1950
1951         if (GET_CODE (op0) == CONST_INT
1952             && (const_ok_for_arm (mask << start_bit)
1953                 || const_ok_for_arm (~(mask << start_bit))))
1954           {
1955             op0 = GEN_INT (~(mask << start_bit));
1956             emit_insn (gen_andsi3 (op2, operands[0], op0));
1957           }
1958         else
1959           {
1960             if (GET_CODE (op0) == CONST_INT)
1961               {
1962                 rtx tmp = gen_reg_rtx (SImode);
1963
1964                 emit_insn (gen_movsi (tmp, op0));
1965                 op0 = tmp;
1966               }
1967
1968             if (start_bit != 0)
1969               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1970             
1971             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1972           }
1973
1974         if (start_bit != 0)
1975           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1976
1977         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1978       }
1979
1980     if (subtarget != target)
1981       {
1982         /* If TARGET is still a SUBREG, then it must be wider than a word,
1983            so we must be careful only to set the subword we were asked to.  */
1984         if (GET_CODE (target) == SUBREG)
1985           emit_move_insn (target, subtarget);
1986         else
1987           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1988       }
1989
1990     DONE;
1991   }"
1992 )
1993
1994 ; constants for op 2 will never be given to these patterns.
1995 (define_insn_and_split "*anddi_notdi_di"
1996   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1997         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1998                 (match_operand:DI 2 "s_register_operand" "0,r")))]
1999   "TARGET_ARM"
2000   "#"
2001   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2002   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2003    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2004   "
2005   {
2006     operands[3] = gen_highpart (SImode, operands[0]);
2007     operands[0] = gen_lowpart (SImode, operands[0]);
2008     operands[4] = gen_highpart (SImode, operands[1]);
2009     operands[1] = gen_lowpart (SImode, operands[1]);
2010     operands[5] = gen_highpart (SImode, operands[2]);
2011     operands[2] = gen_lowpart (SImode, operands[2]);
2012   }"
2013   [(set_attr "length" "8")
2014    (set_attr "predicable" "yes")]
2015 )
2016   
2017 (define_insn_and_split "*anddi_notzesidi_di"
2018   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2019         (and:DI (not:DI (zero_extend:DI
2020                          (match_operand:SI 2 "s_register_operand" "r,r")))
2021                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2022   "TARGET_ARM"
2023   "@
2024    bic%?\\t%Q0, %Q1, %2
2025    #"
2026   ; (not (zero_extend ...)) allows us to just copy the high word from
2027   ; operand1 to operand0.
2028   "TARGET_ARM
2029    && reload_completed
2030    && operands[0] != operands[1]"
2031   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2032    (set (match_dup 3) (match_dup 4))]
2033   "
2034   {
2035     operands[3] = gen_highpart (SImode, operands[0]);
2036     operands[0] = gen_lowpart (SImode, operands[0]);
2037     operands[4] = gen_highpart (SImode, operands[1]);
2038     operands[1] = gen_lowpart (SImode, operands[1]);
2039   }"
2040   [(set_attr "length" "4,8")
2041    (set_attr "predicable" "yes")]
2042 )
2043   
2044 (define_insn_and_split "*anddi_notsesidi_di"
2045   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2046         (and:DI (not:DI (sign_extend:DI
2047                          (match_operand:SI 2 "s_register_operand" "r,r")))
2048                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2049   "TARGET_ARM"
2050   "#"
2051   "TARGET_ARM && reload_completed"
2052   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2053    (set (match_dup 3) (and:SI (not:SI
2054                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2055                                (match_dup 4)))]
2056   "
2057   {
2058     operands[3] = gen_highpart (SImode, operands[0]);
2059     operands[0] = gen_lowpart (SImode, operands[0]);
2060     operands[4] = gen_highpart (SImode, operands[1]);
2061     operands[1] = gen_lowpart (SImode, operands[1]);
2062   }"
2063   [(set_attr "length" "8")
2064    (set_attr "predicable" "yes")]
2065 )
2066   
2067 (define_insn "andsi_notsi_si"
2068   [(set (match_operand:SI 0 "s_register_operand" "=r")
2069         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2070                 (match_operand:SI 1 "s_register_operand" "r")))]
2071   "TARGET_ARM"
2072   "bic%?\\t%0, %1, %2"
2073   [(set_attr "predicable" "yes")]
2074 )
2075
2076 (define_insn "bicsi3"
2077   [(set (match_operand:SI                 0 "register_operand" "=l")
2078         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2079                 (match_operand:SI         2 "register_operand" "0")))]
2080   "TARGET_THUMB"
2081   "bic\\t%0, %0, %1"
2082   [(set_attr "length" "2")]
2083 )
2084
2085 (define_insn "andsi_not_shiftsi_si"
2086   [(set (match_operand:SI 0 "s_register_operand" "=r")
2087         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2088                          [(match_operand:SI 2 "s_register_operand" "r")
2089                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2090                 (match_operand:SI 1 "s_register_operand" "r")))]
2091   "TARGET_ARM"
2092   "bic%?\\t%0, %1, %2%S4"
2093   [(set_attr "predicable" "yes")
2094    (set_attr "shift" "2")
2095    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2096                       (const_string "alu_shift")
2097                       (const_string "alu_shift_reg")))]
2098 )
2099
2100 (define_insn "*andsi_notsi_si_compare0"
2101   [(set (reg:CC_NOOV CC_REGNUM)
2102         (compare:CC_NOOV
2103          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2104                  (match_operand:SI 1 "s_register_operand" "r"))
2105          (const_int 0)))
2106    (set (match_operand:SI 0 "s_register_operand" "=r")
2107         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2108   "TARGET_ARM"
2109   "bic%?s\\t%0, %1, %2"
2110   [(set_attr "conds" "set")]
2111 )
2112
2113 (define_insn "*andsi_notsi_si_compare0_scratch"
2114   [(set (reg:CC_NOOV CC_REGNUM)
2115         (compare:CC_NOOV
2116          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2117                  (match_operand:SI 1 "s_register_operand" "r"))
2118          (const_int 0)))
2119    (clobber (match_scratch:SI 0 "=r"))]
2120   "TARGET_ARM"
2121   "bic%?s\\t%0, %1, %2"
2122   [(set_attr "conds" "set")]
2123 )
2124
2125 (define_insn "iordi3"
2126   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2127         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2128                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2129   "TARGET_ARM && ! TARGET_IWMMXT"
2130   "#"
2131   [(set_attr "length" "8")
2132    (set_attr "predicable" "yes")]
2133 )
2134
2135 (define_insn "*iordi_zesidi_di"
2136   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2137         (ior:DI (zero_extend:DI
2138                  (match_operand:SI 2 "s_register_operand" "r,r"))
2139                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2140   "TARGET_ARM"
2141   "@
2142    orr%?\\t%Q0, %Q1, %2
2143    #"
2144   [(set_attr "length" "4,8")
2145    (set_attr "predicable" "yes")]
2146 )
2147
2148 (define_insn "*iordi_sesidi_di"
2149   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2150         (ior:DI (sign_extend:DI
2151                  (match_operand:SI 2 "s_register_operand" "r,r"))
2152                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2153   "TARGET_ARM"
2154   "#"
2155   [(set_attr "length" "8")
2156    (set_attr "predicable" "yes")]
2157 )
2158
2159 (define_expand "iorsi3"
2160   [(set (match_operand:SI         0 "s_register_operand" "")
2161         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2162                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2163   "TARGET_EITHER"
2164   "
2165   if (GET_CODE (operands[2]) == CONST_INT)
2166     {
2167       if (TARGET_ARM)
2168         {
2169           arm_split_constant (IOR, SImode, NULL_RTX,
2170                               INTVAL (operands[2]), operands[0], operands[1],
2171                               (no_new_pseudos
2172                               ? 0 : preserve_subexpressions_p ()));
2173           DONE;
2174         }
2175       else /* TARGET_THUMB */
2176         operands [2] = force_reg (SImode, operands [2]);
2177     }
2178   "
2179 )
2180
2181 (define_insn_and_split "*arm_iorsi3"
2182   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2183         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2184                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2185   "TARGET_ARM"
2186   "@
2187    orr%?\\t%0, %1, %2
2188    #"
2189   "TARGET_ARM
2190    && GET_CODE (operands[2]) == CONST_INT
2191    && !const_ok_for_arm (INTVAL (operands[2]))"
2192   [(clobber (const_int 0))]
2193   "
2194   arm_split_constant (IOR, SImode, curr_insn, 
2195                       INTVAL (operands[2]), operands[0], operands[1], 0);
2196   DONE;
2197   "
2198   [(set_attr "length" "4,16")
2199    (set_attr "predicable" "yes")]
2200 )
2201
2202 (define_insn "*thumb_iorsi3"
2203   [(set (match_operand:SI         0 "register_operand" "=l")
2204         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2205                 (match_operand:SI 2 "register_operand" "l")))]
2206   "TARGET_THUMB"
2207   "orr\\t%0, %0, %2"
2208   [(set_attr "length" "2")]
2209 )
2210
2211 (define_peephole2
2212   [(match_scratch:SI 3 "r")
2213    (set (match_operand:SI 0 "arm_general_register_operand" "")
2214         (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2215                 (match_operand:SI 2 "const_int_operand" "")))]
2216   "TARGET_ARM
2217    && !const_ok_for_arm (INTVAL (operands[2]))
2218    && const_ok_for_arm (~INTVAL (operands[2]))"
2219   [(set (match_dup 3) (match_dup 2))
2220    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2221   ""
2222 )
2223
2224 (define_insn "*iorsi3_compare0"
2225   [(set (reg:CC_NOOV CC_REGNUM)
2226         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2227                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2228                          (const_int 0)))
2229    (set (match_operand:SI 0 "s_register_operand" "=r")
2230         (ior:SI (match_dup 1) (match_dup 2)))]
2231   "TARGET_ARM"
2232   "orr%?s\\t%0, %1, %2"
2233   [(set_attr "conds" "set")]
2234 )
2235
2236 (define_insn "*iorsi3_compare0_scratch"
2237   [(set (reg:CC_NOOV CC_REGNUM)
2238         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2239                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2240                          (const_int 0)))
2241    (clobber (match_scratch:SI 0 "=r"))]
2242   "TARGET_ARM"
2243   "orr%?s\\t%0, %1, %2"
2244   [(set_attr "conds" "set")]
2245 )
2246
2247 (define_insn "xordi3"
2248   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2249         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2250                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2251   "TARGET_ARM && !TARGET_IWMMXT"
2252   "#"
2253   [(set_attr "length" "8")
2254    (set_attr "predicable" "yes")]
2255 )
2256
2257 (define_insn "*xordi_zesidi_di"
2258   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2259         (xor:DI (zero_extend:DI
2260                  (match_operand:SI 2 "s_register_operand" "r,r"))
2261                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2262   "TARGET_ARM"
2263   "@
2264    eor%?\\t%Q0, %Q1, %2
2265    #"
2266   [(set_attr "length" "4,8")
2267    (set_attr "predicable" "yes")]
2268 )
2269
2270 (define_insn "*xordi_sesidi_di"
2271   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2272         (xor:DI (sign_extend:DI
2273                  (match_operand:SI 2 "s_register_operand" "r,r"))
2274                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2275   "TARGET_ARM"
2276   "#"
2277   [(set_attr "length" "8")
2278    (set_attr "predicable" "yes")]
2279 )
2280
2281 (define_expand "xorsi3"
2282   [(set (match_operand:SI         0 "s_register_operand" "")
2283         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2284                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2285   "TARGET_EITHER"
2286   "if (TARGET_THUMB)
2287      if (GET_CODE (operands[2]) == CONST_INT)
2288        operands[2] = force_reg (SImode, operands[2]);
2289   "
2290 )
2291
2292 (define_insn "*arm_xorsi3"
2293   [(set (match_operand:SI         0 "s_register_operand" "=r")
2294         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2295                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2296   "TARGET_ARM"
2297   "eor%?\\t%0, %1, %2"
2298   [(set_attr "predicable" "yes")]
2299 )
2300
2301 (define_insn "*thumb_xorsi3"
2302   [(set (match_operand:SI         0 "register_operand" "=l")
2303         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2304                 (match_operand:SI 2 "register_operand" "l")))]
2305   "TARGET_THUMB"
2306   "eor\\t%0, %0, %2"
2307   [(set_attr "length" "2")]
2308 )
2309
2310 (define_insn "*xorsi3_compare0"
2311   [(set (reg:CC_NOOV CC_REGNUM)
2312         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2313                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2314                          (const_int 0)))
2315    (set (match_operand:SI 0 "s_register_operand" "=r")
2316         (xor:SI (match_dup 1) (match_dup 2)))]
2317   "TARGET_ARM"
2318   "eor%?s\\t%0, %1, %2"
2319   [(set_attr "conds" "set")]
2320 )
2321
2322 (define_insn "*xorsi3_compare0_scratch"
2323   [(set (reg:CC_NOOV CC_REGNUM)
2324         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2325                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2326                          (const_int 0)))]
2327   "TARGET_ARM"
2328   "teq%?\\t%0, %1"
2329   [(set_attr "conds" "set")]
2330 )
2331
2332 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2333 ; (NOT D) we can sometimes merge the final NOT into one of the following
2334 ; insns.
2335
2336 (define_split
2337   [(set (match_operand:SI 0 "s_register_operand" "")
2338         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2339                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2340                 (match_operand:SI 3 "arm_rhs_operand" "")))
2341    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2342   "TARGET_ARM"
2343   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2344                               (not:SI (match_dup 3))))
2345    (set (match_dup 0) (not:SI (match_dup 4)))]
2346   ""
2347 )
2348
2349 (define_insn "*andsi_iorsi3_notsi"
2350   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2351         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2352                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2353                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2354   "TARGET_ARM"
2355   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2356   [(set_attr "length" "8")
2357    (set_attr "predicable" "yes")]
2358 )
2359
2360 (define_split
2361   [(set (match_operand:SI 0 "s_register_operand" "")
2362         (match_operator:SI 1 "logical_binary_operator"
2363          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2364                            (match_operand:SI 3 "const_int_operand" "")
2365                            (match_operand:SI 4 "const_int_operand" ""))
2366           (match_operator:SI 9 "logical_binary_operator"
2367            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2368                          (match_operand:SI 6 "const_int_operand" ""))
2369             (match_operand:SI 7 "s_register_operand" "")])]))
2370    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2371   "TARGET_ARM
2372    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2373    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2374   [(set (match_dup 8)
2375         (match_op_dup 1
2376          [(ashift:SI (match_dup 2) (match_dup 4))
2377           (match_dup 5)]))
2378    (set (match_dup 0)
2379         (match_op_dup 1
2380          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2381           (match_dup 7)]))]
2382   "
2383   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2384 ")
2385
2386 (define_split
2387   [(set (match_operand:SI 0 "s_register_operand" "")
2388         (match_operator:SI 1 "logical_binary_operator"
2389          [(match_operator:SI 9 "logical_binary_operator"
2390            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2391                          (match_operand:SI 6 "const_int_operand" ""))
2392             (match_operand:SI 7 "s_register_operand" "")])
2393           (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2394                            (match_operand:SI 3 "const_int_operand" "")
2395                            (match_operand:SI 4 "const_int_operand" ""))]))
2396    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2397   "TARGET_ARM
2398    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2399    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2400   [(set (match_dup 8)
2401         (match_op_dup 1
2402          [(ashift:SI (match_dup 2) (match_dup 4))
2403           (match_dup 5)]))
2404    (set (match_dup 0)
2405         (match_op_dup 1
2406          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2407           (match_dup 7)]))]
2408   "
2409   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2410 ")
2411
2412 (define_split
2413   [(set (match_operand:SI 0 "s_register_operand" "")
2414         (match_operator:SI 1 "logical_binary_operator"
2415          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2416                            (match_operand:SI 3 "const_int_operand" "")
2417                            (match_operand:SI 4 "const_int_operand" ""))
2418           (match_operator:SI 9 "logical_binary_operator"
2419            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2420                          (match_operand:SI 6 "const_int_operand" ""))
2421             (match_operand:SI 7 "s_register_operand" "")])]))
2422    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2423   "TARGET_ARM
2424    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2425    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2426   [(set (match_dup 8)
2427         (match_op_dup 1
2428          [(ashift:SI (match_dup 2) (match_dup 4))
2429           (match_dup 5)]))
2430    (set (match_dup 0)
2431         (match_op_dup 1
2432          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2433           (match_dup 7)]))]
2434   "
2435   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2436 ")
2437
2438 (define_split
2439   [(set (match_operand:SI 0 "s_register_operand" "")
2440         (match_operator:SI 1 "logical_binary_operator"
2441          [(match_operator:SI 9 "logical_binary_operator"
2442            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2443                          (match_operand:SI 6 "const_int_operand" ""))
2444             (match_operand:SI 7 "s_register_operand" "")])
2445           (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2446                            (match_operand:SI 3 "const_int_operand" "")
2447                            (match_operand:SI 4 "const_int_operand" ""))]))
2448    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2449   "TARGET_ARM
2450    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2451    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2452   [(set (match_dup 8)
2453         (match_op_dup 1
2454          [(ashift:SI (match_dup 2) (match_dup 4))
2455           (match_dup 5)]))
2456    (set (match_dup 0)
2457         (match_op_dup 1
2458          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2459           (match_dup 7)]))]
2460   "
2461   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2462 ")
2463 \f
2464
2465 ;; Minimum and maximum insns
2466
2467 (define_insn "smaxsi3"
2468   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2469         (smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2470                  (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2471    (clobber (reg:CC CC_REGNUM))]
2472   "TARGET_ARM"
2473   "@
2474    cmp\\t%1, %2\;movlt\\t%0, %2
2475    cmp\\t%1, %2\;movge\\t%0, %1
2476    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2477   [(set_attr "conds" "clob")
2478    (set_attr "length" "8,8,12")]
2479 )
2480
2481 (define_insn "sminsi3"
2482   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2483         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2484                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2485    (clobber (reg:CC CC_REGNUM))]
2486   "TARGET_ARM"
2487   "@
2488    cmp\\t%1, %2\;movge\\t%0, %2
2489    cmp\\t%1, %2\;movlt\\t%0, %1
2490    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2491   [(set_attr "conds" "clob")
2492    (set_attr "length" "8,8,12")]
2493 )
2494
2495 (define_insn "umaxsi3"
2496   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2497         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2498                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2499    (clobber (reg:CC CC_REGNUM))]
2500   "TARGET_ARM"
2501   "@
2502    cmp\\t%1, %2\;movcc\\t%0, %2
2503    cmp\\t%1, %2\;movcs\\t%0, %1
2504    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2505   [(set_attr "conds" "clob")
2506    (set_attr "length" "8,8,12")]
2507 )
2508
2509 (define_insn "uminsi3"
2510   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2511         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2512                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2513    (clobber (reg:CC CC_REGNUM))]
2514   "TARGET_ARM"
2515   "@
2516    cmp\\t%1, %2\;movcs\\t%0, %2
2517    cmp\\t%1, %2\;movcc\\t%0, %1
2518    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2519   [(set_attr "conds" "clob")
2520    (set_attr "length" "8,8,12")]
2521 )
2522
2523 (define_insn "*store_minmaxsi"
2524   [(set (match_operand:SI 0 "memory_operand" "=m")
2525         (match_operator:SI 3 "minmax_operator"
2526          [(match_operand:SI 1 "s_register_operand" "r")
2527           (match_operand:SI 2 "s_register_operand" "r")]))
2528    (clobber (reg:CC CC_REGNUM))]
2529   "TARGET_ARM"
2530   "*
2531   operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2532                                 operands[1], operands[2]);
2533   output_asm_insn (\"cmp\\t%1, %2\", operands);
2534   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2535   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2536   return \"\";
2537   "
2538   [(set_attr "conds" "clob")
2539    (set_attr "length" "12")
2540    (set_attr "type" "store1")]
2541 )
2542
2543 ; Reject the frame pointer in operand[1], since reloading this after
2544 ; it has been eliminated can cause carnage.
2545 (define_insn "*minmax_arithsi"
2546   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2547         (match_operator:SI 4 "shiftable_operator"
2548          [(match_operator:SI 5 "minmax_operator"
2549            [(match_operand:SI 2 "s_register_operand" "r,r")
2550             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2551           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2552    (clobber (reg:CC CC_REGNUM))]
2553   "TARGET_ARM
2554    && (GET_CODE (operands[1]) != REG
2555        || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2556            && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2557   "*
2558   {
2559     enum rtx_code code = GET_CODE (operands[4]);
2560
2561     operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2562                                   operands[2], operands[3]);
2563     output_asm_insn (\"cmp\\t%2, %3\", operands);
2564     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2565     if (which_alternative != 0 || operands[3] != const0_rtx
2566         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2567       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2568     return \"\";
2569   }"
2570   [(set_attr "conds" "clob")
2571    (set_attr "length" "12")]
2572 )
2573
2574 \f
2575 ;; Shift and rotation insns
2576
2577 (define_expand "ashldi3"
2578   [(set (match_operand:DI            0 "s_register_operand" "")
2579         (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2580                    (match_operand:SI 2 "reg_or_int_operand" "")))]
2581   "TARGET_ARM"
2582   "
2583   if (GET_CODE (operands[2]) == CONST_INT)
2584     {
2585       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2586         {
2587           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2588           DONE;
2589         }
2590         /* Ideally we shouldn't fail here if we could know that operands[1] 
2591            ends up already living in an iwmmxt register. Otherwise it's
2592            cheaper to have the alternate code being generated than moving
2593            values to iwmmxt regs and back.  */
2594         FAIL;
2595     }
2596   else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2597     FAIL;
2598   "
2599 )
2600
2601 (define_insn "arm_ashldi3_1bit"
2602   [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
2603         (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2604                    (const_int 1)))
2605    (clobber (reg:CC CC_REGNUM))]
2606   "TARGET_ARM"
2607   "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2608   [(set_attr "conds" "clob")
2609    (set_attr "length" "8")]
2610 )
2611
2612 (define_expand "ashlsi3"
2613   [(set (match_operand:SI            0 "s_register_operand" "")
2614         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2615                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2616   "TARGET_EITHER"
2617   "
2618   if (GET_CODE (operands[2]) == CONST_INT
2619       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2620     {
2621       emit_insn (gen_movsi (operands[0], const0_rtx));
2622       DONE;
2623     }
2624   "
2625 )
2626
2627 (define_insn "*thumb_ashlsi3"
2628   [(set (match_operand:SI            0 "register_operand" "=l,l")
2629         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2630                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2631   "TARGET_THUMB"
2632   "lsl\\t%0, %1, %2"
2633   [(set_attr "length" "2")]
2634 )
2635
2636 (define_expand "ashrdi3"
2637   [(set (match_operand:DI              0 "s_register_operand" "")
2638         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2639                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2640   "TARGET_ARM"
2641   "
2642   if (GET_CODE (operands[2]) == CONST_INT)
2643     {
2644       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2645         {
2646           emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2647           DONE;
2648         }
2649         /* Ideally we shouldn't fail here if we could know that operands[1] 
2650            ends up already living in an iwmmxt register. Otherwise it's
2651            cheaper to have the alternate code being generated than moving
2652            values to iwmmxt regs and back.  */
2653         FAIL;
2654     }
2655   else if (!TARGET_REALLY_IWMMXT)
2656     FAIL;
2657   "
2658 )
2659
2660 (define_insn "arm_ashrdi3_1bit"
2661   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2662         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2663                      (const_int 1)))
2664    (clobber (reg:CC CC_REGNUM))]
2665   "TARGET_ARM"
2666   "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2667   [(set_attr "conds" "clob")
2668    (set_attr "length" "8")]
2669 )
2670
2671 (define_expand "ashrsi3"
2672   [(set (match_operand:SI              0 "s_register_operand" "")
2673         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2674                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2675   "TARGET_EITHER"
2676   "
2677   if (GET_CODE (operands[2]) == CONST_INT
2678       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2679     operands[2] = GEN_INT (31);
2680   "
2681 )
2682
2683 (define_insn "*thumb_ashrsi3"
2684   [(set (match_operand:SI              0 "register_operand" "=l,l")
2685         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2686                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2687   "TARGET_THUMB"
2688   "asr\\t%0, %1, %2"
2689   [(set_attr "length" "2")]
2690 )
2691
2692 (define_expand "lshrdi3"
2693   [(set (match_operand:DI              0 "s_register_operand" "")
2694         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2695                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2696   "TARGET_ARM"
2697   "
2698   if (GET_CODE (operands[2]) == CONST_INT)
2699     {
2700       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2701         {
2702           emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2703           DONE;
2704         }
2705         /* Ideally we shouldn't fail here if we could know that operands[1] 
2706            ends up already living in an iwmmxt register. Otherwise it's
2707            cheaper to have the alternate code being generated than moving
2708            values to iwmmxt regs and back.  */
2709         FAIL;
2710     }
2711   else if (!TARGET_REALLY_IWMMXT)
2712     FAIL;
2713   "
2714 )
2715
2716 (define_insn "arm_lshrdi3_1bit"
2717   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2718         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2719                      (const_int 1)))
2720    (clobber (reg:CC CC_REGNUM))]
2721   "TARGET_ARM"
2722   "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2723   [(set_attr "conds" "clob")
2724    (set_attr "length" "8")]
2725 )
2726
2727 (define_expand "lshrsi3"
2728   [(set (match_operand:SI              0 "s_register_operand" "")
2729         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2730                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2731   "TARGET_EITHER"
2732   "
2733   if (GET_CODE (operands[2]) == CONST_INT
2734       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2735     {
2736       emit_insn (gen_movsi (operands[0], const0_rtx));
2737       DONE;
2738     }
2739   "
2740 )
2741
2742 (define_insn "*thumb_lshrsi3"
2743   [(set (match_operand:SI              0 "register_operand" "=l,l")
2744         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2745                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2746   "TARGET_THUMB"
2747   "lsr\\t%0, %1, %2"
2748   [(set_attr "length" "2")]
2749 )
2750
2751 (define_expand "rotlsi3"
2752   [(set (match_operand:SI              0 "s_register_operand" "")
2753         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2754                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2755   "TARGET_ARM"
2756   "
2757   if (GET_CODE (operands[2]) == CONST_INT)
2758     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2759   else
2760     {
2761       rtx reg = gen_reg_rtx (SImode);
2762       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2763       operands[2] = reg;
2764     }
2765   "
2766 )
2767
2768 (define_expand "rotrsi3"
2769   [(set (match_operand:SI              0 "s_register_operand" "")
2770         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2771                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2772   "TARGET_EITHER"
2773   "
2774   if (TARGET_ARM)
2775     {
2776       if (GET_CODE (operands[2]) == CONST_INT
2777           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2778         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2779     }
2780   else /* TARGET_THUMB */
2781     {
2782       if (GET_CODE (operands [2]) == CONST_INT)
2783         operands [2] = force_reg (SImode, operands[2]);
2784     }
2785   "
2786 )
2787
2788 (define_insn "*thumb_rotrsi3"
2789   [(set (match_operand:SI              0 "register_operand" "=l")
2790         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2791                      (match_operand:SI 2 "register_operand" "l")))]
2792   "TARGET_THUMB"
2793   "ror\\t%0, %0, %2"
2794   [(set_attr "length" "2")]
2795 )
2796
2797 (define_insn "*arm_shiftsi3"
2798   [(set (match_operand:SI   0 "s_register_operand" "=r")
2799         (match_operator:SI  3 "shift_operator"
2800          [(match_operand:SI 1 "s_register_operand"  "r")
2801           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2802   "TARGET_ARM"
2803   "mov%?\\t%0, %1%S3"
2804   [(set_attr "predicable" "yes")
2805    (set_attr "shift" "1")
2806    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2807                       (const_string "alu_shift")
2808                       (const_string "alu_shift_reg")))]
2809 )
2810
2811 (define_insn "*shiftsi3_compare0"
2812   [(set (reg:CC_NOOV CC_REGNUM)
2813         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2814                           [(match_operand:SI 1 "s_register_operand" "r")
2815                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2816                          (const_int 0)))
2817    (set (match_operand:SI 0 "s_register_operand" "=r")
2818         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2819   "TARGET_ARM"
2820   "mov%?s\\t%0, %1%S3"
2821   [(set_attr "conds" "set")
2822    (set_attr "shift" "1")
2823    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2824                       (const_string "alu_shift")
2825                       (const_string "alu_shift_reg")))]
2826 )
2827
2828 (define_insn "*shiftsi3_compare0_scratch"
2829   [(set (reg:CC_NOOV CC_REGNUM)
2830         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2831                           [(match_operand:SI 1 "s_register_operand" "r")
2832                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2833                          (const_int 0)))
2834    (clobber (match_scratch:SI 0 "=r"))]
2835   "TARGET_ARM"
2836   "mov%?s\\t%0, %1%S3"
2837   [(set_attr "conds" "set")
2838    (set_attr "shift" "1")]
2839 )
2840
2841 (define_insn "*notsi_shiftsi"
2842   [(set (match_operand:SI 0 "s_register_operand" "=r")
2843         (not:SI (match_operator:SI 3 "shift_operator"
2844                  [(match_operand:SI 1 "s_register_operand" "r")
2845                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2846   "TARGET_ARM"
2847   "mvn%?\\t%0, %1%S3"
2848   [(set_attr "predicable" "yes")
2849    (set_attr "shift" "1")
2850    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2851                       (const_string "alu_shift")
2852                       (const_string "alu_shift_reg")))]
2853 )
2854
2855 (define_insn "*notsi_shiftsi_compare0"
2856   [(set (reg:CC_NOOV CC_REGNUM)
2857         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2858                           [(match_operand:SI 1 "s_register_operand" "r")
2859                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2860                          (const_int 0)))
2861    (set (match_operand:SI 0 "s_register_operand" "=r")
2862         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2863   "TARGET_ARM"
2864   "mvn%?s\\t%0, %1%S3"
2865   [(set_attr "conds" "set")
2866    (set_attr "shift" "1")
2867    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2868                       (const_string "alu_shift")
2869                       (const_string "alu_shift_reg")))]
2870 )
2871
2872 (define_insn "*not_shiftsi_compare0_scratch"
2873   [(set (reg:CC_NOOV CC_REGNUM)
2874         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2875                           [(match_operand:SI 1 "s_register_operand" "r")
2876                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2877                          (const_int 0)))
2878    (clobber (match_scratch:SI 0 "=r"))]
2879   "TARGET_ARM"
2880   "mvn%?s\\t%0, %1%S3"
2881   [(set_attr "conds" "set")
2882    (set_attr "shift" "1")
2883    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2884                       (const_string "alu_shift")
2885                       (const_string "alu_shift_reg")))]
2886 )
2887
2888 ;; We don't really have extzv, but defining this using shifts helps
2889 ;; to reduce register pressure later on.
2890
2891 (define_expand "extzv"
2892   [(set (match_dup 4)
2893         (ashift:SI (match_operand:SI   1 "register_operand" "")
2894                    (match_operand:SI   2 "const_int_operand" "")))
2895    (set (match_operand:SI              0 "register_operand" "")
2896         (lshiftrt:SI (match_dup 4)
2897                      (match_operand:SI 3 "const_int_operand" "")))]
2898   "TARGET_THUMB"
2899   "
2900   {
2901     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2902     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2903     
2904     operands[3] = GEN_INT (rshift);
2905     
2906     if (lshift == 0)
2907       {
2908         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2909         DONE;
2910       }
2911       
2912     operands[2] = GEN_INT (lshift);
2913     operands[4] = gen_reg_rtx (SImode);
2914   }"
2915 )
2916
2917 \f
2918 ;; Unary arithmetic insns
2919
2920 (define_expand "negdi2"
2921  [(parallel
2922    [(set (match_operand:DI          0 "s_register_operand" "")
2923           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2924     (clobber (reg:CC CC_REGNUM))])]
2925   "TARGET_EITHER"
2926   "
2927   if (TARGET_THUMB)
2928     {
2929       if (GET_CODE (operands[1]) != REG)
2930         operands[1] = force_reg (SImode, operands[1]);
2931      }
2932   "
2933 )
2934
2935 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2936 ;; The second alternative is to allow the common case of a *full* overlap.
2937 (define_insn "*arm_negdi2"
2938   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2939         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2940    (clobber (reg:CC CC_REGNUM))]
2941   "TARGET_ARM"
2942   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2943   [(set_attr "conds" "clob")
2944    (set_attr "length" "8")]
2945 )
2946
2947 (define_insn "*thumb_negdi2"
2948   [(set (match_operand:DI         0 "register_operand" "=&l")
2949         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
2950    (clobber (reg:CC CC_REGNUM))]
2951   "TARGET_THUMB"
2952   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2953   [(set_attr "length" "6")]
2954 )
2955
2956 (define_expand "negsi2"
2957   [(set (match_operand:SI         0 "s_register_operand" "")
2958         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2959   "TARGET_EITHER"
2960   ""
2961 )
2962
2963 (define_insn "*arm_negsi2"
2964   [(set (match_operand:SI         0 "s_register_operand" "=r")
2965         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2966   "TARGET_ARM"
2967   "rsb%?\\t%0, %1, #0"
2968   [(set_attr "predicable" "yes")]
2969 )
2970
2971 (define_insn "*thumb_negsi2"
2972   [(set (match_operand:SI         0 "register_operand" "=l")
2973         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2974   "TARGET_THUMB"
2975   "neg\\t%0, %1"
2976   [(set_attr "length" "2")]
2977 )
2978
2979 (define_expand "negsf2"
2980   [(set (match_operand:SF         0 "s_register_operand" "")
2981         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2982   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2983   ""
2984 )
2985
2986 (define_expand "negdf2"
2987   [(set (match_operand:DF         0 "s_register_operand" "")
2988         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2989   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2990   "")
2991
2992 ;; abssi2 doesn't really clobber the condition codes if a different register
2993 ;; is being set.  To keep things simple, assume during rtl manipulations that
2994 ;; it does, but tell the final scan operator the truth.  Similarly for
2995 ;; (neg (abs...))
2996
2997 (define_expand "abssi2"
2998   [(parallel
2999     [(set (match_operand:SI         0 "s_register_operand" "")
3000           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3001      (clobber (reg:CC CC_REGNUM))])]
3002   "TARGET_ARM"
3003   "")
3004
3005 (define_insn "*arm_abssi2"
3006   [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
3007         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3008    (clobber (reg:CC CC_REGNUM))]
3009   "TARGET_ARM"
3010   "@
3011    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3012    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3013   [(set_attr "conds" "clob,*")
3014    (set_attr "shift" "1")
3015    ;; predicable can't be set based on the variant, so left as no
3016    (set_attr "length" "8")]
3017 )
3018
3019 (define_insn "*neg_abssi2"
3020   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3021         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3022    (clobber (reg:CC CC_REGNUM))]
3023   "TARGET_ARM"
3024   "@
3025    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3026    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3027   [(set_attr "conds" "clob,*")
3028    (set_attr "shift" "1")
3029    ;; predicable can't be set based on the variant, so left as no
3030    (set_attr "length" "8")]
3031 )
3032
3033 (define_expand "abssf2"
3034   [(set (match_operand:SF         0 "s_register_operand" "")
3035         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3036   "TARGET_ARM && TARGET_HARD_FLOAT"
3037   "")
3038
3039 (define_expand "absdf2"
3040   [(set (match_operand:DF         0 "s_register_operand" "")
3041         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3042   "TARGET_ARM && TARGET_HARD_FLOAT"
3043   "")
3044
3045 (define_expand "sqrtsf2"
3046   [(set (match_operand:SF 0 "s_register_operand" "")
3047         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3048   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3049   "")
3050
3051 (define_expand "sqrtdf2"
3052   [(set (match_operand:DF 0 "s_register_operand" "")
3053         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3054   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3055   "")
3056
3057 (define_insn_and_split "one_cmpldi2"
3058   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3059         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3060   "TARGET_ARM"
3061   "#"
3062   "TARGET_ARM && reload_completed"
3063   [(set (match_dup 0) (not:SI (match_dup 1)))
3064    (set (match_dup 2) (not:SI (match_dup 3)))]
3065   "
3066   {
3067     operands[2] = gen_highpart (SImode, operands[0]);
3068     operands[0] = gen_lowpart (SImode, operands[0]);
3069     operands[3] = gen_highpart (SImode, operands[1]);
3070     operands[1] = gen_lowpart (SImode, operands[1]);
3071   }"
3072   [(set_attr "length" "8")
3073    (set_attr "predicable" "yes")]
3074 )
3075
3076 (define_expand "one_cmplsi2"
3077   [(set (match_operand:SI         0 "s_register_operand" "")
3078         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3079   "TARGET_EITHER"
3080   ""
3081 )
3082
3083 (define_insn "*arm_one_cmplsi2"
3084   [(set (match_operand:SI         0 "s_register_operand" "=r")
3085         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3086   "TARGET_ARM"
3087   "mvn%?\\t%0, %1"
3088   [(set_attr "predicable" "yes")]
3089 )
3090
3091 (define_insn "*thumb_one_cmplsi2"
3092   [(set (match_operand:SI         0 "register_operand" "=l")
3093         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3094   "TARGET_THUMB"
3095   "mvn\\t%0, %1"
3096   [(set_attr "length" "2")]
3097 )
3098
3099 (define_insn "*notsi_compare0"
3100   [(set (reg:CC_NOOV CC_REGNUM)
3101         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3102                          (const_int 0)))
3103    (set (match_operand:SI 0 "s_register_operand" "=r")
3104         (not:SI (match_dup 1)))]
3105   "TARGET_ARM"
3106   "mvn%?s\\t%0, %1"
3107   [(set_attr "conds" "set")]
3108 )
3109
3110 (define_insn "*notsi_compare0_scratch"
3111   [(set (reg:CC_NOOV CC_REGNUM)
3112         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3113                          (const_int 0)))
3114    (clobber (match_scratch:SI 0 "=r"))]
3115   "TARGET_ARM"
3116   "mvn%?s\\t%0, %1"
3117   [(set_attr "conds" "set")]
3118 )
3119 \f
3120 ;; Fixed <--> Floating conversion insns
3121
3122 (define_expand "floatsisf2"
3123   [(set (match_operand:SF           0 "s_register_operand" "")
3124         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3125   "TARGET_ARM && TARGET_HARD_FLOAT"
3126   "
3127   if (TARGET_MAVERICK)
3128     {
3129       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3130       DONE;
3131     }
3132 ")
3133
3134 (define_expand "floatsidf2"
3135   [(set (match_operand:DF           0 "s_register_operand" "")
3136         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3137   "TARGET_ARM && TARGET_HARD_FLOAT"
3138   "
3139   if (TARGET_MAVERICK)
3140     {
3141       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3142       DONE;
3143     }
3144 ")
3145
3146 (define_expand "fix_truncsfsi2"
3147   [(set (match_operand:SI         0 "s_register_operand" "")
3148         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3149   "TARGET_ARM && TARGET_HARD_FLOAT"
3150   "
3151   if (TARGET_MAVERICK)
3152     {
3153       if (!cirrus_fp_register (operands[0], SImode))
3154         operands[0] = force_reg (SImode, operands[0]);
3155       if (!cirrus_fp_register (operands[1], SFmode))
3156         operands[1] = force_reg (SFmode, operands[0]);
3157       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3158       DONE;
3159     }
3160 ")
3161
3162 (define_expand "fix_truncdfsi2"
3163   [(set (match_operand:SI         0 "s_register_operand" "")
3164         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3165   "TARGET_ARM && TARGET_HARD_FLOAT"
3166   "
3167   if (TARGET_MAVERICK)
3168     {
3169       if (!cirrus_fp_register (operands[1], DFmode))
3170         operands[1] = force_reg (DFmode, operands[0]);
3171       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3172       DONE;
3173     }
3174 ")
3175
3176 ;; Truncation insns
3177
3178 (define_expand "truncdfsf2"
3179   [(set (match_operand:SF  0 "s_register_operand" "")
3180         (float_truncate:SF
3181          (match_operand:DF 1 "s_register_operand" "")))]
3182   "TARGET_ARM && TARGET_HARD_FLOAT"
3183   ""
3184 )
3185 \f
3186 ;; Zero and sign extension instructions.
3187
3188 (define_insn "zero_extendsidi2"
3189   [(set (match_operand:DI 0 "s_register_operand" "=r")
3190         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3191   "TARGET_ARM"
3192   "*
3193     if (REGNO (operands[1])
3194         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3195       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3196     return \"mov%?\\t%R0, #0\";
3197   "
3198   [(set_attr "length" "8")
3199    (set_attr "predicable" "yes")]
3200 )
3201
3202 (define_insn "zero_extendqidi2"
3203   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3204         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3205   "TARGET_ARM"
3206   "@
3207    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3208    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3209   [(set_attr "length" "8")
3210    (set_attr "predicable" "yes")
3211    (set_attr "type" "*,load_byte")
3212    (set_attr "pool_range" "*,4092")
3213    (set_attr "neg_pool_range" "*,4084")]
3214 )
3215
3216 (define_insn "extendsidi2"
3217   [(set (match_operand:DI 0 "s_register_operand" "=r")
3218         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3219   "TARGET_ARM"
3220   "*
3221     if (REGNO (operands[1])
3222         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3223       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3224     return \"mov%?\\t%R0, %Q0, asr #31\";
3225   "
3226   [(set_attr "length" "8")
3227    (set_attr "shift" "1")
3228    (set_attr "predicable" "yes")]
3229 )
3230
3231 (define_expand "zero_extendhisi2"
3232   [(set (match_dup 2)
3233         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3234                    (const_int 16)))
3235    (set (match_operand:SI 0 "s_register_operand" "")
3236         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3237   "TARGET_EITHER"
3238   "
3239   {
3240     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3241       {
3242         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3243                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3244         DONE;
3245       }
3246
3247     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3248       {
3249         emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3250         DONE;
3251       }
3252
3253     if (!s_register_operand (operands[1], HImode))
3254       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3255
3256     if (arm_arch6)
3257       {
3258         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3259                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3260         DONE;
3261       }
3262
3263     operands[1] = gen_lowpart (SImode, operands[1]);
3264     operands[2] = gen_reg_rtx (SImode);
3265   }"
3266 )
3267
3268 (define_insn "*thumb_zero_extendhisi2"
3269   [(set (match_operand:SI 0 "register_operand" "=l")
3270         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3271   "TARGET_THUMB && !arm_arch6"
3272   "*
3273   rtx mem = XEXP (operands[1], 0);
3274
3275   if (GET_CODE (mem) == CONST)
3276     mem = XEXP (mem, 0);
3277     
3278   if (GET_CODE (mem) == LABEL_REF)
3279     return \"ldr\\t%0, %1\";
3280     
3281   if (GET_CODE (mem) == PLUS)
3282     {
3283       rtx a = XEXP (mem, 0);
3284       rtx b = XEXP (mem, 1);
3285
3286       /* This can happen due to bugs in reload.  */
3287       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3288         {
3289           rtx ops[2];
3290           ops[0] = operands[0];
3291           ops[1] = a;
3292       
3293           output_asm_insn (\"mov        %0, %1\", ops);
3294
3295           XEXP (mem, 0) = operands[0];
3296        }
3297
3298       else if (   GET_CODE (a) == LABEL_REF
3299                && GET_CODE (b) == CONST_INT)
3300         return \"ldr\\t%0, %1\";
3301     }
3302     
3303   return \"ldrh\\t%0, %1\";
3304   "
3305   [(set_attr "length" "4")
3306    (set_attr "type" "load_byte")
3307    (set_attr "pool_range" "60")]
3308 )
3309
3310 (define_insn "*thumb_zero_extendhisi2_v6"
3311   [(set (match_operand:SI 0 "register_operand" "=l,l")
3312         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3313   "TARGET_THUMB && arm_arch6"
3314   "*
3315   rtx mem;
3316
3317   if (which_alternative == 0)
3318     return \"uxth\\t%0, %1\";
3319
3320   mem = XEXP (operands[1], 0);
3321
3322   if (GET_CODE (mem) == CONST)
3323     mem = XEXP (mem, 0);
3324     
3325   if (GET_CODE (mem) == LABEL_REF)
3326     return \"ldr\\t%0, %1\";
3327     
3328   if (GET_CODE (mem) == PLUS)
3329     {
3330       rtx a = XEXP (mem, 0);
3331       rtx b = XEXP (mem, 1);
3332
3333       /* This can happen due to bugs in reload.  */
3334       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3335         {
3336           rtx ops[2];
3337           ops[0] = operands[0];
3338           ops[1] = a;
3339       
3340           output_asm_insn (\"mov        %0, %1\", ops);
3341
3342           XEXP (mem, 0) = operands[0];
3343        }
3344
3345       else if (   GET_CODE (a) == LABEL_REF
3346                && GET_CODE (b) == CONST_INT)
3347         return \"ldr\\t%0, %1\";
3348     }
3349     
3350   return \"ldrh\\t%0, %1\";
3351   "
3352   [(set_attr "length" "2,4")
3353    (set_attr "type" "alu_shift,load_byte")
3354    (set_attr "pool_range" "*,60")]
3355 )
3356
3357 (define_insn "*arm_zero_extendhisi2"
3358   [(set (match_operand:SI 0 "s_register_operand" "=r")
3359         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3360   "TARGET_ARM && arm_arch4 && !arm_arch6"
3361   "ldr%?h\\t%0, %1"
3362   [(set_attr "type" "load_byte")
3363    (set_attr "predicable" "yes")
3364    (set_attr "pool_range" "256")
3365    (set_attr "neg_pool_range" "244")]
3366 )
3367
3368 (define_insn "*arm_zero_extendhisi2_v6"
3369   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3370         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3371   "TARGET_ARM && arm_arch6"
3372   "@
3373    uxth%?\\t%0, %1
3374    ldr%?h\\t%0, %1"
3375   [(set_attr "type" "alu_shift,load_byte")
3376    (set_attr "predicable" "yes")
3377    (set_attr "pool_range" "*,256")
3378    (set_attr "neg_pool_range" "*,244")]
3379 )
3380
3381 (define_insn "*arm_zero_extendhisi2addsi"
3382   [(set (match_operand:SI 0 "s_register_operand" "=r")
3383         (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3384                  (match_operand:SI 2 "s_register_operand" "r")))]
3385   "TARGET_ARM && arm_arch6"
3386   "uxtah%?\\t%0, %2, %1"
3387   [(set_attr "type" "alu_shift")
3388    (set_attr "predicable" "yes")]
3389 )
3390
3391 (define_split
3392   [(set (match_operand:SI 0 "s_register_operand" "")
3393         (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3394    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3395   "TARGET_ARM && (!arm_arch4)"
3396   [(set (match_dup 2) (match_dup 1))
3397    (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3398   "
3399   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3400     FAIL;
3401   "
3402 )
3403
3404 (define_split
3405   [(set (match_operand:SI 0 "s_register_operand" "")
3406         (match_operator:SI 3 "shiftable_operator"
3407          [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3408           (match_operand:SI 4 "s_register_operand" "")]))
3409    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3410   "TARGET_ARM && (!arm_arch4)"
3411   [(set (match_dup 2) (match_dup 1))
3412    (set (match_dup 0)
3413         (match_op_dup 3
3414          [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3415   "
3416   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3417     FAIL;
3418   "
3419 )
3420
3421 (define_expand "zero_extendqisi2"
3422   [(set (match_operand:SI 0 "s_register_operand" "")
3423         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3424   "TARGET_EITHER"
3425   "
3426   if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3427     {
3428       if (TARGET_ARM)
3429         {
3430           emit_insn (gen_andsi3 (operands[0],
3431                                  gen_lowpart (SImode, operands[1]),
3432                                  GEN_INT (255)));
3433         }
3434       else /* TARGET_THUMB */
3435         {
3436           rtx temp = gen_reg_rtx (SImode);
3437           rtx ops[3];
3438           
3439           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3440           operands[1] = gen_lowpart (SImode, operands[1]);
3441
3442           ops[0] = temp;
3443           ops[1] = operands[1];
3444           ops[2] = GEN_INT (24);
3445
3446           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3447                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3448           
3449           ops[0] = operands[0];
3450           ops[1] = temp;
3451           ops[2] = GEN_INT (24);
3452
3453           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3454                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3455         }
3456       DONE;
3457     }
3458   "
3459 )
3460
3461 (define_insn "*thumb_zero_extendqisi2"
3462   [(set (match_operand:SI 0 "register_operand" "=l")
3463         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3464   "TARGET_THUMB && !arm_arch6"
3465   "ldrb\\t%0, %1"
3466   [(set_attr "length" "2")
3467    (set_attr "type" "load_byte")
3468    (set_attr "pool_range" "32")]
3469 )
3470
3471 (define_insn "*thumb_zero_extendqisi2_v6"
3472   [(set (match_operand:SI 0 "register_operand" "=l,l")
3473         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3474   "TARGET_THUMB && arm_arch6"
3475   "@
3476    uxtb\\t%0, %1
3477    ldrb\\t%0, %1"
3478   [(set_attr "length" "2,2")
3479    (set_attr "type" "alu_shift,load_byte")
3480    (set_attr "pool_range" "*,32")]
3481 )
3482
3483 (define_insn "*arm_zero_extendqisi2"
3484   [(set (match_operand:SI 0 "s_register_operand" "=r")
3485         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3486   "TARGET_ARM && !arm_arch6"
3487   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3488   [(set_attr "type" "load_byte")
3489    (set_attr "predicable" "yes")
3490    (set_attr "pool_range" "4096")
3491    (set_attr "neg_pool_range" "4084")]
3492 )
3493
3494 (define_insn "*arm_zero_extendqisi2_v6"
3495   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3496         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3497   "TARGET_ARM && arm_arch6"
3498   "@
3499    uxtb%?\\t%0, %1
3500    ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3501   [(set_attr "type" "alu_shift,load_byte")
3502    (set_attr "predicable" "yes")
3503    (set_attr "pool_range" "*,4096")
3504    (set_attr "neg_pool_range" "*,4084")]
3505 )
3506
3507 (define_insn "*arm_zero_extendqisi2addsi"
3508   [(set (match_operand:SI 0 "s_register_operand" "=r")
3509         (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3510                  (match_operand:SI 2 "s_register_operand" "r")))]
3511   "TARGET_ARM && arm_arch6"
3512   "uxtab%?\\t%0, %2, %1"
3513   [(set_attr "predicable" "yes")
3514    (set_attr "type" "alu_shift")]
3515 )
3516
3517 (define_split
3518   [(set (match_operand:SI 0 "s_register_operand" "")
3519         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3520    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3521   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3522   [(set (match_dup 2) (match_dup 1))
3523    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3524   ""
3525 )
3526
3527 (define_insn "*compareqi_eq0"
3528   [(set (reg:CC_Z CC_REGNUM)
3529         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3530                          (const_int 0)))]
3531   "TARGET_ARM"
3532   "tst\\t%0, #255"
3533   [(set_attr "conds" "set")]
3534 )
3535
3536 (define_expand "extendhisi2"
3537   [(set (match_dup 2)
3538         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3539                    (const_int 16)))
3540    (set (match_operand:SI 0 "s_register_operand" "")
3541         (ashiftrt:SI (match_dup 2)
3542                      (const_int 16)))]
3543   "TARGET_EITHER"
3544   "
3545   {
3546     if (GET_CODE (operands[1]) == MEM)
3547       {
3548         if (TARGET_THUMB)
3549           {
3550             emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3551             DONE;
3552           }
3553         else if (arm_arch4)
3554           {
3555             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3556                        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3557             DONE;
3558           }
3559       }
3560
3561     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3562       {
3563         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3564         DONE;
3565       }
3566
3567     if (!s_register_operand (operands[1], HImode))
3568       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3569
3570     if (arm_arch6)
3571       {
3572         if (TARGET_THUMB)
3573           emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3574         else
3575           emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3576                      gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3577
3578         DONE;
3579       }
3580
3581     operands[1] = gen_lowpart (SImode, operands[1]);
3582     operands[2] = gen_reg_rtx (SImode);
3583   }"
3584 )
3585
3586 (define_insn "thumb_extendhisi2"
3587   [(set (match_operand:SI 0 "register_operand" "=l")
3588         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3589    (clobber (match_scratch:SI 2 "=&l"))]
3590   "TARGET_THUMB && !arm_arch6"
3591   "*
3592   {
3593     rtx ops[4];
3594     rtx mem = XEXP (operands[1], 0);
3595
3596     /* This code used to try to use 'V', and fix the address only if it was
3597        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3598        range of QImode offsets, and offsettable_address_p does a QImode
3599        address check.  */
3600        
3601     if (GET_CODE (mem) == CONST)
3602       mem = XEXP (mem, 0);
3603     
3604     if (GET_CODE (mem) == LABEL_REF)
3605       return \"ldr\\t%0, %1\";
3606     
3607     if (GET_CODE (mem) == PLUS)
3608       {
3609         rtx a = XEXP (mem, 0);
3610         rtx b = XEXP (mem, 1);
3611
3612         if (GET_CODE (a) == LABEL_REF
3613             && GET_CODE (b) == CONST_INT)
3614           return \"ldr\\t%0, %1\";
3615
3616         if (GET_CODE (b) == REG)
3617           return \"ldrsh\\t%0, %1\";
3618           
3619         ops[1] = a;
3620         ops[2] = b;
3621       }
3622     else
3623       {
3624         ops[1] = mem;
3625         ops[2] = const0_rtx;
3626       }
3627       
3628     if (GET_CODE (ops[1]) != REG)
3629       {
3630         debug_rtx (ops[1]);
3631         abort ();
3632       }
3633
3634     ops[0] = operands[0];
3635     ops[3] = operands[2];
3636     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3637     return \"\";
3638   }"
3639   [(set_attr "length" "4")
3640    (set_attr "type" "load_byte")
3641    (set_attr "pool_range" "1020")]
3642 )
3643
3644 ;; We used to have an early-clobber on the scratch register here.
3645 ;; However, there's a bug somewhere in reload which means that this
3646 ;; can be partially ignored during spill allocation if the memory
3647 ;; address also needs reloading; this causes an abort later on when
3648 ;; we try to verify the operands.  Fortunately, we don't really need
3649 ;; the early-clobber: we can always use operand 0 if operand 2
3650 ;; overlaps the address.
3651 (define_insn "*thumb_extendhisi2_insn_v6"
3652   [(set (match_operand:SI 0 "register_operand" "=l,l")
3653         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3654    (clobber (match_scratch:SI 2 "=X,l"))]
3655   "TARGET_THUMB && arm_arch6"
3656   "*
3657   {
3658     rtx ops[4];
3659     rtx mem;
3660
3661     if (which_alternative == 0)
3662       return \"sxth\\t%0, %1\";
3663
3664     mem = XEXP (operands[1], 0);
3665
3666     /* This code used to try to use 'V', and fix the address only if it was
3667        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3668        range of QImode offsets, and offsettable_address_p does a QImode
3669        address check.  */
3670        
3671     if (GET_CODE (mem) == CONST)
3672       mem = XEXP (mem, 0);
3673     
3674     if (GET_CODE (mem) == LABEL_REF)
3675       return \"ldr\\t%0, %1\";
3676     
3677     if (GET_CODE (mem) == PLUS)
3678       {
3679         rtx a = XEXP (mem, 0);
3680         rtx b = XEXP (mem, 1);
3681
3682         if (GET_CODE (a) == LABEL_REF
3683             && GET_CODE (b) == CONST_INT)
3684           return \"ldr\\t%0, %1\";
3685
3686         if (GET_CODE (b) == REG)
3687           return \"ldrsh\\t%0, %1\";
3688           
3689         ops[1] = a;
3690         ops[2] = b;
3691       }
3692     else
3693       {
3694         ops[1] = mem;
3695         ops[2] = const0_rtx;
3696       }
3697       
3698     if (GET_CODE (ops[1]) != REG)
3699       {
3700         debug_rtx (ops[1]);
3701         abort ();
3702       }
3703
3704     ops[0] = operands[0];
3705     if (reg_mentioned_p (operands[2], ops[1]))
3706       ops[3] = ops[0];
3707     else
3708       ops[3] = operands[2];
3709     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3710     return \"\";
3711   }"
3712   [(set_attr "length" "2,4")
3713    (set_attr "type" "alu_shift,load_byte")
3714    (set_attr "pool_range" "*,1020")]
3715 )
3716
3717 (define_expand "extendhisi2_mem"
3718   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3719    (set (match_dup 3)
3720         (zero_extend:SI (match_dup 7)))
3721    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3722    (set (match_operand:SI 0 "" "")
3723         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3724   "TARGET_ARM"
3725   "
3726   {
3727     rtx mem1, mem2;
3728     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3729
3730     mem1 = gen_rtx_MEM (QImode, addr);
3731     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3732     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3733     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3734     operands[0] = gen_lowpart (SImode, operands[0]);
3735     operands[1] = mem1;
3736     operands[2] = gen_reg_rtx (SImode);
3737     operands[3] = gen_reg_rtx (SImode);
3738     operands[6] = gen_reg_rtx (SImode);
3739     operands[7] = mem2;
3740
3741     if (BYTES_BIG_ENDIAN)
3742       {
3743         operands[4] = operands[2];
3744         operands[5] = operands[3];
3745       }
3746     else
3747       {
3748         operands[4] = operands[3];
3749         operands[5] = operands[2];
3750       }
3751   }"
3752 )
3753
3754 (define_insn "*arm_extendhisi2"
3755   [(set (match_operand:SI 0 "s_register_operand" "=r")
3756         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3757   "TARGET_ARM && arm_arch4 && !arm_arch6"
3758   "ldr%?sh\\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_insn "*arm_extendhisi2_v6"
3766   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3767         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3768   "TARGET_ARM && arm_arch6"
3769   "@
3770    sxth%?\\t%0, %1
3771    ldr%?sh\\t%0, %1"
3772   [(set_attr "type" "alu_shift,load_byte")
3773    (set_attr "predicable" "yes")
3774    (set_attr "pool_range" "*,256")
3775    (set_attr "neg_pool_range" "*,244")]
3776 )
3777
3778 (define_insn "*arm_extendhisi2addsi"
3779   [(set (match_operand:SI 0 "s_register_operand" "=r")
3780         (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3781                  (match_operand:SI 2 "s_register_operand" "r")))]
3782   "TARGET_ARM && arm_arch6"
3783   "sxtah%?\\t%0, %2, %1"
3784 )
3785
3786 (define_split
3787   [(set (match_operand:SI                 0 "s_register_operand" "")
3788         (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3789    (clobber (match_operand:SI             2 "s_register_operand" ""))]
3790   "TARGET_ARM && (!arm_arch4)"
3791   [(set (match_dup 2) (match_dup 1))
3792    (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3793   "
3794   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3795     FAIL;
3796   "
3797 )
3798
3799 (define_split
3800   [(set (match_operand:SI                   0 "s_register_operand" "")
3801         (match_operator:SI                  3 "shiftable_operator"
3802          [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3803           (match_operand:SI                 4 "s_register_operand" "")]))
3804    (clobber (match_operand:SI               2 "s_register_operand" ""))]
3805   "TARGET_ARM && (!arm_arch4)"
3806   [(set (match_dup 2) (match_dup 1))
3807    (set (match_dup 0)
3808         (match_op_dup 3
3809          [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3810   "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3811      FAIL;
3812   "
3813 )
3814
3815 (define_expand "extendqihi2"
3816   [(set (match_dup 2)
3817         (ashift:SI (match_operand:QI 1 "general_operand" "")
3818                    (const_int 24)))
3819    (set (match_operand:HI 0 "s_register_operand" "")
3820         (ashiftrt:SI (match_dup 2)
3821                      (const_int 24)))]
3822   "TARGET_ARM"
3823   "
3824   {
3825     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3826       {
3827         emit_insn (gen_rtx_SET (VOIDmode,
3828                                 operands[0],
3829                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3830         DONE;
3831       }
3832     if (!s_register_operand (operands[1], QImode))
3833       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3834     operands[0] = gen_lowpart (SImode, operands[0]);
3835     operands[1] = gen_lowpart (SImode, operands[1]);
3836     operands[2] = gen_reg_rtx (SImode);
3837   }"
3838 )
3839
3840 (define_insn "*extendqihi_insn"
3841   [(set (match_operand:HI 0 "s_register_operand" "=r")
3842         (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3843   "TARGET_ARM && arm_arch4"
3844   "ldr%?sb\\t%0, %1"
3845   [(set_attr "type" "load_byte")
3846    (set_attr "predicable" "yes")
3847    (set_attr "pool_range" "256")
3848    (set_attr "neg_pool_range" "244")]
3849 )
3850
3851 (define_expand "extendqisi2"
3852   [(set (match_dup 2)
3853         (ashift:SI (match_operand:QI 1 "general_operand" "")
3854                    (const_int 24)))
3855    (set (match_operand:SI 0 "s_register_operand" "")
3856         (ashiftrt:SI (match_dup 2)
3857                      (const_int 24)))]
3858   "TARGET_EITHER"
3859   "
3860   {
3861     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3862       {
3863         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3864                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3865         DONE;
3866       }
3867
3868     if (!s_register_operand (operands[1], QImode))
3869       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3870
3871     if (arm_arch6)
3872       {
3873         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3874                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3875         DONE;
3876       }
3877
3878     operands[1] = gen_lowpart (SImode, operands[1]);
3879     operands[2] = gen_reg_rtx (SImode);
3880   }"
3881 )
3882
3883 (define_insn "*arm_extendqisi"
3884   [(set (match_operand:SI 0 "s_register_operand" "=r")
3885         (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3886   "TARGET_ARM && arm_arch4 && !arm_arch6"
3887   "ldr%?sb\\t%0, %1"
3888   [(set_attr "type" "load_byte")
3889    (set_attr "predicable" "yes")
3890    (set_attr "pool_range" "256")
3891    (set_attr "neg_pool_range" "244")]
3892 )
3893
3894 (define_insn "*arm_extendqisi_v6"
3895   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3896         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3897   "TARGET_ARM && arm_arch6"
3898   "@
3899    sxtb%?\\t%0, %1
3900    ldr%?sb\\t%0, %1"
3901   [(set_attr "type" "alu_shift,load_byte")
3902    (set_attr "predicable" "yes")
3903    (set_attr "pool_range" "*,256")
3904    (set_attr "neg_pool_range" "*,244")]
3905 )
3906
3907 (define_insn "*arm_extendqisi2addsi"
3908   [(set (match_operand:SI 0 "s_register_operand" "=r")
3909         (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3910                  (match_operand:SI 2 "s_register_operand" "r")))]
3911   "TARGET_ARM && arm_arch6"
3912   "sxtab%?\\t%0, %2, %1"
3913   [(set_attr "type" "alu_shift")
3914    (set_attr "predicable" "yes")]
3915 )
3916
3917 (define_insn "*thumb_extendqisi2"
3918   [(set (match_operand:SI 0 "register_operand" "=l,l")
3919         (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3920   "TARGET_THUMB && !arm_arch6"
3921   "*
3922   {
3923     rtx ops[3];
3924     rtx mem = XEXP (operands[1], 0);
3925     
3926     if (GET_CODE (mem) == CONST)
3927       mem = XEXP (mem, 0);
3928     
3929     if (GET_CODE (mem) == LABEL_REF)
3930       return \"ldr\\t%0, %1\";
3931
3932     if (GET_CODE (mem) == PLUS
3933         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3934       return \"ldr\\t%0, %1\";
3935       
3936     if (which_alternative == 0)
3937       return \"ldrsb\\t%0, %1\";
3938       
3939     ops[0] = operands[0];
3940     
3941     if (GET_CODE (mem) == PLUS)
3942       {
3943         rtx a = XEXP (mem, 0);
3944         rtx b = XEXP (mem, 1);
3945         
3946         ops[1] = a;
3947         ops[2] = b;
3948
3949         if (GET_CODE (a) == REG)
3950           {
3951             if (GET_CODE (b) == REG)
3952               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3953             else if (REGNO (a) == REGNO (ops[0]))
3954               {
3955                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3956                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3957                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3958               }
3959             else
3960               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3961           }
3962         else if (GET_CODE (b) != REG)
3963           abort ();
3964         else
3965           {
3966             if (REGNO (b) == REGNO (ops[0]))
3967               {
3968                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3969                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3970                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3971               }
3972             else
3973               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3974           }
3975       }
3976     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3977       {
3978         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3979         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3980         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3981       }
3982     else
3983       {
3984         ops[1] = mem;
3985         ops[2] = const0_rtx;
3986         
3987         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3988       }
3989     return \"\";
3990   }"
3991   [(set_attr "length" "2,6")
3992    (set_attr "type" "load_byte,load_byte")
3993    (set_attr "pool_range" "32,32")]
3994 )
3995
3996 (define_insn "*thumb_extendqisi2_v6"
3997   [(set (match_operand:SI 0 "register_operand" "=l,l,l")
3998         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
3999   "TARGET_THUMB && arm_arch6"
4000   "*
4001   {
4002     rtx ops[3];
4003     rtx mem;
4004
4005     if (which_alternative == 0)
4006       return \"sxtb\\t%0, %1\";
4007
4008     mem = XEXP (operands[1], 0);
4009     
4010     if (GET_CODE (mem) == CONST)
4011       mem = XEXP (mem, 0);
4012     
4013     if (GET_CODE (mem) == LABEL_REF)
4014       return \"ldr\\t%0, %1\";
4015
4016     if (GET_CODE (mem) == PLUS
4017         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4018       return \"ldr\\t%0, %1\";
4019       
4020     if (which_alternative == 0)
4021       return \"ldrsb\\t%0, %1\";
4022       
4023     ops[0] = operands[0];
4024     
4025     if (GET_CODE (mem) == PLUS)
4026       {
4027         rtx a = XEXP (mem, 0);
4028         rtx b = XEXP (mem, 1);
4029         
4030         ops[1] = a;
4031         ops[2] = b;
4032
4033         if (GET_CODE (a) == REG)
4034           {
4035             if (GET_CODE (b) == REG)
4036               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4037             else if (REGNO (a) == REGNO (ops[0]))
4038               {
4039                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4040                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4041               }
4042             else
4043               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4044           }
4045         else if (GET_CODE (b) != REG)
4046           abort ();
4047         else
4048           {
4049             if (REGNO (b) == REGNO (ops[0]))
4050               {
4051                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4052                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4053               }
4054             else
4055               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4056           }
4057       }
4058     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4059       {
4060         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4061         output_asm_insn (\"sxtb\\t%0, %0\", ops);
4062       }
4063     else
4064       {
4065         ops[1] = mem;
4066         ops[2] = const0_rtx;
4067         
4068         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4069       }
4070     return \"\";
4071   }"
4072   [(set_attr "length" "2,2,4")
4073    (set_attr "type" "alu_shift,load_byte,load_byte")
4074    (set_attr "pool_range" "*,32,32")]
4075 )
4076
4077 (define_expand "extendsfdf2"
4078   [(set (match_operand:DF                  0 "s_register_operand" "")
4079         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
4080   "TARGET_ARM && TARGET_HARD_FLOAT"
4081   ""
4082 )
4083 \f
4084 ;; Move insns (including loads and stores)
4085
4086 ;; XXX Just some ideas about movti.
4087 ;; I don't think these are a good idea on the arm, there just aren't enough
4088 ;; registers
4089 ;;(define_expand "loadti"
4090 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
4091 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
4092 ;;  "" "")
4093
4094 ;;(define_expand "storeti"
4095 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4096 ;;      (match_operand:TI 1 "s_register_operand" ""))]
4097 ;;  "" "")
4098
4099 ;;(define_expand "movti"
4100 ;;  [(set (match_operand:TI 0 "general_operand" "")
4101 ;;      (match_operand:TI 1 "general_operand" ""))]
4102 ;;  ""
4103 ;;  "
4104 ;;{
4105 ;;  rtx insn;
4106 ;;
4107 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4108 ;;    operands[1] = copy_to_reg (operands[1]);
4109 ;;  if (GET_CODE (operands[0]) == MEM)
4110 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4111 ;;  else if (GET_CODE (operands[1]) == MEM)
4112 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4113 ;;  else
4114 ;;    FAIL;
4115 ;;
4116 ;;  emit_insn (insn);
4117 ;;  DONE;
4118 ;;}")
4119
4120 ;; Recognize garbage generated above.
4121
4122 ;;(define_insn ""
4123 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4124 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4125 ;;  ""
4126 ;;  "*
4127 ;;  {
4128 ;;    register mem = (which_alternative < 3);
4129 ;;    register const char *template;
4130 ;;
4131 ;;    operands[mem] = XEXP (operands[mem], 0);
4132 ;;    switch (which_alternative)
4133 ;;      {
4134 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4135 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
4136 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
4137 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
4138 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
4139 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
4140 ;;      }
4141 ;;    output_asm_insn (template, operands);
4142 ;;    return \"\";
4143 ;;  }")
4144
4145 (define_expand "movdi"
4146   [(set (match_operand:DI 0 "general_operand" "")
4147         (match_operand:DI 1 "general_operand" ""))]
4148   "TARGET_EITHER"
4149   "
4150   if (TARGET_THUMB)
4151     {
4152       if (!no_new_pseudos)
4153         {
4154           if (GET_CODE (operands[0]) != REG)
4155             operands[1] = force_reg (DImode, operands[1]);
4156         }
4157     }
4158   "
4159 )
4160
4161 (define_insn "*arm_movdi"
4162   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r ,m")
4163         (match_operand:DI 1 "di_operand"              "rIK,mi,r"))]
4164   "TARGET_ARM
4165   && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4166   && !TARGET_IWMMXT"
4167   "*
4168   return (output_move_double (operands));
4169   "
4170   [(set_attr "length" "8")
4171    (set_attr "type" "*,load2,store2")
4172    (set_attr "pool_range" "*,1020,*")
4173    (set_attr "neg_pool_range" "*,1008,*")]
4174 )
4175
4176 ;; We can't actually do base+index doubleword loads if the index and
4177 ;; destination overlap.  Split here so that we at least have chance to
4178 ;; schedule.
4179 (define_split
4180   [(set (match_operand:DI 0 "s_register_operand" "")
4181         (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4182                          (match_operand:SI 2 "s_register_operand" ""))))]
4183   "TARGET_LDRD
4184   && reg_overlap_mentioned_p (operands[0], operands[1])
4185   && reg_overlap_mentioned_p (operands[0], operands[2])"
4186   [(set (match_dup 4)
4187         (plus:SI (match_dup 1)
4188                  (match_dup 2)))
4189    (set (match_dup 0)
4190         (mem:DI (match_dup 4)))]
4191   "
4192   operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4193   "
4194 )
4195
4196 ;;; ??? This should have alternatives for constants.
4197 ;;; ??? This was originally identical to the movdf_insn pattern.
4198 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4199 ;;; thumb_reorg with a memory reference.
4200 (define_insn "*thumb_movdi_insn"
4201   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4202         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
4203   "TARGET_THUMB
4204    && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4205    && (   register_operand (operands[0], DImode)
4206        || register_operand (operands[1], DImode))"
4207   "*
4208   {
4209   switch (which_alternative)
4210     {
4211     default:
4212     case 0:
4213       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4214         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
4215       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
4216     case 1:
4217       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4218     case 2:
4219       operands[1] = GEN_INT (- INTVAL (operands[1]));
4220       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4221     case 3:
4222       return \"ldmia\\t%1, {%0, %H0}\";
4223     case 4:
4224       return \"stmia\\t%0, {%1, %H1}\";
4225     case 5:
4226       return thumb_load_double_from_address (operands);
4227     case 6:
4228       operands[2] = gen_rtx_MEM (SImode,
4229                              plus_constant (XEXP (operands[0], 0), 4));
4230       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4231       return \"\";
4232     case 7:
4233       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4234         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4235       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4236     }
4237   }"
4238   [(set_attr "length" "4,4,6,2,2,6,4,4")
4239    (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4240    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4241 )
4242
4243 (define_expand "movsi"
4244   [(set (match_operand:SI 0 "general_operand" "")
4245         (match_operand:SI 1 "general_operand" ""))]
4246   "TARGET_EITHER"
4247   "
4248   if (TARGET_ARM)
4249     {
4250       /* Everything except mem = const or mem = mem can be done easily.  */
4251       if (GET_CODE (operands[0]) == MEM)
4252         operands[1] = force_reg (SImode, operands[1]);
4253       if (arm_general_register_operand (operands[0], SImode)
4254           && GET_CODE (operands[1]) == CONST_INT
4255           && !(const_ok_for_arm (INTVAL (operands[1]))
4256                || const_ok_for_arm (~INTVAL (operands[1]))))
4257         {
4258            arm_split_constant (SET, SImode, NULL_RTX,
4259                                INTVAL (operands[1]), operands[0], NULL_RTX,
4260                               (no_new_pseudos ? 0
4261                                : preserve_subexpressions_p ()));
4262           DONE;
4263         }
4264     }
4265   else /* TARGET_THUMB....  */
4266     {
4267       if (!no_new_pseudos)
4268         {
4269           if (GET_CODE (operands[0]) != REG)
4270             operands[1] = force_reg (SImode, operands[1]);
4271         }
4272     }
4273     
4274   if (flag_pic
4275       && (CONSTANT_P (operands[1])
4276          || symbol_mentioned_p (operands[1])
4277          || label_mentioned_p (operands[1])))
4278     operands[1] = legitimize_pic_address (operands[1], SImode,
4279                                           (no_new_pseudos ? operands[0] : 0));
4280   "
4281 )
4282
4283 (define_insn "*arm_movsi_insn"
4284   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4285         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
4286   "TARGET_ARM && ! TARGET_IWMMXT
4287    && !(TARGET_HARD_FLOAT && TARGET_VFP)
4288    && (   register_operand (operands[0], SImode)
4289        || register_operand (operands[1], SImode))"
4290   "@
4291    mov%?\\t%0, %1
4292    mvn%?\\t%0, #%B1
4293    ldr%?\\t%0, %1
4294    str%?\\t%1, %0"
4295   [(set_attr "type" "*,*,load1,store1")
4296    (set_attr "predicable" "yes")
4297    (set_attr "pool_range" "*,*,4096,*")
4298    (set_attr "neg_pool_range" "*,*,4084,*")]
4299 )
4300
4301 (define_split
4302   [(set (match_operand:SI 0 "arm_general_register_operand" "")
4303         (match_operand:SI 1 "const_int_operand" ""))]
4304   "TARGET_ARM
4305   && (!(const_ok_for_arm (INTVAL (operands[1]))
4306         || const_ok_for_arm (~INTVAL (operands[1]))))"
4307   [(clobber (const_int 0))]
4308   "
4309   arm_split_constant (SET, SImode, NULL_RTX, 
4310                       INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4311   DONE;
4312   "
4313 )
4314
4315 (define_insn "*thumb_movsi_insn"
4316   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4317         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4318   "TARGET_THUMB
4319    && (   register_operand (operands[0], SImode) 
4320        || register_operand (operands[1], SImode))"
4321   "@
4322    mov  %0, %1
4323    mov  %0, %1
4324    #
4325    #
4326    ldmia\\t%1, {%0}
4327    stmia\\t%0, {%1}
4328    ldr\\t%0, %1
4329    str\\t%1, %0
4330    mov\\t%0, %1"
4331   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4332    (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4333    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4334 )
4335
4336 (define_split 
4337   [(set (match_operand:SI 0 "register_operand" "")
4338         (match_operand:SI 1 "const_int_operand" ""))]
4339   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4340   [(set (match_dup 0) (match_dup 1))
4341    (set (match_dup 0) (neg:SI (match_dup 0)))]
4342   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4343 )
4344
4345 (define_split 
4346   [(set (match_operand:SI 0 "register_operand" "")
4347         (match_operand:SI 1 "const_int_operand" ""))]
4348   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4349   [(set (match_dup 0) (match_dup 1))
4350    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4351   "
4352   {
4353     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4354     unsigned HOST_WIDE_INT mask = 0xff;
4355     int i;
4356     
4357     for (i = 0; i < 25; i++)
4358       if ((val & (mask << i)) == val)
4359         break;
4360
4361     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4362     if (i == 0)
4363       FAIL;
4364
4365     operands[1] = GEN_INT (val >> i);
4366     operands[2] = GEN_INT (i);
4367   }"
4368 )
4369
4370 ;; When generating pic, we need to load the symbol offset into a register.
4371 ;; So that the optimizer does not confuse this with a normal symbol load
4372 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
4373 ;; since that is the only type of relocation we can use.
4374
4375 ;; The rather odd constraints on the following are to force reload to leave
4376 ;; the insn alone, and to force the minipool generation pass to then move
4377 ;; the GOT symbol to memory.
4378
4379 (define_insn "pic_load_addr_arm"
4380   [(set (match_operand:SI 0 "s_register_operand" "=r")
4381         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4382   "TARGET_ARM && flag_pic"
4383   "ldr%?\\t%0, %1"
4384   [(set_attr "type" "load1")
4385    (set (attr "pool_range")     (const_int 4096))
4386    (set (attr "neg_pool_range") (const_int 4084))]
4387 )
4388
4389 (define_insn "pic_load_addr_thumb"
4390   [(set (match_operand:SI 0 "s_register_operand" "=l")
4391         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4392   "TARGET_THUMB && flag_pic"
4393   "ldr\\t%0, %1"
4394   [(set_attr "type" "load1")
4395    (set (attr "pool_range") (const_int 1024))]
4396 )
4397
4398 ;; This variant is used for AOF assembly, since it needs to mention the
4399 ;; pic register in the rtl.
4400 (define_expand "pic_load_addr_based"
4401   [(set (match_operand:SI 0 "s_register_operand" "")
4402         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4403   "TARGET_ARM && flag_pic"
4404   "operands[2] = pic_offset_table_rtx;"
4405 )
4406
4407 (define_insn "*pic_load_addr_based_insn"
4408   [(set (match_operand:SI 0 "s_register_operand" "=r")
4409         (unspec:SI [(match_operand 1 "" "")
4410                     (match_operand 2 "s_register_operand" "r")]
4411                    UNSPEC_PIC_SYM))]
4412   "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4413   "*
4414 #ifdef AOF_ASSEMBLER
4415   operands[1] = aof_pic_entry (operands[1]);
4416 #endif
4417   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4418   return \"\";
4419   "
4420   [(set_attr "type" "load1")
4421    (set (attr "pool_range")
4422         (if_then_else (eq_attr "is_thumb" "yes")
4423                       (const_int 1024)
4424                       (const_int 4096)))
4425    (set (attr "neg_pool_range")
4426         (if_then_else (eq_attr "is_thumb" "yes")
4427                       (const_int 0)
4428                       (const_int 4084)))]
4429 )
4430
4431 (define_insn "pic_add_dot_plus_four"
4432   [(set (match_operand:SI 0 "register_operand" "+r")
4433         (unspec:SI [(plus:SI (match_dup 0)
4434                              (const (plus:SI (pc) (const_int 4))))]
4435                    UNSPEC_PIC_BASE))
4436    (use (label_ref (match_operand 1 "" "")))]
4437   "TARGET_THUMB && flag_pic"
4438   "*
4439   (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4440                              CODE_LABEL_NUMBER (operands[1]));
4441   return \"add\\t%0, %|pc\";
4442   "
4443   [(set_attr "length" "2")]
4444 )
4445
4446 (define_insn "pic_add_dot_plus_eight"
4447   [(set (match_operand:SI 0 "register_operand" "+r")
4448         (unspec:SI [(plus:SI (match_dup 0)
4449                              (const (plus:SI (pc) (const_int 8))))]
4450                    UNSPEC_PIC_BASE))
4451    (use (label_ref (match_operand 1 "" "")))]
4452   "TARGET_ARM && flag_pic"
4453   "*
4454     (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4455                                CODE_LABEL_NUMBER (operands[1]));
4456     return \"add%?\\t%0, %|pc, %0\";
4457   "
4458   [(set_attr "predicable" "yes")]
4459 )
4460
4461 (define_expand "builtin_setjmp_receiver"
4462   [(label_ref (match_operand 0 "" ""))]
4463   "flag_pic"
4464   "
4465 {
4466   arm_finalize_pic (0);
4467   DONE;
4468 }")
4469
4470 ;; If copying one reg to another we can set the condition codes according to
4471 ;; its value.  Such a move is common after a return from subroutine and the
4472 ;; result is being tested against zero.
4473
4474 (define_insn "*movsi_compare0"
4475   [(set (reg:CC CC_REGNUM)
4476         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4477                     (const_int 0)))
4478    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4479         (match_dup 1))]
4480   "TARGET_ARM"
4481   "@
4482    cmp%?\\t%0, #0
4483    sub%?s\\t%0, %1, #0"
4484   [(set_attr "conds" "set")]
4485 )
4486
4487 ;; Subroutine to store a half word from a register into memory.
4488 ;; Operand 0 is the source register (HImode)
4489 ;; Operand 1 is the destination address in a register (SImode)
4490
4491 ;; In both this routine and the next, we must be careful not to spill
4492 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4493 ;; can generate unrecognizable rtl.
4494
4495 (define_expand "storehi"
4496   [;; store the low byte
4497    (set (match_operand 1 "" "") (match_dup 3))
4498    ;; extract the high byte
4499    (set (match_dup 2)
4500         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4501    ;; store the high byte
4502    (set (match_dup 4) (match_dup 5))]
4503   "TARGET_ARM"
4504   "
4505   {
4506     rtx op1 = operands[1];
4507     rtx addr = XEXP (op1, 0);
4508     enum rtx_code code = GET_CODE (addr);
4509
4510     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4511         || code == MINUS)
4512       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4513
4514     operands[4] = adjust_address (op1, QImode, 1);
4515     operands[1] = adjust_address (operands[1], QImode, 0);
4516     operands[3] = gen_lowpart (QImode, operands[0]);
4517     operands[0] = gen_lowpart (SImode, operands[0]);
4518     operands[2] = gen_reg_rtx (SImode);
4519     operands[5] = gen_lowpart (QImode, operands[2]);
4520   }"
4521 )
4522
4523 (define_expand "storehi_bigend"
4524   [(set (match_dup 4) (match_dup 3))
4525    (set (match_dup 2)
4526         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4527    (set (match_operand 1 "" "") (match_dup 5))]
4528   "TARGET_ARM"
4529   "
4530   {
4531     rtx op1 = operands[1];
4532     rtx addr = XEXP (op1, 0);
4533     enum rtx_code code = GET_CODE (addr);
4534
4535     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4536         || code == MINUS)
4537       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4538
4539     operands[4] = adjust_address (op1, QImode, 1);
4540     operands[1] = adjust_address (operands[1], QImode, 0);
4541     operands[3] = gen_lowpart (QImode, operands[0]);
4542     operands[0] = gen_lowpart (SImode, operands[0]);
4543     operands[2] = gen_reg_rtx (SImode);
4544     operands[5] = gen_lowpart (QImode, operands[2]);
4545   }"
4546 )
4547
4548 ;; Subroutine to store a half word integer constant into memory.
4549 (define_expand "storeinthi"
4550   [(set (match_operand 0 "" "")
4551         (match_operand 1 "" ""))
4552    (set (match_dup 3) (match_dup 2))]
4553   "TARGET_ARM"
4554   "
4555   {
4556     HOST_WIDE_INT value = INTVAL (operands[1]);
4557     rtx addr = XEXP (operands[0], 0);
4558     rtx op0 = operands[0];
4559     enum rtx_code code = GET_CODE (addr);
4560
4561     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4562         || code == MINUS)
4563       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4564
4565     operands[1] = gen_reg_rtx (SImode);
4566     if (BYTES_BIG_ENDIAN)
4567       {
4568         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4569         if ((value & 255) == ((value >> 8) & 255))
4570           operands[2] = operands[1];
4571         else
4572           {
4573             operands[2] = gen_reg_rtx (SImode);
4574             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4575           }
4576       }
4577     else
4578       {
4579         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4580         if ((value & 255) == ((value >> 8) & 255))
4581           operands[2] = operands[1];
4582         else
4583           {
4584             operands[2] = gen_reg_rtx (SImode);
4585             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4586           }
4587       }
4588
4589     operands[3] = adjust_address (op0, QImode, 1);
4590     operands[0] = adjust_address (operands[0], QImode, 0);
4591     operands[2] = gen_lowpart (QImode, operands[2]);
4592     operands[1] = gen_lowpart (QImode, operands[1]);
4593   }"
4594 )
4595
4596 (define_expand "storehi_single_op"
4597   [(set (match_operand:HI 0 "memory_operand" "")
4598         (match_operand:HI 1 "general_operand" ""))]
4599   "TARGET_ARM && arm_arch4"
4600   "
4601   if (!s_register_operand (operands[1], HImode))
4602     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4603   "
4604 )
4605
4606 (define_expand "movhi"
4607   [(set (match_operand:HI 0 "general_operand" "")
4608         (match_operand:HI 1 "general_operand" ""))]
4609   "TARGET_EITHER"
4610   "
4611   if (TARGET_ARM)
4612     {
4613       if (!no_new_pseudos)
4614         {
4615           if (GET_CODE (operands[0]) == MEM)
4616             {
4617               if (arm_arch4)
4618                 {
4619                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4620                   DONE;
4621                 }
4622               if (GET_CODE (operands[1]) == CONST_INT)
4623                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4624               else
4625                 {
4626                   if (GET_CODE (operands[1]) == MEM)
4627                     operands[1] = force_reg (HImode, operands[1]);
4628                   if (BYTES_BIG_ENDIAN)
4629                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4630                   else
4631                    emit_insn (gen_storehi (operands[1], operands[0]));
4632                 }
4633               DONE;
4634             }
4635           /* Sign extend a constant, and keep it in an SImode reg.  */
4636           else if (GET_CODE (operands[1]) == CONST_INT)
4637             {
4638               rtx reg = gen_reg_rtx (SImode);
4639               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4640
4641               /* If the constant is already valid, leave it alone.  */
4642               if (!const_ok_for_arm (val))
4643                 {
4644                   /* If setting all the top bits will make the constant 
4645                      loadable in a single instruction, then set them.  
4646                      Otherwise, sign extend the number.  */
4647
4648                   if (const_ok_for_arm (~(val | ~0xffff)))
4649                     val |= ~0xffff;
4650                   else if (val & 0x8000)
4651                     val |= ~0xffff;
4652                 }
4653
4654               emit_insn (gen_movsi (reg, GEN_INT (val)));
4655               operands[1] = gen_lowpart (HImode, reg);
4656             }
4657           else if (arm_arch4 && !no_new_pseudos && optimize > 0
4658                    && GET_CODE (operands[1]) == MEM)
4659             {
4660               rtx reg = gen_reg_rtx (SImode);
4661
4662               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4663               operands[1] = gen_lowpart (HImode, reg);
4664             }
4665           else if (!arm_arch4)
4666             {
4667               if (GET_CODE (operands[1]) == MEM)
4668                 {
4669                   rtx base;
4670                   rtx offset = const0_rtx;
4671                   rtx reg = gen_reg_rtx (SImode);
4672
4673                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4674                        || (GET_CODE (base) == PLUS
4675                            && (GET_CODE (offset = XEXP (base, 1))
4676                                == CONST_INT)
4677                            && ((INTVAL(offset) & 1) != 1)
4678                            && GET_CODE (base = XEXP (base, 0)) == REG))
4679                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4680                     {
4681                       HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4682                       rtx new;
4683
4684                       new = gen_rtx_MEM (SImode,
4685                                          plus_constant (base, new_offset));
4686                       MEM_COPY_ATTRIBUTES (new, operands[1]);
4687                       emit_insn (gen_movsi (reg, new));
4688                       if (((INTVAL (offset) & 2) != 0)
4689                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4690                         {
4691                           rtx reg2 = gen_reg_rtx (SImode);
4692
4693                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4694                           reg = reg2;
4695                         }
4696                     }
4697                   else
4698                     emit_insn (gen_movhi_bytes (reg, operands[1]));
4699
4700                   operands[1] = gen_lowpart (HImode, reg);
4701                }
4702            }
4703         }
4704       /* Handle loading a large integer during reload.  */
4705       else if (GET_CODE (operands[1]) == CONST_INT
4706                && !const_ok_for_arm (INTVAL (operands[1]))
4707                && !const_ok_for_arm (~INTVAL (operands[1])))
4708         {
4709           /* Writing a constant to memory needs a scratch, which should
4710              be handled with SECONDARY_RELOADs.  */
4711           if (GET_CODE (operands[0]) != REG)
4712             abort ();
4713
4714           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4715           emit_insn (gen_movsi (operands[0], operands[1]));
4716           DONE;
4717        }
4718     }
4719   else /* TARGET_THUMB */
4720     {
4721       if (!no_new_pseudos)
4722         {
4723           if (GET_CODE (operands[0]) != REG)
4724             operands[1] = force_reg (HImode, operands[1]);
4725
4726           /* ??? We shouldn't really get invalid addresses here, but this can
4727              happen if we are passed a SP (never OK for HImode/QImode) or 
4728              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4729              HImode/QImode) relative address.  */
4730           /* ??? This should perhaps be fixed elsewhere, for instance, in
4731              fixup_stack_1, by checking for other kinds of invalid addresses,
4732              e.g. a bare reference to a virtual register.  This may confuse the
4733              alpha though, which must handle this case differently.  */
4734           if (GET_CODE (operands[0]) == MEM
4735               && !memory_address_p (GET_MODE (operands[0]),
4736                                     XEXP (operands[0], 0)))
4737             operands[0]
4738               = replace_equiv_address (operands[0],
4739                                        copy_to_reg (XEXP (operands[0], 0)));
4740    
4741           if (GET_CODE (operands[1]) == MEM
4742               && !memory_address_p (GET_MODE (operands[1]),
4743                                     XEXP (operands[1], 0)))
4744             operands[1]
4745               = replace_equiv_address (operands[1],
4746                                        copy_to_reg (XEXP (operands[1], 0)));
4747         }
4748       /* Handle loading a large integer during reload.  */
4749       else if (GET_CODE (operands[1]) == CONST_INT
4750                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4751         {
4752           /* Writing a constant to memory needs a scratch, which should
4753              be handled with SECONDARY_RELOADs.  */
4754           if (GET_CODE (operands[0]) != REG)
4755             abort ();
4756
4757           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4758           emit_insn (gen_movsi (operands[0], operands[1]));
4759           DONE;
4760         }
4761     }
4762   "
4763 )
4764
4765 (define_insn "*thumb_movhi_insn"
4766   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4767         (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
4768   "TARGET_THUMB
4769    && (   register_operand (operands[0], HImode)
4770        || register_operand (operands[1], HImode))"
4771   "*
4772   switch (which_alternative)
4773     {
4774     case 0: return \"add        %0, %1, #0\";
4775     case 2: return \"strh       %1, %0\";
4776     case 3: return \"mov        %0, %1\";
4777     case 4: return \"mov        %0, %1\";
4778     case 5: return \"mov        %0, %1\";
4779     default: abort ();
4780     case 1:
4781       /* The stack pointer can end up being taken as an index register.
4782           Catch this case here and deal with it.  */
4783       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4784           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4785           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4786         {
4787           rtx ops[2];
4788           ops[0] = operands[0];
4789           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4790       
4791           output_asm_insn (\"mov        %0, %1\", ops);
4792
4793           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4794     
4795         }
4796       return \"ldrh     %0, %1\";
4797     }"
4798   [(set_attr "length" "2,4,2,2,2,2")
4799    (set_attr "type" "*,load1,store1,*,*,*")]
4800 )
4801
4802
4803 (define_expand "movhi_bytes"
4804   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4805    (set (match_dup 3)
4806         (zero_extend:SI (match_dup 6)))
4807    (set (match_operand:SI 0 "" "")
4808          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4809   "TARGET_ARM"
4810   "
4811   {
4812     rtx mem1, mem2;
4813     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4814
4815     mem1 = gen_rtx_MEM (QImode, addr);
4816     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4817     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4818     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4819     operands[0] = gen_lowpart (SImode, operands[0]);
4820     operands[1] = mem1;
4821     operands[2] = gen_reg_rtx (SImode);
4822     operands[3] = gen_reg_rtx (SImode);
4823     operands[6] = mem2;
4824
4825     if (BYTES_BIG_ENDIAN)
4826       {
4827         operands[4] = operands[2];
4828         operands[5] = operands[3];
4829       }
4830     else
4831       {
4832         operands[4] = operands[3];
4833         operands[5] = operands[2];
4834       }
4835   }"
4836 )
4837
4838 (define_expand "movhi_bigend"
4839   [(set (match_dup 2)
4840         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4841                    (const_int 16)))
4842    (set (match_dup 3)
4843         (ashiftrt:SI (match_dup 2) (const_int 16)))
4844    (set (match_operand:HI 0 "s_register_operand" "")
4845         (match_dup 4))]
4846   "TARGET_ARM"
4847   "
4848   operands[2] = gen_reg_rtx (SImode);
4849   operands[3] = gen_reg_rtx (SImode);
4850   operands[4] = gen_lowpart (HImode, operands[3]);
4851   "
4852 )
4853
4854 ;; Pattern to recognize insn generated default case above
4855 (define_insn "*movhi_insn_arch4"
4856   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4857         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4858   "TARGET_ARM
4859    && arm_arch4
4860    && (GET_CODE (operands[1]) != CONST_INT
4861        || const_ok_for_arm (INTVAL (operands[1]))
4862        || const_ok_for_arm (~INTVAL (operands[1])))"
4863   "@
4864    mov%?\\t%0, %1\\t%@ movhi
4865    mvn%?\\t%0, #%B1\\t%@ movhi
4866    str%?h\\t%1, %0\\t%@ movhi 
4867    ldr%?h\\t%0, %1\\t%@ movhi"
4868   [(set_attr "type" "*,*,store1,load1")
4869    (set_attr "predicable" "yes")
4870    (set_attr "pool_range" "*,*,*,256")
4871    (set_attr "neg_pool_range" "*,*,*,244")]
4872 )
4873
4874 (define_insn "*movhi_bytes"
4875   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4876         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4877   "TARGET_ARM"
4878   "@
4879    mov%?\\t%0, %1\\t%@ movhi
4880    mvn%?\\t%0, #%B1\\t%@ movhi"
4881   [(set_attr "predicable" "yes")]
4882 )
4883
4884 (define_insn "thumb_movhi_clobber"
4885   [(set (match_operand:HI     0 "memory_operand"   "=m")
4886         (match_operand:HI     1 "register_operand" "l"))
4887    (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4888   "TARGET_THUMB"
4889   "*
4890   abort ();"
4891 )
4892         
4893 ;; We use a DImode scratch because we may occasionally need an additional
4894 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4895 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4896 (define_expand "reload_outhi"
4897   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4898               (match_operand:HI 1 "s_register_operand"        "r")
4899               (match_operand:DI 2 "s_register_operand"        "=&l")])]
4900   "TARGET_EITHER"
4901   "if (TARGET_ARM)
4902      arm_reload_out_hi (operands);
4903    else
4904      thumb_reload_out_hi (operands);
4905   DONE;
4906   "
4907 )
4908
4909 (define_expand "reload_inhi"
4910   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4911               (match_operand:HI 1 "arm_reload_memory_operand" "o")
4912               (match_operand:DI 2 "s_register_operand" "=&r")])]
4913   "TARGET_EITHER"
4914   "
4915   if (TARGET_ARM)
4916     arm_reload_in_hi (operands);
4917   else
4918     thumb_reload_out_hi (operands);
4919   DONE;
4920 ")
4921
4922 (define_expand "movqi"
4923   [(set (match_operand:QI 0 "general_operand" "")
4924         (match_operand:QI 1 "general_operand" ""))]
4925   "TARGET_EITHER"
4926   "
4927   if (TARGET_ARM)
4928     {
4929       /* Everything except mem = const or mem = mem can be done easily */
4930
4931       if (!no_new_pseudos)
4932         {
4933           if (GET_CODE (operands[1]) == CONST_INT)
4934             {
4935               rtx reg = gen_reg_rtx (SImode);
4936
4937               emit_insn (gen_movsi (reg, operands[1]));
4938               operands[1] = gen_lowpart (QImode, reg);
4939             }
4940           if (GET_CODE (operands[1]) == MEM && optimize > 0)
4941             {
4942               rtx reg = gen_reg_rtx (SImode);
4943
4944               emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4945               operands[1] = gen_lowpart (QImode, reg);
4946             }
4947           if (GET_CODE (operands[0]) == MEM)
4948             operands[1] = force_reg (QImode, operands[1]);
4949         }
4950     }
4951   else /* TARGET_THUMB */
4952     {
4953       if (!no_new_pseudos)
4954         {
4955           if (GET_CODE (operands[0]) != REG)
4956             operands[1] = force_reg (QImode, operands[1]);
4957
4958           /* ??? We shouldn't really get invalid addresses here, but this can
4959              happen if we are passed a SP (never OK for HImode/QImode) or
4960              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4961              HImode/QImode) relative address.  */
4962           /* ??? This should perhaps be fixed elsewhere, for instance, in
4963              fixup_stack_1, by checking for other kinds of invalid addresses,
4964              e.g. a bare reference to a virtual register.  This may confuse the
4965              alpha though, which must handle this case differently.  */
4966           if (GET_CODE (operands[0]) == MEM
4967               && !memory_address_p (GET_MODE (operands[0]),
4968                                      XEXP (operands[0], 0)))
4969             operands[0]
4970               = replace_equiv_address (operands[0],
4971                                        copy_to_reg (XEXP (operands[0], 0)));
4972           if (GET_CODE (operands[1]) == MEM
4973               && !memory_address_p (GET_MODE (operands[1]),
4974                                     XEXP (operands[1], 0)))
4975              operands[1]
4976                = replace_equiv_address (operands[1],
4977                                         copy_to_reg (XEXP (operands[1], 0)));
4978         }
4979       /* Handle loading a large integer during reload.  */
4980       else if (GET_CODE (operands[1]) == CONST_INT
4981                && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4982         {
4983           /* Writing a constant to memory needs a scratch, which should
4984              be handled with SECONDARY_RELOADs.  */
4985           if (GET_CODE (operands[0]) != REG)
4986             abort ();
4987
4988           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4989           emit_insn (gen_movsi (operands[0], operands[1]));
4990           DONE;
4991        }
4992     }
4993   "
4994 )
4995
4996
4997 (define_insn "*arm_movqi_insn"
4998   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4999         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5000   "TARGET_ARM
5001    && (   register_operand (operands[0], QImode)
5002        || register_operand (operands[1], QImode))"
5003   "@
5004    mov%?\\t%0, %1
5005    mvn%?\\t%0, #%B1
5006    ldr%?b\\t%0, %1
5007    str%?b\\t%1, %0"
5008   [(set_attr "type" "*,*,load1,store1")
5009    (set_attr "predicable" "yes")]
5010 )
5011
5012 (define_insn "*thumb_movqi_insn"
5013   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5014         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
5015   "TARGET_THUMB
5016    && (   register_operand (operands[0], QImode)
5017        || register_operand (operands[1], QImode))"
5018   "@
5019    add\\t%0, %1, #0
5020    ldrb\\t%0, %1
5021    strb\\t%1, %0
5022    mov\\t%0, %1
5023    mov\\t%0, %1
5024    mov\\t%0, %1"
5025   [(set_attr "length" "2")
5026    (set_attr "type" "*,load1,store1,*,*,*")
5027    (set_attr "pool_range" "*,32,*,*,*,*")]
5028 )
5029
5030 (define_expand "movsf"
5031   [(set (match_operand:SF 0 "general_operand" "")
5032         (match_operand:SF 1 "general_operand" ""))]
5033   "TARGET_EITHER"
5034   "
5035   if (TARGET_ARM)
5036     {
5037       if (GET_CODE (operands[0]) == MEM)
5038         operands[1] = force_reg (SFmode, operands[1]);
5039     }
5040   else /* TARGET_THUMB */
5041     {
5042       if (!no_new_pseudos)
5043         {
5044            if (GET_CODE (operands[0]) != REG)
5045              operands[1] = force_reg (SFmode, operands[1]);
5046         }
5047     }
5048   "
5049 )
5050
5051 (define_split
5052   [(set (match_operand:SF 0 "nonimmediate_operand" "")
5053         (match_operand:SF 1 "immediate_operand" ""))]
5054   "TARGET_ARM
5055    && !(TARGET_HARD_FLOAT && TARGET_FPA)
5056    && reload_completed
5057    && GET_CODE (operands[1]) == CONST_DOUBLE"
5058   [(set (match_dup 2) (match_dup 3))]
5059   "
5060   operands[2] = gen_lowpart (SImode, operands[0]);
5061   operands[3] = gen_lowpart (SImode, operands[1]);
5062   if (operands[2] == 0 || operands[3] == 0)
5063     FAIL;
5064   "
5065 )
5066
5067 (define_insn "*arm_movsf_soft_insn"
5068   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5069         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
5070   "TARGET_ARM
5071    && TARGET_SOFT_FLOAT
5072    && (GET_CODE (operands[0]) != MEM
5073        || register_operand (operands[1], SFmode))"
5074   "@
5075    mov%?\\t%0, %1
5076    ldr%?\\t%0, %1\\t%@ float
5077    str%?\\t%1, %0\\t%@ float"
5078   [(set_attr "length" "4,4,4")
5079    (set_attr "predicable" "yes")
5080    (set_attr "type" "*,load1,store1")
5081    (set_attr "pool_range" "*,4096,*")
5082    (set_attr "neg_pool_range" "*,4084,*")]
5083 )
5084
5085 ;;; ??? This should have alternatives for constants.
5086 (define_insn "*thumb_movsf_insn"
5087   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5088         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5089   "TARGET_THUMB
5090    && (   register_operand (operands[0], SFmode) 
5091        || register_operand (operands[1], SFmode))"
5092   "@
5093    add\\t%0, %1, #0
5094    ldmia\\t%1, {%0}
5095    stmia\\t%0, {%1}
5096    ldr\\t%0, %1
5097    str\\t%1, %0
5098    mov\\t%0, %1
5099    mov\\t%0, %1"
5100   [(set_attr "length" "2")
5101    (set_attr "type" "*,load1,store1,load1,store1,*,*")
5102    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5103 )
5104
5105 (define_expand "movdf"
5106   [(set (match_operand:DF 0 "general_operand" "")
5107         (match_operand:DF 1 "general_operand" ""))]
5108   "TARGET_EITHER"
5109   "
5110   if (TARGET_ARM)
5111     {
5112       if (GET_CODE (operands[0]) == MEM)
5113         operands[1] = force_reg (DFmode, operands[1]);
5114     }
5115   else /* TARGET_THUMB */
5116     {
5117       if (!no_new_pseudos)
5118         {
5119           if (GET_CODE (operands[0]) != REG)
5120             operands[1] = force_reg (DFmode, operands[1]);
5121         }
5122     }
5123   "
5124 )
5125
5126 ;; Reloading a df mode value stored in integer regs to memory can require a
5127 ;; scratch reg.
5128 (define_expand "reload_outdf"
5129   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5130    (match_operand:DF 1 "s_register_operand" "r")
5131    (match_operand:SI 2 "s_register_operand" "=&r")]
5132   "TARGET_ARM"
5133   "
5134   {
5135     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5136
5137     if (code == REG)
5138       operands[2] = XEXP (operands[0], 0);
5139     else if (code == POST_INC || code == PRE_DEC)
5140       {
5141         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5142         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5143         emit_insn (gen_movdi (operands[0], operands[1]));
5144         DONE;
5145       }
5146     else if (code == PRE_INC)
5147       {
5148         rtx reg = XEXP (XEXP (operands[0], 0), 0);
5149
5150         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5151         operands[2] = reg;
5152       }
5153     else if (code == POST_DEC)
5154       operands[2] = XEXP (XEXP (operands[0], 0), 0);
5155     else
5156       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5157                              XEXP (XEXP (operands[0], 0), 1)));
5158
5159     emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5160                             operands[1]));
5161
5162     if (code == POST_DEC)
5163       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5164
5165     DONE;
5166   }"
5167 )
5168
5169 (define_insn "*movdf_soft_insn"
5170   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
5171         (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
5172   "TARGET_ARM && TARGET_SOFT_FLOAT
5173   "
5174   "* return output_move_double (operands);"
5175   [(set_attr "length" "8,8,8")
5176    (set_attr "type" "*,load2,store2")
5177    (set_attr "pool_range" "1020")
5178    (set_attr "neg_pool_range" "1008")]
5179 )
5180
5181 ;;; ??? This should have alternatives for constants.
5182 ;;; ??? This was originally identical to the movdi_insn pattern.
5183 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5184 ;;; thumb_reorg with a memory reference.
5185 (define_insn "*thumb_movdf_insn"
5186   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5187         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5188   "TARGET_THUMB
5189    && (   register_operand (operands[0], DFmode)
5190        || register_operand (operands[1], DFmode))"
5191   "*
5192   switch (which_alternative)
5193     {
5194     default:
5195     case 0:
5196       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5197         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5198       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5199     case 1:
5200       return \"ldmia\\t%1, {%0, %H0}\";
5201     case 2:
5202       return \"stmia\\t%0, {%1, %H1}\";
5203     case 3:
5204       return thumb_load_double_from_address (operands);
5205     case 4:
5206       operands[2] = gen_rtx_MEM (SImode,
5207                                  plus_constant (XEXP (operands[0], 0), 4));
5208       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5209       return \"\";
5210     case 5:
5211       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5212         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5213       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5214     }
5215   "
5216   [(set_attr "length" "4,2,2,6,4,4")
5217    (set_attr "type" "*,load2,store2,load2,store2,*")
5218    (set_attr "pool_range" "*,*,*,1020,*,*")]
5219 )
5220
5221 ;; Vector Moves
5222 (define_expand "movv2si"
5223   [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5224         (match_operand:V2SI 1 "general_operand" ""))]
5225   "TARGET_REALLY_IWMMXT"
5226 {
5227 })
5228
5229 (define_expand "movv4hi"
5230   [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5231         (match_operand:V4HI 1 "general_operand" ""))]
5232   "TARGET_REALLY_IWMMXT"
5233 {
5234 })
5235
5236 (define_expand "movv8qi"
5237   [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5238         (match_operand:V8QI 1 "general_operand" ""))]
5239   "TARGET_REALLY_IWMMXT"
5240 {
5241 })
5242 \f
5243
5244 ;; load- and store-multiple insns
5245 ;; The arm can load/store any set of registers, provided that they are in
5246 ;; ascending order; but that is beyond GCC so stick with what it knows.
5247
5248 (define_expand "load_multiple"
5249   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5250                           (match_operand:SI 1 "" ""))
5251                      (use (match_operand:SI 2 "" ""))])]
5252   "TARGET_ARM"
5253   "
5254   /* Support only fixed point registers.  */
5255   if (GET_CODE (operands[2]) != CONST_INT
5256       || INTVAL (operands[2]) > 14
5257       || INTVAL (operands[2]) < 2
5258       || GET_CODE (operands[1]) != MEM
5259       || GET_CODE (operands[0]) != REG
5260       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5261       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5262     FAIL;
5263
5264   operands[3]
5265     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5266                              force_reg (SImode, XEXP (operands[1], 0)),
5267                              TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5268                              MEM_IN_STRUCT_P(operands[1]),
5269                              MEM_SCALAR_P (operands[1]));
5270   "
5271 )
5272
5273 ;; Load multiple with write-back
5274
5275 (define_insn "*ldmsi_postinc4"
5276   [(match_parallel 0 "load_multiple_operation"
5277     [(set (match_operand:SI 1 "s_register_operand" "=r")
5278           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5279                    (const_int 16)))
5280      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5281           (mem:SI (match_dup 2)))
5282      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5283           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5284      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5285           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5286      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5287           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5288   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5289   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5290   [(set_attr "type" "load4")
5291    (set_attr "predicable" "yes")]
5292 )
5293
5294 (define_insn "*ldmsi_postinc3"
5295   [(match_parallel 0 "load_multiple_operation"
5296     [(set (match_operand:SI 1 "s_register_operand" "=r")
5297           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5298                    (const_int 12)))
5299      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5300           (mem:SI (match_dup 2)))
5301      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5302           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5303      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5304           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5305   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5306   "ldm%?ia\\t%1!, {%3, %4, %5}"
5307   [(set_attr "type" "load3")
5308    (set_attr "predicable" "yes")]
5309 )
5310
5311 (define_insn "*ldmsi_postinc2"
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 8)))
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   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5321   "ldm%?ia\\t%1!, {%3, %4}"
5322   [(set_attr "type" "load2")
5323    (set_attr "predicable" "yes")]
5324 )
5325
5326 ;; Ordinary load multiple
5327
5328 (define_insn "*ldmsi4"
5329   [(match_parallel 0 "load_multiple_operation"
5330     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5331           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5332      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5333           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5334      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5335           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5336      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5337           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5338   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5339   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5340   [(set_attr "type" "load4")
5341    (set_attr "predicable" "yes")]
5342 )
5343
5344 (define_insn "*ldmsi3"
5345   [(match_parallel 0 "load_multiple_operation"
5346     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5347           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5348      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5349           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5350      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5351           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5352   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5353   "ldm%?ia\\t%1, {%2, %3, %4}"
5354   [(set_attr "type" "load3")
5355    (set_attr "predicable" "yes")]
5356 )
5357
5358 (define_insn "*ldmsi2"
5359   [(match_parallel 0 "load_multiple_operation"
5360     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5361           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5362      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5363           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5364   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5365   "ldm%?ia\\t%1, {%2, %3}"
5366   [(set_attr "type" "load2")
5367    (set_attr "predicable" "yes")]
5368 )
5369
5370 (define_expand "store_multiple"
5371   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5372                           (match_operand:SI 1 "" ""))
5373                      (use (match_operand:SI 2 "" ""))])]
5374   "TARGET_ARM"
5375   "
5376   /* Support only fixed point registers.  */
5377   if (GET_CODE (operands[2]) != CONST_INT
5378       || INTVAL (operands[2]) > 14
5379       || INTVAL (operands[2]) < 2
5380       || GET_CODE (operands[1]) != REG
5381       || GET_CODE (operands[0]) != MEM
5382       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5383       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5384     FAIL;
5385
5386   operands[3]
5387     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5388                               force_reg (SImode, XEXP (operands[0], 0)),
5389                               TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5390                               MEM_IN_STRUCT_P(operands[0]), 
5391                               MEM_SCALAR_P (operands[0]));
5392   "
5393 )
5394
5395 ;; Store multiple with write-back
5396
5397 (define_insn "*stmsi_postinc4"
5398   [(match_parallel 0 "store_multiple_operation"
5399     [(set (match_operand:SI 1 "s_register_operand" "=r")
5400           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5401                    (const_int 16)))
5402      (set (mem:SI (match_dup 2))
5403           (match_operand:SI 3 "arm_hard_register_operand" ""))
5404      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5405           (match_operand:SI 4 "arm_hard_register_operand" ""))
5406      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5407           (match_operand:SI 5 "arm_hard_register_operand" ""))
5408      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5409           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5410   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5411   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5412   [(set_attr "predicable" "yes")
5413    (set_attr "type" "store4")]
5414 )
5415
5416 (define_insn "*stmsi_postinc3"
5417   [(match_parallel 0 "store_multiple_operation"
5418     [(set (match_operand:SI 1 "s_register_operand" "=r")
5419           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5420                    (const_int 12)))
5421      (set (mem:SI (match_dup 2))
5422           (match_operand:SI 3 "arm_hard_register_operand" ""))
5423      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5424           (match_operand:SI 4 "arm_hard_register_operand" ""))
5425      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5426           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5427   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5428   "stm%?ia\\t%1!, {%3, %4, %5}"
5429   [(set_attr "predicable" "yes")
5430    (set_attr "type" "store3")]
5431 )
5432
5433 (define_insn "*stmsi_postinc2"
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 8)))
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   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5443   "stm%?ia\\t%1!, {%3, %4}"
5444   [(set_attr "predicable" "yes")
5445    (set_attr "type" "store2")]
5446 )
5447
5448 ;; Ordinary store multiple
5449
5450 (define_insn "*stmsi4"
5451   [(match_parallel 0 "store_multiple_operation"
5452     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5453           (match_operand:SI 2 "arm_hard_register_operand" ""))
5454      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5455           (match_operand:SI 3 "arm_hard_register_operand" ""))
5456      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5457           (match_operand:SI 4 "arm_hard_register_operand" ""))
5458      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5459           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5460   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5461   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5462   [(set_attr "predicable" "yes")
5463    (set_attr "type" "store4")]
5464 )
5465
5466 (define_insn "*stmsi3"
5467   [(match_parallel 0 "store_multiple_operation"
5468     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5469           (match_operand:SI 2 "arm_hard_register_operand" ""))
5470      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5471           (match_operand:SI 3 "arm_hard_register_operand" ""))
5472      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5473           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5474   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5475   "stm%?ia\\t%1, {%2, %3, %4}"
5476   [(set_attr "predicable" "yes")
5477    (set_attr "type" "store3")]
5478 )
5479
5480 (define_insn "*stmsi2"
5481   [(match_parallel 0 "store_multiple_operation"
5482     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5483           (match_operand:SI 2 "arm_hard_register_operand" ""))
5484      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5485           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5486   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5487   "stm%?ia\\t%1, {%2, %3}"
5488   [(set_attr "predicable" "yes")
5489    (set_attr "type" "store2")]
5490 )
5491
5492 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5493 ;; We could let this apply for blocks of less than this, but it clobbers so
5494 ;; many registers that there is then probably a better way.
5495
5496 (define_expand "movmemqi"
5497   [(match_operand:BLK 0 "general_operand" "")
5498    (match_operand:BLK 1 "general_operand" "")
5499    (match_operand:SI 2 "const_int_operand" "")
5500    (match_operand:SI 3 "const_int_operand" "")]
5501   "TARGET_EITHER"
5502   "
5503   if (TARGET_ARM)
5504     {
5505       if (arm_gen_movmemqi (operands))
5506         DONE;
5507       FAIL;
5508     }
5509   else /* TARGET_THUMB */
5510     {
5511       if (   INTVAL (operands[3]) != 4
5512           || INTVAL (operands[2]) > 48)
5513         FAIL;
5514
5515       thumb_expand_movmemqi (operands);
5516       DONE;
5517     }
5518   "
5519 )
5520
5521 ;; Thumb block-move insns
5522
5523 (define_insn "movmem12b"
5524   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5525         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5526    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5527         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5528    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5529         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5530    (set (match_operand:SI 0 "register_operand" "=l")
5531         (plus:SI (match_dup 2) (const_int 12)))
5532    (set (match_operand:SI 1 "register_operand" "=l")
5533         (plus:SI (match_dup 3) (const_int 12)))
5534    (clobber (match_scratch:SI 4 "=&l"))
5535    (clobber (match_scratch:SI 5 "=&l"))
5536    (clobber (match_scratch:SI 6 "=&l"))]
5537   "TARGET_THUMB"
5538   "* return thumb_output_move_mem_multiple (3, operands);"
5539   [(set_attr "length" "4")
5540    ; This isn't entirely accurate...  It loads as well, but in terms of
5541    ; scheduling the following insn it is better to consider it as a store
5542    (set_attr "type" "store3")]
5543 )
5544
5545 (define_insn "movmem8b"
5546   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5547         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5548    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5549         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5550    (set (match_operand:SI 0 "register_operand" "=l")
5551         (plus:SI (match_dup 2) (const_int 8)))
5552    (set (match_operand:SI 1 "register_operand" "=l")
5553         (plus:SI (match_dup 3) (const_int 8)))
5554    (clobber (match_scratch:SI 4 "=&l"))
5555    (clobber (match_scratch:SI 5 "=&l"))]
5556   "TARGET_THUMB"
5557   "* return thumb_output_move_mem_multiple (2, operands);"
5558   [(set_attr "length" "4")
5559    ; This isn't entirely accurate...  It loads as well, but in terms of
5560    ; scheduling the following insn it is better to consider it as a store
5561    (set_attr "type" "store2")]
5562 )
5563
5564 \f
5565
5566 ;; Compare & branch insns
5567 ;; The range calculations are based as follows:
5568 ;; For forward branches, the address calculation returns the address of
5569 ;; the next instruction.  This is 2 beyond the branch instruction.
5570 ;; For backward branches, the address calculation returns the address of
5571 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5572 ;; instruction for the shortest sequence, and 4 before the branch instruction
5573 ;; if we have to jump around an unconditional branch.
5574 ;; To the basic branch range the PC offset must be added (this is +4).
5575 ;; So for forward branches we have 
5576 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5577 ;; And for backward branches we have 
5578 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5579 ;;
5580 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5581 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5582
5583 (define_expand "cbranchsi4"
5584   [(set (pc) (if_then_else
5585               (match_operator 0 "arm_comparison_operator"
5586                [(match_operand:SI 1 "s_register_operand" "")
5587                 (match_operand:SI 2 "nonmemory_operand" "")])
5588               (label_ref (match_operand 3 "" ""))
5589               (pc)))]
5590   "TARGET_THUMB"
5591   "
5592   if (thumb_cmpneg_operand (operands[2], SImode))
5593     {
5594       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5595                                               operands[3], operands[0]));
5596       DONE;
5597     }
5598   if (!thumb_cmp_operand (operands[2], SImode))
5599     operands[2] = force_reg (SImode, operands[2]);
5600   ")
5601
5602 (define_insn "*cbranchsi4_insn"
5603   [(set (pc) (if_then_else
5604               (match_operator 0 "arm_comparison_operator"
5605                [(match_operand:SI 1 "s_register_operand" "l,*h")
5606                 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5607               (label_ref (match_operand 3 "" ""))
5608               (pc)))]
5609   "TARGET_THUMB"
5610   "*
5611   output_asm_insn (\"cmp\\t%1, %2\", operands);
5612
5613   switch (get_attr_length (insn))
5614     {
5615     case 4:  return \"b%d0\\t%l3\";
5616     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5617     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5618     }
5619   "
5620   [(set (attr "far_jump")
5621         (if_then_else
5622             (eq_attr "length" "8")
5623             (const_string "yes")
5624             (const_string "no")))
5625    (set (attr "length") 
5626         (if_then_else
5627             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5628                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5629             (const_int 4)
5630             (if_then_else
5631                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5632                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5633                 (const_int 6)
5634                 (const_int 8))))]
5635 )
5636
5637 (define_insn "cbranchsi4_scratch"
5638   [(set (pc) (if_then_else
5639               (match_operator 4 "arm_comparison_operator"
5640                [(match_operand:SI 1 "s_register_operand" "l,0")
5641                 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5642               (label_ref (match_operand 3 "" ""))
5643               (pc)))
5644    (clobber (match_scratch:SI 0 "=l,l"))]
5645   "TARGET_THUMB"
5646   "*
5647   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5648
5649   switch (get_attr_length (insn))
5650     {
5651     case 4:  return \"b%d4\\t%l3\";
5652     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5653     default: return \"b%D4\\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 (define_insn "*movsi_cbranchsi4"
5673   [(set (pc)
5674         (if_then_else
5675          (match_operator 3 "arm_comparison_operator"
5676           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5677            (const_int 0)])
5678          (label_ref (match_operand 2 "" ""))
5679          (pc)))
5680    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5681         (match_dup 1))]
5682   "TARGET_THUMB"
5683   "*{
5684   if (which_alternative == 0)
5685     output_asm_insn (\"cmp\t%0, #0\", operands);
5686   else if (which_alternative == 1)
5687     output_asm_insn (\"sub\t%0, %1, #0\", operands);
5688   else
5689     {
5690       output_asm_insn (\"cmp\t%1, #0\", operands);
5691       if (which_alternative == 2)
5692         output_asm_insn (\"mov\t%0, %1\", operands);
5693       else
5694         output_asm_insn (\"str\t%1, %0\", operands);
5695     }
5696   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5697     {
5698     case 4:  return \"b%d3\\t%l2\";
5699     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5700     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5701     }
5702   }"
5703   [(set (attr "far_jump")
5704         (if_then_else
5705             (ior (and (gt (symbol_ref ("which_alternative"))
5706                           (const_int 1))
5707                       (eq_attr "length" "8"))
5708                  (eq_attr "length" "10"))
5709             (const_string "yes")
5710             (const_string "no")))
5711    (set (attr "length")
5712      (if_then_else
5713        (le (symbol_ref ("which_alternative"))
5714                        (const_int 1))
5715        (if_then_else
5716          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5717               (le (minus (match_dup 2) (pc)) (const_int 256)))
5718          (const_int 4)
5719          (if_then_else
5720            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5721                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5722            (const_int 6)
5723            (const_int 8)))
5724        (if_then_else
5725          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5726               (le (minus (match_dup 2) (pc)) (const_int 256)))
5727          (const_int 6)
5728          (if_then_else
5729            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5730                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5731            (const_int 8)
5732            (const_int 10)))))]
5733 )
5734
5735 (define_insn "*negated_cbranchsi4"
5736   [(set (pc)
5737         (if_then_else
5738          (match_operator 0 "arm_comparison_operator"
5739           [(match_operand:SI 1 "s_register_operand" "l")
5740            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5741          (label_ref (match_operand 3 "" ""))
5742          (pc)))]
5743   "TARGET_THUMB"
5744   "*
5745   output_asm_insn (\"cmn\\t%1, %2\", operands);
5746   switch (get_attr_length (insn))
5747     {
5748     case 4:  return \"b%d0\\t%l3\";
5749     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5750     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5751     }
5752   "
5753   [(set (attr "far_jump")
5754         (if_then_else
5755             (eq_attr "length" "8")
5756             (const_string "yes")
5757             (const_string "no")))
5758    (set (attr "length") 
5759         (if_then_else
5760             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5761                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5762             (const_int 4)
5763             (if_then_else
5764                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5765                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5766                 (const_int 6)
5767                 (const_int 8))))]
5768 )
5769
5770 (define_insn "*tbit_cbranch"
5771   [(set (pc)
5772         (if_then_else
5773          (match_operator 0 "equality_operator"
5774           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5775                             (const_int 1)
5776                             (match_operand:SI 2 "const_int_operand" "i"))
5777            (const_int 0)])
5778          (label_ref (match_operand 3 "" ""))
5779          (pc)))
5780    (clobber (match_scratch:SI 4 "=l"))]
5781   "TARGET_THUMB"
5782   "*
5783   {
5784   rtx op[3];
5785   op[0] = operands[4];
5786   op[1] = operands[1];
5787   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5788
5789   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5790   switch (get_attr_length (insn))
5791     {
5792     case 4:  return \"b%d0\\t%l3\";
5793     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5794     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5795     }
5796   }"
5797   [(set (attr "far_jump")
5798         (if_then_else
5799             (eq_attr "length" "8")
5800             (const_string "yes")
5801             (const_string "no")))
5802    (set (attr "length") 
5803         (if_then_else
5804             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5805                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5806             (const_int 4)
5807             (if_then_else
5808                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5809                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5810                 (const_int 6)
5811                 (const_int 8))))]
5812 )
5813   
5814 (define_insn "*tstsi3_cbranch"
5815   [(set (pc)
5816         (if_then_else
5817          (match_operator 3 "equality_operator"
5818           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5819                    (match_operand:SI 1 "s_register_operand" "l"))
5820            (const_int 0)])
5821          (label_ref (match_operand 2 "" ""))
5822          (pc)))]
5823   "TARGET_THUMB"
5824   "*
5825   {
5826   output_asm_insn (\"tst\\t%0, %1\", operands);
5827   switch (get_attr_length (insn))
5828     {
5829     case 4:  return \"b%d3\\t%l2\";
5830     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5831     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5832     }
5833   }"
5834   [(set (attr "far_jump")
5835         (if_then_else
5836             (eq_attr "length" "8")
5837             (const_string "yes")
5838             (const_string "no")))
5839    (set (attr "length") 
5840         (if_then_else
5841             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5842                  (le (minus (match_dup 2) (pc)) (const_int 256)))
5843             (const_int 4)
5844             (if_then_else
5845                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5846                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
5847                 (const_int 6)
5848                 (const_int 8))))]
5849 )
5850   
5851 (define_insn "*andsi3_cbranch"
5852   [(set (pc)
5853         (if_then_else
5854          (match_operator 5 "equality_operator"
5855           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5856                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5857            (const_int 0)])
5858          (label_ref (match_operand 4 "" ""))
5859          (pc)))
5860    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5861         (and:SI (match_dup 2) (match_dup 3)))
5862    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5863   "TARGET_THUMB"
5864   "*
5865   {
5866   if (which_alternative == 0)
5867     output_asm_insn (\"and\\t%0, %3\", operands);
5868   else if (which_alternative == 1)
5869     {
5870       output_asm_insn (\"and\\t%1, %3\", operands);
5871       output_asm_insn (\"mov\\t%0, %1\", operands);
5872     }
5873   else
5874     {
5875       output_asm_insn (\"and\\t%1, %3\", operands);
5876       output_asm_insn (\"str\\t%1, %0\", operands);
5877     }
5878
5879   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5880     {
5881     case 4:  return \"b%d5\\t%l4\";
5882     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5883     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5884     }
5885   }"
5886   [(set (attr "far_jump")
5887         (if_then_else
5888             (ior (and (eq (symbol_ref ("which_alternative"))
5889                           (const_int 0))
5890                       (eq_attr "length" "8"))
5891                  (eq_attr "length" "10"))
5892             (const_string "yes")
5893             (const_string "no")))
5894    (set (attr "length")
5895      (if_then_else
5896        (eq (symbol_ref ("which_alternative"))
5897                        (const_int 0))
5898        (if_then_else
5899          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5900               (le (minus (match_dup 4) (pc)) (const_int 256)))
5901          (const_int 4)
5902          (if_then_else
5903            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5904                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5905            (const_int 6)
5906            (const_int 8)))
5907        (if_then_else
5908          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5909               (le (minus (match_dup 4) (pc)) (const_int 256)))
5910          (const_int 6)
5911          (if_then_else
5912            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5913                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5914            (const_int 8)
5915            (const_int 10)))))]
5916 )
5917
5918 (define_insn "*orrsi3_cbranch_scratch"
5919   [(set (pc)
5920         (if_then_else
5921          (match_operator 4 "equality_operator"
5922           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
5923                    (match_operand:SI 2 "s_register_operand" "l"))
5924            (const_int 0)])
5925          (label_ref (match_operand 3 "" ""))
5926          (pc)))
5927    (clobber (match_scratch:SI 0 "=l"))]
5928   "TARGET_THUMB"
5929   "*
5930   {
5931   output_asm_insn (\"orr\\t%0, %2\", operands);
5932   switch (get_attr_length (insn))
5933     {
5934     case 4:  return \"b%d4\\t%l3\";
5935     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5936     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5937     }
5938   }"
5939   [(set (attr "far_jump")
5940         (if_then_else
5941             (eq_attr "length" "8")
5942             (const_string "yes")
5943             (const_string "no")))
5944    (set (attr "length") 
5945         (if_then_else
5946             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5947                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5948             (const_int 4)
5949             (if_then_else
5950                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5951                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5952                 (const_int 6)
5953                 (const_int 8))))]
5954 )
5955   
5956 (define_insn "*orrsi3_cbranch"
5957   [(set (pc)
5958         (if_then_else
5959          (match_operator 5 "equality_operator"
5960           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5961                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5962            (const_int 0)])
5963          (label_ref (match_operand 4 "" ""))
5964          (pc)))
5965    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5966         (ior:SI (match_dup 2) (match_dup 3)))
5967    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5968   "TARGET_THUMB"
5969   "*
5970   {
5971   if (which_alternative == 0)
5972     output_asm_insn (\"orr\\t%0, %3\", operands);
5973   else if (which_alternative == 1)
5974     {
5975       output_asm_insn (\"orr\\t%1, %3\", operands);
5976       output_asm_insn (\"mov\\t%0, %1\", operands);
5977     }
5978   else
5979     {
5980       output_asm_insn (\"orr\\t%1, %3\", operands);
5981       output_asm_insn (\"str\\t%1, %0\", operands);
5982     }
5983
5984   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5985     {
5986     case 4:  return \"b%d5\\t%l4\";
5987     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5988     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5989     }
5990   }"
5991   [(set (attr "far_jump")
5992         (if_then_else
5993             (ior (and (eq (symbol_ref ("which_alternative"))
5994                           (const_int 0))
5995                       (eq_attr "length" "8"))
5996                  (eq_attr "length" "10"))
5997             (const_string "yes")
5998             (const_string "no")))
5999    (set (attr "length")
6000      (if_then_else
6001        (eq (symbol_ref ("which_alternative"))
6002                        (const_int 0))
6003        (if_then_else
6004          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6005               (le (minus (match_dup 4) (pc)) (const_int 256)))
6006          (const_int 4)
6007          (if_then_else
6008            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6009                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6010            (const_int 6)
6011            (const_int 8)))
6012        (if_then_else
6013          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6014               (le (minus (match_dup 4) (pc)) (const_int 256)))
6015          (const_int 6)
6016          (if_then_else
6017            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6018                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6019            (const_int 8)
6020            (const_int 10)))))]
6021 )
6022
6023 (define_insn "*xorsi3_cbranch_scratch"
6024   [(set (pc)
6025         (if_then_else
6026          (match_operator 4 "equality_operator"
6027           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6028                    (match_operand:SI 2 "s_register_operand" "l"))
6029            (const_int 0)])
6030          (label_ref (match_operand 3 "" ""))
6031          (pc)))
6032    (clobber (match_scratch:SI 0 "=l"))]
6033   "TARGET_THUMB"
6034   "*
6035   {
6036   output_asm_insn (\"eor\\t%0, %2\", operands);
6037   switch (get_attr_length (insn))
6038     {
6039     case 4:  return \"b%d4\\t%l3\";
6040     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6041     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6042     }
6043   }"
6044   [(set (attr "far_jump")
6045         (if_then_else
6046             (eq_attr "length" "8")
6047             (const_string "yes")
6048             (const_string "no")))
6049    (set (attr "length") 
6050         (if_then_else
6051             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6052                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6053             (const_int 4)
6054             (if_then_else
6055                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6056                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6057                 (const_int 6)
6058                 (const_int 8))))]
6059 )
6060   
6061 (define_insn "*xorsi3_cbranch"
6062   [(set (pc)
6063         (if_then_else
6064          (match_operator 5 "equality_operator"
6065           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6066                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6067            (const_int 0)])
6068          (label_ref (match_operand 4 "" ""))
6069          (pc)))
6070    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6071         (xor:SI (match_dup 2) (match_dup 3)))
6072    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6073   "TARGET_THUMB"
6074   "*
6075   {
6076   if (which_alternative == 0)
6077     output_asm_insn (\"eor\\t%0, %3\", operands);
6078   else if (which_alternative == 1)
6079     {
6080       output_asm_insn (\"eor\\t%1, %3\", operands);
6081       output_asm_insn (\"mov\\t%0, %1\", operands);
6082     }
6083   else
6084     {
6085       output_asm_insn (\"eor\\t%1, %3\", operands);
6086       output_asm_insn (\"str\\t%1, %0\", operands);
6087     }
6088
6089   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6090     {
6091     case 4:  return \"b%d5\\t%l4\";
6092     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6093     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6094     }
6095   }"
6096   [(set (attr "far_jump")
6097         (if_then_else
6098             (ior (and (eq (symbol_ref ("which_alternative"))
6099                           (const_int 0))
6100                       (eq_attr "length" "8"))
6101                  (eq_attr "length" "10"))
6102             (const_string "yes")
6103             (const_string "no")))
6104    (set (attr "length")
6105      (if_then_else
6106        (eq (symbol_ref ("which_alternative"))
6107                        (const_int 0))
6108        (if_then_else
6109          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6110               (le (minus (match_dup 4) (pc)) (const_int 256)))
6111          (const_int 4)
6112          (if_then_else
6113            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6114                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6115            (const_int 6)
6116            (const_int 8)))
6117        (if_then_else
6118          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6119               (le (minus (match_dup 4) (pc)) (const_int 256)))
6120          (const_int 6)
6121          (if_then_else
6122            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6123                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6124            (const_int 8)
6125            (const_int 10)))))]
6126 )
6127
6128 (define_insn "*bicsi3_cbranch_scratch"
6129   [(set (pc)
6130         (if_then_else
6131          (match_operator 4 "equality_operator"
6132           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6133                    (match_operand:SI 1 "s_register_operand" "0"))
6134            (const_int 0)])
6135          (label_ref (match_operand 3 "" ""))
6136          (pc)))
6137    (clobber (match_scratch:SI 0 "=l"))]
6138   "TARGET_THUMB"
6139   "*
6140   {
6141   output_asm_insn (\"bic\\t%0, %2\", operands);
6142   switch (get_attr_length (insn))
6143     {
6144     case 4:  return \"b%d4\\t%l3\";
6145     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6146     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6147     }
6148   }"
6149   [(set (attr "far_jump")
6150         (if_then_else
6151             (eq_attr "length" "8")
6152             (const_string "yes")
6153             (const_string "no")))
6154    (set (attr "length") 
6155         (if_then_else
6156             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6157                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6158             (const_int 4)
6159             (if_then_else
6160                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6161                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6162                 (const_int 6)
6163                 (const_int 8))))]
6164 )
6165   
6166 (define_insn "*bicsi3_cbranch"
6167   [(set (pc)
6168         (if_then_else
6169          (match_operator 5 "equality_operator"
6170           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6171                    (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6172            (const_int 0)])
6173          (label_ref (match_operand 4 "" ""))
6174          (pc)))
6175    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6176         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6177    (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6178   "TARGET_THUMB"
6179   "*
6180   {
6181   if (which_alternative == 0)
6182     output_asm_insn (\"bic\\t%0, %3\", operands);
6183   else if (which_alternative <= 2)
6184     {
6185       output_asm_insn (\"bic\\t%1, %3\", operands);
6186       /* It's ok if OP0 is a lo-reg, even though the mov will set the
6187          conditions again, since we're only testing for equality.  */
6188       output_asm_insn (\"mov\\t%0, %1\", operands);
6189     }
6190   else
6191     {
6192       output_asm_insn (\"bic\\t%1, %3\", operands);
6193       output_asm_insn (\"str\\t%1, %0\", operands);
6194     }
6195
6196   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6197     {
6198     case 4:  return \"b%d5\\t%l4\";
6199     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6200     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6201     }
6202   }"
6203   [(set (attr "far_jump")
6204         (if_then_else
6205             (ior (and (eq (symbol_ref ("which_alternative"))
6206                           (const_int 0))
6207                       (eq_attr "length" "8"))
6208                  (eq_attr "length" "10"))
6209             (const_string "yes")
6210             (const_string "no")))
6211    (set (attr "length")
6212      (if_then_else
6213        (eq (symbol_ref ("which_alternative"))
6214                        (const_int 0))
6215        (if_then_else
6216          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6217               (le (minus (match_dup 4) (pc)) (const_int 256)))
6218          (const_int 4)
6219          (if_then_else
6220            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6221                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6222            (const_int 6)
6223            (const_int 8)))
6224        (if_then_else
6225          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6226               (le (minus (match_dup 4) (pc)) (const_int 256)))
6227          (const_int 6)
6228          (if_then_else
6229            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6230                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6231            (const_int 8)
6232            (const_int 10)))))]
6233 )
6234
6235 (define_insn "*cbranchne_decr1"
6236   [(set (pc)
6237         (if_then_else (match_operator 3 "equality_operator"
6238                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6239                         (const_int 0)])
6240                       (label_ref (match_operand 4 "" ""))
6241                       (pc)))
6242    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6243         (plus:SI (match_dup 2) (const_int -1)))
6244    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6245   "TARGET_THUMB"
6246   "*
6247    {
6248      rtx cond[2];
6249      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6250                                 ? GEU : LTU),
6251                                VOIDmode, operands[2], const1_rtx);
6252      cond[1] = operands[4];
6253
6254      if (which_alternative == 0)
6255        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6256      else if (which_alternative == 1)
6257        {
6258          /* We must provide an alternative for a hi reg because reload 
6259             cannot handle output reloads on a jump instruction, but we
6260             can't subtract into that.  Fortunately a mov from lo to hi
6261             does not clobber the condition codes.  */
6262          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6263          output_asm_insn (\"mov\\t%0, %1\", operands);
6264        }
6265      else
6266        {
6267          /* Similarly, but the target is memory.  */
6268          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6269          output_asm_insn (\"str\\t%1, %0\", operands);
6270        }
6271
6272      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6273        {
6274          case 4:
6275            output_asm_insn (\"b%d0\\t%l1\", cond);
6276            return \"\";
6277          case 6:
6278            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6279            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6280          default:
6281            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6282            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6283        }
6284    }
6285   "
6286   [(set (attr "far_jump")
6287         (if_then_else
6288             (ior (and (eq (symbol_ref ("which_alternative"))
6289                           (const_int 0))
6290                       (eq_attr "length" "8"))
6291                  (eq_attr "length" "10"))
6292             (const_string "yes")
6293             (const_string "no")))
6294    (set_attr_alternative "length"
6295       [
6296        ;; Alternative 0
6297        (if_then_else
6298          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6299               (le (minus (match_dup 4) (pc)) (const_int 256)))
6300          (const_int 4)
6301          (if_then_else
6302            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6303                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6304            (const_int 6)
6305            (const_int 8)))
6306        ;; Alternative 1
6307        (if_then_else
6308          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6309               (le (minus (match_dup 4) (pc)) (const_int 256)))
6310          (const_int 6)
6311          (if_then_else
6312            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6313                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6314            (const_int 8)
6315            (const_int 10)))
6316        ;; Alternative 2
6317        (if_then_else
6318          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6319               (le (minus (match_dup 4) (pc)) (const_int 256)))
6320          (const_int 6)
6321          (if_then_else
6322            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6323                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6324            (const_int 8)
6325            (const_int 10)))
6326        ;; Alternative 3
6327        (if_then_else
6328          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6329               (le (minus (match_dup 4) (pc)) (const_int 256)))
6330          (const_int 6)
6331          (if_then_else
6332            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6333                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6334            (const_int 8)
6335            (const_int 10)))])]
6336 )
6337
6338 (define_insn "*addsi3_cbranch"
6339   [(set (pc)
6340         (if_then_else
6341          (match_operator 4 "comparison_operator"
6342           [(plus:SI
6343             (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6344             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6345            (const_int 0)])
6346          (label_ref (match_operand 5 "" ""))
6347          (pc)))
6348    (set
6349     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6350     (plus:SI (match_dup 2) (match_dup 3)))
6351    (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6352   "TARGET_THUMB
6353    && (GET_CODE (operands[4]) == EQ
6354        || GET_CODE (operands[4]) == NE
6355        || GET_CODE (operands[4]) == GE
6356        || GET_CODE (operands[4]) == LT)"
6357   "*
6358    {
6359      rtx cond[3];
6360
6361      
6362      cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6363      cond[1] = operands[2];
6364      cond[2] = operands[3];
6365
6366      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6367        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6368      else
6369        output_asm_insn (\"add\\t%0, %1, %2\", cond);
6370
6371      if (which_alternative >= 3
6372          && which_alternative < 4)
6373        output_asm_insn (\"mov\\t%0, %1\", operands);
6374      else if (which_alternative >= 4)
6375        output_asm_insn (\"str\\t%1, %0\", operands);
6376
6377      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6378        {
6379          case 4:
6380            return \"b%d4\\t%l5\";
6381          case 6:
6382            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6383          default:
6384            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6385        }
6386    }
6387   "
6388   [(set (attr "far_jump")
6389         (if_then_else
6390             (ior (and (lt (symbol_ref ("which_alternative"))
6391                           (const_int 3))
6392                       (eq_attr "length" "8"))
6393                  (eq_attr "length" "10"))
6394             (const_string "yes")
6395             (const_string "no")))
6396    (set (attr "length")
6397      (if_then_else
6398        (lt (symbol_ref ("which_alternative"))
6399                        (const_int 3))
6400        (if_then_else
6401          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6402               (le (minus (match_dup 5) (pc)) (const_int 256)))
6403          (const_int 4)
6404          (if_then_else
6405            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6406                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6407            (const_int 6)
6408            (const_int 8)))
6409        (if_then_else
6410          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6411               (le (minus (match_dup 5) (pc)) (const_int 256)))
6412          (const_int 6)
6413          (if_then_else
6414            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6415                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6416            (const_int 8)
6417            (const_int 10)))))]
6418 )
6419
6420 (define_insn "*addsi3_cbranch_scratch"
6421   [(set (pc)
6422         (if_then_else
6423          (match_operator 3 "comparison_operator"
6424           [(plus:SI
6425             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6426             (match_operand:SI 2 "reg_or_int_operand" "J,l,I,L"))
6427            (const_int 0)])
6428          (label_ref (match_operand 4 "" ""))
6429          (pc)))
6430    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6431   "TARGET_THUMB
6432    && (GET_CODE (operands[3]) == EQ
6433        || GET_CODE (operands[3]) == NE
6434        || GET_CODE (operands[3]) == GE
6435        || GET_CODE (operands[3]) == LT)"
6436   "*
6437    {
6438      switch (which_alternative)
6439        {
6440        case 0:
6441          output_asm_insn (\"cmp\t%1, #%n2\", operands);
6442          break;
6443        case 1:
6444          output_asm_insn (\"cmn\t%1, %2\", operands);
6445          break;
6446        case 3:
6447          output_asm_insn (\"add\t%0, %1, %2\", operands);
6448          break;
6449        case 4:
6450          output_asm_insn (\"add\t%0, %0, %2\", operands);
6451          break;
6452        }
6453
6454      switch (get_attr_length (insn))
6455        {
6456          case 4:
6457            return \"b%d3\\t%l4\";
6458          case 6:
6459            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6460          default:
6461            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6462        }
6463    }
6464   "
6465   [(set (attr "far_jump")
6466         (if_then_else
6467             (eq_attr "length" "8")
6468             (const_string "yes")
6469             (const_string "no")))
6470    (set (attr "length")
6471        (if_then_else
6472          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6473               (le (minus (match_dup 4) (pc)) (const_int 256)))
6474          (const_int 4)
6475          (if_then_else
6476            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6477                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6478            (const_int 6)
6479            (const_int 8))))]
6480 )
6481
6482 (define_insn "*subsi3_cbranch"
6483   [(set (pc)
6484         (if_then_else
6485          (match_operator 4 "comparison_operator"
6486           [(minus:SI
6487             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6488             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6489            (const_int 0)])
6490          (label_ref (match_operand 5 "" ""))
6491          (pc)))
6492    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6493         (minus:SI (match_dup 2) (match_dup 3)))
6494    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6495   "TARGET_THUMB
6496    && (GET_CODE (operands[4]) == EQ
6497        || GET_CODE (operands[4]) == NE
6498        || GET_CODE (operands[4]) == GE
6499        || GET_CODE (operands[4]) == LT)"
6500   "*
6501    {
6502      if (which_alternative == 0)
6503        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6504      else if (which_alternative == 1)
6505        {
6506          /* We must provide an alternative for a hi reg because reload 
6507             cannot handle output reloads on a jump instruction, but we
6508             can't subtract into that.  Fortunately a mov from lo to hi
6509             does not clobber the condition codes.  */
6510          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6511          output_asm_insn (\"mov\\t%0, %1\", operands);
6512        }
6513      else
6514        {
6515          /* Similarly, but the target is memory.  */
6516          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6517          output_asm_insn (\"str\\t%1, %0\", operands);
6518        }
6519
6520      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6521        {
6522          case 4:
6523            return \"b%d4\\t%l5\";
6524          case 6:
6525            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6526          default:
6527            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6528        }
6529    }
6530   "
6531   [(set (attr "far_jump")
6532         (if_then_else
6533             (ior (and (eq (symbol_ref ("which_alternative"))
6534                           (const_int 0))
6535                       (eq_attr "length" "8"))
6536                  (eq_attr "length" "10"))
6537             (const_string "yes")
6538             (const_string "no")))
6539    (set (attr "length")
6540      (if_then_else
6541        (eq (symbol_ref ("which_alternative"))
6542                        (const_int 0))
6543        (if_then_else
6544          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6545               (le (minus (match_dup 5) (pc)) (const_int 256)))
6546          (const_int 4)
6547          (if_then_else
6548            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6549                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6550            (const_int 6)
6551            (const_int 8)))
6552        (if_then_else
6553          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6554               (le (minus (match_dup 5) (pc)) (const_int 256)))
6555          (const_int 6)
6556          (if_then_else
6557            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6558                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6559            (const_int 8)
6560            (const_int 10)))))]
6561 )
6562
6563 (define_insn "*subsi3_cbranch_scratch"
6564   [(set (pc)
6565         (if_then_else
6566          (match_operator 0 "arm_comparison_operator"
6567           [(minus:SI (match_operand:SI 1 "register_operand" "l")
6568                      (match_operand:SI 2 "nonmemory_operand" "l"))
6569            (const_int 0)])
6570          (label_ref (match_operand 3 "" ""))
6571          (pc)))]
6572   "TARGET_THUMB
6573    && (GET_CODE (operands[0]) == EQ
6574        || GET_CODE (operands[0]) == NE
6575        || GET_CODE (operands[0]) == GE
6576        || GET_CODE (operands[0]) == LT)"
6577   "*
6578   output_asm_insn (\"cmp\\t%1, %2\", operands);
6579   switch (get_attr_length (insn))
6580     {
6581     case 4:  return \"b%d0\\t%l3\";
6582     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6583     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6584     }
6585   "
6586   [(set (attr "far_jump")
6587         (if_then_else
6588             (eq_attr "length" "8")
6589             (const_string "yes")
6590             (const_string "no")))
6591    (set (attr "length") 
6592         (if_then_else
6593             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6594                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6595             (const_int 4)
6596             (if_then_else
6597                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6598                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6599                 (const_int 6)
6600                 (const_int 8))))]
6601 )
6602
6603 ;; Comparison and test insns
6604
6605 (define_expand "cmpsi"
6606   [(match_operand:SI 0 "s_register_operand" "")
6607    (match_operand:SI 1 "arm_add_operand" "")]
6608   "TARGET_ARM"
6609   "{
6610     arm_compare_op0 = operands[0];
6611     arm_compare_op1 = operands[1];
6612     DONE;
6613   }"
6614 )
6615
6616 (define_expand "cmpsf"
6617   [(match_operand:SF 0 "s_register_operand" "")
6618    (match_operand:SF 1 "arm_float_compare_operand" "")]
6619   "TARGET_ARM && TARGET_HARD_FLOAT"
6620   "
6621   arm_compare_op0 = operands[0];
6622   arm_compare_op1 = operands[1];
6623   DONE;
6624   "
6625 )
6626
6627 (define_expand "cmpdf"
6628   [(match_operand:DF 0 "s_register_operand" "")
6629    (match_operand:DF 1 "arm_float_compare_operand" "")]
6630   "TARGET_ARM && TARGET_HARD_FLOAT"
6631   "
6632   arm_compare_op0 = operands[0];
6633   arm_compare_op1 = operands[1];
6634   DONE;
6635   "
6636 )
6637
6638 (define_insn "*arm_cmpsi_insn"
6639   [(set (reg:CC CC_REGNUM)
6640         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6641                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
6642   "TARGET_ARM"
6643   "@
6644    cmp%?\\t%0, %1
6645    cmn%?\\t%0, #%n1"
6646   [(set_attr "conds" "set")]
6647 )
6648
6649 (define_insn "*cmpsi_shiftsi"
6650   [(set (reg:CC CC_REGNUM)
6651         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
6652                     (match_operator:SI  3 "shift_operator"
6653                      [(match_operand:SI 1 "s_register_operand" "r")
6654                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
6655   "TARGET_ARM"
6656   "cmp%?\\t%0, %1%S3"
6657   [(set_attr "conds" "set")
6658    (set_attr "shift" "1")
6659    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6660                       (const_string "alu_shift")
6661                       (const_string "alu_shift_reg")))]
6662 )
6663
6664 (define_insn "*cmpsi_shiftsi_swp"
6665   [(set (reg:CC_SWP CC_REGNUM)
6666         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6667                          [(match_operand:SI 1 "s_register_operand" "r")
6668                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
6669                         (match_operand:SI 0 "s_register_operand" "r")))]
6670   "TARGET_ARM"
6671   "cmp%?\\t%0, %1%S3"
6672   [(set_attr "conds" "set")
6673    (set_attr "shift" "1")
6674    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6675                       (const_string "alu_shift")
6676                       (const_string "alu_shift_reg")))]
6677 )
6678
6679 (define_insn "*cmpsi_neg_shiftsi"
6680   [(set (reg:CC CC_REGNUM)
6681         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6682                     (neg:SI (match_operator:SI 3 "shift_operator"
6683                              [(match_operand:SI 1 "s_register_operand" "r")
6684                               (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
6685   "TARGET_ARM"
6686   "cmn%?\\t%0, %1%S3"
6687   [(set_attr "conds" "set")
6688    (set_attr "shift" "1")
6689    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6690                       (const_string "alu_shift")
6691                       (const_string "alu_shift_reg")))]
6692 )
6693
6694 ;; Cirrus SF compare instruction
6695 (define_insn "*cirrus_cmpsf"
6696   [(set (reg:CCFP CC_REGNUM)
6697         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6698                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
6699   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6700   "cfcmps%?\\tr15, %V0, %V1"
6701   [(set_attr "type"   "mav_farith")
6702    (set_attr "cirrus" "compare")]
6703 )
6704
6705 ;; Cirrus DF compare instruction
6706 (define_insn "*cirrus_cmpdf"
6707   [(set (reg:CCFP CC_REGNUM)
6708         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6709                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
6710   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6711   "cfcmpd%?\\tr15, %V0, %V1"
6712   [(set_attr "type"   "mav_farith")
6713    (set_attr "cirrus" "compare")]
6714 )
6715
6716 ;; Cirrus DI compare instruction
6717 (define_expand "cmpdi"
6718   [(match_operand:DI 0 "cirrus_fp_register" "")
6719    (match_operand:DI 1 "cirrus_fp_register" "")]
6720   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6721   "{
6722      arm_compare_op0 = operands[0];
6723      arm_compare_op1 = operands[1];
6724      DONE;
6725    }")
6726
6727 (define_insn "*cirrus_cmpdi"
6728   [(set (reg:CC CC_REGNUM)
6729         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6730                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
6731   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6732   "cfcmp64%?\\tr15, %V0, %V1"
6733   [(set_attr "type"   "mav_farith")
6734    (set_attr "cirrus" "compare")]
6735 )
6736
6737 ; This insn allows redundant compares to be removed by cse, nothing should
6738 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6739 ; is deleted later on. The match_dup will match the mode here, so that
6740 ; mode changes of the condition codes aren't lost by this even though we don't
6741 ; specify what they are.
6742
6743 (define_insn "*deleted_compare"
6744   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6745   "TARGET_ARM"
6746   "\\t%@ deleted compare"
6747   [(set_attr "conds" "set")
6748    (set_attr "length" "0")]
6749 )
6750
6751 \f
6752 ;; Conditional branch insns
6753
6754 (define_expand "beq"
6755   [(set (pc)
6756         (if_then_else (eq (match_dup 1) (const_int 0))
6757                       (label_ref (match_operand 0 "" ""))
6758                       (pc)))]
6759   "TARGET_ARM"
6760   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6761 )
6762
6763 (define_expand "bne"
6764   [(set (pc)
6765         (if_then_else (ne (match_dup 1) (const_int 0))
6766                       (label_ref (match_operand 0 "" ""))
6767                       (pc)))]
6768   "TARGET_ARM"
6769   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6770 )
6771
6772 (define_expand "bgt"
6773   [(set (pc)
6774         (if_then_else (gt (match_dup 1) (const_int 0))
6775                       (label_ref (match_operand 0 "" ""))
6776                       (pc)))]
6777   "TARGET_ARM"
6778   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6779 )
6780
6781 (define_expand "ble"
6782   [(set (pc)
6783         (if_then_else (le (match_dup 1) (const_int 0))
6784                       (label_ref (match_operand 0 "" ""))
6785                       (pc)))]
6786   "TARGET_ARM"
6787   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6788 )
6789
6790 (define_expand "bge"
6791   [(set (pc)
6792         (if_then_else (ge (match_dup 1) (const_int 0))
6793                       (label_ref (match_operand 0 "" ""))
6794                       (pc)))]
6795   "TARGET_ARM"
6796   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6797 )
6798
6799 (define_expand "blt"
6800   [(set (pc)
6801         (if_then_else (lt (match_dup 1) (const_int 0))
6802                       (label_ref (match_operand 0 "" ""))
6803                       (pc)))]
6804   "TARGET_ARM"
6805   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6806 )
6807
6808 (define_expand "bgtu"
6809   [(set (pc)
6810         (if_then_else (gtu (match_dup 1) (const_int 0))
6811                       (label_ref (match_operand 0 "" ""))
6812                       (pc)))]
6813   "TARGET_ARM"
6814   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6815 )
6816
6817 (define_expand "bleu"
6818   [(set (pc)
6819         (if_then_else (leu (match_dup 1) (const_int 0))
6820                       (label_ref (match_operand 0 "" ""))
6821                       (pc)))]
6822   "TARGET_ARM"
6823   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6824 )
6825
6826 (define_expand "bgeu"
6827   [(set (pc)
6828         (if_then_else (geu (match_dup 1) (const_int 0))
6829                       (label_ref (match_operand 0 "" ""))
6830                       (pc)))]
6831   "TARGET_ARM"
6832   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6833 )
6834
6835 (define_expand "bltu"
6836   [(set (pc)
6837         (if_then_else (ltu (match_dup 1) (const_int 0))
6838                       (label_ref (match_operand 0 "" ""))
6839                       (pc)))]
6840   "TARGET_ARM"
6841   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6842 )
6843
6844 (define_expand "bunordered"
6845   [(set (pc)
6846         (if_then_else (unordered (match_dup 1) (const_int 0))
6847                       (label_ref (match_operand 0 "" ""))
6848                       (pc)))]
6849   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6850   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6851                                       arm_compare_op1);"
6852 )
6853
6854 (define_expand "bordered"
6855   [(set (pc)
6856         (if_then_else (ordered (match_dup 1) (const_int 0))
6857                       (label_ref (match_operand 0 "" ""))
6858                       (pc)))]
6859   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6860   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6861                                       arm_compare_op1);"
6862 )
6863
6864 (define_expand "bungt"
6865   [(set (pc)
6866         (if_then_else (ungt (match_dup 1) (const_int 0))
6867                       (label_ref (match_operand 0 "" ""))
6868                       (pc)))]
6869   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6870   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
6871 )
6872
6873 (define_expand "bunlt"
6874   [(set (pc)
6875         (if_then_else (unlt (match_dup 1) (const_int 0))
6876                       (label_ref (match_operand 0 "" ""))
6877                       (pc)))]
6878   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6879   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
6880 )
6881
6882 (define_expand "bunge"
6883   [(set (pc)
6884         (if_then_else (unge (match_dup 1) (const_int 0))
6885                       (label_ref (match_operand 0 "" ""))
6886                       (pc)))]
6887   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6888   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
6889 )
6890
6891 (define_expand "bunle"
6892   [(set (pc)
6893         (if_then_else (unle (match_dup 1) (const_int 0))
6894                       (label_ref (match_operand 0 "" ""))
6895                       (pc)))]
6896   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6897   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
6898 )
6899
6900 ;; The following two patterns need two branch instructions, since there is
6901 ;; no single instruction that will handle all cases.
6902 (define_expand "buneq"
6903   [(set (pc)
6904         (if_then_else (uneq (match_dup 1) (const_int 0))
6905                       (label_ref (match_operand 0 "" ""))
6906                       (pc)))]
6907   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6908   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6909 )
6910
6911 (define_expand "bltgt"
6912   [(set (pc)
6913         (if_then_else (ltgt (match_dup 1) (const_int 0))
6914                       (label_ref (match_operand 0 "" ""))
6915                       (pc)))]
6916   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6917   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6918 )
6919
6920 ;;
6921 ;; Patterns to match conditional branch insns.
6922 ;;
6923
6924 ; Special pattern to match UNEQ.
6925 (define_insn "*arm_buneq"
6926   [(set (pc)
6927         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6928                       (label_ref (match_operand 0 "" ""))
6929                       (pc)))]
6930   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6931   "*
6932   if (arm_ccfsm_state != 0)
6933     abort ();
6934
6935   return \"bvs\\t%l0\;beq\\t%l0\";
6936   "
6937   [(set_attr "conds" "jump_clob")
6938    (set_attr "length" "8")]
6939 )
6940
6941 ; Special pattern to match LTGT.
6942 (define_insn "*arm_bltgt"
6943   [(set (pc)
6944         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6945                       (label_ref (match_operand 0 "" ""))
6946                       (pc)))]
6947   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6948   "*
6949   if (arm_ccfsm_state != 0)
6950     abort ();
6951
6952   return \"bmi\\t%l0\;bgt\\t%l0\";
6953   "
6954   [(set_attr "conds" "jump_clob")
6955    (set_attr "length" "8")]
6956 )
6957
6958 (define_insn "*arm_cond_branch"
6959   [(set (pc)
6960         (if_then_else (match_operator 1 "arm_comparison_operator"
6961                        [(match_operand 2 "cc_register" "") (const_int 0)])
6962                       (label_ref (match_operand 0 "" ""))
6963                       (pc)))]
6964   "TARGET_ARM"
6965   "*
6966   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6967     {
6968       arm_ccfsm_state += 2;
6969       return \"\";
6970     }
6971   return \"b%d1\\t%l0\";
6972   "
6973   [(set_attr "conds" "use")
6974    (set_attr "type" "branch")]
6975 )
6976
6977 ; Special pattern to match reversed UNEQ.
6978 (define_insn "*arm_buneq_reversed"
6979   [(set (pc)
6980         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6981                       (pc)
6982                       (label_ref (match_operand 0 "" ""))))]
6983   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6984   "*
6985   if (arm_ccfsm_state != 0)
6986     abort ();
6987
6988   return \"bmi\\t%l0\;bgt\\t%l0\";
6989   "
6990   [(set_attr "conds" "jump_clob")
6991    (set_attr "length" "8")]
6992 )
6993
6994 ; Special pattern to match reversed LTGT.
6995 (define_insn "*arm_bltgt_reversed"
6996   [(set (pc)
6997         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6998                       (pc)
6999                       (label_ref (match_operand 0 "" ""))))]
7000   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7001   "*
7002   if (arm_ccfsm_state != 0)
7003     abort ();
7004
7005   return \"bvs\\t%l0\;beq\\t%l0\";
7006   "
7007   [(set_attr "conds" "jump_clob")
7008    (set_attr "length" "8")]
7009 )
7010
7011 (define_insn "*arm_cond_branch_reversed"
7012   [(set (pc)
7013         (if_then_else (match_operator 1 "arm_comparison_operator"
7014                        [(match_operand 2 "cc_register" "") (const_int 0)])
7015                       (pc)
7016                       (label_ref (match_operand 0 "" ""))))]
7017   "TARGET_ARM"
7018   "*
7019   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7020     {
7021       arm_ccfsm_state += 2;
7022       return \"\";
7023     }
7024   return \"b%D1\\t%l0\";
7025   "
7026   [(set_attr "conds" "use")
7027    (set_attr "type" "branch")]
7028 )
7029
7030 \f
7031
7032 ; scc insns
7033
7034 (define_expand "seq"
7035   [(set (match_operand:SI 0 "s_register_operand" "")
7036         (eq:SI (match_dup 1) (const_int 0)))]
7037   "TARGET_ARM"
7038   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7039 )
7040
7041 (define_expand "sne"
7042   [(set (match_operand:SI 0 "s_register_operand" "")
7043         (ne:SI (match_dup 1) (const_int 0)))]
7044   "TARGET_ARM"
7045   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7046 )
7047
7048 (define_expand "sgt"
7049   [(set (match_operand:SI 0 "s_register_operand" "")
7050         (gt:SI (match_dup 1) (const_int 0)))]
7051   "TARGET_ARM"
7052   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7053 )
7054
7055 (define_expand "sle"
7056   [(set (match_operand:SI 0 "s_register_operand" "")
7057         (le:SI (match_dup 1) (const_int 0)))]
7058   "TARGET_ARM"
7059   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7060 )
7061
7062 (define_expand "sge"
7063   [(set (match_operand:SI 0 "s_register_operand" "")
7064         (ge:SI (match_dup 1) (const_int 0)))]
7065   "TARGET_ARM"
7066   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7067 )
7068
7069 (define_expand "slt"
7070   [(set (match_operand:SI 0 "s_register_operand" "")
7071         (lt:SI (match_dup 1) (const_int 0)))]
7072   "TARGET_ARM"
7073   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7074 )
7075
7076 (define_expand "sgtu"
7077   [(set (match_operand:SI 0 "s_register_operand" "")
7078         (gtu:SI (match_dup 1) (const_int 0)))]
7079   "TARGET_ARM"
7080   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7081 )
7082
7083 (define_expand "sleu"
7084   [(set (match_operand:SI 0 "s_register_operand" "")
7085         (leu:SI (match_dup 1) (const_int 0)))]
7086   "TARGET_ARM"
7087   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7088 )
7089
7090 (define_expand "sgeu"
7091   [(set (match_operand:SI 0 "s_register_operand" "")
7092         (geu:SI (match_dup 1) (const_int 0)))]
7093   "TARGET_ARM"
7094   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7095 )
7096
7097 (define_expand "sltu"
7098   [(set (match_operand:SI 0 "s_register_operand" "")
7099         (ltu:SI (match_dup 1) (const_int 0)))]
7100   "TARGET_ARM"
7101   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7102 )
7103
7104 (define_expand "sunordered"
7105   [(set (match_operand:SI 0 "s_register_operand" "")
7106         (unordered:SI (match_dup 1) (const_int 0)))]
7107   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7108   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7109                                       arm_compare_op1);"
7110 )
7111
7112 (define_expand "sordered"
7113   [(set (match_operand:SI 0 "s_register_operand" "")
7114         (ordered:SI (match_dup 1) (const_int 0)))]
7115   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7116   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7117                                       arm_compare_op1);"
7118 )
7119
7120 (define_expand "sungt"
7121   [(set (match_operand:SI 0 "s_register_operand" "")
7122         (ungt:SI (match_dup 1) (const_int 0)))]
7123   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7124   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7125                                       arm_compare_op1);"
7126 )
7127
7128 (define_expand "sunge"
7129   [(set (match_operand:SI 0 "s_register_operand" "")
7130         (unge:SI (match_dup 1) (const_int 0)))]
7131   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7132   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7133                                       arm_compare_op1);"
7134 )
7135
7136 (define_expand "sunlt"
7137   [(set (match_operand:SI 0 "s_register_operand" "")
7138         (unlt:SI (match_dup 1) (const_int 0)))]
7139   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7140   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7141                                       arm_compare_op1);"
7142 )
7143
7144 (define_expand "sunle"
7145   [(set (match_operand:SI 0 "s_register_operand" "")
7146         (unle:SI (match_dup 1) (const_int 0)))]
7147   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7148   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7149                                       arm_compare_op1);"
7150 )
7151
7152 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7153 ;;; simple ARM instructions. 
7154 ;
7155 ; (define_expand "suneq"
7156 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7157 ;       (uneq:SI (match_dup 1) (const_int 0)))]
7158 ;   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7159 ;   "abort ();"
7160 ; )
7161 ;
7162 ; (define_expand "sltgt"
7163 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7164 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
7165 ;   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7166 ;   "abort ();"
7167 ; )
7168
7169 (define_insn "*mov_scc"
7170   [(set (match_operand:SI 0 "s_register_operand" "=r")
7171         (match_operator:SI 1 "arm_comparison_operator"
7172          [(match_operand 2 "cc_register" "") (const_int 0)]))]
7173   "TARGET_ARM"
7174   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7175   [(set_attr "conds" "use")
7176    (set_attr "length" "8")]
7177 )
7178
7179 (define_insn "*mov_negscc"
7180   [(set (match_operand:SI 0 "s_register_operand" "=r")
7181         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7182                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7183   "TARGET_ARM"
7184   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7185   [(set_attr "conds" "use")
7186    (set_attr "length" "8")]
7187 )
7188
7189 (define_insn "*mov_notscc"
7190   [(set (match_operand:SI 0 "s_register_operand" "=r")
7191         (not:SI (match_operator:SI 1 "arm_comparison_operator"
7192                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7193   "TARGET_ARM"
7194   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7195   [(set_attr "conds" "use")
7196    (set_attr "length" "8")]
7197 )
7198
7199 \f
7200 ;; Conditional move insns
7201
7202 (define_expand "movsicc"
7203   [(set (match_operand:SI 0 "s_register_operand" "")
7204         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7205                          (match_operand:SI 2 "arm_not_operand" "")
7206                          (match_operand:SI 3 "arm_not_operand" "")))]
7207   "TARGET_ARM"
7208   "
7209   {
7210     enum rtx_code code = GET_CODE (operands[1]);
7211     rtx ccreg;
7212
7213     if (code == UNEQ || code == LTGT)
7214       FAIL;
7215
7216     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7217     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7218   }"
7219 )
7220
7221 (define_expand "movsfcc"
7222   [(set (match_operand:SF 0 "s_register_operand" "")
7223         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7224                          (match_operand:SF 2 "s_register_operand" "")
7225                          (match_operand:SF 3 "nonmemory_operand" "")))]
7226   "TARGET_ARM"
7227   "
7228   {
7229     enum rtx_code code = GET_CODE (operands[1]);
7230     rtx ccreg;
7231
7232     if (code == UNEQ || code == LTGT)
7233       FAIL;
7234
7235     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
7236        Otherwise, ensure it is a valid FP add operand */
7237     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7238         || (!arm_float_add_operand (operands[3], SFmode)))
7239       operands[3] = force_reg (SFmode, operands[3]);
7240
7241     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7242     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7243   }"
7244 )
7245
7246 (define_expand "movdfcc"
7247   [(set (match_operand:DF 0 "s_register_operand" "")
7248         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7249                          (match_operand:DF 2 "s_register_operand" "")
7250                          (match_operand:DF 3 "arm_float_add_operand" "")))]
7251   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7252   "
7253   {
7254     enum rtx_code code = GET_CODE (operands[1]);
7255     rtx ccreg;
7256
7257     if (code == UNEQ || code == LTGT)
7258       FAIL;
7259
7260     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7261     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7262   }"
7263 )
7264
7265 (define_insn "*movsicc_insn"
7266   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7267         (if_then_else:SI
7268          (match_operator 3 "arm_comparison_operator"
7269           [(match_operand 4 "cc_register" "") (const_int 0)])
7270          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7271          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7272   "TARGET_ARM"
7273   "@
7274    mov%D3\\t%0, %2
7275    mvn%D3\\t%0, #%B2
7276    mov%d3\\t%0, %1
7277    mvn%d3\\t%0, #%B1
7278    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7279    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7280    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7281    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7282   [(set_attr "length" "4,4,4,4,8,8,8,8")
7283    (set_attr "conds" "use")]
7284 )
7285
7286 (define_insn "*movsfcc_soft_insn"
7287   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7288         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7289                           [(match_operand 4 "cc_register" "") (const_int 0)])
7290                          (match_operand:SF 1 "s_register_operand" "0,r")
7291                          (match_operand:SF 2 "s_register_operand" "r,0")))]
7292   "TARGET_ARM && TARGET_SOFT_FLOAT"
7293   "@
7294    mov%D3\\t%0, %2
7295    mov%d3\\t%0, %1"
7296   [(set_attr "conds" "use")]
7297 )
7298
7299 \f
7300 ;; Jump and linkage insns
7301
7302 (define_expand "jump"
7303   [(set (pc)
7304         (label_ref (match_operand 0 "" "")))]
7305   "TARGET_EITHER"
7306   ""
7307 )
7308
7309 (define_insn "*arm_jump"
7310   [(set (pc)
7311         (label_ref (match_operand 0 "" "")))]
7312   "TARGET_ARM"
7313   "*
7314   {
7315     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7316       {
7317         arm_ccfsm_state += 2;
7318         return \"\";
7319       }
7320     return \"b%?\\t%l0\";
7321   }
7322   "
7323   [(set_attr "predicable" "yes")]
7324 )
7325
7326 (define_insn "*thumb_jump"
7327   [(set (pc)
7328         (label_ref (match_operand 0 "" "")))]
7329   "TARGET_THUMB"
7330   "*
7331   if (get_attr_length (insn) == 2)
7332     return \"b\\t%l0\";
7333   return \"bl\\t%l0\\t%@ far jump\";
7334   "
7335   [(set (attr "far_jump")
7336         (if_then_else
7337             (eq_attr "length" "4")
7338             (const_string "yes")
7339             (const_string "no")))
7340    (set (attr "length") 
7341         (if_then_else
7342             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7343                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
7344             (const_int 2)
7345             (const_int 4)))]
7346 )
7347
7348 (define_expand "call"
7349   [(parallel [(call (match_operand 0 "memory_operand" "")
7350                     (match_operand 1 "general_operand" ""))
7351               (use (match_operand 2 "" ""))
7352               (clobber (reg:SI LR_REGNUM))])]
7353   "TARGET_EITHER"
7354   "
7355   {
7356     rtx callee;
7357     
7358     /* In an untyped call, we can get NULL for operand 2.  */
7359     if (operands[2] == NULL_RTX)
7360       operands[2] = const0_rtx;
7361       
7362     /* This is to decide if we should generate indirect calls by loading the
7363        32 bit address of the callee into a register before performing the
7364        branch and link.  operand[2] encodes the long_call/short_call
7365        attribute of the function being called.  This attribute is set whenever
7366        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7367        is used, and the short_call attribute can also be set if function is
7368        declared as static or if it has already been defined in the current
7369        compilation unit.  See arm.c and arm.h for info about this.  The third
7370        parameter to arm_is_longcall_p is used to tell it which pattern
7371        invoked it.  */
7372     callee  = XEXP (operands[0], 0);
7373     
7374     if (GET_CODE (callee) != REG
7375        && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7376       XEXP (operands[0], 0) = force_reg (Pmode, callee);
7377   }"
7378 )
7379
7380 (define_insn "*call_reg_armv5"
7381   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7382          (match_operand 1 "" ""))
7383    (use (match_operand 2 "" ""))
7384    (clobber (reg:SI LR_REGNUM))]
7385   "TARGET_ARM && arm_arch5"
7386   "blx%?\\t%0"
7387   [(set_attr "type" "call")]
7388 )
7389
7390 (define_insn "*call_reg_arm"
7391   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7392          (match_operand 1 "" ""))
7393    (use (match_operand 2 "" ""))
7394    (clobber (reg:SI LR_REGNUM))]
7395   "TARGET_ARM && !arm_arch5"
7396   "*
7397   return output_call (operands);
7398   "
7399   ;; length is worst case, normally it is only two
7400   [(set_attr "length" "12")
7401    (set_attr "type" "call")]
7402 )
7403
7404 (define_insn "*call_mem"
7405   [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7406          (match_operand 1 "" ""))
7407    (use (match_operand 2 "" ""))
7408    (clobber (reg:SI LR_REGNUM))]
7409   "TARGET_ARM"
7410   "*
7411   return output_call_mem (operands);
7412   "
7413   [(set_attr "length" "12")
7414    (set_attr "type" "call")]
7415 )
7416
7417 (define_insn "*call_reg_thumb_v5"
7418   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7419          (match_operand 1 "" ""))
7420    (use (match_operand 2 "" ""))
7421    (clobber (reg:SI LR_REGNUM))]
7422   "TARGET_THUMB && arm_arch5"
7423   "blx\\t%0"
7424   [(set_attr "length" "2")
7425    (set_attr "type" "call")]
7426 )
7427
7428 (define_insn "*call_reg_thumb"
7429   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7430          (match_operand 1 "" ""))
7431    (use (match_operand 2 "" ""))
7432    (clobber (reg:SI LR_REGNUM))]
7433   "TARGET_THUMB && !arm_arch5"
7434   "*
7435   {
7436     if (TARGET_CALLER_INTERWORKING)
7437       return \"bl\\t%__interwork_call_via_%0\";
7438     else
7439       return \"bl\\t%__call_via_%0\";
7440   }"
7441   [(set_attr "type" "call")]
7442 )
7443
7444 (define_expand "call_value"
7445   [(parallel [(set (match_operand       0 "" "")
7446                    (call (match_operand 1 "memory_operand" "")
7447                          (match_operand 2 "general_operand" "")))
7448               (use (match_operand 3 "" ""))
7449               (clobber (reg:SI LR_REGNUM))])]
7450   "TARGET_EITHER"
7451   "
7452   {
7453     rtx callee = XEXP (operands[1], 0);
7454     
7455     /* In an untyped call, we can get NULL for operand 2.  */
7456     if (operands[3] == 0)
7457       operands[3] = const0_rtx;
7458       
7459     /* See the comment in define_expand \"call\".  */
7460     if (GET_CODE (callee) != REG
7461         && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7462       XEXP (operands[1], 0) = force_reg (Pmode, callee);
7463   }"
7464 )
7465
7466 (define_insn "*call_value_reg_armv5"
7467   [(set (match_operand 0 "" "")
7468         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7469               (match_operand 2 "" "")))
7470    (use (match_operand 3 "" ""))
7471    (clobber (reg:SI LR_REGNUM))]
7472   "TARGET_ARM && arm_arch5"
7473   "blx%?\\t%1"
7474   [(set_attr "type" "call")]
7475 )
7476
7477 (define_insn "*call_value_reg_arm"
7478   [(set (match_operand 0 "" "")
7479         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7480               (match_operand 2 "" "")))
7481    (use (match_operand 3 "" ""))
7482    (clobber (reg:SI LR_REGNUM))]
7483   "TARGET_ARM && !arm_arch5"
7484   "*
7485   return output_call (&operands[1]);
7486   "
7487   [(set_attr "length" "12")
7488    (set_attr "type" "call")]
7489 )
7490
7491 (define_insn "*call_value_mem"
7492   [(set (match_operand 0 "" "")
7493         (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7494               (match_operand 2 "" "")))
7495    (use (match_operand 3 "" ""))
7496    (clobber (reg:SI LR_REGNUM))]
7497   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7498   "*
7499   return output_call_mem (&operands[1]);
7500   "
7501   [(set_attr "length" "12")
7502    (set_attr "type" "call")]
7503 )
7504
7505 (define_insn "*call_value_reg_thumb_v5"
7506   [(set (match_operand 0 "" "")
7507         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7508               (match_operand 2 "" "")))
7509    (use (match_operand 3 "" ""))
7510    (clobber (reg:SI LR_REGNUM))]
7511   "TARGET_THUMB && arm_arch5"
7512   "blx\\t%1"
7513   [(set_attr "length" "2")
7514    (set_attr "type" "call")]
7515 )
7516
7517 (define_insn "*call_value_reg_thumb"
7518   [(set (match_operand 0 "" "")
7519         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7520               (match_operand 2 "" "")))
7521    (use (match_operand 3 "" ""))
7522    (clobber (reg:SI LR_REGNUM))]
7523   "TARGET_THUMB && !arm_arch5"
7524   "*
7525   {
7526     if (TARGET_CALLER_INTERWORKING)
7527       return \"bl\\t%__interwork_call_via_%1\";
7528     else
7529       return \"bl\\t%__call_via_%1\";
7530   }"
7531   [(set_attr "type" "call")]
7532 )
7533
7534 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7535 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7536
7537 (define_insn "*call_symbol"
7538   [(call (mem:SI (match_operand:SI 0 "" ""))
7539          (match_operand 1 "" ""))
7540    (use (match_operand 2 "" ""))
7541    (clobber (reg:SI LR_REGNUM))]
7542   "TARGET_ARM
7543    && (GET_CODE (operands[0]) == SYMBOL_REF)
7544    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7545   "*
7546   {
7547     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7548   }"
7549   [(set_attr "type" "call")]
7550 )
7551
7552 (define_insn "*call_value_symbol"
7553   [(set (match_operand 0 "s_register_operand" "")
7554         (call (mem:SI (match_operand:SI 1 "" ""))
7555         (match_operand:SI 2 "" "")))
7556    (use (match_operand 3 "" ""))
7557    (clobber (reg:SI LR_REGNUM))]
7558   "TARGET_ARM
7559    && (GET_CODE (operands[1]) == SYMBOL_REF)
7560    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7561   "*
7562   {
7563     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7564   }"
7565   [(set_attr "type" "call")]
7566 )
7567
7568 (define_insn "*call_insn"
7569   [(call (mem:SI (match_operand:SI 0 "" ""))
7570          (match_operand:SI 1 "" ""))
7571    (use (match_operand 2 "" ""))
7572    (clobber (reg:SI LR_REGNUM))]
7573   "TARGET_THUMB
7574    && GET_CODE (operands[0]) == SYMBOL_REF
7575    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7576   "bl\\t%a0"
7577   [(set_attr "length" "4")
7578    (set_attr "type" "call")]
7579 )
7580
7581 (define_insn "*call_value_insn"
7582   [(set (match_operand 0 "register_operand" "")
7583         (call (mem:SI (match_operand 1 "" ""))
7584               (match_operand 2 "" "")))
7585    (use (match_operand 3 "" ""))
7586    (clobber (reg:SI LR_REGNUM))]
7587   "TARGET_THUMB
7588    && GET_CODE (operands[1]) == SYMBOL_REF
7589    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7590   "bl\\t%a1"
7591   [(set_attr "length" "4")
7592    (set_attr "type" "call")]
7593 )
7594
7595 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7596 (define_expand "sibcall"
7597   [(parallel [(call (match_operand 0 "memory_operand" "")
7598                     (match_operand 1 "general_operand" ""))
7599               (return)
7600               (use (match_operand 2 "" ""))])]
7601   "TARGET_ARM"
7602   "
7603   {
7604     if (operands[2] == NULL_RTX)
7605       operands[2] = const0_rtx;
7606   }"
7607 )
7608
7609 (define_expand "sibcall_value"
7610   [(parallel [(set (match_operand 0 "register_operand" "")
7611                    (call (match_operand 1 "memory_operand" "")
7612                          (match_operand 2 "general_operand" "")))
7613               (return)
7614               (use (match_operand 3 "" ""))])]
7615   "TARGET_ARM"
7616   "
7617   {
7618     if (operands[3] == NULL_RTX)
7619       operands[3] = const0_rtx;
7620   }"
7621 )
7622
7623 (define_insn "*sibcall_insn"
7624  [(call (mem:SI (match_operand:SI 0 "" "X"))
7625         (match_operand 1 "" ""))
7626   (return)
7627   (use (match_operand 2 "" ""))]
7628   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7629   "*
7630   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7631   "
7632   [(set_attr "type" "call")]
7633 )
7634
7635 (define_insn "*sibcall_value_insn"
7636  [(set (match_operand 0 "s_register_operand" "")
7637        (call (mem:SI (match_operand:SI 1 "" "X"))
7638              (match_operand 2 "" "")))
7639   (return)
7640   (use (match_operand 3 "" ""))]
7641   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7642   "*
7643   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7644   "
7645   [(set_attr "type" "call")]
7646 )
7647
7648 ;; Often the return insn will be the same as loading from memory, so set attr
7649 (define_insn "return"
7650   [(return)]
7651   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7652   "*
7653   {
7654     if (arm_ccfsm_state == 2)
7655       {
7656         arm_ccfsm_state += 2;
7657         return \"\";
7658       }
7659     return output_return_instruction (const_true_rtx, TRUE, FALSE);
7660   }"
7661   [(set_attr "type" "load1")
7662    (set_attr "length" "12")
7663    (set_attr "predicable" "yes")]
7664 )
7665
7666 (define_insn "*cond_return"
7667   [(set (pc)
7668         (if_then_else (match_operator 0 "arm_comparison_operator"
7669                        [(match_operand 1 "cc_register" "") (const_int 0)])
7670                       (return)
7671                       (pc)))]
7672   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7673   "*
7674   {
7675     if (arm_ccfsm_state == 2)
7676       {
7677         arm_ccfsm_state += 2;
7678         return \"\";
7679       }
7680     return output_return_instruction (operands[0], TRUE, FALSE);
7681   }"
7682   [(set_attr "conds" "use")
7683    (set_attr "length" "12")
7684    (set_attr "type" "load1")]
7685 )
7686
7687 (define_insn "*cond_return_inverted"
7688   [(set (pc)
7689         (if_then_else (match_operator 0 "arm_comparison_operator"
7690                        [(match_operand 1 "cc_register" "") (const_int 0)])
7691                       (pc)
7692                       (return)))]
7693   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7694   "*
7695   {
7696     if (arm_ccfsm_state == 2)
7697       {
7698         arm_ccfsm_state += 2;
7699         return \"\";
7700       }
7701     return output_return_instruction (operands[0], TRUE, TRUE);
7702   }"
7703   [(set_attr "conds" "use")
7704    (set_attr "length" "12")
7705    (set_attr "type" "load1")]
7706 )
7707
7708 ;; Generate a sequence of instructions to determine if the processor is
7709 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7710 ;; mask.
7711
7712 (define_expand "return_addr_mask"
7713   [(set (match_dup 1)
7714       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7715                        (const_int 0)))
7716    (set (match_operand:SI 0 "s_register_operand" "")
7717       (if_then_else:SI (eq (match_dup 1) (const_int 0))
7718                        (const_int -1)
7719                        (const_int 67108860)))] ; 0x03fffffc
7720   "TARGET_ARM"
7721   "
7722   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7723   ")
7724
7725 (define_insn "*check_arch2"
7726   [(set (match_operand:CC_NOOV 0 "cc_register" "")
7727       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7728                        (const_int 0)))]
7729   "TARGET_ARM"
7730   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7731   [(set_attr "length" "8")
7732    (set_attr "conds" "set")]
7733 )
7734
7735 ;; Call subroutine returning any type.
7736
7737 (define_expand "untyped_call"
7738   [(parallel [(call (match_operand 0 "" "")
7739                     (const_int 0))
7740               (match_operand 1 "" "")
7741               (match_operand 2 "" "")])]
7742   "TARGET_ARM"
7743   "
7744   {
7745     int i;
7746
7747     emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
7748
7749     for (i = 0; i < XVECLEN (operands[2], 0); i++)
7750       {
7751         rtx set = XVECEXP (operands[2], 0, i);
7752
7753         emit_move_insn (SET_DEST (set), SET_SRC (set));
7754       }
7755
7756     /* The optimizer does not know that the call sets the function value
7757        registers we stored in the result block.  We avoid problems by
7758        claiming that all hard registers are used and clobbered at this
7759        point.  */
7760     emit_insn (gen_blockage ());
7761
7762     DONE;
7763   }"
7764 )
7765
7766 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7767 ;; all of memory.  This blocks insns from being moved across this point.
7768
7769 (define_insn "blockage"
7770   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
7771   "TARGET_EITHER"
7772   ""
7773   [(set_attr "length" "0")
7774    (set_attr "type" "block")]
7775 )
7776
7777 (define_expand "casesi"
7778   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
7779    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
7780    (match_operand:SI 2 "const_int_operand" "")  ; total range
7781    (match_operand:SI 3 "" "")                   ; table label
7782    (match_operand:SI 4 "" "")]                  ; Out of range label
7783   "TARGET_ARM"
7784   "
7785   {
7786     rtx reg;
7787     if (operands[1] != const0_rtx)
7788       {
7789         reg = gen_reg_rtx (SImode);
7790
7791         emit_insn (gen_addsi3 (reg, operands[0],
7792                                GEN_INT (-INTVAL (operands[1]))));
7793         operands[0] = reg;
7794       }
7795
7796     if (!const_ok_for_arm (INTVAL (operands[2])))
7797       operands[2] = force_reg (SImode, operands[2]);
7798
7799     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
7800                                          operands[4]));
7801     DONE;
7802   }"
7803 )
7804
7805 ;; The USE in this pattern is needed to tell flow analysis that this is
7806 ;; a CASESI insn.  It has no other purpose.
7807 (define_insn "casesi_internal"
7808   [(parallel [(set (pc)
7809                (if_then_else
7810                 (leu (match_operand:SI 0 "s_register_operand" "r")
7811                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
7812                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
7813                                  (label_ref (match_operand 2 "" ""))))
7814                 (label_ref (match_operand 3 "" ""))))
7815               (clobber (reg:CC CC_REGNUM))
7816               (use (label_ref (match_dup 2)))])]
7817   "TARGET_ARM"
7818   "*
7819     if (flag_pic)
7820       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
7821     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
7822   "
7823   [(set_attr "conds" "clob")
7824    (set_attr "length" "12")]
7825 )
7826
7827 (define_expand "indirect_jump"
7828   [(set (pc)
7829         (match_operand:SI 0 "s_register_operand" ""))]
7830   "TARGET_EITHER"
7831   ""
7832 )
7833
7834 ;; NB Never uses BX.
7835 (define_insn "*arm_indirect_jump"
7836   [(set (pc)
7837         (match_operand:SI 0 "s_register_operand" "r"))]
7838   "TARGET_ARM"
7839   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
7840   [(set_attr "predicable" "yes")]
7841 )
7842
7843 (define_insn "*load_indirect_jump"
7844   [(set (pc)
7845         (match_operand:SI 0 "memory_operand" "m"))]
7846   "TARGET_ARM"
7847   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
7848   [(set_attr "type" "load1")
7849    (set_attr "pool_range" "4096")
7850    (set_attr "neg_pool_range" "4084")
7851    (set_attr "predicable" "yes")]
7852 )
7853
7854 ;; NB Never uses BX.
7855 (define_insn "*thumb_indirect_jump"
7856   [(set (pc)
7857         (match_operand:SI 0 "register_operand" "l*r"))]
7858   "TARGET_THUMB"
7859   "mov\\tpc, %0"
7860   [(set_attr "conds" "clob")
7861    (set_attr "length" "2")]
7862 )
7863
7864 \f
7865 ;; Misc insns
7866
7867 (define_insn "nop"
7868   [(const_int 0)]
7869   "TARGET_EITHER"
7870   "*
7871   if (TARGET_ARM)
7872     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
7873   return  \"mov\\tr8, r8\";
7874   "
7875   [(set (attr "length")
7876         (if_then_else (eq_attr "is_thumb" "yes")
7877                       (const_int 2)
7878                       (const_int 4)))]
7879 )
7880
7881 \f
7882 ;; Patterns to allow combination of arithmetic, cond code and shifts
7883
7884 (define_insn "*arith_shiftsi"
7885   [(set (match_operand:SI 0 "s_register_operand" "=r")
7886         (match_operator:SI 1 "shiftable_operator"
7887           [(match_operator:SI 3 "shift_operator"
7888              [(match_operand:SI 4 "s_register_operand" "r")
7889               (match_operand:SI 5 "reg_or_int_operand" "rI")])
7890            (match_operand:SI 2 "s_register_operand" "r")]))]
7891   "TARGET_ARM"
7892   "%i1%?\\t%0, %2, %4%S3"
7893   [(set_attr "predicable" "yes")
7894    (set_attr "shift" "4")
7895    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7896                       (const_string "alu_shift")
7897                       (const_string "alu_shift_reg")))]
7898 )
7899
7900 (define_split
7901   [(set (match_operand:SI 0 "s_register_operand" "")
7902         (match_operator:SI 1 "shiftable_operator"
7903          [(match_operator:SI 2 "shiftable_operator"
7904            [(match_operator:SI 3 "shift_operator"
7905              [(match_operand:SI 4 "s_register_operand" "")
7906               (match_operand:SI 5 "reg_or_int_operand" "")])
7907             (match_operand:SI 6 "s_register_operand" "")])
7908           (match_operand:SI 7 "arm_rhs_operand" "")]))
7909    (clobber (match_operand:SI 8 "s_register_operand" ""))]
7910   "TARGET_ARM"
7911   [(set (match_dup 8)
7912         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7913                          (match_dup 6)]))
7914    (set (match_dup 0)
7915         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
7916   "")
7917
7918 (define_insn "*arith_shiftsi_compare0"
7919   [(set (reg:CC_NOOV CC_REGNUM)
7920         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7921                           [(match_operator:SI 3 "shift_operator"
7922                             [(match_operand:SI 4 "s_register_operand" "r")
7923                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
7924                            (match_operand:SI 2 "s_register_operand" "r")])
7925                          (const_int 0)))
7926    (set (match_operand:SI 0 "s_register_operand" "=r")
7927         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7928                          (match_dup 2)]))]
7929   "TARGET_ARM"
7930   "%i1%?s\\t%0, %2, %4%S3"
7931   [(set_attr "conds" "set")
7932    (set_attr "shift" "4")
7933    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7934                       (const_string "alu_shift")
7935                       (const_string "alu_shift_reg")))]
7936 )
7937
7938 (define_insn "*arith_shiftsi_compare0_scratch"
7939   [(set (reg:CC_NOOV CC_REGNUM)
7940         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7941                           [(match_operator:SI 3 "shift_operator"
7942                             [(match_operand:SI 4 "s_register_operand" "r")
7943                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
7944                            (match_operand:SI 2 "s_register_operand" "r")])
7945                          (const_int 0)))
7946    (clobber (match_scratch:SI 0 "=r"))]
7947   "TARGET_ARM"
7948   "%i1%?s\\t%0, %2, %4%S3"
7949   [(set_attr "conds" "set")
7950    (set_attr "shift" "4")
7951    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7952                       (const_string "alu_shift")
7953                       (const_string "alu_shift_reg")))]
7954 )
7955
7956 (define_insn "*sub_shiftsi"
7957   [(set (match_operand:SI 0 "s_register_operand" "=r")
7958         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7959                   (match_operator:SI 2 "shift_operator"
7960                    [(match_operand:SI 3 "s_register_operand" "r")
7961                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
7962   "TARGET_ARM"
7963   "sub%?\\t%0, %1, %3%S2"
7964   [(set_attr "predicable" "yes")
7965    (set_attr "shift" "3")
7966    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7967                       (const_string "alu_shift")
7968                       (const_string "alu_shift_reg")))]
7969 )
7970
7971 (define_insn "*sub_shiftsi_compare0"
7972   [(set (reg:CC_NOOV CC_REGNUM)
7973         (compare:CC_NOOV
7974          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7975                    (match_operator:SI 2 "shift_operator"
7976                     [(match_operand:SI 3 "s_register_operand" "r")
7977                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7978          (const_int 0)))
7979    (set (match_operand:SI 0 "s_register_operand" "=r")
7980         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7981                                                  (match_dup 4)])))]
7982   "TARGET_ARM"
7983   "sub%?s\\t%0, %1, %3%S2"
7984   [(set_attr "conds" "set")
7985    (set_attr "shift" "3")
7986    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7987                       (const_string "alu_shift")
7988                       (const_string "alu_shift_reg")))]
7989 )
7990
7991 (define_insn "*sub_shiftsi_compare0_scratch"
7992   [(set (reg:CC_NOOV CC_REGNUM)
7993         (compare:CC_NOOV
7994          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7995                    (match_operator:SI 2 "shift_operator"
7996                     [(match_operand:SI 3 "s_register_operand" "r")
7997                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7998          (const_int 0)))
7999    (clobber (match_scratch:SI 0 "=r"))]
8000   "TARGET_ARM"
8001   "sub%?s\\t%0, %1, %3%S2"
8002   [(set_attr "conds" "set")
8003    (set_attr "shift" "3")
8004    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8005                       (const_string "alu_shift")
8006                       (const_string "alu_shift_reg")))]
8007 )
8008
8009 \f
8010
8011 (define_insn "*and_scc"
8012   [(set (match_operand:SI 0 "s_register_operand" "=r")
8013         (and:SI (match_operator:SI 1 "arm_comparison_operator"
8014                  [(match_operand 3 "cc_register" "") (const_int 0)])
8015                 (match_operand:SI 2 "s_register_operand" "r")))]
8016   "TARGET_ARM"
8017   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8018   [(set_attr "conds" "use")
8019    (set_attr "length" "8")]
8020 )
8021
8022 (define_insn "*ior_scc"
8023   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8024         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8025                  [(match_operand 3 "cc_register" "") (const_int 0)])
8026                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8027   "TARGET_ARM"
8028   "@
8029    orr%d2\\t%0, %1, #1
8030    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8031   [(set_attr "conds" "use")
8032    (set_attr "length" "4,8")]
8033 )
8034
8035 (define_insn "*compare_scc"
8036   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8037         (match_operator:SI 1 "arm_comparison_operator"
8038          [(match_operand:SI 2 "s_register_operand" "r,r")
8039           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8040    (clobber (reg:CC CC_REGNUM))]
8041   "TARGET_ARM"
8042   "*
8043     if (operands[3] == const0_rtx)
8044       {
8045         if (GET_CODE (operands[1]) == LT)
8046           return \"mov\\t%0, %2, lsr #31\";
8047
8048         if (GET_CODE (operands[1]) == GE)
8049           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8050
8051         if (GET_CODE (operands[1]) == EQ)
8052           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8053       }
8054
8055     if (GET_CODE (operands[1]) == NE)
8056       {
8057         if (which_alternative == 1)
8058           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8059         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8060       }
8061     if (which_alternative == 1)
8062       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8063     else
8064       output_asm_insn (\"cmp\\t%2, %3\", operands);
8065     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8066   "
8067   [(set_attr "conds" "clob")
8068    (set_attr "length" "12")]
8069 )
8070
8071 (define_insn "*cond_move"
8072   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8073         (if_then_else:SI (match_operator 3 "equality_operator"
8074                           [(match_operator 4 "arm_comparison_operator"
8075                             [(match_operand 5 "cc_register" "") (const_int 0)])
8076                            (const_int 0)])
8077                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8078                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8079   "TARGET_ARM"
8080   "*
8081     if (GET_CODE (operands[3]) == NE)
8082       {
8083         if (which_alternative != 1)
8084           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8085         if (which_alternative != 0)
8086           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8087         return \"\";
8088       }
8089     if (which_alternative != 0)
8090       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8091     if (which_alternative != 1)
8092       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8093     return \"\";
8094   "
8095   [(set_attr "conds" "use")
8096    (set_attr "length" "4,4,8")]
8097 )
8098
8099 (define_insn "*cond_arith"
8100   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8101         (match_operator:SI 5 "shiftable_operator" 
8102          [(match_operator:SI 4 "arm_comparison_operator"
8103            [(match_operand:SI 2 "s_register_operand" "r,r")
8104             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8105           (match_operand:SI 1 "s_register_operand" "0,?r")]))
8106    (clobber (reg:CC CC_REGNUM))]
8107   "TARGET_ARM"
8108   "*
8109     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8110       return \"%i5\\t%0, %1, %2, lsr #31\";
8111
8112     output_asm_insn (\"cmp\\t%2, %3\", operands);
8113     if (GET_CODE (operands[5]) == AND)
8114       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8115     else if (GET_CODE (operands[5]) == MINUS)
8116       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8117     else if (which_alternative != 0)
8118       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8119     return \"%i5%d4\\t%0, %1, #1\";
8120   "
8121   [(set_attr "conds" "clob")
8122    (set_attr "length" "12")]
8123 )
8124
8125 (define_insn "*cond_sub"
8126   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8127         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8128                   (match_operator:SI 4 "arm_comparison_operator"
8129                    [(match_operand:SI 2 "s_register_operand" "r,r")
8130                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8131    (clobber (reg:CC CC_REGNUM))]
8132   "TARGET_ARM"
8133   "*
8134     output_asm_insn (\"cmp\\t%2, %3\", operands);
8135     if (which_alternative != 0)
8136       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8137     return \"sub%d4\\t%0, %1, #1\";
8138   "
8139   [(set_attr "conds" "clob")
8140    (set_attr "length" "8,12")]
8141 )
8142
8143 (define_insn "*cmp_ite0"
8144   [(set (match_operand 6 "dominant_cc_register" "")
8145         (compare
8146          (if_then_else:SI
8147           (match_operator 4 "arm_comparison_operator"
8148            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8149             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8150           (match_operator:SI 5 "arm_comparison_operator"
8151            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8152             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8153           (const_int 0))
8154          (const_int 0)))]
8155   "TARGET_ARM"
8156   "*
8157   {
8158     static const char * const opcodes[4][2] =
8159     {
8160       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8161        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8162       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8163        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8164       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8165        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8166       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8167        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8168     };
8169     int swap =
8170       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8171
8172     return opcodes[which_alternative][swap];
8173   }"
8174   [(set_attr "conds" "set")
8175    (set_attr "length" "8")]
8176 )
8177
8178 (define_insn "*cmp_ite1"
8179   [(set (match_operand 6 "dominant_cc_register" "")
8180         (compare
8181          (if_then_else:SI
8182           (match_operator 4 "arm_comparison_operator"
8183            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8184             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8185           (match_operator:SI 5 "arm_comparison_operator"
8186            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8187             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8188           (const_int 1))
8189          (const_int 0)))]
8190   "TARGET_ARM"
8191   "*
8192   {
8193     static const char * const opcodes[4][2] =
8194     {
8195       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8196        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8197       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8198        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8199       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8200        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8201       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8202        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8203     };
8204     int swap =
8205       comparison_dominates_p (GET_CODE (operands[5]),
8206                               reverse_condition (GET_CODE (operands[4])));
8207
8208     return opcodes[which_alternative][swap];
8209   }"
8210   [(set_attr "conds" "set")
8211    (set_attr "length" "8")]
8212 )
8213
8214 (define_insn "*cmp_and"
8215   [(set (match_operand 6 "dominant_cc_register" "")
8216         (compare
8217          (and:SI
8218           (match_operator 4 "arm_comparison_operator"
8219            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8220             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8221           (match_operator:SI 5 "arm_comparison_operator"
8222            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8223             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8224          (const_int 0)))]
8225   "TARGET_ARM"
8226   "*
8227   {
8228     static const char *const opcodes[4][2] =
8229     {
8230       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8231        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8232       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8233        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8234       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8235        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8236       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8237        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8238     };
8239     int swap =
8240       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8241
8242     return opcodes[which_alternative][swap];
8243   }"
8244   [(set_attr "conds" "set")
8245    (set_attr "predicable" "no")
8246    (set_attr "length" "8")]
8247 )
8248
8249 (define_insn "*cmp_ior"
8250   [(set (match_operand 6 "dominant_cc_register" "")
8251         (compare
8252          (ior:SI
8253           (match_operator 4 "arm_comparison_operator"
8254            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8255             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8256           (match_operator:SI 5 "arm_comparison_operator"
8257            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8258             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8259          (const_int 0)))]
8260   "TARGET_ARM"
8261   "*
8262 {
8263   static const char *const opcodes[4][2] =
8264   {
8265     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8266      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8267     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8268      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8269     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8270      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8271     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8272      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8273   };
8274   int swap =
8275     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8276
8277   return opcodes[which_alternative][swap];
8278 }
8279 "
8280   [(set_attr "conds" "set")
8281    (set_attr "length" "8")]
8282 )
8283
8284 (define_insn_and_split "*ior_scc_scc"
8285   [(set (match_operand:SI 0 "s_register_operand" "=r")
8286         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8287                  [(match_operand:SI 1 "s_register_operand" "r")
8288                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8289                 (match_operator:SI 6 "arm_comparison_operator"
8290                  [(match_operand:SI 4 "s_register_operand" "r")
8291                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8292    (clobber (reg:CC CC_REGNUM))]
8293   "TARGET_ARM
8294    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8295        != CCmode)"
8296   "#"
8297   "TARGET_ARM && reload_completed"
8298   [(set (match_dup 7)
8299         (compare
8300          (ior:SI
8301           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8302           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8303          (const_int 0)))
8304    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8305   "operands[7]
8306      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8307                                                   DOM_CC_X_OR_Y),
8308                     CC_REGNUM);"
8309   [(set_attr "conds" "clob")
8310    (set_attr "length" "16")])
8311
8312 ; If the above pattern is followed by a CMP insn, then the compare is 
8313 ; redundant, since we can rework the conditional instruction that follows.
8314 (define_insn_and_split "*ior_scc_scc_cmp"
8315   [(set (match_operand 0 "dominant_cc_register" "")
8316         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8317                           [(match_operand:SI 1 "s_register_operand" "r")
8318                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8319                          (match_operator:SI 6 "arm_comparison_operator"
8320                           [(match_operand:SI 4 "s_register_operand" "r")
8321                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8322                  (const_int 0)))
8323    (set (match_operand:SI 7 "s_register_operand" "=r")
8324         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8325                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8326   "TARGET_ARM"
8327   "#"
8328   "TARGET_ARM && reload_completed"
8329   [(set (match_dup 0)
8330         (compare
8331          (ior:SI
8332           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8333           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8334          (const_int 0)))
8335    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8336   ""
8337   [(set_attr "conds" "set")
8338    (set_attr "length" "16")])
8339
8340 (define_insn_and_split "*and_scc_scc"
8341   [(set (match_operand:SI 0 "s_register_operand" "=r")
8342         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8343                  [(match_operand:SI 1 "s_register_operand" "r")
8344                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8345                 (match_operator:SI 6 "arm_comparison_operator"
8346                  [(match_operand:SI 4 "s_register_operand" "r")
8347                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8348    (clobber (reg:CC CC_REGNUM))]
8349   "TARGET_ARM
8350    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8351        != CCmode)"
8352   "#"
8353   "TARGET_ARM && reload_completed
8354    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8355        != CCmode)"
8356   [(set (match_dup 7)
8357         (compare
8358          (and:SI
8359           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8360           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8361          (const_int 0)))
8362    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8363   "operands[7]
8364      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8365                                                   DOM_CC_X_AND_Y),
8366                     CC_REGNUM);"
8367   [(set_attr "conds" "clob")
8368    (set_attr "length" "16")])
8369
8370 ; If the above pattern is followed by a CMP insn, then the compare is 
8371 ; redundant, since we can rework the conditional instruction that follows.
8372 (define_insn_and_split "*and_scc_scc_cmp"
8373   [(set (match_operand 0 "dominant_cc_register" "")
8374         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8375                           [(match_operand:SI 1 "s_register_operand" "r")
8376                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8377                          (match_operator:SI 6 "arm_comparison_operator"
8378                           [(match_operand:SI 4 "s_register_operand" "r")
8379                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8380                  (const_int 0)))
8381    (set (match_operand:SI 7 "s_register_operand" "=r")
8382         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8383                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8384   "TARGET_ARM"
8385   "#"
8386   "TARGET_ARM && reload_completed"
8387   [(set (match_dup 0)
8388         (compare
8389          (and:SI
8390           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8391           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8392          (const_int 0)))
8393    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8394   ""
8395   [(set_attr "conds" "set")
8396    (set_attr "length" "16")])
8397
8398 ;; If there is no dominance in the comparison, then we can still save an
8399 ;; instruction in the AND case, since we can know that the second compare
8400 ;; need only zero the value if false (if true, then the value is already
8401 ;; correct).
8402 (define_insn_and_split "*and_scc_scc_nodom"
8403   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8404         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8405                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
8406                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8407                 (match_operator:SI 6 "arm_comparison_operator"
8408                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
8409                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8410    (clobber (reg:CC CC_REGNUM))]
8411   "TARGET_ARM
8412    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8413        == CCmode)"
8414   "#"
8415   "TARGET_ARM && reload_completed"
8416   [(parallel [(set (match_dup 0)
8417                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8418               (clobber (reg:CC CC_REGNUM))])
8419    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8420    (set (match_dup 0)
8421         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8422                          (match_dup 0)
8423                          (const_int 0)))]
8424   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8425                                               operands[4], operands[5]),
8426                               CC_REGNUM);
8427    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8428                                   operands[5]);"
8429   [(set_attr "conds" "clob")
8430    (set_attr "length" "20")])
8431
8432 (define_split
8433   [(set (reg:CC_NOOV CC_REGNUM)
8434         (compare:CC_NOOV (ior:SI
8435                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8436                                   (const_int 1))
8437                           (match_operator:SI 1 "comparison_operator"
8438                            [(match_operand:SI 2 "s_register_operand" "")
8439                             (match_operand:SI 3 "arm_add_operand" "")]))
8440                          (const_int 0)))
8441    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8442   "TARGET_ARM"
8443   [(set (match_dup 4)
8444         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8445                 (match_dup 0)))
8446    (set (reg:CC_NOOV CC_REGNUM)
8447         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8448                          (const_int 0)))]
8449   "")
8450
8451 (define_split
8452   [(set (reg:CC_NOOV CC_REGNUM)
8453         (compare:CC_NOOV (ior:SI
8454                           (match_operator:SI 1 "comparison_operator"
8455                            [(match_operand:SI 2 "s_register_operand" "")
8456                             (match_operand:SI 3 "arm_add_operand" "")])
8457                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8458                                   (const_int 1)))
8459                          (const_int 0)))
8460    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8461   "TARGET_ARM"
8462   [(set (match_dup 4)
8463         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8464                 (match_dup 0)))
8465    (set (reg:CC_NOOV CC_REGNUM)
8466         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8467                          (const_int 0)))]
8468   "")
8469
8470 (define_insn "*negscc"
8471   [(set (match_operand:SI 0 "s_register_operand" "=r")
8472         (neg:SI (match_operator 3 "arm_comparison_operator"
8473                  [(match_operand:SI 1 "s_register_operand" "r")
8474                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8475    (clobber (reg:CC CC_REGNUM))]
8476   "TARGET_ARM"
8477   "*
8478   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8479     return \"mov\\t%0, %1, asr #31\";
8480
8481   if (GET_CODE (operands[3]) == NE)
8482     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8483
8484   if (GET_CODE (operands[3]) == GT)
8485     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8486
8487   output_asm_insn (\"cmp\\t%1, %2\", operands);
8488   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8489   return \"mvn%d3\\t%0, #0\";
8490   "
8491   [(set_attr "conds" "clob")
8492    (set_attr "length" "12")]
8493 )
8494
8495 (define_insn "movcond"
8496   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8497         (if_then_else:SI
8498          (match_operator 5 "arm_comparison_operator"
8499           [(match_operand:SI 3 "s_register_operand" "r,r,r")
8500            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8501          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8502          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8503    (clobber (reg:CC CC_REGNUM))]
8504   "TARGET_ARM"
8505   "*
8506   if (GET_CODE (operands[5]) == LT
8507       && (operands[4] == const0_rtx))
8508     {
8509       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8510         {
8511           if (operands[2] == const0_rtx)
8512             return \"and\\t%0, %1, %3, asr #31\";
8513           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8514         }
8515       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8516         {
8517           if (operands[1] == const0_rtx)
8518             return \"bic\\t%0, %2, %3, asr #31\";
8519           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8520         }
8521       /* The only case that falls through to here is when both ops 1 & 2
8522          are constants.  */
8523     }
8524
8525   if (GET_CODE (operands[5]) == GE
8526       && (operands[4] == const0_rtx))
8527     {
8528       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8529         {
8530           if (operands[2] == const0_rtx)
8531             return \"bic\\t%0, %1, %3, asr #31\";
8532           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8533         }
8534       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8535         {
8536           if (operands[1] == const0_rtx)
8537             return \"and\\t%0, %2, %3, asr #31\";
8538           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8539         }
8540       /* The only case that falls through to here is when both ops 1 & 2
8541          are constants.  */
8542     }
8543   if (GET_CODE (operands[4]) == CONST_INT
8544       && !const_ok_for_arm (INTVAL (operands[4])))
8545     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8546   else
8547     output_asm_insn (\"cmp\\t%3, %4\", operands);
8548   if (which_alternative != 0)
8549     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8550   if (which_alternative != 1)
8551     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8552   return \"\";
8553   "
8554   [(set_attr "conds" "clob")
8555    (set_attr "length" "8,8,12")]
8556 )
8557
8558 (define_insn "*ifcompare_plus_move"
8559   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8560         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8561                           [(match_operand:SI 4 "s_register_operand" "r,r")
8562                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8563                          (plus:SI
8564                           (match_operand:SI 2 "s_register_operand" "r,r")
8565                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8566                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8567    (clobber (reg:CC CC_REGNUM))]
8568   "TARGET_ARM"
8569   "#"
8570   [(set_attr "conds" "clob")
8571    (set_attr "length" "8,12")]
8572 )
8573
8574 (define_insn "*if_plus_move"
8575   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8576         (if_then_else:SI
8577          (match_operator 4 "arm_comparison_operator"
8578           [(match_operand 5 "cc_register" "") (const_int 0)])
8579          (plus:SI
8580           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8581           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8582          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8583   "TARGET_ARM"
8584   "@
8585    add%d4\\t%0, %2, %3
8586    sub%d4\\t%0, %2, #%n3
8587    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8588    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8589   [(set_attr "conds" "use")
8590    (set_attr "length" "4,4,8,8")
8591    (set_attr "type" "*,*,*,*")]
8592 )
8593
8594 (define_insn "*ifcompare_move_plus"
8595   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8596         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8597                           [(match_operand:SI 4 "s_register_operand" "r,r")
8598                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8599                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8600                          (plus:SI
8601                           (match_operand:SI 2 "s_register_operand" "r,r")
8602                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8603    (clobber (reg:CC CC_REGNUM))]
8604   "TARGET_ARM"
8605   "#"
8606   [(set_attr "conds" "clob")
8607    (set_attr "length" "8,12")]
8608 )
8609
8610 (define_insn "*if_move_plus"
8611   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8612         (if_then_else:SI
8613          (match_operator 4 "arm_comparison_operator"
8614           [(match_operand 5 "cc_register" "") (const_int 0)])
8615          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8616          (plus:SI
8617           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8618           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8619   "TARGET_ARM"
8620   "@
8621    add%D4\\t%0, %2, %3
8622    sub%D4\\t%0, %2, #%n3
8623    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8624    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8625   [(set_attr "conds" "use")
8626    (set_attr "length" "4,4,8,8")
8627    (set_attr "type" "*,*,*,*")]
8628 )
8629
8630 (define_insn "*ifcompare_arith_arith"
8631   [(set (match_operand:SI 0 "s_register_operand" "=r")
8632         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8633                           [(match_operand:SI 5 "s_register_operand" "r")
8634                            (match_operand:SI 6 "arm_add_operand" "rIL")])
8635                          (match_operator:SI 8 "shiftable_operator"
8636                           [(match_operand:SI 1 "s_register_operand" "r")
8637                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8638                          (match_operator:SI 7 "shiftable_operator"
8639                           [(match_operand:SI 3 "s_register_operand" "r")
8640                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8641    (clobber (reg:CC CC_REGNUM))]
8642   "TARGET_ARM"
8643   "#"
8644   [(set_attr "conds" "clob")
8645    (set_attr "length" "12")]
8646 )
8647
8648 (define_insn "*if_arith_arith"
8649   [(set (match_operand:SI 0 "s_register_operand" "=r")
8650         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8651                           [(match_operand 8 "cc_register" "") (const_int 0)])
8652                          (match_operator:SI 6 "shiftable_operator"
8653                           [(match_operand:SI 1 "s_register_operand" "r")
8654                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8655                          (match_operator:SI 7 "shiftable_operator"
8656                           [(match_operand:SI 3 "s_register_operand" "r")
8657                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8658   "TARGET_ARM"
8659   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8660   [(set_attr "conds" "use")
8661    (set_attr "length" "8")]
8662 )
8663
8664 (define_insn "*ifcompare_arith_move"
8665   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8666         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8667                           [(match_operand:SI 2 "s_register_operand" "r,r")
8668                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8669                          (match_operator:SI 7 "shiftable_operator"
8670                           [(match_operand:SI 4 "s_register_operand" "r,r")
8671                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8672                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8673    (clobber (reg:CC CC_REGNUM))]
8674   "TARGET_ARM"
8675   "*
8676   /* If we have an operation where (op x 0) is the identity operation and
8677      the conditional operator is LT or GE and we are comparing against zero and
8678      everything is in registers then we can do this in two instructions.  */
8679   if (operands[3] == const0_rtx
8680       && GET_CODE (operands[7]) != AND
8681       && GET_CODE (operands[5]) == REG
8682       && GET_CODE (operands[1]) == REG 
8683       && REGNO (operands[1]) == REGNO (operands[4])
8684       && REGNO (operands[4]) != REGNO (operands[0]))
8685     {
8686       if (GET_CODE (operands[6]) == LT)
8687         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8688       else if (GET_CODE (operands[6]) == GE)
8689         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8690     }
8691   if (GET_CODE (operands[3]) == CONST_INT
8692       && !const_ok_for_arm (INTVAL (operands[3])))
8693     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8694   else
8695     output_asm_insn (\"cmp\\t%2, %3\", operands);
8696   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8697   if (which_alternative != 0)
8698     return \"mov%D6\\t%0, %1\";
8699   return \"\";
8700   "
8701   [(set_attr "conds" "clob")
8702    (set_attr "length" "8,12")]
8703 )
8704
8705 (define_insn "*if_arith_move"
8706   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8707         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8708                           [(match_operand 6 "cc_register" "") (const_int 0)])
8709                          (match_operator:SI 5 "shiftable_operator"
8710                           [(match_operand:SI 2 "s_register_operand" "r,r")
8711                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8712                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8713   "TARGET_ARM"
8714   "@
8715    %I5%d4\\t%0, %2, %3
8716    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8717   [(set_attr "conds" "use")
8718    (set_attr "length" "4,8")
8719    (set_attr "type" "*,*")]
8720 )
8721
8722 (define_insn "*ifcompare_move_arith"
8723   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8724         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8725                           [(match_operand:SI 4 "s_register_operand" "r,r")
8726                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8727                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8728                          (match_operator:SI 7 "shiftable_operator"
8729                           [(match_operand:SI 2 "s_register_operand" "r,r")
8730                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8731    (clobber (reg:CC CC_REGNUM))]
8732   "TARGET_ARM"
8733   "*
8734   /* If we have an operation where (op x 0) is the identity operation and
8735      the conditional operator is LT or GE and we are comparing against zero and
8736      everything is in registers then we can do this in two instructions */
8737   if (operands[5] == const0_rtx
8738       && GET_CODE (operands[7]) != AND
8739       && GET_CODE (operands[3]) == REG
8740       && GET_CODE (operands[1]) == REG 
8741       && REGNO (operands[1]) == REGNO (operands[2])
8742       && REGNO (operands[2]) != REGNO (operands[0]))
8743     {
8744       if (GET_CODE (operands[6]) == GE)
8745         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8746       else if (GET_CODE (operands[6]) == LT)
8747         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8748     }
8749
8750   if (GET_CODE (operands[5]) == CONST_INT
8751       && !const_ok_for_arm (INTVAL (operands[5])))
8752     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
8753   else
8754     output_asm_insn (\"cmp\\t%4, %5\", operands);
8755
8756   if (which_alternative != 0)
8757     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
8758   return \"%I7%D6\\t%0, %2, %3\";
8759   "
8760   [(set_attr "conds" "clob")
8761    (set_attr "length" "8,12")]
8762 )
8763
8764 (define_insn "*if_move_arith"
8765   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8766         (if_then_else:SI
8767          (match_operator 4 "arm_comparison_operator"
8768           [(match_operand 6 "cc_register" "") (const_int 0)])
8769          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8770          (match_operator:SI 5 "shiftable_operator"
8771           [(match_operand:SI 2 "s_register_operand" "r,r")
8772            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
8773   "TARGET_ARM"
8774   "@
8775    %I5%D4\\t%0, %2, %3
8776    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8777   [(set_attr "conds" "use")
8778    (set_attr "length" "4,8")
8779    (set_attr "type" "*,*")]
8780 )
8781
8782 (define_insn "*ifcompare_move_not"
8783   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8784         (if_then_else:SI
8785          (match_operator 5 "arm_comparison_operator"
8786           [(match_operand:SI 3 "s_register_operand" "r,r")
8787            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8788          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8789          (not:SI
8790           (match_operand:SI 2 "s_register_operand" "r,r"))))
8791    (clobber (reg:CC CC_REGNUM))]
8792   "TARGET_ARM"
8793   "#"
8794   [(set_attr "conds" "clob")
8795    (set_attr "length" "8,12")]
8796 )
8797
8798 (define_insn "*if_move_not"
8799   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8800         (if_then_else:SI
8801          (match_operator 4 "arm_comparison_operator"
8802           [(match_operand 3 "cc_register" "") (const_int 0)])
8803          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8804          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8805   "TARGET_ARM"
8806   "@
8807    mvn%D4\\t%0, %2
8808    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
8809    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8810   [(set_attr "conds" "use")
8811    (set_attr "length" "4,8,8")]
8812 )
8813
8814 (define_insn "*ifcompare_not_move"
8815   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8816         (if_then_else:SI 
8817          (match_operator 5 "arm_comparison_operator"
8818           [(match_operand:SI 3 "s_register_operand" "r,r")
8819            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8820          (not:SI
8821           (match_operand:SI 2 "s_register_operand" "r,r"))
8822          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8823    (clobber (reg:CC CC_REGNUM))]
8824   "TARGET_ARM"
8825   "#"
8826   [(set_attr "conds" "clob")
8827    (set_attr "length" "8,12")]
8828 )
8829
8830 (define_insn "*if_not_move"
8831   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8832         (if_then_else:SI
8833          (match_operator 4 "arm_comparison_operator"
8834           [(match_operand 3 "cc_register" "") (const_int 0)])
8835          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8836          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8837   "TARGET_ARM"
8838   "@
8839    mvn%d4\\t%0, %2
8840    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
8841    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8842   [(set_attr "conds" "use")
8843    (set_attr "length" "4,8,8")]
8844 )
8845
8846 (define_insn "*ifcompare_shift_move"
8847   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8848         (if_then_else:SI
8849          (match_operator 6 "arm_comparison_operator"
8850           [(match_operand:SI 4 "s_register_operand" "r,r")
8851            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8852          (match_operator:SI 7 "shift_operator"
8853           [(match_operand:SI 2 "s_register_operand" "r,r")
8854            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
8855          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8856    (clobber (reg:CC CC_REGNUM))]
8857   "TARGET_ARM"
8858   "#"
8859   [(set_attr "conds" "clob")
8860    (set_attr "length" "8,12")]
8861 )
8862
8863 (define_insn "*if_shift_move"
8864   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8865         (if_then_else:SI
8866          (match_operator 5 "arm_comparison_operator"
8867           [(match_operand 6 "cc_register" "") (const_int 0)])
8868          (match_operator:SI 4 "shift_operator"
8869           [(match_operand:SI 2 "s_register_operand" "r,r,r")
8870            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
8871          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8872   "TARGET_ARM"
8873   "@
8874    mov%d5\\t%0, %2%S4
8875    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
8876    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8877   [(set_attr "conds" "use")
8878    (set_attr "shift" "2")
8879    (set_attr "length" "4,8,8")
8880    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
8881                       (const_string "alu_shift")
8882                       (const_string "alu_shift_reg")))]
8883 )
8884
8885 (define_insn "*ifcompare_move_shift"
8886   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8887         (if_then_else:SI
8888          (match_operator 6 "arm_comparison_operator"
8889           [(match_operand:SI 4 "s_register_operand" "r,r")
8890            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8891          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8892          (match_operator:SI 7 "shift_operator"
8893           [(match_operand:SI 2 "s_register_operand" "r,r")
8894            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
8895    (clobber (reg:CC CC_REGNUM))]
8896   "TARGET_ARM"
8897   "#"
8898   [(set_attr "conds" "clob")
8899    (set_attr "length" "8,12")]
8900 )
8901
8902 (define_insn "*if_move_shift"
8903   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8904         (if_then_else:SI
8905          (match_operator 5 "arm_comparison_operator"
8906           [(match_operand 6 "cc_register" "") (const_int 0)])
8907          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8908          (match_operator:SI 4 "shift_operator"
8909           [(match_operand:SI 2 "s_register_operand" "r,r,r")
8910            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
8911   "TARGET_ARM"
8912   "@
8913    mov%D5\\t%0, %2%S4
8914    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
8915    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8916   [(set_attr "conds" "use")
8917    (set_attr "shift" "2")
8918    (set_attr "length" "4,8,8")
8919    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
8920                       (const_string "alu_shift")
8921                       (const_string "alu_shift_reg")))]
8922 )
8923
8924 (define_insn "*ifcompare_shift_shift"
8925   [(set (match_operand:SI 0 "s_register_operand" "=r")
8926         (if_then_else:SI
8927          (match_operator 7 "arm_comparison_operator"
8928           [(match_operand:SI 5 "s_register_operand" "r")
8929            (match_operand:SI 6 "arm_add_operand" "rIL")])
8930          (match_operator:SI 8 "shift_operator"
8931           [(match_operand:SI 1 "s_register_operand" "r")
8932            (match_operand:SI 2 "arm_rhs_operand" "rM")])
8933          (match_operator:SI 9 "shift_operator"
8934           [(match_operand:SI 3 "s_register_operand" "r")
8935            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
8936    (clobber (reg:CC CC_REGNUM))]
8937   "TARGET_ARM"
8938   "#"
8939   [(set_attr "conds" "clob")
8940    (set_attr "length" "12")]
8941 )
8942
8943 (define_insn "*if_shift_shift"
8944   [(set (match_operand:SI 0 "s_register_operand" "=r")
8945         (if_then_else:SI
8946          (match_operator 5 "arm_comparison_operator"
8947           [(match_operand 8 "cc_register" "") (const_int 0)])
8948          (match_operator:SI 6 "shift_operator"
8949           [(match_operand:SI 1 "s_register_operand" "r")
8950            (match_operand:SI 2 "arm_rhs_operand" "rM")])
8951          (match_operator:SI 7 "shift_operator"
8952           [(match_operand:SI 3 "s_register_operand" "r")
8953            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
8954   "TARGET_ARM"
8955   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8956   [(set_attr "conds" "use")
8957    (set_attr "shift" "1")
8958    (set_attr "length" "8")
8959    (set (attr "type") (if_then_else
8960                         (and (match_operand 2 "const_int_operand" "")
8961                              (match_operand 4 "const_int_operand" ""))
8962                       (const_string "alu_shift")
8963                       (const_string "alu_shift_reg")))]
8964 )
8965
8966 (define_insn "*ifcompare_not_arith"
8967   [(set (match_operand:SI 0 "s_register_operand" "=r")
8968         (if_then_else:SI
8969          (match_operator 6 "arm_comparison_operator"
8970           [(match_operand:SI 4 "s_register_operand" "r")
8971            (match_operand:SI 5 "arm_add_operand" "rIL")])
8972          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8973          (match_operator:SI 7 "shiftable_operator"
8974           [(match_operand:SI 2 "s_register_operand" "r")
8975            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
8976    (clobber (reg:CC CC_REGNUM))]
8977   "TARGET_ARM"
8978   "#"
8979   [(set_attr "conds" "clob")
8980    (set_attr "length" "12")]
8981 )
8982
8983 (define_insn "*if_not_arith"
8984   [(set (match_operand:SI 0 "s_register_operand" "=r")
8985         (if_then_else:SI
8986          (match_operator 5 "arm_comparison_operator"
8987           [(match_operand 4 "cc_register" "") (const_int 0)])
8988          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8989          (match_operator:SI 6 "shiftable_operator"
8990           [(match_operand:SI 2 "s_register_operand" "r")
8991            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
8992   "TARGET_ARM"
8993   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8994   [(set_attr "conds" "use")
8995    (set_attr "length" "8")]
8996 )
8997
8998 (define_insn "*ifcompare_arith_not"
8999   [(set (match_operand:SI 0 "s_register_operand" "=r")
9000         (if_then_else:SI
9001          (match_operator 6 "arm_comparison_operator"
9002           [(match_operand:SI 4 "s_register_operand" "r")
9003            (match_operand:SI 5 "arm_add_operand" "rIL")])
9004          (match_operator:SI 7 "shiftable_operator"
9005           [(match_operand:SI 2 "s_register_operand" "r")
9006            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9007          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9008    (clobber (reg:CC CC_REGNUM))]
9009   "TARGET_ARM"
9010   "#"
9011   [(set_attr "conds" "clob")
9012    (set_attr "length" "12")]
9013 )
9014
9015 (define_insn "*if_arith_not"
9016   [(set (match_operand:SI 0 "s_register_operand" "=r")
9017         (if_then_else:SI
9018          (match_operator 5 "arm_comparison_operator"
9019           [(match_operand 4 "cc_register" "") (const_int 0)])
9020          (match_operator:SI 6 "shiftable_operator"
9021           [(match_operand:SI 2 "s_register_operand" "r")
9022            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9023          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9024   "TARGET_ARM"
9025   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9026   [(set_attr "conds" "use")
9027    (set_attr "length" "8")]
9028 )
9029
9030 (define_insn "*ifcompare_neg_move"
9031   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9032         (if_then_else:SI
9033          (match_operator 5 "arm_comparison_operator"
9034           [(match_operand:SI 3 "s_register_operand" "r,r")
9035            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9036          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9037          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9038    (clobber (reg:CC CC_REGNUM))]
9039   "TARGET_ARM"
9040   "#"
9041   [(set_attr "conds" "clob")
9042    (set_attr "length" "8,12")]
9043 )
9044
9045 (define_insn "*if_neg_move"
9046   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9047         (if_then_else:SI
9048          (match_operator 4 "arm_comparison_operator"
9049           [(match_operand 3 "cc_register" "") (const_int 0)])
9050          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9051          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9052   "TARGET_ARM"
9053   "@
9054    rsb%d4\\t%0, %2, #0
9055    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9056    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9057   [(set_attr "conds" "use")
9058    (set_attr "length" "4,8,8")]
9059 )
9060
9061 (define_insn "*ifcompare_move_neg"
9062   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9063         (if_then_else:SI
9064          (match_operator 5 "arm_comparison_operator"
9065           [(match_operand:SI 3 "s_register_operand" "r,r")
9066            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9067          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9068          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9069    (clobber (reg:CC CC_REGNUM))]
9070   "TARGET_ARM"
9071   "#"
9072   [(set_attr "conds" "clob")
9073    (set_attr "length" "8,12")]
9074 )
9075
9076 (define_insn "*if_move_neg"
9077   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9078         (if_then_else:SI
9079          (match_operator 4 "arm_comparison_operator"
9080           [(match_operand 3 "cc_register" "") (const_int 0)])
9081          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9082          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9083   "TARGET_ARM"
9084   "@
9085    rsb%D4\\t%0, %2, #0
9086    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9087    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9088   [(set_attr "conds" "use")
9089    (set_attr "length" "4,8,8")]
9090 )
9091
9092 (define_insn "*arith_adjacentmem"
9093   [(set (match_operand:SI 0 "s_register_operand" "=r")
9094         (match_operator:SI 1 "shiftable_operator"
9095          [(match_operand:SI 2 "memory_operand" "m")
9096           (match_operand:SI 3 "memory_operand" "m")]))
9097    (clobber (match_scratch:SI 4 "=r"))]
9098   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9099   "*
9100   {
9101     rtx ldm[3];
9102     rtx arith[4];
9103     int val1 = 0, val2 = 0;
9104
9105     if (REGNO (operands[0]) > REGNO (operands[4]))
9106       {
9107         ldm[1] = operands[4];
9108         ldm[2] = operands[0];
9109       }
9110     else
9111       {
9112         ldm[1] = operands[0];
9113         ldm[2] = operands[4];
9114       }
9115     if (GET_CODE (XEXP (operands[2], 0)) != REG)
9116       val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
9117     if (GET_CODE (XEXP (operands[3], 0)) != REG)
9118       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9119     arith[0] = operands[0];
9120     arith[3] = operands[1];
9121     if (val1 < val2)
9122       {
9123         arith[1] = ldm[1];
9124         arith[2] = ldm[2];
9125       }
9126     else
9127       {
9128         arith[1] = ldm[2];
9129         arith[2] = ldm[1];
9130       }
9131    if (val1 && val2)
9132       {
9133         rtx ops[3];
9134         ldm[0] = ops[0] = operands[4];
9135         ops[1] = XEXP (XEXP (operands[2], 0), 0);
9136         ops[2] = XEXP (XEXP (operands[2], 0), 1);
9137         output_add_immediate (ops);
9138         if (val1 < val2)
9139           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9140         else
9141           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9142       }
9143     else if (val1)
9144       {
9145         ldm[0] = XEXP (operands[3], 0);
9146         if (val1 < val2)
9147           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9148         else
9149           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9150       }
9151     else
9152       {
9153         ldm[0] = XEXP (operands[2], 0);
9154         if (val1 < val2)
9155           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9156         else
9157           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9158       }
9159     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9160     return \"\";
9161   }"
9162   [(set_attr "length" "12")
9163    (set_attr "predicable" "yes")
9164    (set_attr "type" "load1")]
9165 )
9166
9167 ;; the arm can support extended pre-inc instructions
9168
9169 ;; In all these cases, we use operands 0 and 1 for the register being
9170 ;; incremented because those are the operands that local-alloc will
9171 ;; tie and these are the pair most likely to be tieable (and the ones
9172 ;; that will benefit the most).
9173
9174 ;; We reject the frame pointer if it occurs anywhere in these patterns since
9175 ;; elimination will cause too many headaches.
9176
9177 (define_insn "*strqi_preinc"
9178   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9179                          (match_operand:SI 2 "index_operand" "rJ")))
9180         (match_operand:QI 3 "s_register_operand" "r"))
9181    (set (match_operand:SI 0 "s_register_operand" "=r")
9182         (plus:SI (match_dup 1) (match_dup 2)))]
9183   "TARGET_ARM
9184    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9185    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9186    && (GET_CODE (operands[2]) != REG
9187        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9188   "str%?b\\t%3, [%0, %2]!"
9189   [(set_attr "type" "store1")
9190    (set_attr "predicable" "yes")]
9191 )
9192
9193 (define_insn "*strqi_predec"
9194   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9195                           (match_operand:SI 2 "s_register_operand" "r")))
9196         (match_operand:QI 3 "s_register_operand" "r"))
9197    (set (match_operand:SI 0 "s_register_operand" "=r")
9198         (minus:SI (match_dup 1) (match_dup 2)))]
9199   "TARGET_ARM
9200    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9201    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9202    && (GET_CODE (operands[2]) != REG
9203        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9204   "str%?b\\t%3, [%0, -%2]!"
9205   [(set_attr "type" "store1")
9206    (set_attr "predicable" "yes")]
9207 )
9208
9209 (define_insn "*loadqi_preinc"
9210   [(set (match_operand:QI 3 "s_register_operand" "=r")
9211         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9212                          (match_operand:SI 2 "index_operand" "rJ"))))
9213    (set (match_operand:SI 0 "s_register_operand" "=r")
9214         (plus:SI (match_dup 1) (match_dup 2)))]
9215   "TARGET_ARM
9216    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9217    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9218    && (GET_CODE (operands[2]) != REG
9219        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9220   "ldr%?b\\t%3, [%0, %2]!"
9221   [(set_attr "type" "load_byte")
9222    (set_attr "predicable" "yes")]
9223 )
9224
9225 (define_insn "*loadqi_predec"
9226   [(set (match_operand:QI 3 "s_register_operand" "=r")
9227         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9228                           (match_operand:SI 2 "s_register_operand" "r"))))
9229    (set (match_operand:SI 0 "s_register_operand" "=r")
9230         (minus:SI (match_dup 1) (match_dup 2)))]
9231   "TARGET_ARM
9232    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9233    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9234    && (GET_CODE (operands[2]) != REG
9235        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9236   "ldr%?b\\t%3, [%0, -%2]!"
9237   [(set_attr "type" "load_byte")
9238    (set_attr "predicable" "yes")]
9239 )
9240
9241 (define_insn "*loadqisi_preinc"
9242   [(set (match_operand:SI 3 "s_register_operand" "=r")
9243         (zero_extend:SI
9244          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9245                           (match_operand:SI 2 "index_operand" "rJ")))))
9246    (set (match_operand:SI 0 "s_register_operand" "=r")
9247         (plus:SI (match_dup 1) (match_dup 2)))]
9248   "TARGET_ARM
9249    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9250    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9251    && (GET_CODE (operands[2]) != REG
9252        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9253   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
9254   [(set_attr "type" "load_byte")
9255    (set_attr "predicable" "yes")]
9256 )
9257
9258 (define_insn "*loadqisi_predec"
9259   [(set (match_operand:SI 3 "s_register_operand" "=r")
9260         (zero_extend:SI
9261          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9262                            (match_operand:SI 2 "s_register_operand" "r")))))
9263    (set (match_operand:SI 0 "s_register_operand" "=r")
9264         (minus:SI (match_dup 1) (match_dup 2)))]
9265   "TARGET_ARM
9266    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9267    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9268    && (GET_CODE (operands[2]) != REG
9269        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9270   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
9271   [(set_attr "type" "load_byte")
9272    (set_attr "predicable" "yes")]
9273 )
9274
9275 (define_insn "*strsi_preinc"
9276   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9277                          (match_operand:SI 2 "index_operand" "rJ")))
9278         (match_operand:SI 3 "s_register_operand" "r"))
9279    (set (match_operand:SI 0 "s_register_operand" "=r")
9280         (plus:SI (match_dup 1) (match_dup 2)))]
9281   "TARGET_ARM
9282    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9283    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9284    && (GET_CODE (operands[2]) != REG
9285        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9286   "str%?\\t%3, [%0, %2]!"
9287   [(set_attr "type" "store1")
9288    (set_attr "predicable" "yes")]
9289 )
9290
9291 (define_insn "*strsi_predec"
9292   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9293                           (match_operand:SI 2 "s_register_operand" "r")))
9294         (match_operand:SI 3 "s_register_operand" "r"))
9295    (set (match_operand:SI 0 "s_register_operand" "=r")
9296         (minus:SI (match_dup 1) (match_dup 2)))]
9297   "TARGET_ARM
9298    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9299    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9300    && (GET_CODE (operands[2]) != REG
9301        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9302   "str%?\\t%3, [%0, -%2]!"
9303   [(set_attr "type" "store1")
9304    (set_attr "predicable" "yes")]
9305 )
9306
9307 (define_insn "*loadsi_preinc"
9308   [(set (match_operand:SI 3 "s_register_operand" "=r")
9309         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9310                          (match_operand:SI 2 "index_operand" "rJ"))))
9311    (set (match_operand:SI 0 "s_register_operand" "=r")
9312         (plus:SI (match_dup 1) (match_dup 2)))]
9313   "TARGET_ARM
9314    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9315    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9316    && (GET_CODE (operands[2]) != REG
9317        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9318   "ldr%?\\t%3, [%0, %2]!"
9319   [(set_attr "type" "load1")
9320    (set_attr "predicable" "yes")]
9321 )
9322
9323 (define_insn "*loadsi_predec"
9324   [(set (match_operand:SI 3 "s_register_operand" "=r")
9325         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9326                           (match_operand:SI 2 "s_register_operand" "r"))))
9327    (set (match_operand:SI 0 "s_register_operand" "=r")
9328         (minus:SI (match_dup 1) (match_dup 2)))]
9329   "TARGET_ARM
9330    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9331    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9332    && (GET_CODE (operands[2]) != REG
9333        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9334   "ldr%?\\t%3, [%0, -%2]!"
9335   [(set_attr "type" "load1")
9336    (set_attr "predicable" "yes")]
9337 )
9338
9339 (define_insn "*strqi_shiftpreinc"
9340   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9341                           [(match_operand:SI 3 "s_register_operand" "r")
9342                            (match_operand:SI 4 "const_shift_operand" "n")])
9343                          (match_operand:SI 1 "s_register_operand" "0")))
9344         (match_operand:QI 5 "s_register_operand" "r"))
9345    (set (match_operand:SI 0 "s_register_operand" "=r")
9346         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9347                  (match_dup 1)))]
9348   "TARGET_ARM
9349    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9350    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9351    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9352   "str%?b\\t%5, [%0, %3%S2]!"
9353   [(set_attr "type" "store1")
9354    (set_attr "predicable" "yes")]
9355 )
9356
9357 (define_insn "*strqi_shiftpredec"
9358   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9359                           (match_operator:SI 2 "shift_operator"
9360                            [(match_operand:SI 3 "s_register_operand" "r")
9361                             (match_operand:SI 4 "const_shift_operand" "n")])))
9362         (match_operand:QI 5 "s_register_operand" "r"))
9363    (set (match_operand:SI 0 "s_register_operand" "=r")
9364         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9365                                                  (match_dup 4)])))]
9366   "TARGET_ARM
9367    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9368    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9369    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9370   "str%?b\\t%5, [%0, -%3%S2]!"
9371   [(set_attr "type" "store1")
9372    (set_attr "predicable" "yes")]
9373 )
9374
9375 (define_insn "*loadqi_shiftpreinc"
9376   [(set (match_operand:QI 5 "s_register_operand" "=r")
9377         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9378                           [(match_operand:SI 3 "s_register_operand" "r")
9379                            (match_operand:SI 4 "const_shift_operand" "n")])
9380                          (match_operand:SI 1 "s_register_operand" "0"))))
9381    (set (match_operand:SI 0 "s_register_operand" "=r")
9382         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9383                  (match_dup 1)))]
9384   "TARGET_ARM
9385    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9386    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9387    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9388   "ldr%?b\\t%5, [%0, %3%S2]!"
9389   [(set_attr "type" "load_byte")
9390    (set_attr "predicable" "yes")]
9391 )
9392
9393 (define_insn "*loadqi_shiftpredec"
9394   [(set (match_operand:QI 5 "s_register_operand" "=r")
9395         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9396                           (match_operator:SI 2 "shift_operator"
9397                            [(match_operand:SI 3 "s_register_operand" "r")
9398                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9399    (set (match_operand:SI 0 "s_register_operand" "=r")
9400         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9401                                                  (match_dup 4)])))]
9402   "TARGET_ARM
9403    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9404    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9405    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9406   "ldr%?b\\t%5, [%0, -%3%S2]!"
9407   [(set_attr "type" "load_byte")
9408    (set_attr "predicable" "yes")]
9409 )
9410
9411 (define_insn "*strsi_shiftpreinc"
9412   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9413                           [(match_operand:SI 3 "s_register_operand" "r")
9414                            (match_operand:SI 4 "const_shift_operand" "n")])
9415                          (match_operand:SI 1 "s_register_operand" "0")))
9416         (match_operand:SI 5 "s_register_operand" "r"))
9417    (set (match_operand:SI 0 "s_register_operand" "=r")
9418         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9419                  (match_dup 1)))]
9420   "TARGET_ARM
9421    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9422    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9423    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9424   "str%?\\t%5, [%0, %3%S2]!"
9425   [(set_attr "type" "store1")
9426    (set_attr "predicable" "yes")]
9427 )
9428
9429 (define_insn "*strsi_shiftpredec"
9430   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9431                           (match_operator:SI 2 "shift_operator"
9432                            [(match_operand:SI 3 "s_register_operand" "r")
9433                             (match_operand:SI 4 "const_shift_operand" "n")])))
9434         (match_operand:SI 5 "s_register_operand" "r"))
9435    (set (match_operand:SI 0 "s_register_operand" "=r")
9436         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9437                                                  (match_dup 4)])))]
9438   "TARGET_ARM
9439    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9440    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9441    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9442   "str%?\\t%5, [%0, -%3%S2]!"
9443   [(set_attr "type" "store1")
9444    (set_attr "predicable" "yes")]
9445 )
9446
9447 (define_insn "*loadsi_shiftpreinc"
9448   [(set (match_operand:SI 5 "s_register_operand" "=r")
9449         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9450                           [(match_operand:SI 3 "s_register_operand" "r")
9451                            (match_operand:SI 4 "const_shift_operand" "n")])
9452                          (match_operand:SI 1 "s_register_operand" "0"))))
9453    (set (match_operand:SI 0 "s_register_operand" "=r")
9454         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9455                  (match_dup 1)))]
9456   "TARGET_ARM
9457    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9458    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9459    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9460   "ldr%?\\t%5, [%0, %3%S2]!"
9461   [(set_attr "type" "load1")
9462    (set_attr "predicable" "yes")]
9463 )
9464
9465 (define_insn "*loadsi_shiftpredec"
9466   [(set (match_operand:SI 5 "s_register_operand" "=r")
9467         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9468                           (match_operator:SI 2 "shift_operator"
9469                            [(match_operand:SI 3 "s_register_operand" "r")
9470                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9471    (set (match_operand:SI 0 "s_register_operand" "=r")
9472         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9473                                                  (match_dup 4)])))]
9474   "TARGET_ARM
9475    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9476    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9477    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9478   "ldr%?\\t%5, [%0, -%3%S2]!"
9479   [(set_attr "type" "load1")
9480    (set_attr "predicable" "yes")])
9481
9482 ; It can also support extended post-inc expressions, but combine doesn't
9483 ; try these....
9484 ; It doesn't seem worth adding peepholes for anything but the most common
9485 ; cases since, unlike combine, the increment must immediately follow the load
9486 ; for this pattern to match.
9487 ; We must watch to see that the source/destination register isn't also the
9488 ; same as the base address register, and that if the index is a register,
9489 ; that it is not the same as the base address register.  In such cases the
9490 ; instruction that we would generate would have UNPREDICTABLE behavior so 
9491 ; we cannot use it.
9492
9493 (define_peephole
9494   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9495         (match_operand:QI 2 "s_register_operand" "r"))
9496    (set (match_dup 0)
9497         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9498   "TARGET_ARM
9499    && (REGNO (operands[2]) != REGNO (operands[0]))
9500    && (GET_CODE (operands[1]) != REG
9501        || (REGNO (operands[1]) != REGNO (operands[0])))"
9502   "str%?b\\t%2, [%0], %1"
9503 )
9504
9505 (define_peephole
9506   [(set (match_operand:QI 0 "s_register_operand" "=r")
9507         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9508    (set (match_dup 1)
9509         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9510   "TARGET_ARM
9511    && REGNO (operands[0]) != REGNO(operands[1])
9512    && (GET_CODE (operands[2]) != REG
9513        || REGNO(operands[0]) != REGNO (operands[2]))"
9514   "ldr%?b\\t%0, [%1], %2"
9515 )
9516
9517 (define_peephole
9518   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9519         (match_operand:SI 2 "s_register_operand" "r"))
9520    (set (match_dup 0)
9521         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9522   "TARGET_ARM
9523    && (REGNO (operands[2]) != REGNO (operands[0]))
9524    && (GET_CODE (operands[1]) != REG
9525        || (REGNO (operands[1]) != REGNO (operands[0])))"
9526   "str%?\\t%2, [%0], %1"
9527 )
9528
9529 (define_peephole
9530   [(set (match_operand:SI 0 "s_register_operand" "=r")
9531         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9532    (set (match_dup 1)
9533         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9534   "TARGET_ARM
9535    && REGNO (operands[0]) != REGNO(operands[1])
9536    && (GET_CODE (operands[2]) != REG
9537        || REGNO(operands[0]) != REGNO (operands[2]))"
9538   "ldr%?\\t%0, [%1], %2"
9539 )
9540
9541 (define_peephole
9542   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9543                          (match_operand:SI 1 "index_operand" "rJ")))
9544         (match_operand:QI 2 "s_register_operand" "r"))
9545    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
9546   "TARGET_ARM
9547    && (REGNO (operands[2]) != REGNO (operands[0]))
9548    && (GET_CODE (operands[1]) != REG
9549        || (REGNO (operands[1]) != REGNO (operands[0])))"
9550   "str%?b\\t%2, [%0, %1]!"
9551 )
9552
9553 (define_peephole
9554   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9555                           [(match_operand:SI 0 "s_register_operand" "r")
9556                            (match_operand:SI 1 "const_int_operand" "n")])
9557                          (match_operand:SI 2 "s_register_operand" "+r")))
9558         (match_operand:QI 3 "s_register_operand" "r"))
9559    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9560                                (match_dup 2)))]
9561   "TARGET_ARM
9562    && (REGNO (operands[3]) != REGNO (operands[2]))
9563    && (REGNO (operands[0]) != REGNO (operands[2]))"
9564   "str%?b\\t%3, [%2, %0%S4]!"
9565 )
9566
9567 ; This pattern is never tried by combine, so do it as a peephole
9568
9569 (define_peephole2
9570   [(set (match_operand:SI 0 "arm_general_register_operand" "")
9571         (match_operand:SI 1 "arm_general_register_operand" ""))
9572    (set (reg:CC CC_REGNUM)
9573         (compare:CC (match_dup 1) (const_int 0)))]
9574   "TARGET_ARM"
9575   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9576               (set (match_dup 0) (match_dup 1))])]
9577   ""
9578 )
9579
9580 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9581 ; reversed, check that the memory references aren't volatile.
9582
9583 (define_peephole
9584   [(set (match_operand:SI 0 "s_register_operand" "=r")
9585         (match_operand:SI 4 "memory_operand" "m"))
9586    (set (match_operand:SI 1 "s_register_operand" "=r")
9587         (match_operand:SI 5 "memory_operand" "m"))
9588    (set (match_operand:SI 2 "s_register_operand" "=r")
9589         (match_operand:SI 6 "memory_operand" "m"))
9590    (set (match_operand:SI 3 "s_register_operand" "=r")
9591         (match_operand:SI 7 "memory_operand" "m"))]
9592   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9593   "*
9594   return emit_ldm_seq (operands, 4);
9595   "
9596 )
9597
9598 (define_peephole
9599   [(set (match_operand:SI 0 "s_register_operand" "=r")
9600         (match_operand:SI 3 "memory_operand" "m"))
9601    (set (match_operand:SI 1 "s_register_operand" "=r")
9602         (match_operand:SI 4 "memory_operand" "m"))
9603    (set (match_operand:SI 2 "s_register_operand" "=r")
9604         (match_operand:SI 5 "memory_operand" "m"))]
9605   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9606   "*
9607   return emit_ldm_seq (operands, 3);
9608   "
9609 )
9610
9611 (define_peephole
9612   [(set (match_operand:SI 0 "s_register_operand" "=r")
9613         (match_operand:SI 2 "memory_operand" "m"))
9614    (set (match_operand:SI 1 "s_register_operand" "=r")
9615         (match_operand:SI 3 "memory_operand" "m"))]
9616   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9617   "*
9618   return emit_ldm_seq (operands, 2);
9619   "
9620 )
9621
9622 (define_peephole
9623   [(set (match_operand:SI 4 "memory_operand" "=m")
9624         (match_operand:SI 0 "s_register_operand" "r"))
9625    (set (match_operand:SI 5 "memory_operand" "=m")
9626         (match_operand:SI 1 "s_register_operand" "r"))
9627    (set (match_operand:SI 6 "memory_operand" "=m")
9628         (match_operand:SI 2 "s_register_operand" "r"))
9629    (set (match_operand:SI 7 "memory_operand" "=m")
9630         (match_operand:SI 3 "s_register_operand" "r"))]
9631   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9632   "*
9633   return emit_stm_seq (operands, 4);
9634   "
9635 )
9636
9637 (define_peephole
9638   [(set (match_operand:SI 3 "memory_operand" "=m")
9639         (match_operand:SI 0 "s_register_operand" "r"))
9640    (set (match_operand:SI 4 "memory_operand" "=m")
9641         (match_operand:SI 1 "s_register_operand" "r"))
9642    (set (match_operand:SI 5 "memory_operand" "=m")
9643         (match_operand:SI 2 "s_register_operand" "r"))]
9644   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9645   "*
9646   return emit_stm_seq (operands, 3);
9647   "
9648 )
9649
9650 (define_peephole
9651   [(set (match_operand:SI 2 "memory_operand" "=m")
9652         (match_operand:SI 0 "s_register_operand" "r"))
9653    (set (match_operand:SI 3 "memory_operand" "=m")
9654         (match_operand:SI 1 "s_register_operand" "r"))]
9655   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9656   "*
9657   return emit_stm_seq (operands, 2);
9658   "
9659 )
9660
9661 (define_split
9662   [(set (match_operand:SI 0 "s_register_operand" "")
9663         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9664                        (const_int 0))
9665                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9666                          [(match_operand:SI 3 "s_register_operand" "")
9667                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
9668    (clobber (match_operand:SI 5 "s_register_operand" ""))]
9669   "TARGET_ARM"
9670   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9671    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9672                               (match_dup 5)))]
9673   ""
9674 )
9675
9676 ;; This split can be used because CC_Z mode implies that the following
9677 ;; branch will be an equality, or an unsigned inequality, so the sign
9678 ;; extension is not needed.
9679
9680 (define_split
9681   [(set (reg:CC_Z CC_REGNUM)
9682         (compare:CC_Z
9683          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9684                     (const_int 24))
9685          (match_operand 1 "const_int_operand" "")))
9686    (clobber (match_scratch:SI 2 ""))]
9687   "TARGET_ARM
9688    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9689        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9690   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9691    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9692   "
9693   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9694   "
9695 )
9696
9697 (define_expand "prologue"
9698   [(clobber (const_int 0))]
9699   "TARGET_EITHER"
9700   "if (TARGET_ARM)
9701      arm_expand_prologue ();
9702    else
9703      thumb_expand_prologue ();
9704   DONE;
9705   "
9706 )
9707
9708 (define_expand "epilogue"
9709   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9710   "TARGET_EITHER"
9711   "
9712   if (TARGET_THUMB)
9713     thumb_expand_epilogue ();
9714   else if (USE_RETURN_INSN (FALSE))
9715     {
9716       emit_jump_insn (gen_return ());
9717       DONE;
9718     }
9719   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9720         gen_rtvec (1,
9721                 gen_rtx_RETURN (VOIDmode)),
9722         VUNSPEC_EPILOGUE));
9723   DONE;
9724   "
9725 )
9726
9727 ;; Note - although unspec_volatile's USE all hard registers,
9728 ;; USEs are ignored after relaod has completed.  Thus we need
9729 ;; to add an unspec of the link register to ensure that flow
9730 ;; does not think that it is unused by the sibcall branch that
9731 ;; will replace the standard function epilogue.
9732 (define_insn "sibcall_epilogue"
9733   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9734               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9735   "TARGET_ARM"
9736   "*
9737   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9738     return output_return_instruction (const_true_rtx, FALSE, FALSE);
9739   return arm_output_epilogue (next_nonnote_insn (insn));
9740   "
9741 ;; Length is absolute worst case
9742   [(set_attr "length" "44")
9743    (set_attr "type" "block")
9744    ;; We don't clobber the conditions, but the potential length of this
9745    ;; operation is sufficient to make conditionalizing the sequence 
9746    ;; unlikely to be profitable.
9747    (set_attr "conds" "clob")]
9748 )
9749
9750 (define_insn "*epilogue_insns"
9751   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9752   "TARGET_EITHER"
9753   "*
9754   if (TARGET_ARM)
9755     return arm_output_epilogue (NULL);
9756   else /* TARGET_THUMB */
9757     return thumb_unexpanded_epilogue ();
9758   "
9759   ; Length is absolute worst case
9760   [(set_attr "length" "44")
9761    (set_attr "type" "block")
9762    ;; We don't clobber the conditions, but the potential length of this
9763    ;; operation is sufficient to make conditionalizing the sequence 
9764    ;; unlikely to be profitable.
9765    (set_attr "conds" "clob")]
9766 )
9767
9768 (define_expand "eh_epilogue"
9769   [(use (match_operand:SI 0 "register_operand" ""))
9770    (use (match_operand:SI 1 "register_operand" ""))
9771    (use (match_operand:SI 2 "register_operand" ""))]
9772   "TARGET_EITHER"
9773   "
9774   {
9775     cfun->machine->eh_epilogue_sp_ofs = operands[1];
9776     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9777       {
9778         rtx ra = gen_rtx_REG (Pmode, 2);
9779
9780         emit_move_insn (ra, operands[2]);
9781         operands[2] = ra;
9782       }
9783     /* This is a hack -- we may have crystalized the function type too
9784        early.  */
9785     cfun->machine->func_type = 0;
9786   }"
9787 )
9788
9789 ;; This split is only used during output to reduce the number of patterns
9790 ;; that need assembler instructions adding to them.  We allowed the setting
9791 ;; of the conditions to be implicit during rtl generation so that
9792 ;; the conditional compare patterns would work.  However this conflicts to
9793 ;; some extent with the conditional data operations, so we have to split them
9794 ;; up again here.
9795
9796 (define_split
9797   [(set (match_operand:SI 0 "s_register_operand" "")
9798         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9799                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9800                          (match_dup 0)
9801                          (match_operand 4 "" "")))
9802    (clobber (reg:CC CC_REGNUM))]
9803   "TARGET_ARM && reload_completed"
9804   [(set (match_dup 5) (match_dup 6))
9805    (cond_exec (match_dup 7)
9806               (set (match_dup 0) (match_dup 4)))]
9807   "
9808   {
9809     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9810                                              operands[2], operands[3]);
9811     enum rtx_code rc = GET_CODE (operands[1]);
9812
9813     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9814     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9815     if (mode == CCFPmode || mode == CCFPEmode)
9816       rc = reverse_condition_maybe_unordered (rc);
9817     else
9818       rc = reverse_condition (rc);
9819
9820     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9821   }"
9822 )
9823
9824 (define_split
9825   [(set (match_operand:SI 0 "s_register_operand" "")
9826         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9827                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9828                          (match_operand 4 "" "")
9829                          (match_dup 0)))
9830    (clobber (reg:CC CC_REGNUM))]
9831   "TARGET_ARM && reload_completed"
9832   [(set (match_dup 5) (match_dup 6))
9833    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9834               (set (match_dup 0) (match_dup 4)))]
9835   "
9836   {
9837     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9838                                              operands[2], operands[3]);
9839
9840     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9841     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9842   }"
9843 )
9844
9845 (define_split
9846   [(set (match_operand:SI 0 "s_register_operand" "")
9847         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9848                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9849                          (match_operand 4 "" "")
9850                          (match_operand 5 "" "")))
9851    (clobber (reg:CC CC_REGNUM))]
9852   "TARGET_ARM && reload_completed"
9853   [(set (match_dup 6) (match_dup 7))
9854    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9855               (set (match_dup 0) (match_dup 4)))
9856    (cond_exec (match_dup 8)
9857               (set (match_dup 0) (match_dup 5)))]
9858   "
9859   {
9860     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9861                                              operands[2], operands[3]);
9862     enum rtx_code rc = GET_CODE (operands[1]);
9863
9864     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9865     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9866     if (mode == CCFPmode || mode == CCFPEmode)
9867       rc = reverse_condition_maybe_unordered (rc);
9868     else
9869       rc = reverse_condition (rc);
9870
9871     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9872   }"
9873 )
9874
9875 (define_split
9876   [(set (match_operand:SI 0 "s_register_operand" "")
9877         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9878                           [(match_operand:SI 2 "s_register_operand" "")
9879                            (match_operand:SI 3 "arm_add_operand" "")])
9880                          (match_operand:SI 4 "arm_rhs_operand" "")
9881                          (not:SI
9882                           (match_operand:SI 5 "s_register_operand" ""))))
9883    (clobber (reg:CC CC_REGNUM))]
9884   "TARGET_ARM && reload_completed"
9885   [(set (match_dup 6) (match_dup 7))
9886    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9887               (set (match_dup 0) (match_dup 4)))
9888    (cond_exec (match_dup 8)
9889               (set (match_dup 0) (not:SI (match_dup 5))))]
9890   "
9891   {
9892     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9893                                              operands[2], operands[3]);
9894     enum rtx_code rc = GET_CODE (operands[1]);
9895
9896     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9897     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9898     if (mode == CCFPmode || mode == CCFPEmode)
9899       rc = reverse_condition_maybe_unordered (rc);
9900     else
9901       rc = reverse_condition (rc);
9902
9903     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9904   }"
9905 )
9906
9907 (define_insn "*cond_move_not"
9908   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9909         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9910                           [(match_operand 3 "cc_register" "") (const_int 0)])
9911                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9912                          (not:SI
9913                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
9914   "TARGET_ARM"
9915   "@
9916    mvn%D4\\t%0, %2
9917    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
9918   [(set_attr "conds" "use")
9919    (set_attr "length" "4,8")]
9920 )
9921
9922 ;; The next two patterns occur when an AND operation is followed by a
9923 ;; scc insn sequence 
9924
9925 (define_insn "*sign_extract_onebit"
9926   [(set (match_operand:SI 0 "s_register_operand" "=r")
9927         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9928                          (const_int 1)
9929                          (match_operand:SI 2 "const_int_operand" "n")))
9930     (clobber (reg:CC CC_REGNUM))]
9931   "TARGET_ARM"
9932   "*
9933     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9934     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
9935     return \"mvnne\\t%0, #0\";
9936   "
9937   [(set_attr "conds" "clob")
9938    (set_attr "length" "8")]
9939 )
9940
9941 (define_insn "*not_signextract_onebit"
9942   [(set (match_operand:SI 0 "s_register_operand" "=r")
9943         (not:SI
9944          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9945                           (const_int 1)
9946                           (match_operand:SI 2 "const_int_operand" "n"))))
9947    (clobber (reg:CC CC_REGNUM))]
9948   "TARGET_ARM"
9949   "*
9950     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9951     output_asm_insn (\"tst\\t%1, %2\", operands);
9952     output_asm_insn (\"mvneq\\t%0, #0\", operands);
9953     return \"movne\\t%0, #0\";
9954   "
9955   [(set_attr "conds" "clob")
9956    (set_attr "length" "12")]
9957 )
9958
9959 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
9960 ;; expressions.  For simplicity, the first register is also in the unspec
9961 ;; part.
9962 (define_insn "*push_multi"
9963   [(match_parallel 2 "multi_register_push"
9964     [(set (match_operand:BLK 0 "memory_operand" "=m")
9965           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
9966                       UNSPEC_PUSH_MULT))])]
9967   "TARGET_ARM"
9968   "*
9969   {
9970     int num_saves = XVECLEN (operands[2], 0);
9971      
9972     /* For the StrongARM at least it is faster to
9973        use STR to store only a single register.  */
9974     if (num_saves == 1)
9975       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9976     else
9977       {
9978         int i;
9979         char pattern[100];
9980
9981         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9982
9983         for (i = 1; i < num_saves; i++)
9984           {
9985             strcat (pattern, \", %|\");
9986             strcat (pattern,
9987                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9988           }
9989
9990         strcat (pattern, \"}\");
9991         output_asm_insn (pattern, operands);
9992       }
9993
9994     return \"\";
9995   }"
9996   [(set_attr "type" "store4")]
9997 )
9998
9999 (define_insn "stack_tie"
10000   [(set (mem:BLK (scratch))
10001         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
10002                      (match_operand:SI 1 "s_register_operand" "r")]
10003                     UNSPEC_PRLG_STK))]
10004   ""
10005   ""
10006   [(set_attr "length" "0")]
10007 )
10008
10009 ;; Similarly for the floating point registers
10010 (define_insn "*push_fp_multi"
10011   [(match_parallel 2 "multi_register_push"
10012     [(set (match_operand:BLK 0 "memory_operand" "=m")
10013           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10014                       UNSPEC_PUSH_MULT))])]
10015   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
10016   "*
10017   {
10018     char pattern[100];
10019
10020     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10021     output_asm_insn (pattern, operands);
10022     return \"\";
10023   }"
10024   [(set_attr "type" "f_store")]
10025 )
10026
10027 ;; Special patterns for dealing with the constant pool
10028
10029 (define_insn "align_4"
10030   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10031   "TARGET_EITHER"
10032   "*
10033   assemble_align (32);
10034   return \"\";
10035   "
10036 )
10037
10038 (define_insn "align_8"
10039   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10040   "TARGET_EITHER"
10041   "*
10042   assemble_align (64);
10043   return \"\";
10044   "
10045 )
10046
10047 (define_insn "consttable_end"
10048   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10049   "TARGET_EITHER"
10050   "*
10051   making_const_table = FALSE;
10052   return \"\";
10053   "
10054 )
10055
10056 (define_insn "consttable_1"
10057   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10058   "TARGET_THUMB"
10059   "*
10060   making_const_table = TRUE;
10061   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10062   assemble_zeros (3);
10063   return \"\";
10064   "
10065   [(set_attr "length" "4")]
10066 )
10067
10068 (define_insn "consttable_2"
10069   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10070   "TARGET_THUMB"
10071   "*
10072   making_const_table = TRUE;
10073   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10074   assemble_zeros (2);
10075   return \"\";
10076   "
10077   [(set_attr "length" "4")]
10078 )
10079
10080 (define_insn "consttable_4"
10081   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10082   "TARGET_EITHER"
10083   "*
10084   {
10085     making_const_table = TRUE;
10086     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10087       {
10088       case MODE_FLOAT:
10089       {
10090         REAL_VALUE_TYPE r;
10091         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10092         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10093         break;
10094       }
10095       default:
10096         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
10097         break;
10098       }
10099     return \"\";
10100   }"
10101   [(set_attr "length" "4")]
10102 )
10103
10104 (define_insn "consttable_8"
10105   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10106   "TARGET_EITHER"
10107   "*
10108   {
10109     making_const_table = TRUE;
10110     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10111       {
10112        case MODE_FLOAT:
10113         {
10114           REAL_VALUE_TYPE r;
10115           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10116           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10117           break;
10118         }
10119       default:
10120         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10121         break;
10122       }
10123     return \"\";
10124   }"
10125   [(set_attr "length" "8")]
10126 )
10127
10128 ;; Miscellaneous Thumb patterns
10129
10130 (define_expand "tablejump"
10131   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10132               (use (label_ref (match_operand 1 "" "")))])]
10133   "TARGET_THUMB"
10134   "
10135   if (flag_pic)
10136     {
10137       /* Hopefully, CSE will eliminate this copy.  */
10138       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10139       rtx reg2 = gen_reg_rtx (SImode);
10140
10141       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10142       operands[0] = reg2;
10143     }
10144   "
10145 )
10146
10147 ;; NB never uses BX.
10148 (define_insn "*thumb_tablejump"
10149   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10150    (use (label_ref (match_operand 1 "" "")))]
10151   "TARGET_THUMB"
10152   "mov\\t%|pc, %0"
10153   [(set_attr "length" "2")]
10154 )
10155
10156 ;; V5 Instructions,
10157
10158 (define_insn "clzsi2"
10159   [(set (match_operand:SI 0 "s_register_operand" "=r")
10160         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10161   "TARGET_ARM && arm_arch5"
10162   "clz%?\\t%0, %1"
10163   [(set_attr "predicable" "yes")])
10164
10165 (define_expand "ffssi2"
10166   [(set (match_operand:SI 0 "s_register_operand" "")
10167         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10168   "TARGET_ARM && arm_arch5"
10169   "
10170   {
10171     rtx t1, t2, t3;
10172
10173     t1 = gen_reg_rtx (SImode);
10174     t2 = gen_reg_rtx (SImode);
10175     t3 = gen_reg_rtx (SImode);
10176
10177     emit_insn (gen_negsi2 (t1, operands[1]));
10178     emit_insn (gen_andsi3 (t2, operands[1], t1));
10179     emit_insn (gen_clzsi2 (t3, t2));
10180     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10181     DONE;
10182   }"
10183 )
10184
10185 (define_expand "ctzsi2"
10186   [(set (match_operand:SI 0 "s_register_operand" "")
10187         (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10188   "TARGET_ARM && arm_arch5"
10189   "
10190   {
10191     rtx t1, t2, t3;
10192
10193     t1 = gen_reg_rtx (SImode);
10194     t2 = gen_reg_rtx (SImode);
10195     t3 = gen_reg_rtx (SImode);
10196
10197     emit_insn (gen_negsi2 (t1, operands[1]));
10198     emit_insn (gen_andsi3 (t2, operands[1], t1));
10199     emit_insn (gen_clzsi2 (t3, t2));
10200     emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10201     DONE;
10202   }"
10203 )
10204
10205 ;; V5E instructions.
10206
10207 (define_insn "prefetch"
10208   [(prefetch (match_operand:SI 0 "address_operand" "p")
10209              (match_operand:SI 1 "" "")
10210              (match_operand:SI 2 "" ""))]
10211   "TARGET_ARM && arm_arch5e"
10212   "pld\\t%a0")
10213
10214 ;; General predication pattern
10215
10216 (define_cond_exec
10217   [(match_operator 0 "arm_comparison_operator"
10218     [(match_operand 1 "cc_register" "")
10219      (const_int 0)])]
10220   "TARGET_ARM"
10221   ""
10222 )
10223
10224 (define_insn "prologue_use"
10225   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10226   ""
10227   "%@ %0 needed for prologue"
10228 )
10229
10230 ;; Load the FPA co-processor patterns
10231 (include "fpa.md")
10232 ;; Load the Maverick co-processor patterns
10233 (include "cirrus.md")
10234 ;; Load the Intel Wireless Multimedia Extension patterns
10235 (include "iwmmxt.md")
10236 ;; Load the VFP co-processor patterns
10237 (include "vfp.md")
10238