OSDN Git Service

* arm.c (arm_const_double_inline_cost): Handle any constant by
[pf3gnuchains/gcc-fork.git] / gcc / config / arm / arm.md
1 ;;- Machine description for ARM for GNU compiler
2 ;;  Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;;  2001, 2002, 2003, 2004, 2005  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   [(R0_REGNUM        0)         ; First CORE register
34    (IP_REGNUM       12)         ; Scratch register
35    (SP_REGNUM       13)         ; Stack pointer
36    (LR_REGNUM       14)         ; Return address register
37    (PC_REGNUM       15)         ; Program counter
38    (CC_REGNUM       24)         ; Condition code pseudo register
39    (LAST_ARM_REGNUM 15)         ;
40    (FPA_F0_REGNUM   16)         ; FIRST_FPA_REGNUM
41    (FPA_F7_REGNUM   23)         ; LAST_FPA_REGNUM
42   ]
43 )
44 ;; 3rd operand to select_dominance_cc_mode
45 (define_constants
46   [(DOM_CC_X_AND_Y  0)
47    (DOM_CC_NX_OR_Y  1)
48    (DOM_CC_X_OR_Y   2)
49   ]
50 )
51
52 ;; UNSPEC Usage:
53 ;; Note: sin and cos are no-longer used.
54
55 (define_constants
56   [(UNSPEC_SIN       0) ; `sin' operation (MODE_FLOAT):
57                         ;   operand 0 is the result,
58                         ;   operand 1 the parameter.
59    (UNPSEC_COS       1) ; `cos' operation (MODE_FLOAT):
60                         ;   operand 0 is the result,
61                         ;   operand 1 the parameter.
62    (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
63                         ;   operand 0 is the first register,
64                         ;   subsequent registers are in parallel (use ...)
65                         ;   expressions.
66    (UNSPEC_PIC_SYM   3) ; A symbol that has been treated properly for pic
67                         ;   usage, that is, we will add the pic_register
68                         ;   value to it before trying to dereference it.
69    (UNSPEC_PIC_BASE  4) ; Adding the PC value to the offset to the
70                         ;   GLOBAL_OFFSET_TABLE.  The operation is fully
71                         ;   described by the RTL but must be wrapped to
72                         ;   prevent combine from trying to rip it apart.
73    (UNSPEC_PRLG_STK  5) ; A special barrier that prevents frame accesses 
74                         ;   being scheduled before the stack adjustment insn.
75    (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
76                         ; this unspec is used to prevent the deletion of
77                         ; instructions setting registers for EH handling
78                         ; and stack frame generation.  Operand 0 is the
79                         ; register to "use".
80    (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
81    (UNSPEC_WSHUFH    8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
82    (UNSPEC_WACC      9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
83    (UNSPEC_TMOVMSK  10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
84    (UNSPEC_WSAD     11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
85    (UNSPEC_WSADZ    12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
86    (UNSPEC_WMACS    13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
87    (UNSPEC_WMACU    14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
88    (UNSPEC_WMACSZ   15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
89    (UNSPEC_WMACUZ   16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
90    (UNSPEC_CLRDI    17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
91    (UNSPEC_WMADDS   18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
92    (UNSPEC_WMADDU   19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
93   ]
94 )
95
96 ;; UNSPEC_VOLATILE Usage:
97
98 (define_constants
99   [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
100                         ;   insn in the code.
101    (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
102                         ;   instruction epilogue sequence that isn't expanded
103                         ;   into normal RTL.  Used for both normal and sibcall
104                         ;   epilogues.
105    (VUNSPEC_ALIGN    2) ; `align' insn.  Used at the head of a minipool table 
106                         ;   for inlined constants.
107    (VUNSPEC_POOL_END 3) ; `end-of-table'.  Used to mark the end of a minipool
108                         ;   table.
109    (VUNSPEC_POOL_1   4) ; `pool-entry(1)'.  An entry in the constant pool for
110                         ;   an 8-bit object.
111    (VUNSPEC_POOL_2   5) ; `pool-entry(2)'.  An entry in the constant pool for
112                         ;   a 16-bit object.
113    (VUNSPEC_POOL_4   6) ; `pool-entry(4)'.  An entry in the constant pool for
114                         ;   a 32-bit object.
115    (VUNSPEC_POOL_8   7) ; `pool-entry(8)'.  An entry in the constant pool for
116                         ;   a 64-bit object.
117    (VUNSPEC_TMRC     8) ; Used by the iWMMXt TMRC instruction.
118    (VUNSPEC_TMCR     9) ; Used by the iWMMXt TMCR instruction.
119    (VUNSPEC_ALIGN8   10) ; 8-byte alignment version of VUNSPEC_ALIGN
120    (VUNSPEC_WCMP_EQ  11) ; Used by the iWMMXt WCMPEQ instructions
121    (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
122    (VUNSPEC_WCMP_GT  13) ; Used by the iwMMXT WCMPGT instructions
123    (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
124                          ; handling.
125   ]
126 )
127 \f
128 ;;---------------------------------------------------------------------------
129 ;; Attributes
130
131 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
132 ; generating ARM code.  This is used to control the length of some insn
133 ; patterns that share the same RTL in both ARM and Thumb code.
134 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
135
136 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
137 ; scheduling decisions for the load unit and the multiplier.
138 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
139
140 ; IS_XSCALE is set to 'yes' when compiling for XScale.
141 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
142
143 ;; Operand number of an input operand that is shifted.  Zero if the
144 ;; given instruction does not shift one of its input operands.
145 (define_attr "shift" "" (const_int 0))
146
147 ; Floating Point Unit.  If we only have floating point emulation, then there
148 ; is no point in scheduling the floating point insns.  (Well, for best
149 ; performance we should try and group them together).
150 (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
151   (const (symbol_ref "arm_fpu_attr")))
152
153 ; LENGTH of an instruction (in bytes)
154 (define_attr "length" "" (const_int 4))
155
156 ; POOL_RANGE is how far away from a constant pool entry that this insn
157 ; can be placed.  If the distance is zero, then this insn will never
158 ; reference the pool.
159 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
160 ; before its address.
161 (define_attr "pool_range" "" (const_int 0))
162 (define_attr "neg_pool_range" "" (const_int 0))
163
164 ; An assembler sequence may clobber the condition codes without us knowing.
165 ; If such an insn references the pool, then we have no way of knowing how,
166 ; so use the most conservative value for pool_range.
167 (define_asm_attributes
168  [(set_attr "conds" "clob")
169   (set_attr "length" "4")
170   (set_attr "pool_range" "250")])
171
172 ;; The instruction used to implement a particular pattern.  This
173 ;; information is used by pipeline descriptions to provide accurate
174 ;; scheduling information.
175
176 (define_attr "insn"
177         "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals,smlawy,smuad,smuadx,smlad,smladx,smusd,smusdx,smlsd,smlsdx,smmul,smmulr,other"
178         (const_string "other"))
179
180 ; TYPE attribute is used to detect floating point instructions which, if
181 ; running on a co-processor can run in parallel with other, basic instructions
182 ; If write-buffer scheduling is enabled then it can also be used in the
183 ; scheduling of writes.
184
185 ; Classification of each insn
186 ; alu           any alu  instruction that doesn't hit memory or fp
187 ;               regs or have a shifted source operand
188 ; alu_shift     any data instruction that doesn't hit memory or fp
189 ;               regs, but has a source operand shifted by a constant
190 ; alu_shift_reg any data instruction that doesn't hit memory or fp
191 ;               regs, but has a source operand shifted by a register value
192 ; mult          a multiply instruction
193 ; block         blockage insn, this blocks all functional units
194 ; float         a floating point arithmetic operation (subject to expansion)
195 ; fdivd         DFmode floating point division
196 ; fdivs         SFmode floating point division
197 ; fmul          Floating point multiply
198 ; ffmul         Fast floating point multiply
199 ; farith        Floating point arithmetic (4 cycle)
200 ; ffarith       Fast floating point arithmetic (2 cycle)
201 ; float_em      a floating point arithmetic operation that is normally emulated
202 ;               even on a machine with an fpa.
203 ; f_load        a floating point load from memory
204 ; f_store       a floating point store to memory
205 ; f_mem_r       a transfer of a floating point register to a real reg via mem
206 ; r_mem_f       the reverse of f_mem_r
207 ; f_2_r         fast transfer float to arm (no memory needed)
208 ; r_2_f         fast transfer arm to float
209 ; branch        a branch
210 ; call          a subroutine call
211 ; load_byte     load byte(s) from memory to arm registers
212 ; load1         load 1 word from memory to arm registers
213 ; load2         load 2 words from memory to arm registers
214 ; load3         load 3 words from memory to arm registers
215 ; load4         load 4 words from memory to arm registers
216 ; store         store 1 word to memory from arm registers
217 ; store2        store 2 words
218 ; store3        store 3 words
219 ; store4        store 4 (or more) words
220 ;  Additions for Cirrus Maverick co-processor:
221 ; mav_farith    Floating point arithmetic (4 cycle)
222 ; mav_dmult     Double multiplies (7 cycle)
223 ;
224 (define_attr "type"
225         "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,float_em,f_load,f_store,f_mem_r,r_mem_f,f_2_r,r_2_f,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult" 
226         (if_then_else 
227          (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
228          (const_string "mult")
229          (const_string "alu")))
230
231 ; Load scheduling, set from the arm_ld_sched variable
232 ; initialized by arm_override_options() 
233 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
234
235 ; condition codes: this one is used by final_prescan_insn to speed up
236 ; conditionalizing instructions.  It saves having to scan the rtl to see if
237 ; it uses or alters the condition codes.
238
239 ; USE means that the condition codes are used by the insn in the process of
240 ;   outputting code, this means (at present) that we can't use the insn in
241 ;   inlined branches
242 ;
243 ; SET means that the purpose of the insn is to set the condition codes in a
244 ;   well defined manner.
245 ;
246 ; CLOB means that the condition codes are altered in an undefined manner, if
247 ;   they are altered at all
248 ;
249 ; JUMP_CLOB is used when the condition cannot be represented by a single
250 ;   instruction (UNEQ and LTGT).  These cannot be predicated.
251 ;
252 ; NOCOND means that the condition codes are neither altered nor affect the
253 ;   output of this insn
254
255 (define_attr "conds" "use,set,clob,jump_clob,nocond"
256         (if_then_else (eq_attr "type" "call")
257          (const_string "clob")
258          (const_string "nocond")))
259
260 ; Predicable means that the insn can be conditionally executed based on
261 ; an automatically added predicate (additional patterns are generated by 
262 ; gen...).  We default to 'no' because no Thumb patterns match this rule
263 ; and not all ARM patterns do.
264 (define_attr "predicable" "no,yes" (const_string "no"))
265
266 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
267 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
268 ; suffer blockages enough to warrant modelling this (and it can adversely
269 ; affect the schedule).
270 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
271
272 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
273 ; to stall the processor.  Used with model_wbuf above.
274 (define_attr "write_conflict" "no,yes"
275   (if_then_else (eq_attr "type"
276                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
277                 (const_string "yes")
278                 (const_string "no")))
279
280 ; Classify the insns into those that take one cycle and those that take more
281 ; than one on the main cpu execution unit.
282 (define_attr "core_cycles" "single,multi"
283   (if_then_else (eq_attr "type"
284                  "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
285                 (const_string "single")
286                 (const_string "multi")))
287
288 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
289 ;; distant label.  Only applicable to Thumb code.
290 (define_attr "far_jump" "yes,no" (const_string "no"))
291
292
293 ;;---------------------------------------------------------------------------
294 ;; Mode macros
295
296 ; A list of modes that are exactly 64 bits in size.  We use this to expand
297 ; some splits that are the same for all modes when operating on ARM 
298 ; registers.
299 (define_mode_macro ANY64 [DI DF V8QI V4HI V2SI V2SF])
300
301 ;;---------------------------------------------------------------------------
302 ;; Predicates
303
304 (include "predicates.md")
305
306 ;;---------------------------------------------------------------------------
307 ;; Pipeline descriptions
308
309 ;; Processor type.  This is created automatically from arm-cores.def.
310 (include "arm-tune.md")
311
312 ;; True if the generic scheduling description should be used.
313
314 (define_attr "generic_sched" "yes,no"
315   (const (if_then_else 
316           (eq_attr "tune" "arm926ejs,arm1026ejs,arm1136js,arm1136jfs") 
317           (const_string "no")
318           (const_string "yes"))))
319
320 (include "arm-generic.md")
321 (include "arm926ejs.md")
322 (include "arm1026ejs.md")
323 (include "arm1136jfs.md")
324
325 \f
326 ;;---------------------------------------------------------------------------
327 ;; Insn patterns
328 ;;
329 ;; Addition insns.
330
331 ;; Note: For DImode insns, there is normally no reason why operands should
332 ;; not be in the same register, what we don't want is for something being
333 ;; written to partially overlap something that is an input.
334 ;; Cirrus 64bit additions should not be split because we have a native
335 ;; 64bit addition instructions.
336
337 (define_expand "adddi3"
338  [(parallel
339    [(set (match_operand:DI           0 "s_register_operand" "")
340           (plus:DI (match_operand:DI 1 "s_register_operand" "")
341                    (match_operand:DI 2 "s_register_operand" "")))
342     (clobber (reg:CC CC_REGNUM))])]
343   "TARGET_EITHER"
344   "
345   if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
346     {
347       if (!cirrus_fp_register (operands[0], DImode))
348         operands[0] = force_reg (DImode, operands[0]);
349       if (!cirrus_fp_register (operands[1], DImode))
350         operands[1] = force_reg (DImode, operands[1]);
351       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
352       DONE;
353     }
354
355   if (TARGET_THUMB)
356     {
357       if (GET_CODE (operands[1]) != REG)
358         operands[1] = force_reg (SImode, operands[1]);
359       if (GET_CODE (operands[2]) != REG)
360         operands[2] = force_reg (SImode, operands[2]);
361      }
362   "
363 )
364
365 (define_insn "*thumb_adddi3"
366   [(set (match_operand:DI          0 "register_operand" "=l")
367         (plus:DI (match_operand:DI 1 "register_operand" "%0")
368                  (match_operand:DI 2 "register_operand" "l")))
369    (clobber (reg:CC CC_REGNUM))
370   ]
371   "TARGET_THUMB"
372   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
373   [(set_attr "length" "4")]
374 )
375
376 (define_insn_and_split "*arm_adddi3"
377   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
378         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
379                  (match_operand:DI 2 "s_register_operand" "r,  0")))
380    (clobber (reg:CC CC_REGNUM))]
381   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
382   "#"
383   "TARGET_ARM && reload_completed"
384   [(parallel [(set (reg:CC_C CC_REGNUM)
385                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
386                                  (match_dup 1)))
387               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
388    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
389                                (plus:SI (match_dup 4) (match_dup 5))))]
390   "
391   {
392     operands[3] = gen_highpart (SImode, operands[0]);
393     operands[0] = gen_lowpart (SImode, operands[0]);
394     operands[4] = gen_highpart (SImode, operands[1]);
395     operands[1] = gen_lowpart (SImode, operands[1]);
396     operands[5] = gen_highpart (SImode, operands[2]);
397     operands[2] = gen_lowpart (SImode, operands[2]);
398   }"
399   [(set_attr "conds" "clob")
400    (set_attr "length" "8")]
401 )
402
403 (define_insn_and_split "*adddi_sesidi_di"
404   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
405         (plus:DI (sign_extend:DI
406                   (match_operand:SI 2 "s_register_operand" "r,r"))
407                  (match_operand:DI 1 "s_register_operand" "r,0")))
408    (clobber (reg:CC CC_REGNUM))]
409   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
410   "#"
411   "TARGET_ARM && reload_completed"
412   [(parallel [(set (reg:CC_C CC_REGNUM)
413                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
414                                  (match_dup 1)))
415               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
416    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
417                                (plus:SI (ashiftrt:SI (match_dup 2)
418                                                      (const_int 31))
419                                         (match_dup 4))))]
420   "
421   {
422     operands[3] = gen_highpart (SImode, operands[0]);
423     operands[0] = gen_lowpart (SImode, operands[0]);
424     operands[4] = gen_highpart (SImode, operands[1]);
425     operands[1] = gen_lowpart (SImode, operands[1]);
426     operands[2] = gen_lowpart (SImode, operands[2]);
427   }"
428   [(set_attr "conds" "clob")
429    (set_attr "length" "8")]
430 )
431
432 (define_insn_and_split "*adddi_zesidi_di"
433   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
434         (plus:DI (zero_extend:DI
435                   (match_operand:SI 2 "s_register_operand" "r,r"))
436                  (match_operand:DI 1 "s_register_operand" "r,0")))
437    (clobber (reg:CC CC_REGNUM))]
438   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
439   "#"
440   "TARGET_ARM && reload_completed"
441   [(parallel [(set (reg:CC_C CC_REGNUM)
442                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
443                                  (match_dup 1)))
444               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
445    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
446                                (plus:SI (match_dup 4) (const_int 0))))]
447   "
448   {
449     operands[3] = gen_highpart (SImode, operands[0]);
450     operands[0] = gen_lowpart (SImode, operands[0]);
451     operands[4] = gen_highpart (SImode, operands[1]);
452     operands[1] = gen_lowpart (SImode, operands[1]);
453     operands[2] = gen_lowpart (SImode, operands[2]);
454   }"
455   [(set_attr "conds" "clob")
456    (set_attr "length" "8")]
457 )
458
459 (define_expand "addsi3"
460   [(set (match_operand:SI          0 "s_register_operand" "")
461         (plus:SI (match_operand:SI 1 "s_register_operand" "")
462                  (match_operand:SI 2 "reg_or_int_operand" "")))]
463   "TARGET_EITHER"
464   "
465   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
466     {
467       arm_split_constant (PLUS, SImode, NULL_RTX,
468                           INTVAL (operands[2]), operands[0], operands[1],
469                           optimize && !no_new_pseudos);
470       DONE;
471     }
472   "
473 )
474
475 ; If there is a scratch available, this will be faster than synthesizing the
476 ; addition.
477 (define_peephole2
478   [(match_scratch:SI 3 "r")
479    (set (match_operand:SI          0 "arm_general_register_operand" "")
480         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
481                  (match_operand:SI 2 "const_int_operand"  "")))]
482   "TARGET_ARM &&
483    !(const_ok_for_arm (INTVAL (operands[2]))
484      || const_ok_for_arm (-INTVAL (operands[2])))
485     && const_ok_for_arm (~INTVAL (operands[2]))"
486   [(set (match_dup 3) (match_dup 2))
487    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
488   ""
489 )
490
491 (define_insn_and_split "*arm_addsi3"
492   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
493         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
494                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
495   "TARGET_ARM"
496   "@
497    add%?\\t%0, %1, %2
498    sub%?\\t%0, %1, #%n2
499    #"
500   "TARGET_ARM &&
501    GET_CODE (operands[2]) == CONST_INT
502    && !(const_ok_for_arm (INTVAL (operands[2]))
503         || const_ok_for_arm (-INTVAL (operands[2])))"
504   [(clobber (const_int 0))]
505   "
506   arm_split_constant (PLUS, SImode, curr_insn,
507                       INTVAL (operands[2]), operands[0],
508                       operands[1], 0);
509   DONE;
510   "
511   [(set_attr "length" "4,4,16")
512    (set_attr "predicable" "yes")]
513 )
514
515 ;; Register group 'k' is a single register group containing only the stack
516 ;; register.  Trying to reload it will always fail catastrophically,
517 ;; so never allow those alternatives to match if reloading is needed.
518
519 (define_insn "*thumb_addsi3"
520   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
521         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
522                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
523   "TARGET_THUMB"
524   "*
525    static const char * const asms[] = 
526    {
527      \"add\\t%0, %0, %2\",
528      \"sub\\t%0, %0, #%n2\",
529      \"add\\t%0, %1, %2\",
530      \"add\\t%0, %0, %2\",
531      \"add\\t%0, %0, %2\",
532      \"add\\t%0, %1, %2\",
533      \"add\\t%0, %1, %2\"
534    };
535    if ((which_alternative == 2 || which_alternative == 6)
536        && GET_CODE (operands[2]) == CONST_INT
537        && INTVAL (operands[2]) < 0)
538      return \"sub\\t%0, %1, #%n2\";
539    return asms[which_alternative];
540   "
541   [(set_attr "length" "2")]
542 )
543
544 ;; Reloading and elimination of the frame pointer can
545 ;; sometimes cause this optimization to be missed.
546 (define_peephole2
547   [(set (match_operand:SI 0 "arm_general_register_operand" "")
548         (match_operand:SI 1 "const_int_operand" ""))
549    (set (match_dup 0)
550         (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
551   "TARGET_THUMB
552    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
553    && (INTVAL (operands[1]) & 3) == 0"
554   [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
555   ""
556 )
557
558 (define_insn "*addsi3_compare0"
559   [(set (reg:CC_NOOV CC_REGNUM)
560         (compare:CC_NOOV
561          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
562                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
563          (const_int 0)))
564    (set (match_operand:SI 0 "s_register_operand" "=r,r")
565         (plus:SI (match_dup 1) (match_dup 2)))]
566   "TARGET_ARM"
567   "@
568    add%?s\\t%0, %1, %2
569    sub%?s\\t%0, %1, #%n2"
570   [(set_attr "conds" "set")]
571 )
572
573 (define_insn "*addsi3_compare0_scratch"
574   [(set (reg:CC_NOOV CC_REGNUM)
575         (compare:CC_NOOV
576          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
577                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
578          (const_int 0)))]
579   "TARGET_ARM"
580   "@
581    cmn%?\\t%0, %1
582    cmp%?\\t%0, #%n1"
583   [(set_attr "conds" "set")]
584 )
585
586 (define_insn "*compare_negsi_si"
587   [(set (reg:CC_Z CC_REGNUM)
588         (compare:CC_Z
589          (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
590          (match_operand:SI 1 "s_register_operand" "r")))]
591   "TARGET_ARM"
592   "cmn%?\\t%1, %0"
593   [(set_attr "conds" "set")]
594 )
595
596 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
597 ;; addend is a constant.
598 (define_insn "*cmpsi2_addneg"
599   [(set (reg:CC CC_REGNUM)
600         (compare:CC
601          (match_operand:SI 1 "s_register_operand" "r,r")
602          (match_operand:SI 2 "arm_addimm_operand" "I,L")))
603    (set (match_operand:SI 0 "s_register_operand" "=r,r")
604         (plus:SI (match_dup 1)
605                  (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
606   "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
607   "@
608    sub%?s\\t%0, %1, %2
609    add%?s\\t%0, %1, #%n2"
610   [(set_attr "conds" "set")]
611 )
612
613 ;; Convert the sequence
614 ;;  sub  rd, rn, #1
615 ;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
616 ;;  bne  dest
617 ;; into
618 ;;  subs rd, rn, #1
619 ;;  bcs  dest   ((unsigned)rn >= 1)
620 ;; similarly for the beq variant using bcc.
621 ;; This is a common looping idiom (while (n--))
622 (define_peephole2
623   [(set (match_operand:SI 0 "arm_general_register_operand" "")
624         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
625                  (const_int -1)))
626    (set (match_operand 2 "cc_register" "")
627         (compare (match_dup 0) (const_int -1)))
628    (set (pc)
629         (if_then_else (match_operator 3 "equality_operator"
630                        [(match_dup 2) (const_int 0)])
631                       (match_operand 4 "" "")
632                       (match_operand 5 "" "")))]
633   "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
634   [(parallel[
635     (set (match_dup 2)
636          (compare:CC
637           (match_dup 1) (const_int 1)))
638     (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
639    (set (pc)
640         (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
641                       (match_dup 4)
642                       (match_dup 5)))]
643   "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
644    operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
645                                   ? GEU : LTU),
646                                  VOIDmode, 
647                                  operands[2], const0_rtx);"
648 )
649
650 ;; The next four insns work because they compare the result with one of
651 ;; the operands, and we know that the use of the condition code is
652 ;; either GEU or LTU, so we can use the carry flag from the addition
653 ;; instead of doing the compare a second time.
654 (define_insn "*addsi3_compare_op1"
655   [(set (reg:CC_C CC_REGNUM)
656         (compare:CC_C
657          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
658                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
659          (match_dup 1)))
660    (set (match_operand:SI 0 "s_register_operand" "=r,r")
661         (plus:SI (match_dup 1) (match_dup 2)))]
662   "TARGET_ARM"
663   "@
664    add%?s\\t%0, %1, %2
665    sub%?s\\t%0, %1, #%n2"
666   [(set_attr "conds" "set")]
667 )
668
669 (define_insn "*addsi3_compare_op2"
670   [(set (reg:CC_C CC_REGNUM)
671         (compare:CC_C
672          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
673                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
674          (match_dup 2)))
675    (set (match_operand:SI 0 "s_register_operand" "=r,r")
676         (plus:SI (match_dup 1) (match_dup 2)))]
677   "TARGET_ARM"
678   "@
679    add%?s\\t%0, %1, %2
680    sub%?s\\t%0, %1, #%n2"
681   [(set_attr "conds" "set")]
682 )
683
684 (define_insn "*compare_addsi2_op0"
685   [(set (reg:CC_C CC_REGNUM)
686         (compare:CC_C
687          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
688                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
689          (match_dup 0)))]
690   "TARGET_ARM"
691   "@
692    cmn%?\\t%0, %1
693    cmp%?\\t%0, #%n1"
694   [(set_attr "conds" "set")]
695 )
696
697 (define_insn "*compare_addsi2_op1"
698   [(set (reg:CC_C CC_REGNUM)
699         (compare:CC_C
700          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
701                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
702          (match_dup 1)))]
703   "TARGET_ARM"
704   "@
705    cmn%?\\t%0, %1
706    cmp%?\\t%0, #%n1"
707   [(set_attr "conds" "set")]
708 )
709
710 (define_insn "*addsi3_carryin"
711   [(set (match_operand:SI 0 "s_register_operand" "=r")
712         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
713                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
714                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
715   "TARGET_ARM"
716   "adc%?\\t%0, %1, %2"
717   [(set_attr "conds" "use")]
718 )
719
720 (define_insn "*addsi3_carryin_shift"
721   [(set (match_operand:SI 0 "s_register_operand" "=r")
722         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
723                  (plus:SI
724                    (match_operator:SI 2 "shift_operator"
725                       [(match_operand:SI 3 "s_register_operand" "r")
726                        (match_operand:SI 4 "reg_or_int_operand" "rM")])
727                     (match_operand:SI 1 "s_register_operand" "r"))))]
728   "TARGET_ARM"
729   "adc%?\\t%0, %1, %3%S2"
730   [(set_attr "conds" "use")
731    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
732                       (const_string "alu_shift")
733                       (const_string "alu_shift_reg")))]
734 )
735
736 (define_insn "*addsi3_carryin_alt1"
737   [(set (match_operand:SI 0 "s_register_operand" "=r")
738         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
739                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
740                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
741   "TARGET_ARM"
742   "adc%?\\t%0, %1, %2"
743   [(set_attr "conds" "use")]
744 )
745
746 (define_insn "*addsi3_carryin_alt2"
747   [(set (match_operand:SI 0 "s_register_operand" "=r")
748         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
749                           (match_operand:SI 1 "s_register_operand" "r"))
750                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
751   "TARGET_ARM"
752   "adc%?\\t%0, %1, %2"
753   [(set_attr "conds" "use")]
754 )
755
756 (define_insn "*addsi3_carryin_alt3"
757   [(set (match_operand:SI 0 "s_register_operand" "=r")
758         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
759                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
760                  (match_operand:SI 1 "s_register_operand" "r")))]
761   "TARGET_ARM"
762   "adc%?\\t%0, %1, %2"
763   [(set_attr "conds" "use")]
764 )
765
766 (define_insn "incscc"
767   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
768         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
769                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
770                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
771   "TARGET_ARM"
772   "@
773   add%d2\\t%0, %1, #1
774   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
775   [(set_attr "conds" "use")
776    (set_attr "length" "4,8")]
777 )
778
779 ; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
780 (define_split
781   [(set (match_operand:SI 0 "s_register_operand" "")
782         (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
783                             (match_operand:SI 2 "s_register_operand" ""))
784                  (const_int -1)))
785    (clobber (match_operand:SI 3 "s_register_operand" ""))]
786   "TARGET_ARM"
787   [(set (match_dup 3) (match_dup 1))
788    (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
789   "
790   operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
791 ")
792
793 (define_expand "addsf3"
794   [(set (match_operand:SF          0 "s_register_operand" "")
795         (plus:SF (match_operand:SF 1 "s_register_operand" "")
796                  (match_operand:SF 2 "arm_float_add_operand" "")))]
797   "TARGET_ARM && TARGET_HARD_FLOAT"
798   "
799   if (TARGET_MAVERICK
800       && !cirrus_fp_register (operands[2], SFmode))
801     operands[2] = force_reg (SFmode, operands[2]);
802 ")
803
804 (define_expand "adddf3"
805   [(set (match_operand:DF          0 "s_register_operand" "")
806         (plus:DF (match_operand:DF 1 "s_register_operand" "")
807                  (match_operand:DF 2 "arm_float_add_operand" "")))]
808   "TARGET_ARM && TARGET_HARD_FLOAT"
809   "
810   if (TARGET_MAVERICK
811       && !cirrus_fp_register (operands[2], DFmode))
812     operands[2] = force_reg (DFmode, operands[2]);
813 ")
814
815 (define_expand "subdi3"
816  [(parallel
817    [(set (match_operand:DI            0 "s_register_operand" "")
818           (minus:DI (match_operand:DI 1 "s_register_operand" "")
819                     (match_operand:DI 2 "s_register_operand" "")))
820     (clobber (reg:CC CC_REGNUM))])]
821   "TARGET_EITHER"
822   "
823   if (TARGET_HARD_FLOAT && TARGET_MAVERICK
824       && TARGET_ARM
825       && cirrus_fp_register (operands[0], DImode)
826       && cirrus_fp_register (operands[1], DImode))
827     {
828       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
829       DONE;
830     }
831
832   if (TARGET_THUMB)
833     {
834       if (GET_CODE (operands[1]) != REG)
835         operands[1] = force_reg (SImode, operands[1]);
836       if (GET_CODE (operands[2]) != REG)
837         operands[2] = force_reg (SImode, operands[2]);
838      }  
839   "
840 )
841
842 (define_insn "*arm_subdi3"
843   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
844         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
845                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
846    (clobber (reg:CC CC_REGNUM))]
847   "TARGET_ARM"
848   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
849   [(set_attr "conds" "clob")
850    (set_attr "length" "8")]
851 )
852
853 (define_insn "*thumb_subdi3"
854   [(set (match_operand:DI           0 "register_operand" "=l")
855         (minus:DI (match_operand:DI 1 "register_operand"  "0")
856                   (match_operand:DI 2 "register_operand"  "l")))
857    (clobber (reg:CC CC_REGNUM))]
858   "TARGET_THUMB"
859   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
860   [(set_attr "length" "4")]
861 )
862
863 (define_insn "*subdi_di_zesidi"
864   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
865         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
866                   (zero_extend:DI
867                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
868    (clobber (reg:CC CC_REGNUM))]
869   "TARGET_ARM"
870   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
871   [(set_attr "conds" "clob")
872    (set_attr "length" "8")]
873 )
874
875 (define_insn "*subdi_di_sesidi"
876   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
877         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
878                   (sign_extend:DI
879                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
880    (clobber (reg:CC CC_REGNUM))]
881   "TARGET_ARM"
882   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
883   [(set_attr "conds" "clob")
884    (set_attr "length" "8")]
885 )
886
887 (define_insn "*subdi_zesidi_di"
888   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
889         (minus:DI (zero_extend:DI
890                    (match_operand:SI 2 "s_register_operand"  "r,r"))
891                   (match_operand:DI  1 "s_register_operand" "?r,0")))
892    (clobber (reg:CC CC_REGNUM))]
893   "TARGET_ARM"
894   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
895   [(set_attr "conds" "clob")
896    (set_attr "length" "8")]
897 )
898
899 (define_insn "*subdi_sesidi_di"
900   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
901         (minus:DI (sign_extend:DI
902                    (match_operand:SI 2 "s_register_operand"   "r,r"))
903                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
904    (clobber (reg:CC CC_REGNUM))]
905   "TARGET_ARM"
906   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
907   [(set_attr "conds" "clob")
908    (set_attr "length" "8")]
909 )
910
911 (define_insn "*subdi_zesidi_zesidi"
912   [(set (match_operand:DI            0 "s_register_operand" "=r")
913         (minus:DI (zero_extend:DI
914                    (match_operand:SI 1 "s_register_operand"  "r"))
915                   (zero_extend:DI
916                    (match_operand:SI 2 "s_register_operand"  "r"))))
917    (clobber (reg:CC CC_REGNUM))]
918   "TARGET_ARM"
919   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
920   [(set_attr "conds" "clob")
921    (set_attr "length" "8")]
922 )
923
924 (define_expand "subsi3"
925   [(set (match_operand:SI           0 "s_register_operand" "")
926         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
927                   (match_operand:SI 2 "s_register_operand" "")))]
928   "TARGET_EITHER"
929   "
930   if (GET_CODE (operands[1]) == CONST_INT)
931     {
932       if (TARGET_ARM)
933         {
934           arm_split_constant (MINUS, SImode, NULL_RTX,
935                               INTVAL (operands[1]), operands[0],
936                               operands[2], optimize && !no_new_pseudos);
937           DONE;
938         }
939       else /* TARGET_THUMB */
940         operands[1] = force_reg (SImode, operands[1]);
941     }
942   "
943 )
944
945 (define_insn "*thumb_subsi3_insn"
946   [(set (match_operand:SI           0 "register_operand" "=l")
947         (minus:SI (match_operand:SI 1 "register_operand" "l")
948                   (match_operand:SI 2 "register_operand" "l")))]
949   "TARGET_THUMB"
950   "sub\\t%0, %1, %2"
951   [(set_attr "length" "2")]
952 )
953
954 (define_insn_and_split "*arm_subsi3_insn"
955   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
956         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
957                   (match_operand:SI 2 "s_register_operand" "r,r")))]
958   "TARGET_ARM"
959   "@
960    rsb%?\\t%0, %2, %1
961    #"
962   "TARGET_ARM
963    && GET_CODE (operands[1]) == CONST_INT
964    && !const_ok_for_arm (INTVAL (operands[1]))"
965   [(clobber (const_int 0))]
966   "
967   arm_split_constant (MINUS, SImode, curr_insn,
968                       INTVAL (operands[1]), operands[0], operands[2], 0);
969   DONE;
970   "
971   [(set_attr "length" "4,16")
972    (set_attr "predicable" "yes")]
973 )
974
975 (define_peephole2
976   [(match_scratch:SI 3 "r")
977    (set (match_operand:SI 0 "arm_general_register_operand" "")
978         (minus:SI (match_operand:SI 1 "const_int_operand" "")
979                   (match_operand:SI 2 "arm_general_register_operand" "")))]
980   "TARGET_ARM
981    && !const_ok_for_arm (INTVAL (operands[1]))
982    && const_ok_for_arm (~INTVAL (operands[1]))"
983   [(set (match_dup 3) (match_dup 1))
984    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
985   ""
986 )
987
988 (define_insn "*subsi3_compare0"
989   [(set (reg:CC_NOOV CC_REGNUM)
990         (compare:CC_NOOV
991          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
992                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
993          (const_int 0)))
994    (set (match_operand:SI 0 "s_register_operand" "=r,r")
995         (minus:SI (match_dup 1) (match_dup 2)))]
996   "TARGET_ARM"
997   "@
998    sub%?s\\t%0, %1, %2
999    rsb%?s\\t%0, %2, %1"
1000   [(set_attr "conds" "set")]
1001 )
1002
1003 (define_insn "decscc"
1004   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1005         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1006                   (match_operator:SI 2 "arm_comparison_operator"
1007                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1008   "TARGET_ARM"
1009   "@
1010    sub%d2\\t%0, %1, #1
1011    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1012   [(set_attr "conds" "use")
1013    (set_attr "length" "*,8")]
1014 )
1015
1016 (define_expand "subsf3"
1017   [(set (match_operand:SF           0 "s_register_operand" "")
1018         (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1019                   (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1020   "TARGET_ARM && TARGET_HARD_FLOAT"
1021   "
1022   if (TARGET_MAVERICK)
1023     {
1024       if (!cirrus_fp_register (operands[1], SFmode))
1025         operands[1] = force_reg (SFmode, operands[1]);
1026       if (!cirrus_fp_register (operands[2], SFmode))
1027         operands[2] = force_reg (SFmode, operands[2]);
1028     }
1029 ")
1030
1031 (define_expand "subdf3"
1032   [(set (match_operand:DF           0 "s_register_operand" "")
1033         (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1034                   (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1035   "TARGET_ARM && TARGET_HARD_FLOAT"
1036   "
1037   if (TARGET_MAVERICK)
1038     {
1039        if (!cirrus_fp_register (operands[1], DFmode))
1040          operands[1] = force_reg (DFmode, operands[1]);
1041        if (!cirrus_fp_register (operands[2], DFmode))
1042          operands[2] = force_reg (DFmode, operands[2]);
1043     }
1044 ")
1045
1046 \f
1047 ;; Multiplication insns
1048
1049 (define_expand "mulsi3"
1050   [(set (match_operand:SI          0 "s_register_operand" "")
1051         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1052                  (match_operand:SI 1 "s_register_operand" "")))]
1053   "TARGET_EITHER"
1054   ""
1055 )
1056
1057 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1058 (define_insn "*arm_mulsi3"
1059   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1060         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1061                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1062   "TARGET_ARM"
1063   "mul%?\\t%0, %2, %1"
1064   [(set_attr "insn" "mul")
1065    (set_attr "predicable" "yes")]
1066 )
1067
1068 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1069 ; 1 and 2; are the same, because reload will make operand 0 match 
1070 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1071 ; this by adding another alternative to match this case, and then `reload' 
1072 ; it ourselves.  This alternative must come first.
1073 (define_insn "*thumb_mulsi3"
1074   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1075         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1076                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1077   "TARGET_THUMB"
1078   "*
1079   if (which_alternative < 2)
1080     return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1081   else
1082     return \"mul\\t%0, %0, %2\";
1083   "
1084   [(set_attr "length" "4,4,2")
1085    (set_attr "insn" "mul")]
1086 )
1087
1088 (define_insn "*mulsi3_compare0"
1089   [(set (reg:CC_NOOV CC_REGNUM)
1090         (compare:CC_NOOV (mult:SI
1091                           (match_operand:SI 2 "s_register_operand" "r,r")
1092                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1093                          (const_int 0)))
1094    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1095         (mult:SI (match_dup 2) (match_dup 1)))]
1096   "TARGET_ARM"
1097   "mul%?s\\t%0, %2, %1"
1098   [(set_attr "conds" "set")
1099    (set_attr "insn" "muls")]
1100 )
1101
1102 (define_insn "*mulsi_compare0_scratch"
1103   [(set (reg:CC_NOOV CC_REGNUM)
1104         (compare:CC_NOOV (mult:SI
1105                           (match_operand:SI 2 "s_register_operand" "r,r")
1106                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1107                          (const_int 0)))
1108    (clobber (match_scratch:SI 0 "=&r,&r"))]
1109   "TARGET_ARM"
1110   "mul%?s\\t%0, %2, %1"
1111   [(set_attr "conds" "set")
1112    (set_attr "insn" "muls")]
1113 )
1114
1115 ;; Unnamed templates to match MLA instruction.
1116
1117 (define_insn "*mulsi3addsi"
1118   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1119         (plus:SI
1120           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1121                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1122           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1123   "TARGET_ARM"
1124   "mla%?\\t%0, %2, %1, %3"
1125   [(set_attr "insn" "mla")
1126    (set_attr "predicable" "yes")]
1127 )
1128
1129 (define_insn "*mulsi3addsi_compare0"
1130   [(set (reg:CC_NOOV CC_REGNUM)
1131         (compare:CC_NOOV
1132          (plus:SI (mult:SI
1133                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1134                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1135                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1136          (const_int 0)))
1137    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1138         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1139                  (match_dup 3)))]
1140   "TARGET_ARM"
1141   "mla%?s\\t%0, %2, %1, %3"
1142   [(set_attr "conds" "set")
1143    (set_attr "insn" "mlas")]
1144 )
1145
1146 (define_insn "*mulsi3addsi_compare0_scratch"
1147   [(set (reg:CC_NOOV CC_REGNUM)
1148         (compare:CC_NOOV
1149          (plus:SI (mult:SI
1150                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1151                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1152                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1153          (const_int 0)))
1154    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1155   "TARGET_ARM"
1156   "mla%?s\\t%0, %2, %1, %3"
1157   [(set_attr "conds" "set")
1158    (set_attr "insn" "mlas")]
1159 )
1160
1161 ;; Unnamed template to match long long multiply-accumulate (smlal)
1162
1163 (define_insn "*mulsidi3adddi"
1164   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1165         (plus:DI
1166          (mult:DI
1167           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1168           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1169          (match_operand:DI 1 "s_register_operand" "0")))]
1170   "TARGET_ARM && arm_arch3m"
1171   "smlal%?\\t%Q0, %R0, %3, %2"
1172   [(set_attr "insn" "smlal")
1173    (set_attr "predicable" "yes")]
1174 )
1175
1176 (define_insn "mulsidi3"
1177   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1178         (mult:DI
1179          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1180          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1181   "TARGET_ARM && arm_arch3m"
1182   "smull%?\\t%Q0, %R0, %1, %2"
1183   [(set_attr "insn" "smull")
1184    (set_attr "predicable" "yes")]
1185 )
1186
1187 (define_insn "umulsidi3"
1188   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1189         (mult:DI
1190          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1191          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1192   "TARGET_ARM && arm_arch3m"
1193   "umull%?\\t%Q0, %R0, %1, %2"
1194   [(set_attr "insn" "umull")
1195    (set_attr "predicable" "yes")]
1196 )
1197
1198 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1199
1200 (define_insn "*umulsidi3adddi"
1201   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1202         (plus:DI
1203          (mult:DI
1204           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1205           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1206          (match_operand:DI 1 "s_register_operand" "0")))]
1207   "TARGET_ARM && arm_arch3m"
1208   "umlal%?\\t%Q0, %R0, %3, %2"
1209   [(set_attr "insn" "umlal")
1210    (set_attr "predicable" "yes")]
1211 )
1212
1213 (define_insn "smulsi3_highpart"
1214   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1215         (truncate:SI
1216          (lshiftrt:DI
1217           (mult:DI
1218            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1219            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1220           (const_int 32))))
1221    (clobber (match_scratch:SI 3 "=&r,&r"))]
1222   "TARGET_ARM && arm_arch3m"
1223   "smull%?\\t%3, %0, %2, %1"
1224   [(set_attr "insn" "smull")
1225    (set_attr "predicable" "yes")]
1226 )
1227
1228 (define_insn "umulsi3_highpart"
1229   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1230         (truncate:SI
1231          (lshiftrt:DI
1232           (mult:DI
1233            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1234            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1235           (const_int 32))))
1236    (clobber (match_scratch:SI 3 "=&r,&r"))]
1237   "TARGET_ARM && arm_arch3m"
1238   "umull%?\\t%3, %0, %2, %1"
1239   [(set_attr "insn" "umull")
1240    (set_attr "predicable" "yes")]
1241 )
1242
1243 (define_insn "mulhisi3"
1244   [(set (match_operand:SI 0 "s_register_operand" "=r")
1245         (mult:SI (sign_extend:SI
1246                   (match_operand:HI 1 "s_register_operand" "%r"))
1247                  (sign_extend:SI
1248                   (match_operand:HI 2 "s_register_operand" "r"))))]
1249   "TARGET_ARM && arm_arch5e"
1250   "smulbb%?\\t%0, %1, %2"
1251   [(set_attr "insn" "smulxy")
1252    (set_attr "predicable" "yes")]
1253 )
1254
1255 (define_insn "*mulhisi3tb"
1256   [(set (match_operand:SI 0 "s_register_operand" "=r")
1257         (mult:SI (ashiftrt:SI
1258                   (match_operand:SI 1 "s_register_operand" "r")
1259                   (const_int 16))
1260                  (sign_extend:SI
1261                   (match_operand:HI 2 "s_register_operand" "r"))))]
1262   "TARGET_ARM && arm_arch5e"
1263   "smultb%?\\t%0, %1, %2"
1264   [(set_attr "insn" "smulxy")
1265    (set_attr "predicable" "yes")]
1266 )
1267
1268 (define_insn "*mulhisi3bt"
1269   [(set (match_operand:SI 0 "s_register_operand" "=r")
1270         (mult:SI (sign_extend:SI
1271                   (match_operand:HI 1 "s_register_operand" "r"))
1272                  (ashiftrt:SI
1273                   (match_operand:SI 2 "s_register_operand" "r")
1274                   (const_int 16))))]
1275   "TARGET_ARM && arm_arch5e"
1276   "smulbt%?\\t%0, %1, %2"
1277   [(set_attr "insn" "smulxy")
1278    (set_attr "predicable" "yes")]
1279 )
1280
1281 (define_insn "*mulhisi3tt"
1282   [(set (match_operand:SI 0 "s_register_operand" "=r")
1283         (mult:SI (ashiftrt:SI
1284                   (match_operand:SI 1 "s_register_operand" "r")
1285                   (const_int 16))
1286                  (ashiftrt:SI
1287                   (match_operand:SI 2 "s_register_operand" "r")
1288                   (const_int 16))))]
1289   "TARGET_ARM && arm_arch5e"
1290   "smultt%?\\t%0, %1, %2"
1291   [(set_attr "insn" "smulxy")
1292    (set_attr "predicable" "yes")]
1293 )
1294
1295 (define_insn "*mulhisi3addsi"
1296   [(set (match_operand:SI 0 "s_register_operand" "=r")
1297         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1298                  (mult:SI (sign_extend:SI
1299                            (match_operand:HI 2 "s_register_operand" "%r"))
1300                           (sign_extend:SI
1301                            (match_operand:HI 3 "s_register_operand" "r")))))]
1302   "TARGET_ARM && arm_arch5e"
1303   "smlabb%?\\t%0, %2, %3, %1"
1304   [(set_attr "insn" "smlaxy")
1305    (set_attr "predicable" "yes")]
1306 )
1307
1308 (define_insn "*mulhidi3adddi"
1309   [(set (match_operand:DI 0 "s_register_operand" "=r")
1310         (plus:DI
1311           (match_operand:DI 1 "s_register_operand" "0")
1312           (mult:DI (sign_extend:DI
1313                     (match_operand:HI 2 "s_register_operand" "%r"))
1314                    (sign_extend:DI
1315                     (match_operand:HI 3 "s_register_operand" "r")))))]
1316   "TARGET_ARM && arm_arch5e"
1317   "smlalbb%?\\t%Q0, %R0, %2, %3"
1318   [(set_attr "insn" "smlalxy")
1319    (set_attr "predicable" "yes")])
1320
1321 (define_expand "mulsf3"
1322   [(set (match_operand:SF          0 "s_register_operand" "")
1323         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1324                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1325   "TARGET_ARM && TARGET_HARD_FLOAT"
1326   "
1327   if (TARGET_MAVERICK
1328       && !cirrus_fp_register (operands[2], SFmode))
1329     operands[2] = force_reg (SFmode, operands[2]);
1330 ")
1331
1332 (define_expand "muldf3"
1333   [(set (match_operand:DF          0 "s_register_operand" "")
1334         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1335                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1336   "TARGET_ARM && TARGET_HARD_FLOAT"
1337   "
1338   if (TARGET_MAVERICK
1339       && !cirrus_fp_register (operands[2], DFmode))
1340     operands[2] = force_reg (DFmode, operands[2]);
1341 ")
1342 \f
1343 ;; Division insns
1344
1345 (define_expand "divsf3"
1346   [(set (match_operand:SF 0 "s_register_operand" "")
1347         (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1348                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1349   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1350   "")
1351
1352 (define_expand "divdf3"
1353   [(set (match_operand:DF 0 "s_register_operand" "")
1354         (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1355                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1356   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1357   "")
1358 \f
1359 ;; Modulo insns
1360
1361 (define_expand "modsf3"
1362   [(set (match_operand:SF 0 "s_register_operand" "")
1363         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1364                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1365   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1366   "")
1367
1368 (define_expand "moddf3"
1369   [(set (match_operand:DF 0 "s_register_operand" "")
1370         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1371                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1372   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1373   "")
1374 \f
1375 ;; Boolean and,ior,xor insns
1376
1377 ;; Split up double word logical operations
1378
1379 ;; Split up simple DImode logical operations.  Simply perform the logical
1380 ;; operation on the upper and lower halves of the registers.
1381 (define_split
1382   [(set (match_operand:DI 0 "s_register_operand" "")
1383         (match_operator:DI 6 "logical_binary_operator"
1384           [(match_operand:DI 1 "s_register_operand" "")
1385            (match_operand:DI 2 "s_register_operand" "")]))]
1386   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1387   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1388    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1389   "
1390   {
1391     operands[3] = gen_highpart (SImode, operands[0]);
1392     operands[0] = gen_lowpart (SImode, operands[0]);
1393     operands[4] = gen_highpart (SImode, operands[1]);
1394     operands[1] = gen_lowpart (SImode, operands[1]);
1395     operands[5] = gen_highpart (SImode, operands[2]);
1396     operands[2] = gen_lowpart (SImode, operands[2]);
1397   }"
1398 )
1399
1400 (define_split
1401   [(set (match_operand:DI 0 "s_register_operand" "")
1402         (match_operator:DI 6 "logical_binary_operator"
1403           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1404            (match_operand:DI 1 "s_register_operand" "")]))]
1405   "TARGET_ARM && reload_completed"
1406   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1407    (set (match_dup 3) (match_op_dup:SI 6
1408                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1409                          (match_dup 4)]))]
1410   "
1411   {
1412     operands[3] = gen_highpart (SImode, operands[0]);
1413     operands[0] = gen_lowpart (SImode, operands[0]);
1414     operands[4] = gen_highpart (SImode, operands[1]);
1415     operands[1] = gen_lowpart (SImode, operands[1]);
1416     operands[5] = gen_highpart (SImode, operands[2]);
1417     operands[2] = gen_lowpart (SImode, operands[2]);
1418   }"
1419 )
1420
1421 ;; The zero extend of operand 2 means we can just copy the high part of
1422 ;; operand1 into operand0.
1423 (define_split
1424   [(set (match_operand:DI 0 "s_register_operand" "")
1425         (ior:DI
1426           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1427           (match_operand:DI 1 "s_register_operand" "")))]
1428   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1429   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1430    (set (match_dup 3) (match_dup 4))]
1431   "
1432   {
1433     operands[4] = gen_highpart (SImode, operands[1]);
1434     operands[3] = gen_highpart (SImode, operands[0]);
1435     operands[0] = gen_lowpart (SImode, operands[0]);
1436     operands[1] = gen_lowpart (SImode, operands[1]);
1437   }"
1438 )
1439
1440 ;; The zero extend of operand 2 means we can just copy the high part of
1441 ;; operand1 into operand0.
1442 (define_split
1443   [(set (match_operand:DI 0 "s_register_operand" "")
1444         (xor:DI
1445           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1446           (match_operand:DI 1 "s_register_operand" "")))]
1447   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1448   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1449    (set (match_dup 3) (match_dup 4))]
1450   "
1451   {
1452     operands[4] = gen_highpart (SImode, operands[1]);
1453     operands[3] = gen_highpart (SImode, operands[0]);
1454     operands[0] = gen_lowpart (SImode, operands[0]);
1455     operands[1] = gen_lowpart (SImode, operands[1]);
1456   }"
1457 )
1458
1459 (define_insn "anddi3"
1460   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1461         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1462                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1463   "TARGET_ARM && ! TARGET_IWMMXT"
1464   "#"
1465   [(set_attr "length" "8")]
1466 )
1467
1468 (define_insn_and_split "*anddi_zesidi_di"
1469   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1470         (and:DI (zero_extend:DI
1471                  (match_operand:SI 2 "s_register_operand" "r,r"))
1472                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1473   "TARGET_ARM"
1474   "#"
1475   "TARGET_ARM && reload_completed"
1476   ; The zero extend of operand 2 clears the high word of the output
1477   ; operand.
1478   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1479    (set (match_dup 3) (const_int 0))]
1480   "
1481   {
1482     operands[3] = gen_highpart (SImode, operands[0]);
1483     operands[0] = gen_lowpart (SImode, operands[0]);
1484     operands[1] = gen_lowpart (SImode, operands[1]);
1485   }"
1486   [(set_attr "length" "8")]
1487 )
1488
1489 (define_insn "*anddi_sesdi_di"
1490   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1491         (and:DI (sign_extend:DI
1492                  (match_operand:SI 2 "s_register_operand" "r,r"))
1493                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1494   "TARGET_ARM"
1495   "#"
1496   [(set_attr "length" "8")]
1497 )
1498
1499 (define_expand "andsi3"
1500   [(set (match_operand:SI         0 "s_register_operand" "")
1501         (and:SI (match_operand:SI 1 "s_register_operand" "")
1502                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1503   "TARGET_EITHER"
1504   "
1505   if (TARGET_ARM)
1506     {
1507       if (GET_CODE (operands[2]) == CONST_INT)
1508         {
1509           arm_split_constant (AND, SImode, NULL_RTX,
1510                               INTVAL (operands[2]), operands[0],
1511                               operands[1], optimize && !no_new_pseudos);
1512
1513           DONE;
1514         }
1515     }
1516   else /* TARGET_THUMB */
1517     {
1518       if (GET_CODE (operands[2]) != CONST_INT)
1519         operands[2] = force_reg (SImode, operands[2]);
1520       else
1521         {
1522           int i;
1523           
1524           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1525             {
1526               operands[2] = force_reg (SImode,
1527                                        GEN_INT (~INTVAL (operands[2])));
1528               
1529               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1530               
1531               DONE;
1532             }
1533
1534           for (i = 9; i <= 31; i++)
1535             {
1536               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1537                 {
1538                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1539                                         const0_rtx));
1540                   DONE;
1541                 }
1542               else if ((((HOST_WIDE_INT) 1) << i) - 1
1543                        == ~INTVAL (operands[2]))
1544                 {
1545                   rtx shift = GEN_INT (i);
1546                   rtx reg = gen_reg_rtx (SImode);
1547                 
1548                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1549                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1550                   
1551                   DONE;
1552                 }
1553             }
1554
1555           operands[2] = force_reg (SImode, operands[2]);
1556         }
1557     }
1558   "
1559 )
1560
1561 (define_insn_and_split "*arm_andsi3_insn"
1562   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1563         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1564                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1565   "TARGET_ARM"
1566   "@
1567    and%?\\t%0, %1, %2
1568    bic%?\\t%0, %1, #%B2
1569    #"
1570   "TARGET_ARM
1571    && GET_CODE (operands[2]) == CONST_INT
1572    && !(const_ok_for_arm (INTVAL (operands[2]))
1573         || const_ok_for_arm (~INTVAL (operands[2])))"
1574   [(clobber (const_int 0))]
1575   "
1576   arm_split_constant  (AND, SImode, curr_insn, 
1577                        INTVAL (operands[2]), operands[0], operands[1], 0);
1578   DONE;
1579   "
1580   [(set_attr "length" "4,4,16")
1581    (set_attr "predicable" "yes")]
1582 )
1583
1584 (define_insn "*thumb_andsi3_insn"
1585   [(set (match_operand:SI         0 "register_operand" "=l")
1586         (and:SI (match_operand:SI 1 "register_operand" "%0")
1587                 (match_operand:SI 2 "register_operand" "l")))]
1588   "TARGET_THUMB"
1589   "and\\t%0, %0, %2"
1590   [(set_attr "length" "2")]
1591 )
1592
1593 (define_insn "*andsi3_compare0"
1594   [(set (reg:CC_NOOV CC_REGNUM)
1595         (compare:CC_NOOV
1596          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1597                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1598          (const_int 0)))
1599    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1600         (and:SI (match_dup 1) (match_dup 2)))]
1601   "TARGET_ARM"
1602   "@
1603    and%?s\\t%0, %1, %2
1604    bic%?s\\t%0, %1, #%B2"
1605   [(set_attr "conds" "set")]
1606 )
1607
1608 (define_insn "*andsi3_compare0_scratch"
1609   [(set (reg:CC_NOOV CC_REGNUM)
1610         (compare:CC_NOOV
1611          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1612                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1613          (const_int 0)))
1614    (clobber (match_scratch:SI 2 "=X,r"))]
1615   "TARGET_ARM"
1616   "@
1617    tst%?\\t%0, %1
1618    bic%?s\\t%2, %0, #%B1"
1619   [(set_attr "conds" "set")]
1620 )
1621
1622 (define_insn "*zeroextractsi_compare0_scratch"
1623   [(set (reg:CC_NOOV CC_REGNUM)
1624         (compare:CC_NOOV (zero_extract:SI
1625                           (match_operand:SI 0 "s_register_operand" "r")
1626                           (match_operand 1 "const_int_operand" "n")
1627                           (match_operand 2 "const_int_operand" "n"))
1628                          (const_int 0)))]
1629   "TARGET_ARM
1630   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1631       && INTVAL (operands[1]) > 0 
1632       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1633       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1634   "*
1635   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1636                          << INTVAL (operands[2]));
1637   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1638   return \"\";
1639   "
1640   [(set_attr "conds" "set")]
1641 )
1642
1643 (define_insn_and_split "*ne_zeroextractsi"
1644   [(set (match_operand:SI 0 "s_register_operand" "=r")
1645         (ne:SI (zero_extract:SI
1646                 (match_operand:SI 1 "s_register_operand" "r")
1647                 (match_operand:SI 2 "const_int_operand" "n")
1648                 (match_operand:SI 3 "const_int_operand" "n"))
1649                (const_int 0)))
1650    (clobber (reg:CC CC_REGNUM))]
1651   "TARGET_ARM
1652    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1653        && INTVAL (operands[2]) > 0 
1654        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1655        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1656   "#"
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   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1663                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1664                                     (const_int 0)))
1665               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1666    (set (match_dup 0)
1667         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1668                          (match_dup 0) (const_int 1)))]
1669   "
1670   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1671                          << INTVAL (operands[3])); 
1672   "
1673   [(set_attr "conds" "clob")
1674    (set_attr "length" "8")]
1675 )
1676
1677 (define_insn_and_split "*ne_zeroextractsi_shifted"
1678   [(set (match_operand:SI 0 "s_register_operand" "=r")
1679         (ne:SI (zero_extract:SI
1680                 (match_operand:SI 1 "s_register_operand" "r")
1681                 (match_operand:SI 2 "const_int_operand" "n")
1682                 (const_int 0))
1683                (const_int 0)))
1684    (clobber (reg:CC CC_REGNUM))]
1685   "TARGET_ARM"
1686   "#"
1687   "TARGET_ARM"
1688   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1689                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1690                                     (const_int 0)))
1691               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1692    (set (match_dup 0)
1693         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1694                          (match_dup 0) (const_int 1)))]
1695   "
1696   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1697   "
1698   [(set_attr "conds" "clob")
1699    (set_attr "length" "8")]
1700 )
1701
1702 (define_insn_and_split "*ite_ne_zeroextractsi"
1703   [(set (match_operand:SI 0 "s_register_operand" "=r")
1704         (if_then_else:SI (ne (zero_extract:SI
1705                               (match_operand:SI 1 "s_register_operand" "r")
1706                               (match_operand:SI 2 "const_int_operand" "n")
1707                               (match_operand:SI 3 "const_int_operand" "n"))
1708                              (const_int 0))
1709                          (match_operand:SI 4 "arm_not_operand" "rIK")
1710                          (const_int 0)))
1711    (clobber (reg:CC CC_REGNUM))]
1712   "TARGET_ARM
1713    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1714        && INTVAL (operands[2]) > 0 
1715        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1716        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1717    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1718   "#"
1719   "TARGET_ARM
1720    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1721        && INTVAL (operands[2]) > 0 
1722        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1723        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1724    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1725   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1726                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1727                                     (const_int 0)))
1728               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1729    (set (match_dup 0)
1730         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1731                          (match_dup 0) (match_dup 4)))]
1732   "
1733   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1734                          << INTVAL (operands[3])); 
1735   "
1736   [(set_attr "conds" "clob")
1737    (set_attr "length" "8")]
1738 )
1739
1740 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1741   [(set (match_operand:SI 0 "s_register_operand" "=r")
1742         (if_then_else:SI (ne (zero_extract:SI
1743                               (match_operand:SI 1 "s_register_operand" "r")
1744                               (match_operand:SI 2 "const_int_operand" "n")
1745                               (const_int 0))
1746                              (const_int 0))
1747                          (match_operand:SI 3 "arm_not_operand" "rIK")
1748                          (const_int 0)))
1749    (clobber (reg:CC CC_REGNUM))]
1750   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1751   "#"
1752   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1753   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1754                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1755                                     (const_int 0)))
1756               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1757    (set (match_dup 0)
1758         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1759                          (match_dup 0) (match_dup 3)))]
1760   "
1761   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1762   "
1763   [(set_attr "conds" "clob")
1764    (set_attr "length" "8")]
1765 )
1766
1767 (define_split
1768   [(set (match_operand:SI 0 "s_register_operand" "")
1769         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1770                          (match_operand:SI 2 "const_int_operand" "")
1771                          (match_operand:SI 3 "const_int_operand" "")))
1772    (clobber (match_operand:SI 4 "s_register_operand" ""))]
1773   "TARGET_THUMB"
1774   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1775    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1776   "{
1777      HOST_WIDE_INT temp = INTVAL (operands[2]);
1778
1779      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1780      operands[3] = GEN_INT (32 - temp);
1781    }"
1782 )
1783
1784 (define_split
1785   [(set (match_operand:SI 0 "s_register_operand" "")
1786         (match_operator:SI 1 "shiftable_operator"
1787          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1788                            (match_operand:SI 3 "const_int_operand" "")
1789                            (match_operand:SI 4 "const_int_operand" ""))
1790           (match_operand:SI 5 "s_register_operand" "")]))
1791    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1792   "TARGET_ARM"
1793   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1794    (set (match_dup 0)
1795         (match_op_dup 1
1796          [(lshiftrt:SI (match_dup 6) (match_dup 4))
1797           (match_dup 5)]))]
1798   "{
1799      HOST_WIDE_INT temp = INTVAL (operands[3]);
1800
1801      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1802      operands[4] = GEN_INT (32 - temp);
1803    }"
1804 )
1805   
1806 (define_split
1807   [(set (match_operand:SI 0 "s_register_operand" "")
1808         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1809                          (match_operand:SI 2 "const_int_operand" "")
1810                          (match_operand:SI 3 "const_int_operand" "")))]
1811   "TARGET_THUMB"
1812   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1813    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1814   "{
1815      HOST_WIDE_INT temp = INTVAL (operands[2]);
1816
1817      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1818      operands[3] = GEN_INT (32 - temp);
1819    }"
1820 )
1821
1822 (define_split
1823   [(set (match_operand:SI 0 "s_register_operand" "")
1824         (match_operator:SI 1 "shiftable_operator"
1825          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1826                            (match_operand:SI 3 "const_int_operand" "")
1827                            (match_operand:SI 4 "const_int_operand" ""))
1828           (match_operand:SI 5 "s_register_operand" "")]))
1829    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1830   "TARGET_ARM"
1831   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1832    (set (match_dup 0)
1833         (match_op_dup 1
1834          [(ashiftrt:SI (match_dup 6) (match_dup 4))
1835           (match_dup 5)]))]
1836   "{
1837      HOST_WIDE_INT temp = INTVAL (operands[3]);
1838
1839      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1840      operands[4] = GEN_INT (32 - temp);
1841    }"
1842 )
1843   
1844 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1845 ;;; represented by the bitfield, then this will produce incorrect results.
1846 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1847 ;;; which have a real bit-field insert instruction, the truncation happens
1848 ;;; in the bit-field insert instruction itself.  Since arm does not have a
1849 ;;; bit-field insert instruction, we would have to emit code here to truncate
1850 ;;; the value before we insert.  This loses some of the advantage of having
1851 ;;; this insv pattern, so this pattern needs to be reevalutated.
1852
1853 (define_expand "insv"
1854   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1855                          (match_operand:SI 1 "general_operand" "")
1856                          (match_operand:SI 2 "general_operand" ""))
1857         (match_operand:SI 3 "reg_or_int_operand" ""))]
1858   "TARGET_ARM"
1859   "
1860   {
1861     int start_bit = INTVAL (operands[2]);
1862     int width = INTVAL (operands[1]);
1863     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1864     rtx target, subtarget;
1865
1866     target = operands[0];
1867     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1868        subreg as the final target.  */
1869     if (GET_CODE (target) == SUBREG)
1870       {
1871         subtarget = gen_reg_rtx (SImode);
1872         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1873             < GET_MODE_SIZE (SImode))
1874           target = SUBREG_REG (target);
1875       }
1876     else
1877       subtarget = target;    
1878
1879     if (GET_CODE (operands[3]) == CONST_INT)
1880       {
1881         /* Since we are inserting a known constant, we may be able to
1882            reduce the number of bits that we have to clear so that
1883            the mask becomes simple.  */
1884         /* ??? This code does not check to see if the new mask is actually
1885            simpler.  It may not be.  */
1886         rtx op1 = gen_reg_rtx (SImode);
1887         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1888            start of this pattern.  */
1889         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1890         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1891
1892         emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1893         emit_insn (gen_iorsi3 (subtarget, op1,
1894                                gen_int_mode (op3_value << start_bit, SImode)));
1895       }
1896     else if (start_bit == 0
1897              && !(const_ok_for_arm (mask)
1898                   || const_ok_for_arm (~mask)))
1899       {
1900         /* A Trick, since we are setting the bottom bits in the word,
1901            we can shift operand[3] up, operand[0] down, OR them together
1902            and rotate the result back again.  This takes 3 insns, and
1903            the third might be mergeable into another op.  */
1904         /* The shift up copes with the possibility that operand[3] is
1905            wider than the bitfield.  */
1906         rtx op0 = gen_reg_rtx (SImode);
1907         rtx op1 = gen_reg_rtx (SImode);
1908
1909         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1910         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1911         emit_insn (gen_iorsi3  (op1, op1, op0));
1912         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1913       }
1914     else if ((width + start_bit == 32)
1915              && !(const_ok_for_arm (mask)
1916                   || const_ok_for_arm (~mask)))
1917       {
1918         /* Similar trick, but slightly less efficient.  */
1919
1920         rtx op0 = gen_reg_rtx (SImode);
1921         rtx op1 = gen_reg_rtx (SImode);
1922
1923         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1924         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1925         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1926         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1927       }
1928     else
1929       {
1930         rtx op0 = GEN_INT (mask);
1931         rtx op1 = gen_reg_rtx (SImode);
1932         rtx op2 = gen_reg_rtx (SImode);
1933
1934         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1935           {
1936             rtx tmp = gen_reg_rtx (SImode);
1937
1938             emit_insn (gen_movsi (tmp, op0));
1939             op0 = tmp;
1940           }
1941
1942         /* Mask out any bits in operand[3] that are not needed.  */
1943            emit_insn (gen_andsi3 (op1, operands[3], op0));
1944
1945         if (GET_CODE (op0) == CONST_INT
1946             && (const_ok_for_arm (mask << start_bit)
1947                 || const_ok_for_arm (~(mask << start_bit))))
1948           {
1949             op0 = GEN_INT (~(mask << start_bit));
1950             emit_insn (gen_andsi3 (op2, operands[0], op0));
1951           }
1952         else
1953           {
1954             if (GET_CODE (op0) == CONST_INT)
1955               {
1956                 rtx tmp = gen_reg_rtx (SImode);
1957
1958                 emit_insn (gen_movsi (tmp, op0));
1959                 op0 = tmp;
1960               }
1961
1962             if (start_bit != 0)
1963               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1964             
1965             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1966           }
1967
1968         if (start_bit != 0)
1969           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1970
1971         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1972       }
1973
1974     if (subtarget != target)
1975       {
1976         /* If TARGET is still a SUBREG, then it must be wider than a word,
1977            so we must be careful only to set the subword we were asked to.  */
1978         if (GET_CODE (target) == SUBREG)
1979           emit_move_insn (target, subtarget);
1980         else
1981           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1982       }
1983
1984     DONE;
1985   }"
1986 )
1987
1988 ; constants for op 2 will never be given to these patterns.
1989 (define_insn_and_split "*anddi_notdi_di"
1990   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1991         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1992                 (match_operand:DI 2 "s_register_operand" "0,r")))]
1993   "TARGET_ARM"
1994   "#"
1995   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1996   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1997    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
1998   "
1999   {
2000     operands[3] = gen_highpart (SImode, operands[0]);
2001     operands[0] = gen_lowpart (SImode, operands[0]);
2002     operands[4] = gen_highpart (SImode, operands[1]);
2003     operands[1] = gen_lowpart (SImode, operands[1]);
2004     operands[5] = gen_highpart (SImode, operands[2]);
2005     operands[2] = gen_lowpart (SImode, operands[2]);
2006   }"
2007   [(set_attr "length" "8")
2008    (set_attr "predicable" "yes")]
2009 )
2010   
2011 (define_insn_and_split "*anddi_notzesidi_di"
2012   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2013         (and:DI (not:DI (zero_extend:DI
2014                          (match_operand:SI 2 "s_register_operand" "r,r")))
2015                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2016   "TARGET_ARM"
2017   "@
2018    bic%?\\t%Q0, %Q1, %2
2019    #"
2020   ; (not (zero_extend ...)) allows us to just copy the high word from
2021   ; operand1 to operand0.
2022   "TARGET_ARM
2023    && reload_completed
2024    && operands[0] != operands[1]"
2025   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2026    (set (match_dup 3) (match_dup 4))]
2027   "
2028   {
2029     operands[3] = gen_highpart (SImode, operands[0]);
2030     operands[0] = gen_lowpart (SImode, operands[0]);
2031     operands[4] = gen_highpart (SImode, operands[1]);
2032     operands[1] = gen_lowpart (SImode, operands[1]);
2033   }"
2034   [(set_attr "length" "4,8")
2035    (set_attr "predicable" "yes")]
2036 )
2037   
2038 (define_insn_and_split "*anddi_notsesidi_di"
2039   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2040         (and:DI (not:DI (sign_extend:DI
2041                          (match_operand:SI 2 "s_register_operand" "r,r")))
2042                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2043   "TARGET_ARM"
2044   "#"
2045   "TARGET_ARM && reload_completed"
2046   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2047    (set (match_dup 3) (and:SI (not:SI
2048                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2049                                (match_dup 4)))]
2050   "
2051   {
2052     operands[3] = gen_highpart (SImode, operands[0]);
2053     operands[0] = gen_lowpart (SImode, operands[0]);
2054     operands[4] = gen_highpart (SImode, operands[1]);
2055     operands[1] = gen_lowpart (SImode, operands[1]);
2056   }"
2057   [(set_attr "length" "8")
2058    (set_attr "predicable" "yes")]
2059 )
2060   
2061 (define_insn "andsi_notsi_si"
2062   [(set (match_operand:SI 0 "s_register_operand" "=r")
2063         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2064                 (match_operand:SI 1 "s_register_operand" "r")))]
2065   "TARGET_ARM"
2066   "bic%?\\t%0, %1, %2"
2067   [(set_attr "predicable" "yes")]
2068 )
2069
2070 (define_insn "bicsi3"
2071   [(set (match_operand:SI                 0 "register_operand" "=l")
2072         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2073                 (match_operand:SI         2 "register_operand" "0")))]
2074   "TARGET_THUMB"
2075   "bic\\t%0, %0, %1"
2076   [(set_attr "length" "2")]
2077 )
2078
2079 (define_insn "andsi_not_shiftsi_si"
2080   [(set (match_operand:SI 0 "s_register_operand" "=r")
2081         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2082                          [(match_operand:SI 2 "s_register_operand" "r")
2083                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2084                 (match_operand:SI 1 "s_register_operand" "r")))]
2085   "TARGET_ARM"
2086   "bic%?\\t%0, %1, %2%S4"
2087   [(set_attr "predicable" "yes")
2088    (set_attr "shift" "2")
2089    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2090                       (const_string "alu_shift")
2091                       (const_string "alu_shift_reg")))]
2092 )
2093
2094 (define_insn "*andsi_notsi_si_compare0"
2095   [(set (reg:CC_NOOV CC_REGNUM)
2096         (compare:CC_NOOV
2097          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2098                  (match_operand:SI 1 "s_register_operand" "r"))
2099          (const_int 0)))
2100    (set (match_operand:SI 0 "s_register_operand" "=r")
2101         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2102   "TARGET_ARM"
2103   "bic%?s\\t%0, %1, %2"
2104   [(set_attr "conds" "set")]
2105 )
2106
2107 (define_insn "*andsi_notsi_si_compare0_scratch"
2108   [(set (reg:CC_NOOV CC_REGNUM)
2109         (compare:CC_NOOV
2110          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2111                  (match_operand:SI 1 "s_register_operand" "r"))
2112          (const_int 0)))
2113    (clobber (match_scratch:SI 0 "=r"))]
2114   "TARGET_ARM"
2115   "bic%?s\\t%0, %1, %2"
2116   [(set_attr "conds" "set")]
2117 )
2118
2119 (define_insn "iordi3"
2120   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2121         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2122                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2123   "TARGET_ARM && ! TARGET_IWMMXT"
2124   "#"
2125   [(set_attr "length" "8")
2126    (set_attr "predicable" "yes")]
2127 )
2128
2129 (define_insn "*iordi_zesidi_di"
2130   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2131         (ior:DI (zero_extend:DI
2132                  (match_operand:SI 2 "s_register_operand" "r,r"))
2133                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2134   "TARGET_ARM"
2135   "@
2136    orr%?\\t%Q0, %Q1, %2
2137    #"
2138   [(set_attr "length" "4,8")
2139    (set_attr "predicable" "yes")]
2140 )
2141
2142 (define_insn "*iordi_sesidi_di"
2143   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2144         (ior:DI (sign_extend:DI
2145                  (match_operand:SI 2 "s_register_operand" "r,r"))
2146                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2147   "TARGET_ARM"
2148   "#"
2149   [(set_attr "length" "8")
2150    (set_attr "predicable" "yes")]
2151 )
2152
2153 (define_expand "iorsi3"
2154   [(set (match_operand:SI         0 "s_register_operand" "")
2155         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2156                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2157   "TARGET_EITHER"
2158   "
2159   if (GET_CODE (operands[2]) == CONST_INT)
2160     {
2161       if (TARGET_ARM)
2162         {
2163           arm_split_constant (IOR, SImode, NULL_RTX,
2164                               INTVAL (operands[2]), operands[0], operands[1],
2165                               optimize && !no_new_pseudos);
2166           DONE;
2167         }
2168       else /* TARGET_THUMB */
2169         operands [2] = force_reg (SImode, operands [2]);
2170     }
2171   "
2172 )
2173
2174 (define_insn_and_split "*arm_iorsi3"
2175   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2176         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2177                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2178   "TARGET_ARM"
2179   "@
2180    orr%?\\t%0, %1, %2
2181    #"
2182   "TARGET_ARM
2183    && GET_CODE (operands[2]) == CONST_INT
2184    && !const_ok_for_arm (INTVAL (operands[2]))"
2185   [(clobber (const_int 0))]
2186   "
2187   arm_split_constant (IOR, SImode, curr_insn, 
2188                       INTVAL (operands[2]), operands[0], operands[1], 0);
2189   DONE;
2190   "
2191   [(set_attr "length" "4,16")
2192    (set_attr "predicable" "yes")]
2193 )
2194
2195 (define_insn "*thumb_iorsi3"
2196   [(set (match_operand:SI         0 "register_operand" "=l")
2197         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2198                 (match_operand:SI 2 "register_operand" "l")))]
2199   "TARGET_THUMB"
2200   "orr\\t%0, %0, %2"
2201   [(set_attr "length" "2")]
2202 )
2203
2204 (define_peephole2
2205   [(match_scratch:SI 3 "r")
2206    (set (match_operand:SI 0 "arm_general_register_operand" "")
2207         (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2208                 (match_operand:SI 2 "const_int_operand" "")))]
2209   "TARGET_ARM
2210    && !const_ok_for_arm (INTVAL (operands[2]))
2211    && const_ok_for_arm (~INTVAL (operands[2]))"
2212   [(set (match_dup 3) (match_dup 2))
2213    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2214   ""
2215 )
2216
2217 (define_insn "*iorsi3_compare0"
2218   [(set (reg:CC_NOOV CC_REGNUM)
2219         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2220                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2221                          (const_int 0)))
2222    (set (match_operand:SI 0 "s_register_operand" "=r")
2223         (ior:SI (match_dup 1) (match_dup 2)))]
2224   "TARGET_ARM"
2225   "orr%?s\\t%0, %1, %2"
2226   [(set_attr "conds" "set")]
2227 )
2228
2229 (define_insn "*iorsi3_compare0_scratch"
2230   [(set (reg:CC_NOOV CC_REGNUM)
2231         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2232                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2233                          (const_int 0)))
2234    (clobber (match_scratch:SI 0 "=r"))]
2235   "TARGET_ARM"
2236   "orr%?s\\t%0, %1, %2"
2237   [(set_attr "conds" "set")]
2238 )
2239
2240 (define_insn "xordi3"
2241   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2242         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2243                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2244   "TARGET_ARM && !TARGET_IWMMXT"
2245   "#"
2246   [(set_attr "length" "8")
2247    (set_attr "predicable" "yes")]
2248 )
2249
2250 (define_insn "*xordi_zesidi_di"
2251   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2252         (xor:DI (zero_extend:DI
2253                  (match_operand:SI 2 "s_register_operand" "r,r"))
2254                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2255   "TARGET_ARM"
2256   "@
2257    eor%?\\t%Q0, %Q1, %2
2258    #"
2259   [(set_attr "length" "4,8")
2260    (set_attr "predicable" "yes")]
2261 )
2262
2263 (define_insn "*xordi_sesidi_di"
2264   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2265         (xor:DI (sign_extend:DI
2266                  (match_operand:SI 2 "s_register_operand" "r,r"))
2267                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2268   "TARGET_ARM"
2269   "#"
2270   [(set_attr "length" "8")
2271    (set_attr "predicable" "yes")]
2272 )
2273
2274 (define_expand "xorsi3"
2275   [(set (match_operand:SI         0 "s_register_operand" "")
2276         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2277                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2278   "TARGET_EITHER"
2279   "if (TARGET_THUMB)
2280      if (GET_CODE (operands[2]) == CONST_INT)
2281        operands[2] = force_reg (SImode, operands[2]);
2282   "
2283 )
2284
2285 (define_insn "*arm_xorsi3"
2286   [(set (match_operand:SI         0 "s_register_operand" "=r")
2287         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2288                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2289   "TARGET_ARM"
2290   "eor%?\\t%0, %1, %2"
2291   [(set_attr "predicable" "yes")]
2292 )
2293
2294 (define_insn "*thumb_xorsi3"
2295   [(set (match_operand:SI         0 "register_operand" "=l")
2296         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2297                 (match_operand:SI 2 "register_operand" "l")))]
2298   "TARGET_THUMB"
2299   "eor\\t%0, %0, %2"
2300   [(set_attr "length" "2")]
2301 )
2302
2303 (define_insn "*xorsi3_compare0"
2304   [(set (reg:CC_NOOV CC_REGNUM)
2305         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2306                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2307                          (const_int 0)))
2308    (set (match_operand:SI 0 "s_register_operand" "=r")
2309         (xor:SI (match_dup 1) (match_dup 2)))]
2310   "TARGET_ARM"
2311   "eor%?s\\t%0, %1, %2"
2312   [(set_attr "conds" "set")]
2313 )
2314
2315 (define_insn "*xorsi3_compare0_scratch"
2316   [(set (reg:CC_NOOV CC_REGNUM)
2317         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2318                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2319                          (const_int 0)))]
2320   "TARGET_ARM"
2321   "teq%?\\t%0, %1"
2322   [(set_attr "conds" "set")]
2323 )
2324
2325 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2326 ; (NOT D) we can sometimes merge the final NOT into one of the following
2327 ; insns.
2328
2329 (define_split
2330   [(set (match_operand:SI 0 "s_register_operand" "")
2331         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2332                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2333                 (match_operand:SI 3 "arm_rhs_operand" "")))
2334    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2335   "TARGET_ARM"
2336   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2337                               (not:SI (match_dup 3))))
2338    (set (match_dup 0) (not:SI (match_dup 4)))]
2339   ""
2340 )
2341
2342 (define_insn "*andsi_iorsi3_notsi"
2343   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2344         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2345                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2346                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2347   "TARGET_ARM"
2348   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2349   [(set_attr "length" "8")
2350    (set_attr "predicable" "yes")]
2351 )
2352
2353 (define_split
2354   [(set (match_operand:SI 0 "s_register_operand" "")
2355         (match_operator:SI 1 "logical_binary_operator"
2356          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2357                            (match_operand:SI 3 "const_int_operand" "")
2358                            (match_operand:SI 4 "const_int_operand" ""))
2359           (match_operator:SI 9 "logical_binary_operator"
2360            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2361                          (match_operand:SI 6 "const_int_operand" ""))
2362             (match_operand:SI 7 "s_register_operand" "")])]))
2363    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2364   "TARGET_ARM
2365    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2366    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2367   [(set (match_dup 8)
2368         (match_op_dup 1
2369          [(ashift:SI (match_dup 2) (match_dup 4))
2370           (match_dup 5)]))
2371    (set (match_dup 0)
2372         (match_op_dup 1
2373          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2374           (match_dup 7)]))]
2375   "
2376   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2377 ")
2378
2379 (define_split
2380   [(set (match_operand:SI 0 "s_register_operand" "")
2381         (match_operator:SI 1 "logical_binary_operator"
2382          [(match_operator:SI 9 "logical_binary_operator"
2383            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2384                          (match_operand:SI 6 "const_int_operand" ""))
2385             (match_operand:SI 7 "s_register_operand" "")])
2386           (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2387                            (match_operand:SI 3 "const_int_operand" "")
2388                            (match_operand:SI 4 "const_int_operand" ""))]))
2389    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2390   "TARGET_ARM
2391    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2392    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2393   [(set (match_dup 8)
2394         (match_op_dup 1
2395          [(ashift:SI (match_dup 2) (match_dup 4))
2396           (match_dup 5)]))
2397    (set (match_dup 0)
2398         (match_op_dup 1
2399          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2400           (match_dup 7)]))]
2401   "
2402   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2403 ")
2404
2405 (define_split
2406   [(set (match_operand:SI 0 "s_register_operand" "")
2407         (match_operator:SI 1 "logical_binary_operator"
2408          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2409                            (match_operand:SI 3 "const_int_operand" "")
2410                            (match_operand:SI 4 "const_int_operand" ""))
2411           (match_operator:SI 9 "logical_binary_operator"
2412            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2413                          (match_operand:SI 6 "const_int_operand" ""))
2414             (match_operand:SI 7 "s_register_operand" "")])]))
2415    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2416   "TARGET_ARM
2417    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2418    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2419   [(set (match_dup 8)
2420         (match_op_dup 1
2421          [(ashift:SI (match_dup 2) (match_dup 4))
2422           (match_dup 5)]))
2423    (set (match_dup 0)
2424         (match_op_dup 1
2425          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2426           (match_dup 7)]))]
2427   "
2428   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2429 ")
2430
2431 (define_split
2432   [(set (match_operand:SI 0 "s_register_operand" "")
2433         (match_operator:SI 1 "logical_binary_operator"
2434          [(match_operator:SI 9 "logical_binary_operator"
2435            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2436                          (match_operand:SI 6 "const_int_operand" ""))
2437             (match_operand:SI 7 "s_register_operand" "")])
2438           (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2439                            (match_operand:SI 3 "const_int_operand" "")
2440                            (match_operand:SI 4 "const_int_operand" ""))]))
2441    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2442   "TARGET_ARM
2443    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2444    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2445   [(set (match_dup 8)
2446         (match_op_dup 1
2447          [(ashift:SI (match_dup 2) (match_dup 4))
2448           (match_dup 5)]))
2449    (set (match_dup 0)
2450         (match_op_dup 1
2451          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2452           (match_dup 7)]))]
2453   "
2454   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2455 ")
2456 \f
2457
2458 ;; Minimum and maximum insns
2459
2460 (define_insn "smaxsi3"
2461   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2462         (smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2463                  (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2464    (clobber (reg:CC CC_REGNUM))]
2465   "TARGET_ARM"
2466   "@
2467    cmp\\t%1, %2\;movlt\\t%0, %2
2468    cmp\\t%1, %2\;movge\\t%0, %1
2469    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2470   [(set_attr "conds" "clob")
2471    (set_attr "length" "8,8,12")]
2472 )
2473
2474 (define_insn "sminsi3"
2475   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2476         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2477                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2478    (clobber (reg:CC CC_REGNUM))]
2479   "TARGET_ARM"
2480   "@
2481    cmp\\t%1, %2\;movge\\t%0, %2
2482    cmp\\t%1, %2\;movlt\\t%0, %1
2483    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2484   [(set_attr "conds" "clob")
2485    (set_attr "length" "8,8,12")]
2486 )
2487
2488 (define_insn "umaxsi3"
2489   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2490         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2491                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2492    (clobber (reg:CC CC_REGNUM))]
2493   "TARGET_ARM"
2494   "@
2495    cmp\\t%1, %2\;movcc\\t%0, %2
2496    cmp\\t%1, %2\;movcs\\t%0, %1
2497    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2498   [(set_attr "conds" "clob")
2499    (set_attr "length" "8,8,12")]
2500 )
2501
2502 (define_insn "uminsi3"
2503   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2504         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2505                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2506    (clobber (reg:CC CC_REGNUM))]
2507   "TARGET_ARM"
2508   "@
2509    cmp\\t%1, %2\;movcs\\t%0, %2
2510    cmp\\t%1, %2\;movcc\\t%0, %1
2511    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2512   [(set_attr "conds" "clob")
2513    (set_attr "length" "8,8,12")]
2514 )
2515
2516 (define_insn "*store_minmaxsi"
2517   [(set (match_operand:SI 0 "memory_operand" "=m")
2518         (match_operator:SI 3 "minmax_operator"
2519          [(match_operand:SI 1 "s_register_operand" "r")
2520           (match_operand:SI 2 "s_register_operand" "r")]))
2521    (clobber (reg:CC CC_REGNUM))]
2522   "TARGET_ARM"
2523   "*
2524   operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2525                                 operands[1], operands[2]);
2526   output_asm_insn (\"cmp\\t%1, %2\", operands);
2527   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2528   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2529   return \"\";
2530   "
2531   [(set_attr "conds" "clob")
2532    (set_attr "length" "12")
2533    (set_attr "type" "store1")]
2534 )
2535
2536 ; Reject the frame pointer in operand[1], since reloading this after
2537 ; it has been eliminated can cause carnage.
2538 (define_insn "*minmax_arithsi"
2539   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2540         (match_operator:SI 4 "shiftable_operator"
2541          [(match_operator:SI 5 "minmax_operator"
2542            [(match_operand:SI 2 "s_register_operand" "r,r")
2543             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2544           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2545    (clobber (reg:CC CC_REGNUM))]
2546   "TARGET_ARM && !arm_eliminable_register (operands[1])"
2547   "*
2548   {
2549     enum rtx_code code = GET_CODE (operands[4]);
2550
2551     operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2552                                   operands[2], operands[3]);
2553     output_asm_insn (\"cmp\\t%2, %3\", operands);
2554     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2555     if (which_alternative != 0 || operands[3] != const0_rtx
2556         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2557       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2558     return \"\";
2559   }"
2560   [(set_attr "conds" "clob")
2561    (set_attr "length" "12")]
2562 )
2563
2564 \f
2565 ;; Shift and rotation insns
2566
2567 (define_expand "ashldi3"
2568   [(set (match_operand:DI            0 "s_register_operand" "")
2569         (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2570                    (match_operand:SI 2 "reg_or_int_operand" "")))]
2571   "TARGET_ARM"
2572   "
2573   if (GET_CODE (operands[2]) == CONST_INT)
2574     {
2575       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2576         {
2577           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2578           DONE;
2579         }
2580         /* Ideally we shouldn't fail here if we could know that operands[1] 
2581            ends up already living in an iwmmxt register. Otherwise it's
2582            cheaper to have the alternate code being generated than moving
2583            values to iwmmxt regs and back.  */
2584         FAIL;
2585     }
2586   else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2587     FAIL;
2588   "
2589 )
2590
2591 (define_insn "arm_ashldi3_1bit"
2592   [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
2593         (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2594                    (const_int 1)))
2595    (clobber (reg:CC CC_REGNUM))]
2596   "TARGET_ARM"
2597   "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2598   [(set_attr "conds" "clob")
2599    (set_attr "length" "8")]
2600 )
2601
2602 (define_expand "ashlsi3"
2603   [(set (match_operand:SI            0 "s_register_operand" "")
2604         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2605                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2606   "TARGET_EITHER"
2607   "
2608   if (GET_CODE (operands[2]) == CONST_INT
2609       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2610     {
2611       emit_insn (gen_movsi (operands[0], const0_rtx));
2612       DONE;
2613     }
2614   "
2615 )
2616
2617 (define_insn "*thumb_ashlsi3"
2618   [(set (match_operand:SI            0 "register_operand" "=l,l")
2619         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2620                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2621   "TARGET_THUMB"
2622   "lsl\\t%0, %1, %2"
2623   [(set_attr "length" "2")]
2624 )
2625
2626 (define_expand "ashrdi3"
2627   [(set (match_operand:DI              0 "s_register_operand" "")
2628         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2629                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2630   "TARGET_ARM"
2631   "
2632   if (GET_CODE (operands[2]) == CONST_INT)
2633     {
2634       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2635         {
2636           emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2637           DONE;
2638         }
2639         /* Ideally we shouldn't fail here if we could know that operands[1] 
2640            ends up already living in an iwmmxt register. Otherwise it's
2641            cheaper to have the alternate code being generated than moving
2642            values to iwmmxt regs and back.  */
2643         FAIL;
2644     }
2645   else if (!TARGET_REALLY_IWMMXT)
2646     FAIL;
2647   "
2648 )
2649
2650 (define_insn "arm_ashrdi3_1bit"
2651   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2652         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2653                      (const_int 1)))
2654    (clobber (reg:CC CC_REGNUM))]
2655   "TARGET_ARM"
2656   "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2657   [(set_attr "conds" "clob")
2658    (set_attr "length" "8")]
2659 )
2660
2661 (define_expand "ashrsi3"
2662   [(set (match_operand:SI              0 "s_register_operand" "")
2663         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2664                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2665   "TARGET_EITHER"
2666   "
2667   if (GET_CODE (operands[2]) == CONST_INT
2668       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2669     operands[2] = GEN_INT (31);
2670   "
2671 )
2672
2673 (define_insn "*thumb_ashrsi3"
2674   [(set (match_operand:SI              0 "register_operand" "=l,l")
2675         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2676                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2677   "TARGET_THUMB"
2678   "asr\\t%0, %1, %2"
2679   [(set_attr "length" "2")]
2680 )
2681
2682 (define_expand "lshrdi3"
2683   [(set (match_operand:DI              0 "s_register_operand" "")
2684         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2685                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2686   "TARGET_ARM"
2687   "
2688   if (GET_CODE (operands[2]) == CONST_INT)
2689     {
2690       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2691         {
2692           emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2693           DONE;
2694         }
2695         /* Ideally we shouldn't fail here if we could know that operands[1] 
2696            ends up already living in an iwmmxt register. Otherwise it's
2697            cheaper to have the alternate code being generated than moving
2698            values to iwmmxt regs and back.  */
2699         FAIL;
2700     }
2701   else if (!TARGET_REALLY_IWMMXT)
2702     FAIL;
2703   "
2704 )
2705
2706 (define_insn "arm_lshrdi3_1bit"
2707   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2708         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2709                      (const_int 1)))
2710    (clobber (reg:CC CC_REGNUM))]
2711   "TARGET_ARM"
2712   "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2713   [(set_attr "conds" "clob")
2714    (set_attr "length" "8")]
2715 )
2716
2717 (define_expand "lshrsi3"
2718   [(set (match_operand:SI              0 "s_register_operand" "")
2719         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2720                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2721   "TARGET_EITHER"
2722   "
2723   if (GET_CODE (operands[2]) == CONST_INT
2724       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2725     {
2726       emit_insn (gen_movsi (operands[0], const0_rtx));
2727       DONE;
2728     }
2729   "
2730 )
2731
2732 (define_insn "*thumb_lshrsi3"
2733   [(set (match_operand:SI              0 "register_operand" "=l,l")
2734         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2735                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2736   "TARGET_THUMB"
2737   "lsr\\t%0, %1, %2"
2738   [(set_attr "length" "2")]
2739 )
2740
2741 (define_expand "rotlsi3"
2742   [(set (match_operand:SI              0 "s_register_operand" "")
2743         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2744                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2745   "TARGET_ARM"
2746   "
2747   if (GET_CODE (operands[2]) == CONST_INT)
2748     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2749   else
2750     {
2751       rtx reg = gen_reg_rtx (SImode);
2752       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2753       operands[2] = reg;
2754     }
2755   "
2756 )
2757
2758 (define_expand "rotrsi3"
2759   [(set (match_operand:SI              0 "s_register_operand" "")
2760         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2761                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2762   "TARGET_EITHER"
2763   "
2764   if (TARGET_ARM)
2765     {
2766       if (GET_CODE (operands[2]) == CONST_INT
2767           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2768         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2769     }
2770   else /* TARGET_THUMB */
2771     {
2772       if (GET_CODE (operands [2]) == CONST_INT)
2773         operands [2] = force_reg (SImode, operands[2]);
2774     }
2775   "
2776 )
2777
2778 (define_insn "*thumb_rotrsi3"
2779   [(set (match_operand:SI              0 "register_operand" "=l")
2780         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2781                      (match_operand:SI 2 "register_operand" "l")))]
2782   "TARGET_THUMB"
2783   "ror\\t%0, %0, %2"
2784   [(set_attr "length" "2")]
2785 )
2786
2787 (define_insn "*arm_shiftsi3"
2788   [(set (match_operand:SI   0 "s_register_operand" "=r")
2789         (match_operator:SI  3 "shift_operator"
2790          [(match_operand:SI 1 "s_register_operand"  "r")
2791           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2792   "TARGET_ARM"
2793   "mov%?\\t%0, %1%S3"
2794   [(set_attr "predicable" "yes")
2795    (set_attr "shift" "1")
2796    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2797                       (const_string "alu_shift")
2798                       (const_string "alu_shift_reg")))]
2799 )
2800
2801 (define_insn "*shiftsi3_compare0"
2802   [(set (reg:CC_NOOV CC_REGNUM)
2803         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2804                           [(match_operand:SI 1 "s_register_operand" "r")
2805                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2806                          (const_int 0)))
2807    (set (match_operand:SI 0 "s_register_operand" "=r")
2808         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2809   "TARGET_ARM"
2810   "mov%?s\\t%0, %1%S3"
2811   [(set_attr "conds" "set")
2812    (set_attr "shift" "1")
2813    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2814                       (const_string "alu_shift")
2815                       (const_string "alu_shift_reg")))]
2816 )
2817
2818 (define_insn "*shiftsi3_compare0_scratch"
2819   [(set (reg:CC_NOOV CC_REGNUM)
2820         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2821                           [(match_operand:SI 1 "s_register_operand" "r")
2822                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2823                          (const_int 0)))
2824    (clobber (match_scratch:SI 0 "=r"))]
2825   "TARGET_ARM"
2826   "mov%?s\\t%0, %1%S3"
2827   [(set_attr "conds" "set")
2828    (set_attr "shift" "1")]
2829 )
2830
2831 (define_insn "*notsi_shiftsi"
2832   [(set (match_operand:SI 0 "s_register_operand" "=r")
2833         (not:SI (match_operator:SI 3 "shift_operator"
2834                  [(match_operand:SI 1 "s_register_operand" "r")
2835                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2836   "TARGET_ARM"
2837   "mvn%?\\t%0, %1%S3"
2838   [(set_attr "predicable" "yes")
2839    (set_attr "shift" "1")
2840    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2841                       (const_string "alu_shift")
2842                       (const_string "alu_shift_reg")))]
2843 )
2844
2845 (define_insn "*notsi_shiftsi_compare0"
2846   [(set (reg:CC_NOOV CC_REGNUM)
2847         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2848                           [(match_operand:SI 1 "s_register_operand" "r")
2849                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2850                          (const_int 0)))
2851    (set (match_operand:SI 0 "s_register_operand" "=r")
2852         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2853   "TARGET_ARM"
2854   "mvn%?s\\t%0, %1%S3"
2855   [(set_attr "conds" "set")
2856    (set_attr "shift" "1")
2857    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2858                       (const_string "alu_shift")
2859                       (const_string "alu_shift_reg")))]
2860 )
2861
2862 (define_insn "*not_shiftsi_compare0_scratch"
2863   [(set (reg:CC_NOOV CC_REGNUM)
2864         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2865                           [(match_operand:SI 1 "s_register_operand" "r")
2866                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2867                          (const_int 0)))
2868    (clobber (match_scratch:SI 0 "=r"))]
2869   "TARGET_ARM"
2870   "mvn%?s\\t%0, %1%S3"
2871   [(set_attr "conds" "set")
2872    (set_attr "shift" "1")
2873    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2874                       (const_string "alu_shift")
2875                       (const_string "alu_shift_reg")))]
2876 )
2877
2878 ;; We don't really have extzv, but defining this using shifts helps
2879 ;; to reduce register pressure later on.
2880
2881 (define_expand "extzv"
2882   [(set (match_dup 4)
2883         (ashift:SI (match_operand:SI   1 "register_operand" "")
2884                    (match_operand:SI   2 "const_int_operand" "")))
2885    (set (match_operand:SI              0 "register_operand" "")
2886         (lshiftrt:SI (match_dup 4)
2887                      (match_operand:SI 3 "const_int_operand" "")))]
2888   "TARGET_THUMB"
2889   "
2890   {
2891     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2892     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2893     
2894     operands[3] = GEN_INT (rshift);
2895     
2896     if (lshift == 0)
2897       {
2898         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2899         DONE;
2900       }
2901       
2902     operands[2] = GEN_INT (lshift);
2903     operands[4] = gen_reg_rtx (SImode);
2904   }"
2905 )
2906
2907 \f
2908 ;; Unary arithmetic insns
2909
2910 (define_expand "negdi2"
2911  [(parallel
2912    [(set (match_operand:DI          0 "s_register_operand" "")
2913           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2914     (clobber (reg:CC CC_REGNUM))])]
2915   "TARGET_EITHER"
2916   "
2917   if (TARGET_THUMB)
2918     {
2919       if (GET_CODE (operands[1]) != REG)
2920         operands[1] = force_reg (SImode, operands[1]);
2921      }
2922   "
2923 )
2924
2925 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2926 ;; The second alternative is to allow the common case of a *full* overlap.
2927 (define_insn "*arm_negdi2"
2928   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2929         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2930    (clobber (reg:CC CC_REGNUM))]
2931   "TARGET_ARM"
2932   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2933   [(set_attr "conds" "clob")
2934    (set_attr "length" "8")]
2935 )
2936
2937 (define_insn "*thumb_negdi2"
2938   [(set (match_operand:DI         0 "register_operand" "=&l")
2939         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
2940    (clobber (reg:CC CC_REGNUM))]
2941   "TARGET_THUMB"
2942   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2943   [(set_attr "length" "6")]
2944 )
2945
2946 (define_expand "negsi2"
2947   [(set (match_operand:SI         0 "s_register_operand" "")
2948         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2949   "TARGET_EITHER"
2950   ""
2951 )
2952
2953 (define_insn "*arm_negsi2"
2954   [(set (match_operand:SI         0 "s_register_operand" "=r")
2955         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2956   "TARGET_ARM"
2957   "rsb%?\\t%0, %1, #0"
2958   [(set_attr "predicable" "yes")]
2959 )
2960
2961 (define_insn "*thumb_negsi2"
2962   [(set (match_operand:SI         0 "register_operand" "=l")
2963         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2964   "TARGET_THUMB"
2965   "neg\\t%0, %1"
2966   [(set_attr "length" "2")]
2967 )
2968
2969 (define_expand "negsf2"
2970   [(set (match_operand:SF         0 "s_register_operand" "")
2971         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2972   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2973   ""
2974 )
2975
2976 (define_expand "negdf2"
2977   [(set (match_operand:DF         0 "s_register_operand" "")
2978         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2979   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2980   "")
2981
2982 ;; abssi2 doesn't really clobber the condition codes if a different register
2983 ;; is being set.  To keep things simple, assume during rtl manipulations that
2984 ;; it does, but tell the final scan operator the truth.  Similarly for
2985 ;; (neg (abs...))
2986
2987 (define_expand "abssi2"
2988   [(parallel
2989     [(set (match_operand:SI         0 "s_register_operand" "")
2990           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
2991      (clobber (reg:CC CC_REGNUM))])]
2992   "TARGET_ARM"
2993   "")
2994
2995 (define_insn "*arm_abssi2"
2996   [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
2997         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2998    (clobber (reg:CC CC_REGNUM))]
2999   "TARGET_ARM"
3000   "@
3001    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3002    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3003   [(set_attr "conds" "clob,*")
3004    (set_attr "shift" "1")
3005    ;; predicable can't be set based on the variant, so left as no
3006    (set_attr "length" "8")]
3007 )
3008
3009 (define_insn "*neg_abssi2"
3010   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3011         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3012    (clobber (reg:CC CC_REGNUM))]
3013   "TARGET_ARM"
3014   "@
3015    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3016    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3017   [(set_attr "conds" "clob,*")
3018    (set_attr "shift" "1")
3019    ;; predicable can't be set based on the variant, so left as no
3020    (set_attr "length" "8")]
3021 )
3022
3023 (define_expand "abssf2"
3024   [(set (match_operand:SF         0 "s_register_operand" "")
3025         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3026   "TARGET_ARM && TARGET_HARD_FLOAT"
3027   "")
3028
3029 (define_expand "absdf2"
3030   [(set (match_operand:DF         0 "s_register_operand" "")
3031         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3032   "TARGET_ARM && TARGET_HARD_FLOAT"
3033   "")
3034
3035 (define_expand "sqrtsf2"
3036   [(set (match_operand:SF 0 "s_register_operand" "")
3037         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3038   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3039   "")
3040
3041 (define_expand "sqrtdf2"
3042   [(set (match_operand:DF 0 "s_register_operand" "")
3043         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3044   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3045   "")
3046
3047 (define_insn_and_split "one_cmpldi2"
3048   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3049         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3050   "TARGET_ARM"
3051   "#"
3052   "TARGET_ARM && reload_completed"
3053   [(set (match_dup 0) (not:SI (match_dup 1)))
3054    (set (match_dup 2) (not:SI (match_dup 3)))]
3055   "
3056   {
3057     operands[2] = gen_highpart (SImode, operands[0]);
3058     operands[0] = gen_lowpart (SImode, operands[0]);
3059     operands[3] = gen_highpart (SImode, operands[1]);
3060     operands[1] = gen_lowpart (SImode, operands[1]);
3061   }"
3062   [(set_attr "length" "8")
3063    (set_attr "predicable" "yes")]
3064 )
3065
3066 (define_expand "one_cmplsi2"
3067   [(set (match_operand:SI         0 "s_register_operand" "")
3068         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3069   "TARGET_EITHER"
3070   ""
3071 )
3072
3073 (define_insn "*arm_one_cmplsi2"
3074   [(set (match_operand:SI         0 "s_register_operand" "=r")
3075         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3076   "TARGET_ARM"
3077   "mvn%?\\t%0, %1"
3078   [(set_attr "predicable" "yes")]
3079 )
3080
3081 (define_insn "*thumb_one_cmplsi2"
3082   [(set (match_operand:SI         0 "register_operand" "=l")
3083         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3084   "TARGET_THUMB"
3085   "mvn\\t%0, %1"
3086   [(set_attr "length" "2")]
3087 )
3088
3089 (define_insn "*notsi_compare0"
3090   [(set (reg:CC_NOOV CC_REGNUM)
3091         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3092                          (const_int 0)))
3093    (set (match_operand:SI 0 "s_register_operand" "=r")
3094         (not:SI (match_dup 1)))]
3095   "TARGET_ARM"
3096   "mvn%?s\\t%0, %1"
3097   [(set_attr "conds" "set")]
3098 )
3099
3100 (define_insn "*notsi_compare0_scratch"
3101   [(set (reg:CC_NOOV CC_REGNUM)
3102         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3103                          (const_int 0)))
3104    (clobber (match_scratch:SI 0 "=r"))]
3105   "TARGET_ARM"
3106   "mvn%?s\\t%0, %1"
3107   [(set_attr "conds" "set")]
3108 )
3109 \f
3110 ;; Fixed <--> Floating conversion insns
3111
3112 (define_expand "floatsisf2"
3113   [(set (match_operand:SF           0 "s_register_operand" "")
3114         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3115   "TARGET_ARM && TARGET_HARD_FLOAT"
3116   "
3117   if (TARGET_MAVERICK)
3118     {
3119       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3120       DONE;
3121     }
3122 ")
3123
3124 (define_expand "floatsidf2"
3125   [(set (match_operand:DF           0 "s_register_operand" "")
3126         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3127   "TARGET_ARM && TARGET_HARD_FLOAT"
3128   "
3129   if (TARGET_MAVERICK)
3130     {
3131       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3132       DONE;
3133     }
3134 ")
3135
3136 (define_expand "fix_truncsfsi2"
3137   [(set (match_operand:SI         0 "s_register_operand" "")
3138         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3139   "TARGET_ARM && TARGET_HARD_FLOAT"
3140   "
3141   if (TARGET_MAVERICK)
3142     {
3143       if (!cirrus_fp_register (operands[0], SImode))
3144         operands[0] = force_reg (SImode, operands[0]);
3145       if (!cirrus_fp_register (operands[1], SFmode))
3146         operands[1] = force_reg (SFmode, operands[0]);
3147       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3148       DONE;
3149     }
3150 ")
3151
3152 (define_expand "fix_truncdfsi2"
3153   [(set (match_operand:SI         0 "s_register_operand" "")
3154         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3155   "TARGET_ARM && TARGET_HARD_FLOAT"
3156   "
3157   if (TARGET_MAVERICK)
3158     {
3159       if (!cirrus_fp_register (operands[1], DFmode))
3160         operands[1] = force_reg (DFmode, operands[0]);
3161       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3162       DONE;
3163     }
3164 ")
3165
3166 ;; Truncation insns
3167
3168 (define_expand "truncdfsf2"
3169   [(set (match_operand:SF  0 "s_register_operand" "")
3170         (float_truncate:SF
3171          (match_operand:DF 1 "s_register_operand" "")))]
3172   "TARGET_ARM && TARGET_HARD_FLOAT"
3173   ""
3174 )
3175 \f
3176 ;; Zero and sign extension instructions.
3177
3178 (define_insn "zero_extendsidi2"
3179   [(set (match_operand:DI 0 "s_register_operand" "=r")
3180         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3181   "TARGET_ARM"
3182   "*
3183     if (REGNO (operands[1])
3184         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3185       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3186     return \"mov%?\\t%R0, #0\";
3187   "
3188   [(set_attr "length" "8")
3189    (set_attr "predicable" "yes")]
3190 )
3191
3192 (define_insn "zero_extendqidi2"
3193   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3194         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3195   "TARGET_ARM"
3196   "@
3197    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3198    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3199   [(set_attr "length" "8")
3200    (set_attr "predicable" "yes")
3201    (set_attr "type" "*,load_byte")
3202    (set_attr "pool_range" "*,4092")
3203    (set_attr "neg_pool_range" "*,4084")]
3204 )
3205
3206 (define_insn "extendsidi2"
3207   [(set (match_operand:DI 0 "s_register_operand" "=r")
3208         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3209   "TARGET_ARM"
3210   "*
3211     if (REGNO (operands[1])
3212         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3213       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3214     return \"mov%?\\t%R0, %Q0, asr #31\";
3215   "
3216   [(set_attr "length" "8")
3217    (set_attr "shift" "1")
3218    (set_attr "predicable" "yes")]
3219 )
3220
3221 (define_expand "zero_extendhisi2"
3222   [(set (match_dup 2)
3223         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3224                    (const_int 16)))
3225    (set (match_operand:SI 0 "s_register_operand" "")
3226         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3227   "TARGET_EITHER"
3228   "
3229   {
3230     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3231       {
3232         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3233                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3234         DONE;
3235       }
3236
3237     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3238       {
3239         emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3240         DONE;
3241       }
3242
3243     if (!s_register_operand (operands[1], HImode))
3244       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3245
3246     if (arm_arch6)
3247       {
3248         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3249                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3250         DONE;
3251       }
3252
3253     operands[1] = gen_lowpart (SImode, operands[1]);
3254     operands[2] = gen_reg_rtx (SImode);
3255   }"
3256 )
3257
3258 (define_insn "*thumb_zero_extendhisi2"
3259   [(set (match_operand:SI 0 "register_operand" "=l")
3260         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3261   "TARGET_THUMB && !arm_arch6"
3262   "*
3263   rtx mem = XEXP (operands[1], 0);
3264
3265   if (GET_CODE (mem) == CONST)
3266     mem = XEXP (mem, 0);
3267     
3268   if (GET_CODE (mem) == LABEL_REF)
3269     return \"ldr\\t%0, %1\";
3270     
3271   if (GET_CODE (mem) == PLUS)
3272     {
3273       rtx a = XEXP (mem, 0);
3274       rtx b = XEXP (mem, 1);
3275
3276       /* This can happen due to bugs in reload.  */
3277       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3278         {
3279           rtx ops[2];
3280           ops[0] = operands[0];
3281           ops[1] = a;
3282       
3283           output_asm_insn (\"mov        %0, %1\", ops);
3284
3285           XEXP (mem, 0) = operands[0];
3286        }
3287
3288       else if (   GET_CODE (a) == LABEL_REF
3289                && GET_CODE (b) == CONST_INT)
3290         return \"ldr\\t%0, %1\";
3291     }
3292     
3293   return \"ldrh\\t%0, %1\";
3294   "
3295   [(set_attr "length" "4")
3296    (set_attr "type" "load_byte")
3297    (set_attr "pool_range" "60")]
3298 )
3299
3300 (define_insn "*thumb_zero_extendhisi2_v6"
3301   [(set (match_operand:SI 0 "register_operand" "=l,l")
3302         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3303   "TARGET_THUMB && arm_arch6"
3304   "*
3305   rtx mem;
3306
3307   if (which_alternative == 0)
3308     return \"uxth\\t%0, %1\";
3309
3310   mem = XEXP (operands[1], 0);
3311
3312   if (GET_CODE (mem) == CONST)
3313     mem = XEXP (mem, 0);
3314     
3315   if (GET_CODE (mem) == LABEL_REF)
3316     return \"ldr\\t%0, %1\";
3317     
3318   if (GET_CODE (mem) == PLUS)
3319     {
3320       rtx a = XEXP (mem, 0);
3321       rtx b = XEXP (mem, 1);
3322
3323       /* This can happen due to bugs in reload.  */
3324       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3325         {
3326           rtx ops[2];
3327           ops[0] = operands[0];
3328           ops[1] = a;
3329       
3330           output_asm_insn (\"mov        %0, %1\", ops);
3331
3332           XEXP (mem, 0) = operands[0];
3333        }
3334
3335       else if (   GET_CODE (a) == LABEL_REF
3336                && GET_CODE (b) == CONST_INT)
3337         return \"ldr\\t%0, %1\";
3338     }
3339     
3340   return \"ldrh\\t%0, %1\";
3341   "
3342   [(set_attr "length" "2,4")
3343    (set_attr "type" "alu_shift,load_byte")
3344    (set_attr "pool_range" "*,60")]
3345 )
3346
3347 (define_insn "*arm_zero_extendhisi2"
3348   [(set (match_operand:SI 0 "s_register_operand" "=r")
3349         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3350   "TARGET_ARM && arm_arch4 && !arm_arch6"
3351   "ldr%?h\\t%0, %1"
3352   [(set_attr "type" "load_byte")
3353    (set_attr "predicable" "yes")
3354    (set_attr "pool_range" "256")
3355    (set_attr "neg_pool_range" "244")]
3356 )
3357
3358 (define_insn "*arm_zero_extendhisi2_v6"
3359   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3360         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3361   "TARGET_ARM && arm_arch6"
3362   "@
3363    uxth%?\\t%0, %1
3364    ldr%?h\\t%0, %1"
3365   [(set_attr "type" "alu_shift,load_byte")
3366    (set_attr "predicable" "yes")
3367    (set_attr "pool_range" "*,256")
3368    (set_attr "neg_pool_range" "*,244")]
3369 )
3370
3371 (define_insn "*arm_zero_extendhisi2addsi"
3372   [(set (match_operand:SI 0 "s_register_operand" "=r")
3373         (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3374                  (match_operand:SI 2 "s_register_operand" "r")))]
3375   "TARGET_ARM && arm_arch6"
3376   "uxtah%?\\t%0, %2, %1"
3377   [(set_attr "type" "alu_shift")
3378    (set_attr "predicable" "yes")]
3379 )
3380
3381 (define_split
3382   [(set (match_operand:SI 0 "s_register_operand" "")
3383         (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3384    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3385   "TARGET_ARM && (!arm_arch4)"
3386   [(set (match_dup 2) (match_dup 1))
3387    (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3388   "
3389   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3390     FAIL;
3391   "
3392 )
3393
3394 (define_split
3395   [(set (match_operand:SI 0 "s_register_operand" "")
3396         (match_operator:SI 3 "shiftable_operator"
3397          [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3398           (match_operand:SI 4 "s_register_operand" "")]))
3399    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3400   "TARGET_ARM && (!arm_arch4)"
3401   [(set (match_dup 2) (match_dup 1))
3402    (set (match_dup 0)
3403         (match_op_dup 3
3404          [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3405   "
3406   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3407     FAIL;
3408   "
3409 )
3410
3411 (define_expand "zero_extendqisi2"
3412   [(set (match_operand:SI 0 "s_register_operand" "")
3413         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3414   "TARGET_EITHER"
3415   "
3416   if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3417     {
3418       if (TARGET_ARM)
3419         {
3420           emit_insn (gen_andsi3 (operands[0],
3421                                  gen_lowpart (SImode, operands[1]),
3422                                  GEN_INT (255)));
3423         }
3424       else /* TARGET_THUMB */
3425         {
3426           rtx temp = gen_reg_rtx (SImode);
3427           rtx ops[3];
3428           
3429           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3430           operands[1] = gen_lowpart (SImode, operands[1]);
3431
3432           ops[0] = temp;
3433           ops[1] = operands[1];
3434           ops[2] = GEN_INT (24);
3435
3436           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3437                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3438           
3439           ops[0] = operands[0];
3440           ops[1] = temp;
3441           ops[2] = GEN_INT (24);
3442
3443           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3444                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3445         }
3446       DONE;
3447     }
3448   "
3449 )
3450
3451 (define_insn "*thumb_zero_extendqisi2"
3452   [(set (match_operand:SI 0 "register_operand" "=l")
3453         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3454   "TARGET_THUMB && !arm_arch6"
3455   "ldrb\\t%0, %1"
3456   [(set_attr "length" "2")
3457    (set_attr "type" "load_byte")
3458    (set_attr "pool_range" "32")]
3459 )
3460
3461 (define_insn "*thumb_zero_extendqisi2_v6"
3462   [(set (match_operand:SI 0 "register_operand" "=l,l")
3463         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3464   "TARGET_THUMB && arm_arch6"
3465   "@
3466    uxtb\\t%0, %1
3467    ldrb\\t%0, %1"
3468   [(set_attr "length" "2,2")
3469    (set_attr "type" "alu_shift,load_byte")
3470    (set_attr "pool_range" "*,32")]
3471 )
3472
3473 (define_insn "*arm_zero_extendqisi2"
3474   [(set (match_operand:SI 0 "s_register_operand" "=r")
3475         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3476   "TARGET_ARM && !arm_arch6"
3477   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3478   [(set_attr "type" "load_byte")
3479    (set_attr "predicable" "yes")
3480    (set_attr "pool_range" "4096")
3481    (set_attr "neg_pool_range" "4084")]
3482 )
3483
3484 (define_insn "*arm_zero_extendqisi2_v6"
3485   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3486         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3487   "TARGET_ARM && arm_arch6"
3488   "@
3489    uxtb%?\\t%0, %1
3490    ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3491   [(set_attr "type" "alu_shift,load_byte")
3492    (set_attr "predicable" "yes")
3493    (set_attr "pool_range" "*,4096")
3494    (set_attr "neg_pool_range" "*,4084")]
3495 )
3496
3497 (define_insn "*arm_zero_extendqisi2addsi"
3498   [(set (match_operand:SI 0 "s_register_operand" "=r")
3499         (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3500                  (match_operand:SI 2 "s_register_operand" "r")))]
3501   "TARGET_ARM && arm_arch6"
3502   "uxtab%?\\t%0, %2, %1"
3503   [(set_attr "predicable" "yes")
3504    (set_attr "type" "alu_shift")]
3505 )
3506
3507 (define_split
3508   [(set (match_operand:SI 0 "s_register_operand" "")
3509         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3510    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3511   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3512   [(set (match_dup 2) (match_dup 1))
3513    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3514   ""
3515 )
3516
3517 (define_insn "*compareqi_eq0"
3518   [(set (reg:CC_Z CC_REGNUM)
3519         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3520                          (const_int 0)))]
3521   "TARGET_ARM"
3522   "tst\\t%0, #255"
3523   [(set_attr "conds" "set")]
3524 )
3525
3526 (define_expand "extendhisi2"
3527   [(set (match_dup 2)
3528         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3529                    (const_int 16)))
3530    (set (match_operand:SI 0 "s_register_operand" "")
3531         (ashiftrt:SI (match_dup 2)
3532                      (const_int 16)))]
3533   "TARGET_EITHER"
3534   "
3535   {
3536     if (GET_CODE (operands[1]) == MEM)
3537       {
3538         if (TARGET_THUMB)
3539           {
3540             emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3541             DONE;
3542           }
3543         else if (arm_arch4)
3544           {
3545             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3546                        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3547             DONE;
3548           }
3549       }
3550
3551     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3552       {
3553         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3554         DONE;
3555       }
3556
3557     if (!s_register_operand (operands[1], HImode))
3558       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3559
3560     if (arm_arch6)
3561       {
3562         if (TARGET_THUMB)
3563           emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3564         else
3565           emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3566                      gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3567
3568         DONE;
3569       }
3570
3571     operands[1] = gen_lowpart (SImode, operands[1]);
3572     operands[2] = gen_reg_rtx (SImode);
3573   }"
3574 )
3575
3576 (define_insn "thumb_extendhisi2"
3577   [(set (match_operand:SI 0 "register_operand" "=l")
3578         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3579    (clobber (match_scratch:SI 2 "=&l"))]
3580   "TARGET_THUMB && !arm_arch6"
3581   "*
3582   {
3583     rtx ops[4];
3584     rtx mem = XEXP (operands[1], 0);
3585
3586     /* This code used to try to use 'V', and fix the address only if it was
3587        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3588        range of QImode offsets, and offsettable_address_p does a QImode
3589        address check.  */
3590        
3591     if (GET_CODE (mem) == CONST)
3592       mem = XEXP (mem, 0);
3593     
3594     if (GET_CODE (mem) == LABEL_REF)
3595       return \"ldr\\t%0, %1\";
3596     
3597     if (GET_CODE (mem) == PLUS)
3598       {
3599         rtx a = XEXP (mem, 0);
3600         rtx b = XEXP (mem, 1);
3601
3602         if (GET_CODE (a) == LABEL_REF
3603             && GET_CODE (b) == CONST_INT)
3604           return \"ldr\\t%0, %1\";
3605
3606         if (GET_CODE (b) == REG)
3607           return \"ldrsh\\t%0, %1\";
3608           
3609         ops[1] = a;
3610         ops[2] = b;
3611       }
3612     else
3613       {
3614         ops[1] = mem;
3615         ops[2] = const0_rtx;
3616       }
3617       
3618     if (GET_CODE (ops[1]) != REG)
3619       {
3620         debug_rtx (ops[1]);
3621         abort ();
3622       }
3623
3624     ops[0] = operands[0];
3625     ops[3] = operands[2];
3626     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3627     return \"\";
3628   }"
3629   [(set_attr "length" "4")
3630    (set_attr "type" "load_byte")
3631    (set_attr "pool_range" "1020")]
3632 )
3633
3634 ;; We used to have an early-clobber on the scratch register here.
3635 ;; However, there's a bug somewhere in reload which means that this
3636 ;; can be partially ignored during spill allocation if the memory
3637 ;; address also needs reloading; this causes an abort later on when
3638 ;; we try to verify the operands.  Fortunately, we don't really need
3639 ;; the early-clobber: we can always use operand 0 if operand 2
3640 ;; overlaps the address.
3641 (define_insn "*thumb_extendhisi2_insn_v6"
3642   [(set (match_operand:SI 0 "register_operand" "=l,l")
3643         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3644    (clobber (match_scratch:SI 2 "=X,l"))]
3645   "TARGET_THUMB && arm_arch6"
3646   "*
3647   {
3648     rtx ops[4];
3649     rtx mem;
3650
3651     if (which_alternative == 0)
3652       return \"sxth\\t%0, %1\";
3653
3654     mem = XEXP (operands[1], 0);
3655
3656     /* This code used to try to use 'V', and fix the address only if it was
3657        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3658        range of QImode offsets, and offsettable_address_p does a QImode
3659        address check.  */
3660        
3661     if (GET_CODE (mem) == CONST)
3662       mem = XEXP (mem, 0);
3663     
3664     if (GET_CODE (mem) == LABEL_REF)
3665       return \"ldr\\t%0, %1\";
3666     
3667     if (GET_CODE (mem) == PLUS)
3668       {
3669         rtx a = XEXP (mem, 0);
3670         rtx b = XEXP (mem, 1);
3671
3672         if (GET_CODE (a) == LABEL_REF
3673             && GET_CODE (b) == CONST_INT)
3674           return \"ldr\\t%0, %1\";
3675
3676         if (GET_CODE (b) == REG)
3677           return \"ldrsh\\t%0, %1\";
3678           
3679         ops[1] = a;
3680         ops[2] = b;
3681       }
3682     else
3683       {
3684         ops[1] = mem;
3685         ops[2] = const0_rtx;
3686       }
3687       
3688     if (GET_CODE (ops[1]) != REG)
3689       {
3690         debug_rtx (ops[1]);
3691         abort ();
3692       }
3693
3694     ops[0] = operands[0];
3695     if (reg_mentioned_p (operands[2], ops[1]))
3696       ops[3] = ops[0];
3697     else
3698       ops[3] = operands[2];
3699     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3700     return \"\";
3701   }"
3702   [(set_attr "length" "2,4")
3703    (set_attr "type" "alu_shift,load_byte")
3704    (set_attr "pool_range" "*,1020")]
3705 )
3706
3707 (define_expand "extendhisi2_mem"
3708   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3709    (set (match_dup 3)
3710         (zero_extend:SI (match_dup 7)))
3711    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3712    (set (match_operand:SI 0 "" "")
3713         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3714   "TARGET_ARM"
3715   "
3716   {
3717     rtx mem1, mem2;
3718     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3719
3720     mem1 = gen_rtx_MEM (QImode, addr);
3721     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3722     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3723     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3724     operands[0] = gen_lowpart (SImode, operands[0]);
3725     operands[1] = mem1;
3726     operands[2] = gen_reg_rtx (SImode);
3727     operands[3] = gen_reg_rtx (SImode);
3728     operands[6] = gen_reg_rtx (SImode);
3729     operands[7] = mem2;
3730
3731     if (BYTES_BIG_ENDIAN)
3732       {
3733         operands[4] = operands[2];
3734         operands[5] = operands[3];
3735       }
3736     else
3737       {
3738         operands[4] = operands[3];
3739         operands[5] = operands[2];
3740       }
3741   }"
3742 )
3743
3744 (define_insn "*arm_extendhisi2"
3745   [(set (match_operand:SI 0 "s_register_operand" "=r")
3746         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3747   "TARGET_ARM && arm_arch4 && !arm_arch6"
3748   "ldr%?sh\\t%0, %1"
3749   [(set_attr "type" "load_byte")
3750    (set_attr "predicable" "yes")
3751    (set_attr "pool_range" "256")
3752    (set_attr "neg_pool_range" "244")]
3753 )
3754
3755 (define_insn "*arm_extendhisi2_v6"
3756   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3757         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3758   "TARGET_ARM && arm_arch6"
3759   "@
3760    sxth%?\\t%0, %1
3761    ldr%?sh\\t%0, %1"
3762   [(set_attr "type" "alu_shift,load_byte")
3763    (set_attr "predicable" "yes")
3764    (set_attr "pool_range" "*,256")
3765    (set_attr "neg_pool_range" "*,244")]
3766 )
3767
3768 (define_insn "*arm_extendhisi2addsi"
3769   [(set (match_operand:SI 0 "s_register_operand" "=r")
3770         (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3771                  (match_operand:SI 2 "s_register_operand" "r")))]
3772   "TARGET_ARM && arm_arch6"
3773   "sxtah%?\\t%0, %2, %1"
3774 )
3775
3776 (define_split
3777   [(set (match_operand:SI                 0 "s_register_operand" "")
3778         (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3779    (clobber (match_operand:SI             2 "s_register_operand" ""))]
3780   "TARGET_ARM && (!arm_arch4)"
3781   [(set (match_dup 2) (match_dup 1))
3782    (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3783   "
3784   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3785     FAIL;
3786   "
3787 )
3788
3789 (define_split
3790   [(set (match_operand:SI                   0 "s_register_operand" "")
3791         (match_operator:SI                  3 "shiftable_operator"
3792          [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3793           (match_operand:SI                 4 "s_register_operand" "")]))
3794    (clobber (match_operand:SI               2 "s_register_operand" ""))]
3795   "TARGET_ARM && (!arm_arch4)"
3796   [(set (match_dup 2) (match_dup 1))
3797    (set (match_dup 0)
3798         (match_op_dup 3
3799          [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3800   "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3801      FAIL;
3802   "
3803 )
3804
3805 (define_expand "extendqihi2"
3806   [(set (match_dup 2)
3807         (ashift:SI (match_operand:QI 1 "general_operand" "")
3808                    (const_int 24)))
3809    (set (match_operand:HI 0 "s_register_operand" "")
3810         (ashiftrt:SI (match_dup 2)
3811                      (const_int 24)))]
3812   "TARGET_ARM"
3813   "
3814   {
3815     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3816       {
3817         emit_insn (gen_rtx_SET (VOIDmode,
3818                                 operands[0],
3819                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3820         DONE;
3821       }
3822     if (!s_register_operand (operands[1], QImode))
3823       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3824     operands[0] = gen_lowpart (SImode, operands[0]);
3825     operands[1] = gen_lowpart (SImode, operands[1]);
3826     operands[2] = gen_reg_rtx (SImode);
3827   }"
3828 )
3829
3830 (define_insn "*extendqihi_insn"
3831   [(set (match_operand:HI 0 "s_register_operand" "=r")
3832         (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3833   "TARGET_ARM && arm_arch4"
3834   "ldr%?sb\\t%0, %1"
3835   [(set_attr "type" "load_byte")
3836    (set_attr "predicable" "yes")
3837    (set_attr "pool_range" "256")
3838    (set_attr "neg_pool_range" "244")]
3839 )
3840
3841 (define_expand "extendqisi2"
3842   [(set (match_dup 2)
3843         (ashift:SI (match_operand:QI 1 "general_operand" "")
3844                    (const_int 24)))
3845    (set (match_operand:SI 0 "s_register_operand" "")
3846         (ashiftrt:SI (match_dup 2)
3847                      (const_int 24)))]
3848   "TARGET_EITHER"
3849   "
3850   {
3851     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3852       {
3853         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3854                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3855         DONE;
3856       }
3857
3858     if (!s_register_operand (operands[1], QImode))
3859       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3860
3861     if (arm_arch6)
3862       {
3863         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3864                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3865         DONE;
3866       }
3867
3868     operands[1] = gen_lowpart (SImode, operands[1]);
3869     operands[2] = gen_reg_rtx (SImode);
3870   }"
3871 )
3872
3873 (define_insn "*arm_extendqisi"
3874   [(set (match_operand:SI 0 "s_register_operand" "=r")
3875         (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3876   "TARGET_ARM && arm_arch4 && !arm_arch6"
3877   "ldr%?sb\\t%0, %1"
3878   [(set_attr "type" "load_byte")
3879    (set_attr "predicable" "yes")
3880    (set_attr "pool_range" "256")
3881    (set_attr "neg_pool_range" "244")]
3882 )
3883
3884 (define_insn "*arm_extendqisi_v6"
3885   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3886         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3887   "TARGET_ARM && arm_arch6"
3888   "@
3889    sxtb%?\\t%0, %1
3890    ldr%?sb\\t%0, %1"
3891   [(set_attr "type" "alu_shift,load_byte")
3892    (set_attr "predicable" "yes")
3893    (set_attr "pool_range" "*,256")
3894    (set_attr "neg_pool_range" "*,244")]
3895 )
3896
3897 (define_insn "*arm_extendqisi2addsi"
3898   [(set (match_operand:SI 0 "s_register_operand" "=r")
3899         (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3900                  (match_operand:SI 2 "s_register_operand" "r")))]
3901   "TARGET_ARM && arm_arch6"
3902   "sxtab%?\\t%0, %2, %1"
3903   [(set_attr "type" "alu_shift")
3904    (set_attr "predicable" "yes")]
3905 )
3906
3907 (define_insn "*thumb_extendqisi2"
3908   [(set (match_operand:SI 0 "register_operand" "=l,l")
3909         (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3910   "TARGET_THUMB && !arm_arch6"
3911   "*
3912   {
3913     rtx ops[3];
3914     rtx mem = XEXP (operands[1], 0);
3915     
3916     if (GET_CODE (mem) == CONST)
3917       mem = XEXP (mem, 0);
3918     
3919     if (GET_CODE (mem) == LABEL_REF)
3920       return \"ldr\\t%0, %1\";
3921
3922     if (GET_CODE (mem) == PLUS
3923         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3924       return \"ldr\\t%0, %1\";
3925       
3926     if (which_alternative == 0)
3927       return \"ldrsb\\t%0, %1\";
3928       
3929     ops[0] = operands[0];
3930     
3931     if (GET_CODE (mem) == PLUS)
3932       {
3933         rtx a = XEXP (mem, 0);
3934         rtx b = XEXP (mem, 1);
3935         
3936         ops[1] = a;
3937         ops[2] = b;
3938
3939         if (GET_CODE (a) == REG)
3940           {
3941             if (GET_CODE (b) == REG)
3942               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3943             else if (REGNO (a) == REGNO (ops[0]))
3944               {
3945                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3946                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3947                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3948               }
3949             else
3950               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3951           }
3952         else if (GET_CODE (b) != REG)
3953           abort ();
3954         else
3955           {
3956             if (REGNO (b) == REGNO (ops[0]))
3957               {
3958                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3959                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3960                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3961               }
3962             else
3963               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3964           }
3965       }
3966     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3967       {
3968         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", 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       {
3974         ops[1] = mem;
3975         ops[2] = const0_rtx;
3976         
3977         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3978       }
3979     return \"\";
3980   }"
3981   [(set_attr "length" "2,6")
3982    (set_attr "type" "load_byte,load_byte")
3983    (set_attr "pool_range" "32,32")]
3984 )
3985
3986 (define_insn "*thumb_extendqisi2_v6"
3987   [(set (match_operand:SI 0 "register_operand" "=l,l,l")
3988         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
3989   "TARGET_THUMB && arm_arch6"
3990   "*
3991   {
3992     rtx ops[3];
3993     rtx mem;
3994
3995     if (which_alternative == 0)
3996       return \"sxtb\\t%0, %1\";
3997
3998     mem = XEXP (operands[1], 0);
3999     
4000     if (GET_CODE (mem) == CONST)
4001       mem = XEXP (mem, 0);
4002     
4003     if (GET_CODE (mem) == LABEL_REF)
4004       return \"ldr\\t%0, %1\";
4005
4006     if (GET_CODE (mem) == PLUS
4007         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4008       return \"ldr\\t%0, %1\";
4009       
4010     if (which_alternative == 0)
4011       return \"ldrsb\\t%0, %1\";
4012       
4013     ops[0] = operands[0];
4014     
4015     if (GET_CODE (mem) == PLUS)
4016       {
4017         rtx a = XEXP (mem, 0);
4018         rtx b = XEXP (mem, 1);
4019         
4020         ops[1] = a;
4021         ops[2] = b;
4022
4023         if (GET_CODE (a) == REG)
4024           {
4025             if (GET_CODE (b) == REG)
4026               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4027             else if (REGNO (a) == REGNO (ops[0]))
4028               {
4029                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4030                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4031               }
4032             else
4033               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4034           }
4035         else if (GET_CODE (b) != REG)
4036           abort ();
4037         else
4038           {
4039             if (REGNO (b) == REGNO (ops[0]))
4040               {
4041                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4042                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4043               }
4044             else
4045               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4046           }
4047       }
4048     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4049       {
4050         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4051         output_asm_insn (\"sxtb\\t%0, %0\", ops);
4052       }
4053     else
4054       {
4055         ops[1] = mem;
4056         ops[2] = const0_rtx;
4057         
4058         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4059       }
4060     return \"\";
4061   }"
4062   [(set_attr "length" "2,2,4")
4063    (set_attr "type" "alu_shift,load_byte,load_byte")
4064    (set_attr "pool_range" "*,32,32")]
4065 )
4066
4067 (define_expand "extendsfdf2"
4068   [(set (match_operand:DF                  0 "s_register_operand" "")
4069         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
4070   "TARGET_ARM && TARGET_HARD_FLOAT"
4071   ""
4072 )
4073 \f
4074 ;; Move insns (including loads and stores)
4075
4076 ;; XXX Just some ideas about movti.
4077 ;; I don't think these are a good idea on the arm, there just aren't enough
4078 ;; registers
4079 ;;(define_expand "loadti"
4080 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
4081 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
4082 ;;  "" "")
4083
4084 ;;(define_expand "storeti"
4085 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4086 ;;      (match_operand:TI 1 "s_register_operand" ""))]
4087 ;;  "" "")
4088
4089 ;;(define_expand "movti"
4090 ;;  [(set (match_operand:TI 0 "general_operand" "")
4091 ;;      (match_operand:TI 1 "general_operand" ""))]
4092 ;;  ""
4093 ;;  "
4094 ;;{
4095 ;;  rtx insn;
4096 ;;
4097 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4098 ;;    operands[1] = copy_to_reg (operands[1]);
4099 ;;  if (GET_CODE (operands[0]) == MEM)
4100 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4101 ;;  else if (GET_CODE (operands[1]) == MEM)
4102 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4103 ;;  else
4104 ;;    FAIL;
4105 ;;
4106 ;;  emit_insn (insn);
4107 ;;  DONE;
4108 ;;}")
4109
4110 ;; Recognize garbage generated above.
4111
4112 ;;(define_insn ""
4113 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4114 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4115 ;;  ""
4116 ;;  "*
4117 ;;  {
4118 ;;    register mem = (which_alternative < 3);
4119 ;;    register const char *template;
4120 ;;
4121 ;;    operands[mem] = XEXP (operands[mem], 0);
4122 ;;    switch (which_alternative)
4123 ;;      {
4124 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4125 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
4126 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
4127 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
4128 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
4129 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
4130 ;;      }
4131 ;;    output_asm_insn (template, operands);
4132 ;;    return \"\";
4133 ;;  }")
4134
4135 (define_expand "movdi"
4136   [(set (match_operand:DI 0 "general_operand" "")
4137         (match_operand:DI 1 "general_operand" ""))]
4138   "TARGET_EITHER"
4139   "
4140   if (TARGET_THUMB)
4141     {
4142       if (!no_new_pseudos)
4143         {
4144           if (GET_CODE (operands[0]) != REG)
4145             operands[1] = force_reg (DImode, operands[1]);
4146         }
4147     }
4148   "
4149 )
4150
4151 (define_insn "*arm_movdi"
4152   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4153         (match_operand:DI 1 "di_operand"              "rDa,Db,Dc,mi,r"))]
4154   "TARGET_ARM
4155   && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4156   && !TARGET_IWMMXT"
4157   "*
4158   switch (which_alternative)
4159     {
4160     case 0:
4161     case 1:
4162     case 2:
4163       return \"#\";
4164     default:
4165       return output_move_double (operands);
4166     }
4167   "
4168   [(set_attr "length" "8,12,16,8,8")
4169    (set_attr "type" "*,*,*,load2,store2")
4170    (set_attr "pool_range" "*,*,*,1020,*")
4171    (set_attr "neg_pool_range" "*,*,*,1008,*")]
4172 )
4173
4174 (define_split
4175   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4176         (match_operand:ANY64 1 "const_double_operand" ""))]
4177   "TARGET_ARM
4178    && reload_completed
4179    && (arm_const_double_inline_cost (operands[1])
4180        <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4181   [(const_int 0)]
4182   "
4183   arm_split_constant (SET, SImode, curr_insn,
4184                       INTVAL (gen_lowpart (SImode, operands[1])),
4185                       gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4186   arm_split_constant (SET, SImode, curr_insn,
4187                       INTVAL (gen_highpart_mode (SImode,
4188                                                  GET_MODE (operands[0]),
4189                                                  operands[1])),
4190                       gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4191   DONE;
4192   "
4193 )
4194
4195 (define_split
4196   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4197         (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4198   "TARGET_EITHER && reload_completed"
4199   [(set (match_dup 0) (match_dup 1))
4200    (set (match_dup 2) (match_dup 3))]
4201   "
4202   operands[2] = gen_highpart (SImode, operands[0]);
4203   operands[3] = gen_highpart (SImode, operands[1]);
4204   operands[0] = gen_lowpart (SImode, operands[0]);
4205   operands[1] = gen_lowpart (SImode, operands[1]);
4206
4207   /* Handle a partial overlap.  */
4208   if (rtx_equal_p (operands[0], operands[3]))
4209     {
4210       rtx tmp0 = operands[0];
4211       rtx tmp1 = operands[1];
4212
4213       operands[0] = operands[2];
4214       operands[1] = operands[3];
4215       operands[2] = tmp0;
4216       operands[3] = tmp1;
4217     }
4218   "
4219 )
4220
4221 ;; We can't actually do base+index doubleword loads if the index and
4222 ;; destination overlap.  Split here so that we at least have chance to
4223 ;; schedule.
4224 (define_split
4225   [(set (match_operand:DI 0 "s_register_operand" "")
4226         (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4227                          (match_operand:SI 2 "s_register_operand" ""))))]
4228   "TARGET_LDRD
4229   && reg_overlap_mentioned_p (operands[0], operands[1])
4230   && reg_overlap_mentioned_p (operands[0], operands[2])"
4231   [(set (match_dup 4)
4232         (plus:SI (match_dup 1)
4233                  (match_dup 2)))
4234    (set (match_dup 0)
4235         (mem:DI (match_dup 4)))]
4236   "
4237   operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4238   "
4239 )
4240
4241 ;;; ??? This should have alternatives for constants.
4242 ;;; ??? This was originally identical to the movdf_insn pattern.
4243 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4244 ;;; thumb_reorg with a memory reference.
4245 (define_insn "*thumb_movdi_insn"
4246   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4247         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
4248   "TARGET_THUMB
4249    && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4250    && (   register_operand (operands[0], DImode)
4251        || register_operand (operands[1], DImode))"
4252   "*
4253   {
4254   switch (which_alternative)
4255     {
4256     default:
4257     case 0:
4258       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4259         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
4260       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
4261     case 1:
4262       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4263     case 2:
4264       operands[1] = GEN_INT (- INTVAL (operands[1]));
4265       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4266     case 3:
4267       return \"ldmia\\t%1, {%0, %H0}\";
4268     case 4:
4269       return \"stmia\\t%0, {%1, %H1}\";
4270     case 5:
4271       return thumb_load_double_from_address (operands);
4272     case 6:
4273       operands[2] = gen_rtx_MEM (SImode,
4274                              plus_constant (XEXP (operands[0], 0), 4));
4275       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4276       return \"\";
4277     case 7:
4278       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4279         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4280       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4281     }
4282   }"
4283   [(set_attr "length" "4,4,6,2,2,6,4,4")
4284    (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4285    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4286 )
4287
4288 (define_expand "movsi"
4289   [(set (match_operand:SI 0 "general_operand" "")
4290         (match_operand:SI 1 "general_operand" ""))]
4291   "TARGET_EITHER"
4292   "
4293   if (TARGET_ARM)
4294     {
4295       /* Everything except mem = const or mem = mem can be done easily.  */
4296       if (GET_CODE (operands[0]) == MEM)
4297         operands[1] = force_reg (SImode, operands[1]);
4298       if (arm_general_register_operand (operands[0], SImode)
4299           && GET_CODE (operands[1]) == CONST_INT
4300           && !(const_ok_for_arm (INTVAL (operands[1]))
4301                || const_ok_for_arm (~INTVAL (operands[1]))))
4302         {
4303            arm_split_constant (SET, SImode, NULL_RTX,
4304                                INTVAL (operands[1]), operands[0], NULL_RTX,
4305                                optimize && !no_new_pseudos);
4306           DONE;
4307         }
4308     }
4309   else /* TARGET_THUMB....  */
4310     {
4311       if (!no_new_pseudos)
4312         {
4313           if (GET_CODE (operands[0]) != REG)
4314             operands[1] = force_reg (SImode, operands[1]);
4315         }
4316     }
4317     
4318   if (flag_pic
4319       && (CONSTANT_P (operands[1])
4320          || symbol_mentioned_p (operands[1])
4321          || label_mentioned_p (operands[1])))
4322     operands[1] = legitimize_pic_address (operands[1], SImode,
4323                                           (no_new_pseudos ? operands[0] : 0));
4324   "
4325 )
4326
4327 (define_insn "*arm_movsi_insn"
4328   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4329         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
4330   "TARGET_ARM && ! TARGET_IWMMXT
4331    && !(TARGET_HARD_FLOAT && TARGET_VFP)
4332    && (   register_operand (operands[0], SImode)
4333        || register_operand (operands[1], SImode))"
4334   "@
4335    mov%?\\t%0, %1
4336    mvn%?\\t%0, #%B1
4337    ldr%?\\t%0, %1
4338    str%?\\t%1, %0"
4339   [(set_attr "type" "*,*,load1,store1")
4340    (set_attr "predicable" "yes")
4341    (set_attr "pool_range" "*,*,4096,*")
4342    (set_attr "neg_pool_range" "*,*,4084,*")]
4343 )
4344
4345 (define_split
4346   [(set (match_operand:SI 0 "arm_general_register_operand" "")
4347         (match_operand:SI 1 "const_int_operand" ""))]
4348   "TARGET_ARM
4349   && (!(const_ok_for_arm (INTVAL (operands[1]))
4350         || const_ok_for_arm (~INTVAL (operands[1]))))"
4351   [(clobber (const_int 0))]
4352   "
4353   arm_split_constant (SET, SImode, NULL_RTX, 
4354                       INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4355   DONE;
4356   "
4357 )
4358
4359 (define_insn "*thumb_movsi_insn"
4360   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4361         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4362   "TARGET_THUMB
4363    && (   register_operand (operands[0], SImode) 
4364        || register_operand (operands[1], SImode))"
4365   "@
4366    mov  %0, %1
4367    mov  %0, %1
4368    #
4369    #
4370    ldmia\\t%1, {%0}
4371    stmia\\t%0, {%1}
4372    ldr\\t%0, %1
4373    str\\t%1, %0
4374    mov\\t%0, %1"
4375   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4376    (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4377    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4378 )
4379
4380 (define_split 
4381   [(set (match_operand:SI 0 "register_operand" "")
4382         (match_operand:SI 1 "const_int_operand" ""))]
4383   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4384   [(set (match_dup 0) (match_dup 1))
4385    (set (match_dup 0) (neg:SI (match_dup 0)))]
4386   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4387 )
4388
4389 (define_split 
4390   [(set (match_operand:SI 0 "register_operand" "")
4391         (match_operand:SI 1 "const_int_operand" ""))]
4392   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4393   [(set (match_dup 0) (match_dup 1))
4394    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4395   "
4396   {
4397     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4398     unsigned HOST_WIDE_INT mask = 0xff;
4399     int i;
4400     
4401     for (i = 0; i < 25; i++)
4402       if ((val & (mask << i)) == val)
4403         break;
4404
4405     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4406     if (i == 0)
4407       FAIL;
4408
4409     operands[1] = GEN_INT (val >> i);
4410     operands[2] = GEN_INT (i);
4411   }"
4412 )
4413
4414 ;; When generating pic, we need to load the symbol offset into a register.
4415 ;; So that the optimizer does not confuse this with a normal symbol load
4416 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
4417 ;; since that is the only type of relocation we can use.
4418
4419 ;; The rather odd constraints on the following are to force reload to leave
4420 ;; the insn alone, and to force the minipool generation pass to then move
4421 ;; the GOT symbol to memory.
4422
4423 (define_insn "pic_load_addr_arm"
4424   [(set (match_operand:SI 0 "s_register_operand" "=r")
4425         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4426   "TARGET_ARM && flag_pic"
4427   "ldr%?\\t%0, %1"
4428   [(set_attr "type" "load1")
4429    (set (attr "pool_range")     (const_int 4096))
4430    (set (attr "neg_pool_range") (const_int 4084))]
4431 )
4432
4433 (define_insn "pic_load_addr_thumb"
4434   [(set (match_operand:SI 0 "s_register_operand" "=l")
4435         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4436   "TARGET_THUMB && flag_pic"
4437   "ldr\\t%0, %1"
4438   [(set_attr "type" "load1")
4439    (set (attr "pool_range") (const_int 1024))]
4440 )
4441
4442 ;; This variant is used for AOF assembly, since it needs to mention the
4443 ;; pic register in the rtl.
4444 (define_expand "pic_load_addr_based"
4445   [(set (match_operand:SI 0 "s_register_operand" "")
4446         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4447   "TARGET_ARM && flag_pic"
4448   "operands[2] = pic_offset_table_rtx;"
4449 )
4450
4451 (define_insn "*pic_load_addr_based_insn"
4452   [(set (match_operand:SI 0 "s_register_operand" "=r")
4453         (unspec:SI [(match_operand 1 "" "")
4454                     (match_operand 2 "s_register_operand" "r")]
4455                    UNSPEC_PIC_SYM))]
4456   "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4457   "*
4458 #ifdef AOF_ASSEMBLER
4459   operands[1] = aof_pic_entry (operands[1]);
4460 #endif
4461   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4462   return \"\";
4463   "
4464   [(set_attr "type" "load1")
4465    (set (attr "pool_range")
4466         (if_then_else (eq_attr "is_thumb" "yes")
4467                       (const_int 1024)
4468                       (const_int 4096)))
4469    (set (attr "neg_pool_range")
4470         (if_then_else (eq_attr "is_thumb" "yes")
4471                       (const_int 0)
4472                       (const_int 4084)))]
4473 )
4474
4475 (define_insn "pic_add_dot_plus_four"
4476   [(set (match_operand:SI 0 "register_operand" "+r")
4477         (unspec:SI [(plus:SI (match_dup 0)
4478                              (const (plus:SI (pc) (const_int 4))))]
4479                    UNSPEC_PIC_BASE))
4480    (use (label_ref (match_operand 1 "" "")))]
4481   "TARGET_THUMB && flag_pic"
4482   "*
4483   (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4484                              CODE_LABEL_NUMBER (operands[1]));
4485   return \"add\\t%0, %|pc\";
4486   "
4487   [(set_attr "length" "2")]
4488 )
4489
4490 (define_insn "pic_add_dot_plus_eight"
4491   [(set (match_operand:SI 0 "register_operand" "+r")
4492         (unspec:SI [(plus:SI (match_dup 0)
4493                              (const (plus:SI (pc) (const_int 8))))]
4494                    UNSPEC_PIC_BASE))
4495    (use (label_ref (match_operand 1 "" "")))]
4496   "TARGET_ARM && flag_pic"
4497   "*
4498     (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4499                                CODE_LABEL_NUMBER (operands[1]));
4500     return \"add%?\\t%0, %|pc, %0\";
4501   "
4502   [(set_attr "predicable" "yes")]
4503 )
4504
4505 (define_expand "builtin_setjmp_receiver"
4506   [(label_ref (match_operand 0 "" ""))]
4507   "flag_pic"
4508   "
4509 {
4510   /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4511      register.  */
4512   arm_load_pic_register (3);
4513   DONE;
4514 }")
4515
4516 ;; If copying one reg to another we can set the condition codes according to
4517 ;; its value.  Such a move is common after a return from subroutine and the
4518 ;; result is being tested against zero.
4519
4520 (define_insn "*movsi_compare0"
4521   [(set (reg:CC CC_REGNUM)
4522         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4523                     (const_int 0)))
4524    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4525         (match_dup 1))]
4526   "TARGET_ARM"
4527   "@
4528    cmp%?\\t%0, #0
4529    sub%?s\\t%0, %1, #0"
4530   [(set_attr "conds" "set")]
4531 )
4532
4533 ;; Subroutine to store a half word from a register into memory.
4534 ;; Operand 0 is the source register (HImode)
4535 ;; Operand 1 is the destination address in a register (SImode)
4536
4537 ;; In both this routine and the next, we must be careful not to spill
4538 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4539 ;; can generate unrecognizable rtl.
4540
4541 (define_expand "storehi"
4542   [;; store the low byte
4543    (set (match_operand 1 "" "") (match_dup 3))
4544    ;; extract the high byte
4545    (set (match_dup 2)
4546         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4547    ;; store the high byte
4548    (set (match_dup 4) (match_dup 5))]
4549   "TARGET_ARM"
4550   "
4551   {
4552     rtx op1 = operands[1];
4553     rtx addr = XEXP (op1, 0);
4554     enum rtx_code code = GET_CODE (addr);
4555
4556     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4557         || code == MINUS)
4558       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4559
4560     operands[4] = adjust_address (op1, QImode, 1);
4561     operands[1] = adjust_address (operands[1], QImode, 0);
4562     operands[3] = gen_lowpart (QImode, operands[0]);
4563     operands[0] = gen_lowpart (SImode, operands[0]);
4564     operands[2] = gen_reg_rtx (SImode);
4565     operands[5] = gen_lowpart (QImode, operands[2]);
4566   }"
4567 )
4568
4569 (define_expand "storehi_bigend"
4570   [(set (match_dup 4) (match_dup 3))
4571    (set (match_dup 2)
4572         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4573    (set (match_operand 1 "" "") (match_dup 5))]
4574   "TARGET_ARM"
4575   "
4576   {
4577     rtx op1 = operands[1];
4578     rtx addr = XEXP (op1, 0);
4579     enum rtx_code code = GET_CODE (addr);
4580
4581     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4582         || code == MINUS)
4583       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4584
4585     operands[4] = adjust_address (op1, QImode, 1);
4586     operands[1] = adjust_address (operands[1], QImode, 0);
4587     operands[3] = gen_lowpart (QImode, operands[0]);
4588     operands[0] = gen_lowpart (SImode, operands[0]);
4589     operands[2] = gen_reg_rtx (SImode);
4590     operands[5] = gen_lowpart (QImode, operands[2]);
4591   }"
4592 )
4593
4594 ;; Subroutine to store a half word integer constant into memory.
4595 (define_expand "storeinthi"
4596   [(set (match_operand 0 "" "")
4597         (match_operand 1 "" ""))
4598    (set (match_dup 3) (match_dup 2))]
4599   "TARGET_ARM"
4600   "
4601   {
4602     HOST_WIDE_INT value = INTVAL (operands[1]);
4603     rtx addr = XEXP (operands[0], 0);
4604     rtx op0 = operands[0];
4605     enum rtx_code code = GET_CODE (addr);
4606
4607     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4608         || code == MINUS)
4609       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4610
4611     operands[1] = gen_reg_rtx (SImode);
4612     if (BYTES_BIG_ENDIAN)
4613       {
4614         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4615         if ((value & 255) == ((value >> 8) & 255))
4616           operands[2] = operands[1];
4617         else
4618           {
4619             operands[2] = gen_reg_rtx (SImode);
4620             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4621           }
4622       }
4623     else
4624       {
4625         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4626         if ((value & 255) == ((value >> 8) & 255))
4627           operands[2] = operands[1];
4628         else
4629           {
4630             operands[2] = gen_reg_rtx (SImode);
4631             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4632           }
4633       }
4634
4635     operands[3] = adjust_address (op0, QImode, 1);
4636     operands[0] = adjust_address (operands[0], QImode, 0);
4637     operands[2] = gen_lowpart (QImode, operands[2]);
4638     operands[1] = gen_lowpart (QImode, operands[1]);
4639   }"
4640 )
4641
4642 (define_expand "storehi_single_op"
4643   [(set (match_operand:HI 0 "memory_operand" "")
4644         (match_operand:HI 1 "general_operand" ""))]
4645   "TARGET_ARM && arm_arch4"
4646   "
4647   if (!s_register_operand (operands[1], HImode))
4648     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4649   "
4650 )
4651
4652 (define_expand "movhi"
4653   [(set (match_operand:HI 0 "general_operand" "")
4654         (match_operand:HI 1 "general_operand" ""))]
4655   "TARGET_EITHER"
4656   "
4657   if (TARGET_ARM)
4658     {
4659       if (!no_new_pseudos)
4660         {
4661           if (GET_CODE (operands[0]) == MEM)
4662             {
4663               if (arm_arch4)
4664                 {
4665                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4666                   DONE;
4667                 }
4668               if (GET_CODE (operands[1]) == CONST_INT)
4669                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4670               else
4671                 {
4672                   if (GET_CODE (operands[1]) == MEM)
4673                     operands[1] = force_reg (HImode, operands[1]);
4674                   if (BYTES_BIG_ENDIAN)
4675                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4676                   else
4677                    emit_insn (gen_storehi (operands[1], operands[0]));
4678                 }
4679               DONE;
4680             }
4681           /* Sign extend a constant, and keep it in an SImode reg.  */
4682           else if (GET_CODE (operands[1]) == CONST_INT)
4683             {
4684               rtx reg = gen_reg_rtx (SImode);
4685               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4686
4687               /* If the constant is already valid, leave it alone.  */
4688               if (!const_ok_for_arm (val))
4689                 {
4690                   /* If setting all the top bits will make the constant 
4691                      loadable in a single instruction, then set them.  
4692                      Otherwise, sign extend the number.  */
4693
4694                   if (const_ok_for_arm (~(val | ~0xffff)))
4695                     val |= ~0xffff;
4696                   else if (val & 0x8000)
4697                     val |= ~0xffff;
4698                 }
4699
4700               emit_insn (gen_movsi (reg, GEN_INT (val)));
4701               operands[1] = gen_lowpart (HImode, reg);
4702             }
4703           else if (arm_arch4 && optimize && !no_new_pseudos
4704                    && GET_CODE (operands[1]) == MEM)
4705             {
4706               rtx reg = gen_reg_rtx (SImode);
4707
4708               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4709               operands[1] = gen_lowpart (HImode, reg);
4710             }
4711           else if (!arm_arch4)
4712             {
4713               if (GET_CODE (operands[1]) == MEM)
4714                 {
4715                   rtx base;
4716                   rtx offset = const0_rtx;
4717                   rtx reg = gen_reg_rtx (SImode);
4718
4719                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4720                        || (GET_CODE (base) == PLUS
4721                            && (GET_CODE (offset = XEXP (base, 1))
4722                                == CONST_INT)
4723                            && ((INTVAL(offset) & 1) != 1)
4724                            && GET_CODE (base = XEXP (base, 0)) == REG))
4725                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4726                     {
4727                       HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4728                       rtx new;
4729
4730                       new = gen_rtx_MEM (SImode,
4731                                          plus_constant (base, new_offset));
4732                       MEM_COPY_ATTRIBUTES (new, operands[1]);
4733                       emit_insn (gen_movsi (reg, new));
4734                       if (((INTVAL (offset) & 2) != 0)
4735                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4736                         {
4737                           rtx reg2 = gen_reg_rtx (SImode);
4738
4739                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4740                           reg = reg2;
4741                         }
4742                     }
4743                   else
4744                     emit_insn (gen_movhi_bytes (reg, operands[1]));
4745
4746                   operands[1] = gen_lowpart (HImode, reg);
4747                }
4748            }
4749         }
4750       /* Handle loading a large integer during reload.  */
4751       else if (GET_CODE (operands[1]) == CONST_INT
4752                && !const_ok_for_arm (INTVAL (operands[1]))
4753                && !const_ok_for_arm (~INTVAL (operands[1])))
4754         {
4755           /* Writing a constant to memory needs a scratch, which should
4756              be handled with SECONDARY_RELOADs.  */
4757           if (GET_CODE (operands[0]) != REG)
4758             abort ();
4759
4760           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4761           emit_insn (gen_movsi (operands[0], operands[1]));
4762           DONE;
4763        }
4764     }
4765   else /* TARGET_THUMB */
4766     {
4767       if (!no_new_pseudos)
4768         {
4769           if (GET_CODE (operands[0]) != REG)
4770             operands[1] = force_reg (HImode, operands[1]);
4771
4772           /* ??? We shouldn't really get invalid addresses here, but this can
4773              happen if we are passed a SP (never OK for HImode/QImode) or 
4774              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4775              HImode/QImode) relative address.  */
4776           /* ??? This should perhaps be fixed elsewhere, for instance, in
4777              fixup_stack_1, by checking for other kinds of invalid addresses,
4778              e.g. a bare reference to a virtual register.  This may confuse the
4779              alpha though, which must handle this case differently.  */
4780           if (GET_CODE (operands[0]) == MEM
4781               && !memory_address_p (GET_MODE (operands[0]),
4782                                     XEXP (operands[0], 0)))
4783             operands[0]
4784               = replace_equiv_address (operands[0],
4785                                        copy_to_reg (XEXP (operands[0], 0)));
4786    
4787           if (GET_CODE (operands[1]) == MEM
4788               && !memory_address_p (GET_MODE (operands[1]),
4789                                     XEXP (operands[1], 0)))
4790             operands[1]
4791               = replace_equiv_address (operands[1],
4792                                        copy_to_reg (XEXP (operands[1], 0)));
4793         }
4794       /* Handle loading a large integer during reload.  */
4795       else if (GET_CODE (operands[1]) == CONST_INT
4796                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4797         {
4798           /* Writing a constant to memory needs a scratch, which should
4799              be handled with SECONDARY_RELOADs.  */
4800           if (GET_CODE (operands[0]) != REG)
4801             abort ();
4802
4803           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4804           emit_insn (gen_movsi (operands[0], operands[1]));
4805           DONE;
4806         }
4807     }
4808   "
4809 )
4810
4811 (define_insn "*thumb_movhi_insn"
4812   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4813         (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
4814   "TARGET_THUMB
4815    && (   register_operand (operands[0], HImode)
4816        || register_operand (operands[1], HImode))"
4817   "*
4818   switch (which_alternative)
4819     {
4820     case 0: return \"add        %0, %1, #0\";
4821     case 2: return \"strh       %1, %0\";
4822     case 3: return \"mov        %0, %1\";
4823     case 4: return \"mov        %0, %1\";
4824     case 5: return \"mov        %0, %1\";
4825     default: abort ();
4826     case 1:
4827       /* The stack pointer can end up being taken as an index register.
4828           Catch this case here and deal with it.  */
4829       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4830           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4831           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4832         {
4833           rtx ops[2];
4834           ops[0] = operands[0];
4835           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4836       
4837           output_asm_insn (\"mov        %0, %1\", ops);
4838
4839           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4840     
4841         }
4842       return \"ldrh     %0, %1\";
4843     }"
4844   [(set_attr "length" "2,4,2,2,2,2")
4845    (set_attr "type" "*,load1,store1,*,*,*")]
4846 )
4847
4848
4849 (define_expand "movhi_bytes"
4850   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4851    (set (match_dup 3)
4852         (zero_extend:SI (match_dup 6)))
4853    (set (match_operand:SI 0 "" "")
4854          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4855   "TARGET_ARM"
4856   "
4857   {
4858     rtx mem1, mem2;
4859     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4860
4861     mem1 = gen_rtx_MEM (QImode, addr);
4862     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4863     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4864     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4865     operands[0] = gen_lowpart (SImode, operands[0]);
4866     operands[1] = mem1;
4867     operands[2] = gen_reg_rtx (SImode);
4868     operands[3] = gen_reg_rtx (SImode);
4869     operands[6] = mem2;
4870
4871     if (BYTES_BIG_ENDIAN)
4872       {
4873         operands[4] = operands[2];
4874         operands[5] = operands[3];
4875       }
4876     else
4877       {
4878         operands[4] = operands[3];
4879         operands[5] = operands[2];
4880       }
4881   }"
4882 )
4883
4884 (define_expand "movhi_bigend"
4885   [(set (match_dup 2)
4886         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4887                    (const_int 16)))
4888    (set (match_dup 3)
4889         (ashiftrt:SI (match_dup 2) (const_int 16)))
4890    (set (match_operand:HI 0 "s_register_operand" "")
4891         (match_dup 4))]
4892   "TARGET_ARM"
4893   "
4894   operands[2] = gen_reg_rtx (SImode);
4895   operands[3] = gen_reg_rtx (SImode);
4896   operands[4] = gen_lowpart (HImode, operands[3]);
4897   "
4898 )
4899
4900 ;; Pattern to recognize insn generated default case above
4901 (define_insn "*movhi_insn_arch4"
4902   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4903         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4904   "TARGET_ARM
4905    && arm_arch4
4906    && (GET_CODE (operands[1]) != CONST_INT
4907        || const_ok_for_arm (INTVAL (operands[1]))
4908        || const_ok_for_arm (~INTVAL (operands[1])))"
4909   "@
4910    mov%?\\t%0, %1\\t%@ movhi
4911    mvn%?\\t%0, #%B1\\t%@ movhi
4912    str%?h\\t%1, %0\\t%@ movhi
4913    ldr%?h\\t%0, %1\\t%@ movhi"
4914   [(set_attr "type" "*,*,store1,load1")
4915    (set_attr "predicable" "yes")
4916    (set_attr "pool_range" "*,*,*,256")
4917    (set_attr "neg_pool_range" "*,*,*,244")]
4918 )
4919
4920 (define_insn "*movhi_bytes"
4921   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4922         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4923   "TARGET_ARM"
4924   "@
4925    mov%?\\t%0, %1\\t%@ movhi
4926    mvn%?\\t%0, #%B1\\t%@ movhi"
4927   [(set_attr "predicable" "yes")]
4928 )
4929
4930 (define_insn "thumb_movhi_clobber"
4931   [(set (match_operand:HI     0 "memory_operand"   "=m")
4932         (match_operand:HI     1 "register_operand" "l"))
4933    (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4934   "TARGET_THUMB"
4935   "*
4936   abort ();"
4937 )
4938         
4939 ;; We use a DImode scratch because we may occasionally need an additional
4940 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4941 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4942 (define_expand "reload_outhi"
4943   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4944               (match_operand:HI 1 "s_register_operand"        "r")
4945               (match_operand:DI 2 "s_register_operand"        "=&l")])]
4946   "TARGET_EITHER"
4947   "if (TARGET_ARM)
4948      arm_reload_out_hi (operands);
4949    else
4950      thumb_reload_out_hi (operands);
4951   DONE;
4952   "
4953 )
4954
4955 (define_expand "reload_inhi"
4956   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4957               (match_operand:HI 1 "arm_reload_memory_operand" "o")
4958               (match_operand:DI 2 "s_register_operand" "=&r")])]
4959   "TARGET_EITHER"
4960   "
4961   if (TARGET_ARM)
4962     arm_reload_in_hi (operands);
4963   else
4964     thumb_reload_out_hi (operands);
4965   DONE;
4966 ")
4967
4968 (define_expand "movqi"
4969   [(set (match_operand:QI 0 "general_operand" "")
4970         (match_operand:QI 1 "general_operand" ""))]
4971   "TARGET_EITHER"
4972   "
4973   if (TARGET_ARM)
4974     {
4975       /* Everything except mem = const or mem = mem can be done easily */
4976
4977       if (!no_new_pseudos)
4978         {
4979           if (GET_CODE (operands[1]) == CONST_INT)
4980             {
4981               rtx reg = gen_reg_rtx (SImode);
4982
4983               emit_insn (gen_movsi (reg, operands[1]));
4984               operands[1] = gen_lowpart (QImode, reg);
4985             }
4986           if (GET_CODE (operands[1]) == MEM && optimize > 0)
4987             {
4988               rtx reg = gen_reg_rtx (SImode);
4989
4990               emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4991               operands[1] = gen_lowpart (QImode, reg);
4992             }
4993           if (GET_CODE (operands[0]) == MEM)
4994             operands[1] = force_reg (QImode, operands[1]);
4995         }
4996     }
4997   else /* TARGET_THUMB */
4998     {
4999       if (!no_new_pseudos)
5000         {
5001           if (GET_CODE (operands[0]) != REG)
5002             operands[1] = force_reg (QImode, operands[1]);
5003
5004           /* ??? We shouldn't really get invalid addresses here, but this can
5005              happen if we are passed a SP (never OK for HImode/QImode) or
5006              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
5007              HImode/QImode) relative address.  */
5008           /* ??? This should perhaps be fixed elsewhere, for instance, in
5009              fixup_stack_1, by checking for other kinds of invalid addresses,
5010              e.g. a bare reference to a virtual register.  This may confuse the
5011              alpha though, which must handle this case differently.  */
5012           if (GET_CODE (operands[0]) == MEM
5013               && !memory_address_p (GET_MODE (operands[0]),
5014                                      XEXP (operands[0], 0)))
5015             operands[0]
5016               = replace_equiv_address (operands[0],
5017                                        copy_to_reg (XEXP (operands[0], 0)));
5018           if (GET_CODE (operands[1]) == MEM
5019               && !memory_address_p (GET_MODE (operands[1]),
5020                                     XEXP (operands[1], 0)))
5021              operands[1]
5022                = replace_equiv_address (operands[1],
5023                                         copy_to_reg (XEXP (operands[1], 0)));
5024         }
5025       /* Handle loading a large integer during reload.  */
5026       else if (GET_CODE (operands[1]) == CONST_INT
5027                && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
5028         {
5029           /* Writing a constant to memory needs a scratch, which should
5030              be handled with SECONDARY_RELOADs.  */
5031           if (GET_CODE (operands[0]) != REG)
5032             abort ();
5033
5034           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5035           emit_insn (gen_movsi (operands[0], operands[1]));
5036           DONE;
5037        }
5038     }
5039   "
5040 )
5041
5042
5043 (define_insn "*arm_movqi_insn"
5044   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5045         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5046   "TARGET_ARM
5047    && (   register_operand (operands[0], QImode)
5048        || register_operand (operands[1], QImode))"
5049   "@
5050    mov%?\\t%0, %1
5051    mvn%?\\t%0, #%B1
5052    ldr%?b\\t%0, %1
5053    str%?b\\t%1, %0"
5054   [(set_attr "type" "*,*,load1,store1")
5055    (set_attr "predicable" "yes")]
5056 )
5057
5058 (define_insn "*thumb_movqi_insn"
5059   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5060         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
5061   "TARGET_THUMB
5062    && (   register_operand (operands[0], QImode)
5063        || register_operand (operands[1], QImode))"
5064   "@
5065    add\\t%0, %1, #0
5066    ldrb\\t%0, %1
5067    strb\\t%1, %0
5068    mov\\t%0, %1
5069    mov\\t%0, %1
5070    mov\\t%0, %1"
5071   [(set_attr "length" "2")
5072    (set_attr "type" "*,load1,store1,*,*,*")
5073    (set_attr "pool_range" "*,32,*,*,*,*")]
5074 )
5075
5076 (define_expand "movsf"
5077   [(set (match_operand:SF 0 "general_operand" "")
5078         (match_operand:SF 1 "general_operand" ""))]
5079   "TARGET_EITHER"
5080   "
5081   if (TARGET_ARM)
5082     {
5083       if (GET_CODE (operands[0]) == MEM)
5084         operands[1] = force_reg (SFmode, operands[1]);
5085     }
5086   else /* TARGET_THUMB */
5087     {
5088       if (!no_new_pseudos)
5089         {
5090            if (GET_CODE (operands[0]) != REG)
5091              operands[1] = force_reg (SFmode, operands[1]);
5092         }
5093     }
5094   "
5095 )
5096
5097 (define_split
5098   [(set (match_operand:SF 0 "nonimmediate_operand" "")
5099         (match_operand:SF 1 "immediate_operand" ""))]
5100   "TARGET_ARM
5101    && !(TARGET_HARD_FLOAT && TARGET_FPA)
5102    && reload_completed
5103    && GET_CODE (operands[1]) == CONST_DOUBLE"
5104   [(set (match_dup 2) (match_dup 3))]
5105   "
5106   operands[2] = gen_lowpart (SImode, operands[0]);
5107   operands[3] = gen_lowpart (SImode, operands[1]);
5108   if (operands[2] == 0 || operands[3] == 0)
5109     FAIL;
5110   "
5111 )
5112
5113 (define_insn "*arm_movsf_soft_insn"
5114   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5115         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
5116   "TARGET_ARM
5117    && TARGET_SOFT_FLOAT
5118    && (GET_CODE (operands[0]) != MEM
5119        || register_operand (operands[1], SFmode))"
5120   "@
5121    mov%?\\t%0, %1
5122    ldr%?\\t%0, %1\\t%@ float
5123    str%?\\t%1, %0\\t%@ float"
5124   [(set_attr "length" "4,4,4")
5125    (set_attr "predicable" "yes")
5126    (set_attr "type" "*,load1,store1")
5127    (set_attr "pool_range" "*,4096,*")
5128    (set_attr "neg_pool_range" "*,4084,*")]
5129 )
5130
5131 ;;; ??? This should have alternatives for constants.
5132 (define_insn "*thumb_movsf_insn"
5133   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5134         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5135   "TARGET_THUMB
5136    && (   register_operand (operands[0], SFmode) 
5137        || register_operand (operands[1], SFmode))"
5138   "@
5139    add\\t%0, %1, #0
5140    ldmia\\t%1, {%0}
5141    stmia\\t%0, {%1}
5142    ldr\\t%0, %1
5143    str\\t%1, %0
5144    mov\\t%0, %1
5145    mov\\t%0, %1"
5146   [(set_attr "length" "2")
5147    (set_attr "type" "*,load1,store1,load1,store1,*,*")
5148    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5149 )
5150
5151 (define_expand "movdf"
5152   [(set (match_operand:DF 0 "general_operand" "")
5153         (match_operand:DF 1 "general_operand" ""))]
5154   "TARGET_EITHER"
5155   "
5156   if (TARGET_ARM)
5157     {
5158       if (GET_CODE (operands[0]) == MEM)
5159         operands[1] = force_reg (DFmode, operands[1]);
5160     }
5161   else /* TARGET_THUMB */
5162     {
5163       if (!no_new_pseudos)
5164         {
5165           if (GET_CODE (operands[0]) != REG)
5166             operands[1] = force_reg (DFmode, operands[1]);
5167         }
5168     }
5169   "
5170 )
5171
5172 ;; Reloading a df mode value stored in integer regs to memory can require a
5173 ;; scratch reg.
5174 (define_expand "reload_outdf"
5175   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5176    (match_operand:DF 1 "s_register_operand" "r")
5177    (match_operand:SI 2 "s_register_operand" "=&r")]
5178   "TARGET_ARM"
5179   "
5180   {
5181     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5182
5183     if (code == REG)
5184       operands[2] = XEXP (operands[0], 0);
5185     else if (code == POST_INC || code == PRE_DEC)
5186       {
5187         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5188         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5189         emit_insn (gen_movdi (operands[0], operands[1]));
5190         DONE;
5191       }
5192     else if (code == PRE_INC)
5193       {
5194         rtx reg = XEXP (XEXP (operands[0], 0), 0);
5195
5196         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5197         operands[2] = reg;
5198       }
5199     else if (code == POST_DEC)
5200       operands[2] = XEXP (XEXP (operands[0], 0), 0);
5201     else
5202       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5203                              XEXP (XEXP (operands[0], 0), 1)));
5204
5205     emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5206                             operands[1]));
5207
5208     if (code == POST_DEC)
5209       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5210
5211     DONE;
5212   }"
5213 )
5214
5215 (define_insn "*movdf_soft_insn"
5216   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5217         (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
5218   "TARGET_ARM && TARGET_SOFT_FLOAT
5219   "
5220   "*
5221   switch (which_alternative)
5222     {
5223     case 0:
5224     case 1:
5225     case 2:
5226       return \"#\";
5227     default:
5228       return output_move_double (operands);
5229     }
5230   "
5231   [(set_attr "length" "8,12,16,8,8")
5232    (set_attr "type" "*,*,*,load2,store2")
5233    (set_attr "pool_range" "1020")
5234    (set_attr "neg_pool_range" "1008")]
5235 )
5236
5237 ;;; ??? This should have alternatives for constants.
5238 ;;; ??? This was originally identical to the movdi_insn pattern.
5239 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5240 ;;; thumb_reorg with a memory reference.
5241 (define_insn "*thumb_movdf_insn"
5242   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5243         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5244   "TARGET_THUMB
5245    && (   register_operand (operands[0], DFmode)
5246        || register_operand (operands[1], DFmode))"
5247   "*
5248   switch (which_alternative)
5249     {
5250     default:
5251     case 0:
5252       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5253         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5254       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5255     case 1:
5256       return \"ldmia\\t%1, {%0, %H0}\";
5257     case 2:
5258       return \"stmia\\t%0, {%1, %H1}\";
5259     case 3:
5260       return thumb_load_double_from_address (operands);
5261     case 4:
5262       operands[2] = gen_rtx_MEM (SImode,
5263                                  plus_constant (XEXP (operands[0], 0), 4));
5264       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5265       return \"\";
5266     case 5:
5267       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5268         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5269       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5270     }
5271   "
5272   [(set_attr "length" "4,2,2,6,4,4")
5273    (set_attr "type" "*,load2,store2,load2,store2,*")
5274    (set_attr "pool_range" "*,*,*,1020,*,*")]
5275 )
5276
5277 (define_expand "movxf"
5278   [(set (match_operand:XF 0 "general_operand" "")
5279         (match_operand:XF 1 "general_operand" ""))]
5280   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
5281   "
5282   if (GET_CODE (operands[0]) == MEM)
5283     operands[1] = force_reg (XFmode, operands[1]);
5284   "
5285 )
5286
5287 ;; Vector Moves
5288 (define_expand "movv2si"
5289   [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5290         (match_operand:V2SI 1 "general_operand" ""))]
5291   "TARGET_REALLY_IWMMXT"
5292 {
5293 })
5294
5295 (define_expand "movv4hi"
5296   [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5297         (match_operand:V4HI 1 "general_operand" ""))]
5298   "TARGET_REALLY_IWMMXT"
5299 {
5300 })
5301
5302 (define_expand "movv8qi"
5303   [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5304         (match_operand:V8QI 1 "general_operand" ""))]
5305   "TARGET_REALLY_IWMMXT"
5306 {
5307 })
5308 \f
5309
5310 ;; load- and store-multiple insns
5311 ;; The arm can load/store any set of registers, provided that they are in
5312 ;; ascending order; but that is beyond GCC so stick with what it knows.
5313
5314 (define_expand "load_multiple"
5315   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5316                           (match_operand:SI 1 "" ""))
5317                      (use (match_operand:SI 2 "" ""))])]
5318   "TARGET_ARM"
5319 {
5320   HOST_WIDE_INT offset = 0;
5321
5322   /* Support only fixed point registers.  */
5323   if (GET_CODE (operands[2]) != CONST_INT
5324       || INTVAL (operands[2]) > 14
5325       || INTVAL (operands[2]) < 2
5326       || GET_CODE (operands[1]) != MEM
5327       || GET_CODE (operands[0]) != REG
5328       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5329       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5330     FAIL;
5331
5332   operands[3]
5333     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5334                              force_reg (SImode, XEXP (operands[1], 0)),
5335                              TRUE, FALSE, operands[1], &offset);
5336 })
5337
5338 ;; Load multiple with write-back
5339
5340 (define_insn "*ldmsi_postinc4"
5341   [(match_parallel 0 "load_multiple_operation"
5342     [(set (match_operand:SI 1 "s_register_operand" "=r")
5343           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5344                    (const_int 16)))
5345      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5346           (mem:SI (match_dup 2)))
5347      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5348           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5349      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5350           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5351      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5352           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5353   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5354   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5355   [(set_attr "type" "load4")
5356    (set_attr "predicable" "yes")]
5357 )
5358
5359 (define_insn "*ldmsi_postinc4_thumb"
5360   [(match_parallel 0 "load_multiple_operation"
5361     [(set (match_operand:SI 1 "s_register_operand" "=l")
5362           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5363                    (const_int 16)))
5364      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5365           (mem:SI (match_dup 2)))
5366      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5367           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5368      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5369           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5370      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5371           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5372   "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5373   "ldmia\\t%1!, {%3, %4, %5, %6}"
5374   [(set_attr "type" "load4")]
5375 )
5376
5377 (define_insn "*ldmsi_postinc3"
5378   [(match_parallel 0 "load_multiple_operation"
5379     [(set (match_operand:SI 1 "s_register_operand" "=r")
5380           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5381                    (const_int 12)))
5382      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5383           (mem:SI (match_dup 2)))
5384      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5385           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5386      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5387           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5388   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5389   "ldm%?ia\\t%1!, {%3, %4, %5}"
5390   [(set_attr "type" "load3")
5391    (set_attr "predicable" "yes")]
5392 )
5393
5394 (define_insn "*ldmsi_postinc2"
5395   [(match_parallel 0 "load_multiple_operation"
5396     [(set (match_operand:SI 1 "s_register_operand" "=r")
5397           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5398                    (const_int 8)))
5399      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5400           (mem:SI (match_dup 2)))
5401      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5402           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5403   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5404   "ldm%?ia\\t%1!, {%3, %4}"
5405   [(set_attr "type" "load2")
5406    (set_attr "predicable" "yes")]
5407 )
5408
5409 ;; Ordinary load multiple
5410
5411 (define_insn "*ldmsi4"
5412   [(match_parallel 0 "load_multiple_operation"
5413     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5414           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5415      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5416           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5417      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5418           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5419      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5420           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5421   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5422   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5423   [(set_attr "type" "load4")
5424    (set_attr "predicable" "yes")]
5425 )
5426
5427 (define_insn "*ldmsi3"
5428   [(match_parallel 0 "load_multiple_operation"
5429     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5430           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5431      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5432           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5433      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5434           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5435   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5436   "ldm%?ia\\t%1, {%2, %3, %4}"
5437   [(set_attr "type" "load3")
5438    (set_attr "predicable" "yes")]
5439 )
5440
5441 (define_insn "*ldmsi2"
5442   [(match_parallel 0 "load_multiple_operation"
5443     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5444           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5445      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5446           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5447   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5448   "ldm%?ia\\t%1, {%2, %3}"
5449   [(set_attr "type" "load2")
5450    (set_attr "predicable" "yes")]
5451 )
5452
5453 (define_expand "store_multiple"
5454   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5455                           (match_operand:SI 1 "" ""))
5456                      (use (match_operand:SI 2 "" ""))])]
5457   "TARGET_ARM"
5458 {
5459   HOST_WIDE_INT offset = 0;
5460
5461   /* Support only fixed point registers.  */
5462   if (GET_CODE (operands[2]) != CONST_INT
5463       || INTVAL (operands[2]) > 14
5464       || INTVAL (operands[2]) < 2
5465       || GET_CODE (operands[1]) != REG
5466       || GET_CODE (operands[0]) != MEM
5467       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5468       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5469     FAIL;
5470
5471   operands[3]
5472     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5473                               force_reg (SImode, XEXP (operands[0], 0)),
5474                               TRUE, FALSE, operands[0], &offset);
5475 })
5476
5477 ;; Store multiple with write-back
5478
5479 (define_insn "*stmsi_postinc4"
5480   [(match_parallel 0 "store_multiple_operation"
5481     [(set (match_operand:SI 1 "s_register_operand" "=r")
5482           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5483                    (const_int 16)))
5484      (set (mem:SI (match_dup 2))
5485           (match_operand:SI 3 "arm_hard_register_operand" ""))
5486      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5487           (match_operand:SI 4 "arm_hard_register_operand" ""))
5488      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5489           (match_operand:SI 5 "arm_hard_register_operand" ""))
5490      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5491           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5492   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5493   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5494   [(set_attr "predicable" "yes")
5495    (set_attr "type" "store4")]
5496 )
5497
5498 (define_insn "*stmsi_postinc4_thumb"
5499   [(match_parallel 0 "store_multiple_operation"
5500     [(set (match_operand:SI 1 "s_register_operand" "=l")
5501           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5502                    (const_int 16)))
5503      (set (mem:SI (match_dup 2))
5504           (match_operand:SI 3 "arm_hard_register_operand" ""))
5505      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5506           (match_operand:SI 4 "arm_hard_register_operand" ""))
5507      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5508           (match_operand:SI 5 "arm_hard_register_operand" ""))
5509      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5510           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5511   "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5512   "stmia\\t%1!, {%3, %4, %5, %6}"
5513   [(set_attr "type" "store4")]
5514 )
5515
5516 (define_insn "*stmsi_postinc3"
5517   [(match_parallel 0 "store_multiple_operation"
5518     [(set (match_operand:SI 1 "s_register_operand" "=r")
5519           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5520                    (const_int 12)))
5521      (set (mem:SI (match_dup 2))
5522           (match_operand:SI 3 "arm_hard_register_operand" ""))
5523      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5524           (match_operand:SI 4 "arm_hard_register_operand" ""))
5525      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5526           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5527   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5528   "stm%?ia\\t%1!, {%3, %4, %5}"
5529   [(set_attr "predicable" "yes")
5530    (set_attr "type" "store3")]
5531 )
5532
5533 (define_insn "*stmsi_postinc2"
5534   [(match_parallel 0 "store_multiple_operation"
5535     [(set (match_operand:SI 1 "s_register_operand" "=r")
5536           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5537                    (const_int 8)))
5538      (set (mem:SI (match_dup 2))
5539           (match_operand:SI 3 "arm_hard_register_operand" ""))
5540      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5541           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5542   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5543   "stm%?ia\\t%1!, {%3, %4}"
5544   [(set_attr "predicable" "yes")
5545    (set_attr "type" "store2")]
5546 )
5547
5548 ;; Ordinary store multiple
5549
5550 (define_insn "*stmsi4"
5551   [(match_parallel 0 "store_multiple_operation"
5552     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5553           (match_operand:SI 2 "arm_hard_register_operand" ""))
5554      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5555           (match_operand:SI 3 "arm_hard_register_operand" ""))
5556      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5557           (match_operand:SI 4 "arm_hard_register_operand" ""))
5558      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5559           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5560   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5561   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5562   [(set_attr "predicable" "yes")
5563    (set_attr "type" "store4")]
5564 )
5565
5566 (define_insn "*stmsi3"
5567   [(match_parallel 0 "store_multiple_operation"
5568     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5569           (match_operand:SI 2 "arm_hard_register_operand" ""))
5570      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5571           (match_operand:SI 3 "arm_hard_register_operand" ""))
5572      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5573           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5574   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5575   "stm%?ia\\t%1, {%2, %3, %4}"
5576   [(set_attr "predicable" "yes")
5577    (set_attr "type" "store3")]
5578 )
5579
5580 (define_insn "*stmsi2"
5581   [(match_parallel 0 "store_multiple_operation"
5582     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5583           (match_operand:SI 2 "arm_hard_register_operand" ""))
5584      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5585           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5586   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5587   "stm%?ia\\t%1, {%2, %3}"
5588   [(set_attr "predicable" "yes")
5589    (set_attr "type" "store2")]
5590 )
5591
5592 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5593 ;; We could let this apply for blocks of less than this, but it clobbers so
5594 ;; many registers that there is then probably a better way.
5595
5596 (define_expand "movmemqi"
5597   [(match_operand:BLK 0 "general_operand" "")
5598    (match_operand:BLK 1 "general_operand" "")
5599    (match_operand:SI 2 "const_int_operand" "")
5600    (match_operand:SI 3 "const_int_operand" "")]
5601   "TARGET_EITHER"
5602   "
5603   if (TARGET_ARM)
5604     {
5605       if (arm_gen_movmemqi (operands))
5606         DONE;
5607       FAIL;
5608     }
5609   else /* TARGET_THUMB */
5610     {
5611       if (   INTVAL (operands[3]) != 4
5612           || INTVAL (operands[2]) > 48)
5613         FAIL;
5614
5615       thumb_expand_movmemqi (operands);
5616       DONE;
5617     }
5618   "
5619 )
5620
5621 ;; Thumb block-move insns
5622
5623 (define_insn "movmem12b"
5624   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5625         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5626    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5627         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5628    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5629         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5630    (set (match_operand:SI 0 "register_operand" "=l")
5631         (plus:SI (match_dup 2) (const_int 12)))
5632    (set (match_operand:SI 1 "register_operand" "=l")
5633         (plus:SI (match_dup 3) (const_int 12)))
5634    (clobber (match_scratch:SI 4 "=&l"))
5635    (clobber (match_scratch:SI 5 "=&l"))
5636    (clobber (match_scratch:SI 6 "=&l"))]
5637   "TARGET_THUMB"
5638   "* return thumb_output_move_mem_multiple (3, operands);"
5639   [(set_attr "length" "4")
5640    ; This isn't entirely accurate...  It loads as well, but in terms of
5641    ; scheduling the following insn it is better to consider it as a store
5642    (set_attr "type" "store3")]
5643 )
5644
5645 (define_insn "movmem8b"
5646   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5647         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5648    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5649         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5650    (set (match_operand:SI 0 "register_operand" "=l")
5651         (plus:SI (match_dup 2) (const_int 8)))
5652    (set (match_operand:SI 1 "register_operand" "=l")
5653         (plus:SI (match_dup 3) (const_int 8)))
5654    (clobber (match_scratch:SI 4 "=&l"))
5655    (clobber (match_scratch:SI 5 "=&l"))]
5656   "TARGET_THUMB"
5657   "* return thumb_output_move_mem_multiple (2, operands);"
5658   [(set_attr "length" "4")
5659    ; This isn't entirely accurate...  It loads as well, but in terms of
5660    ; scheduling the following insn it is better to consider it as a store
5661    (set_attr "type" "store2")]
5662 )
5663
5664 \f
5665
5666 ;; Compare & branch insns
5667 ;; The range calculations are based as follows:
5668 ;; For forward branches, the address calculation returns the address of
5669 ;; the next instruction.  This is 2 beyond the branch instruction.
5670 ;; For backward branches, the address calculation returns the address of
5671 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5672 ;; instruction for the shortest sequence, and 4 before the branch instruction
5673 ;; if we have to jump around an unconditional branch.
5674 ;; To the basic branch range the PC offset must be added (this is +4).
5675 ;; So for forward branches we have 
5676 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5677 ;; And for backward branches we have 
5678 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5679 ;;
5680 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5681 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5682
5683 (define_expand "cbranchsi4"
5684   [(set (pc) (if_then_else
5685               (match_operator 0 "arm_comparison_operator"
5686                [(match_operand:SI 1 "s_register_operand" "")
5687                 (match_operand:SI 2 "nonmemory_operand" "")])
5688               (label_ref (match_operand 3 "" ""))
5689               (pc)))]
5690   "TARGET_THUMB"
5691   "
5692   if (thumb_cmpneg_operand (operands[2], SImode))
5693     {
5694       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5695                                               operands[3], operands[0]));
5696       DONE;
5697     }
5698   if (!thumb_cmp_operand (operands[2], SImode))
5699     operands[2] = force_reg (SImode, operands[2]);
5700   ")
5701
5702 (define_insn "*cbranchsi4_insn"
5703   [(set (pc) (if_then_else
5704               (match_operator 0 "arm_comparison_operator"
5705                [(match_operand:SI 1 "s_register_operand" "l,*h")
5706                 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5707               (label_ref (match_operand 3 "" ""))
5708               (pc)))]
5709   "TARGET_THUMB"
5710   "*
5711   output_asm_insn (\"cmp\\t%1, %2\", operands);
5712
5713   switch (get_attr_length (insn))
5714     {
5715     case 4:  return \"b%d0\\t%l3\";
5716     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5717     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5718     }
5719   "
5720   [(set (attr "far_jump")
5721         (if_then_else
5722             (eq_attr "length" "8")
5723             (const_string "yes")
5724             (const_string "no")))
5725    (set (attr "length") 
5726         (if_then_else
5727             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5728                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5729             (const_int 4)
5730             (if_then_else
5731                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5732                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5733                 (const_int 6)
5734                 (const_int 8))))]
5735 )
5736
5737 (define_insn "cbranchsi4_scratch"
5738   [(set (pc) (if_then_else
5739               (match_operator 4 "arm_comparison_operator"
5740                [(match_operand:SI 1 "s_register_operand" "l,0")
5741                 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5742               (label_ref (match_operand 3 "" ""))
5743               (pc)))
5744    (clobber (match_scratch:SI 0 "=l,l"))]
5745   "TARGET_THUMB"
5746   "*
5747   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5748
5749   switch (get_attr_length (insn))
5750     {
5751     case 4:  return \"b%d4\\t%l3\";
5752     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5753     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5754     }
5755   "
5756   [(set (attr "far_jump")
5757         (if_then_else
5758             (eq_attr "length" "8")
5759             (const_string "yes")
5760             (const_string "no")))
5761    (set (attr "length") 
5762         (if_then_else
5763             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5764                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5765             (const_int 4)
5766             (if_then_else
5767                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5768                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5769                 (const_int 6)
5770                 (const_int 8))))]
5771 )
5772 (define_insn "*movsi_cbranchsi4"
5773   [(set (pc)
5774         (if_then_else
5775          (match_operator 3 "arm_comparison_operator"
5776           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5777            (const_int 0)])
5778          (label_ref (match_operand 2 "" ""))
5779          (pc)))
5780    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5781         (match_dup 1))]
5782   "TARGET_THUMB"
5783   "*{
5784   if (which_alternative == 0)
5785     output_asm_insn (\"cmp\t%0, #0\", operands);
5786   else if (which_alternative == 1)
5787     output_asm_insn (\"sub\t%0, %1, #0\", operands);
5788   else
5789     {
5790       output_asm_insn (\"cmp\t%1, #0\", operands);
5791       if (which_alternative == 2)
5792         output_asm_insn (\"mov\t%0, %1\", operands);
5793       else
5794         output_asm_insn (\"str\t%1, %0\", operands);
5795     }
5796   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5797     {
5798     case 4:  return \"b%d3\\t%l2\";
5799     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5800     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5801     }
5802   }"
5803   [(set (attr "far_jump")
5804         (if_then_else
5805             (ior (and (gt (symbol_ref ("which_alternative"))
5806                           (const_int 1))
5807                       (eq_attr "length" "8"))
5808                  (eq_attr "length" "10"))
5809             (const_string "yes")
5810             (const_string "no")))
5811    (set (attr "length")
5812      (if_then_else
5813        (le (symbol_ref ("which_alternative"))
5814                        (const_int 1))
5815        (if_then_else
5816          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5817               (le (minus (match_dup 2) (pc)) (const_int 256)))
5818          (const_int 4)
5819          (if_then_else
5820            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5821                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5822            (const_int 6)
5823            (const_int 8)))
5824        (if_then_else
5825          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5826               (le (minus (match_dup 2) (pc)) (const_int 256)))
5827          (const_int 6)
5828          (if_then_else
5829            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5830                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5831            (const_int 8)
5832            (const_int 10)))))]
5833 )
5834
5835 (define_insn "*negated_cbranchsi4"
5836   [(set (pc)
5837         (if_then_else
5838          (match_operator 0 "equality_operator"
5839           [(match_operand:SI 1 "s_register_operand" "l")
5840            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5841          (label_ref (match_operand 3 "" ""))
5842          (pc)))]
5843   "TARGET_THUMB"
5844   "*
5845   output_asm_insn (\"cmn\\t%1, %2\", operands);
5846   switch (get_attr_length (insn))
5847     {
5848     case 4:  return \"b%d0\\t%l3\";
5849     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5850     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5851     }
5852   "
5853   [(set (attr "far_jump")
5854         (if_then_else
5855             (eq_attr "length" "8")
5856             (const_string "yes")
5857             (const_string "no")))
5858    (set (attr "length") 
5859         (if_then_else
5860             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5861                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5862             (const_int 4)
5863             (if_then_else
5864                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5865                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5866                 (const_int 6)
5867                 (const_int 8))))]
5868 )
5869
5870 (define_insn "*tbit_cbranch"
5871   [(set (pc)
5872         (if_then_else
5873          (match_operator 0 "equality_operator"
5874           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5875                             (const_int 1)
5876                             (match_operand:SI 2 "const_int_operand" "i"))
5877            (const_int 0)])
5878          (label_ref (match_operand 3 "" ""))
5879          (pc)))
5880    (clobber (match_scratch:SI 4 "=l"))]
5881   "TARGET_THUMB"
5882   "*
5883   {
5884   rtx op[3];
5885   op[0] = operands[4];
5886   op[1] = operands[1];
5887   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5888
5889   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5890   switch (get_attr_length (insn))
5891     {
5892     case 4:  return \"b%d0\\t%l3\";
5893     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5894     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5895     }
5896   }"
5897   [(set (attr "far_jump")
5898         (if_then_else
5899             (eq_attr "length" "8")
5900             (const_string "yes")
5901             (const_string "no")))
5902    (set (attr "length") 
5903         (if_then_else
5904             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5905                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5906             (const_int 4)
5907             (if_then_else
5908                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5909                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5910                 (const_int 6)
5911                 (const_int 8))))]
5912 )
5913   
5914 (define_insn "*tstsi3_cbranch"
5915   [(set (pc)
5916         (if_then_else
5917          (match_operator 3 "equality_operator"
5918           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5919                    (match_operand:SI 1 "s_register_operand" "l"))
5920            (const_int 0)])
5921          (label_ref (match_operand 2 "" ""))
5922          (pc)))]
5923   "TARGET_THUMB"
5924   "*
5925   {
5926   output_asm_insn (\"tst\\t%0, %1\", operands);
5927   switch (get_attr_length (insn))
5928     {
5929     case 4:  return \"b%d3\\t%l2\";
5930     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5931     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5932     }
5933   }"
5934   [(set (attr "far_jump")
5935         (if_then_else
5936             (eq_attr "length" "8")
5937             (const_string "yes")
5938             (const_string "no")))
5939    (set (attr "length") 
5940         (if_then_else
5941             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5942                  (le (minus (match_dup 2) (pc)) (const_int 256)))
5943             (const_int 4)
5944             (if_then_else
5945                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5946                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
5947                 (const_int 6)
5948                 (const_int 8))))]
5949 )
5950   
5951 (define_insn "*andsi3_cbranch"
5952   [(set (pc)
5953         (if_then_else
5954          (match_operator 5 "equality_operator"
5955           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5956                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5957            (const_int 0)])
5958          (label_ref (match_operand 4 "" ""))
5959          (pc)))
5960    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5961         (and:SI (match_dup 2) (match_dup 3)))
5962    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5963   "TARGET_THUMB"
5964   "*
5965   {
5966   if (which_alternative == 0)
5967     output_asm_insn (\"and\\t%0, %3\", operands);
5968   else if (which_alternative == 1)
5969     {
5970       output_asm_insn (\"and\\t%1, %3\", operands);
5971       output_asm_insn (\"mov\\t%0, %1\", operands);
5972     }
5973   else
5974     {
5975       output_asm_insn (\"and\\t%1, %3\", operands);
5976       output_asm_insn (\"str\\t%1, %0\", operands);
5977     }
5978
5979   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5980     {
5981     case 4:  return \"b%d5\\t%l4\";
5982     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5983     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5984     }
5985   }"
5986   [(set (attr "far_jump")
5987         (if_then_else
5988             (ior (and (eq (symbol_ref ("which_alternative"))
5989                           (const_int 0))
5990                       (eq_attr "length" "8"))
5991                  (eq_attr "length" "10"))
5992             (const_string "yes")
5993             (const_string "no")))
5994    (set (attr "length")
5995      (if_then_else
5996        (eq (symbol_ref ("which_alternative"))
5997                        (const_int 0))
5998        (if_then_else
5999          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6000               (le (minus (match_dup 4) (pc)) (const_int 256)))
6001          (const_int 4)
6002          (if_then_else
6003            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6004                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6005            (const_int 6)
6006            (const_int 8)))
6007        (if_then_else
6008          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6009               (le (minus (match_dup 4) (pc)) (const_int 256)))
6010          (const_int 6)
6011          (if_then_else
6012            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6013                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6014            (const_int 8)
6015            (const_int 10)))))]
6016 )
6017
6018 (define_insn "*orrsi3_cbranch_scratch"
6019   [(set (pc)
6020         (if_then_else
6021          (match_operator 4 "equality_operator"
6022           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6023                    (match_operand:SI 2 "s_register_operand" "l"))
6024            (const_int 0)])
6025          (label_ref (match_operand 3 "" ""))
6026          (pc)))
6027    (clobber (match_scratch:SI 0 "=l"))]
6028   "TARGET_THUMB"
6029   "*
6030   {
6031   output_asm_insn (\"orr\\t%0, %2\", operands);
6032   switch (get_attr_length (insn))
6033     {
6034     case 4:  return \"b%d4\\t%l3\";
6035     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6036     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6037     }
6038   }"
6039   [(set (attr "far_jump")
6040         (if_then_else
6041             (eq_attr "length" "8")
6042             (const_string "yes")
6043             (const_string "no")))
6044    (set (attr "length") 
6045         (if_then_else
6046             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6047                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6048             (const_int 4)
6049             (if_then_else
6050                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6051                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6052                 (const_int 6)
6053                 (const_int 8))))]
6054 )
6055   
6056 (define_insn "*orrsi3_cbranch"
6057   [(set (pc)
6058         (if_then_else
6059          (match_operator 5 "equality_operator"
6060           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6061                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6062            (const_int 0)])
6063          (label_ref (match_operand 4 "" ""))
6064          (pc)))
6065    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6066         (ior:SI (match_dup 2) (match_dup 3)))
6067    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6068   "TARGET_THUMB"
6069   "*
6070   {
6071   if (which_alternative == 0)
6072     output_asm_insn (\"orr\\t%0, %3\", operands);
6073   else if (which_alternative == 1)
6074     {
6075       output_asm_insn (\"orr\\t%1, %3\", operands);
6076       output_asm_insn (\"mov\\t%0, %1\", operands);
6077     }
6078   else
6079     {
6080       output_asm_insn (\"orr\\t%1, %3\", operands);
6081       output_asm_insn (\"str\\t%1, %0\", operands);
6082     }
6083
6084   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6085     {
6086     case 4:  return \"b%d5\\t%l4\";
6087     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6088     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6089     }
6090   }"
6091   [(set (attr "far_jump")
6092         (if_then_else
6093             (ior (and (eq (symbol_ref ("which_alternative"))
6094                           (const_int 0))
6095                       (eq_attr "length" "8"))
6096                  (eq_attr "length" "10"))
6097             (const_string "yes")
6098             (const_string "no")))
6099    (set (attr "length")
6100      (if_then_else
6101        (eq (symbol_ref ("which_alternative"))
6102                        (const_int 0))
6103        (if_then_else
6104          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6105               (le (minus (match_dup 4) (pc)) (const_int 256)))
6106          (const_int 4)
6107          (if_then_else
6108            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6109                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6110            (const_int 6)
6111            (const_int 8)))
6112        (if_then_else
6113          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6114               (le (minus (match_dup 4) (pc)) (const_int 256)))
6115          (const_int 6)
6116          (if_then_else
6117            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6118                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6119            (const_int 8)
6120            (const_int 10)))))]
6121 )
6122
6123 (define_insn "*xorsi3_cbranch_scratch"
6124   [(set (pc)
6125         (if_then_else
6126          (match_operator 4 "equality_operator"
6127           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6128                    (match_operand:SI 2 "s_register_operand" "l"))
6129            (const_int 0)])
6130          (label_ref (match_operand 3 "" ""))
6131          (pc)))
6132    (clobber (match_scratch:SI 0 "=l"))]
6133   "TARGET_THUMB"
6134   "*
6135   {
6136   output_asm_insn (\"eor\\t%0, %2\", operands);
6137   switch (get_attr_length (insn))
6138     {
6139     case 4:  return \"b%d4\\t%l3\";
6140     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6141     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6142     }
6143   }"
6144   [(set (attr "far_jump")
6145         (if_then_else
6146             (eq_attr "length" "8")
6147             (const_string "yes")
6148             (const_string "no")))
6149    (set (attr "length") 
6150         (if_then_else
6151             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6152                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6153             (const_int 4)
6154             (if_then_else
6155                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6156                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6157                 (const_int 6)
6158                 (const_int 8))))]
6159 )
6160   
6161 (define_insn "*xorsi3_cbranch"
6162   [(set (pc)
6163         (if_then_else
6164          (match_operator 5 "equality_operator"
6165           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6166                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6167            (const_int 0)])
6168          (label_ref (match_operand 4 "" ""))
6169          (pc)))
6170    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6171         (xor:SI (match_dup 2) (match_dup 3)))
6172    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6173   "TARGET_THUMB"
6174   "*
6175   {
6176   if (which_alternative == 0)
6177     output_asm_insn (\"eor\\t%0, %3\", operands);
6178   else if (which_alternative == 1)
6179     {
6180       output_asm_insn (\"eor\\t%1, %3\", operands);
6181       output_asm_insn (\"mov\\t%0, %1\", operands);
6182     }
6183   else
6184     {
6185       output_asm_insn (\"eor\\t%1, %3\", operands);
6186       output_asm_insn (\"str\\t%1, %0\", operands);
6187     }
6188
6189   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6190     {
6191     case 4:  return \"b%d5\\t%l4\";
6192     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6193     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6194     }
6195   }"
6196   [(set (attr "far_jump")
6197         (if_then_else
6198             (ior (and (eq (symbol_ref ("which_alternative"))
6199                           (const_int 0))
6200                       (eq_attr "length" "8"))
6201                  (eq_attr "length" "10"))
6202             (const_string "yes")
6203             (const_string "no")))
6204    (set (attr "length")
6205      (if_then_else
6206        (eq (symbol_ref ("which_alternative"))
6207                        (const_int 0))
6208        (if_then_else
6209          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6210               (le (minus (match_dup 4) (pc)) (const_int 256)))
6211          (const_int 4)
6212          (if_then_else
6213            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6214                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6215            (const_int 6)
6216            (const_int 8)))
6217        (if_then_else
6218          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6219               (le (minus (match_dup 4) (pc)) (const_int 256)))
6220          (const_int 6)
6221          (if_then_else
6222            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6223                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6224            (const_int 8)
6225            (const_int 10)))))]
6226 )
6227
6228 (define_insn "*bicsi3_cbranch_scratch"
6229   [(set (pc)
6230         (if_then_else
6231          (match_operator 4 "equality_operator"
6232           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6233                    (match_operand:SI 1 "s_register_operand" "0"))
6234            (const_int 0)])
6235          (label_ref (match_operand 3 "" ""))
6236          (pc)))
6237    (clobber (match_scratch:SI 0 "=l"))]
6238   "TARGET_THUMB"
6239   "*
6240   {
6241   output_asm_insn (\"bic\\t%0, %2\", operands);
6242   switch (get_attr_length (insn))
6243     {
6244     case 4:  return \"b%d4\\t%l3\";
6245     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6246     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6247     }
6248   }"
6249   [(set (attr "far_jump")
6250         (if_then_else
6251             (eq_attr "length" "8")
6252             (const_string "yes")
6253             (const_string "no")))
6254    (set (attr "length") 
6255         (if_then_else
6256             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6257                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6258             (const_int 4)
6259             (if_then_else
6260                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6261                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6262                 (const_int 6)
6263                 (const_int 8))))]
6264 )
6265   
6266 (define_insn "*bicsi3_cbranch"
6267   [(set (pc)
6268         (if_then_else
6269          (match_operator 5 "equality_operator"
6270           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6271                    (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6272            (const_int 0)])
6273          (label_ref (match_operand 4 "" ""))
6274          (pc)))
6275    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6276         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6277    (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6278   "TARGET_THUMB"
6279   "*
6280   {
6281   if (which_alternative == 0)
6282     output_asm_insn (\"bic\\t%0, %3\", operands);
6283   else if (which_alternative <= 2)
6284     {
6285       output_asm_insn (\"bic\\t%1, %3\", operands);
6286       /* It's ok if OP0 is a lo-reg, even though the mov will set the
6287          conditions again, since we're only testing for equality.  */
6288       output_asm_insn (\"mov\\t%0, %1\", operands);
6289     }
6290   else
6291     {
6292       output_asm_insn (\"bic\\t%1, %3\", operands);
6293       output_asm_insn (\"str\\t%1, %0\", operands);
6294     }
6295
6296   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6297     {
6298     case 4:  return \"b%d5\\t%l4\";
6299     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6300     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6301     }
6302   }"
6303   [(set (attr "far_jump")
6304         (if_then_else
6305             (ior (and (eq (symbol_ref ("which_alternative"))
6306                           (const_int 0))
6307                       (eq_attr "length" "8"))
6308                  (eq_attr "length" "10"))
6309             (const_string "yes")
6310             (const_string "no")))
6311    (set (attr "length")
6312      (if_then_else
6313        (eq (symbol_ref ("which_alternative"))
6314                        (const_int 0))
6315        (if_then_else
6316          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6317               (le (minus (match_dup 4) (pc)) (const_int 256)))
6318          (const_int 4)
6319          (if_then_else
6320            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6321                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6322            (const_int 6)
6323            (const_int 8)))
6324        (if_then_else
6325          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6326               (le (minus (match_dup 4) (pc)) (const_int 256)))
6327          (const_int 6)
6328          (if_then_else
6329            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6330                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6331            (const_int 8)
6332            (const_int 10)))))]
6333 )
6334
6335 (define_insn "*cbranchne_decr1"
6336   [(set (pc)
6337         (if_then_else (match_operator 3 "equality_operator"
6338                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6339                         (const_int 0)])
6340                       (label_ref (match_operand 4 "" ""))
6341                       (pc)))
6342    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6343         (plus:SI (match_dup 2) (const_int -1)))
6344    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6345   "TARGET_THUMB"
6346   "*
6347    {
6348      rtx cond[2];
6349      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6350                                 ? GEU : LTU),
6351                                VOIDmode, operands[2], const1_rtx);
6352      cond[1] = operands[4];
6353
6354      if (which_alternative == 0)
6355        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6356      else if (which_alternative == 1)
6357        {
6358          /* We must provide an alternative for a hi reg because reload 
6359             cannot handle output reloads on a jump instruction, but we
6360             can't subtract into that.  Fortunately a mov from lo to hi
6361             does not clobber the condition codes.  */
6362          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6363          output_asm_insn (\"mov\\t%0, %1\", operands);
6364        }
6365      else
6366        {
6367          /* Similarly, but the target is memory.  */
6368          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6369          output_asm_insn (\"str\\t%1, %0\", operands);
6370        }
6371
6372      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6373        {
6374          case 4:
6375            output_asm_insn (\"b%d0\\t%l1\", cond);
6376            return \"\";
6377          case 6:
6378            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6379            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6380          default:
6381            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6382            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6383        }
6384    }
6385   "
6386   [(set (attr "far_jump")
6387         (if_then_else
6388             (ior (and (eq (symbol_ref ("which_alternative"))
6389                           (const_int 0))
6390                       (eq_attr "length" "8"))
6391                  (eq_attr "length" "10"))
6392             (const_string "yes")
6393             (const_string "no")))
6394    (set_attr_alternative "length"
6395       [
6396        ;; Alternative 0
6397        (if_then_else
6398          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6399               (le (minus (match_dup 4) (pc)) (const_int 256)))
6400          (const_int 4)
6401          (if_then_else
6402            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6403                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6404            (const_int 6)
6405            (const_int 8)))
6406        ;; Alternative 1
6407        (if_then_else
6408          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6409               (le (minus (match_dup 4) (pc)) (const_int 256)))
6410          (const_int 6)
6411          (if_then_else
6412            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6413                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6414            (const_int 8)
6415            (const_int 10)))
6416        ;; Alternative 2
6417        (if_then_else
6418          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6419               (le (minus (match_dup 4) (pc)) (const_int 256)))
6420          (const_int 6)
6421          (if_then_else
6422            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6423                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6424            (const_int 8)
6425            (const_int 10)))
6426        ;; Alternative 3
6427        (if_then_else
6428          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6429               (le (minus (match_dup 4) (pc)) (const_int 256)))
6430          (const_int 6)
6431          (if_then_else
6432            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6433                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6434            (const_int 8)
6435            (const_int 10)))])]
6436 )
6437
6438 (define_insn "*addsi3_cbranch"
6439   [(set (pc)
6440         (if_then_else
6441          (match_operator 4 "comparison_operator"
6442           [(plus:SI
6443             (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6444             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6445            (const_int 0)])
6446          (label_ref (match_operand 5 "" ""))
6447          (pc)))
6448    (set
6449     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6450     (plus:SI (match_dup 2) (match_dup 3)))
6451    (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6452   "TARGET_THUMB
6453    && (GET_CODE (operands[4]) == EQ
6454        || GET_CODE (operands[4]) == NE
6455        || GET_CODE (operands[4]) == GE
6456        || GET_CODE (operands[4]) == LT)"
6457   "*
6458    {
6459      rtx cond[3];
6460
6461      
6462      cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6463      cond[1] = operands[2];
6464      cond[2] = operands[3];
6465
6466      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6467        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6468      else
6469        output_asm_insn (\"add\\t%0, %1, %2\", cond);
6470
6471      if (which_alternative >= 3
6472          && which_alternative < 4)
6473        output_asm_insn (\"mov\\t%0, %1\", operands);
6474      else if (which_alternative >= 4)
6475        output_asm_insn (\"str\\t%1, %0\", operands);
6476
6477      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6478        {
6479          case 4:
6480            return \"b%d4\\t%l5\";
6481          case 6:
6482            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6483          default:
6484            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6485        }
6486    }
6487   "
6488   [(set (attr "far_jump")
6489         (if_then_else
6490             (ior (and (lt (symbol_ref ("which_alternative"))
6491                           (const_int 3))
6492                       (eq_attr "length" "8"))
6493                  (eq_attr "length" "10"))
6494             (const_string "yes")
6495             (const_string "no")))
6496    (set (attr "length")
6497      (if_then_else
6498        (lt (symbol_ref ("which_alternative"))
6499                        (const_int 3))
6500        (if_then_else
6501          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6502               (le (minus (match_dup 5) (pc)) (const_int 256)))
6503          (const_int 4)
6504          (if_then_else
6505            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6506                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6507            (const_int 6)
6508            (const_int 8)))
6509        (if_then_else
6510          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6511               (le (minus (match_dup 5) (pc)) (const_int 256)))
6512          (const_int 6)
6513          (if_then_else
6514            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6515                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6516            (const_int 8)
6517            (const_int 10)))))]
6518 )
6519
6520 (define_insn "*addsi3_cbranch_scratch"
6521   [(set (pc)
6522         (if_then_else
6523          (match_operator 3 "comparison_operator"
6524           [(plus:SI
6525             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6526             (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
6527            (const_int 0)])
6528          (label_ref (match_operand 4 "" ""))
6529          (pc)))
6530    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6531   "TARGET_THUMB
6532    && (GET_CODE (operands[3]) == EQ
6533        || GET_CODE (operands[3]) == NE
6534        || GET_CODE (operands[3]) == GE
6535        || GET_CODE (operands[3]) == LT)"
6536   "*
6537    {
6538      switch (which_alternative)
6539        {
6540        case 0:
6541          output_asm_insn (\"cmp\t%1, #%n2\", operands);
6542          break;
6543        case 1:
6544          output_asm_insn (\"cmn\t%1, %2\", operands);
6545          break;
6546        case 2:
6547          if (INTVAL (operands[2]) < 0)
6548            output_asm_insn (\"sub\t%0, %1, %2\", operands);
6549          else
6550            output_asm_insn (\"add\t%0, %1, %2\", operands);
6551          break;
6552        case 3:
6553          if (INTVAL (operands[2]) < 0)
6554            output_asm_insn (\"sub\t%0, %0, %2\", operands);
6555          else
6556            output_asm_insn (\"add\t%0, %0, %2\", operands);
6557          break;
6558        }
6559
6560      switch (get_attr_length (insn))
6561        {
6562          case 4:
6563            return \"b%d3\\t%l4\";
6564          case 6:
6565            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6566          default:
6567            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6568        }
6569    }
6570   "
6571   [(set (attr "far_jump")
6572         (if_then_else
6573             (eq_attr "length" "8")
6574             (const_string "yes")
6575             (const_string "no")))
6576    (set (attr "length")
6577        (if_then_else
6578          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6579               (le (minus (match_dup 4) (pc)) (const_int 256)))
6580          (const_int 4)
6581          (if_then_else
6582            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6583                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6584            (const_int 6)
6585            (const_int 8))))]
6586 )
6587
6588 (define_insn "*subsi3_cbranch"
6589   [(set (pc)
6590         (if_then_else
6591          (match_operator 4 "comparison_operator"
6592           [(minus:SI
6593             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6594             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6595            (const_int 0)])
6596          (label_ref (match_operand 5 "" ""))
6597          (pc)))
6598    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6599         (minus:SI (match_dup 2) (match_dup 3)))
6600    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6601   "TARGET_THUMB
6602    && (GET_CODE (operands[4]) == EQ
6603        || GET_CODE (operands[4]) == NE
6604        || GET_CODE (operands[4]) == GE
6605        || GET_CODE (operands[4]) == LT)"
6606   "*
6607    {
6608      if (which_alternative == 0)
6609        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6610      else if (which_alternative == 1)
6611        {
6612          /* We must provide an alternative for a hi reg because reload 
6613             cannot handle output reloads on a jump instruction, but we
6614             can't subtract into that.  Fortunately a mov from lo to hi
6615             does not clobber the condition codes.  */
6616          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6617          output_asm_insn (\"mov\\t%0, %1\", operands);
6618        }
6619      else
6620        {
6621          /* Similarly, but the target is memory.  */
6622          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6623          output_asm_insn (\"str\\t%1, %0\", operands);
6624        }
6625
6626      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6627        {
6628          case 4:
6629            return \"b%d4\\t%l5\";
6630          case 6:
6631            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6632          default:
6633            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6634        }
6635    }
6636   "
6637   [(set (attr "far_jump")
6638         (if_then_else
6639             (ior (and (eq (symbol_ref ("which_alternative"))
6640                           (const_int 0))
6641                       (eq_attr "length" "8"))
6642                  (eq_attr "length" "10"))
6643             (const_string "yes")
6644             (const_string "no")))
6645    (set (attr "length")
6646      (if_then_else
6647        (eq (symbol_ref ("which_alternative"))
6648                        (const_int 0))
6649        (if_then_else
6650          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6651               (le (minus (match_dup 5) (pc)) (const_int 256)))
6652          (const_int 4)
6653          (if_then_else
6654            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6655                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6656            (const_int 6)
6657            (const_int 8)))
6658        (if_then_else
6659          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6660               (le (minus (match_dup 5) (pc)) (const_int 256)))
6661          (const_int 6)
6662          (if_then_else
6663            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6664                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6665            (const_int 8)
6666            (const_int 10)))))]
6667 )
6668
6669 (define_insn "*subsi3_cbranch_scratch"
6670   [(set (pc)
6671         (if_then_else
6672          (match_operator 0 "arm_comparison_operator"
6673           [(minus:SI (match_operand:SI 1 "register_operand" "l")
6674                      (match_operand:SI 2 "nonmemory_operand" "l"))
6675            (const_int 0)])
6676          (label_ref (match_operand 3 "" ""))
6677          (pc)))]
6678   "TARGET_THUMB
6679    && (GET_CODE (operands[0]) == EQ
6680        || GET_CODE (operands[0]) == NE
6681        || GET_CODE (operands[0]) == GE
6682        || GET_CODE (operands[0]) == LT)"
6683   "*
6684   output_asm_insn (\"cmp\\t%1, %2\", operands);
6685   switch (get_attr_length (insn))
6686     {
6687     case 4:  return \"b%d0\\t%l3\";
6688     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6689     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6690     }
6691   "
6692   [(set (attr "far_jump")
6693         (if_then_else
6694             (eq_attr "length" "8")
6695             (const_string "yes")
6696             (const_string "no")))
6697    (set (attr "length") 
6698         (if_then_else
6699             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6700                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6701             (const_int 4)
6702             (if_then_else
6703                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6704                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6705                 (const_int 6)
6706                 (const_int 8))))]
6707 )
6708
6709 ;; Comparison and test insns
6710
6711 (define_expand "cmpsi"
6712   [(match_operand:SI 0 "s_register_operand" "")
6713    (match_operand:SI 1 "arm_add_operand" "")]
6714   "TARGET_ARM"
6715   "{
6716     arm_compare_op0 = operands[0];
6717     arm_compare_op1 = operands[1];
6718     DONE;
6719   }"
6720 )
6721
6722 (define_expand "cmpsf"
6723   [(match_operand:SF 0 "s_register_operand" "")
6724    (match_operand:SF 1 "arm_float_compare_operand" "")]
6725   "TARGET_ARM && TARGET_HARD_FLOAT"
6726   "
6727   arm_compare_op0 = operands[0];
6728   arm_compare_op1 = operands[1];
6729   DONE;
6730   "
6731 )
6732
6733 (define_expand "cmpdf"
6734   [(match_operand:DF 0 "s_register_operand" "")
6735    (match_operand:DF 1 "arm_float_compare_operand" "")]
6736   "TARGET_ARM && TARGET_HARD_FLOAT"
6737   "
6738   arm_compare_op0 = operands[0];
6739   arm_compare_op1 = operands[1];
6740   DONE;
6741   "
6742 )
6743
6744 (define_insn "*arm_cmpsi_insn"
6745   [(set (reg:CC CC_REGNUM)
6746         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6747                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
6748   "TARGET_ARM"
6749   "@
6750    cmp%?\\t%0, %1
6751    cmn%?\\t%0, #%n1"
6752   [(set_attr "conds" "set")]
6753 )
6754
6755 (define_insn "*cmpsi_shiftsi"
6756   [(set (reg:CC CC_REGNUM)
6757         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
6758                     (match_operator:SI  3 "shift_operator"
6759                      [(match_operand:SI 1 "s_register_operand" "r")
6760                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
6761   "TARGET_ARM"
6762   "cmp%?\\t%0, %1%S3"
6763   [(set_attr "conds" "set")
6764    (set_attr "shift" "1")
6765    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6766                       (const_string "alu_shift")
6767                       (const_string "alu_shift_reg")))]
6768 )
6769
6770 (define_insn "*cmpsi_shiftsi_swp"
6771   [(set (reg:CC_SWP CC_REGNUM)
6772         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6773                          [(match_operand:SI 1 "s_register_operand" "r")
6774                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
6775                         (match_operand:SI 0 "s_register_operand" "r")))]
6776   "TARGET_ARM"
6777   "cmp%?\\t%0, %1%S3"
6778   [(set_attr "conds" "set")
6779    (set_attr "shift" "1")
6780    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6781                       (const_string "alu_shift")
6782                       (const_string "alu_shift_reg")))]
6783 )
6784
6785 (define_insn "*cmpsi_negshiftsi_si"
6786   [(set (reg:CC_Z CC_REGNUM)
6787         (compare:CC_Z
6788          (neg:SI (match_operator:SI 1 "shift_operator"
6789                     [(match_operand:SI 2 "s_register_operand" "r")
6790                      (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6791          (match_operand:SI 0 "s_register_operand" "r")))]
6792   "TARGET_ARM"
6793   "cmn%?\\t%0, %2%S1"
6794   [(set_attr "conds" "set")
6795    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
6796                                     (const_string "alu_shift")
6797                                     (const_string "alu_shift_reg")))]
6798 )
6799
6800 ;; Cirrus SF compare instruction
6801 (define_insn "*cirrus_cmpsf"
6802   [(set (reg:CCFP CC_REGNUM)
6803         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6804                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
6805   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6806   "cfcmps%?\\tr15, %V0, %V1"
6807   [(set_attr "type"   "mav_farith")
6808    (set_attr "cirrus" "compare")]
6809 )
6810
6811 ;; Cirrus DF compare instruction
6812 (define_insn "*cirrus_cmpdf"
6813   [(set (reg:CCFP CC_REGNUM)
6814         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6815                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
6816   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6817   "cfcmpd%?\\tr15, %V0, %V1"
6818   [(set_attr "type"   "mav_farith")
6819    (set_attr "cirrus" "compare")]
6820 )
6821
6822 ;; Cirrus DI compare instruction
6823 (define_expand "cmpdi"
6824   [(match_operand:DI 0 "cirrus_fp_register" "")
6825    (match_operand:DI 1 "cirrus_fp_register" "")]
6826   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6827   "{
6828      arm_compare_op0 = operands[0];
6829      arm_compare_op1 = operands[1];
6830      DONE;
6831    }")
6832
6833 (define_insn "*cirrus_cmpdi"
6834   [(set (reg:CC CC_REGNUM)
6835         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6836                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
6837   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6838   "cfcmp64%?\\tr15, %V0, %V1"
6839   [(set_attr "type"   "mav_farith")
6840    (set_attr "cirrus" "compare")]
6841 )
6842
6843 ; This insn allows redundant compares to be removed by cse, nothing should
6844 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6845 ; is deleted later on. The match_dup will match the mode here, so that
6846 ; mode changes of the condition codes aren't lost by this even though we don't
6847 ; specify what they are.
6848
6849 (define_insn "*deleted_compare"
6850   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6851   "TARGET_ARM"
6852   "\\t%@ deleted compare"
6853   [(set_attr "conds" "set")
6854    (set_attr "length" "0")]
6855 )
6856
6857 \f
6858 ;; Conditional branch insns
6859
6860 (define_expand "beq"
6861   [(set (pc)
6862         (if_then_else (eq (match_dup 1) (const_int 0))
6863                       (label_ref (match_operand 0 "" ""))
6864                       (pc)))]
6865   "TARGET_ARM"
6866   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6867 )
6868
6869 (define_expand "bne"
6870   [(set (pc)
6871         (if_then_else (ne (match_dup 1) (const_int 0))
6872                       (label_ref (match_operand 0 "" ""))
6873                       (pc)))]
6874   "TARGET_ARM"
6875   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6876 )
6877
6878 (define_expand "bgt"
6879   [(set (pc)
6880         (if_then_else (gt (match_dup 1) (const_int 0))
6881                       (label_ref (match_operand 0 "" ""))
6882                       (pc)))]
6883   "TARGET_ARM"
6884   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6885 )
6886
6887 (define_expand "ble"
6888   [(set (pc)
6889         (if_then_else (le (match_dup 1) (const_int 0))
6890                       (label_ref (match_operand 0 "" ""))
6891                       (pc)))]
6892   "TARGET_ARM"
6893   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6894 )
6895
6896 (define_expand "bge"
6897   [(set (pc)
6898         (if_then_else (ge (match_dup 1) (const_int 0))
6899                       (label_ref (match_operand 0 "" ""))
6900                       (pc)))]
6901   "TARGET_ARM"
6902   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6903 )
6904
6905 (define_expand "blt"
6906   [(set (pc)
6907         (if_then_else (lt (match_dup 1) (const_int 0))
6908                       (label_ref (match_operand 0 "" ""))
6909                       (pc)))]
6910   "TARGET_ARM"
6911   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6912 )
6913
6914 (define_expand "bgtu"
6915   [(set (pc)
6916         (if_then_else (gtu (match_dup 1) (const_int 0))
6917                       (label_ref (match_operand 0 "" ""))
6918                       (pc)))]
6919   "TARGET_ARM"
6920   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6921 )
6922
6923 (define_expand "bleu"
6924   [(set (pc)
6925         (if_then_else (leu (match_dup 1) (const_int 0))
6926                       (label_ref (match_operand 0 "" ""))
6927                       (pc)))]
6928   "TARGET_ARM"
6929   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6930 )
6931
6932 (define_expand "bgeu"
6933   [(set (pc)
6934         (if_then_else (geu (match_dup 1) (const_int 0))
6935                       (label_ref (match_operand 0 "" ""))
6936                       (pc)))]
6937   "TARGET_ARM"
6938   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6939 )
6940
6941 (define_expand "bltu"
6942   [(set (pc)
6943         (if_then_else (ltu (match_dup 1) (const_int 0))
6944                       (label_ref (match_operand 0 "" ""))
6945                       (pc)))]
6946   "TARGET_ARM"
6947   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6948 )
6949
6950 (define_expand "bunordered"
6951   [(set (pc)
6952         (if_then_else (unordered (match_dup 1) (const_int 0))
6953                       (label_ref (match_operand 0 "" ""))
6954                       (pc)))]
6955   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6956   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6957                                       arm_compare_op1);"
6958 )
6959
6960 (define_expand "bordered"
6961   [(set (pc)
6962         (if_then_else (ordered (match_dup 1) (const_int 0))
6963                       (label_ref (match_operand 0 "" ""))
6964                       (pc)))]
6965   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6966   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6967                                       arm_compare_op1);"
6968 )
6969
6970 (define_expand "bungt"
6971   [(set (pc)
6972         (if_then_else (ungt (match_dup 1) (const_int 0))
6973                       (label_ref (match_operand 0 "" ""))
6974                       (pc)))]
6975   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6976   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
6977 )
6978
6979 (define_expand "bunlt"
6980   [(set (pc)
6981         (if_then_else (unlt (match_dup 1) (const_int 0))
6982                       (label_ref (match_operand 0 "" ""))
6983                       (pc)))]
6984   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6985   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
6986 )
6987
6988 (define_expand "bunge"
6989   [(set (pc)
6990         (if_then_else (unge (match_dup 1) (const_int 0))
6991                       (label_ref (match_operand 0 "" ""))
6992                       (pc)))]
6993   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6994   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
6995 )
6996
6997 (define_expand "bunle"
6998   [(set (pc)
6999         (if_then_else (unle (match_dup 1) (const_int 0))
7000                       (label_ref (match_operand 0 "" ""))
7001                       (pc)))]
7002   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7003   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
7004 )
7005
7006 ;; The following two patterns need two branch instructions, since there is
7007 ;; no single instruction that will handle all cases.
7008 (define_expand "buneq"
7009   [(set (pc)
7010         (if_then_else (uneq (match_dup 1) (const_int 0))
7011                       (label_ref (match_operand 0 "" ""))
7012                       (pc)))]
7013   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7014   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
7015 )
7016
7017 (define_expand "bltgt"
7018   [(set (pc)
7019         (if_then_else (ltgt (match_dup 1) (const_int 0))
7020                       (label_ref (match_operand 0 "" ""))
7021                       (pc)))]
7022   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7023   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
7024 )
7025
7026 ;;
7027 ;; Patterns to match conditional branch insns.
7028 ;;
7029
7030 ; Special pattern to match UNEQ.
7031 (define_insn "*arm_buneq"
7032   [(set (pc)
7033         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7034                       (label_ref (match_operand 0 "" ""))
7035                       (pc)))]
7036   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7037   "*
7038   if (arm_ccfsm_state != 0)
7039     abort ();
7040
7041   return \"bvs\\t%l0\;beq\\t%l0\";
7042   "
7043   [(set_attr "conds" "jump_clob")
7044    (set_attr "length" "8")]
7045 )
7046
7047 ; Special pattern to match LTGT.
7048 (define_insn "*arm_bltgt"
7049   [(set (pc)
7050         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7051                       (label_ref (match_operand 0 "" ""))
7052                       (pc)))]
7053   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7054   "*
7055   if (arm_ccfsm_state != 0)
7056     abort ();
7057
7058   return \"bmi\\t%l0\;bgt\\t%l0\";
7059   "
7060   [(set_attr "conds" "jump_clob")
7061    (set_attr "length" "8")]
7062 )
7063
7064 (define_insn "*arm_cond_branch"
7065   [(set (pc)
7066         (if_then_else (match_operator 1 "arm_comparison_operator"
7067                        [(match_operand 2 "cc_register" "") (const_int 0)])
7068                       (label_ref (match_operand 0 "" ""))
7069                       (pc)))]
7070   "TARGET_ARM"
7071   "*
7072   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7073     {
7074       arm_ccfsm_state += 2;
7075       return \"\";
7076     }
7077   return \"b%d1\\t%l0\";
7078   "
7079   [(set_attr "conds" "use")
7080    (set_attr "type" "branch")]
7081 )
7082
7083 ; Special pattern to match reversed UNEQ.
7084 (define_insn "*arm_buneq_reversed"
7085   [(set (pc)
7086         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7087                       (pc)
7088                       (label_ref (match_operand 0 "" ""))))]
7089   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7090   "*
7091   if (arm_ccfsm_state != 0)
7092     abort ();
7093
7094   return \"bmi\\t%l0\;bgt\\t%l0\";
7095   "
7096   [(set_attr "conds" "jump_clob")
7097    (set_attr "length" "8")]
7098 )
7099
7100 ; Special pattern to match reversed LTGT.
7101 (define_insn "*arm_bltgt_reversed"
7102   [(set (pc)
7103         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7104                       (pc)
7105                       (label_ref (match_operand 0 "" ""))))]
7106   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7107   "*
7108   if (arm_ccfsm_state != 0)
7109     abort ();
7110
7111   return \"bvs\\t%l0\;beq\\t%l0\";
7112   "
7113   [(set_attr "conds" "jump_clob")
7114    (set_attr "length" "8")]
7115 )
7116
7117 (define_insn "*arm_cond_branch_reversed"
7118   [(set (pc)
7119         (if_then_else (match_operator 1 "arm_comparison_operator"
7120                        [(match_operand 2 "cc_register" "") (const_int 0)])
7121                       (pc)
7122                       (label_ref (match_operand 0 "" ""))))]
7123   "TARGET_ARM"
7124   "*
7125   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7126     {
7127       arm_ccfsm_state += 2;
7128       return \"\";
7129     }
7130   return \"b%D1\\t%l0\";
7131   "
7132   [(set_attr "conds" "use")
7133    (set_attr "type" "branch")]
7134 )
7135
7136 \f
7137
7138 ; scc insns
7139
7140 (define_expand "seq"
7141   [(set (match_operand:SI 0 "s_register_operand" "")
7142         (eq:SI (match_dup 1) (const_int 0)))]
7143   "TARGET_ARM"
7144   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7145 )
7146
7147 (define_expand "sne"
7148   [(set (match_operand:SI 0 "s_register_operand" "")
7149         (ne:SI (match_dup 1) (const_int 0)))]
7150   "TARGET_ARM"
7151   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7152 )
7153
7154 (define_expand "sgt"
7155   [(set (match_operand:SI 0 "s_register_operand" "")
7156         (gt:SI (match_dup 1) (const_int 0)))]
7157   "TARGET_ARM"
7158   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7159 )
7160
7161 (define_expand "sle"
7162   [(set (match_operand:SI 0 "s_register_operand" "")
7163         (le:SI (match_dup 1) (const_int 0)))]
7164   "TARGET_ARM"
7165   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7166 )
7167
7168 (define_expand "sge"
7169   [(set (match_operand:SI 0 "s_register_operand" "")
7170         (ge:SI (match_dup 1) (const_int 0)))]
7171   "TARGET_ARM"
7172   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7173 )
7174
7175 (define_expand "slt"
7176   [(set (match_operand:SI 0 "s_register_operand" "")
7177         (lt:SI (match_dup 1) (const_int 0)))]
7178   "TARGET_ARM"
7179   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7180 )
7181
7182 (define_expand "sgtu"
7183   [(set (match_operand:SI 0 "s_register_operand" "")
7184         (gtu:SI (match_dup 1) (const_int 0)))]
7185   "TARGET_ARM"
7186   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7187 )
7188
7189 (define_expand "sleu"
7190   [(set (match_operand:SI 0 "s_register_operand" "")
7191         (leu:SI (match_dup 1) (const_int 0)))]
7192   "TARGET_ARM"
7193   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7194 )
7195
7196 (define_expand "sgeu"
7197   [(set (match_operand:SI 0 "s_register_operand" "")
7198         (geu:SI (match_dup 1) (const_int 0)))]
7199   "TARGET_ARM"
7200   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7201 )
7202
7203 (define_expand "sltu"
7204   [(set (match_operand:SI 0 "s_register_operand" "")
7205         (ltu:SI (match_dup 1) (const_int 0)))]
7206   "TARGET_ARM"
7207   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7208 )
7209
7210 (define_expand "sunordered"
7211   [(set (match_operand:SI 0 "s_register_operand" "")
7212         (unordered:SI (match_dup 1) (const_int 0)))]
7213   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7214   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7215                                       arm_compare_op1);"
7216 )
7217
7218 (define_expand "sordered"
7219   [(set (match_operand:SI 0 "s_register_operand" "")
7220         (ordered:SI (match_dup 1) (const_int 0)))]
7221   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7222   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7223                                       arm_compare_op1);"
7224 )
7225
7226 (define_expand "sungt"
7227   [(set (match_operand:SI 0 "s_register_operand" "")
7228         (ungt:SI (match_dup 1) (const_int 0)))]
7229   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7230   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7231                                       arm_compare_op1);"
7232 )
7233
7234 (define_expand "sunge"
7235   [(set (match_operand:SI 0 "s_register_operand" "")
7236         (unge:SI (match_dup 1) (const_int 0)))]
7237   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7238   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7239                                       arm_compare_op1);"
7240 )
7241
7242 (define_expand "sunlt"
7243   [(set (match_operand:SI 0 "s_register_operand" "")
7244         (unlt:SI (match_dup 1) (const_int 0)))]
7245   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7246   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7247                                       arm_compare_op1);"
7248 )
7249
7250 (define_expand "sunle"
7251   [(set (match_operand:SI 0 "s_register_operand" "")
7252         (unle:SI (match_dup 1) (const_int 0)))]
7253   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7254   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7255                                       arm_compare_op1);"
7256 )
7257
7258 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7259 ;;; simple ARM instructions. 
7260 ;
7261 ; (define_expand "suneq"
7262 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7263 ;       (uneq:SI (match_dup 1) (const_int 0)))]
7264 ;   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7265 ;   "abort ();"
7266 ; )
7267 ;
7268 ; (define_expand "sltgt"
7269 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7270 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
7271 ;   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7272 ;   "abort ();"
7273 ; )
7274
7275 (define_insn "*mov_scc"
7276   [(set (match_operand:SI 0 "s_register_operand" "=r")
7277         (match_operator:SI 1 "arm_comparison_operator"
7278          [(match_operand 2 "cc_register" "") (const_int 0)]))]
7279   "TARGET_ARM"
7280   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7281   [(set_attr "conds" "use")
7282    (set_attr "length" "8")]
7283 )
7284
7285 (define_insn "*mov_negscc"
7286   [(set (match_operand:SI 0 "s_register_operand" "=r")
7287         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7288                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7289   "TARGET_ARM"
7290   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7291   [(set_attr "conds" "use")
7292    (set_attr "length" "8")]
7293 )
7294
7295 (define_insn "*mov_notscc"
7296   [(set (match_operand:SI 0 "s_register_operand" "=r")
7297         (not:SI (match_operator:SI 1 "arm_comparison_operator"
7298                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7299   "TARGET_ARM"
7300   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7301   [(set_attr "conds" "use")
7302    (set_attr "length" "8")]
7303 )
7304
7305 \f
7306 ;; Conditional move insns
7307
7308 (define_expand "movsicc"
7309   [(set (match_operand:SI 0 "s_register_operand" "")
7310         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7311                          (match_operand:SI 2 "arm_not_operand" "")
7312                          (match_operand:SI 3 "arm_not_operand" "")))]
7313   "TARGET_ARM"
7314   "
7315   {
7316     enum rtx_code code = GET_CODE (operands[1]);
7317     rtx ccreg;
7318
7319     if (code == UNEQ || code == LTGT)
7320       FAIL;
7321
7322     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7323     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7324   }"
7325 )
7326
7327 (define_expand "movsfcc"
7328   [(set (match_operand:SF 0 "s_register_operand" "")
7329         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7330                          (match_operand:SF 2 "s_register_operand" "")
7331                          (match_operand:SF 3 "nonmemory_operand" "")))]
7332   "TARGET_ARM"
7333   "
7334   {
7335     enum rtx_code code = GET_CODE (operands[1]);
7336     rtx ccreg;
7337
7338     if (code == UNEQ || code == LTGT)
7339       FAIL;
7340
7341     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
7342        Otherwise, ensure it is a valid FP add operand */
7343     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7344         || (!arm_float_add_operand (operands[3], SFmode)))
7345       operands[3] = force_reg (SFmode, operands[3]);
7346
7347     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7348     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7349   }"
7350 )
7351
7352 (define_expand "movdfcc"
7353   [(set (match_operand:DF 0 "s_register_operand" "")
7354         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7355                          (match_operand:DF 2 "s_register_operand" "")
7356                          (match_operand:DF 3 "arm_float_add_operand" "")))]
7357   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7358   "
7359   {
7360     enum rtx_code code = GET_CODE (operands[1]);
7361     rtx ccreg;
7362
7363     if (code == UNEQ || code == LTGT)
7364       FAIL;
7365
7366     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7367     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7368   }"
7369 )
7370
7371 (define_insn "*movsicc_insn"
7372   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7373         (if_then_else:SI
7374          (match_operator 3 "arm_comparison_operator"
7375           [(match_operand 4 "cc_register" "") (const_int 0)])
7376          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7377          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7378   "TARGET_ARM"
7379   "@
7380    mov%D3\\t%0, %2
7381    mvn%D3\\t%0, #%B2
7382    mov%d3\\t%0, %1
7383    mvn%d3\\t%0, #%B1
7384    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7385    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7386    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7387    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7388   [(set_attr "length" "4,4,4,4,8,8,8,8")
7389    (set_attr "conds" "use")]
7390 )
7391
7392 (define_insn "*movsfcc_soft_insn"
7393   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7394         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7395                           [(match_operand 4 "cc_register" "") (const_int 0)])
7396                          (match_operand:SF 1 "s_register_operand" "0,r")
7397                          (match_operand:SF 2 "s_register_operand" "r,0")))]
7398   "TARGET_ARM && TARGET_SOFT_FLOAT"
7399   "@
7400    mov%D3\\t%0, %2
7401    mov%d3\\t%0, %1"
7402   [(set_attr "conds" "use")]
7403 )
7404
7405 \f
7406 ;; Jump and linkage insns
7407
7408 (define_expand "jump"
7409   [(set (pc)
7410         (label_ref (match_operand 0 "" "")))]
7411   "TARGET_EITHER"
7412   ""
7413 )
7414
7415 (define_insn "*arm_jump"
7416   [(set (pc)
7417         (label_ref (match_operand 0 "" "")))]
7418   "TARGET_ARM"
7419   "*
7420   {
7421     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7422       {
7423         arm_ccfsm_state += 2;
7424         return \"\";
7425       }
7426     return \"b%?\\t%l0\";
7427   }
7428   "
7429   [(set_attr "predicable" "yes")]
7430 )
7431
7432 (define_insn "*thumb_jump"
7433   [(set (pc)
7434         (label_ref (match_operand 0 "" "")))]
7435   "TARGET_THUMB"
7436   "*
7437   if (get_attr_length (insn) == 2)
7438     return \"b\\t%l0\";
7439   return \"bl\\t%l0\\t%@ far jump\";
7440   "
7441   [(set (attr "far_jump")
7442         (if_then_else
7443             (eq_attr "length" "4")
7444             (const_string "yes")
7445             (const_string "no")))
7446    (set (attr "length") 
7447         (if_then_else
7448             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7449                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
7450             (const_int 2)
7451             (const_int 4)))]
7452 )
7453
7454 (define_expand "call"
7455   [(parallel [(call (match_operand 0 "memory_operand" "")
7456                     (match_operand 1 "general_operand" ""))
7457               (use (match_operand 2 "" ""))
7458               (clobber (reg:SI LR_REGNUM))])]
7459   "TARGET_EITHER"
7460   "
7461   {
7462     rtx callee;
7463     
7464     /* In an untyped call, we can get NULL for operand 2.  */
7465     if (operands[2] == NULL_RTX)
7466       operands[2] = const0_rtx;
7467       
7468     /* This is to decide if we should generate indirect calls by loading the
7469        32 bit address of the callee into a register before performing the
7470        branch and link.  operand[2] encodes the long_call/short_call
7471        attribute of the function being called.  This attribute is set whenever
7472        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7473        is used, and the short_call attribute can also be set if function is
7474        declared as static or if it has already been defined in the current
7475        compilation unit.  See arm.c and arm.h for info about this.  The third
7476        parameter to arm_is_longcall_p is used to tell it which pattern
7477        invoked it.  */
7478     callee  = XEXP (operands[0], 0);
7479     
7480     if (GET_CODE (callee) != REG
7481        && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7482       XEXP (operands[0], 0) = force_reg (Pmode, callee);
7483   }"
7484 )
7485
7486 (define_insn "*call_reg_armv5"
7487   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7488          (match_operand 1 "" ""))
7489    (use (match_operand 2 "" ""))
7490    (clobber (reg:SI LR_REGNUM))]
7491   "TARGET_ARM && arm_arch5"
7492   "blx%?\\t%0"
7493   [(set_attr "type" "call")]
7494 )
7495
7496 (define_insn "*call_reg_arm"
7497   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7498          (match_operand 1 "" ""))
7499    (use (match_operand 2 "" ""))
7500    (clobber (reg:SI LR_REGNUM))]
7501   "TARGET_ARM && !arm_arch5"
7502   "*
7503   return output_call (operands);
7504   "
7505   ;; length is worst case, normally it is only two
7506   [(set_attr "length" "12")
7507    (set_attr "type" "call")]
7508 )
7509
7510 (define_insn "*call_mem"
7511   [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7512          (match_operand 1 "" ""))
7513    (use (match_operand 2 "" ""))
7514    (clobber (reg:SI LR_REGNUM))]
7515   "TARGET_ARM"
7516   "*
7517   return output_call_mem (operands);
7518   "
7519   [(set_attr "length" "12")
7520    (set_attr "type" "call")]
7521 )
7522
7523 (define_insn "*call_reg_thumb_v5"
7524   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7525          (match_operand 1 "" ""))
7526    (use (match_operand 2 "" ""))
7527    (clobber (reg:SI LR_REGNUM))]
7528   "TARGET_THUMB && arm_arch5"
7529   "blx\\t%0"
7530   [(set_attr "length" "2")
7531    (set_attr "type" "call")]
7532 )
7533
7534 (define_insn "*call_reg_thumb"
7535   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7536          (match_operand 1 "" ""))
7537    (use (match_operand 2 "" ""))
7538    (clobber (reg:SI LR_REGNUM))]
7539   "TARGET_THUMB && !arm_arch5"
7540   "*
7541   {
7542     if (!TARGET_CALLER_INTERWORKING)
7543       return thumb_call_via_reg (operands[0]);
7544     else if (operands[1] == const0_rtx)
7545       return \"bl\\t%__interwork_call_via_%0\";
7546     else if (frame_pointer_needed)
7547       return \"bl\\t%__interwork_r7_call_via_%0\";
7548     else
7549       return \"bl\\t%__interwork_r11_call_via_%0\";
7550   }"
7551   [(set_attr "type" "call")]
7552 )
7553
7554 (define_expand "call_value"
7555   [(parallel [(set (match_operand       0 "" "")
7556                    (call (match_operand 1 "memory_operand" "")
7557                          (match_operand 2 "general_operand" "")))
7558               (use (match_operand 3 "" ""))
7559               (clobber (reg:SI LR_REGNUM))])]
7560   "TARGET_EITHER"
7561   "
7562   {
7563     rtx callee = XEXP (operands[1], 0);
7564     
7565     /* In an untyped call, we can get NULL for operand 2.  */
7566     if (operands[3] == 0)
7567       operands[3] = const0_rtx;
7568       
7569     /* See the comment in define_expand \"call\".  */
7570     if (GET_CODE (callee) != REG
7571         && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7572       XEXP (operands[1], 0) = force_reg (Pmode, callee);
7573   }"
7574 )
7575
7576 (define_insn "*call_value_reg_armv5"
7577   [(set (match_operand 0 "" "")
7578         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7579               (match_operand 2 "" "")))
7580    (use (match_operand 3 "" ""))
7581    (clobber (reg:SI LR_REGNUM))]
7582   "TARGET_ARM && arm_arch5"
7583   "blx%?\\t%1"
7584   [(set_attr "type" "call")]
7585 )
7586
7587 (define_insn "*call_value_reg_arm"
7588   [(set (match_operand 0 "" "")
7589         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7590               (match_operand 2 "" "")))
7591    (use (match_operand 3 "" ""))
7592    (clobber (reg:SI LR_REGNUM))]
7593   "TARGET_ARM && !arm_arch5"
7594   "*
7595   return output_call (&operands[1]);
7596   "
7597   [(set_attr "length" "12")
7598    (set_attr "type" "call")]
7599 )
7600
7601 (define_insn "*call_value_mem"
7602   [(set (match_operand 0 "" "")
7603         (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7604               (match_operand 2 "" "")))
7605    (use (match_operand 3 "" ""))
7606    (clobber (reg:SI LR_REGNUM))]
7607   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7608   "*
7609   return output_call_mem (&operands[1]);
7610   "
7611   [(set_attr "length" "12")
7612    (set_attr "type" "call")]
7613 )
7614
7615 (define_insn "*call_value_reg_thumb_v5"
7616   [(set (match_operand 0 "" "")
7617         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7618               (match_operand 2 "" "")))
7619    (use (match_operand 3 "" ""))
7620    (clobber (reg:SI LR_REGNUM))]
7621   "TARGET_THUMB && arm_arch5"
7622   "blx\\t%1"
7623   [(set_attr "length" "2")
7624    (set_attr "type" "call")]
7625 )
7626
7627 (define_insn "*call_value_reg_thumb"
7628   [(set (match_operand 0 "" "")
7629         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7630               (match_operand 2 "" "")))
7631    (use (match_operand 3 "" ""))
7632    (clobber (reg:SI LR_REGNUM))]
7633   "TARGET_THUMB && !arm_arch5"
7634   "*
7635   {
7636     if (!TARGET_CALLER_INTERWORKING)
7637       return thumb_call_via_reg (operands[1]);
7638     else if (operands[2] == const0_rtx)
7639       return \"bl\\t%__interwork_call_via_%1\";
7640     else if (frame_pointer_needed)
7641       return \"bl\\t%__interwork_r7_call_via_%1\";
7642     else
7643       return \"bl\\t%__interwork_r11_call_via_%1\";
7644   }"
7645   [(set_attr "type" "call")]
7646 )
7647
7648 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7649 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7650
7651 (define_insn "*call_symbol"
7652   [(call (mem:SI (match_operand:SI 0 "" ""))
7653          (match_operand 1 "" ""))
7654    (use (match_operand 2 "" ""))
7655    (clobber (reg:SI LR_REGNUM))]
7656   "TARGET_ARM
7657    && (GET_CODE (operands[0]) == SYMBOL_REF)
7658    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7659   "*
7660   {
7661     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7662   }"
7663   [(set_attr "type" "call")]
7664 )
7665
7666 (define_insn "*call_value_symbol"
7667   [(set (match_operand 0 "" "")
7668         (call (mem:SI (match_operand:SI 1 "" ""))
7669         (match_operand:SI 2 "" "")))
7670    (use (match_operand 3 "" ""))
7671    (clobber (reg:SI LR_REGNUM))]
7672   "TARGET_ARM
7673    && (GET_CODE (operands[1]) == SYMBOL_REF)
7674    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7675   "*
7676   {
7677     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7678   }"
7679   [(set_attr "type" "call")]
7680 )
7681
7682 (define_insn "*call_insn"
7683   [(call (mem:SI (match_operand:SI 0 "" ""))
7684          (match_operand:SI 1 "" ""))
7685    (use (match_operand 2 "" ""))
7686    (clobber (reg:SI LR_REGNUM))]
7687   "TARGET_THUMB
7688    && GET_CODE (operands[0]) == SYMBOL_REF
7689    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7690   "bl\\t%a0"
7691   [(set_attr "length" "4")
7692    (set_attr "type" "call")]
7693 )
7694
7695 (define_insn "*call_value_insn"
7696   [(set (match_operand 0 "" "")
7697         (call (mem:SI (match_operand 1 "" ""))
7698               (match_operand 2 "" "")))
7699    (use (match_operand 3 "" ""))
7700    (clobber (reg:SI LR_REGNUM))]
7701   "TARGET_THUMB
7702    && GET_CODE (operands[1]) == SYMBOL_REF
7703    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7704   "bl\\t%a1"
7705   [(set_attr "length" "4")
7706    (set_attr "type" "call")]
7707 )
7708
7709 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7710 (define_expand "sibcall"
7711   [(parallel [(call (match_operand 0 "memory_operand" "")
7712                     (match_operand 1 "general_operand" ""))
7713               (return)
7714               (use (match_operand 2 "" ""))])]
7715   "TARGET_ARM"
7716   "
7717   {
7718     if (operands[2] == NULL_RTX)
7719       operands[2] = const0_rtx;
7720   }"
7721 )
7722
7723 (define_expand "sibcall_value"
7724   [(parallel [(set (match_operand 0 "" "")
7725                    (call (match_operand 1 "memory_operand" "")
7726                          (match_operand 2 "general_operand" "")))
7727               (return)
7728               (use (match_operand 3 "" ""))])]
7729   "TARGET_ARM"
7730   "
7731   {
7732     if (operands[3] == NULL_RTX)
7733       operands[3] = const0_rtx;
7734   }"
7735 )
7736
7737 (define_insn "*sibcall_insn"
7738  [(call (mem:SI (match_operand:SI 0 "" "X"))
7739         (match_operand 1 "" ""))
7740   (return)
7741   (use (match_operand 2 "" ""))]
7742   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7743   "*
7744   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7745   "
7746   [(set_attr "type" "call")]
7747 )
7748
7749 (define_insn "*sibcall_value_insn"
7750  [(set (match_operand 0 "" "")
7751        (call (mem:SI (match_operand:SI 1 "" "X"))
7752              (match_operand 2 "" "")))
7753   (return)
7754   (use (match_operand 3 "" ""))]
7755   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7756   "*
7757   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7758   "
7759   [(set_attr "type" "call")]
7760 )
7761
7762 ;; Often the return insn will be the same as loading from memory, so set attr
7763 (define_insn "return"
7764   [(return)]
7765   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7766   "*
7767   {
7768     if (arm_ccfsm_state == 2)
7769       {
7770         arm_ccfsm_state += 2;
7771         return \"\";
7772       }
7773     return output_return_instruction (const_true_rtx, TRUE, FALSE);
7774   }"
7775   [(set_attr "type" "load1")
7776    (set_attr "length" "12")
7777    (set_attr "predicable" "yes")]
7778 )
7779
7780 (define_insn "*cond_return"
7781   [(set (pc)
7782         (if_then_else (match_operator 0 "arm_comparison_operator"
7783                        [(match_operand 1 "cc_register" "") (const_int 0)])
7784                       (return)
7785                       (pc)))]
7786   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7787   "*
7788   {
7789     if (arm_ccfsm_state == 2)
7790       {
7791         arm_ccfsm_state += 2;
7792         return \"\";
7793       }
7794     return output_return_instruction (operands[0], TRUE, FALSE);
7795   }"
7796   [(set_attr "conds" "use")
7797    (set_attr "length" "12")
7798    (set_attr "type" "load1")]
7799 )
7800
7801 (define_insn "*cond_return_inverted"
7802   [(set (pc)
7803         (if_then_else (match_operator 0 "arm_comparison_operator"
7804                        [(match_operand 1 "cc_register" "") (const_int 0)])
7805                       (pc)
7806                       (return)))]
7807   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7808   "*
7809   {
7810     if (arm_ccfsm_state == 2)
7811       {
7812         arm_ccfsm_state += 2;
7813         return \"\";
7814       }
7815     return output_return_instruction (operands[0], TRUE, TRUE);
7816   }"
7817   [(set_attr "conds" "use")
7818    (set_attr "length" "12")
7819    (set_attr "type" "load1")]
7820 )
7821
7822 ;; Generate a sequence of instructions to determine if the processor is
7823 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7824 ;; mask.
7825
7826 (define_expand "return_addr_mask"
7827   [(set (match_dup 1)
7828       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7829                        (const_int 0)))
7830    (set (match_operand:SI 0 "s_register_operand" "")
7831       (if_then_else:SI (eq (match_dup 1) (const_int 0))
7832                        (const_int -1)
7833                        (const_int 67108860)))] ; 0x03fffffc
7834   "TARGET_ARM"
7835   "
7836   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7837   ")
7838
7839 (define_insn "*check_arch2"
7840   [(set (match_operand:CC_NOOV 0 "cc_register" "")
7841       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7842                        (const_int 0)))]
7843   "TARGET_ARM"
7844   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7845   [(set_attr "length" "8")
7846    (set_attr "conds" "set")]
7847 )
7848
7849 ;; Call subroutine returning any type.
7850
7851 (define_expand "untyped_call"
7852   [(parallel [(call (match_operand 0 "" "")
7853                     (const_int 0))
7854               (match_operand 1 "" "")
7855               (match_operand 2 "" "")])]
7856   "TARGET_EITHER"
7857   "
7858   {
7859     int i;
7860     rtx par = gen_rtx_PARALLEL (VOIDmode,
7861                                 rtvec_alloc (XVECLEN (operands[2], 0)));
7862     rtx addr = gen_reg_rtx (Pmode);
7863     rtx mem;
7864     int size = 0;
7865
7866     emit_move_insn (addr, XEXP (operands[1], 0));
7867     mem = change_address (operands[1], BLKmode, addr);
7868
7869     for (i = 0; i < XVECLEN (operands[2], 0); i++)
7870       {
7871         rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
7872
7873         /* Default code only uses r0 as a return value, but we could
7874            be using anything up to 4 registers.  */
7875         if (REGNO (src) == R0_REGNUM)
7876           src = gen_rtx_REG (TImode, R0_REGNUM);
7877
7878         XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
7879                                                  GEN_INT (size));
7880         size += GET_MODE_SIZE (GET_MODE (src));
7881       }
7882
7883     emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
7884                                     const0_rtx));
7885
7886     size = 0;
7887
7888     for (i = 0; i < XVECLEN (par, 0); i++)
7889       {
7890         HOST_WIDE_INT offset = 0;
7891         rtx reg = XEXP (XVECEXP (par, 0, i), 0);
7892
7893         if (size != 0)
7894           emit_move_insn (addr, plus_constant (addr, size));
7895
7896         mem = change_address (mem, GET_MODE (reg), NULL);
7897         if (REGNO (reg) == R0_REGNUM)
7898           {
7899             /* On thumb we have to use a write-back instruction.  */
7900             emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
7901                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7902             size = TARGET_ARM ? 16 : 0;
7903           }
7904         else
7905           {
7906             emit_move_insn (mem, reg);
7907             size = GET_MODE_SIZE (GET_MODE (reg));
7908           }
7909       }
7910
7911     /* The optimizer does not know that the call sets the function value
7912        registers we stored in the result block.  We avoid problems by
7913        claiming that all hard registers are used and clobbered at this
7914        point.  */
7915     emit_insn (gen_blockage ());
7916
7917     DONE;
7918   }"
7919 )
7920
7921 (define_expand "untyped_return"
7922   [(match_operand:BLK 0 "memory_operand" "")
7923    (match_operand 1 "" "")]
7924   "TARGET_EITHER"
7925   "
7926   {
7927     int i;
7928     rtx addr = gen_reg_rtx (Pmode);
7929     rtx mem;
7930     int size = 0;
7931
7932     emit_move_insn (addr, XEXP (operands[0], 0));
7933     mem = change_address (operands[0], BLKmode, addr);
7934
7935     for (i = 0; i < XVECLEN (operands[1], 0); i++)
7936       {
7937         HOST_WIDE_INT offset = 0;
7938         rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
7939
7940         if (size != 0)
7941           emit_move_insn (addr, plus_constant (addr, size));
7942
7943         mem = change_address (mem, GET_MODE (reg), NULL);
7944         if (REGNO (reg) == R0_REGNUM)
7945           {
7946             /* On thumb we have to use a write-back instruction.  */
7947             emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
7948                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7949             size = TARGET_ARM ? 16 : 0;
7950           }
7951         else
7952           {
7953             emit_move_insn (reg, mem);
7954             size = GET_MODE_SIZE (GET_MODE (reg));
7955           }
7956       }
7957
7958     /* Emit USE insns before the return.  */
7959     for (i = 0; i < XVECLEN (operands[1], 0); i++)
7960       emit_insn (gen_rtx_USE (VOIDmode,
7961                               SET_DEST (XVECEXP (operands[1], 0, i))));
7962
7963     /* Construct the return.  */
7964     expand_naked_return ();
7965
7966     DONE;
7967   }"
7968 )
7969
7970 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7971 ;; all of memory.  This blocks insns from being moved across this point.
7972
7973 (define_insn "blockage"
7974   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
7975   "TARGET_EITHER"
7976   ""
7977   [(set_attr "length" "0")
7978    (set_attr "type" "block")]
7979 )
7980
7981 (define_expand "casesi"
7982   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
7983    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
7984    (match_operand:SI 2 "const_int_operand" "")  ; total range
7985    (match_operand:SI 3 "" "")                   ; table label
7986    (match_operand:SI 4 "" "")]                  ; Out of range label
7987   "TARGET_ARM"
7988   "
7989   {
7990     rtx reg;
7991     if (operands[1] != const0_rtx)
7992       {
7993         reg = gen_reg_rtx (SImode);
7994
7995         emit_insn (gen_addsi3 (reg, operands[0],
7996                                GEN_INT (-INTVAL (operands[1]))));
7997         operands[0] = reg;
7998       }
7999
8000     if (!const_ok_for_arm (INTVAL (operands[2])))
8001       operands[2] = force_reg (SImode, operands[2]);
8002
8003     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
8004                                          operands[4]));
8005     DONE;
8006   }"
8007 )
8008
8009 ;; The USE in this pattern is needed to tell flow analysis that this is
8010 ;; a CASESI insn.  It has no other purpose.
8011 (define_insn "casesi_internal"
8012   [(parallel [(set (pc)
8013                (if_then_else
8014                 (leu (match_operand:SI 0 "s_register_operand" "r")
8015                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
8016                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8017                                  (label_ref (match_operand 2 "" ""))))
8018                 (label_ref (match_operand 3 "" ""))))
8019               (clobber (reg:CC CC_REGNUM))
8020               (use (label_ref (match_dup 2)))])]
8021   "TARGET_ARM"
8022   "*
8023     if (flag_pic)
8024       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8025     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8026   "
8027   [(set_attr "conds" "clob")
8028    (set_attr "length" "12")]
8029 )
8030
8031 (define_expand "indirect_jump"
8032   [(set (pc)
8033         (match_operand:SI 0 "s_register_operand" ""))]
8034   "TARGET_EITHER"
8035   ""
8036 )
8037
8038 ;; NB Never uses BX.
8039 (define_insn "*arm_indirect_jump"
8040   [(set (pc)
8041         (match_operand:SI 0 "s_register_operand" "r"))]
8042   "TARGET_ARM"
8043   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
8044   [(set_attr "predicable" "yes")]
8045 )
8046
8047 (define_insn "*load_indirect_jump"
8048   [(set (pc)
8049         (match_operand:SI 0 "memory_operand" "m"))]
8050   "TARGET_ARM"
8051   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
8052   [(set_attr "type" "load1")
8053    (set_attr "pool_range" "4096")
8054    (set_attr "neg_pool_range" "4084")
8055    (set_attr "predicable" "yes")]
8056 )
8057
8058 ;; NB Never uses BX.
8059 (define_insn "*thumb_indirect_jump"
8060   [(set (pc)
8061         (match_operand:SI 0 "register_operand" "l*r"))]
8062   "TARGET_THUMB"
8063   "mov\\tpc, %0"
8064   [(set_attr "conds" "clob")
8065    (set_attr "length" "2")]
8066 )
8067
8068 \f
8069 ;; Misc insns
8070
8071 (define_insn "nop"
8072   [(const_int 0)]
8073   "TARGET_EITHER"
8074   "*
8075   if (TARGET_ARM)
8076     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8077   return  \"mov\\tr8, r8\";
8078   "
8079   [(set (attr "length")
8080         (if_then_else (eq_attr "is_thumb" "yes")
8081                       (const_int 2)
8082                       (const_int 4)))]
8083 )
8084
8085 \f
8086 ;; Patterns to allow combination of arithmetic, cond code and shifts
8087
8088 (define_insn "*arith_shiftsi"
8089   [(set (match_operand:SI 0 "s_register_operand" "=r")
8090         (match_operator:SI 1 "shiftable_operator"
8091           [(match_operator:SI 3 "shift_operator"
8092              [(match_operand:SI 4 "s_register_operand" "r")
8093               (match_operand:SI 5 "reg_or_int_operand" "rI")])
8094            (match_operand:SI 2 "s_register_operand" "r")]))]
8095   "TARGET_ARM"
8096   "%i1%?\\t%0, %2, %4%S3"
8097   [(set_attr "predicable" "yes")
8098    (set_attr "shift" "4")
8099    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8100                       (const_string "alu_shift")
8101                       (const_string "alu_shift_reg")))]
8102 )
8103
8104 (define_split
8105   [(set (match_operand:SI 0 "s_register_operand" "")
8106         (match_operator:SI 1 "shiftable_operator"
8107          [(match_operator:SI 2 "shiftable_operator"
8108            [(match_operator:SI 3 "shift_operator"
8109              [(match_operand:SI 4 "s_register_operand" "")
8110               (match_operand:SI 5 "reg_or_int_operand" "")])
8111             (match_operand:SI 6 "s_register_operand" "")])
8112           (match_operand:SI 7 "arm_rhs_operand" "")]))
8113    (clobber (match_operand:SI 8 "s_register_operand" ""))]
8114   "TARGET_ARM"
8115   [(set (match_dup 8)
8116         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8117                          (match_dup 6)]))
8118    (set (match_dup 0)
8119         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8120   "")
8121
8122 (define_insn "*arith_shiftsi_compare0"
8123   [(set (reg:CC_NOOV CC_REGNUM)
8124         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8125                           [(match_operator:SI 3 "shift_operator"
8126                             [(match_operand:SI 4 "s_register_operand" "r")
8127                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8128                            (match_operand:SI 2 "s_register_operand" "r")])
8129                          (const_int 0)))
8130    (set (match_operand:SI 0 "s_register_operand" "=r")
8131         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8132                          (match_dup 2)]))]
8133   "TARGET_ARM"
8134   "%i1%?s\\t%0, %2, %4%S3"
8135   [(set_attr "conds" "set")
8136    (set_attr "shift" "4")
8137    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8138                       (const_string "alu_shift")
8139                       (const_string "alu_shift_reg")))]
8140 )
8141
8142 (define_insn "*arith_shiftsi_compare0_scratch"
8143   [(set (reg:CC_NOOV CC_REGNUM)
8144         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8145                           [(match_operator:SI 3 "shift_operator"
8146                             [(match_operand:SI 4 "s_register_operand" "r")
8147                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8148                            (match_operand:SI 2 "s_register_operand" "r")])
8149                          (const_int 0)))
8150    (clobber (match_scratch:SI 0 "=r"))]
8151   "TARGET_ARM"
8152   "%i1%?s\\t%0, %2, %4%S3"
8153   [(set_attr "conds" "set")
8154    (set_attr "shift" "4")
8155    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8156                       (const_string "alu_shift")
8157                       (const_string "alu_shift_reg")))]
8158 )
8159
8160 (define_insn "*sub_shiftsi"
8161   [(set (match_operand:SI 0 "s_register_operand" "=r")
8162         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8163                   (match_operator:SI 2 "shift_operator"
8164                    [(match_operand:SI 3 "s_register_operand" "r")
8165                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
8166   "TARGET_ARM"
8167   "sub%?\\t%0, %1, %3%S2"
8168   [(set_attr "predicable" "yes")
8169    (set_attr "shift" "3")
8170    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8171                       (const_string "alu_shift")
8172                       (const_string "alu_shift_reg")))]
8173 )
8174
8175 (define_insn "*sub_shiftsi_compare0"
8176   [(set (reg:CC_NOOV CC_REGNUM)
8177         (compare:CC_NOOV
8178          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8179                    (match_operator:SI 2 "shift_operator"
8180                     [(match_operand:SI 3 "s_register_operand" "r")
8181                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8182          (const_int 0)))
8183    (set (match_operand:SI 0 "s_register_operand" "=r")
8184         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8185                                                  (match_dup 4)])))]
8186   "TARGET_ARM"
8187   "sub%?s\\t%0, %1, %3%S2"
8188   [(set_attr "conds" "set")
8189    (set_attr "shift" "3")
8190    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8191                       (const_string "alu_shift")
8192                       (const_string "alu_shift_reg")))]
8193 )
8194
8195 (define_insn "*sub_shiftsi_compare0_scratch"
8196   [(set (reg:CC_NOOV CC_REGNUM)
8197         (compare:CC_NOOV
8198          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8199                    (match_operator:SI 2 "shift_operator"
8200                     [(match_operand:SI 3 "s_register_operand" "r")
8201                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8202          (const_int 0)))
8203    (clobber (match_scratch:SI 0 "=r"))]
8204   "TARGET_ARM"
8205   "sub%?s\\t%0, %1, %3%S2"
8206   [(set_attr "conds" "set")
8207    (set_attr "shift" "3")
8208    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8209                       (const_string "alu_shift")
8210                       (const_string "alu_shift_reg")))]
8211 )
8212
8213 \f
8214
8215 (define_insn "*and_scc"
8216   [(set (match_operand:SI 0 "s_register_operand" "=r")
8217         (and:SI (match_operator:SI 1 "arm_comparison_operator"
8218                  [(match_operand 3 "cc_register" "") (const_int 0)])
8219                 (match_operand:SI 2 "s_register_operand" "r")))]
8220   "TARGET_ARM"
8221   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8222   [(set_attr "conds" "use")
8223    (set_attr "length" "8")]
8224 )
8225
8226 (define_insn "*ior_scc"
8227   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8228         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8229                  [(match_operand 3 "cc_register" "") (const_int 0)])
8230                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8231   "TARGET_ARM"
8232   "@
8233    orr%d2\\t%0, %1, #1
8234    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8235   [(set_attr "conds" "use")
8236    (set_attr "length" "4,8")]
8237 )
8238
8239 (define_insn "*compare_scc"
8240   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8241         (match_operator:SI 1 "arm_comparison_operator"
8242          [(match_operand:SI 2 "s_register_operand" "r,r")
8243           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8244    (clobber (reg:CC CC_REGNUM))]
8245   "TARGET_ARM"
8246   "*
8247     if (operands[3] == const0_rtx)
8248       {
8249         if (GET_CODE (operands[1]) == LT)
8250           return \"mov\\t%0, %2, lsr #31\";
8251
8252         if (GET_CODE (operands[1]) == GE)
8253           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8254
8255         if (GET_CODE (operands[1]) == EQ)
8256           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8257       }
8258
8259     if (GET_CODE (operands[1]) == NE)
8260       {
8261         if (which_alternative == 1)
8262           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8263         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8264       }
8265     if (which_alternative == 1)
8266       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8267     else
8268       output_asm_insn (\"cmp\\t%2, %3\", operands);
8269     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8270   "
8271   [(set_attr "conds" "clob")
8272    (set_attr "length" "12")]
8273 )
8274
8275 (define_insn "*cond_move"
8276   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8277         (if_then_else:SI (match_operator 3 "equality_operator"
8278                           [(match_operator 4 "arm_comparison_operator"
8279                             [(match_operand 5 "cc_register" "") (const_int 0)])
8280                            (const_int 0)])
8281                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8282                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8283   "TARGET_ARM"
8284   "*
8285     if (GET_CODE (operands[3]) == NE)
8286       {
8287         if (which_alternative != 1)
8288           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8289         if (which_alternative != 0)
8290           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8291         return \"\";
8292       }
8293     if (which_alternative != 0)
8294       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8295     if (which_alternative != 1)
8296       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8297     return \"\";
8298   "
8299   [(set_attr "conds" "use")
8300    (set_attr "length" "4,4,8")]
8301 )
8302
8303 (define_insn "*cond_arith"
8304   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8305         (match_operator:SI 5 "shiftable_operator" 
8306          [(match_operator:SI 4 "arm_comparison_operator"
8307            [(match_operand:SI 2 "s_register_operand" "r,r")
8308             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8309           (match_operand:SI 1 "s_register_operand" "0,?r")]))
8310    (clobber (reg:CC CC_REGNUM))]
8311   "TARGET_ARM"
8312   "*
8313     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8314       return \"%i5\\t%0, %1, %2, lsr #31\";
8315
8316     output_asm_insn (\"cmp\\t%2, %3\", operands);
8317     if (GET_CODE (operands[5]) == AND)
8318       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8319     else if (GET_CODE (operands[5]) == MINUS)
8320       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8321     else if (which_alternative != 0)
8322       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8323     return \"%i5%d4\\t%0, %1, #1\";
8324   "
8325   [(set_attr "conds" "clob")
8326    (set_attr "length" "12")]
8327 )
8328
8329 (define_insn "*cond_sub"
8330   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8331         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8332                   (match_operator:SI 4 "arm_comparison_operator"
8333                    [(match_operand:SI 2 "s_register_operand" "r,r")
8334                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8335    (clobber (reg:CC CC_REGNUM))]
8336   "TARGET_ARM"
8337   "*
8338     output_asm_insn (\"cmp\\t%2, %3\", operands);
8339     if (which_alternative != 0)
8340       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8341     return \"sub%d4\\t%0, %1, #1\";
8342   "
8343   [(set_attr "conds" "clob")
8344    (set_attr "length" "8,12")]
8345 )
8346
8347 (define_insn "*cmp_ite0"
8348   [(set (match_operand 6 "dominant_cc_register" "")
8349         (compare
8350          (if_then_else:SI
8351           (match_operator 4 "arm_comparison_operator"
8352            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8353             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8354           (match_operator:SI 5 "arm_comparison_operator"
8355            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8356             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8357           (const_int 0))
8358          (const_int 0)))]
8359   "TARGET_ARM"
8360   "*
8361   {
8362     static const char * const opcodes[4][2] =
8363     {
8364       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8365        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8366       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8367        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8368       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8369        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8370       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8371        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8372     };
8373     int swap =
8374       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8375
8376     return opcodes[which_alternative][swap];
8377   }"
8378   [(set_attr "conds" "set")
8379    (set_attr "length" "8")]
8380 )
8381
8382 (define_insn "*cmp_ite1"
8383   [(set (match_operand 6 "dominant_cc_register" "")
8384         (compare
8385          (if_then_else:SI
8386           (match_operator 4 "arm_comparison_operator"
8387            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8388             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8389           (match_operator:SI 5 "arm_comparison_operator"
8390            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8391             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8392           (const_int 1))
8393          (const_int 0)))]
8394   "TARGET_ARM"
8395   "*
8396   {
8397     static const char * const opcodes[4][2] =
8398     {
8399       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8400        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8401       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8402        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8403       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8404        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8405       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8406        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8407     };
8408     int swap =
8409       comparison_dominates_p (GET_CODE (operands[5]),
8410                               reverse_condition (GET_CODE (operands[4])));
8411
8412     return opcodes[which_alternative][swap];
8413   }"
8414   [(set_attr "conds" "set")
8415    (set_attr "length" "8")]
8416 )
8417
8418 (define_insn "*cmp_and"
8419   [(set (match_operand 6 "dominant_cc_register" "")
8420         (compare
8421          (and:SI
8422           (match_operator 4 "arm_comparison_operator"
8423            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8424             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8425           (match_operator:SI 5 "arm_comparison_operator"
8426            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8427             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8428          (const_int 0)))]
8429   "TARGET_ARM"
8430   "*
8431   {
8432     static const char *const opcodes[4][2] =
8433     {
8434       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8435        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8436       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8437        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8438       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8439        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8440       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8441        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8442     };
8443     int swap =
8444       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8445
8446     return opcodes[which_alternative][swap];
8447   }"
8448   [(set_attr "conds" "set")
8449    (set_attr "predicable" "no")
8450    (set_attr "length" "8")]
8451 )
8452
8453 (define_insn "*cmp_ior"
8454   [(set (match_operand 6 "dominant_cc_register" "")
8455         (compare
8456          (ior:SI
8457           (match_operator 4 "arm_comparison_operator"
8458            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8459             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8460           (match_operator:SI 5 "arm_comparison_operator"
8461            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8462             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8463          (const_int 0)))]
8464   "TARGET_ARM"
8465   "*
8466 {
8467   static const char *const opcodes[4][2] =
8468   {
8469     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8470      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8471     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8472      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8473     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8474      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8475     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8476      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8477   };
8478   int swap =
8479     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8480
8481   return opcodes[which_alternative][swap];
8482 }
8483 "
8484   [(set_attr "conds" "set")
8485    (set_attr "length" "8")]
8486 )
8487
8488 (define_insn_and_split "*ior_scc_scc"
8489   [(set (match_operand:SI 0 "s_register_operand" "=r")
8490         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8491                  [(match_operand:SI 1 "s_register_operand" "r")
8492                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8493                 (match_operator:SI 6 "arm_comparison_operator"
8494                  [(match_operand:SI 4 "s_register_operand" "r")
8495                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8496    (clobber (reg:CC CC_REGNUM))]
8497   "TARGET_ARM
8498    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8499        != CCmode)"
8500   "#"
8501   "TARGET_ARM && reload_completed"
8502   [(set (match_dup 7)
8503         (compare
8504          (ior:SI
8505           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8506           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8507          (const_int 0)))
8508    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8509   "operands[7]
8510      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8511                                                   DOM_CC_X_OR_Y),
8512                     CC_REGNUM);"
8513   [(set_attr "conds" "clob")
8514    (set_attr "length" "16")])
8515
8516 ; If the above pattern is followed by a CMP insn, then the compare is 
8517 ; redundant, since we can rework the conditional instruction that follows.
8518 (define_insn_and_split "*ior_scc_scc_cmp"
8519   [(set (match_operand 0 "dominant_cc_register" "")
8520         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8521                           [(match_operand:SI 1 "s_register_operand" "r")
8522                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8523                          (match_operator:SI 6 "arm_comparison_operator"
8524                           [(match_operand:SI 4 "s_register_operand" "r")
8525                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8526                  (const_int 0)))
8527    (set (match_operand:SI 7 "s_register_operand" "=r")
8528         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8529                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8530   "TARGET_ARM"
8531   "#"
8532   "TARGET_ARM && reload_completed"
8533   [(set (match_dup 0)
8534         (compare
8535          (ior:SI
8536           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8537           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8538          (const_int 0)))
8539    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8540   ""
8541   [(set_attr "conds" "set")
8542    (set_attr "length" "16")])
8543
8544 (define_insn_and_split "*and_scc_scc"
8545   [(set (match_operand:SI 0 "s_register_operand" "=r")
8546         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8547                  [(match_operand:SI 1 "s_register_operand" "r")
8548                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8549                 (match_operator:SI 6 "arm_comparison_operator"
8550                  [(match_operand:SI 4 "s_register_operand" "r")
8551                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8552    (clobber (reg:CC CC_REGNUM))]
8553   "TARGET_ARM
8554    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8555        != CCmode)"
8556   "#"
8557   "TARGET_ARM && reload_completed
8558    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8559        != CCmode)"
8560   [(set (match_dup 7)
8561         (compare
8562          (and:SI
8563           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8564           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8565          (const_int 0)))
8566    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8567   "operands[7]
8568      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8569                                                   DOM_CC_X_AND_Y),
8570                     CC_REGNUM);"
8571   [(set_attr "conds" "clob")
8572    (set_attr "length" "16")])
8573
8574 ; If the above pattern is followed by a CMP insn, then the compare is 
8575 ; redundant, since we can rework the conditional instruction that follows.
8576 (define_insn_and_split "*and_scc_scc_cmp"
8577   [(set (match_operand 0 "dominant_cc_register" "")
8578         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8579                           [(match_operand:SI 1 "s_register_operand" "r")
8580                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8581                          (match_operator:SI 6 "arm_comparison_operator"
8582                           [(match_operand:SI 4 "s_register_operand" "r")
8583                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8584                  (const_int 0)))
8585    (set (match_operand:SI 7 "s_register_operand" "=r")
8586         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8587                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8588   "TARGET_ARM"
8589   "#"
8590   "TARGET_ARM && reload_completed"
8591   [(set (match_dup 0)
8592         (compare
8593          (and:SI
8594           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8595           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8596          (const_int 0)))
8597    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8598   ""
8599   [(set_attr "conds" "set")
8600    (set_attr "length" "16")])
8601
8602 ;; If there is no dominance in the comparison, then we can still save an
8603 ;; instruction in the AND case, since we can know that the second compare
8604 ;; need only zero the value if false (if true, then the value is already
8605 ;; correct).
8606 (define_insn_and_split "*and_scc_scc_nodom"
8607   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8608         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8609                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
8610                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8611                 (match_operator:SI 6 "arm_comparison_operator"
8612                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
8613                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8614    (clobber (reg:CC CC_REGNUM))]
8615   "TARGET_ARM
8616    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8617        == CCmode)"
8618   "#"
8619   "TARGET_ARM && reload_completed"
8620   [(parallel [(set (match_dup 0)
8621                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8622               (clobber (reg:CC CC_REGNUM))])
8623    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8624    (set (match_dup 0)
8625         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8626                          (match_dup 0)
8627                          (const_int 0)))]
8628   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8629                                               operands[4], operands[5]),
8630                               CC_REGNUM);
8631    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8632                                   operands[5]);"
8633   [(set_attr "conds" "clob")
8634    (set_attr "length" "20")])
8635
8636 (define_split
8637   [(set (reg:CC_NOOV CC_REGNUM)
8638         (compare:CC_NOOV (ior:SI
8639                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8640                                   (const_int 1))
8641                           (match_operator:SI 1 "comparison_operator"
8642                            [(match_operand:SI 2 "s_register_operand" "")
8643                             (match_operand:SI 3 "arm_add_operand" "")]))
8644                          (const_int 0)))
8645    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8646   "TARGET_ARM"
8647   [(set (match_dup 4)
8648         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8649                 (match_dup 0)))
8650    (set (reg:CC_NOOV CC_REGNUM)
8651         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8652                          (const_int 0)))]
8653   "")
8654
8655 (define_split
8656   [(set (reg:CC_NOOV CC_REGNUM)
8657         (compare:CC_NOOV (ior:SI
8658                           (match_operator:SI 1 "comparison_operator"
8659                            [(match_operand:SI 2 "s_register_operand" "")
8660                             (match_operand:SI 3 "arm_add_operand" "")])
8661                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8662                                   (const_int 1)))
8663                          (const_int 0)))
8664    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8665   "TARGET_ARM"
8666   [(set (match_dup 4)
8667         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8668                 (match_dup 0)))
8669    (set (reg:CC_NOOV CC_REGNUM)
8670         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8671                          (const_int 0)))]
8672   "")
8673
8674 (define_insn "*negscc"
8675   [(set (match_operand:SI 0 "s_register_operand" "=r")
8676         (neg:SI (match_operator 3 "arm_comparison_operator"
8677                  [(match_operand:SI 1 "s_register_operand" "r")
8678                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8679    (clobber (reg:CC CC_REGNUM))]
8680   "TARGET_ARM"
8681   "*
8682   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8683     return \"mov\\t%0, %1, asr #31\";
8684
8685   if (GET_CODE (operands[3]) == NE)
8686     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8687
8688   if (GET_CODE (operands[3]) == GT)
8689     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8690
8691   output_asm_insn (\"cmp\\t%1, %2\", operands);
8692   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8693   return \"mvn%d3\\t%0, #0\";
8694   "
8695   [(set_attr "conds" "clob")
8696    (set_attr "length" "12")]
8697 )
8698
8699 (define_insn "movcond"
8700   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8701         (if_then_else:SI
8702          (match_operator 5 "arm_comparison_operator"
8703           [(match_operand:SI 3 "s_register_operand" "r,r,r")
8704            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8705          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8706          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8707    (clobber (reg:CC CC_REGNUM))]
8708   "TARGET_ARM"
8709   "*
8710   if (GET_CODE (operands[5]) == LT
8711       && (operands[4] == const0_rtx))
8712     {
8713       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8714         {
8715           if (operands[2] == const0_rtx)
8716             return \"and\\t%0, %1, %3, asr #31\";
8717           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8718         }
8719       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8720         {
8721           if (operands[1] == const0_rtx)
8722             return \"bic\\t%0, %2, %3, asr #31\";
8723           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8724         }
8725       /* The only case that falls through to here is when both ops 1 & 2
8726          are constants.  */
8727     }
8728
8729   if (GET_CODE (operands[5]) == GE
8730       && (operands[4] == const0_rtx))
8731     {
8732       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8733         {
8734           if (operands[2] == const0_rtx)
8735             return \"bic\\t%0, %1, %3, asr #31\";
8736           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8737         }
8738       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8739         {
8740           if (operands[1] == const0_rtx)
8741             return \"and\\t%0, %2, %3, asr #31\";
8742           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8743         }
8744       /* The only case that falls through to here is when both ops 1 & 2
8745          are constants.  */
8746     }
8747   if (GET_CODE (operands[4]) == CONST_INT
8748       && !const_ok_for_arm (INTVAL (operands[4])))
8749     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8750   else
8751     output_asm_insn (\"cmp\\t%3, %4\", operands);
8752   if (which_alternative != 0)
8753     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8754   if (which_alternative != 1)
8755     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8756   return \"\";
8757   "
8758   [(set_attr "conds" "clob")
8759    (set_attr "length" "8,8,12")]
8760 )
8761
8762 (define_insn "*ifcompare_plus_move"
8763   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8764         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8765                           [(match_operand:SI 4 "s_register_operand" "r,r")
8766                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8767                          (plus:SI
8768                           (match_operand:SI 2 "s_register_operand" "r,r")
8769                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8770                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8771    (clobber (reg:CC CC_REGNUM))]
8772   "TARGET_ARM"
8773   "#"
8774   [(set_attr "conds" "clob")
8775    (set_attr "length" "8,12")]
8776 )
8777
8778 (define_insn "*if_plus_move"
8779   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8780         (if_then_else:SI
8781          (match_operator 4 "arm_comparison_operator"
8782           [(match_operand 5 "cc_register" "") (const_int 0)])
8783          (plus:SI
8784           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8785           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8786          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8787   "TARGET_ARM"
8788   "@
8789    add%d4\\t%0, %2, %3
8790    sub%d4\\t%0, %2, #%n3
8791    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8792    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8793   [(set_attr "conds" "use")
8794    (set_attr "length" "4,4,8,8")
8795    (set_attr "type" "*,*,*,*")]
8796 )
8797
8798 (define_insn "*ifcompare_move_plus"
8799   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8800         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8801                           [(match_operand:SI 4 "s_register_operand" "r,r")
8802                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8803                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8804                          (plus:SI
8805                           (match_operand:SI 2 "s_register_operand" "r,r")
8806                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8807    (clobber (reg:CC CC_REGNUM))]
8808   "TARGET_ARM"
8809   "#"
8810   [(set_attr "conds" "clob")
8811    (set_attr "length" "8,12")]
8812 )
8813
8814 (define_insn "*if_move_plus"
8815   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8816         (if_then_else:SI
8817          (match_operator 4 "arm_comparison_operator"
8818           [(match_operand 5 "cc_register" "") (const_int 0)])
8819          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8820          (plus:SI
8821           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8822           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8823   "TARGET_ARM"
8824   "@
8825    add%D4\\t%0, %2, %3
8826    sub%D4\\t%0, %2, #%n3
8827    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8828    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8829   [(set_attr "conds" "use")
8830    (set_attr "length" "4,4,8,8")
8831    (set_attr "type" "*,*,*,*")]
8832 )
8833
8834 (define_insn "*ifcompare_arith_arith"
8835   [(set (match_operand:SI 0 "s_register_operand" "=r")
8836         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8837                           [(match_operand:SI 5 "s_register_operand" "r")
8838                            (match_operand:SI 6 "arm_add_operand" "rIL")])
8839                          (match_operator:SI 8 "shiftable_operator"
8840                           [(match_operand:SI 1 "s_register_operand" "r")
8841                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8842                          (match_operator:SI 7 "shiftable_operator"
8843                           [(match_operand:SI 3 "s_register_operand" "r")
8844                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8845    (clobber (reg:CC CC_REGNUM))]
8846   "TARGET_ARM"
8847   "#"
8848   [(set_attr "conds" "clob")
8849    (set_attr "length" "12")]
8850 )
8851
8852 (define_insn "*if_arith_arith"
8853   [(set (match_operand:SI 0 "s_register_operand" "=r")
8854         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8855                           [(match_operand 8 "cc_register" "") (const_int 0)])
8856                          (match_operator:SI 6 "shiftable_operator"
8857                           [(match_operand:SI 1 "s_register_operand" "r")
8858                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8859                          (match_operator:SI 7 "shiftable_operator"
8860                           [(match_operand:SI 3 "s_register_operand" "r")
8861                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8862   "TARGET_ARM"
8863   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8864   [(set_attr "conds" "use")
8865    (set_attr "length" "8")]
8866 )
8867
8868 (define_insn "*ifcompare_arith_move"
8869   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8870         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8871                           [(match_operand:SI 2 "s_register_operand" "r,r")
8872                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8873                          (match_operator:SI 7 "shiftable_operator"
8874                           [(match_operand:SI 4 "s_register_operand" "r,r")
8875                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8876                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8877    (clobber (reg:CC CC_REGNUM))]
8878   "TARGET_ARM"
8879   "*
8880   /* If we have an operation where (op x 0) is the identity operation and
8881      the conditional operator is LT or GE and we are comparing against zero and
8882      everything is in registers then we can do this in two instructions.  */
8883   if (operands[3] == const0_rtx
8884       && GET_CODE (operands[7]) != AND
8885       && GET_CODE (operands[5]) == REG
8886       && GET_CODE (operands[1]) == REG 
8887       && REGNO (operands[1]) == REGNO (operands[4])
8888       && REGNO (operands[4]) != REGNO (operands[0]))
8889     {
8890       if (GET_CODE (operands[6]) == LT)
8891         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8892       else if (GET_CODE (operands[6]) == GE)
8893         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8894     }
8895   if (GET_CODE (operands[3]) == CONST_INT
8896       && !const_ok_for_arm (INTVAL (operands[3])))
8897     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8898   else
8899     output_asm_insn (\"cmp\\t%2, %3\", operands);
8900   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8901   if (which_alternative != 0)
8902     return \"mov%D6\\t%0, %1\";
8903   return \"\";
8904   "
8905   [(set_attr "conds" "clob")
8906    (set_attr "length" "8,12")]
8907 )
8908
8909 (define_insn "*if_arith_move"
8910   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8911         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8912                           [(match_operand 6 "cc_register" "") (const_int 0)])
8913                          (match_operator:SI 5 "shiftable_operator"
8914                           [(match_operand:SI 2 "s_register_operand" "r,r")
8915                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8916                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8917   "TARGET_ARM"
8918   "@
8919    %I5%d4\\t%0, %2, %3
8920    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8921   [(set_attr "conds" "use")
8922    (set_attr "length" "4,8")
8923    (set_attr "type" "*,*")]
8924 )
8925
8926 (define_insn "*ifcompare_move_arith"
8927   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8928         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8929                           [(match_operand:SI 4 "s_register_operand" "r,r")
8930                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8931                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8932                          (match_operator:SI 7 "shiftable_operator"
8933                           [(match_operand:SI 2 "s_register_operand" "r,r")
8934                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8935    (clobber (reg:CC CC_REGNUM))]
8936   "TARGET_ARM"
8937   "*
8938   /* If we have an operation where (op x 0) is the identity operation and
8939      the conditional operator is LT or GE and we are comparing against zero and
8940      everything is in registers then we can do this in two instructions */
8941   if (operands[5] == const0_rtx
8942       && GET_CODE (operands[7]) != AND
8943       && GET_CODE (operands[3]) == REG
8944       && GET_CODE (operands[1]) == REG 
8945       && REGNO (operands[1]) == REGNO (operands[2])
8946       && REGNO (operands[2]) != REGNO (operands[0]))
8947     {
8948       if (GET_CODE (operands[6]) == GE)
8949         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8950       else if (GET_CODE (operands[6]) == LT)
8951         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8952     }
8953
8954   if (GET_CODE (operands[5]) == CONST_INT
8955       && !const_ok_for_arm (INTVAL (operands[5])))
8956     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
8957   else
8958     output_asm_insn (\"cmp\\t%4, %5\", operands);
8959
8960   if (which_alternative != 0)
8961     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
8962   return \"%I7%D6\\t%0, %2, %3\";
8963   "
8964   [(set_attr "conds" "clob")
8965    (set_attr "length" "8,12")]
8966 )
8967
8968 (define_insn "*if_move_arith"
8969   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8970         (if_then_else:SI
8971          (match_operator 4 "arm_comparison_operator"
8972           [(match_operand 6 "cc_register" "") (const_int 0)])
8973          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8974          (match_operator:SI 5 "shiftable_operator"
8975           [(match_operand:SI 2 "s_register_operand" "r,r")
8976            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
8977   "TARGET_ARM"
8978   "@
8979    %I5%D4\\t%0, %2, %3
8980    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8981   [(set_attr "conds" "use")
8982    (set_attr "length" "4,8")
8983    (set_attr "type" "*,*")]
8984 )
8985
8986 (define_insn "*ifcompare_move_not"
8987   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8988         (if_then_else:SI
8989          (match_operator 5 "arm_comparison_operator"
8990           [(match_operand:SI 3 "s_register_operand" "r,r")
8991            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8992          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8993          (not:SI
8994           (match_operand:SI 2 "s_register_operand" "r,r"))))
8995    (clobber (reg:CC CC_REGNUM))]
8996   "TARGET_ARM"
8997   "#"
8998   [(set_attr "conds" "clob")
8999    (set_attr "length" "8,12")]
9000 )
9001
9002 (define_insn "*if_move_not"
9003   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9004         (if_then_else:SI
9005          (match_operator 4 "arm_comparison_operator"
9006           [(match_operand 3 "cc_register" "") (const_int 0)])
9007          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9008          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9009   "TARGET_ARM"
9010   "@
9011    mvn%D4\\t%0, %2
9012    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9013    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
9014   [(set_attr "conds" "use")
9015    (set_attr "length" "4,8,8")]
9016 )
9017
9018 (define_insn "*ifcompare_not_move"
9019   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9020         (if_then_else:SI 
9021          (match_operator 5 "arm_comparison_operator"
9022           [(match_operand:SI 3 "s_register_operand" "r,r")
9023            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9024          (not:SI
9025           (match_operand:SI 2 "s_register_operand" "r,r"))
9026          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9027    (clobber (reg:CC CC_REGNUM))]
9028   "TARGET_ARM"
9029   "#"
9030   [(set_attr "conds" "clob")
9031    (set_attr "length" "8,12")]
9032 )
9033
9034 (define_insn "*if_not_move"
9035   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9036         (if_then_else:SI
9037          (match_operator 4 "arm_comparison_operator"
9038           [(match_operand 3 "cc_register" "") (const_int 0)])
9039          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9040          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9041   "TARGET_ARM"
9042   "@
9043    mvn%d4\\t%0, %2
9044    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9045    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
9046   [(set_attr "conds" "use")
9047    (set_attr "length" "4,8,8")]
9048 )
9049
9050 (define_insn "*ifcompare_shift_move"
9051   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9052         (if_then_else:SI
9053          (match_operator 6 "arm_comparison_operator"
9054           [(match_operand:SI 4 "s_register_operand" "r,r")
9055            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9056          (match_operator:SI 7 "shift_operator"
9057           [(match_operand:SI 2 "s_register_operand" "r,r")
9058            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9059          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9060    (clobber (reg:CC CC_REGNUM))]
9061   "TARGET_ARM"
9062   "#"
9063   [(set_attr "conds" "clob")
9064    (set_attr "length" "8,12")]
9065 )
9066
9067 (define_insn "*if_shift_move"
9068   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9069         (if_then_else:SI
9070          (match_operator 5 "arm_comparison_operator"
9071           [(match_operand 6 "cc_register" "") (const_int 0)])
9072          (match_operator:SI 4 "shift_operator"
9073           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9074            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9075          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9076   "TARGET_ARM"
9077   "@
9078    mov%d5\\t%0, %2%S4
9079    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9080    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
9081   [(set_attr "conds" "use")
9082    (set_attr "shift" "2")
9083    (set_attr "length" "4,8,8")
9084    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9085                       (const_string "alu_shift")
9086                       (const_string "alu_shift_reg")))]
9087 )
9088
9089 (define_insn "*ifcompare_move_shift"
9090   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9091         (if_then_else:SI
9092          (match_operator 6 "arm_comparison_operator"
9093           [(match_operand:SI 4 "s_register_operand" "r,r")
9094            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9095          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9096          (match_operator:SI 7 "shift_operator"
9097           [(match_operand:SI 2 "s_register_operand" "r,r")
9098            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
9099    (clobber (reg:CC CC_REGNUM))]
9100   "TARGET_ARM"
9101   "#"
9102   [(set_attr "conds" "clob")
9103    (set_attr "length" "8,12")]
9104 )
9105
9106 (define_insn "*if_move_shift"
9107   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9108         (if_then_else:SI
9109          (match_operator 5 "arm_comparison_operator"
9110           [(match_operand 6 "cc_register" "") (const_int 0)])
9111          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9112          (match_operator:SI 4 "shift_operator"
9113           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9114            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
9115   "TARGET_ARM"
9116   "@
9117    mov%D5\\t%0, %2%S4
9118    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9119    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
9120   [(set_attr "conds" "use")
9121    (set_attr "shift" "2")
9122    (set_attr "length" "4,8,8")
9123    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9124                       (const_string "alu_shift")
9125                       (const_string "alu_shift_reg")))]
9126 )
9127
9128 (define_insn "*ifcompare_shift_shift"
9129   [(set (match_operand:SI 0 "s_register_operand" "=r")
9130         (if_then_else:SI
9131          (match_operator 7 "arm_comparison_operator"
9132           [(match_operand:SI 5 "s_register_operand" "r")
9133            (match_operand:SI 6 "arm_add_operand" "rIL")])
9134          (match_operator:SI 8 "shift_operator"
9135           [(match_operand:SI 1 "s_register_operand" "r")
9136            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9137          (match_operator:SI 9 "shift_operator"
9138           [(match_operand:SI 3 "s_register_operand" "r")
9139            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
9140    (clobber (reg:CC CC_REGNUM))]
9141   "TARGET_ARM"
9142   "#"
9143   [(set_attr "conds" "clob")
9144    (set_attr "length" "12")]
9145 )
9146
9147 (define_insn "*if_shift_shift"
9148   [(set (match_operand:SI 0 "s_register_operand" "=r")
9149         (if_then_else:SI
9150          (match_operator 5 "arm_comparison_operator"
9151           [(match_operand 8 "cc_register" "") (const_int 0)])
9152          (match_operator:SI 6 "shift_operator"
9153           [(match_operand:SI 1 "s_register_operand" "r")
9154            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9155          (match_operator:SI 7 "shift_operator"
9156           [(match_operand:SI 3 "s_register_operand" "r")
9157            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
9158   "TARGET_ARM"
9159   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
9160   [(set_attr "conds" "use")
9161    (set_attr "shift" "1")
9162    (set_attr "length" "8")
9163    (set (attr "type") (if_then_else
9164                         (and (match_operand 2 "const_int_operand" "")
9165                              (match_operand 4 "const_int_operand" ""))
9166                       (const_string "alu_shift")
9167                       (const_string "alu_shift_reg")))]
9168 )
9169
9170 (define_insn "*ifcompare_not_arith"
9171   [(set (match_operand:SI 0 "s_register_operand" "=r")
9172         (if_then_else:SI
9173          (match_operator 6 "arm_comparison_operator"
9174           [(match_operand:SI 4 "s_register_operand" "r")
9175            (match_operand:SI 5 "arm_add_operand" "rIL")])
9176          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9177          (match_operator:SI 7 "shiftable_operator"
9178           [(match_operand:SI 2 "s_register_operand" "r")
9179            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
9180    (clobber (reg:CC CC_REGNUM))]
9181   "TARGET_ARM"
9182   "#"
9183   [(set_attr "conds" "clob")
9184    (set_attr "length" "12")]
9185 )
9186
9187 (define_insn "*if_not_arith"
9188   [(set (match_operand:SI 0 "s_register_operand" "=r")
9189         (if_then_else:SI
9190          (match_operator 5 "arm_comparison_operator"
9191           [(match_operand 4 "cc_register" "") (const_int 0)])
9192          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9193          (match_operator:SI 6 "shiftable_operator"
9194           [(match_operand:SI 2 "s_register_operand" "r")
9195            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
9196   "TARGET_ARM"
9197   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
9198   [(set_attr "conds" "use")
9199    (set_attr "length" "8")]
9200 )
9201
9202 (define_insn "*ifcompare_arith_not"
9203   [(set (match_operand:SI 0 "s_register_operand" "=r")
9204         (if_then_else:SI
9205          (match_operator 6 "arm_comparison_operator"
9206           [(match_operand:SI 4 "s_register_operand" "r")
9207            (match_operand:SI 5 "arm_add_operand" "rIL")])
9208          (match_operator:SI 7 "shiftable_operator"
9209           [(match_operand:SI 2 "s_register_operand" "r")
9210            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9211          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9212    (clobber (reg:CC CC_REGNUM))]
9213   "TARGET_ARM"
9214   "#"
9215   [(set_attr "conds" "clob")
9216    (set_attr "length" "12")]
9217 )
9218
9219 (define_insn "*if_arith_not"
9220   [(set (match_operand:SI 0 "s_register_operand" "=r")
9221         (if_then_else:SI
9222          (match_operator 5 "arm_comparison_operator"
9223           [(match_operand 4 "cc_register" "") (const_int 0)])
9224          (match_operator:SI 6 "shiftable_operator"
9225           [(match_operand:SI 2 "s_register_operand" "r")
9226            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9227          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9228   "TARGET_ARM"
9229   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9230   [(set_attr "conds" "use")
9231    (set_attr "length" "8")]
9232 )
9233
9234 (define_insn "*ifcompare_neg_move"
9235   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9236         (if_then_else:SI
9237          (match_operator 5 "arm_comparison_operator"
9238           [(match_operand:SI 3 "s_register_operand" "r,r")
9239            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9240          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9241          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9242    (clobber (reg:CC CC_REGNUM))]
9243   "TARGET_ARM"
9244   "#"
9245   [(set_attr "conds" "clob")
9246    (set_attr "length" "8,12")]
9247 )
9248
9249 (define_insn "*if_neg_move"
9250   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9251         (if_then_else:SI
9252          (match_operator 4 "arm_comparison_operator"
9253           [(match_operand 3 "cc_register" "") (const_int 0)])
9254          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9255          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9256   "TARGET_ARM"
9257   "@
9258    rsb%d4\\t%0, %2, #0
9259    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9260    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9261   [(set_attr "conds" "use")
9262    (set_attr "length" "4,8,8")]
9263 )
9264
9265 (define_insn "*ifcompare_move_neg"
9266   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9267         (if_then_else:SI
9268          (match_operator 5 "arm_comparison_operator"
9269           [(match_operand:SI 3 "s_register_operand" "r,r")
9270            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9271          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9272          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9273    (clobber (reg:CC CC_REGNUM))]
9274   "TARGET_ARM"
9275   "#"
9276   [(set_attr "conds" "clob")
9277    (set_attr "length" "8,12")]
9278 )
9279
9280 (define_insn "*if_move_neg"
9281   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9282         (if_then_else:SI
9283          (match_operator 4 "arm_comparison_operator"
9284           [(match_operand 3 "cc_register" "") (const_int 0)])
9285          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9286          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9287   "TARGET_ARM"
9288   "@
9289    rsb%D4\\t%0, %2, #0
9290    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9291    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9292   [(set_attr "conds" "use")
9293    (set_attr "length" "4,8,8")]
9294 )
9295
9296 (define_insn "*arith_adjacentmem"
9297   [(set (match_operand:SI 0 "s_register_operand" "=r")
9298         (match_operator:SI 1 "shiftable_operator"
9299          [(match_operand:SI 2 "memory_operand" "m")
9300           (match_operand:SI 3 "memory_operand" "m")]))
9301    (clobber (match_scratch:SI 4 "=r"))]
9302   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9303   "*
9304   {
9305     rtx ldm[3];
9306     rtx arith[4];
9307     rtx base_reg;
9308     HOST_WIDE_INT val1 = 0, val2 = 0;
9309
9310     if (REGNO (operands[0]) > REGNO (operands[4]))
9311       {
9312         ldm[1] = operands[4];
9313         ldm[2] = operands[0];
9314       }
9315     else
9316       {
9317         ldm[1] = operands[0];
9318         ldm[2] = operands[4];
9319       }
9320
9321     base_reg = XEXP (operands[2], 0);
9322
9323     if (!REG_P (base_reg))
9324       {
9325         val1 = INTVAL (XEXP (base_reg, 1));
9326         base_reg = XEXP (base_reg, 0);
9327       }
9328
9329     if (!REG_P (XEXP (operands[3], 0)))
9330       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9331
9332     arith[0] = operands[0];
9333     arith[3] = operands[1];
9334
9335     if (val1 < val2)
9336       {
9337         arith[1] = ldm[1];
9338         arith[2] = ldm[2];
9339       }
9340     else
9341       {
9342         arith[1] = ldm[2];
9343         arith[2] = ldm[1];
9344       }
9345
9346     ldm[0] = base_reg;
9347     if (val1 !=0 && val2 != 0)
9348       {
9349         if (val1 == 4 || val2 == 4)
9350           /* Other val must be 8, since we know they are adjacent and neither
9351              is zero.  */
9352           output_asm_insn (\"ldm%?ib\\t%0, {%1, %2}\", ldm);
9353         else
9354           {
9355             rtx ops[3];
9356
9357             ldm[0] = ops[0] = operands[4];
9358             ops[1] = base_reg;
9359             ops[2] = GEN_INT (val1);
9360             output_add_immediate (ops);
9361             if (val1 < val2)
9362               output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9363             else
9364               output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9365           }
9366       }
9367     else if (val1 != 0)
9368       {
9369         if (val1 < val2)
9370           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9371         else
9372           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9373       }
9374     else
9375       {
9376         if (val1 < val2)
9377           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9378         else
9379           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9380       }
9381     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9382     return \"\";
9383   }"
9384   [(set_attr "length" "12")
9385    (set_attr "predicable" "yes")
9386    (set_attr "type" "load1")]
9387 )
9388
9389 ;; the arm can support extended pre-inc instructions
9390
9391 ;; In all these cases, we use operands 0 and 1 for the register being
9392 ;; incremented because those are the operands that local-alloc will
9393 ;; tie and these are the pair most likely to be tieable (and the ones
9394 ;; that will benefit the most).
9395
9396 ;; We reject the frame pointer if it occurs anywhere in these patterns since
9397 ;; elimination will cause too many headaches.
9398
9399 (define_insn "*strqi_preinc"
9400   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9401                          (match_operand:SI 2 "index_operand" "rJ")))
9402         (match_operand:QI 3 "s_register_operand" "r"))
9403    (set (match_operand:SI 0 "s_register_operand" "=r")
9404         (plus:SI (match_dup 1) (match_dup 2)))]
9405   "TARGET_ARM
9406    && !arm_eliminable_register (operands[0])
9407    && !arm_eliminable_register (operands[1])
9408    && !arm_eliminable_register (operands[2])"
9409   "str%?b\\t%3, [%0, %2]!"
9410   [(set_attr "type" "store1")
9411    (set_attr "predicable" "yes")]
9412 )
9413
9414 (define_insn "*strqi_predec"
9415   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9416                           (match_operand:SI 2 "s_register_operand" "r")))
9417         (match_operand:QI 3 "s_register_operand" "r"))
9418    (set (match_operand:SI 0 "s_register_operand" "=r")
9419         (minus:SI (match_dup 1) (match_dup 2)))]
9420   "TARGET_ARM
9421    && !arm_eliminable_register (operands[0])
9422    && !arm_eliminable_register (operands[1])
9423    && !arm_eliminable_register (operands[2])"
9424   "str%?b\\t%3, [%0, -%2]!"
9425   [(set_attr "type" "store1")
9426    (set_attr "predicable" "yes")]
9427 )
9428
9429 (define_insn "*loadqi_preinc"
9430   [(set (match_operand:QI 3 "s_register_operand" "=r")
9431         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9432                          (match_operand:SI 2 "index_operand" "rJ"))))
9433    (set (match_operand:SI 0 "s_register_operand" "=r")
9434         (plus:SI (match_dup 1) (match_dup 2)))]
9435   "TARGET_ARM
9436    && !arm_eliminable_register (operands[0])
9437    && !arm_eliminable_register (operands[1])
9438    && !arm_eliminable_register (operands[2])"
9439   "ldr%?b\\t%3, [%0, %2]!"
9440   [(set_attr "type" "load_byte")
9441    (set_attr "predicable" "yes")]
9442 )
9443
9444 (define_insn "*loadqi_predec"
9445   [(set (match_operand:QI 3 "s_register_operand" "=r")
9446         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9447                           (match_operand:SI 2 "s_register_operand" "r"))))
9448    (set (match_operand:SI 0 "s_register_operand" "=r")
9449         (minus:SI (match_dup 1) (match_dup 2)))]
9450   "TARGET_ARM
9451    && !arm_eliminable_register (operands[0])
9452    && !arm_eliminable_register (operands[1])
9453    && !arm_eliminable_register (operands[2])"
9454   "ldr%?b\\t%3, [%0, -%2]!"
9455   [(set_attr "type" "load_byte")
9456    (set_attr "predicable" "yes")]
9457 )
9458
9459 (define_insn "*loadqisi_preinc"
9460   [(set (match_operand:SI 3 "s_register_operand" "=r")
9461         (zero_extend:SI
9462          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9463                           (match_operand:SI 2 "index_operand" "rJ")))))
9464    (set (match_operand:SI 0 "s_register_operand" "=r")
9465         (plus:SI (match_dup 1) (match_dup 2)))]
9466   "TARGET_ARM
9467    && !arm_eliminable_register (operands[0])
9468    && !arm_eliminable_register (operands[1])
9469    && !arm_eliminable_register (operands[2])"
9470   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
9471   [(set_attr "type" "load_byte")
9472    (set_attr "predicable" "yes")]
9473 )
9474
9475 (define_insn "*loadqisi_predec"
9476   [(set (match_operand:SI 3 "s_register_operand" "=r")
9477         (zero_extend:SI
9478          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9479                            (match_operand:SI 2 "s_register_operand" "r")))))
9480    (set (match_operand:SI 0 "s_register_operand" "=r")
9481         (minus:SI (match_dup 1) (match_dup 2)))]
9482   "TARGET_ARM
9483    && !arm_eliminable_register (operands[0])
9484    && !arm_eliminable_register (operands[1])
9485    && !arm_eliminable_register (operands[2])"
9486   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
9487   [(set_attr "type" "load_byte")
9488    (set_attr "predicable" "yes")]
9489 )
9490
9491 (define_insn "*strsi_preinc"
9492   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9493                          (match_operand:SI 2 "index_operand" "rJ")))
9494         (match_operand:SI 3 "s_register_operand" "r"))
9495    (set (match_operand:SI 0 "s_register_operand" "=r")
9496         (plus:SI (match_dup 1) (match_dup 2)))]
9497   "TARGET_ARM
9498    && !arm_eliminable_register (operands[0])
9499    && !arm_eliminable_register (operands[1])
9500    && !arm_eliminable_register (operands[2])"
9501   "str%?\\t%3, [%0, %2]!"
9502   [(set_attr "type" "store1")
9503    (set_attr "predicable" "yes")]
9504 )
9505
9506 (define_insn "*strsi_predec"
9507   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9508                           (match_operand:SI 2 "s_register_operand" "r")))
9509         (match_operand:SI 3 "s_register_operand" "r"))
9510    (set (match_operand:SI 0 "s_register_operand" "=r")
9511         (minus:SI (match_dup 1) (match_dup 2)))]
9512   "TARGET_ARM
9513    && !arm_eliminable_register (operands[0])
9514    && !arm_eliminable_register (operands[1])
9515    && !arm_eliminable_register (operands[2])"
9516   "str%?\\t%3, [%0, -%2]!"
9517   [(set_attr "type" "store1")
9518    (set_attr "predicable" "yes")]
9519 )
9520
9521 (define_insn "*loadsi_preinc"
9522   [(set (match_operand:SI 3 "s_register_operand" "=r")
9523         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9524                          (match_operand:SI 2 "index_operand" "rJ"))))
9525    (set (match_operand:SI 0 "s_register_operand" "=r")
9526         (plus:SI (match_dup 1) (match_dup 2)))]
9527   "TARGET_ARM
9528    && !arm_eliminable_register (operands[0])
9529    && !arm_eliminable_register (operands[1])
9530    && !arm_eliminable_register (operands[2])"
9531   "ldr%?\\t%3, [%0, %2]!"
9532   [(set_attr "type" "load1")
9533    (set_attr "predicable" "yes")]
9534 )
9535
9536 (define_insn "*loadsi_predec"
9537   [(set (match_operand:SI 3 "s_register_operand" "=r")
9538         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9539                           (match_operand:SI 2 "s_register_operand" "r"))))
9540    (set (match_operand:SI 0 "s_register_operand" "=r")
9541         (minus:SI (match_dup 1) (match_dup 2)))]
9542   "TARGET_ARM
9543    && !arm_eliminable_register (operands[0])
9544    && !arm_eliminable_register (operands[1])
9545    && !arm_eliminable_register (operands[2])"
9546   "ldr%?\\t%3, [%0, -%2]!"
9547   [(set_attr "type" "load1")
9548    (set_attr "predicable" "yes")]
9549 )
9550
9551 (define_insn "*strqi_shiftpreinc"
9552   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9553                           [(match_operand:SI 3 "s_register_operand" "r")
9554                            (match_operand:SI 4 "const_shift_operand" "n")])
9555                          (match_operand:SI 1 "s_register_operand" "0")))
9556         (match_operand:QI 5 "s_register_operand" "r"))
9557    (set (match_operand:SI 0 "s_register_operand" "=r")
9558         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9559                  (match_dup 1)))]
9560   "TARGET_ARM
9561    && !arm_eliminable_register (operands[0])
9562    && !arm_eliminable_register (operands[1])
9563    && !arm_eliminable_register (operands[3])"
9564   "str%?b\\t%5, [%0, %3%S2]!"
9565   [(set_attr "type" "store1")
9566    (set_attr "predicable" "yes")]
9567 )
9568
9569 (define_insn "*strqi_shiftpredec"
9570   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9571                           (match_operator:SI 2 "shift_operator"
9572                            [(match_operand:SI 3 "s_register_operand" "r")
9573                             (match_operand:SI 4 "const_shift_operand" "n")])))
9574         (match_operand:QI 5 "s_register_operand" "r"))
9575    (set (match_operand:SI 0 "s_register_operand" "=r")
9576         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9577                                                  (match_dup 4)])))]
9578   "TARGET_ARM
9579    && !arm_eliminable_register (operands[0])
9580    && !arm_eliminable_register (operands[1])
9581    && !arm_eliminable_register (operands[3])"
9582   "str%?b\\t%5, [%0, -%3%S2]!"
9583   [(set_attr "type" "store1")
9584    (set_attr "predicable" "yes")]
9585 )
9586
9587 (define_insn "*loadqi_shiftpreinc"
9588   [(set (match_operand:QI 5 "s_register_operand" "=r")
9589         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9590                           [(match_operand:SI 3 "s_register_operand" "r")
9591                            (match_operand:SI 4 "const_shift_operand" "n")])
9592                          (match_operand:SI 1 "s_register_operand" "0"))))
9593    (set (match_operand:SI 0 "s_register_operand" "=r")
9594         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9595                  (match_dup 1)))]
9596   "TARGET_ARM
9597    && !arm_eliminable_register (operands[0])
9598    && !arm_eliminable_register (operands[1])
9599    && !arm_eliminable_register (operands[3])"
9600   "ldr%?b\\t%5, [%0, %3%S2]!"
9601   [(set_attr "type" "load_byte")
9602    (set_attr "predicable" "yes")]
9603 )
9604
9605 (define_insn "*loadqi_shiftpredec"
9606   [(set (match_operand:QI 5 "s_register_operand" "=r")
9607         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9608                           (match_operator:SI 2 "shift_operator"
9609                            [(match_operand:SI 3 "s_register_operand" "r")
9610                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9611    (set (match_operand:SI 0 "s_register_operand" "=r")
9612         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9613                                                  (match_dup 4)])))]
9614   "TARGET_ARM
9615    && !arm_eliminable_register (operands[0])
9616    && !arm_eliminable_register (operands[1])
9617    && !arm_eliminable_register (operands[3])"
9618   "ldr%?b\\t%5, [%0, -%3%S2]!"
9619   [(set_attr "type" "load_byte")
9620    (set_attr "predicable" "yes")]
9621 )
9622
9623 (define_insn "*strsi_shiftpreinc"
9624   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9625                           [(match_operand:SI 3 "s_register_operand" "r")
9626                            (match_operand:SI 4 "const_shift_operand" "n")])
9627                          (match_operand:SI 1 "s_register_operand" "0")))
9628         (match_operand:SI 5 "s_register_operand" "r"))
9629    (set (match_operand:SI 0 "s_register_operand" "=r")
9630         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9631                  (match_dup 1)))]
9632   "TARGET_ARM
9633    && !arm_eliminable_register (operands[0])
9634    && !arm_eliminable_register (operands[1])
9635    && !arm_eliminable_register (operands[3])"
9636   "str%?\\t%5, [%0, %3%S2]!"
9637   [(set_attr "type" "store1")
9638    (set_attr "predicable" "yes")]
9639 )
9640
9641 (define_insn "*strsi_shiftpredec"
9642   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9643                           (match_operator:SI 2 "shift_operator"
9644                            [(match_operand:SI 3 "s_register_operand" "r")
9645                             (match_operand:SI 4 "const_shift_operand" "n")])))
9646         (match_operand:SI 5 "s_register_operand" "r"))
9647    (set (match_operand:SI 0 "s_register_operand" "=r")
9648         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9649                                                  (match_dup 4)])))]
9650   "TARGET_ARM
9651    && !arm_eliminable_register (operands[0])
9652    && !arm_eliminable_register (operands[1])
9653    && !arm_eliminable_register (operands[3])"
9654   "str%?\\t%5, [%0, -%3%S2]!"
9655   [(set_attr "type" "store1")
9656    (set_attr "predicable" "yes")]
9657 )
9658
9659 (define_insn "*loadsi_shiftpreinc"
9660   [(set (match_operand:SI 5 "s_register_operand" "=r")
9661         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9662                           [(match_operand:SI 3 "s_register_operand" "r")
9663                            (match_operand:SI 4 "const_shift_operand" "n")])
9664                          (match_operand:SI 1 "s_register_operand" "0"))))
9665    (set (match_operand:SI 0 "s_register_operand" "=r")
9666         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9667                  (match_dup 1)))]
9668   "TARGET_ARM
9669    && !arm_eliminable_register (operands[0])
9670    && !arm_eliminable_register (operands[1])
9671    && !arm_eliminable_register (operands[3])"
9672   "ldr%?\\t%5, [%0, %3%S2]!"
9673   [(set_attr "type" "load1")
9674    (set_attr "predicable" "yes")]
9675 )
9676
9677 (define_insn "*loadsi_shiftpredec"
9678   [(set (match_operand:SI 5 "s_register_operand" "=r")
9679         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9680                           (match_operator:SI 2 "shift_operator"
9681                            [(match_operand:SI 3 "s_register_operand" "r")
9682                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9683    (set (match_operand:SI 0 "s_register_operand" "=r")
9684         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9685                                                  (match_dup 4)])))]
9686   "TARGET_ARM
9687    && !arm_eliminable_register (operands[0])
9688    && !arm_eliminable_register (operands[1])
9689    && !arm_eliminable_register (operands[3])"
9690   "ldr%?\\t%5, [%0, -%3%S2]!"
9691   [(set_attr "type" "load1")
9692    (set_attr "predicable" "yes")])
9693
9694 ; It can also support extended post-inc expressions, but combine doesn't
9695 ; try these....
9696 ; It doesn't seem worth adding peepholes for anything but the most common
9697 ; cases since, unlike combine, the increment must immediately follow the load
9698 ; for this pattern to match.
9699 ; We must watch to see that the source/destination register isn't also the
9700 ; same as the base address register, and that if the index is a register,
9701 ; that it is not the same as the base address register.  In such cases the
9702 ; instruction that we would generate would have UNPREDICTABLE behavior so 
9703 ; we cannot use it.
9704
9705 (define_peephole
9706   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9707         (match_operand:QI 2 "s_register_operand" "r"))
9708    (set (match_dup 0)
9709         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9710   "TARGET_ARM
9711    && (REGNO (operands[2]) != REGNO (operands[0]))
9712    && (GET_CODE (operands[1]) != REG
9713        || (REGNO (operands[1]) != REGNO (operands[0])))"
9714   "str%?b\\t%2, [%0], %1"
9715 )
9716
9717 (define_peephole
9718   [(set (match_operand:QI 0 "s_register_operand" "=r")
9719         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9720    (set (match_dup 1)
9721         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9722   "TARGET_ARM
9723    && REGNO (operands[0]) != REGNO(operands[1])
9724    && (GET_CODE (operands[2]) != REG
9725        || REGNO(operands[0]) != REGNO (operands[2]))"
9726   "ldr%?b\\t%0, [%1], %2"
9727 )
9728
9729 (define_peephole
9730   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9731         (match_operand:SI 2 "s_register_operand" "r"))
9732    (set (match_dup 0)
9733         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9734   "TARGET_ARM
9735    && (REGNO (operands[2]) != REGNO (operands[0]))
9736    && (GET_CODE (operands[1]) != REG
9737        || (REGNO (operands[1]) != REGNO (operands[0])))"
9738   "str%?\\t%2, [%0], %1"
9739 )
9740
9741 (define_peephole
9742   [(set (match_operand:SI 0 "s_register_operand" "=r")
9743         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9744    (set (match_dup 1)
9745         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9746   "TARGET_ARM
9747    && REGNO (operands[0]) != REGNO(operands[1])
9748    && (GET_CODE (operands[2]) != REG
9749        || REGNO(operands[0]) != REGNO (operands[2]))"
9750   "ldr%?\\t%0, [%1], %2"
9751 )
9752
9753 (define_peephole
9754   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9755                          (match_operand:SI 1 "index_operand" "rJ")))
9756         (match_operand:QI 2 "s_register_operand" "r"))
9757    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
9758   "TARGET_ARM
9759    && (REGNO (operands[2]) != REGNO (operands[0]))
9760    && (GET_CODE (operands[1]) != REG
9761        || (REGNO (operands[1]) != REGNO (operands[0])))"
9762   "str%?b\\t%2, [%0, %1]!"
9763 )
9764
9765 (define_peephole
9766   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9767                           [(match_operand:SI 0 "s_register_operand" "r")
9768                            (match_operand:SI 1 "const_int_operand" "n")])
9769                          (match_operand:SI 2 "s_register_operand" "+r")))
9770         (match_operand:QI 3 "s_register_operand" "r"))
9771    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9772                                (match_dup 2)))]
9773   "TARGET_ARM
9774    && (REGNO (operands[3]) != REGNO (operands[2]))
9775    && (REGNO (operands[0]) != REGNO (operands[2]))"
9776   "str%?b\\t%3, [%2, %0%S4]!"
9777 )
9778
9779 ; This pattern is never tried by combine, so do it as a peephole
9780
9781 (define_peephole2
9782   [(set (match_operand:SI 0 "arm_general_register_operand" "")
9783         (match_operand:SI 1 "arm_general_register_operand" ""))
9784    (set (reg:CC CC_REGNUM)
9785         (compare:CC (match_dup 1) (const_int 0)))]
9786   "TARGET_ARM"
9787   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9788               (set (match_dup 0) (match_dup 1))])]
9789   ""
9790 )
9791
9792 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9793 ; reversed, check that the memory references aren't volatile.
9794
9795 (define_peephole
9796   [(set (match_operand:SI 0 "s_register_operand" "=r")
9797         (match_operand:SI 4 "memory_operand" "m"))
9798    (set (match_operand:SI 1 "s_register_operand" "=r")
9799         (match_operand:SI 5 "memory_operand" "m"))
9800    (set (match_operand:SI 2 "s_register_operand" "=r")
9801         (match_operand:SI 6 "memory_operand" "m"))
9802    (set (match_operand:SI 3 "s_register_operand" "=r")
9803         (match_operand:SI 7 "memory_operand" "m"))]
9804   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9805   "*
9806   return emit_ldm_seq (operands, 4);
9807   "
9808 )
9809
9810 (define_peephole
9811   [(set (match_operand:SI 0 "s_register_operand" "=r")
9812         (match_operand:SI 3 "memory_operand" "m"))
9813    (set (match_operand:SI 1 "s_register_operand" "=r")
9814         (match_operand:SI 4 "memory_operand" "m"))
9815    (set (match_operand:SI 2 "s_register_operand" "=r")
9816         (match_operand:SI 5 "memory_operand" "m"))]
9817   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9818   "*
9819   return emit_ldm_seq (operands, 3);
9820   "
9821 )
9822
9823 (define_peephole
9824   [(set (match_operand:SI 0 "s_register_operand" "=r")
9825         (match_operand:SI 2 "memory_operand" "m"))
9826    (set (match_operand:SI 1 "s_register_operand" "=r")
9827         (match_operand:SI 3 "memory_operand" "m"))]
9828   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9829   "*
9830   return emit_ldm_seq (operands, 2);
9831   "
9832 )
9833
9834 (define_peephole
9835   [(set (match_operand:SI 4 "memory_operand" "=m")
9836         (match_operand:SI 0 "s_register_operand" "r"))
9837    (set (match_operand:SI 5 "memory_operand" "=m")
9838         (match_operand:SI 1 "s_register_operand" "r"))
9839    (set (match_operand:SI 6 "memory_operand" "=m")
9840         (match_operand:SI 2 "s_register_operand" "r"))
9841    (set (match_operand:SI 7 "memory_operand" "=m")
9842         (match_operand:SI 3 "s_register_operand" "r"))]
9843   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9844   "*
9845   return emit_stm_seq (operands, 4);
9846   "
9847 )
9848
9849 (define_peephole
9850   [(set (match_operand:SI 3 "memory_operand" "=m")
9851         (match_operand:SI 0 "s_register_operand" "r"))
9852    (set (match_operand:SI 4 "memory_operand" "=m")
9853         (match_operand:SI 1 "s_register_operand" "r"))
9854    (set (match_operand:SI 5 "memory_operand" "=m")
9855         (match_operand:SI 2 "s_register_operand" "r"))]
9856   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9857   "*
9858   return emit_stm_seq (operands, 3);
9859   "
9860 )
9861
9862 (define_peephole
9863   [(set (match_operand:SI 2 "memory_operand" "=m")
9864         (match_operand:SI 0 "s_register_operand" "r"))
9865    (set (match_operand:SI 3 "memory_operand" "=m")
9866         (match_operand:SI 1 "s_register_operand" "r"))]
9867   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9868   "*
9869   return emit_stm_seq (operands, 2);
9870   "
9871 )
9872
9873 (define_split
9874   [(set (match_operand:SI 0 "s_register_operand" "")
9875         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9876                        (const_int 0))
9877                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9878                          [(match_operand:SI 3 "s_register_operand" "")
9879                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
9880    (clobber (match_operand:SI 5 "s_register_operand" ""))]
9881   "TARGET_ARM"
9882   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9883    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9884                               (match_dup 5)))]
9885   ""
9886 )
9887
9888 ;; This split can be used because CC_Z mode implies that the following
9889 ;; branch will be an equality, or an unsigned inequality, so the sign
9890 ;; extension is not needed.
9891
9892 (define_split
9893   [(set (reg:CC_Z CC_REGNUM)
9894         (compare:CC_Z
9895          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9896                     (const_int 24))
9897          (match_operand 1 "const_int_operand" "")))
9898    (clobber (match_scratch:SI 2 ""))]
9899   "TARGET_ARM
9900    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9901        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9902   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9903    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9904   "
9905   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9906   "
9907 )
9908
9909 (define_expand "prologue"
9910   [(clobber (const_int 0))]
9911   "TARGET_EITHER"
9912   "if (TARGET_ARM)
9913      arm_expand_prologue ();
9914    else
9915      thumb_expand_prologue ();
9916   DONE;
9917   "
9918 )
9919
9920 (define_expand "epilogue"
9921   [(clobber (const_int 0))]
9922   "TARGET_EITHER"
9923   "
9924   if (current_function_calls_eh_return)
9925     emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
9926   if (TARGET_THUMB)
9927     thumb_expand_epilogue ();
9928   else if (USE_RETURN_INSN (FALSE))
9929     {
9930       emit_jump_insn (gen_return ());
9931       DONE;
9932     }
9933   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9934         gen_rtvec (1,
9935                 gen_rtx_RETURN (VOIDmode)),
9936         VUNSPEC_EPILOGUE));
9937   DONE;
9938   "
9939 )
9940
9941 ;; Note - although unspec_volatile's USE all hard registers,
9942 ;; USEs are ignored after relaod has completed.  Thus we need
9943 ;; to add an unspec of the link register to ensure that flow
9944 ;; does not think that it is unused by the sibcall branch that
9945 ;; will replace the standard function epilogue.
9946 (define_insn "sibcall_epilogue"
9947   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9948               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9949   "TARGET_ARM"
9950   "*
9951   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9952     return output_return_instruction (const_true_rtx, FALSE, FALSE);
9953   return arm_output_epilogue (next_nonnote_insn (insn));
9954   "
9955 ;; Length is absolute worst case
9956   [(set_attr "length" "44")
9957    (set_attr "type" "block")
9958    ;; We don't clobber the conditions, but the potential length of this
9959    ;; operation is sufficient to make conditionalizing the sequence 
9960    ;; unlikely to be profitable.
9961    (set_attr "conds" "clob")]
9962 )
9963
9964 (define_insn "*epilogue_insns"
9965   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9966   "TARGET_EITHER"
9967   "*
9968   if (TARGET_ARM)
9969     return arm_output_epilogue (NULL);
9970   else /* TARGET_THUMB */
9971     return thumb_unexpanded_epilogue ();
9972   "
9973   ; Length is absolute worst case
9974   [(set_attr "length" "44")
9975    (set_attr "type" "block")
9976    ;; We don't clobber the conditions, but the potential length of this
9977    ;; operation is sufficient to make conditionalizing the sequence 
9978    ;; unlikely to be profitable.
9979    (set_attr "conds" "clob")]
9980 )
9981
9982 (define_expand "eh_epilogue"
9983   [(use (match_operand:SI 0 "register_operand" ""))
9984    (use (match_operand:SI 1 "register_operand" ""))
9985    (use (match_operand:SI 2 "register_operand" ""))]
9986   "TARGET_EITHER"
9987   "
9988   {
9989     cfun->machine->eh_epilogue_sp_ofs = operands[1];
9990     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9991       {
9992         rtx ra = gen_rtx_REG (Pmode, 2);
9993
9994         emit_move_insn (ra, operands[2]);
9995         operands[2] = ra;
9996       }
9997     /* This is a hack -- we may have crystalized the function type too
9998        early.  */
9999     cfun->machine->func_type = 0;
10000   }"
10001 )
10002
10003 ;; This split is only used during output to reduce the number of patterns
10004 ;; that need assembler instructions adding to them.  We allowed the setting
10005 ;; of the conditions to be implicit during rtl generation so that
10006 ;; the conditional compare patterns would work.  However this conflicts to
10007 ;; some extent with the conditional data operations, so we have to split them
10008 ;; up again here.
10009
10010 (define_split
10011   [(set (match_operand:SI 0 "s_register_operand" "")
10012         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10013                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10014                          (match_dup 0)
10015                          (match_operand 4 "" "")))
10016    (clobber (reg:CC CC_REGNUM))]
10017   "TARGET_ARM && reload_completed"
10018   [(set (match_dup 5) (match_dup 6))
10019    (cond_exec (match_dup 7)
10020               (set (match_dup 0) (match_dup 4)))]
10021   "
10022   {
10023     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10024                                              operands[2], operands[3]);
10025     enum rtx_code rc = GET_CODE (operands[1]);
10026
10027     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10028     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10029     if (mode == CCFPmode || mode == CCFPEmode)
10030       rc = reverse_condition_maybe_unordered (rc);
10031     else
10032       rc = reverse_condition (rc);
10033
10034     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10035   }"
10036 )
10037
10038 (define_split
10039   [(set (match_operand:SI 0 "s_register_operand" "")
10040         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10041                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10042                          (match_operand 4 "" "")
10043                          (match_dup 0)))
10044    (clobber (reg:CC CC_REGNUM))]
10045   "TARGET_ARM && reload_completed"
10046   [(set (match_dup 5) (match_dup 6))
10047    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10048               (set (match_dup 0) (match_dup 4)))]
10049   "
10050   {
10051     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10052                                              operands[2], operands[3]);
10053
10054     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10055     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10056   }"
10057 )
10058
10059 (define_split
10060   [(set (match_operand:SI 0 "s_register_operand" "")
10061         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10062                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10063                          (match_operand 4 "" "")
10064                          (match_operand 5 "" "")))
10065    (clobber (reg:CC CC_REGNUM))]
10066   "TARGET_ARM && reload_completed"
10067   [(set (match_dup 6) (match_dup 7))
10068    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10069               (set (match_dup 0) (match_dup 4)))
10070    (cond_exec (match_dup 8)
10071               (set (match_dup 0) (match_dup 5)))]
10072   "
10073   {
10074     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10075                                              operands[2], operands[3]);
10076     enum rtx_code rc = GET_CODE (operands[1]);
10077
10078     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10079     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10080     if (mode == CCFPmode || mode == CCFPEmode)
10081       rc = reverse_condition_maybe_unordered (rc);
10082     else
10083       rc = reverse_condition (rc);
10084
10085     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10086   }"
10087 )
10088
10089 (define_split
10090   [(set (match_operand:SI 0 "s_register_operand" "")
10091         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10092                           [(match_operand:SI 2 "s_register_operand" "")
10093                            (match_operand:SI 3 "arm_add_operand" "")])
10094                          (match_operand:SI 4 "arm_rhs_operand" "")
10095                          (not:SI
10096                           (match_operand:SI 5 "s_register_operand" ""))))
10097    (clobber (reg:CC CC_REGNUM))]
10098   "TARGET_ARM && reload_completed"
10099   [(set (match_dup 6) (match_dup 7))
10100    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10101               (set (match_dup 0) (match_dup 4)))
10102    (cond_exec (match_dup 8)
10103               (set (match_dup 0) (not:SI (match_dup 5))))]
10104   "
10105   {
10106     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10107                                              operands[2], operands[3]);
10108     enum rtx_code rc = GET_CODE (operands[1]);
10109
10110     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10111     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10112     if (mode == CCFPmode || mode == CCFPEmode)
10113       rc = reverse_condition_maybe_unordered (rc);
10114     else
10115       rc = reverse_condition (rc);
10116
10117     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10118   }"
10119 )
10120
10121 (define_insn "*cond_move_not"
10122   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10123         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10124                           [(match_operand 3 "cc_register" "") (const_int 0)])
10125                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10126                          (not:SI
10127                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
10128   "TARGET_ARM"
10129   "@
10130    mvn%D4\\t%0, %2
10131    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
10132   [(set_attr "conds" "use")
10133    (set_attr "length" "4,8")]
10134 )
10135
10136 ;; The next two patterns occur when an AND operation is followed by a
10137 ;; scc insn sequence 
10138
10139 (define_insn "*sign_extract_onebit"
10140   [(set (match_operand:SI 0 "s_register_operand" "=r")
10141         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10142                          (const_int 1)
10143                          (match_operand:SI 2 "const_int_operand" "n")))
10144     (clobber (reg:CC CC_REGNUM))]
10145   "TARGET_ARM"
10146   "*
10147     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10148     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10149     return \"mvnne\\t%0, #0\";
10150   "
10151   [(set_attr "conds" "clob")
10152    (set_attr "length" "8")]
10153 )
10154
10155 (define_insn "*not_signextract_onebit"
10156   [(set (match_operand:SI 0 "s_register_operand" "=r")
10157         (not:SI
10158          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10159                           (const_int 1)
10160                           (match_operand:SI 2 "const_int_operand" "n"))))
10161    (clobber (reg:CC CC_REGNUM))]
10162   "TARGET_ARM"
10163   "*
10164     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10165     output_asm_insn (\"tst\\t%1, %2\", operands);
10166     output_asm_insn (\"mvneq\\t%0, #0\", operands);
10167     return \"movne\\t%0, #0\";
10168   "
10169   [(set_attr "conds" "clob")
10170    (set_attr "length" "12")]
10171 )
10172
10173 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
10174 ;; expressions.  For simplicity, the first register is also in the unspec
10175 ;; part.
10176 (define_insn "*push_multi"
10177   [(match_parallel 2 "multi_register_push"
10178     [(set (match_operand:BLK 0 "memory_operand" "=m")
10179           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
10180                       UNSPEC_PUSH_MULT))])]
10181   "TARGET_ARM"
10182   "*
10183   {
10184     int num_saves = XVECLEN (operands[2], 0);
10185      
10186     /* For the StrongARM at least it is faster to
10187        use STR to store only a single register.  */
10188     if (num_saves == 1)
10189       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10190     else
10191       {
10192         int i;
10193         char pattern[100];
10194
10195         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10196
10197         for (i = 1; i < num_saves; i++)
10198           {
10199             strcat (pattern, \", %|\");
10200             strcat (pattern,
10201                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10202           }
10203
10204         strcat (pattern, \"}\");
10205         output_asm_insn (pattern, operands);
10206       }
10207
10208     return \"\";
10209   }"
10210   [(set_attr "type" "store4")]
10211 )
10212
10213 (define_insn "stack_tie"
10214   [(set (mem:BLK (scratch))
10215         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
10216                      (match_operand:SI 1 "s_register_operand" "r")]
10217                     UNSPEC_PRLG_STK))]
10218   ""
10219   ""
10220   [(set_attr "length" "0")]
10221 )
10222
10223 ;; Similarly for the floating point registers
10224 (define_insn "*push_fp_multi"
10225   [(match_parallel 2 "multi_register_push"
10226     [(set (match_operand:BLK 0 "memory_operand" "=m")
10227           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10228                       UNSPEC_PUSH_MULT))])]
10229   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
10230   "*
10231   {
10232     char pattern[100];
10233
10234     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10235     output_asm_insn (pattern, operands);
10236     return \"\";
10237   }"
10238   [(set_attr "type" "f_store")]
10239 )
10240
10241 ;; Special patterns for dealing with the constant pool
10242
10243 (define_insn "align_4"
10244   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10245   "TARGET_EITHER"
10246   "*
10247   assemble_align (32);
10248   return \"\";
10249   "
10250 )
10251
10252 (define_insn "align_8"
10253   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10254   "TARGET_EITHER"
10255   "*
10256   assemble_align (64);
10257   return \"\";
10258   "
10259 )
10260
10261 (define_insn "consttable_end"
10262   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10263   "TARGET_EITHER"
10264   "*
10265   making_const_table = FALSE;
10266   return \"\";
10267   "
10268 )
10269
10270 (define_insn "consttable_1"
10271   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10272   "TARGET_THUMB"
10273   "*
10274   making_const_table = TRUE;
10275   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10276   assemble_zeros (3);
10277   return \"\";
10278   "
10279   [(set_attr "length" "4")]
10280 )
10281
10282 (define_insn "consttable_2"
10283   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10284   "TARGET_THUMB"
10285   "*
10286   making_const_table = TRUE;
10287   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10288   assemble_zeros (2);
10289   return \"\";
10290   "
10291   [(set_attr "length" "4")]
10292 )
10293
10294 (define_insn "consttable_4"
10295   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10296   "TARGET_EITHER"
10297   "*
10298   {
10299     making_const_table = TRUE;
10300     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10301       {
10302       case MODE_FLOAT:
10303       {
10304         REAL_VALUE_TYPE r;
10305         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10306         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10307         break;
10308       }
10309       default:
10310         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
10311         break;
10312       }
10313     return \"\";
10314   }"
10315   [(set_attr "length" "4")]
10316 )
10317
10318 (define_insn "consttable_8"
10319   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10320   "TARGET_EITHER"
10321   "*
10322   {
10323     making_const_table = TRUE;
10324     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10325       {
10326        case MODE_FLOAT:
10327         {
10328           REAL_VALUE_TYPE r;
10329           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10330           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10331           break;
10332         }
10333       default:
10334         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10335         break;
10336       }
10337     return \"\";
10338   }"
10339   [(set_attr "length" "8")]
10340 )
10341
10342 ;; Miscellaneous Thumb patterns
10343
10344 (define_expand "tablejump"
10345   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10346               (use (label_ref (match_operand 1 "" "")))])]
10347   "TARGET_THUMB"
10348   "
10349   if (flag_pic)
10350     {
10351       /* Hopefully, CSE will eliminate this copy.  */
10352       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10353       rtx reg2 = gen_reg_rtx (SImode);
10354
10355       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10356       operands[0] = reg2;
10357     }
10358   "
10359 )
10360
10361 ;; NB never uses BX.
10362 (define_insn "*thumb_tablejump"
10363   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10364    (use (label_ref (match_operand 1 "" "")))]
10365   "TARGET_THUMB"
10366   "mov\\t%|pc, %0"
10367   [(set_attr "length" "2")]
10368 )
10369
10370 ;; V5 Instructions,
10371
10372 (define_insn "clzsi2"
10373   [(set (match_operand:SI 0 "s_register_operand" "=r")
10374         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10375   "TARGET_ARM && arm_arch5"
10376   "clz%?\\t%0, %1"
10377   [(set_attr "predicable" "yes")])
10378
10379 (define_expand "ffssi2"
10380   [(set (match_operand:SI 0 "s_register_operand" "")
10381         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10382   "TARGET_ARM && arm_arch5"
10383   "
10384   {
10385     rtx t1, t2, t3;
10386
10387     t1 = gen_reg_rtx (SImode);
10388     t2 = gen_reg_rtx (SImode);
10389     t3 = gen_reg_rtx (SImode);
10390
10391     emit_insn (gen_negsi2 (t1, operands[1]));
10392     emit_insn (gen_andsi3 (t2, operands[1], t1));
10393     emit_insn (gen_clzsi2 (t3, t2));
10394     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10395     DONE;
10396   }"
10397 )
10398
10399 (define_expand "ctzsi2"
10400   [(set (match_operand:SI 0 "s_register_operand" "")
10401         (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10402   "TARGET_ARM && arm_arch5"
10403   "
10404   {
10405     rtx t1, t2, t3;
10406
10407     t1 = gen_reg_rtx (SImode);
10408     t2 = gen_reg_rtx (SImode);
10409     t3 = gen_reg_rtx (SImode);
10410
10411     emit_insn (gen_negsi2 (t1, operands[1]));
10412     emit_insn (gen_andsi3 (t2, operands[1], t1));
10413     emit_insn (gen_clzsi2 (t3, t2));
10414     emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10415     DONE;
10416   }"
10417 )
10418
10419 ;; V5E instructions.
10420
10421 (define_insn "prefetch"
10422   [(prefetch (match_operand:SI 0 "address_operand" "p")
10423              (match_operand:SI 1 "" "")
10424              (match_operand:SI 2 "" ""))]
10425   "TARGET_ARM && arm_arch5e"
10426   "pld\\t%a0")
10427
10428 ;; General predication pattern
10429
10430 (define_cond_exec
10431   [(match_operator 0 "arm_comparison_operator"
10432     [(match_operand 1 "cc_register" "")
10433      (const_int 0)])]
10434   "TARGET_ARM"
10435   ""
10436 )
10437
10438 (define_insn "prologue_use"
10439   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10440   ""
10441   "%@ %0 needed for prologue"
10442 )
10443
10444
10445 ;; Patterns for exception handling
10446
10447 (define_expand "eh_return"
10448   [(use (match_operand 0 "general_operand" ""))]
10449   "TARGET_EITHER"
10450   "
10451   {
10452     if (TARGET_ARM)
10453       emit_insn (gen_arm_eh_return (operands[0]));
10454     else
10455       emit_insn (gen_thumb_eh_return (operands[0]));
10456     DONE;
10457   }"
10458 )
10459                                    
10460 ;; We can't expand this before we know where the link register is stored.
10461 (define_insn_and_split "arm_eh_return"
10462   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10463                     VUNSPEC_EH_RETURN)
10464    (clobber (match_scratch:SI 1 "=&r"))]
10465   "TARGET_ARM"
10466   "#"
10467   "&& reload_completed"
10468   [(const_int 0)]
10469   "
10470   {
10471     arm_set_return_address (operands[0], operands[1]);
10472     DONE;
10473   }"
10474 )
10475
10476 (define_insn_and_split "thumb_eh_return"
10477   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10478                     VUNSPEC_EH_RETURN)
10479    (clobber (match_scratch:SI 1 "=&l"))]
10480   "TARGET_THUMB"
10481   "#"
10482   "&& reload_completed"
10483   [(const_int 0)]
10484   "
10485   {
10486     thumb_set_return_address (operands[0], operands[1]);
10487     DONE;
10488   }"
10489 )
10490
10491 ;; Load the FPA co-processor patterns
10492 (include "fpa.md")
10493 ;; Load the Maverick co-processor patterns
10494 (include "cirrus.md")
10495 ;; Load the Intel Wireless Multimedia Extension patterns
10496 (include "iwmmxt.md")
10497 ;; Load the VFP co-processor patterns
10498 (include "vfp.md")
10499