OSDN Git Service

Update FSF address.
[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, 51 Franklin Street, Fifth Floor,
23 ;; Boston, MA 02110-1301, USA.
24
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26
27 \f
28 ;;---------------------------------------------------------------------------
29 ;; Constants
30
31 ;; Register numbers
32 (define_constants
33   [(R0_REGNUM        0)         ; First CORE register
34    (IP_REGNUM       12)         ; Scratch register
35    (SP_REGNUM       13)         ; Stack pointer
36    (LR_REGNUM       14)         ; Return address register
37    (PC_REGNUM       15)         ; Program counter
38    (CC_REGNUM       24)         ; Condition code pseudo register
39    (LAST_ARM_REGNUM 15)         ;
40    (FPA_F0_REGNUM   16)         ; FIRST_FPA_REGNUM
41    (FPA_F7_REGNUM   23)         ; LAST_FPA_REGNUM
42   ]
43 )
44 ;; 3rd operand to select_dominance_cc_mode
45 (define_constants
46   [(DOM_CC_X_AND_Y  0)
47    (DOM_CC_NX_OR_Y  1)
48    (DOM_CC_X_OR_Y   2)
49   ]
50 )
51
52 ;; UNSPEC Usage:
53 ;; Note: sin and cos are no-longer used.
54
55 (define_constants
56   [(UNSPEC_SIN       0) ; `sin' operation (MODE_FLOAT):
57                         ;   operand 0 is the result,
58                         ;   operand 1 the parameter.
59    (UNPSEC_COS       1) ; `cos' operation (MODE_FLOAT):
60                         ;   operand 0 is the result,
61                         ;   operand 1 the parameter.
62    (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
63                         ;   operand 0 is the first register,
64                         ;   subsequent registers are in parallel (use ...)
65                         ;   expressions.
66    (UNSPEC_PIC_SYM   3) ; A symbol that has been treated properly for pic
67                         ;   usage, that is, we will add the pic_register
68                         ;   value to it before trying to dereference it.
69    (UNSPEC_PIC_BASE  4) ; Adding the PC value to the offset to the
70                         ;   GLOBAL_OFFSET_TABLE.  The operation is fully
71                         ;   described by the RTL but must be wrapped to
72                         ;   prevent combine from trying to rip it apart.
73    (UNSPEC_PRLG_STK  5) ; A special barrier that prevents frame accesses 
74                         ;   being scheduled before the stack adjustment insn.
75    (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
76                         ; this unspec is used to prevent the deletion of
77                         ; instructions setting registers for EH handling
78                         ; and stack frame generation.  Operand 0 is the
79                         ; register to "use".
80    (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
81    (UNSPEC_WSHUFH    8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
82    (UNSPEC_WACC      9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
83    (UNSPEC_TMOVMSK  10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
84    (UNSPEC_WSAD     11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
85    (UNSPEC_WSADZ    12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
86    (UNSPEC_WMACS    13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
87    (UNSPEC_WMACU    14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
88    (UNSPEC_WMACSZ   15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
89    (UNSPEC_WMACUZ   16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
90    (UNSPEC_CLRDI    17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
91    (UNSPEC_WMADDS   18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
92    (UNSPEC_WMADDU   19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
93   ]
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_tune_strongarm")))
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_load[sd]    single/double load from memory
206 ; f_store[sd]   single/double store to memory
207 ; f_flag        a transfer of co-processor flags to the CPSR
208 ; f_mem_r       a transfer of a floating point register to a real reg via mem
209 ; r_mem_f       the reverse of f_mem_r
210 ; f_2_r         fast transfer float to arm (no memory needed)
211 ; r_2_f         fast transfer arm to float
212 ; f_cvt         convert floating<->integral
213 ; branch        a branch
214 ; call          a subroutine call
215 ; load_byte     load byte(s) from memory to arm registers
216 ; load1         load 1 word from memory to arm registers
217 ; load2         load 2 words from memory to arm registers
218 ; load3         load 3 words from memory to arm registers
219 ; load4         load 4 words from memory to arm registers
220 ; store         store 1 word to memory from arm registers
221 ; store2        store 2 words
222 ; store3        store 3 words
223 ; store4        store 4 (or more) words
224 ;  Additions for Cirrus Maverick co-processor:
225 ; mav_farith    Floating point arithmetic (4 cycle)
226 ; mav_dmult     Double multiplies (7 cycle)
227 ;
228 (define_attr "type"
229         "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,f_flag,float_em,f_load,f_store,f_loads,f_loadd,f_stores,f_stored,f_mem_r,r_mem_f,f_2_r,r_2_f,f_cvt,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult" 
230         (if_then_else 
231          (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
232          (const_string "mult")
233          (const_string "alu")))
234
235 ; Load scheduling, set from the arm_ld_sched variable
236 ; initialized by arm_override_options() 
237 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
238
239 ; condition codes: this one is used by final_prescan_insn to speed up
240 ; conditionalizing instructions.  It saves having to scan the rtl to see if
241 ; it uses or alters the condition codes.
242
243 ; USE means that the condition codes are used by the insn in the process of
244 ;   outputting code, this means (at present) that we can't use the insn in
245 ;   inlined branches
246 ;
247 ; SET means that the purpose of the insn is to set the condition codes in a
248 ;   well defined manner.
249 ;
250 ; CLOB means that the condition codes are altered in an undefined manner, if
251 ;   they are altered at all
252 ;
253 ; JUMP_CLOB is used when the condition cannot be represented by a single
254 ;   instruction (UNEQ and LTGT).  These cannot be predicated.
255 ;
256 ; NOCOND means that the condition codes are neither altered nor affect the
257 ;   output of this insn
258
259 (define_attr "conds" "use,set,clob,jump_clob,nocond"
260         (if_then_else (eq_attr "type" "call")
261          (const_string "clob")
262          (const_string "nocond")))
263
264 ; Predicable means that the insn can be conditionally executed based on
265 ; an automatically added predicate (additional patterns are generated by 
266 ; gen...).  We default to 'no' because no Thumb patterns match this rule
267 ; and not all ARM patterns do.
268 (define_attr "predicable" "no,yes" (const_string "no"))
269
270 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
271 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
272 ; suffer blockages enough to warrant modelling this (and it can adversely
273 ; affect the schedule).
274 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
275
276 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
277 ; to stall the processor.  Used with model_wbuf above.
278 (define_attr "write_conflict" "no,yes"
279   (if_then_else (eq_attr "type"
280                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
281                 (const_string "yes")
282                 (const_string "no")))
283
284 ; Classify the insns into those that take one cycle and those that take more
285 ; than one on the main cpu execution unit.
286 (define_attr "core_cycles" "single,multi"
287   (if_then_else (eq_attr "type"
288                  "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
289                 (const_string "single")
290                 (const_string "multi")))
291
292 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
293 ;; distant label.  Only applicable to Thumb code.
294 (define_attr "far_jump" "yes,no" (const_string "no"))
295
296
297 ;;---------------------------------------------------------------------------
298 ;; Mode macros
299
300 ; A list of modes that are exactly 64 bits in size.  We use this to expand
301 ; some splits that are the same for all modes when operating on ARM 
302 ; registers.
303 (define_mode_macro ANY64 [DI DF V8QI V4HI V2SI V2SF])
304
305 ;;---------------------------------------------------------------------------
306 ;; Predicates
307
308 (include "predicates.md")
309
310 ;;---------------------------------------------------------------------------
311 ;; Pipeline descriptions
312
313 ;; Processor type.  This is created automatically from arm-cores.def.
314 (include "arm-tune.md")
315
316 ;; True if the generic scheduling description should be used.
317
318 (define_attr "generic_sched" "yes,no"
319   (const (if_then_else 
320           (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs") 
321           (const_string "no")
322           (const_string "yes"))))
323
324 (define_attr "generic_vfp" "yes,no"
325   (const (if_then_else
326           (and (eq_attr "fpu" "vfp")
327                (eq_attr "tune" "!arm1020e,arm1022e"))
328           (const_string "yes")
329           (const_string "no"))))
330
331 (include "arm-generic.md")
332 (include "arm926ejs.md")
333 (include "arm1020e.md")
334 (include "arm1026ejs.md")
335 (include "arm1136jfs.md")
336
337 \f
338 ;;---------------------------------------------------------------------------
339 ;; Insn patterns
340 ;;
341 ;; Addition insns.
342
343 ;; Note: For DImode insns, there is normally no reason why operands should
344 ;; not be in the same register, what we don't want is for something being
345 ;; written to partially overlap something that is an input.
346 ;; Cirrus 64bit additions should not be split because we have a native
347 ;; 64bit addition instructions.
348
349 (define_expand "adddi3"
350  [(parallel
351    [(set (match_operand:DI           0 "s_register_operand" "")
352           (plus:DI (match_operand:DI 1 "s_register_operand" "")
353                    (match_operand:DI 2 "s_register_operand" "")))
354     (clobber (reg:CC CC_REGNUM))])]
355   "TARGET_EITHER"
356   "
357   if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
358     {
359       if (!cirrus_fp_register (operands[0], DImode))
360         operands[0] = force_reg (DImode, operands[0]);
361       if (!cirrus_fp_register (operands[1], DImode))
362         operands[1] = force_reg (DImode, operands[1]);
363       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
364       DONE;
365     }
366
367   if (TARGET_THUMB)
368     {
369       if (GET_CODE (operands[1]) != REG)
370         operands[1] = force_reg (SImode, operands[1]);
371       if (GET_CODE (operands[2]) != REG)
372         operands[2] = force_reg (SImode, operands[2]);
373      }
374   "
375 )
376
377 (define_insn "*thumb_adddi3"
378   [(set (match_operand:DI          0 "register_operand" "=l")
379         (plus:DI (match_operand:DI 1 "register_operand" "%0")
380                  (match_operand:DI 2 "register_operand" "l")))
381    (clobber (reg:CC CC_REGNUM))
382   ]
383   "TARGET_THUMB"
384   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
385   [(set_attr "length" "4")]
386 )
387
388 (define_insn_and_split "*arm_adddi3"
389   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
390         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
391                  (match_operand:DI 2 "s_register_operand" "r,  0")))
392    (clobber (reg:CC CC_REGNUM))]
393   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
394   "#"
395   "TARGET_ARM && reload_completed"
396   [(parallel [(set (reg:CC_C CC_REGNUM)
397                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
398                                  (match_dup 1)))
399               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
400    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
401                                (plus:SI (match_dup 4) (match_dup 5))))]
402   "
403   {
404     operands[3] = gen_highpart (SImode, operands[0]);
405     operands[0] = gen_lowpart (SImode, operands[0]);
406     operands[4] = gen_highpart (SImode, operands[1]);
407     operands[1] = gen_lowpart (SImode, operands[1]);
408     operands[5] = gen_highpart (SImode, operands[2]);
409     operands[2] = gen_lowpart (SImode, operands[2]);
410   }"
411   [(set_attr "conds" "clob")
412    (set_attr "length" "8")]
413 )
414
415 (define_insn_and_split "*adddi_sesidi_di"
416   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
417         (plus:DI (sign_extend:DI
418                   (match_operand:SI 2 "s_register_operand" "r,r"))
419                  (match_operand:DI 1 "s_register_operand" "r,0")))
420    (clobber (reg:CC CC_REGNUM))]
421   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
422   "#"
423   "TARGET_ARM && reload_completed"
424   [(parallel [(set (reg:CC_C CC_REGNUM)
425                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
426                                  (match_dup 1)))
427               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
428    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
429                                (plus:SI (ashiftrt:SI (match_dup 2)
430                                                      (const_int 31))
431                                         (match_dup 4))))]
432   "
433   {
434     operands[3] = gen_highpart (SImode, operands[0]);
435     operands[0] = gen_lowpart (SImode, operands[0]);
436     operands[4] = gen_highpart (SImode, operands[1]);
437     operands[1] = gen_lowpart (SImode, operands[1]);
438     operands[2] = gen_lowpart (SImode, operands[2]);
439   }"
440   [(set_attr "conds" "clob")
441    (set_attr "length" "8")]
442 )
443
444 (define_insn_and_split "*adddi_zesidi_di"
445   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
446         (plus:DI (zero_extend:DI
447                   (match_operand:SI 2 "s_register_operand" "r,r"))
448                  (match_operand:DI 1 "s_register_operand" "r,0")))
449    (clobber (reg:CC CC_REGNUM))]
450   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
451   "#"
452   "TARGET_ARM && reload_completed"
453   [(parallel [(set (reg:CC_C CC_REGNUM)
454                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
455                                  (match_dup 1)))
456               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
457    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
458                                (plus:SI (match_dup 4) (const_int 0))))]
459   "
460   {
461     operands[3] = gen_highpart (SImode, operands[0]);
462     operands[0] = gen_lowpart (SImode, operands[0]);
463     operands[4] = gen_highpart (SImode, operands[1]);
464     operands[1] = gen_lowpart (SImode, operands[1]);
465     operands[2] = gen_lowpart (SImode, operands[2]);
466   }"
467   [(set_attr "conds" "clob")
468    (set_attr "length" "8")]
469 )
470
471 (define_expand "addsi3"
472   [(set (match_operand:SI          0 "s_register_operand" "")
473         (plus:SI (match_operand:SI 1 "s_register_operand" "")
474                  (match_operand:SI 2 "reg_or_int_operand" "")))]
475   "TARGET_EITHER"
476   "
477   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
478     {
479       arm_split_constant (PLUS, SImode, NULL_RTX,
480                           INTVAL (operands[2]), operands[0], operands[1],
481                           optimize && !no_new_pseudos);
482       DONE;
483     }
484   "
485 )
486
487 ; If there is a scratch available, this will be faster than synthesizing the
488 ; addition.
489 (define_peephole2
490   [(match_scratch:SI 3 "r")
491    (set (match_operand:SI          0 "arm_general_register_operand" "")
492         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
493                  (match_operand:SI 2 "const_int_operand"  "")))]
494   "TARGET_ARM &&
495    !(const_ok_for_arm (INTVAL (operands[2]))
496      || const_ok_for_arm (-INTVAL (operands[2])))
497     && const_ok_for_arm (~INTVAL (operands[2]))"
498   [(set (match_dup 3) (match_dup 2))
499    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
500   ""
501 )
502
503 (define_insn_and_split "*arm_addsi3"
504   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
505         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
506                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
507   "TARGET_ARM"
508   "@
509    add%?\\t%0, %1, %2
510    sub%?\\t%0, %1, #%n2
511    #"
512   "TARGET_ARM &&
513    GET_CODE (operands[2]) == CONST_INT
514    && !(const_ok_for_arm (INTVAL (operands[2]))
515         || const_ok_for_arm (-INTVAL (operands[2])))"
516   [(clobber (const_int 0))]
517   "
518   arm_split_constant (PLUS, SImode, curr_insn,
519                       INTVAL (operands[2]), operands[0],
520                       operands[1], 0);
521   DONE;
522   "
523   [(set_attr "length" "4,4,16")
524    (set_attr "predicable" "yes")]
525 )
526
527 ;; Register group 'k' is a single register group containing only the stack
528 ;; register.  Trying to reload it will always fail catastrophically,
529 ;; so never allow those alternatives to match if reloading is needed.
530
531 (define_insn "*thumb_addsi3"
532   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
533         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
534                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
535   "TARGET_THUMB"
536   "*
537    static const char * const asms[] = 
538    {
539      \"add\\t%0, %0, %2\",
540      \"sub\\t%0, %0, #%n2\",
541      \"add\\t%0, %1, %2\",
542      \"add\\t%0, %0, %2\",
543      \"add\\t%0, %0, %2\",
544      \"add\\t%0, %1, %2\",
545      \"add\\t%0, %1, %2\"
546    };
547    if ((which_alternative == 2 || which_alternative == 6)
548        && GET_CODE (operands[2]) == CONST_INT
549        && INTVAL (operands[2]) < 0)
550      return \"sub\\t%0, %1, #%n2\";
551    return asms[which_alternative];
552   "
553   [(set_attr "length" "2")]
554 )
555
556 ;; Reloading and elimination of the frame pointer can
557 ;; sometimes cause this optimization to be missed.
558 (define_peephole2
559   [(set (match_operand:SI 0 "arm_general_register_operand" "")
560         (match_operand:SI 1 "const_int_operand" ""))
561    (set (match_dup 0)
562         (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
563   "TARGET_THUMB
564    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
565    && (INTVAL (operands[1]) & 3) == 0"
566   [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
567   ""
568 )
569
570 (define_insn "*addsi3_compare0"
571   [(set (reg:CC_NOOV CC_REGNUM)
572         (compare:CC_NOOV
573          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
574                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
575          (const_int 0)))
576    (set (match_operand:SI 0 "s_register_operand" "=r,r")
577         (plus:SI (match_dup 1) (match_dup 2)))]
578   "TARGET_ARM"
579   "@
580    add%?s\\t%0, %1, %2
581    sub%?s\\t%0, %1, #%n2"
582   [(set_attr "conds" "set")]
583 )
584
585 (define_insn "*addsi3_compare0_scratch"
586   [(set (reg:CC_NOOV CC_REGNUM)
587         (compare:CC_NOOV
588          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
589                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
590          (const_int 0)))]
591   "TARGET_ARM"
592   "@
593    cmn%?\\t%0, %1
594    cmp%?\\t%0, #%n1"
595   [(set_attr "conds" "set")]
596 )
597
598 (define_insn "*compare_negsi_si"
599   [(set (reg:CC_Z CC_REGNUM)
600         (compare:CC_Z
601          (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
602          (match_operand:SI 1 "s_register_operand" "r")))]
603   "TARGET_ARM"
604   "cmn%?\\t%1, %0"
605   [(set_attr "conds" "set")]
606 )
607
608 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
609 ;; addend is a constant.
610 (define_insn "*cmpsi2_addneg"
611   [(set (reg:CC CC_REGNUM)
612         (compare:CC
613          (match_operand:SI 1 "s_register_operand" "r,r")
614          (match_operand:SI 2 "arm_addimm_operand" "I,L")))
615    (set (match_operand:SI 0 "s_register_operand" "=r,r")
616         (plus:SI (match_dup 1)
617                  (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
618   "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
619   "@
620    sub%?s\\t%0, %1, %2
621    add%?s\\t%0, %1, #%n2"
622   [(set_attr "conds" "set")]
623 )
624
625 ;; Convert the sequence
626 ;;  sub  rd, rn, #1
627 ;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
628 ;;  bne  dest
629 ;; into
630 ;;  subs rd, rn, #1
631 ;;  bcs  dest   ((unsigned)rn >= 1)
632 ;; similarly for the beq variant using bcc.
633 ;; This is a common looping idiom (while (n--))
634 (define_peephole2
635   [(set (match_operand:SI 0 "arm_general_register_operand" "")
636         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
637                  (const_int -1)))
638    (set (match_operand 2 "cc_register" "")
639         (compare (match_dup 0) (const_int -1)))
640    (set (pc)
641         (if_then_else (match_operator 3 "equality_operator"
642                        [(match_dup 2) (const_int 0)])
643                       (match_operand 4 "" "")
644                       (match_operand 5 "" "")))]
645   "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
646   [(parallel[
647     (set (match_dup 2)
648          (compare:CC
649           (match_dup 1) (const_int 1)))
650     (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
651    (set (pc)
652         (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
653                       (match_dup 4)
654                       (match_dup 5)))]
655   "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
656    operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
657                                   ? GEU : LTU),
658                                  VOIDmode, 
659                                  operands[2], const0_rtx);"
660 )
661
662 ;; The next four insns work because they compare the result with one of
663 ;; the operands, and we know that the use of the condition code is
664 ;; either GEU or LTU, so we can use the carry flag from the addition
665 ;; instead of doing the compare a second time.
666 (define_insn "*addsi3_compare_op1"
667   [(set (reg:CC_C CC_REGNUM)
668         (compare:CC_C
669          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
670                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
671          (match_dup 1)))
672    (set (match_operand:SI 0 "s_register_operand" "=r,r")
673         (plus:SI (match_dup 1) (match_dup 2)))]
674   "TARGET_ARM"
675   "@
676    add%?s\\t%0, %1, %2
677    sub%?s\\t%0, %1, #%n2"
678   [(set_attr "conds" "set")]
679 )
680
681 (define_insn "*addsi3_compare_op2"
682   [(set (reg:CC_C CC_REGNUM)
683         (compare:CC_C
684          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
685                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
686          (match_dup 2)))
687    (set (match_operand:SI 0 "s_register_operand" "=r,r")
688         (plus:SI (match_dup 1) (match_dup 2)))]
689   "TARGET_ARM"
690   "@
691    add%?s\\t%0, %1, %2
692    sub%?s\\t%0, %1, #%n2"
693   [(set_attr "conds" "set")]
694 )
695
696 (define_insn "*compare_addsi2_op0"
697   [(set (reg:CC_C CC_REGNUM)
698         (compare:CC_C
699          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
700                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
701          (match_dup 0)))]
702   "TARGET_ARM"
703   "@
704    cmn%?\\t%0, %1
705    cmp%?\\t%0, #%n1"
706   [(set_attr "conds" "set")]
707 )
708
709 (define_insn "*compare_addsi2_op1"
710   [(set (reg:CC_C CC_REGNUM)
711         (compare:CC_C
712          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
713                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
714          (match_dup 1)))]
715   "TARGET_ARM"
716   "@
717    cmn%?\\t%0, %1
718    cmp%?\\t%0, #%n1"
719   [(set_attr "conds" "set")]
720 )
721
722 (define_insn "*addsi3_carryin"
723   [(set (match_operand:SI 0 "s_register_operand" "=r")
724         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
725                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
726                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
727   "TARGET_ARM"
728   "adc%?\\t%0, %1, %2"
729   [(set_attr "conds" "use")]
730 )
731
732 (define_insn "*addsi3_carryin_shift"
733   [(set (match_operand:SI 0 "s_register_operand" "=r")
734         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
735                  (plus:SI
736                    (match_operator:SI 2 "shift_operator"
737                       [(match_operand:SI 3 "s_register_operand" "r")
738                        (match_operand:SI 4 "reg_or_int_operand" "rM")])
739                     (match_operand:SI 1 "s_register_operand" "r"))))]
740   "TARGET_ARM"
741   "adc%?\\t%0, %1, %3%S2"
742   [(set_attr "conds" "use")
743    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
744                       (const_string "alu_shift")
745                       (const_string "alu_shift_reg")))]
746 )
747
748 (define_insn "*addsi3_carryin_alt1"
749   [(set (match_operand:SI 0 "s_register_operand" "=r")
750         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
751                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
752                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
753   "TARGET_ARM"
754   "adc%?\\t%0, %1, %2"
755   [(set_attr "conds" "use")]
756 )
757
758 (define_insn "*addsi3_carryin_alt2"
759   [(set (match_operand:SI 0 "s_register_operand" "=r")
760         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
761                           (match_operand:SI 1 "s_register_operand" "r"))
762                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
763   "TARGET_ARM"
764   "adc%?\\t%0, %1, %2"
765   [(set_attr "conds" "use")]
766 )
767
768 (define_insn "*addsi3_carryin_alt3"
769   [(set (match_operand:SI 0 "s_register_operand" "=r")
770         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
771                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
772                  (match_operand:SI 1 "s_register_operand" "r")))]
773   "TARGET_ARM"
774   "adc%?\\t%0, %1, %2"
775   [(set_attr "conds" "use")]
776 )
777
778 (define_insn "incscc"
779   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
780         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
781                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
782                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
783   "TARGET_ARM"
784   "@
785   add%d2\\t%0, %1, #1
786   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
787   [(set_attr "conds" "use")
788    (set_attr "length" "4,8")]
789 )
790
791 ; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
792 (define_split
793   [(set (match_operand:SI 0 "s_register_operand" "")
794         (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
795                             (match_operand:SI 2 "s_register_operand" ""))
796                  (const_int -1)))
797    (clobber (match_operand:SI 3 "s_register_operand" ""))]
798   "TARGET_ARM"
799   [(set (match_dup 3) (match_dup 1))
800    (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
801   "
802   operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
803 ")
804
805 (define_expand "addsf3"
806   [(set (match_operand:SF          0 "s_register_operand" "")
807         (plus:SF (match_operand:SF 1 "s_register_operand" "")
808                  (match_operand:SF 2 "arm_float_add_operand" "")))]
809   "TARGET_ARM && TARGET_HARD_FLOAT"
810   "
811   if (TARGET_MAVERICK
812       && !cirrus_fp_register (operands[2], SFmode))
813     operands[2] = force_reg (SFmode, operands[2]);
814 ")
815
816 (define_expand "adddf3"
817   [(set (match_operand:DF          0 "s_register_operand" "")
818         (plus:DF (match_operand:DF 1 "s_register_operand" "")
819                  (match_operand:DF 2 "arm_float_add_operand" "")))]
820   "TARGET_ARM && TARGET_HARD_FLOAT"
821   "
822   if (TARGET_MAVERICK
823       && !cirrus_fp_register (operands[2], DFmode))
824     operands[2] = force_reg (DFmode, operands[2]);
825 ")
826
827 (define_expand "subdi3"
828  [(parallel
829    [(set (match_operand:DI            0 "s_register_operand" "")
830           (minus:DI (match_operand:DI 1 "s_register_operand" "")
831                     (match_operand:DI 2 "s_register_operand" "")))
832     (clobber (reg:CC CC_REGNUM))])]
833   "TARGET_EITHER"
834   "
835   if (TARGET_HARD_FLOAT && TARGET_MAVERICK
836       && TARGET_ARM
837       && cirrus_fp_register (operands[0], DImode)
838       && cirrus_fp_register (operands[1], DImode))
839     {
840       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
841       DONE;
842     }
843
844   if (TARGET_THUMB)
845     {
846       if (GET_CODE (operands[1]) != REG)
847         operands[1] = force_reg (SImode, operands[1]);
848       if (GET_CODE (operands[2]) != REG)
849         operands[2] = force_reg (SImode, operands[2]);
850      }  
851   "
852 )
853
854 (define_insn "*arm_subdi3"
855   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
856         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
857                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
858    (clobber (reg:CC CC_REGNUM))]
859   "TARGET_ARM"
860   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
861   [(set_attr "conds" "clob")
862    (set_attr "length" "8")]
863 )
864
865 (define_insn "*thumb_subdi3"
866   [(set (match_operand:DI           0 "register_operand" "=l")
867         (minus:DI (match_operand:DI 1 "register_operand"  "0")
868                   (match_operand:DI 2 "register_operand"  "l")))
869    (clobber (reg:CC CC_REGNUM))]
870   "TARGET_THUMB"
871   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
872   [(set_attr "length" "4")]
873 )
874
875 (define_insn "*subdi_di_zesidi"
876   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
877         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
878                   (zero_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, #0"
883   [(set_attr "conds" "clob")
884    (set_attr "length" "8")]
885 )
886
887 (define_insn "*subdi_di_sesidi"
888   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
889         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
890                   (sign_extend:DI
891                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
892    (clobber (reg:CC CC_REGNUM))]
893   "TARGET_ARM"
894   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
895   [(set_attr "conds" "clob")
896    (set_attr "length" "8")]
897 )
898
899 (define_insn "*subdi_zesidi_di"
900   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
901         (minus:DI (zero_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, #0"
907   [(set_attr "conds" "clob")
908    (set_attr "length" "8")]
909 )
910
911 (define_insn "*subdi_sesidi_di"
912   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
913         (minus:DI (sign_extend:DI
914                    (match_operand:SI 2 "s_register_operand"   "r,r"))
915                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
916    (clobber (reg:CC CC_REGNUM))]
917   "TARGET_ARM"
918   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
919   [(set_attr "conds" "clob")
920    (set_attr "length" "8")]
921 )
922
923 (define_insn "*subdi_zesidi_zesidi"
924   [(set (match_operand:DI            0 "s_register_operand" "=r")
925         (minus:DI (zero_extend:DI
926                    (match_operand:SI 1 "s_register_operand"  "r"))
927                   (zero_extend:DI
928                    (match_operand:SI 2 "s_register_operand"  "r"))))
929    (clobber (reg:CC CC_REGNUM))]
930   "TARGET_ARM"
931   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
932   [(set_attr "conds" "clob")
933    (set_attr "length" "8")]
934 )
935
936 (define_expand "subsi3"
937   [(set (match_operand:SI           0 "s_register_operand" "")
938         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
939                   (match_operand:SI 2 "s_register_operand" "")))]
940   "TARGET_EITHER"
941   "
942   if (GET_CODE (operands[1]) == CONST_INT)
943     {
944       if (TARGET_ARM)
945         {
946           arm_split_constant (MINUS, SImode, NULL_RTX,
947                               INTVAL (operands[1]), operands[0],
948                               operands[2], optimize && !no_new_pseudos);
949           DONE;
950         }
951       else /* TARGET_THUMB */
952         operands[1] = force_reg (SImode, operands[1]);
953     }
954   "
955 )
956
957 (define_insn "*thumb_subsi3_insn"
958   [(set (match_operand:SI           0 "register_operand" "=l")
959         (minus:SI (match_operand:SI 1 "register_operand" "l")
960                   (match_operand:SI 2 "register_operand" "l")))]
961   "TARGET_THUMB"
962   "sub\\t%0, %1, %2"
963   [(set_attr "length" "2")]
964 )
965
966 (define_insn_and_split "*arm_subsi3_insn"
967   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
968         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
969                   (match_operand:SI 2 "s_register_operand" "r,r")))]
970   "TARGET_ARM"
971   "@
972    rsb%?\\t%0, %2, %1
973    #"
974   "TARGET_ARM
975    && GET_CODE (operands[1]) == CONST_INT
976    && !const_ok_for_arm (INTVAL (operands[1]))"
977   [(clobber (const_int 0))]
978   "
979   arm_split_constant (MINUS, SImode, curr_insn,
980                       INTVAL (operands[1]), operands[0], operands[2], 0);
981   DONE;
982   "
983   [(set_attr "length" "4,16")
984    (set_attr "predicable" "yes")]
985 )
986
987 (define_peephole2
988   [(match_scratch:SI 3 "r")
989    (set (match_operand:SI 0 "arm_general_register_operand" "")
990         (minus:SI (match_operand:SI 1 "const_int_operand" "")
991                   (match_operand:SI 2 "arm_general_register_operand" "")))]
992   "TARGET_ARM
993    && !const_ok_for_arm (INTVAL (operands[1]))
994    && const_ok_for_arm (~INTVAL (operands[1]))"
995   [(set (match_dup 3) (match_dup 1))
996    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
997   ""
998 )
999
1000 (define_insn "*subsi3_compare0"
1001   [(set (reg:CC_NOOV CC_REGNUM)
1002         (compare:CC_NOOV
1003          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1004                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1005          (const_int 0)))
1006    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1007         (minus:SI (match_dup 1) (match_dup 2)))]
1008   "TARGET_ARM"
1009   "@
1010    sub%?s\\t%0, %1, %2
1011    rsb%?s\\t%0, %2, %1"
1012   [(set_attr "conds" "set")]
1013 )
1014
1015 (define_insn "decscc"
1016   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1017         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1018                   (match_operator:SI 2 "arm_comparison_operator"
1019                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1020   "TARGET_ARM"
1021   "@
1022    sub%d2\\t%0, %1, #1
1023    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1024   [(set_attr "conds" "use")
1025    (set_attr "length" "*,8")]
1026 )
1027
1028 (define_expand "subsf3"
1029   [(set (match_operand:SF           0 "s_register_operand" "")
1030         (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1031                   (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1032   "TARGET_ARM && TARGET_HARD_FLOAT"
1033   "
1034   if (TARGET_MAVERICK)
1035     {
1036       if (!cirrus_fp_register (operands[1], SFmode))
1037         operands[1] = force_reg (SFmode, operands[1]);
1038       if (!cirrus_fp_register (operands[2], SFmode))
1039         operands[2] = force_reg (SFmode, operands[2]);
1040     }
1041 ")
1042
1043 (define_expand "subdf3"
1044   [(set (match_operand:DF           0 "s_register_operand" "")
1045         (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1046                   (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1047   "TARGET_ARM && TARGET_HARD_FLOAT"
1048   "
1049   if (TARGET_MAVERICK)
1050     {
1051        if (!cirrus_fp_register (operands[1], DFmode))
1052          operands[1] = force_reg (DFmode, operands[1]);
1053        if (!cirrus_fp_register (operands[2], DFmode))
1054          operands[2] = force_reg (DFmode, operands[2]);
1055     }
1056 ")
1057
1058 \f
1059 ;; Multiplication insns
1060
1061 (define_expand "mulsi3"
1062   [(set (match_operand:SI          0 "s_register_operand" "")
1063         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1064                  (match_operand:SI 1 "s_register_operand" "")))]
1065   "TARGET_EITHER"
1066   ""
1067 )
1068
1069 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1070 (define_insn "*arm_mulsi3"
1071   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1072         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1073                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1074   "TARGET_ARM"
1075   "mul%?\\t%0, %2, %1"
1076   [(set_attr "insn" "mul")
1077    (set_attr "predicable" "yes")]
1078 )
1079
1080 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1081 ; 1 and 2; are the same, because reload will make operand 0 match 
1082 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1083 ; this by adding another alternative to match this case, and then `reload' 
1084 ; it ourselves.  This alternative must come first.
1085 (define_insn "*thumb_mulsi3"
1086   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1087         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1088                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1089   "TARGET_THUMB"
1090   "*
1091   if (which_alternative < 2)
1092     return \"mov\\t%0, %1\;mul\\t%0, %2\";
1093   else
1094     return \"mul\\t%0, %2\";
1095   "
1096   [(set_attr "length" "4,4,2")
1097    (set_attr "insn" "mul")]
1098 )
1099
1100 (define_insn "*mulsi3_compare0"
1101   [(set (reg:CC_NOOV CC_REGNUM)
1102         (compare:CC_NOOV (mult:SI
1103                           (match_operand:SI 2 "s_register_operand" "r,r")
1104                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1105                          (const_int 0)))
1106    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1107         (mult:SI (match_dup 2) (match_dup 1)))]
1108   "TARGET_ARM"
1109   "mul%?s\\t%0, %2, %1"
1110   [(set_attr "conds" "set")
1111    (set_attr "insn" "muls")]
1112 )
1113
1114 (define_insn "*mulsi_compare0_scratch"
1115   [(set (reg:CC_NOOV CC_REGNUM)
1116         (compare:CC_NOOV (mult:SI
1117                           (match_operand:SI 2 "s_register_operand" "r,r")
1118                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1119                          (const_int 0)))
1120    (clobber (match_scratch:SI 0 "=&r,&r"))]
1121   "TARGET_ARM"
1122   "mul%?s\\t%0, %2, %1"
1123   [(set_attr "conds" "set")
1124    (set_attr "insn" "muls")]
1125 )
1126
1127 ;; Unnamed templates to match MLA instruction.
1128
1129 (define_insn "*mulsi3addsi"
1130   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1131         (plus:SI
1132           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1133                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1134           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1135   "TARGET_ARM"
1136   "mla%?\\t%0, %2, %1, %3"
1137   [(set_attr "insn" "mla")
1138    (set_attr "predicable" "yes")]
1139 )
1140
1141 (define_insn "*mulsi3addsi_compare0"
1142   [(set (reg:CC_NOOV CC_REGNUM)
1143         (compare:CC_NOOV
1144          (plus:SI (mult:SI
1145                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1146                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1147                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1148          (const_int 0)))
1149    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1150         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1151                  (match_dup 3)))]
1152   "TARGET_ARM"
1153   "mla%?s\\t%0, %2, %1, %3"
1154   [(set_attr "conds" "set")
1155    (set_attr "insn" "mlas")]
1156 )
1157
1158 (define_insn "*mulsi3addsi_compare0_scratch"
1159   [(set (reg:CC_NOOV CC_REGNUM)
1160         (compare:CC_NOOV
1161          (plus:SI (mult:SI
1162                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1163                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1164                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1165          (const_int 0)))
1166    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1167   "TARGET_ARM"
1168   "mla%?s\\t%0, %2, %1, %3"
1169   [(set_attr "conds" "set")
1170    (set_attr "insn" "mlas")]
1171 )
1172
1173 ;; Unnamed template to match long long multiply-accumulate (smlal)
1174
1175 (define_insn "*mulsidi3adddi"
1176   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1177         (plus:DI
1178          (mult:DI
1179           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1180           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1181          (match_operand:DI 1 "s_register_operand" "0")))]
1182   "TARGET_ARM && arm_arch3m"
1183   "smlal%?\\t%Q0, %R0, %3, %2"
1184   [(set_attr "insn" "smlal")
1185    (set_attr "predicable" "yes")]
1186 )
1187
1188 (define_insn "mulsidi3"
1189   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1190         (mult:DI
1191          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1192          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1193   "TARGET_ARM && arm_arch3m"
1194   "smull%?\\t%Q0, %R0, %1, %2"
1195   [(set_attr "insn" "smull")
1196    (set_attr "predicable" "yes")]
1197 )
1198
1199 (define_insn "umulsidi3"
1200   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1201         (mult:DI
1202          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1203          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1204   "TARGET_ARM && arm_arch3m"
1205   "umull%?\\t%Q0, %R0, %1, %2"
1206   [(set_attr "insn" "umull")
1207    (set_attr "predicable" "yes")]
1208 )
1209
1210 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1211
1212 (define_insn "*umulsidi3adddi"
1213   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1214         (plus:DI
1215          (mult:DI
1216           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1217           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1218          (match_operand:DI 1 "s_register_operand" "0")))]
1219   "TARGET_ARM && arm_arch3m"
1220   "umlal%?\\t%Q0, %R0, %3, %2"
1221   [(set_attr "insn" "umlal")
1222    (set_attr "predicable" "yes")]
1223 )
1224
1225 (define_insn "smulsi3_highpart"
1226   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1227         (truncate:SI
1228          (lshiftrt:DI
1229           (mult:DI
1230            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1231            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1232           (const_int 32))))
1233    (clobber (match_scratch:SI 3 "=&r,&r"))]
1234   "TARGET_ARM && arm_arch3m"
1235   "smull%?\\t%3, %0, %2, %1"
1236   [(set_attr "insn" "smull")
1237    (set_attr "predicable" "yes")]
1238 )
1239
1240 (define_insn "umulsi3_highpart"
1241   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1242         (truncate:SI
1243          (lshiftrt:DI
1244           (mult:DI
1245            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1246            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1247           (const_int 32))))
1248    (clobber (match_scratch:SI 3 "=&r,&r"))]
1249   "TARGET_ARM && arm_arch3m"
1250   "umull%?\\t%3, %0, %2, %1"
1251   [(set_attr "insn" "umull")
1252    (set_attr "predicable" "yes")]
1253 )
1254
1255 (define_insn "mulhisi3"
1256   [(set (match_operand:SI 0 "s_register_operand" "=r")
1257         (mult:SI (sign_extend:SI
1258                   (match_operand:HI 1 "s_register_operand" "%r"))
1259                  (sign_extend:SI
1260                   (match_operand:HI 2 "s_register_operand" "r"))))]
1261   "TARGET_ARM && arm_arch5e"
1262   "smulbb%?\\t%0, %1, %2"
1263   [(set_attr "insn" "smulxy")
1264    (set_attr "predicable" "yes")]
1265 )
1266
1267 (define_insn "*mulhisi3tb"
1268   [(set (match_operand:SI 0 "s_register_operand" "=r")
1269         (mult:SI (ashiftrt:SI
1270                   (match_operand:SI 1 "s_register_operand" "r")
1271                   (const_int 16))
1272                  (sign_extend:SI
1273                   (match_operand:HI 2 "s_register_operand" "r"))))]
1274   "TARGET_ARM && arm_arch5e"
1275   "smultb%?\\t%0, %1, %2"
1276   [(set_attr "insn" "smulxy")
1277    (set_attr "predicable" "yes")]
1278 )
1279
1280 (define_insn "*mulhisi3bt"
1281   [(set (match_operand:SI 0 "s_register_operand" "=r")
1282         (mult:SI (sign_extend:SI
1283                   (match_operand:HI 1 "s_register_operand" "r"))
1284                  (ashiftrt:SI
1285                   (match_operand:SI 2 "s_register_operand" "r")
1286                   (const_int 16))))]
1287   "TARGET_ARM && arm_arch5e"
1288   "smulbt%?\\t%0, %1, %2"
1289   [(set_attr "insn" "smulxy")
1290    (set_attr "predicable" "yes")]
1291 )
1292
1293 (define_insn "*mulhisi3tt"
1294   [(set (match_operand:SI 0 "s_register_operand" "=r")
1295         (mult:SI (ashiftrt:SI
1296                   (match_operand:SI 1 "s_register_operand" "r")
1297                   (const_int 16))
1298                  (ashiftrt:SI
1299                   (match_operand:SI 2 "s_register_operand" "r")
1300                   (const_int 16))))]
1301   "TARGET_ARM && arm_arch5e"
1302   "smultt%?\\t%0, %1, %2"
1303   [(set_attr "insn" "smulxy")
1304    (set_attr "predicable" "yes")]
1305 )
1306
1307 (define_insn "*mulhisi3addsi"
1308   [(set (match_operand:SI 0 "s_register_operand" "=r")
1309         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1310                  (mult:SI (sign_extend:SI
1311                            (match_operand:HI 2 "s_register_operand" "%r"))
1312                           (sign_extend:SI
1313                            (match_operand:HI 3 "s_register_operand" "r")))))]
1314   "TARGET_ARM && arm_arch5e"
1315   "smlabb%?\\t%0, %2, %3, %1"
1316   [(set_attr "insn" "smlaxy")
1317    (set_attr "predicable" "yes")]
1318 )
1319
1320 (define_insn "*mulhidi3adddi"
1321   [(set (match_operand:DI 0 "s_register_operand" "=r")
1322         (plus:DI
1323           (match_operand:DI 1 "s_register_operand" "0")
1324           (mult:DI (sign_extend:DI
1325                     (match_operand:HI 2 "s_register_operand" "%r"))
1326                    (sign_extend:DI
1327                     (match_operand:HI 3 "s_register_operand" "r")))))]
1328   "TARGET_ARM && arm_arch5e"
1329   "smlalbb%?\\t%Q0, %R0, %2, %3"
1330   [(set_attr "insn" "smlalxy")
1331    (set_attr "predicable" "yes")])
1332
1333 (define_expand "mulsf3"
1334   [(set (match_operand:SF          0 "s_register_operand" "")
1335         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1336                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1337   "TARGET_ARM && TARGET_HARD_FLOAT"
1338   "
1339   if (TARGET_MAVERICK
1340       && !cirrus_fp_register (operands[2], SFmode))
1341     operands[2] = force_reg (SFmode, operands[2]);
1342 ")
1343
1344 (define_expand "muldf3"
1345   [(set (match_operand:DF          0 "s_register_operand" "")
1346         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1347                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1348   "TARGET_ARM && TARGET_HARD_FLOAT"
1349   "
1350   if (TARGET_MAVERICK
1351       && !cirrus_fp_register (operands[2], DFmode))
1352     operands[2] = force_reg (DFmode, operands[2]);
1353 ")
1354 \f
1355 ;; Division insns
1356
1357 (define_expand "divsf3"
1358   [(set (match_operand:SF 0 "s_register_operand" "")
1359         (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1360                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1361   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1362   "")
1363
1364 (define_expand "divdf3"
1365   [(set (match_operand:DF 0 "s_register_operand" "")
1366         (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1367                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1368   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1369   "")
1370 \f
1371 ;; Modulo insns
1372
1373 (define_expand "modsf3"
1374   [(set (match_operand:SF 0 "s_register_operand" "")
1375         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1376                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1377   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1378   "")
1379
1380 (define_expand "moddf3"
1381   [(set (match_operand:DF 0 "s_register_operand" "")
1382         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1383                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1384   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1385   "")
1386 \f
1387 ;; Boolean and,ior,xor insns
1388
1389 ;; Split up double word logical operations
1390
1391 ;; Split up simple DImode logical operations.  Simply perform the logical
1392 ;; operation on the upper and lower halves of the registers.
1393 (define_split
1394   [(set (match_operand:DI 0 "s_register_operand" "")
1395         (match_operator:DI 6 "logical_binary_operator"
1396           [(match_operand:DI 1 "s_register_operand" "")
1397            (match_operand:DI 2 "s_register_operand" "")]))]
1398   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1399   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1400    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1401   "
1402   {
1403     operands[3] = gen_highpart (SImode, operands[0]);
1404     operands[0] = gen_lowpart (SImode, operands[0]);
1405     operands[4] = gen_highpart (SImode, operands[1]);
1406     operands[1] = gen_lowpart (SImode, operands[1]);
1407     operands[5] = gen_highpart (SImode, operands[2]);
1408     operands[2] = gen_lowpart (SImode, operands[2]);
1409   }"
1410 )
1411
1412 (define_split
1413   [(set (match_operand:DI 0 "s_register_operand" "")
1414         (match_operator:DI 6 "logical_binary_operator"
1415           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1416            (match_operand:DI 1 "s_register_operand" "")]))]
1417   "TARGET_ARM && reload_completed"
1418   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1419    (set (match_dup 3) (match_op_dup:SI 6
1420                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1421                          (match_dup 4)]))]
1422   "
1423   {
1424     operands[3] = gen_highpart (SImode, operands[0]);
1425     operands[0] = gen_lowpart (SImode, operands[0]);
1426     operands[4] = gen_highpart (SImode, operands[1]);
1427     operands[1] = gen_lowpart (SImode, operands[1]);
1428     operands[5] = gen_highpart (SImode, operands[2]);
1429     operands[2] = gen_lowpart (SImode, operands[2]);
1430   }"
1431 )
1432
1433 ;; The zero extend of operand 2 means we can just copy the high part of
1434 ;; operand1 into operand0.
1435 (define_split
1436   [(set (match_operand:DI 0 "s_register_operand" "")
1437         (ior:DI
1438           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1439           (match_operand:DI 1 "s_register_operand" "")))]
1440   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1441   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1442    (set (match_dup 3) (match_dup 4))]
1443   "
1444   {
1445     operands[4] = gen_highpart (SImode, operands[1]);
1446     operands[3] = gen_highpart (SImode, operands[0]);
1447     operands[0] = gen_lowpart (SImode, operands[0]);
1448     operands[1] = gen_lowpart (SImode, operands[1]);
1449   }"
1450 )
1451
1452 ;; The zero extend of operand 2 means we can just copy the high part of
1453 ;; operand1 into operand0.
1454 (define_split
1455   [(set (match_operand:DI 0 "s_register_operand" "")
1456         (xor:DI
1457           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1458           (match_operand:DI 1 "s_register_operand" "")))]
1459   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1460   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1461    (set (match_dup 3) (match_dup 4))]
1462   "
1463   {
1464     operands[4] = gen_highpart (SImode, operands[1]);
1465     operands[3] = gen_highpart (SImode, operands[0]);
1466     operands[0] = gen_lowpart (SImode, operands[0]);
1467     operands[1] = gen_lowpart (SImode, operands[1]);
1468   }"
1469 )
1470
1471 (define_insn "anddi3"
1472   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1473         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1474                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1475   "TARGET_ARM && ! TARGET_IWMMXT"
1476   "#"
1477   [(set_attr "length" "8")]
1478 )
1479
1480 (define_insn_and_split "*anddi_zesidi_di"
1481   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1482         (and:DI (zero_extend:DI
1483                  (match_operand:SI 2 "s_register_operand" "r,r"))
1484                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1485   "TARGET_ARM"
1486   "#"
1487   "TARGET_ARM && reload_completed"
1488   ; The zero extend of operand 2 clears the high word of the output
1489   ; operand.
1490   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1491    (set (match_dup 3) (const_int 0))]
1492   "
1493   {
1494     operands[3] = gen_highpart (SImode, operands[0]);
1495     operands[0] = gen_lowpart (SImode, operands[0]);
1496     operands[1] = gen_lowpart (SImode, operands[1]);
1497   }"
1498   [(set_attr "length" "8")]
1499 )
1500
1501 (define_insn "*anddi_sesdi_di"
1502   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1503         (and:DI (sign_extend:DI
1504                  (match_operand:SI 2 "s_register_operand" "r,r"))
1505                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1506   "TARGET_ARM"
1507   "#"
1508   [(set_attr "length" "8")]
1509 )
1510
1511 (define_expand "andsi3"
1512   [(set (match_operand:SI         0 "s_register_operand" "")
1513         (and:SI (match_operand:SI 1 "s_register_operand" "")
1514                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1515   "TARGET_EITHER"
1516   "
1517   if (TARGET_ARM)
1518     {
1519       if (GET_CODE (operands[2]) == CONST_INT)
1520         {
1521           arm_split_constant (AND, SImode, NULL_RTX,
1522                               INTVAL (operands[2]), operands[0],
1523                               operands[1], optimize && !no_new_pseudos);
1524
1525           DONE;
1526         }
1527     }
1528   else /* TARGET_THUMB */
1529     {
1530       if (GET_CODE (operands[2]) != CONST_INT)
1531         operands[2] = force_reg (SImode, operands[2]);
1532       else
1533         {
1534           int i;
1535           
1536           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1537             {
1538               operands[2] = force_reg (SImode,
1539                                        GEN_INT (~INTVAL (operands[2])));
1540               
1541               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1542               
1543               DONE;
1544             }
1545
1546           for (i = 9; i <= 31; i++)
1547             {
1548               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1549                 {
1550                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1551                                         const0_rtx));
1552                   DONE;
1553                 }
1554               else if ((((HOST_WIDE_INT) 1) << i) - 1
1555                        == ~INTVAL (operands[2]))
1556                 {
1557                   rtx shift = GEN_INT (i);
1558                   rtx reg = gen_reg_rtx (SImode);
1559                 
1560                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1561                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1562                   
1563                   DONE;
1564                 }
1565             }
1566
1567           operands[2] = force_reg (SImode, operands[2]);
1568         }
1569     }
1570   "
1571 )
1572
1573 (define_insn_and_split "*arm_andsi3_insn"
1574   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1575         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1576                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1577   "TARGET_ARM"
1578   "@
1579    and%?\\t%0, %1, %2
1580    bic%?\\t%0, %1, #%B2
1581    #"
1582   "TARGET_ARM
1583    && GET_CODE (operands[2]) == CONST_INT
1584    && !(const_ok_for_arm (INTVAL (operands[2]))
1585         || const_ok_for_arm (~INTVAL (operands[2])))"
1586   [(clobber (const_int 0))]
1587   "
1588   arm_split_constant  (AND, SImode, curr_insn, 
1589                        INTVAL (operands[2]), operands[0], operands[1], 0);
1590   DONE;
1591   "
1592   [(set_attr "length" "4,4,16")
1593    (set_attr "predicable" "yes")]
1594 )
1595
1596 (define_insn "*thumb_andsi3_insn"
1597   [(set (match_operand:SI         0 "register_operand" "=l")
1598         (and:SI (match_operand:SI 1 "register_operand" "%0")
1599                 (match_operand:SI 2 "register_operand" "l")))]
1600   "TARGET_THUMB"
1601   "and\\t%0, %0, %2"
1602   [(set_attr "length" "2")]
1603 )
1604
1605 (define_insn "*andsi3_compare0"
1606   [(set (reg:CC_NOOV CC_REGNUM)
1607         (compare:CC_NOOV
1608          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1609                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1610          (const_int 0)))
1611    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1612         (and:SI (match_dup 1) (match_dup 2)))]
1613   "TARGET_ARM"
1614   "@
1615    and%?s\\t%0, %1, %2
1616    bic%?s\\t%0, %1, #%B2"
1617   [(set_attr "conds" "set")]
1618 )
1619
1620 (define_insn "*andsi3_compare0_scratch"
1621   [(set (reg:CC_NOOV CC_REGNUM)
1622         (compare:CC_NOOV
1623          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1624                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1625          (const_int 0)))
1626    (clobber (match_scratch:SI 2 "=X,r"))]
1627   "TARGET_ARM"
1628   "@
1629    tst%?\\t%0, %1
1630    bic%?s\\t%2, %0, #%B1"
1631   [(set_attr "conds" "set")]
1632 )
1633
1634 (define_insn "*zeroextractsi_compare0_scratch"
1635   [(set (reg:CC_NOOV CC_REGNUM)
1636         (compare:CC_NOOV (zero_extract:SI
1637                           (match_operand:SI 0 "s_register_operand" "r")
1638                           (match_operand 1 "const_int_operand" "n")
1639                           (match_operand 2 "const_int_operand" "n"))
1640                          (const_int 0)))]
1641   "TARGET_ARM
1642   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1643       && INTVAL (operands[1]) > 0 
1644       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1645       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1646   "*
1647   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1648                          << INTVAL (operands[2]));
1649   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1650   return \"\";
1651   "
1652   [(set_attr "conds" "set")]
1653 )
1654
1655 (define_insn_and_split "*ne_zeroextractsi"
1656   [(set (match_operand:SI 0 "s_register_operand" "=r")
1657         (ne:SI (zero_extract:SI
1658                 (match_operand:SI 1 "s_register_operand" "r")
1659                 (match_operand:SI 2 "const_int_operand" "n")
1660                 (match_operand:SI 3 "const_int_operand" "n"))
1661                (const_int 0)))
1662    (clobber (reg:CC CC_REGNUM))]
1663   "TARGET_ARM
1664    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1665        && INTVAL (operands[2]) > 0 
1666        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1667        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1668   "#"
1669   "TARGET_ARM
1670    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1671        && INTVAL (operands[2]) > 0 
1672        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1673        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1674   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1675                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1676                                     (const_int 0)))
1677               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1678    (set (match_dup 0)
1679         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1680                          (match_dup 0) (const_int 1)))]
1681   "
1682   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1683                          << INTVAL (operands[3])); 
1684   "
1685   [(set_attr "conds" "clob")
1686    (set_attr "length" "8")]
1687 )
1688
1689 (define_insn_and_split "*ne_zeroextractsi_shifted"
1690   [(set (match_operand:SI 0 "s_register_operand" "=r")
1691         (ne:SI (zero_extract:SI
1692                 (match_operand:SI 1 "s_register_operand" "r")
1693                 (match_operand:SI 2 "const_int_operand" "n")
1694                 (const_int 0))
1695                (const_int 0)))
1696    (clobber (reg:CC CC_REGNUM))]
1697   "TARGET_ARM"
1698   "#"
1699   "TARGET_ARM"
1700   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1701                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1702                                     (const_int 0)))
1703               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1704    (set (match_dup 0)
1705         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1706                          (match_dup 0) (const_int 1)))]
1707   "
1708   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1709   "
1710   [(set_attr "conds" "clob")
1711    (set_attr "length" "8")]
1712 )
1713
1714 (define_insn_and_split "*ite_ne_zeroextractsi"
1715   [(set (match_operand:SI 0 "s_register_operand" "=r")
1716         (if_then_else:SI (ne (zero_extract:SI
1717                               (match_operand:SI 1 "s_register_operand" "r")
1718                               (match_operand:SI 2 "const_int_operand" "n")
1719                               (match_operand:SI 3 "const_int_operand" "n"))
1720                              (const_int 0))
1721                          (match_operand:SI 4 "arm_not_operand" "rIK")
1722                          (const_int 0)))
1723    (clobber (reg:CC CC_REGNUM))]
1724   "TARGET_ARM
1725    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1726        && INTVAL (operands[2]) > 0 
1727        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1728        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1729    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1730   "#"
1731   "TARGET_ARM
1732    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1733        && INTVAL (operands[2]) > 0 
1734        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1735        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1736    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1737   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1738                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1739                                     (const_int 0)))
1740               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1741    (set (match_dup 0)
1742         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1743                          (match_dup 0) (match_dup 4)))]
1744   "
1745   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1746                          << INTVAL (operands[3])); 
1747   "
1748   [(set_attr "conds" "clob")
1749    (set_attr "length" "8")]
1750 )
1751
1752 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1753   [(set (match_operand:SI 0 "s_register_operand" "=r")
1754         (if_then_else:SI (ne (zero_extract:SI
1755                               (match_operand:SI 1 "s_register_operand" "r")
1756                               (match_operand:SI 2 "const_int_operand" "n")
1757                               (const_int 0))
1758                              (const_int 0))
1759                          (match_operand:SI 3 "arm_not_operand" "rIK")
1760                          (const_int 0)))
1761    (clobber (reg:CC CC_REGNUM))]
1762   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1763   "#"
1764   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1765   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1766                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1767                                     (const_int 0)))
1768               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1769    (set (match_dup 0)
1770         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1771                          (match_dup 0) (match_dup 3)))]
1772   "
1773   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1774   "
1775   [(set_attr "conds" "clob")
1776    (set_attr "length" "8")]
1777 )
1778
1779 (define_split
1780   [(set (match_operand:SI 0 "s_register_operand" "")
1781         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1782                          (match_operand:SI 2 "const_int_operand" "")
1783                          (match_operand:SI 3 "const_int_operand" "")))
1784    (clobber (match_operand:SI 4 "s_register_operand" ""))]
1785   "TARGET_THUMB"
1786   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1787    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1788   "{
1789      HOST_WIDE_INT temp = INTVAL (operands[2]);
1790
1791      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1792      operands[3] = GEN_INT (32 - temp);
1793    }"
1794 )
1795
1796 (define_split
1797   [(set (match_operand:SI 0 "s_register_operand" "")
1798         (match_operator:SI 1 "shiftable_operator"
1799          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1800                            (match_operand:SI 3 "const_int_operand" "")
1801                            (match_operand:SI 4 "const_int_operand" ""))
1802           (match_operand:SI 5 "s_register_operand" "")]))
1803    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1804   "TARGET_ARM"
1805   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1806    (set (match_dup 0)
1807         (match_op_dup 1
1808          [(lshiftrt:SI (match_dup 6) (match_dup 4))
1809           (match_dup 5)]))]
1810   "{
1811      HOST_WIDE_INT temp = INTVAL (operands[3]);
1812
1813      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1814      operands[4] = GEN_INT (32 - temp);
1815    }"
1816 )
1817   
1818 (define_split
1819   [(set (match_operand:SI 0 "s_register_operand" "")
1820         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1821                          (match_operand:SI 2 "const_int_operand" "")
1822                          (match_operand:SI 3 "const_int_operand" "")))]
1823   "TARGET_THUMB"
1824   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1825    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1826   "{
1827      HOST_WIDE_INT temp = INTVAL (operands[2]);
1828
1829      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1830      operands[3] = GEN_INT (32 - temp);
1831    }"
1832 )
1833
1834 (define_split
1835   [(set (match_operand:SI 0 "s_register_operand" "")
1836         (match_operator:SI 1 "shiftable_operator"
1837          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1838                            (match_operand:SI 3 "const_int_operand" "")
1839                            (match_operand:SI 4 "const_int_operand" ""))
1840           (match_operand:SI 5 "s_register_operand" "")]))
1841    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1842   "TARGET_ARM"
1843   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1844    (set (match_dup 0)
1845         (match_op_dup 1
1846          [(ashiftrt:SI (match_dup 6) (match_dup 4))
1847           (match_dup 5)]))]
1848   "{
1849      HOST_WIDE_INT temp = INTVAL (operands[3]);
1850
1851      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1852      operands[4] = GEN_INT (32 - temp);
1853    }"
1854 )
1855   
1856 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1857 ;;; represented by the bitfield, then this will produce incorrect results.
1858 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1859 ;;; which have a real bit-field insert instruction, the truncation happens
1860 ;;; in the bit-field insert instruction itself.  Since arm does not have a
1861 ;;; bit-field insert instruction, we would have to emit code here to truncate
1862 ;;; the value before we insert.  This loses some of the advantage of having
1863 ;;; this insv pattern, so this pattern needs to be reevalutated.
1864
1865 (define_expand "insv"
1866   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1867                          (match_operand:SI 1 "general_operand" "")
1868                          (match_operand:SI 2 "general_operand" ""))
1869         (match_operand:SI 3 "reg_or_int_operand" ""))]
1870   "TARGET_ARM"
1871   "
1872   {
1873     int start_bit = INTVAL (operands[2]);
1874     int width = INTVAL (operands[1]);
1875     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1876     rtx target, subtarget;
1877
1878     target = operands[0];
1879     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1880        subreg as the final target.  */
1881     if (GET_CODE (target) == SUBREG)
1882       {
1883         subtarget = gen_reg_rtx (SImode);
1884         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1885             < GET_MODE_SIZE (SImode))
1886           target = SUBREG_REG (target);
1887       }
1888     else
1889       subtarget = target;    
1890
1891     if (GET_CODE (operands[3]) == CONST_INT)
1892       {
1893         /* Since we are inserting a known constant, we may be able to
1894            reduce the number of bits that we have to clear so that
1895            the mask becomes simple.  */
1896         /* ??? This code does not check to see if the new mask is actually
1897            simpler.  It may not be.  */
1898         rtx op1 = gen_reg_rtx (SImode);
1899         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1900            start of this pattern.  */
1901         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1902         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1903
1904         emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1905         emit_insn (gen_iorsi3 (subtarget, op1,
1906                                gen_int_mode (op3_value << start_bit, SImode)));
1907       }
1908     else if (start_bit == 0
1909              && !(const_ok_for_arm (mask)
1910                   || const_ok_for_arm (~mask)))
1911       {
1912         /* A Trick, since we are setting the bottom bits in the word,
1913            we can shift operand[3] up, operand[0] down, OR them together
1914            and rotate the result back again.  This takes 3 insns, and
1915            the third might be mergeable into another op.  */
1916         /* The shift up copes with the possibility that operand[3] is
1917            wider than the bitfield.  */
1918         rtx op0 = gen_reg_rtx (SImode);
1919         rtx op1 = gen_reg_rtx (SImode);
1920
1921         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1922         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1923         emit_insn (gen_iorsi3  (op1, op1, op0));
1924         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1925       }
1926     else if ((width + start_bit == 32)
1927              && !(const_ok_for_arm (mask)
1928                   || const_ok_for_arm (~mask)))
1929       {
1930         /* Similar trick, but slightly less efficient.  */
1931
1932         rtx op0 = gen_reg_rtx (SImode);
1933         rtx op1 = gen_reg_rtx (SImode);
1934
1935         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1936         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1937         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1938         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1939       }
1940     else
1941       {
1942         rtx op0 = GEN_INT (mask);
1943         rtx op1 = gen_reg_rtx (SImode);
1944         rtx op2 = gen_reg_rtx (SImode);
1945
1946         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1947           {
1948             rtx tmp = gen_reg_rtx (SImode);
1949
1950             emit_insn (gen_movsi (tmp, op0));
1951             op0 = tmp;
1952           }
1953
1954         /* Mask out any bits in operand[3] that are not needed.  */
1955            emit_insn (gen_andsi3 (op1, operands[3], op0));
1956
1957         if (GET_CODE (op0) == CONST_INT
1958             && (const_ok_for_arm (mask << start_bit)
1959                 || const_ok_for_arm (~(mask << start_bit))))
1960           {
1961             op0 = GEN_INT (~(mask << start_bit));
1962             emit_insn (gen_andsi3 (op2, operands[0], op0));
1963           }
1964         else
1965           {
1966             if (GET_CODE (op0) == CONST_INT)
1967               {
1968                 rtx tmp = gen_reg_rtx (SImode);
1969
1970                 emit_insn (gen_movsi (tmp, op0));
1971                 op0 = tmp;
1972               }
1973
1974             if (start_bit != 0)
1975               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1976             
1977             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1978           }
1979
1980         if (start_bit != 0)
1981           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1982
1983         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1984       }
1985
1986     if (subtarget != target)
1987       {
1988         /* If TARGET is still a SUBREG, then it must be wider than a word,
1989            so we must be careful only to set the subword we were asked to.  */
1990         if (GET_CODE (target) == SUBREG)
1991           emit_move_insn (target, subtarget);
1992         else
1993           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1994       }
1995
1996     DONE;
1997   }"
1998 )
1999
2000 ; constants for op 2 will never be given to these patterns.
2001 (define_insn_and_split "*anddi_notdi_di"
2002   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2003         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2004                 (match_operand:DI 2 "s_register_operand" "0,r")))]
2005   "TARGET_ARM"
2006   "#"
2007   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2008   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2009    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2010   "
2011   {
2012     operands[3] = gen_highpart (SImode, operands[0]);
2013     operands[0] = gen_lowpart (SImode, operands[0]);
2014     operands[4] = gen_highpart (SImode, operands[1]);
2015     operands[1] = gen_lowpart (SImode, operands[1]);
2016     operands[5] = gen_highpart (SImode, operands[2]);
2017     operands[2] = gen_lowpart (SImode, operands[2]);
2018   }"
2019   [(set_attr "length" "8")
2020    (set_attr "predicable" "yes")]
2021 )
2022   
2023 (define_insn_and_split "*anddi_notzesidi_di"
2024   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2025         (and:DI (not:DI (zero_extend:DI
2026                          (match_operand:SI 2 "s_register_operand" "r,r")))
2027                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2028   "TARGET_ARM"
2029   "@
2030    bic%?\\t%Q0, %Q1, %2
2031    #"
2032   ; (not (zero_extend ...)) allows us to just copy the high word from
2033   ; operand1 to operand0.
2034   "TARGET_ARM
2035    && reload_completed
2036    && operands[0] != operands[1]"
2037   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2038    (set (match_dup 3) (match_dup 4))]
2039   "
2040   {
2041     operands[3] = gen_highpart (SImode, operands[0]);
2042     operands[0] = gen_lowpart (SImode, operands[0]);
2043     operands[4] = gen_highpart (SImode, operands[1]);
2044     operands[1] = gen_lowpart (SImode, operands[1]);
2045   }"
2046   [(set_attr "length" "4,8")
2047    (set_attr "predicable" "yes")]
2048 )
2049   
2050 (define_insn_and_split "*anddi_notsesidi_di"
2051   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2052         (and:DI (not:DI (sign_extend:DI
2053                          (match_operand:SI 2 "s_register_operand" "r,r")))
2054                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2055   "TARGET_ARM"
2056   "#"
2057   "TARGET_ARM && reload_completed"
2058   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2059    (set (match_dup 3) (and:SI (not:SI
2060                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2061                                (match_dup 4)))]
2062   "
2063   {
2064     operands[3] = gen_highpart (SImode, operands[0]);
2065     operands[0] = gen_lowpart (SImode, operands[0]);
2066     operands[4] = gen_highpart (SImode, operands[1]);
2067     operands[1] = gen_lowpart (SImode, operands[1]);
2068   }"
2069   [(set_attr "length" "8")
2070    (set_attr "predicable" "yes")]
2071 )
2072   
2073 (define_insn "andsi_notsi_si"
2074   [(set (match_operand:SI 0 "s_register_operand" "=r")
2075         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2076                 (match_operand:SI 1 "s_register_operand" "r")))]
2077   "TARGET_ARM"
2078   "bic%?\\t%0, %1, %2"
2079   [(set_attr "predicable" "yes")]
2080 )
2081
2082 (define_insn "bicsi3"
2083   [(set (match_operand:SI                 0 "register_operand" "=l")
2084         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2085                 (match_operand:SI         2 "register_operand" "0")))]
2086   "TARGET_THUMB"
2087   "bic\\t%0, %0, %1"
2088   [(set_attr "length" "2")]
2089 )
2090
2091 (define_insn "andsi_not_shiftsi_si"
2092   [(set (match_operand:SI 0 "s_register_operand" "=r")
2093         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2094                          [(match_operand:SI 2 "s_register_operand" "r")
2095                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2096                 (match_operand:SI 1 "s_register_operand" "r")))]
2097   "TARGET_ARM"
2098   "bic%?\\t%0, %1, %2%S4"
2099   [(set_attr "predicable" "yes")
2100    (set_attr "shift" "2")
2101    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2102                       (const_string "alu_shift")
2103                       (const_string "alu_shift_reg")))]
2104 )
2105
2106 (define_insn "*andsi_notsi_si_compare0"
2107   [(set (reg:CC_NOOV CC_REGNUM)
2108         (compare:CC_NOOV
2109          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2110                  (match_operand:SI 1 "s_register_operand" "r"))
2111          (const_int 0)))
2112    (set (match_operand:SI 0 "s_register_operand" "=r")
2113         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2114   "TARGET_ARM"
2115   "bic%?s\\t%0, %1, %2"
2116   [(set_attr "conds" "set")]
2117 )
2118
2119 (define_insn "*andsi_notsi_si_compare0_scratch"
2120   [(set (reg:CC_NOOV CC_REGNUM)
2121         (compare:CC_NOOV
2122          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2123                  (match_operand:SI 1 "s_register_operand" "r"))
2124          (const_int 0)))
2125    (clobber (match_scratch:SI 0 "=r"))]
2126   "TARGET_ARM"
2127   "bic%?s\\t%0, %1, %2"
2128   [(set_attr "conds" "set")]
2129 )
2130
2131 (define_insn "iordi3"
2132   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2133         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2134                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2135   "TARGET_ARM && ! TARGET_IWMMXT"
2136   "#"
2137   [(set_attr "length" "8")
2138    (set_attr "predicable" "yes")]
2139 )
2140
2141 (define_insn "*iordi_zesidi_di"
2142   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2143         (ior:DI (zero_extend:DI
2144                  (match_operand:SI 2 "s_register_operand" "r,r"))
2145                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2146   "TARGET_ARM"
2147   "@
2148    orr%?\\t%Q0, %Q1, %2
2149    #"
2150   [(set_attr "length" "4,8")
2151    (set_attr "predicable" "yes")]
2152 )
2153
2154 (define_insn "*iordi_sesidi_di"
2155   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2156         (ior:DI (sign_extend:DI
2157                  (match_operand:SI 2 "s_register_operand" "r,r"))
2158                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2159   "TARGET_ARM"
2160   "#"
2161   [(set_attr "length" "8")
2162    (set_attr "predicable" "yes")]
2163 )
2164
2165 (define_expand "iorsi3"
2166   [(set (match_operand:SI         0 "s_register_operand" "")
2167         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2168                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2169   "TARGET_EITHER"
2170   "
2171   if (GET_CODE (operands[2]) == CONST_INT)
2172     {
2173       if (TARGET_ARM)
2174         {
2175           arm_split_constant (IOR, SImode, NULL_RTX,
2176                               INTVAL (operands[2]), operands[0], operands[1],
2177                               optimize && !no_new_pseudos);
2178           DONE;
2179         }
2180       else /* TARGET_THUMB */
2181         operands [2] = force_reg (SImode, operands [2]);
2182     }
2183   "
2184 )
2185
2186 (define_insn_and_split "*arm_iorsi3"
2187   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2188         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2189                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2190   "TARGET_ARM"
2191   "@
2192    orr%?\\t%0, %1, %2
2193    #"
2194   "TARGET_ARM
2195    && GET_CODE (operands[2]) == CONST_INT
2196    && !const_ok_for_arm (INTVAL (operands[2]))"
2197   [(clobber (const_int 0))]
2198   "
2199   arm_split_constant (IOR, SImode, curr_insn, 
2200                       INTVAL (operands[2]), operands[0], operands[1], 0);
2201   DONE;
2202   "
2203   [(set_attr "length" "4,16")
2204    (set_attr "predicable" "yes")]
2205 )
2206
2207 (define_insn "*thumb_iorsi3"
2208   [(set (match_operand:SI         0 "register_operand" "=l")
2209         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2210                 (match_operand:SI 2 "register_operand" "l")))]
2211   "TARGET_THUMB"
2212   "orr\\t%0, %0, %2"
2213   [(set_attr "length" "2")]
2214 )
2215
2216 (define_peephole2
2217   [(match_scratch:SI 3 "r")
2218    (set (match_operand:SI 0 "arm_general_register_operand" "")
2219         (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2220                 (match_operand:SI 2 "const_int_operand" "")))]
2221   "TARGET_ARM
2222    && !const_ok_for_arm (INTVAL (operands[2]))
2223    && const_ok_for_arm (~INTVAL (operands[2]))"
2224   [(set (match_dup 3) (match_dup 2))
2225    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2226   ""
2227 )
2228
2229 (define_insn "*iorsi3_compare0"
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    (set (match_operand:SI 0 "s_register_operand" "=r")
2235         (ior:SI (match_dup 1) (match_dup 2)))]
2236   "TARGET_ARM"
2237   "orr%?s\\t%0, %1, %2"
2238   [(set_attr "conds" "set")]
2239 )
2240
2241 (define_insn "*iorsi3_compare0_scratch"
2242   [(set (reg:CC_NOOV CC_REGNUM)
2243         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2244                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2245                          (const_int 0)))
2246    (clobber (match_scratch:SI 0 "=r"))]
2247   "TARGET_ARM"
2248   "orr%?s\\t%0, %1, %2"
2249   [(set_attr "conds" "set")]
2250 )
2251
2252 (define_insn "xordi3"
2253   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2254         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2255                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2256   "TARGET_ARM && !TARGET_IWMMXT"
2257   "#"
2258   [(set_attr "length" "8")
2259    (set_attr "predicable" "yes")]
2260 )
2261
2262 (define_insn "*xordi_zesidi_di"
2263   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2264         (xor:DI (zero_extend:DI
2265                  (match_operand:SI 2 "s_register_operand" "r,r"))
2266                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2267   "TARGET_ARM"
2268   "@
2269    eor%?\\t%Q0, %Q1, %2
2270    #"
2271   [(set_attr "length" "4,8")
2272    (set_attr "predicable" "yes")]
2273 )
2274
2275 (define_insn "*xordi_sesidi_di"
2276   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2277         (xor:DI (sign_extend:DI
2278                  (match_operand:SI 2 "s_register_operand" "r,r"))
2279                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2280   "TARGET_ARM"
2281   "#"
2282   [(set_attr "length" "8")
2283    (set_attr "predicable" "yes")]
2284 )
2285
2286 (define_expand "xorsi3"
2287   [(set (match_operand:SI         0 "s_register_operand" "")
2288         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2289                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2290   "TARGET_EITHER"
2291   "if (TARGET_THUMB)
2292      if (GET_CODE (operands[2]) == CONST_INT)
2293        operands[2] = force_reg (SImode, operands[2]);
2294   "
2295 )
2296
2297 (define_insn "*arm_xorsi3"
2298   [(set (match_operand:SI         0 "s_register_operand" "=r")
2299         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2300                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2301   "TARGET_ARM"
2302   "eor%?\\t%0, %1, %2"
2303   [(set_attr "predicable" "yes")]
2304 )
2305
2306 (define_insn "*thumb_xorsi3"
2307   [(set (match_operand:SI         0 "register_operand" "=l")
2308         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2309                 (match_operand:SI 2 "register_operand" "l")))]
2310   "TARGET_THUMB"
2311   "eor\\t%0, %0, %2"
2312   [(set_attr "length" "2")]
2313 )
2314
2315 (define_insn "*xorsi3_compare0"
2316   [(set (reg:CC_NOOV CC_REGNUM)
2317         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2318                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2319                          (const_int 0)))
2320    (set (match_operand:SI 0 "s_register_operand" "=r")
2321         (xor:SI (match_dup 1) (match_dup 2)))]
2322   "TARGET_ARM"
2323   "eor%?s\\t%0, %1, %2"
2324   [(set_attr "conds" "set")]
2325 )
2326
2327 (define_insn "*xorsi3_compare0_scratch"
2328   [(set (reg:CC_NOOV CC_REGNUM)
2329         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2330                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2331                          (const_int 0)))]
2332   "TARGET_ARM"
2333   "teq%?\\t%0, %1"
2334   [(set_attr "conds" "set")]
2335 )
2336
2337 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2338 ; (NOT D) we can sometimes merge the final NOT into one of the following
2339 ; insns.
2340
2341 (define_split
2342   [(set (match_operand:SI 0 "s_register_operand" "")
2343         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2344                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2345                 (match_operand:SI 3 "arm_rhs_operand" "")))
2346    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2347   "TARGET_ARM"
2348   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2349                               (not:SI (match_dup 3))))
2350    (set (match_dup 0) (not:SI (match_dup 4)))]
2351   ""
2352 )
2353
2354 (define_insn "*andsi_iorsi3_notsi"
2355   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2356         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2357                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2358                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2359   "TARGET_ARM"
2360   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2361   [(set_attr "length" "8")
2362    (set_attr "predicable" "yes")]
2363 )
2364
2365 (define_split
2366   [(set (match_operand:SI 0 "s_register_operand" "")
2367         (match_operator:SI 1 "logical_binary_operator"
2368          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2369                            (match_operand:SI 3 "const_int_operand" "")
2370                            (match_operand:SI 4 "const_int_operand" ""))
2371           (match_operator:SI 9 "logical_binary_operator"
2372            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2373                          (match_operand:SI 6 "const_int_operand" ""))
2374             (match_operand:SI 7 "s_register_operand" "")])]))
2375    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2376   "TARGET_ARM
2377    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2378    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2379   [(set (match_dup 8)
2380         (match_op_dup 1
2381          [(ashift:SI (match_dup 2) (match_dup 4))
2382           (match_dup 5)]))
2383    (set (match_dup 0)
2384         (match_op_dup 1
2385          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2386           (match_dup 7)]))]
2387   "
2388   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2389 ")
2390
2391 (define_split
2392   [(set (match_operand:SI 0 "s_register_operand" "")
2393         (match_operator:SI 1 "logical_binary_operator"
2394          [(match_operator:SI 9 "logical_binary_operator"
2395            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2396                          (match_operand:SI 6 "const_int_operand" ""))
2397             (match_operand:SI 7 "s_register_operand" "")])
2398           (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2399                            (match_operand:SI 3 "const_int_operand" "")
2400                            (match_operand:SI 4 "const_int_operand" ""))]))
2401    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2402   "TARGET_ARM
2403    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2404    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2405   [(set (match_dup 8)
2406         (match_op_dup 1
2407          [(ashift:SI (match_dup 2) (match_dup 4))
2408           (match_dup 5)]))
2409    (set (match_dup 0)
2410         (match_op_dup 1
2411          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2412           (match_dup 7)]))]
2413   "
2414   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2415 ")
2416
2417 (define_split
2418   [(set (match_operand:SI 0 "s_register_operand" "")
2419         (match_operator:SI 1 "logical_binary_operator"
2420          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2421                            (match_operand:SI 3 "const_int_operand" "")
2422                            (match_operand:SI 4 "const_int_operand" ""))
2423           (match_operator:SI 9 "logical_binary_operator"
2424            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2425                          (match_operand:SI 6 "const_int_operand" ""))
2426             (match_operand:SI 7 "s_register_operand" "")])]))
2427    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2428   "TARGET_ARM
2429    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2430    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2431   [(set (match_dup 8)
2432         (match_op_dup 1
2433          [(ashift:SI (match_dup 2) (match_dup 4))
2434           (match_dup 5)]))
2435    (set (match_dup 0)
2436         (match_op_dup 1
2437          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2438           (match_dup 7)]))]
2439   "
2440   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2441 ")
2442
2443 (define_split
2444   [(set (match_operand:SI 0 "s_register_operand" "")
2445         (match_operator:SI 1 "logical_binary_operator"
2446          [(match_operator:SI 9 "logical_binary_operator"
2447            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2448                          (match_operand:SI 6 "const_int_operand" ""))
2449             (match_operand:SI 7 "s_register_operand" "")])
2450           (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2451                            (match_operand:SI 3 "const_int_operand" "")
2452                            (match_operand:SI 4 "const_int_operand" ""))]))
2453    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2454   "TARGET_ARM
2455    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2456    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2457   [(set (match_dup 8)
2458         (match_op_dup 1
2459          [(ashift:SI (match_dup 2) (match_dup 4))
2460           (match_dup 5)]))
2461    (set (match_dup 0)
2462         (match_op_dup 1
2463          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2464           (match_dup 7)]))]
2465   "
2466   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2467 ")
2468 \f
2469
2470 ;; Minimum and maximum insns
2471
2472 (define_insn "smaxsi3"
2473   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2474         (smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2475                  (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2476    (clobber (reg:CC CC_REGNUM))]
2477   "TARGET_ARM"
2478   "@
2479    cmp\\t%1, %2\;movlt\\t%0, %2
2480    cmp\\t%1, %2\;movge\\t%0, %1
2481    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2482   [(set_attr "conds" "clob")
2483    (set_attr "length" "8,8,12")]
2484 )
2485
2486 (define_insn "sminsi3"
2487   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2488         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2489                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2490    (clobber (reg:CC CC_REGNUM))]
2491   "TARGET_ARM"
2492   "@
2493    cmp\\t%1, %2\;movge\\t%0, %2
2494    cmp\\t%1, %2\;movlt\\t%0, %1
2495    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2496   [(set_attr "conds" "clob")
2497    (set_attr "length" "8,8,12")]
2498 )
2499
2500 (define_insn "umaxsi3"
2501   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2502         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2503                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2504    (clobber (reg:CC CC_REGNUM))]
2505   "TARGET_ARM"
2506   "@
2507    cmp\\t%1, %2\;movcc\\t%0, %2
2508    cmp\\t%1, %2\;movcs\\t%0, %1
2509    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2510   [(set_attr "conds" "clob")
2511    (set_attr "length" "8,8,12")]
2512 )
2513
2514 (define_insn "uminsi3"
2515   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2516         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2517                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2518    (clobber (reg:CC CC_REGNUM))]
2519   "TARGET_ARM"
2520   "@
2521    cmp\\t%1, %2\;movcs\\t%0, %2
2522    cmp\\t%1, %2\;movcc\\t%0, %1
2523    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2524   [(set_attr "conds" "clob")
2525    (set_attr "length" "8,8,12")]
2526 )
2527
2528 (define_insn "*store_minmaxsi"
2529   [(set (match_operand:SI 0 "memory_operand" "=m")
2530         (match_operator:SI 3 "minmax_operator"
2531          [(match_operand:SI 1 "s_register_operand" "r")
2532           (match_operand:SI 2 "s_register_operand" "r")]))
2533    (clobber (reg:CC CC_REGNUM))]
2534   "TARGET_ARM"
2535   "*
2536   operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2537                                 operands[1], operands[2]);
2538   output_asm_insn (\"cmp\\t%1, %2\", operands);
2539   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2540   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2541   return \"\";
2542   "
2543   [(set_attr "conds" "clob")
2544    (set_attr "length" "12")
2545    (set_attr "type" "store1")]
2546 )
2547
2548 ; Reject the frame pointer in operand[1], since reloading this after
2549 ; it has been eliminated can cause carnage.
2550 (define_insn "*minmax_arithsi"
2551   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2552         (match_operator:SI 4 "shiftable_operator"
2553          [(match_operator:SI 5 "minmax_operator"
2554            [(match_operand:SI 2 "s_register_operand" "r,r")
2555             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2556           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2557    (clobber (reg:CC CC_REGNUM))]
2558   "TARGET_ARM && !arm_eliminable_register (operands[1])"
2559   "*
2560   {
2561     enum rtx_code code = GET_CODE (operands[4]);
2562
2563     operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2564                                   operands[2], operands[3]);
2565     output_asm_insn (\"cmp\\t%2, %3\", operands);
2566     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2567     if (which_alternative != 0 || operands[3] != const0_rtx
2568         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2569       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2570     return \"\";
2571   }"
2572   [(set_attr "conds" "clob")
2573    (set_attr "length" "12")]
2574 )
2575
2576 \f
2577 ;; Shift and rotation insns
2578
2579 (define_expand "ashldi3"
2580   [(set (match_operand:DI            0 "s_register_operand" "")
2581         (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2582                    (match_operand:SI 2 "reg_or_int_operand" "")))]
2583   "TARGET_ARM"
2584   "
2585   if (GET_CODE (operands[2]) == CONST_INT)
2586     {
2587       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2588         {
2589           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2590           DONE;
2591         }
2592         /* Ideally we shouldn't fail here if we could know that operands[1] 
2593            ends up already living in an iwmmxt register. Otherwise it's
2594            cheaper to have the alternate code being generated than moving
2595            values to iwmmxt regs and back.  */
2596         FAIL;
2597     }
2598   else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2599     FAIL;
2600   "
2601 )
2602
2603 (define_insn "arm_ashldi3_1bit"
2604   [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
2605         (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2606                    (const_int 1)))
2607    (clobber (reg:CC CC_REGNUM))]
2608   "TARGET_ARM"
2609   "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2610   [(set_attr "conds" "clob")
2611    (set_attr "length" "8")]
2612 )
2613
2614 (define_expand "ashlsi3"
2615   [(set (match_operand:SI            0 "s_register_operand" "")
2616         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2617                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2618   "TARGET_EITHER"
2619   "
2620   if (GET_CODE (operands[2]) == CONST_INT
2621       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2622     {
2623       emit_insn (gen_movsi (operands[0], const0_rtx));
2624       DONE;
2625     }
2626   "
2627 )
2628
2629 (define_insn "*thumb_ashlsi3"
2630   [(set (match_operand:SI            0 "register_operand" "=l,l")
2631         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2632                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2633   "TARGET_THUMB"
2634   "lsl\\t%0, %1, %2"
2635   [(set_attr "length" "2")]
2636 )
2637
2638 (define_expand "ashrdi3"
2639   [(set (match_operand:DI              0 "s_register_operand" "")
2640         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2641                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2642   "TARGET_ARM"
2643   "
2644   if (GET_CODE (operands[2]) == CONST_INT)
2645     {
2646       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2647         {
2648           emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2649           DONE;
2650         }
2651         /* Ideally we shouldn't fail here if we could know that operands[1] 
2652            ends up already living in an iwmmxt register. Otherwise it's
2653            cheaper to have the alternate code being generated than moving
2654            values to iwmmxt regs and back.  */
2655         FAIL;
2656     }
2657   else if (!TARGET_REALLY_IWMMXT)
2658     FAIL;
2659   "
2660 )
2661
2662 (define_insn "arm_ashrdi3_1bit"
2663   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2664         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2665                      (const_int 1)))
2666    (clobber (reg:CC CC_REGNUM))]
2667   "TARGET_ARM"
2668   "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2669   [(set_attr "conds" "clob")
2670    (set_attr "length" "8")]
2671 )
2672
2673 (define_expand "ashrsi3"
2674   [(set (match_operand:SI              0 "s_register_operand" "")
2675         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2676                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2677   "TARGET_EITHER"
2678   "
2679   if (GET_CODE (operands[2]) == CONST_INT
2680       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2681     operands[2] = GEN_INT (31);
2682   "
2683 )
2684
2685 (define_insn "*thumb_ashrsi3"
2686   [(set (match_operand:SI              0 "register_operand" "=l,l")
2687         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2688                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2689   "TARGET_THUMB"
2690   "asr\\t%0, %1, %2"
2691   [(set_attr "length" "2")]
2692 )
2693
2694 (define_expand "lshrdi3"
2695   [(set (match_operand:DI              0 "s_register_operand" "")
2696         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2697                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2698   "TARGET_ARM"
2699   "
2700   if (GET_CODE (operands[2]) == CONST_INT)
2701     {
2702       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2703         {
2704           emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2705           DONE;
2706         }
2707         /* Ideally we shouldn't fail here if we could know that operands[1] 
2708            ends up already living in an iwmmxt register. Otherwise it's
2709            cheaper to have the alternate code being generated than moving
2710            values to iwmmxt regs and back.  */
2711         FAIL;
2712     }
2713   else if (!TARGET_REALLY_IWMMXT)
2714     FAIL;
2715   "
2716 )
2717
2718 (define_insn "arm_lshrdi3_1bit"
2719   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2720         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2721                      (const_int 1)))
2722    (clobber (reg:CC CC_REGNUM))]
2723   "TARGET_ARM"
2724   "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2725   [(set_attr "conds" "clob")
2726    (set_attr "length" "8")]
2727 )
2728
2729 (define_expand "lshrsi3"
2730   [(set (match_operand:SI              0 "s_register_operand" "")
2731         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2732                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2733   "TARGET_EITHER"
2734   "
2735   if (GET_CODE (operands[2]) == CONST_INT
2736       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2737     {
2738       emit_insn (gen_movsi (operands[0], const0_rtx));
2739       DONE;
2740     }
2741   "
2742 )
2743
2744 (define_insn "*thumb_lshrsi3"
2745   [(set (match_operand:SI              0 "register_operand" "=l,l")
2746         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2747                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2748   "TARGET_THUMB"
2749   "lsr\\t%0, %1, %2"
2750   [(set_attr "length" "2")]
2751 )
2752
2753 (define_expand "rotlsi3"
2754   [(set (match_operand:SI              0 "s_register_operand" "")
2755         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2756                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2757   "TARGET_ARM"
2758   "
2759   if (GET_CODE (operands[2]) == CONST_INT)
2760     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2761   else
2762     {
2763       rtx reg = gen_reg_rtx (SImode);
2764       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2765       operands[2] = reg;
2766     }
2767   "
2768 )
2769
2770 (define_expand "rotrsi3"
2771   [(set (match_operand:SI              0 "s_register_operand" "")
2772         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2773                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2774   "TARGET_EITHER"
2775   "
2776   if (TARGET_ARM)
2777     {
2778       if (GET_CODE (operands[2]) == CONST_INT
2779           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2780         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2781     }
2782   else /* TARGET_THUMB */
2783     {
2784       if (GET_CODE (operands [2]) == CONST_INT)
2785         operands [2] = force_reg (SImode, operands[2]);
2786     }
2787   "
2788 )
2789
2790 (define_insn "*thumb_rotrsi3"
2791   [(set (match_operand:SI              0 "register_operand" "=l")
2792         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2793                      (match_operand:SI 2 "register_operand" "l")))]
2794   "TARGET_THUMB"
2795   "ror\\t%0, %0, %2"
2796   [(set_attr "length" "2")]
2797 )
2798
2799 (define_insn "*arm_shiftsi3"
2800   [(set (match_operand:SI   0 "s_register_operand" "=r")
2801         (match_operator:SI  3 "shift_operator"
2802          [(match_operand:SI 1 "s_register_operand"  "r")
2803           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2804   "TARGET_ARM"
2805   "mov%?\\t%0, %1%S3"
2806   [(set_attr "predicable" "yes")
2807    (set_attr "shift" "1")
2808    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2809                       (const_string "alu_shift")
2810                       (const_string "alu_shift_reg")))]
2811 )
2812
2813 (define_insn "*shiftsi3_compare0"
2814   [(set (reg:CC_NOOV CC_REGNUM)
2815         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2816                           [(match_operand:SI 1 "s_register_operand" "r")
2817                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2818                          (const_int 0)))
2819    (set (match_operand:SI 0 "s_register_operand" "=r")
2820         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2821   "TARGET_ARM"
2822   "mov%?s\\t%0, %1%S3"
2823   [(set_attr "conds" "set")
2824    (set_attr "shift" "1")
2825    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2826                       (const_string "alu_shift")
2827                       (const_string "alu_shift_reg")))]
2828 )
2829
2830 (define_insn "*shiftsi3_compare0_scratch"
2831   [(set (reg:CC_NOOV CC_REGNUM)
2832         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2833                           [(match_operand:SI 1 "s_register_operand" "r")
2834                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2835                          (const_int 0)))
2836    (clobber (match_scratch:SI 0 "=r"))]
2837   "TARGET_ARM"
2838   "mov%?s\\t%0, %1%S3"
2839   [(set_attr "conds" "set")
2840    (set_attr "shift" "1")]
2841 )
2842
2843 (define_insn "*notsi_shiftsi"
2844   [(set (match_operand:SI 0 "s_register_operand" "=r")
2845         (not:SI (match_operator:SI 3 "shift_operator"
2846                  [(match_operand:SI 1 "s_register_operand" "r")
2847                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2848   "TARGET_ARM"
2849   "mvn%?\\t%0, %1%S3"
2850   [(set_attr "predicable" "yes")
2851    (set_attr "shift" "1")
2852    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2853                       (const_string "alu_shift")
2854                       (const_string "alu_shift_reg")))]
2855 )
2856
2857 (define_insn "*notsi_shiftsi_compare0"
2858   [(set (reg:CC_NOOV CC_REGNUM)
2859         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2860                           [(match_operand:SI 1 "s_register_operand" "r")
2861                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2862                          (const_int 0)))
2863    (set (match_operand:SI 0 "s_register_operand" "=r")
2864         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2865   "TARGET_ARM"
2866   "mvn%?s\\t%0, %1%S3"
2867   [(set_attr "conds" "set")
2868    (set_attr "shift" "1")
2869    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2870                       (const_string "alu_shift")
2871                       (const_string "alu_shift_reg")))]
2872 )
2873
2874 (define_insn "*not_shiftsi_compare0_scratch"
2875   [(set (reg:CC_NOOV CC_REGNUM)
2876         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2877                           [(match_operand:SI 1 "s_register_operand" "r")
2878                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2879                          (const_int 0)))
2880    (clobber (match_scratch:SI 0 "=r"))]
2881   "TARGET_ARM"
2882   "mvn%?s\\t%0, %1%S3"
2883   [(set_attr "conds" "set")
2884    (set_attr "shift" "1")
2885    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2886                       (const_string "alu_shift")
2887                       (const_string "alu_shift_reg")))]
2888 )
2889
2890 ;; We don't really have extzv, but defining this using shifts helps
2891 ;; to reduce register pressure later on.
2892
2893 (define_expand "extzv"
2894   [(set (match_dup 4)
2895         (ashift:SI (match_operand:SI   1 "register_operand" "")
2896                    (match_operand:SI   2 "const_int_operand" "")))
2897    (set (match_operand:SI              0 "register_operand" "")
2898         (lshiftrt:SI (match_dup 4)
2899                      (match_operand:SI 3 "const_int_operand" "")))]
2900   "TARGET_THUMB"
2901   "
2902   {
2903     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2904     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2905     
2906     operands[3] = GEN_INT (rshift);
2907     
2908     if (lshift == 0)
2909       {
2910         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2911         DONE;
2912       }
2913       
2914     operands[2] = GEN_INT (lshift);
2915     operands[4] = gen_reg_rtx (SImode);
2916   }"
2917 )
2918
2919 \f
2920 ;; Unary arithmetic insns
2921
2922 (define_expand "negdi2"
2923  [(parallel
2924    [(set (match_operand:DI          0 "s_register_operand" "")
2925           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2926     (clobber (reg:CC CC_REGNUM))])]
2927   "TARGET_EITHER"
2928   "
2929   if (TARGET_THUMB)
2930     {
2931       if (GET_CODE (operands[1]) != REG)
2932         operands[1] = force_reg (SImode, operands[1]);
2933      }
2934   "
2935 )
2936
2937 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2938 ;; The second alternative is to allow the common case of a *full* overlap.
2939 (define_insn "*arm_negdi2"
2940   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2941         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2942    (clobber (reg:CC CC_REGNUM))]
2943   "TARGET_ARM"
2944   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2945   [(set_attr "conds" "clob")
2946    (set_attr "length" "8")]
2947 )
2948
2949 (define_insn "*thumb_negdi2"
2950   [(set (match_operand:DI         0 "register_operand" "=&l")
2951         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
2952    (clobber (reg:CC CC_REGNUM))]
2953   "TARGET_THUMB"
2954   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2955   [(set_attr "length" "6")]
2956 )
2957
2958 (define_expand "negsi2"
2959   [(set (match_operand:SI         0 "s_register_operand" "")
2960         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2961   "TARGET_EITHER"
2962   ""
2963 )
2964
2965 (define_insn "*arm_negsi2"
2966   [(set (match_operand:SI         0 "s_register_operand" "=r")
2967         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2968   "TARGET_ARM"
2969   "rsb%?\\t%0, %1, #0"
2970   [(set_attr "predicable" "yes")]
2971 )
2972
2973 (define_insn "*thumb_negsi2"
2974   [(set (match_operand:SI         0 "register_operand" "=l")
2975         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2976   "TARGET_THUMB"
2977   "neg\\t%0, %1"
2978   [(set_attr "length" "2")]
2979 )
2980
2981 (define_expand "negsf2"
2982   [(set (match_operand:SF         0 "s_register_operand" "")
2983         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2984   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
2985   ""
2986 )
2987
2988 (define_expand "negdf2"
2989   [(set (match_operand:DF         0 "s_register_operand" "")
2990         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2991   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
2992   "")
2993
2994 ;; abssi2 doesn't really clobber the condition codes if a different register
2995 ;; is being set.  To keep things simple, assume during rtl manipulations that
2996 ;; it does, but tell the final scan operator the truth.  Similarly for
2997 ;; (neg (abs...))
2998
2999 (define_expand "abssi2"
3000   [(parallel
3001     [(set (match_operand:SI         0 "s_register_operand" "")
3002           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3003      (clobber (reg:CC CC_REGNUM))])]
3004   "TARGET_ARM"
3005   "")
3006
3007 (define_insn "*arm_abssi2"
3008   [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
3009         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3010    (clobber (reg:CC CC_REGNUM))]
3011   "TARGET_ARM"
3012   "@
3013    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3014    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3015   [(set_attr "conds" "clob,*")
3016    (set_attr "shift" "1")
3017    ;; predicable can't be set based on the variant, so left as no
3018    (set_attr "length" "8")]
3019 )
3020
3021 (define_insn "*neg_abssi2"
3022   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3023         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3024    (clobber (reg:CC CC_REGNUM))]
3025   "TARGET_ARM"
3026   "@
3027    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3028    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3029   [(set_attr "conds" "clob,*")
3030    (set_attr "shift" "1")
3031    ;; predicable can't be set based on the variant, so left as no
3032    (set_attr "length" "8")]
3033 )
3034
3035 (define_expand "abssf2"
3036   [(set (match_operand:SF         0 "s_register_operand" "")
3037         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3038   "TARGET_ARM && TARGET_HARD_FLOAT"
3039   "")
3040
3041 (define_expand "absdf2"
3042   [(set (match_operand:DF         0 "s_register_operand" "")
3043         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3044   "TARGET_ARM && TARGET_HARD_FLOAT"
3045   "")
3046
3047 (define_expand "sqrtsf2"
3048   [(set (match_operand:SF 0 "s_register_operand" "")
3049         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3050   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3051   "")
3052
3053 (define_expand "sqrtdf2"
3054   [(set (match_operand:DF 0 "s_register_operand" "")
3055         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3056   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3057   "")
3058
3059 (define_insn_and_split "one_cmpldi2"
3060   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3061         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3062   "TARGET_ARM"
3063   "#"
3064   "TARGET_ARM && reload_completed"
3065   [(set (match_dup 0) (not:SI (match_dup 1)))
3066    (set (match_dup 2) (not:SI (match_dup 3)))]
3067   "
3068   {
3069     operands[2] = gen_highpart (SImode, operands[0]);
3070     operands[0] = gen_lowpart (SImode, operands[0]);
3071     operands[3] = gen_highpart (SImode, operands[1]);
3072     operands[1] = gen_lowpart (SImode, operands[1]);
3073   }"
3074   [(set_attr "length" "8")
3075    (set_attr "predicable" "yes")]
3076 )
3077
3078 (define_expand "one_cmplsi2"
3079   [(set (match_operand:SI         0 "s_register_operand" "")
3080         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3081   "TARGET_EITHER"
3082   ""
3083 )
3084
3085 (define_insn "*arm_one_cmplsi2"
3086   [(set (match_operand:SI         0 "s_register_operand" "=r")
3087         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3088   "TARGET_ARM"
3089   "mvn%?\\t%0, %1"
3090   [(set_attr "predicable" "yes")]
3091 )
3092
3093 (define_insn "*thumb_one_cmplsi2"
3094   [(set (match_operand:SI         0 "register_operand" "=l")
3095         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3096   "TARGET_THUMB"
3097   "mvn\\t%0, %1"
3098   [(set_attr "length" "2")]
3099 )
3100
3101 (define_insn "*notsi_compare0"
3102   [(set (reg:CC_NOOV CC_REGNUM)
3103         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3104                          (const_int 0)))
3105    (set (match_operand:SI 0 "s_register_operand" "=r")
3106         (not:SI (match_dup 1)))]
3107   "TARGET_ARM"
3108   "mvn%?s\\t%0, %1"
3109   [(set_attr "conds" "set")]
3110 )
3111
3112 (define_insn "*notsi_compare0_scratch"
3113   [(set (reg:CC_NOOV CC_REGNUM)
3114         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3115                          (const_int 0)))
3116    (clobber (match_scratch:SI 0 "=r"))]
3117   "TARGET_ARM"
3118   "mvn%?s\\t%0, %1"
3119   [(set_attr "conds" "set")]
3120 )
3121 \f
3122 ;; Fixed <--> Floating conversion insns
3123
3124 (define_expand "floatsisf2"
3125   [(set (match_operand:SF           0 "s_register_operand" "")
3126         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3127   "TARGET_ARM && TARGET_HARD_FLOAT"
3128   "
3129   if (TARGET_MAVERICK)
3130     {
3131       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3132       DONE;
3133     }
3134 ")
3135
3136 (define_expand "floatsidf2"
3137   [(set (match_operand:DF           0 "s_register_operand" "")
3138         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3139   "TARGET_ARM && TARGET_HARD_FLOAT"
3140   "
3141   if (TARGET_MAVERICK)
3142     {
3143       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3144       DONE;
3145     }
3146 ")
3147
3148 (define_expand "fix_truncsfsi2"
3149   [(set (match_operand:SI         0 "s_register_operand" "")
3150         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3151   "TARGET_ARM && TARGET_HARD_FLOAT"
3152   "
3153   if (TARGET_MAVERICK)
3154     {
3155       if (!cirrus_fp_register (operands[0], SImode))
3156         operands[0] = force_reg (SImode, operands[0]);
3157       if (!cirrus_fp_register (operands[1], SFmode))
3158         operands[1] = force_reg (SFmode, operands[0]);
3159       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3160       DONE;
3161     }
3162 ")
3163
3164 (define_expand "fix_truncdfsi2"
3165   [(set (match_operand:SI         0 "s_register_operand" "")
3166         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3167   "TARGET_ARM && TARGET_HARD_FLOAT"
3168   "
3169   if (TARGET_MAVERICK)
3170     {
3171       if (!cirrus_fp_register (operands[1], DFmode))
3172         operands[1] = force_reg (DFmode, operands[0]);
3173       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3174       DONE;
3175     }
3176 ")
3177
3178 ;; Truncation insns
3179
3180 (define_expand "truncdfsf2"
3181   [(set (match_operand:SF  0 "s_register_operand" "")
3182         (float_truncate:SF
3183          (match_operand:DF 1 "s_register_operand" "")))]
3184   "TARGET_ARM && TARGET_HARD_FLOAT"
3185   ""
3186 )
3187 \f
3188 ;; Zero and sign extension instructions.
3189
3190 (define_insn "zero_extendsidi2"
3191   [(set (match_operand:DI 0 "s_register_operand" "=r")
3192         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3193   "TARGET_ARM"
3194   "*
3195     if (REGNO (operands[1])
3196         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3197       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3198     return \"mov%?\\t%R0, #0\";
3199   "
3200   [(set_attr "length" "8")
3201    (set_attr "predicable" "yes")]
3202 )
3203
3204 (define_insn "zero_extendqidi2"
3205   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3206         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3207   "TARGET_ARM"
3208   "@
3209    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3210    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3211   [(set_attr "length" "8")
3212    (set_attr "predicable" "yes")
3213    (set_attr "type" "*,load_byte")
3214    (set_attr "pool_range" "*,4092")
3215    (set_attr "neg_pool_range" "*,4084")]
3216 )
3217
3218 (define_insn "extendsidi2"
3219   [(set (match_operand:DI 0 "s_register_operand" "=r")
3220         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3221   "TARGET_ARM"
3222   "*
3223     if (REGNO (operands[1])
3224         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3225       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3226     return \"mov%?\\t%R0, %Q0, asr #31\";
3227   "
3228   [(set_attr "length" "8")
3229    (set_attr "shift" "1")
3230    (set_attr "predicable" "yes")]
3231 )
3232
3233 (define_expand "zero_extendhisi2"
3234   [(set (match_dup 2)
3235         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3236                    (const_int 16)))
3237    (set (match_operand:SI 0 "s_register_operand" "")
3238         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3239   "TARGET_EITHER"
3240   "
3241   {
3242     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3243       {
3244         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3245                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3246         DONE;
3247       }
3248
3249     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3250       {
3251         emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3252         DONE;
3253       }
3254
3255     if (!s_register_operand (operands[1], HImode))
3256       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3257
3258     if (arm_arch6)
3259       {
3260         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3261                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3262         DONE;
3263       }
3264
3265     operands[1] = gen_lowpart (SImode, operands[1]);
3266     operands[2] = gen_reg_rtx (SImode);
3267   }"
3268 )
3269
3270 (define_insn "*thumb_zero_extendhisi2"
3271   [(set (match_operand:SI 0 "register_operand" "=l")
3272         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3273   "TARGET_THUMB && !arm_arch6"
3274   "*
3275   rtx mem = XEXP (operands[1], 0);
3276
3277   if (GET_CODE (mem) == CONST)
3278     mem = XEXP (mem, 0);
3279     
3280   if (GET_CODE (mem) == LABEL_REF)
3281     return \"ldr\\t%0, %1\";
3282     
3283   if (GET_CODE (mem) == PLUS)
3284     {
3285       rtx a = XEXP (mem, 0);
3286       rtx b = XEXP (mem, 1);
3287
3288       /* This can happen due to bugs in reload.  */
3289       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3290         {
3291           rtx ops[2];
3292           ops[0] = operands[0];
3293           ops[1] = a;
3294       
3295           output_asm_insn (\"mov        %0, %1\", ops);
3296
3297           XEXP (mem, 0) = operands[0];
3298        }
3299
3300       else if (   GET_CODE (a) == LABEL_REF
3301                && GET_CODE (b) == CONST_INT)
3302         return \"ldr\\t%0, %1\";
3303     }
3304     
3305   return \"ldrh\\t%0, %1\";
3306   "
3307   [(set_attr "length" "4")
3308    (set_attr "type" "load_byte")
3309    (set_attr "pool_range" "60")]
3310 )
3311
3312 (define_insn "*thumb_zero_extendhisi2_v6"
3313   [(set (match_operand:SI 0 "register_operand" "=l,l")
3314         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3315   "TARGET_THUMB && arm_arch6"
3316   "*
3317   rtx mem;
3318
3319   if (which_alternative == 0)
3320     return \"uxth\\t%0, %1\";
3321
3322   mem = XEXP (operands[1], 0);
3323
3324   if (GET_CODE (mem) == CONST)
3325     mem = XEXP (mem, 0);
3326     
3327   if (GET_CODE (mem) == LABEL_REF)
3328     return \"ldr\\t%0, %1\";
3329     
3330   if (GET_CODE (mem) == PLUS)
3331     {
3332       rtx a = XEXP (mem, 0);
3333       rtx b = XEXP (mem, 1);
3334
3335       /* This can happen due to bugs in reload.  */
3336       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3337         {
3338           rtx ops[2];
3339           ops[0] = operands[0];
3340           ops[1] = a;
3341       
3342           output_asm_insn (\"mov        %0, %1\", ops);
3343
3344           XEXP (mem, 0) = operands[0];
3345        }
3346
3347       else if (   GET_CODE (a) == LABEL_REF
3348                && GET_CODE (b) == CONST_INT)
3349         return \"ldr\\t%0, %1\";
3350     }
3351     
3352   return \"ldrh\\t%0, %1\";
3353   "
3354   [(set_attr "length" "2,4")
3355    (set_attr "type" "alu_shift,load_byte")
3356    (set_attr "pool_range" "*,60")]
3357 )
3358
3359 (define_insn "*arm_zero_extendhisi2"
3360   [(set (match_operand:SI 0 "s_register_operand" "=r")
3361         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3362   "TARGET_ARM && arm_arch4 && !arm_arch6"
3363   "ldr%?h\\t%0, %1"
3364   [(set_attr "type" "load_byte")
3365    (set_attr "predicable" "yes")
3366    (set_attr "pool_range" "256")
3367    (set_attr "neg_pool_range" "244")]
3368 )
3369
3370 (define_insn "*arm_zero_extendhisi2_v6"
3371   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3372         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3373   "TARGET_ARM && arm_arch6"
3374   "@
3375    uxth%?\\t%0, %1
3376    ldr%?h\\t%0, %1"
3377   [(set_attr "type" "alu_shift,load_byte")
3378    (set_attr "predicable" "yes")
3379    (set_attr "pool_range" "*,256")
3380    (set_attr "neg_pool_range" "*,244")]
3381 )
3382
3383 (define_insn "*arm_zero_extendhisi2addsi"
3384   [(set (match_operand:SI 0 "s_register_operand" "=r")
3385         (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3386                  (match_operand:SI 2 "s_register_operand" "r")))]
3387   "TARGET_ARM && arm_arch6"
3388   "uxtah%?\\t%0, %2, %1"
3389   [(set_attr "type" "alu_shift")
3390    (set_attr "predicable" "yes")]
3391 )
3392
3393 (define_split
3394   [(set (match_operand:SI 0 "s_register_operand" "")
3395         (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3396    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3397   "TARGET_ARM && (!arm_arch4)"
3398   [(set (match_dup 2) (match_dup 1))
3399    (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3400   "
3401   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3402     FAIL;
3403   "
3404 )
3405
3406 (define_split
3407   [(set (match_operand:SI 0 "s_register_operand" "")
3408         (match_operator:SI 3 "shiftable_operator"
3409          [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3410           (match_operand:SI 4 "s_register_operand" "")]))
3411    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3412   "TARGET_ARM && (!arm_arch4)"
3413   [(set (match_dup 2) (match_dup 1))
3414    (set (match_dup 0)
3415         (match_op_dup 3
3416          [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3417   "
3418   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3419     FAIL;
3420   "
3421 )
3422
3423 (define_expand "zero_extendqisi2"
3424   [(set (match_operand:SI 0 "s_register_operand" "")
3425         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3426   "TARGET_EITHER"
3427   "
3428   if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3429     {
3430       if (TARGET_ARM)
3431         {
3432           emit_insn (gen_andsi3 (operands[0],
3433                                  gen_lowpart (SImode, operands[1]),
3434                                  GEN_INT (255)));
3435         }
3436       else /* TARGET_THUMB */
3437         {
3438           rtx temp = gen_reg_rtx (SImode);
3439           rtx ops[3];
3440           
3441           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3442           operands[1] = gen_lowpart (SImode, operands[1]);
3443
3444           ops[0] = temp;
3445           ops[1] = operands[1];
3446           ops[2] = GEN_INT (24);
3447
3448           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3449                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3450           
3451           ops[0] = operands[0];
3452           ops[1] = temp;
3453           ops[2] = GEN_INT (24);
3454
3455           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3456                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3457         }
3458       DONE;
3459     }
3460   "
3461 )
3462
3463 (define_insn "*thumb_zero_extendqisi2"
3464   [(set (match_operand:SI 0 "register_operand" "=l")
3465         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3466   "TARGET_THUMB && !arm_arch6"
3467   "ldrb\\t%0, %1"
3468   [(set_attr "length" "2")
3469    (set_attr "type" "load_byte")
3470    (set_attr "pool_range" "32")]
3471 )
3472
3473 (define_insn "*thumb_zero_extendqisi2_v6"
3474   [(set (match_operand:SI 0 "register_operand" "=l,l")
3475         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3476   "TARGET_THUMB && arm_arch6"
3477   "@
3478    uxtb\\t%0, %1
3479    ldrb\\t%0, %1"
3480   [(set_attr "length" "2,2")
3481    (set_attr "type" "alu_shift,load_byte")
3482    (set_attr "pool_range" "*,32")]
3483 )
3484
3485 (define_insn "*arm_zero_extendqisi2"
3486   [(set (match_operand:SI 0 "s_register_operand" "=r")
3487         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3488   "TARGET_ARM && !arm_arch6"
3489   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3490   [(set_attr "type" "load_byte")
3491    (set_attr "predicable" "yes")
3492    (set_attr "pool_range" "4096")
3493    (set_attr "neg_pool_range" "4084")]
3494 )
3495
3496 (define_insn "*arm_zero_extendqisi2_v6"
3497   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3498         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3499   "TARGET_ARM && arm_arch6"
3500   "@
3501    uxtb%?\\t%0, %1
3502    ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3503   [(set_attr "type" "alu_shift,load_byte")
3504    (set_attr "predicable" "yes")
3505    (set_attr "pool_range" "*,4096")
3506    (set_attr "neg_pool_range" "*,4084")]
3507 )
3508
3509 (define_insn "*arm_zero_extendqisi2addsi"
3510   [(set (match_operand:SI 0 "s_register_operand" "=r")
3511         (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3512                  (match_operand:SI 2 "s_register_operand" "r")))]
3513   "TARGET_ARM && arm_arch6"
3514   "uxtab%?\\t%0, %2, %1"
3515   [(set_attr "predicable" "yes")
3516    (set_attr "type" "alu_shift")]
3517 )
3518
3519 (define_split
3520   [(set (match_operand:SI 0 "s_register_operand" "")
3521         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3522    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3523   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3524   [(set (match_dup 2) (match_dup 1))
3525    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3526   ""
3527 )
3528
3529 (define_insn "*compareqi_eq0"
3530   [(set (reg:CC_Z CC_REGNUM)
3531         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3532                          (const_int 0)))]
3533   "TARGET_ARM"
3534   "tst\\t%0, #255"
3535   [(set_attr "conds" "set")]
3536 )
3537
3538 (define_expand "extendhisi2"
3539   [(set (match_dup 2)
3540         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3541                    (const_int 16)))
3542    (set (match_operand:SI 0 "s_register_operand" "")
3543         (ashiftrt:SI (match_dup 2)
3544                      (const_int 16)))]
3545   "TARGET_EITHER"
3546   "
3547   {
3548     if (GET_CODE (operands[1]) == MEM)
3549       {
3550         if (TARGET_THUMB)
3551           {
3552             emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3553             DONE;
3554           }
3555         else if (arm_arch4)
3556           {
3557             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3558                        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3559             DONE;
3560           }
3561       }
3562
3563     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3564       {
3565         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3566         DONE;
3567       }
3568
3569     if (!s_register_operand (operands[1], HImode))
3570       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3571
3572     if (arm_arch6)
3573       {
3574         if (TARGET_THUMB)
3575           emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3576         else
3577           emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3578                      gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3579
3580         DONE;
3581       }
3582
3583     operands[1] = gen_lowpart (SImode, operands[1]);
3584     operands[2] = gen_reg_rtx (SImode);
3585   }"
3586 )
3587
3588 (define_insn "thumb_extendhisi2"
3589   [(set (match_operand:SI 0 "register_operand" "=l")
3590         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3591    (clobber (match_scratch:SI 2 "=&l"))]
3592   "TARGET_THUMB && !arm_arch6"
3593   "*
3594   {
3595     rtx ops[4];
3596     rtx mem = XEXP (operands[1], 0);
3597
3598     /* This code used to try to use 'V', and fix the address only if it was
3599        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3600        range of QImode offsets, and offsettable_address_p does a QImode
3601        address check.  */
3602        
3603     if (GET_CODE (mem) == CONST)
3604       mem = XEXP (mem, 0);
3605     
3606     if (GET_CODE (mem) == LABEL_REF)
3607       return \"ldr\\t%0, %1\";
3608     
3609     if (GET_CODE (mem) == PLUS)
3610       {
3611         rtx a = XEXP (mem, 0);
3612         rtx b = XEXP (mem, 1);
3613
3614         if (GET_CODE (a) == LABEL_REF
3615             && GET_CODE (b) == CONST_INT)
3616           return \"ldr\\t%0, %1\";
3617
3618         if (GET_CODE (b) == REG)
3619           return \"ldrsh\\t%0, %1\";
3620           
3621         ops[1] = a;
3622         ops[2] = b;
3623       }
3624     else
3625       {
3626         ops[1] = mem;
3627         ops[2] = const0_rtx;
3628       }
3629
3630     gcc_assert (GET_CODE (ops[1]) == REG);
3631
3632     ops[0] = operands[0];
3633     ops[3] = operands[2];
3634     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3635     return \"\";
3636   }"
3637   [(set_attr "length" "4")
3638    (set_attr "type" "load_byte")
3639    (set_attr "pool_range" "1020")]
3640 )
3641
3642 ;; We used to have an early-clobber on the scratch register here.
3643 ;; However, there's a bug somewhere in reload which means that this
3644 ;; can be partially ignored during spill allocation if the memory
3645 ;; address also needs reloading; this causes us to die later on when
3646 ;; we try to verify the operands.  Fortunately, we don't really need
3647 ;; the early-clobber: we can always use operand 0 if operand 2
3648 ;; overlaps the address.
3649 (define_insn "*thumb_extendhisi2_insn_v6"
3650   [(set (match_operand:SI 0 "register_operand" "=l,l")
3651         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3652    (clobber (match_scratch:SI 2 "=X,l"))]
3653   "TARGET_THUMB && arm_arch6"
3654   "*
3655   {
3656     rtx ops[4];
3657     rtx mem;
3658
3659     if (which_alternative == 0)
3660       return \"sxth\\t%0, %1\";
3661
3662     mem = XEXP (operands[1], 0);
3663
3664     /* This code used to try to use 'V', and fix the address only if it was
3665        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3666        range of QImode offsets, and offsettable_address_p does a QImode
3667        address check.  */
3668        
3669     if (GET_CODE (mem) == CONST)
3670       mem = XEXP (mem, 0);
3671     
3672     if (GET_CODE (mem) == LABEL_REF)
3673       return \"ldr\\t%0, %1\";
3674     
3675     if (GET_CODE (mem) == PLUS)
3676       {
3677         rtx a = XEXP (mem, 0);
3678         rtx b = XEXP (mem, 1);
3679
3680         if (GET_CODE (a) == LABEL_REF
3681             && GET_CODE (b) == CONST_INT)
3682           return \"ldr\\t%0, %1\";
3683
3684         if (GET_CODE (b) == REG)
3685           return \"ldrsh\\t%0, %1\";
3686           
3687         ops[1] = a;
3688         ops[2] = b;
3689       }
3690     else
3691       {
3692         ops[1] = mem;
3693         ops[2] = const0_rtx;
3694       }
3695       
3696     gcc_assert (GET_CODE (ops[1]) == REG);
3697
3698     ops[0] = operands[0];
3699     if (reg_mentioned_p (operands[2], ops[1]))
3700       ops[3] = ops[0];
3701     else
3702       ops[3] = operands[2];
3703     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3704     return \"\";
3705   }"
3706   [(set_attr "length" "2,4")
3707    (set_attr "type" "alu_shift,load_byte")
3708    (set_attr "pool_range" "*,1020")]
3709 )
3710
3711 (define_expand "extendhisi2_mem"
3712   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3713    (set (match_dup 3)
3714         (zero_extend:SI (match_dup 7)))
3715    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3716    (set (match_operand:SI 0 "" "")
3717         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3718   "TARGET_ARM"
3719   "
3720   {
3721     rtx mem1, mem2;
3722     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3723
3724     mem1 = gen_rtx_MEM (QImode, addr);
3725     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3726     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3727     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3728     operands[0] = gen_lowpart (SImode, operands[0]);
3729     operands[1] = mem1;
3730     operands[2] = gen_reg_rtx (SImode);
3731     operands[3] = gen_reg_rtx (SImode);
3732     operands[6] = gen_reg_rtx (SImode);
3733     operands[7] = mem2;
3734
3735     if (BYTES_BIG_ENDIAN)
3736       {
3737         operands[4] = operands[2];
3738         operands[5] = operands[3];
3739       }
3740     else
3741       {
3742         operands[4] = operands[3];
3743         operands[5] = operands[2];
3744       }
3745   }"
3746 )
3747
3748 (define_insn "*arm_extendhisi2"
3749   [(set (match_operand:SI 0 "s_register_operand" "=r")
3750         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3751   "TARGET_ARM && arm_arch4 && !arm_arch6"
3752   "ldr%?sh\\t%0, %1"
3753   [(set_attr "type" "load_byte")
3754    (set_attr "predicable" "yes")
3755    (set_attr "pool_range" "256")
3756    (set_attr "neg_pool_range" "244")]
3757 )
3758
3759 (define_insn "*arm_extendhisi2_v6"
3760   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3761         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3762   "TARGET_ARM && arm_arch6"
3763   "@
3764    sxth%?\\t%0, %1
3765    ldr%?sh\\t%0, %1"
3766   [(set_attr "type" "alu_shift,load_byte")
3767    (set_attr "predicable" "yes")
3768    (set_attr "pool_range" "*,256")
3769    (set_attr "neg_pool_range" "*,244")]
3770 )
3771
3772 (define_insn "*arm_extendhisi2addsi"
3773   [(set (match_operand:SI 0 "s_register_operand" "=r")
3774         (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3775                  (match_operand:SI 2 "s_register_operand" "r")))]
3776   "TARGET_ARM && arm_arch6"
3777   "sxtah%?\\t%0, %2, %1"
3778 )
3779
3780 (define_split
3781   [(set (match_operand:SI                 0 "s_register_operand" "")
3782         (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3783    (clobber (match_operand:SI             2 "s_register_operand" ""))]
3784   "TARGET_ARM && (!arm_arch4)"
3785   [(set (match_dup 2) (match_dup 1))
3786    (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3787   "
3788   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3789     FAIL;
3790   "
3791 )
3792
3793 (define_split
3794   [(set (match_operand:SI                   0 "s_register_operand" "")
3795         (match_operator:SI                  3 "shiftable_operator"
3796          [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3797           (match_operand:SI                 4 "s_register_operand" "")]))
3798    (clobber (match_operand:SI               2 "s_register_operand" ""))]
3799   "TARGET_ARM && (!arm_arch4)"
3800   [(set (match_dup 2) (match_dup 1))
3801    (set (match_dup 0)
3802         (match_op_dup 3
3803          [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3804   "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3805      FAIL;
3806   "
3807 )
3808
3809 (define_expand "extendqihi2"
3810   [(set (match_dup 2)
3811         (ashift:SI (match_operand:QI 1 "general_operand" "")
3812                    (const_int 24)))
3813    (set (match_operand:HI 0 "s_register_operand" "")
3814         (ashiftrt:SI (match_dup 2)
3815                      (const_int 24)))]
3816   "TARGET_ARM"
3817   "
3818   {
3819     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3820       {
3821         emit_insn (gen_rtx_SET (VOIDmode,
3822                                 operands[0],
3823                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3824         DONE;
3825       }
3826     if (!s_register_operand (operands[1], QImode))
3827       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3828     operands[0] = gen_lowpart (SImode, operands[0]);
3829     operands[1] = gen_lowpart (SImode, operands[1]);
3830     operands[2] = gen_reg_rtx (SImode);
3831   }"
3832 )
3833
3834 (define_insn "*extendqihi_insn"
3835   [(set (match_operand:HI 0 "s_register_operand" "=r")
3836         (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3837   "TARGET_ARM && arm_arch4"
3838   "ldr%?sb\\t%0, %1"
3839   [(set_attr "type" "load_byte")
3840    (set_attr "predicable" "yes")
3841    (set_attr "pool_range" "256")
3842    (set_attr "neg_pool_range" "244")]
3843 )
3844
3845 (define_expand "extendqisi2"
3846   [(set (match_dup 2)
3847         (ashift:SI (match_operand:QI 1 "general_operand" "")
3848                    (const_int 24)))
3849    (set (match_operand:SI 0 "s_register_operand" "")
3850         (ashiftrt:SI (match_dup 2)
3851                      (const_int 24)))]
3852   "TARGET_EITHER"
3853   "
3854   {
3855     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3856       {
3857         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3858                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3859         DONE;
3860       }
3861
3862     if (!s_register_operand (operands[1], QImode))
3863       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3864
3865     if (arm_arch6)
3866       {
3867         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3868                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3869         DONE;
3870       }
3871
3872     operands[1] = gen_lowpart (SImode, operands[1]);
3873     operands[2] = gen_reg_rtx (SImode);
3874   }"
3875 )
3876
3877 (define_insn "*arm_extendqisi"
3878   [(set (match_operand:SI 0 "s_register_operand" "=r")
3879         (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3880   "TARGET_ARM && arm_arch4 && !arm_arch6"
3881   "ldr%?sb\\t%0, %1"
3882   [(set_attr "type" "load_byte")
3883    (set_attr "predicable" "yes")
3884    (set_attr "pool_range" "256")
3885    (set_attr "neg_pool_range" "244")]
3886 )
3887
3888 (define_insn "*arm_extendqisi_v6"
3889   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3890         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3891   "TARGET_ARM && arm_arch6"
3892   "@
3893    sxtb%?\\t%0, %1
3894    ldr%?sb\\t%0, %1"
3895   [(set_attr "type" "alu_shift,load_byte")
3896    (set_attr "predicable" "yes")
3897    (set_attr "pool_range" "*,256")
3898    (set_attr "neg_pool_range" "*,244")]
3899 )
3900
3901 (define_insn "*arm_extendqisi2addsi"
3902   [(set (match_operand:SI 0 "s_register_operand" "=r")
3903         (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3904                  (match_operand:SI 2 "s_register_operand" "r")))]
3905   "TARGET_ARM && arm_arch6"
3906   "sxtab%?\\t%0, %2, %1"
3907   [(set_attr "type" "alu_shift")
3908    (set_attr "predicable" "yes")]
3909 )
3910
3911 (define_insn "*thumb_extendqisi2"
3912   [(set (match_operand:SI 0 "register_operand" "=l,l")
3913         (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3914   "TARGET_THUMB && !arm_arch6"
3915   "*
3916   {
3917     rtx ops[3];
3918     rtx mem = XEXP (operands[1], 0);
3919     
3920     if (GET_CODE (mem) == CONST)
3921       mem = XEXP (mem, 0);
3922     
3923     if (GET_CODE (mem) == LABEL_REF)
3924       return \"ldr\\t%0, %1\";
3925
3926     if (GET_CODE (mem) == PLUS
3927         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3928       return \"ldr\\t%0, %1\";
3929       
3930     if (which_alternative == 0)
3931       return \"ldrsb\\t%0, %1\";
3932       
3933     ops[0] = operands[0];
3934     
3935     if (GET_CODE (mem) == PLUS)
3936       {
3937         rtx a = XEXP (mem, 0);
3938         rtx b = XEXP (mem, 1);
3939         
3940         ops[1] = a;
3941         ops[2] = b;
3942
3943         if (GET_CODE (a) == REG)
3944           {
3945             if (GET_CODE (b) == REG)
3946               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3947             else if (REGNO (a) == REGNO (ops[0]))
3948               {
3949                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3950                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3951                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3952               }
3953             else
3954               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3955           }
3956         else
3957           {
3958             gcc_assert (GET_CODE (b) == REG);
3959             if (REGNO (b) == REGNO (ops[0]))
3960               {
3961                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3962                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3963                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3964               }
3965             else
3966               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3967           }
3968       }
3969     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3970       {
3971         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3972         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3973         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3974       }
3975     else
3976       {
3977         ops[1] = mem;
3978         ops[2] = const0_rtx;
3979         
3980         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3981       }
3982     return \"\";
3983   }"
3984   [(set_attr "length" "2,6")
3985    (set_attr "type" "load_byte,load_byte")
3986    (set_attr "pool_range" "32,32")]
3987 )
3988
3989 (define_insn "*thumb_extendqisi2_v6"
3990   [(set (match_operand:SI 0 "register_operand" "=l,l,l")
3991         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
3992   "TARGET_THUMB && arm_arch6"
3993   "*
3994   {
3995     rtx ops[3];
3996     rtx mem;
3997
3998     if (which_alternative == 0)
3999       return \"sxtb\\t%0, %1\";
4000
4001     mem = XEXP (operands[1], 0);
4002     
4003     if (GET_CODE (mem) == CONST)
4004       mem = XEXP (mem, 0);
4005     
4006     if (GET_CODE (mem) == LABEL_REF)
4007       return \"ldr\\t%0, %1\";
4008
4009     if (GET_CODE (mem) == PLUS
4010         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4011       return \"ldr\\t%0, %1\";
4012       
4013     if (which_alternative == 0)
4014       return \"ldrsb\\t%0, %1\";
4015       
4016     ops[0] = operands[0];
4017     
4018     if (GET_CODE (mem) == PLUS)
4019       {
4020         rtx a = XEXP (mem, 0);
4021         rtx b = XEXP (mem, 1);
4022         
4023         ops[1] = a;
4024         ops[2] = b;
4025
4026         if (GET_CODE (a) == REG)
4027           {
4028             if (GET_CODE (b) == REG)
4029               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4030             else if (REGNO (a) == REGNO (ops[0]))
4031               {
4032                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4033                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4034               }
4035             else
4036               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4037           }
4038         else
4039           {
4040             gcc_assert (GET_CODE (b) == REG);
4041             if (REGNO (b) == REGNO (ops[0]))
4042               {
4043                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4044                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4045               }
4046             else
4047               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4048           }
4049       }
4050     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4051       {
4052         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4053         output_asm_insn (\"sxtb\\t%0, %0\", ops);
4054       }
4055     else
4056       {
4057         ops[1] = mem;
4058         ops[2] = const0_rtx;
4059         
4060         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4061       }
4062     return \"\";
4063   }"
4064   [(set_attr "length" "2,2,4")
4065    (set_attr "type" "alu_shift,load_byte,load_byte")
4066    (set_attr "pool_range" "*,32,32")]
4067 )
4068
4069 (define_expand "extendsfdf2"
4070   [(set (match_operand:DF                  0 "s_register_operand" "")
4071         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
4072   "TARGET_ARM && TARGET_HARD_FLOAT"
4073   ""
4074 )
4075 \f
4076 ;; Move insns (including loads and stores)
4077
4078 ;; XXX Just some ideas about movti.
4079 ;; I don't think these are a good idea on the arm, there just aren't enough
4080 ;; registers
4081 ;;(define_expand "loadti"
4082 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
4083 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
4084 ;;  "" "")
4085
4086 ;;(define_expand "storeti"
4087 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4088 ;;      (match_operand:TI 1 "s_register_operand" ""))]
4089 ;;  "" "")
4090
4091 ;;(define_expand "movti"
4092 ;;  [(set (match_operand:TI 0 "general_operand" "")
4093 ;;      (match_operand:TI 1 "general_operand" ""))]
4094 ;;  ""
4095 ;;  "
4096 ;;{
4097 ;;  rtx insn;
4098 ;;
4099 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4100 ;;    operands[1] = copy_to_reg (operands[1]);
4101 ;;  if (GET_CODE (operands[0]) == MEM)
4102 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4103 ;;  else if (GET_CODE (operands[1]) == MEM)
4104 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4105 ;;  else
4106 ;;    FAIL;
4107 ;;
4108 ;;  emit_insn (insn);
4109 ;;  DONE;
4110 ;;}")
4111
4112 ;; Recognize garbage generated above.
4113
4114 ;;(define_insn ""
4115 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4116 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4117 ;;  ""
4118 ;;  "*
4119 ;;  {
4120 ;;    register mem = (which_alternative < 3);
4121 ;;    register const char *template;
4122 ;;
4123 ;;    operands[mem] = XEXP (operands[mem], 0);
4124 ;;    switch (which_alternative)
4125 ;;      {
4126 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4127 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
4128 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
4129 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
4130 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
4131 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
4132 ;;      }
4133 ;;    output_asm_insn (template, operands);
4134 ;;    return \"\";
4135 ;;  }")
4136
4137 (define_expand "movdi"
4138   [(set (match_operand:DI 0 "general_operand" "")
4139         (match_operand:DI 1 "general_operand" ""))]
4140   "TARGET_EITHER"
4141   "
4142   if (TARGET_THUMB)
4143     {
4144       if (!no_new_pseudos)
4145         {
4146           if (GET_CODE (operands[0]) != REG)
4147             operands[1] = force_reg (DImode, operands[1]);
4148         }
4149     }
4150   "
4151 )
4152
4153 (define_insn "*arm_movdi"
4154   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4155         (match_operand:DI 1 "di_operand"              "rDa,Db,Dc,mi,r"))]
4156   "TARGET_ARM
4157   && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4158   && !TARGET_IWMMXT"
4159   "*
4160   switch (which_alternative)
4161     {
4162     case 0:
4163     case 1:
4164     case 2:
4165       return \"#\";
4166     default:
4167       return output_move_double (operands);
4168     }
4169   "
4170   [(set_attr "length" "8,12,16,8,8")
4171    (set_attr "type" "*,*,*,load2,store2")
4172    (set_attr "pool_range" "*,*,*,1020,*")
4173    (set_attr "neg_pool_range" "*,*,*,1008,*")]
4174 )
4175
4176 (define_split
4177   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4178         (match_operand:ANY64 1 "const_double_operand" ""))]
4179   "TARGET_ARM
4180    && reload_completed
4181    && (arm_const_double_inline_cost (operands[1])
4182        <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4183   [(const_int 0)]
4184   "
4185   arm_split_constant (SET, SImode, curr_insn,
4186                       INTVAL (gen_lowpart (SImode, operands[1])),
4187                       gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4188   arm_split_constant (SET, SImode, curr_insn,
4189                       INTVAL (gen_highpart_mode (SImode,
4190                                                  GET_MODE (operands[0]),
4191                                                  operands[1])),
4192                       gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4193   DONE;
4194   "
4195 )
4196
4197 ; If optimizing for size, or if we have load delay slots, then 
4198 ; we want to split the constant into two separate operations. 
4199 ; In both cases this may split a trivial part into a single data op
4200 ; leaving a single complex constant to load.  We can also get longer
4201 ; offsets in a LDR which means we get better chances of sharing the pool
4202 ; entries.  Finally, we can normally do a better job of scheduling
4203 ; LDR instructions than we can with LDM.
4204 ; This pattern will only match if the one above did not.
4205 (define_split
4206   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4207         (match_operand:ANY64 1 "const_double_operand" ""))]
4208   "TARGET_ARM && reload_completed
4209    && arm_const_double_by_parts (operands[1])"
4210   [(set (match_dup 0) (match_dup 1))
4211    (set (match_dup 2) (match_dup 3))]
4212   "
4213   operands[2] = gen_highpart (SImode, operands[0]);
4214   operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4215                                    operands[1]);
4216   operands[0] = gen_lowpart (SImode, operands[0]);
4217   operands[1] = gen_lowpart (SImode, operands[1]);
4218   "
4219 )
4220
4221 (define_split
4222   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4223         (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4224   "TARGET_EITHER && reload_completed"
4225   [(set (match_dup 0) (match_dup 1))
4226    (set (match_dup 2) (match_dup 3))]
4227   "
4228   operands[2] = gen_highpart (SImode, operands[0]);
4229   operands[3] = gen_highpart (SImode, operands[1]);
4230   operands[0] = gen_lowpart (SImode, operands[0]);
4231   operands[1] = gen_lowpart (SImode, operands[1]);
4232
4233   /* Handle a partial overlap.  */
4234   if (rtx_equal_p (operands[0], operands[3]))
4235     {
4236       rtx tmp0 = operands[0];
4237       rtx tmp1 = operands[1];
4238
4239       operands[0] = operands[2];
4240       operands[1] = operands[3];
4241       operands[2] = tmp0;
4242       operands[3] = tmp1;
4243     }
4244   "
4245 )
4246
4247 ;; We can't actually do base+index doubleword loads if the index and
4248 ;; destination overlap.  Split here so that we at least have chance to
4249 ;; schedule.
4250 (define_split
4251   [(set (match_operand:DI 0 "s_register_operand" "")
4252         (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4253                          (match_operand:SI 2 "s_register_operand" ""))))]
4254   "TARGET_LDRD
4255   && reg_overlap_mentioned_p (operands[0], operands[1])
4256   && reg_overlap_mentioned_p (operands[0], operands[2])"
4257   [(set (match_dup 4)
4258         (plus:SI (match_dup 1)
4259                  (match_dup 2)))
4260    (set (match_dup 0)
4261         (mem:DI (match_dup 4)))]
4262   "
4263   operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4264   "
4265 )
4266
4267 ;;; ??? This should have alternatives for constants.
4268 ;;; ??? This was originally identical to the movdf_insn pattern.
4269 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4270 ;;; thumb_reorg with a memory reference.
4271 (define_insn "*thumb_movdi_insn"
4272   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4273         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
4274   "TARGET_THUMB
4275    && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4276    && (   register_operand (operands[0], DImode)
4277        || register_operand (operands[1], DImode))"
4278   "*
4279   {
4280   switch (which_alternative)
4281     {
4282     default:
4283     case 0:
4284       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4285         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
4286       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
4287     case 1:
4288       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4289     case 2:
4290       operands[1] = GEN_INT (- INTVAL (operands[1]));
4291       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4292     case 3:
4293       return \"ldmia\\t%1, {%0, %H0}\";
4294     case 4:
4295       return \"stmia\\t%0, {%1, %H1}\";
4296     case 5:
4297       return thumb_load_double_from_address (operands);
4298     case 6:
4299       operands[2] = gen_rtx_MEM (SImode,
4300                              plus_constant (XEXP (operands[0], 0), 4));
4301       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4302       return \"\";
4303     case 7:
4304       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4305         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4306       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4307     }
4308   }"
4309   [(set_attr "length" "4,4,6,2,2,6,4,4")
4310    (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4311    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4312 )
4313
4314 (define_expand "movsi"
4315   [(set (match_operand:SI 0 "general_operand" "")
4316         (match_operand:SI 1 "general_operand" ""))]
4317   "TARGET_EITHER"
4318   "
4319   if (TARGET_ARM)
4320     {
4321       /* Everything except mem = const or mem = mem can be done easily.  */
4322       if (GET_CODE (operands[0]) == MEM)
4323         operands[1] = force_reg (SImode, operands[1]);
4324       if (arm_general_register_operand (operands[0], SImode)
4325           && GET_CODE (operands[1]) == CONST_INT
4326           && !(const_ok_for_arm (INTVAL (operands[1]))
4327                || const_ok_for_arm (~INTVAL (operands[1]))))
4328         {
4329            arm_split_constant (SET, SImode, NULL_RTX,
4330                                INTVAL (operands[1]), operands[0], NULL_RTX,
4331                                optimize && !no_new_pseudos);
4332           DONE;
4333         }
4334     }
4335   else /* TARGET_THUMB....  */
4336     {
4337       if (!no_new_pseudos)
4338         {
4339           if (GET_CODE (operands[0]) != REG)
4340             operands[1] = force_reg (SImode, operands[1]);
4341         }
4342     }
4343     
4344   if (flag_pic
4345       && (CONSTANT_P (operands[1])
4346          || symbol_mentioned_p (operands[1])
4347          || label_mentioned_p (operands[1])))
4348     operands[1] = legitimize_pic_address (operands[1], SImode,
4349                                           (no_new_pseudos ? operands[0] : 0));
4350   "
4351 )
4352
4353 (define_insn "*arm_movsi_insn"
4354   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4355         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
4356   "TARGET_ARM && ! TARGET_IWMMXT
4357    && !(TARGET_HARD_FLOAT && TARGET_VFP)
4358    && (   register_operand (operands[0], SImode)
4359        || register_operand (operands[1], SImode))"
4360   "@
4361    mov%?\\t%0, %1
4362    mvn%?\\t%0, #%B1
4363    ldr%?\\t%0, %1
4364    str%?\\t%1, %0"
4365   [(set_attr "type" "*,*,load1,store1")
4366    (set_attr "predicable" "yes")
4367    (set_attr "pool_range" "*,*,4096,*")
4368    (set_attr "neg_pool_range" "*,*,4084,*")]
4369 )
4370
4371 (define_split
4372   [(set (match_operand:SI 0 "arm_general_register_operand" "")
4373         (match_operand:SI 1 "const_int_operand" ""))]
4374   "TARGET_ARM
4375   && (!(const_ok_for_arm (INTVAL (operands[1]))
4376         || const_ok_for_arm (~INTVAL (operands[1]))))"
4377   [(clobber (const_int 0))]
4378   "
4379   arm_split_constant (SET, SImode, NULL_RTX, 
4380                       INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4381   DONE;
4382   "
4383 )
4384
4385 (define_insn "*thumb_movsi_insn"
4386   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4387         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4388   "TARGET_THUMB
4389    && (   register_operand (operands[0], SImode) 
4390        || register_operand (operands[1], SImode))"
4391   "@
4392    mov  %0, %1
4393    mov  %0, %1
4394    #
4395    #
4396    ldmia\\t%1, {%0}
4397    stmia\\t%0, {%1}
4398    ldr\\t%0, %1
4399    str\\t%1, %0
4400    mov\\t%0, %1"
4401   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4402    (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4403    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4404 )
4405
4406 (define_split 
4407   [(set (match_operand:SI 0 "register_operand" "")
4408         (match_operand:SI 1 "const_int_operand" ""))]
4409   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4410   [(set (match_dup 0) (match_dup 1))
4411    (set (match_dup 0) (neg:SI (match_dup 0)))]
4412   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4413 )
4414
4415 (define_split 
4416   [(set (match_operand:SI 0 "register_operand" "")
4417         (match_operand:SI 1 "const_int_operand" ""))]
4418   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4419   [(set (match_dup 0) (match_dup 1))
4420    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4421   "
4422   {
4423     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4424     unsigned HOST_WIDE_INT mask = 0xff;
4425     int i;
4426     
4427     for (i = 0; i < 25; i++)
4428       if ((val & (mask << i)) == val)
4429         break;
4430
4431     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4432     if (i == 0)
4433       FAIL;
4434
4435     operands[1] = GEN_INT (val >> i);
4436     operands[2] = GEN_INT (i);
4437   }"
4438 )
4439
4440 ;; When generating pic, we need to load the symbol offset into a register.
4441 ;; So that the optimizer does not confuse this with a normal symbol load
4442 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
4443 ;; since that is the only type of relocation we can use.
4444
4445 ;; The rather odd constraints on the following are to force reload to leave
4446 ;; the insn alone, and to force the minipool generation pass to then move
4447 ;; the GOT symbol to memory.
4448
4449 (define_insn "pic_load_addr_arm"
4450   [(set (match_operand:SI 0 "s_register_operand" "=r")
4451         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4452   "TARGET_ARM && flag_pic"
4453   "ldr%?\\t%0, %1"
4454   [(set_attr "type" "load1")
4455    (set (attr "pool_range")     (const_int 4096))
4456    (set (attr "neg_pool_range") (const_int 4084))]
4457 )
4458
4459 (define_insn "pic_load_addr_thumb"
4460   [(set (match_operand:SI 0 "s_register_operand" "=l")
4461         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4462   "TARGET_THUMB && flag_pic"
4463   "ldr\\t%0, %1"
4464   [(set_attr "type" "load1")
4465    (set (attr "pool_range") (const_int 1024))]
4466 )
4467
4468 ;; This variant is used for AOF assembly, since it needs to mention the
4469 ;; pic register in the rtl.
4470 (define_expand "pic_load_addr_based"
4471   [(set (match_operand:SI 0 "s_register_operand" "")
4472         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4473   "TARGET_ARM && flag_pic"
4474   "operands[2] = pic_offset_table_rtx;"
4475 )
4476
4477 (define_insn "*pic_load_addr_based_insn"
4478   [(set (match_operand:SI 0 "s_register_operand" "=r")
4479         (unspec:SI [(match_operand 1 "" "")
4480                     (match_operand 2 "s_register_operand" "r")]
4481                    UNSPEC_PIC_SYM))]
4482   "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4483   "*
4484 #ifdef AOF_ASSEMBLER
4485   operands[1] = aof_pic_entry (operands[1]);
4486 #endif
4487   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4488   return \"\";
4489   "
4490   [(set_attr "type" "load1")
4491    (set (attr "pool_range")
4492         (if_then_else (eq_attr "is_thumb" "yes")
4493                       (const_int 1024)
4494                       (const_int 4096)))
4495    (set (attr "neg_pool_range")
4496         (if_then_else (eq_attr "is_thumb" "yes")
4497                       (const_int 0)
4498                       (const_int 4084)))]
4499 )
4500
4501 (define_insn "pic_add_dot_plus_four"
4502   [(set (match_operand:SI 0 "register_operand" "+r")
4503         (unspec:SI [(plus:SI (match_dup 0)
4504                              (const (plus:SI (pc) (const_int 4))))]
4505                    UNSPEC_PIC_BASE))
4506    (use (label_ref (match_operand 1 "" "")))]
4507   "TARGET_THUMB && flag_pic"
4508   "*
4509   (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4510                              CODE_LABEL_NUMBER (operands[1]));
4511   return \"add\\t%0, %|pc\";
4512   "
4513   [(set_attr "length" "2")]
4514 )
4515
4516 (define_insn "pic_add_dot_plus_eight"
4517   [(set (match_operand:SI 0 "register_operand" "+r")
4518         (unspec:SI [(plus:SI (match_dup 0)
4519                              (const (plus:SI (pc) (const_int 8))))]
4520                    UNSPEC_PIC_BASE))
4521    (use (label_ref (match_operand 1 "" "")))]
4522   "TARGET_ARM && flag_pic"
4523   "*
4524     (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4525                                CODE_LABEL_NUMBER (operands[1]));
4526     return \"add%?\\t%0, %|pc, %0\";
4527   "
4528   [(set_attr "predicable" "yes")]
4529 )
4530
4531 (define_expand "builtin_setjmp_receiver"
4532   [(label_ref (match_operand 0 "" ""))]
4533   "flag_pic"
4534   "
4535 {
4536   /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4537      register.  */
4538   arm_load_pic_register (3);
4539   DONE;
4540 }")
4541
4542 ;; If copying one reg to another we can set the condition codes according to
4543 ;; its value.  Such a move is common after a return from subroutine and the
4544 ;; result is being tested against zero.
4545
4546 (define_insn "*movsi_compare0"
4547   [(set (reg:CC CC_REGNUM)
4548         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4549                     (const_int 0)))
4550    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4551         (match_dup 1))]
4552   "TARGET_ARM"
4553   "@
4554    cmp%?\\t%0, #0
4555    sub%?s\\t%0, %1, #0"
4556   [(set_attr "conds" "set")]
4557 )
4558
4559 ;; Subroutine to store a half word from a register into memory.
4560 ;; Operand 0 is the source register (HImode)
4561 ;; Operand 1 is the destination address in a register (SImode)
4562
4563 ;; In both this routine and the next, we must be careful not to spill
4564 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4565 ;; can generate unrecognizable rtl.
4566
4567 (define_expand "storehi"
4568   [;; store the low byte
4569    (set (match_operand 1 "" "") (match_dup 3))
4570    ;; extract the high byte
4571    (set (match_dup 2)
4572         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4573    ;; store the high byte
4574    (set (match_dup 4) (match_dup 5))]
4575   "TARGET_ARM"
4576   "
4577   {
4578     rtx op1 = operands[1];
4579     rtx addr = XEXP (op1, 0);
4580     enum rtx_code code = GET_CODE (addr);
4581
4582     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4583         || code == MINUS)
4584       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4585
4586     operands[4] = adjust_address (op1, QImode, 1);
4587     operands[1] = adjust_address (operands[1], QImode, 0);
4588     operands[3] = gen_lowpart (QImode, operands[0]);
4589     operands[0] = gen_lowpart (SImode, operands[0]);
4590     operands[2] = gen_reg_rtx (SImode);
4591     operands[5] = gen_lowpart (QImode, operands[2]);
4592   }"
4593 )
4594
4595 (define_expand "storehi_bigend"
4596   [(set (match_dup 4) (match_dup 3))
4597    (set (match_dup 2)
4598         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4599    (set (match_operand 1 "" "") (match_dup 5))]
4600   "TARGET_ARM"
4601   "
4602   {
4603     rtx op1 = operands[1];
4604     rtx addr = XEXP (op1, 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       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4610
4611     operands[4] = adjust_address (op1, QImode, 1);
4612     operands[1] = adjust_address (operands[1], QImode, 0);
4613     operands[3] = gen_lowpart (QImode, operands[0]);
4614     operands[0] = gen_lowpart (SImode, operands[0]);
4615     operands[2] = gen_reg_rtx (SImode);
4616     operands[5] = gen_lowpart (QImode, operands[2]);
4617   }"
4618 )
4619
4620 ;; Subroutine to store a half word integer constant into memory.
4621 (define_expand "storeinthi"
4622   [(set (match_operand 0 "" "")
4623         (match_operand 1 "" ""))
4624    (set (match_dup 3) (match_dup 2))]
4625   "TARGET_ARM"
4626   "
4627   {
4628     HOST_WIDE_INT value = INTVAL (operands[1]);
4629     rtx addr = XEXP (operands[0], 0);
4630     rtx op0 = operands[0];
4631     enum rtx_code code = GET_CODE (addr);
4632
4633     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4634         || code == MINUS)
4635       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4636
4637     operands[1] = gen_reg_rtx (SImode);
4638     if (BYTES_BIG_ENDIAN)
4639       {
4640         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4641         if ((value & 255) == ((value >> 8) & 255))
4642           operands[2] = operands[1];
4643         else
4644           {
4645             operands[2] = gen_reg_rtx (SImode);
4646             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4647           }
4648       }
4649     else
4650       {
4651         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4652         if ((value & 255) == ((value >> 8) & 255))
4653           operands[2] = operands[1];
4654         else
4655           {
4656             operands[2] = gen_reg_rtx (SImode);
4657             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4658           }
4659       }
4660
4661     operands[3] = adjust_address (op0, QImode, 1);
4662     operands[0] = adjust_address (operands[0], QImode, 0);
4663     operands[2] = gen_lowpart (QImode, operands[2]);
4664     operands[1] = gen_lowpart (QImode, operands[1]);
4665   }"
4666 )
4667
4668 (define_expand "storehi_single_op"
4669   [(set (match_operand:HI 0 "memory_operand" "")
4670         (match_operand:HI 1 "general_operand" ""))]
4671   "TARGET_ARM && arm_arch4"
4672   "
4673   if (!s_register_operand (operands[1], HImode))
4674     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4675   "
4676 )
4677
4678 (define_expand "movhi"
4679   [(set (match_operand:HI 0 "general_operand" "")
4680         (match_operand:HI 1 "general_operand" ""))]
4681   "TARGET_EITHER"
4682   "
4683   if (TARGET_ARM)
4684     {
4685       if (!no_new_pseudos)
4686         {
4687           if (GET_CODE (operands[0]) == MEM)
4688             {
4689               if (arm_arch4)
4690                 {
4691                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4692                   DONE;
4693                 }
4694               if (GET_CODE (operands[1]) == CONST_INT)
4695                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4696               else
4697                 {
4698                   if (GET_CODE (operands[1]) == MEM)
4699                     operands[1] = force_reg (HImode, operands[1]);
4700                   if (BYTES_BIG_ENDIAN)
4701                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4702                   else
4703                    emit_insn (gen_storehi (operands[1], operands[0]));
4704                 }
4705               DONE;
4706             }
4707           /* Sign extend a constant, and keep it in an SImode reg.  */
4708           else if (GET_CODE (operands[1]) == CONST_INT)
4709             {
4710               rtx reg = gen_reg_rtx (SImode);
4711               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4712
4713               /* If the constant is already valid, leave it alone.  */
4714               if (!const_ok_for_arm (val))
4715                 {
4716                   /* If setting all the top bits will make the constant 
4717                      loadable in a single instruction, then set them.  
4718                      Otherwise, sign extend the number.  */
4719
4720                   if (const_ok_for_arm (~(val | ~0xffff)))
4721                     val |= ~0xffff;
4722                   else if (val & 0x8000)
4723                     val |= ~0xffff;
4724                 }
4725
4726               emit_insn (gen_movsi (reg, GEN_INT (val)));
4727               operands[1] = gen_lowpart (HImode, reg);
4728             }
4729           else if (arm_arch4 && optimize && !no_new_pseudos
4730                    && GET_CODE (operands[1]) == MEM)
4731             {
4732               rtx reg = gen_reg_rtx (SImode);
4733
4734               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4735               operands[1] = gen_lowpart (HImode, reg);
4736             }
4737           else if (!arm_arch4)
4738             {
4739               if (GET_CODE (operands[1]) == MEM)
4740                 {
4741                   rtx base;
4742                   rtx offset = const0_rtx;
4743                   rtx reg = gen_reg_rtx (SImode);
4744
4745                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4746                        || (GET_CODE (base) == PLUS
4747                            && (GET_CODE (offset = XEXP (base, 1))
4748                                == CONST_INT)
4749                            && ((INTVAL(offset) & 1) != 1)
4750                            && GET_CODE (base = XEXP (base, 0)) == REG))
4751                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4752                     {
4753                       HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4754                       rtx new;
4755
4756                       new = gen_rtx_MEM (SImode,
4757                                          plus_constant (base, new_offset));
4758                       MEM_COPY_ATTRIBUTES (new, operands[1]);
4759                       emit_insn (gen_movsi (reg, new));
4760                       if (((INTVAL (offset) & 2) != 0)
4761                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4762                         {
4763                           rtx reg2 = gen_reg_rtx (SImode);
4764
4765                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4766                           reg = reg2;
4767                         }
4768                     }
4769                   else
4770                     emit_insn (gen_movhi_bytes (reg, operands[1]));
4771
4772                   operands[1] = gen_lowpart (HImode, reg);
4773                }
4774            }
4775         }
4776       /* Handle loading a large integer during reload.  */
4777       else if (GET_CODE (operands[1]) == CONST_INT
4778                && !const_ok_for_arm (INTVAL (operands[1]))
4779                && !const_ok_for_arm (~INTVAL (operands[1])))
4780         {
4781           /* Writing a constant to memory needs a scratch, which should
4782              be handled with SECONDARY_RELOADs.  */
4783           gcc_assert (GET_CODE (operands[0]) == REG);
4784
4785           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4786           emit_insn (gen_movsi (operands[0], operands[1]));
4787           DONE;
4788        }
4789     }
4790   else /* TARGET_THUMB */
4791     {
4792       if (!no_new_pseudos)
4793         {
4794           if (GET_CODE (operands[0]) != REG)
4795             operands[1] = force_reg (HImode, operands[1]);
4796
4797           /* ??? We shouldn't really get invalid addresses here, but this can
4798              happen if we are passed a SP (never OK for HImode/QImode) or 
4799              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4800              HImode/QImode) relative address.  */
4801           /* ??? This should perhaps be fixed elsewhere, for instance, in
4802              fixup_stack_1, by checking for other kinds of invalid addresses,
4803              e.g. a bare reference to a virtual register.  This may confuse the
4804              alpha though, which must handle this case differently.  */
4805           if (GET_CODE (operands[0]) == MEM
4806               && !memory_address_p (GET_MODE (operands[0]),
4807                                     XEXP (operands[0], 0)))
4808             operands[0]
4809               = replace_equiv_address (operands[0],
4810                                        copy_to_reg (XEXP (operands[0], 0)));
4811    
4812           if (GET_CODE (operands[1]) == MEM
4813               && !memory_address_p (GET_MODE (operands[1]),
4814                                     XEXP (operands[1], 0)))
4815             operands[1]
4816               = replace_equiv_address (operands[1],
4817                                        copy_to_reg (XEXP (operands[1], 0)));
4818         }
4819       /* Handle loading a large integer during reload.  */
4820       else if (GET_CODE (operands[1]) == CONST_INT
4821                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4822         {
4823           /* Writing a constant to memory needs a scratch, which should
4824              be handled with SECONDARY_RELOADs.  */
4825           gcc_assert (GET_CODE (operands[0]) == REG);
4826
4827           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4828           emit_insn (gen_movsi (operands[0], operands[1]));
4829           DONE;
4830         }
4831     }
4832   "
4833 )
4834
4835 (define_insn "*thumb_movhi_insn"
4836   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4837         (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
4838   "TARGET_THUMB
4839    && (   register_operand (operands[0], HImode)
4840        || register_operand (operands[1], HImode))"
4841   "*
4842   switch (which_alternative)
4843     {
4844     case 0: return \"add        %0, %1, #0\";
4845     case 2: return \"strh       %1, %0\";
4846     case 3: return \"mov        %0, %1\";
4847     case 4: return \"mov        %0, %1\";
4848     case 5: return \"mov        %0, %1\";
4849     default: gcc_unreachable ();
4850     case 1:
4851       /* The stack pointer can end up being taken as an index register.
4852           Catch this case here and deal with it.  */
4853       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4854           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4855           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4856         {
4857           rtx ops[2];
4858           ops[0] = operands[0];
4859           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4860       
4861           output_asm_insn (\"mov        %0, %1\", ops);
4862
4863           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4864     
4865         }
4866       return \"ldrh     %0, %1\";
4867     }"
4868   [(set_attr "length" "2,4,2,2,2,2")
4869    (set_attr "type" "*,load1,store1,*,*,*")]
4870 )
4871
4872
4873 (define_expand "movhi_bytes"
4874   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4875    (set (match_dup 3)
4876         (zero_extend:SI (match_dup 6)))
4877    (set (match_operand:SI 0 "" "")
4878          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4879   "TARGET_ARM"
4880   "
4881   {
4882     rtx mem1, mem2;
4883     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4884
4885     mem1 = gen_rtx_MEM (QImode, addr);
4886     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4887     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4888     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4889     operands[0] = gen_lowpart (SImode, operands[0]);
4890     operands[1] = mem1;
4891     operands[2] = gen_reg_rtx (SImode);
4892     operands[3] = gen_reg_rtx (SImode);
4893     operands[6] = mem2;
4894
4895     if (BYTES_BIG_ENDIAN)
4896       {
4897         operands[4] = operands[2];
4898         operands[5] = operands[3];
4899       }
4900     else
4901       {
4902         operands[4] = operands[3];
4903         operands[5] = operands[2];
4904       }
4905   }"
4906 )
4907
4908 (define_expand "movhi_bigend"
4909   [(set (match_dup 2)
4910         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4911                    (const_int 16)))
4912    (set (match_dup 3)
4913         (ashiftrt:SI (match_dup 2) (const_int 16)))
4914    (set (match_operand:HI 0 "s_register_operand" "")
4915         (match_dup 4))]
4916   "TARGET_ARM"
4917   "
4918   operands[2] = gen_reg_rtx (SImode);
4919   operands[3] = gen_reg_rtx (SImode);
4920   operands[4] = gen_lowpart (HImode, operands[3]);
4921   "
4922 )
4923
4924 ;; Pattern to recognize insn generated default case above
4925 (define_insn "*movhi_insn_arch4"
4926   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4927         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4928   "TARGET_ARM
4929    && arm_arch4
4930    && (GET_CODE (operands[1]) != CONST_INT
4931        || const_ok_for_arm (INTVAL (operands[1]))
4932        || const_ok_for_arm (~INTVAL (operands[1])))"
4933   "@
4934    mov%?\\t%0, %1\\t%@ movhi
4935    mvn%?\\t%0, #%B1\\t%@ movhi
4936    str%?h\\t%1, %0\\t%@ movhi
4937    ldr%?h\\t%0, %1\\t%@ movhi"
4938   [(set_attr "type" "*,*,store1,load1")
4939    (set_attr "predicable" "yes")
4940    (set_attr "pool_range" "*,*,*,256")
4941    (set_attr "neg_pool_range" "*,*,*,244")]
4942 )
4943
4944 (define_insn "*movhi_bytes"
4945   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4946         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4947   "TARGET_ARM"
4948   "@
4949    mov%?\\t%0, %1\\t%@ movhi
4950    mvn%?\\t%0, #%B1\\t%@ movhi"
4951   [(set_attr "predicable" "yes")]
4952 )
4953
4954 (define_insn "thumb_movhi_clobber"
4955   [(set (match_operand:HI     0 "memory_operand"   "=m")
4956         (match_operand:HI     1 "register_operand" "l"))
4957    (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4958   "TARGET_THUMB"
4959   "*
4960   gcc_unreachable ();"
4961 )
4962         
4963 ;; We use a DImode scratch because we may occasionally need an additional
4964 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4965 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4966 (define_expand "reload_outhi"
4967   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4968               (match_operand:HI 1 "s_register_operand"        "r")
4969               (match_operand:DI 2 "s_register_operand"        "=&l")])]
4970   "TARGET_EITHER"
4971   "if (TARGET_ARM)
4972      arm_reload_out_hi (operands);
4973    else
4974      thumb_reload_out_hi (operands);
4975   DONE;
4976   "
4977 )
4978
4979 (define_expand "reload_inhi"
4980   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4981               (match_operand:HI 1 "arm_reload_memory_operand" "o")
4982               (match_operand:DI 2 "s_register_operand" "=&r")])]
4983   "TARGET_EITHER"
4984   "
4985   if (TARGET_ARM)
4986     arm_reload_in_hi (operands);
4987   else
4988     thumb_reload_out_hi (operands);
4989   DONE;
4990 ")
4991
4992 (define_expand "movqi"
4993   [(set (match_operand:QI 0 "general_operand" "")
4994         (match_operand:QI 1 "general_operand" ""))]
4995   "TARGET_EITHER"
4996   "
4997   if (TARGET_ARM)
4998     {
4999       /* Everything except mem = const or mem = mem can be done easily */
5000
5001       if (!no_new_pseudos)
5002         {
5003           if (GET_CODE (operands[1]) == CONST_INT)
5004             {
5005               rtx reg = gen_reg_rtx (SImode);
5006
5007               emit_insn (gen_movsi (reg, operands[1]));
5008               operands[1] = gen_lowpart (QImode, reg);
5009             }
5010           if (GET_CODE (operands[1]) == MEM && optimize > 0)
5011             {
5012               rtx reg = gen_reg_rtx (SImode);
5013
5014               emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5015               operands[1] = gen_lowpart (QImode, reg);
5016             }
5017           if (GET_CODE (operands[0]) == MEM)
5018             operands[1] = force_reg (QImode, operands[1]);
5019         }
5020     }
5021   else /* TARGET_THUMB */
5022     {
5023       if (!no_new_pseudos)
5024         {
5025           if (GET_CODE (operands[0]) != REG)
5026             operands[1] = force_reg (QImode, operands[1]);
5027
5028           /* ??? We shouldn't really get invalid addresses here, but this can
5029              happen if we are passed a SP (never OK for HImode/QImode) or
5030              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
5031              HImode/QImode) relative address.  */
5032           /* ??? This should perhaps be fixed elsewhere, for instance, in
5033              fixup_stack_1, by checking for other kinds of invalid addresses,
5034              e.g. a bare reference to a virtual register.  This may confuse the
5035              alpha though, which must handle this case differently.  */
5036           if (GET_CODE (operands[0]) == MEM
5037               && !memory_address_p (GET_MODE (operands[0]),
5038                                      XEXP (operands[0], 0)))
5039             operands[0]
5040               = replace_equiv_address (operands[0],
5041                                        copy_to_reg (XEXP (operands[0], 0)));
5042           if (GET_CODE (operands[1]) == MEM
5043               && !memory_address_p (GET_MODE (operands[1]),
5044                                     XEXP (operands[1], 0)))
5045              operands[1]
5046                = replace_equiv_address (operands[1],
5047                                         copy_to_reg (XEXP (operands[1], 0)));
5048         }
5049       /* Handle loading a large integer during reload.  */
5050       else if (GET_CODE (operands[1]) == CONST_INT
5051                && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
5052         {
5053           /* Writing a constant to memory needs a scratch, which should
5054              be handled with SECONDARY_RELOADs.  */
5055           gcc_assert (GET_CODE (operands[0]) == REG);
5056
5057           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5058           emit_insn (gen_movsi (operands[0], operands[1]));
5059           DONE;
5060        }
5061     }
5062   "
5063 )
5064
5065
5066 (define_insn "*arm_movqi_insn"
5067   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5068         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5069   "TARGET_ARM
5070    && (   register_operand (operands[0], QImode)
5071        || register_operand (operands[1], QImode))"
5072   "@
5073    mov%?\\t%0, %1
5074    mvn%?\\t%0, #%B1
5075    ldr%?b\\t%0, %1
5076    str%?b\\t%1, %0"
5077   [(set_attr "type" "*,*,load1,store1")
5078    (set_attr "predicable" "yes")]
5079 )
5080
5081 (define_insn "*thumb_movqi_insn"
5082   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5083         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
5084   "TARGET_THUMB
5085    && (   register_operand (operands[0], QImode)
5086        || register_operand (operands[1], QImode))"
5087   "@
5088    add\\t%0, %1, #0
5089    ldrb\\t%0, %1
5090    strb\\t%1, %0
5091    mov\\t%0, %1
5092    mov\\t%0, %1
5093    mov\\t%0, %1"
5094   [(set_attr "length" "2")
5095    (set_attr "type" "*,load1,store1,*,*,*")
5096    (set_attr "pool_range" "*,32,*,*,*,*")]
5097 )
5098
5099 (define_expand "movsf"
5100   [(set (match_operand:SF 0 "general_operand" "")
5101         (match_operand:SF 1 "general_operand" ""))]
5102   "TARGET_EITHER"
5103   "
5104   if (TARGET_ARM)
5105     {
5106       if (GET_CODE (operands[0]) == MEM)
5107         operands[1] = force_reg (SFmode, operands[1]);
5108     }
5109   else /* TARGET_THUMB */
5110     {
5111       if (!no_new_pseudos)
5112         {
5113            if (GET_CODE (operands[0]) != REG)
5114              operands[1] = force_reg (SFmode, operands[1]);
5115         }
5116     }
5117   "
5118 )
5119
5120 (define_split
5121   [(set (match_operand:SF 0 "nonimmediate_operand" "")
5122         (match_operand:SF 1 "immediate_operand" ""))]
5123   "TARGET_ARM
5124    && !(TARGET_HARD_FLOAT && TARGET_FPA)
5125    && reload_completed
5126    && GET_CODE (operands[1]) == CONST_DOUBLE"
5127   [(set (match_dup 2) (match_dup 3))]
5128   "
5129   operands[2] = gen_lowpart (SImode, operands[0]);
5130   operands[3] = gen_lowpart (SImode, operands[1]);
5131   if (operands[2] == 0 || operands[3] == 0)
5132     FAIL;
5133   "
5134 )
5135
5136 (define_insn "*arm_movsf_soft_insn"
5137   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5138         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
5139   "TARGET_ARM
5140    && TARGET_SOFT_FLOAT
5141    && (GET_CODE (operands[0]) != MEM
5142        || register_operand (operands[1], SFmode))"
5143   "@
5144    mov%?\\t%0, %1
5145    ldr%?\\t%0, %1\\t%@ float
5146    str%?\\t%1, %0\\t%@ float"
5147   [(set_attr "length" "4,4,4")
5148    (set_attr "predicable" "yes")
5149    (set_attr "type" "*,load1,store1")
5150    (set_attr "pool_range" "*,4096,*")
5151    (set_attr "neg_pool_range" "*,4084,*")]
5152 )
5153
5154 ;;; ??? This should have alternatives for constants.
5155 (define_insn "*thumb_movsf_insn"
5156   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5157         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5158   "TARGET_THUMB
5159    && (   register_operand (operands[0], SFmode) 
5160        || register_operand (operands[1], SFmode))"
5161   "@
5162    add\\t%0, %1, #0
5163    ldmia\\t%1, {%0}
5164    stmia\\t%0, {%1}
5165    ldr\\t%0, %1
5166    str\\t%1, %0
5167    mov\\t%0, %1
5168    mov\\t%0, %1"
5169   [(set_attr "length" "2")
5170    (set_attr "type" "*,load1,store1,load1,store1,*,*")
5171    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5172 )
5173
5174 (define_expand "movdf"
5175   [(set (match_operand:DF 0 "general_operand" "")
5176         (match_operand:DF 1 "general_operand" ""))]
5177   "TARGET_EITHER"
5178   "
5179   if (TARGET_ARM)
5180     {
5181       if (GET_CODE (operands[0]) == MEM)
5182         operands[1] = force_reg (DFmode, operands[1]);
5183     }
5184   else /* TARGET_THUMB */
5185     {
5186       if (!no_new_pseudos)
5187         {
5188           if (GET_CODE (operands[0]) != REG)
5189             operands[1] = force_reg (DFmode, operands[1]);
5190         }
5191     }
5192   "
5193 )
5194
5195 ;; Reloading a df mode value stored in integer regs to memory can require a
5196 ;; scratch reg.
5197 (define_expand "reload_outdf"
5198   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5199    (match_operand:DF 1 "s_register_operand" "r")
5200    (match_operand:SI 2 "s_register_operand" "=&r")]
5201   "TARGET_ARM"
5202   "
5203   {
5204     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5205
5206     if (code == REG)
5207       operands[2] = XEXP (operands[0], 0);
5208     else if (code == POST_INC || code == PRE_DEC)
5209       {
5210         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5211         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5212         emit_insn (gen_movdi (operands[0], operands[1]));
5213         DONE;
5214       }
5215     else if (code == PRE_INC)
5216       {
5217         rtx reg = XEXP (XEXP (operands[0], 0), 0);
5218
5219         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5220         operands[2] = reg;
5221       }
5222     else if (code == POST_DEC)
5223       operands[2] = XEXP (XEXP (operands[0], 0), 0);
5224     else
5225       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5226                              XEXP (XEXP (operands[0], 0), 1)));
5227
5228     emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5229                             operands[1]));
5230
5231     if (code == POST_DEC)
5232       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5233
5234     DONE;
5235   }"
5236 )
5237
5238 (define_insn "*movdf_soft_insn"
5239   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5240         (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
5241   "TARGET_ARM && TARGET_SOFT_FLOAT
5242   "
5243   "*
5244   switch (which_alternative)
5245     {
5246     case 0:
5247     case 1:
5248     case 2:
5249       return \"#\";
5250     default:
5251       return output_move_double (operands);
5252     }
5253   "
5254   [(set_attr "length" "8,12,16,8,8")
5255    (set_attr "type" "*,*,*,load2,store2")
5256    (set_attr "pool_range" "1020")
5257    (set_attr "neg_pool_range" "1008")]
5258 )
5259
5260 ;;; ??? This should have alternatives for constants.
5261 ;;; ??? This was originally identical to the movdi_insn pattern.
5262 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5263 ;;; thumb_reorg with a memory reference.
5264 (define_insn "*thumb_movdf_insn"
5265   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5266         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5267   "TARGET_THUMB
5268    && (   register_operand (operands[0], DFmode)
5269        || register_operand (operands[1], DFmode))"
5270   "*
5271   switch (which_alternative)
5272     {
5273     default:
5274     case 0:
5275       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5276         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5277       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5278     case 1:
5279       return \"ldmia\\t%1, {%0, %H0}\";
5280     case 2:
5281       return \"stmia\\t%0, {%1, %H1}\";
5282     case 3:
5283       return thumb_load_double_from_address (operands);
5284     case 4:
5285       operands[2] = gen_rtx_MEM (SImode,
5286                                  plus_constant (XEXP (operands[0], 0), 4));
5287       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5288       return \"\";
5289     case 5:
5290       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5291         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5292       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5293     }
5294   "
5295   [(set_attr "length" "4,2,2,6,4,4")
5296    (set_attr "type" "*,load2,store2,load2,store2,*")
5297    (set_attr "pool_range" "*,*,*,1020,*,*")]
5298 )
5299
5300 (define_expand "movxf"
5301   [(set (match_operand:XF 0 "general_operand" "")
5302         (match_operand:XF 1 "general_operand" ""))]
5303   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
5304   "
5305   if (GET_CODE (operands[0]) == MEM)
5306     operands[1] = force_reg (XFmode, operands[1]);
5307   "
5308 )
5309
5310 ;; Vector Moves
5311 (define_expand "movv2si"
5312   [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5313         (match_operand:V2SI 1 "general_operand" ""))]
5314   "TARGET_REALLY_IWMMXT"
5315 {
5316 })
5317
5318 (define_expand "movv4hi"
5319   [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5320         (match_operand:V4HI 1 "general_operand" ""))]
5321   "TARGET_REALLY_IWMMXT"
5322 {
5323 })
5324
5325 (define_expand "movv8qi"
5326   [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5327         (match_operand:V8QI 1 "general_operand" ""))]
5328   "TARGET_REALLY_IWMMXT"
5329 {
5330 })
5331 \f
5332
5333 ;; load- and store-multiple insns
5334 ;; The arm can load/store any set of registers, provided that they are in
5335 ;; ascending order; but that is beyond GCC so stick with what it knows.
5336
5337 (define_expand "load_multiple"
5338   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5339                           (match_operand:SI 1 "" ""))
5340                      (use (match_operand:SI 2 "" ""))])]
5341   "TARGET_ARM"
5342 {
5343   HOST_WIDE_INT offset = 0;
5344
5345   /* Support only fixed point registers.  */
5346   if (GET_CODE (operands[2]) != CONST_INT
5347       || INTVAL (operands[2]) > 14
5348       || INTVAL (operands[2]) < 2
5349       || GET_CODE (operands[1]) != MEM
5350       || GET_CODE (operands[0]) != REG
5351       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5352       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5353     FAIL;
5354
5355   operands[3]
5356     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5357                              force_reg (SImode, XEXP (operands[1], 0)),
5358                              TRUE, FALSE, operands[1], &offset);
5359 })
5360
5361 ;; Load multiple with write-back
5362
5363 (define_insn "*ldmsi_postinc4"
5364   [(match_parallel 0 "load_multiple_operation"
5365     [(set (match_operand:SI 1 "s_register_operand" "=r")
5366           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5367                    (const_int 16)))
5368      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5369           (mem:SI (match_dup 2)))
5370      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5371           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5372      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5373           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5374      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5375           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5376   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5377   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5378   [(set_attr "type" "load4")
5379    (set_attr "predicable" "yes")]
5380 )
5381
5382 (define_insn "*ldmsi_postinc4_thumb"
5383   [(match_parallel 0 "load_multiple_operation"
5384     [(set (match_operand:SI 1 "s_register_operand" "=l")
5385           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5386                    (const_int 16)))
5387      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5388           (mem:SI (match_dup 2)))
5389      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5390           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5391      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5392           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5393      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5394           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5395   "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5396   "ldmia\\t%1!, {%3, %4, %5, %6}"
5397   [(set_attr "type" "load4")]
5398 )
5399
5400 (define_insn "*ldmsi_postinc3"
5401   [(match_parallel 0 "load_multiple_operation"
5402     [(set (match_operand:SI 1 "s_register_operand" "=r")
5403           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5404                    (const_int 12)))
5405      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5406           (mem:SI (match_dup 2)))
5407      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5408           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5409      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5410           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5411   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5412   "ldm%?ia\\t%1!, {%3, %4, %5}"
5413   [(set_attr "type" "load3")
5414    (set_attr "predicable" "yes")]
5415 )
5416
5417 (define_insn "*ldmsi_postinc2"
5418   [(match_parallel 0 "load_multiple_operation"
5419     [(set (match_operand:SI 1 "s_register_operand" "=r")
5420           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5421                    (const_int 8)))
5422      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5423           (mem:SI (match_dup 2)))
5424      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5425           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5426   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5427   "ldm%?ia\\t%1!, {%3, %4}"
5428   [(set_attr "type" "load2")
5429    (set_attr "predicable" "yes")]
5430 )
5431
5432 ;; Ordinary load multiple
5433
5434 (define_insn "*ldmsi4"
5435   [(match_parallel 0 "load_multiple_operation"
5436     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5437           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5438      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5439           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5440      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5441           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5442      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5443           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5444   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5445   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5446   [(set_attr "type" "load4")
5447    (set_attr "predicable" "yes")]
5448 )
5449
5450 (define_insn "*ldmsi3"
5451   [(match_parallel 0 "load_multiple_operation"
5452     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5453           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5454      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5455           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5456      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5457           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5458   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5459   "ldm%?ia\\t%1, {%2, %3, %4}"
5460   [(set_attr "type" "load3")
5461    (set_attr "predicable" "yes")]
5462 )
5463
5464 (define_insn "*ldmsi2"
5465   [(match_parallel 0 "load_multiple_operation"
5466     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5467           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5468      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5469           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5470   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5471   "ldm%?ia\\t%1, {%2, %3}"
5472   [(set_attr "type" "load2")
5473    (set_attr "predicable" "yes")]
5474 )
5475
5476 (define_expand "store_multiple"
5477   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5478                           (match_operand:SI 1 "" ""))
5479                      (use (match_operand:SI 2 "" ""))])]
5480   "TARGET_ARM"
5481 {
5482   HOST_WIDE_INT offset = 0;
5483
5484   /* Support only fixed point registers.  */
5485   if (GET_CODE (operands[2]) != CONST_INT
5486       || INTVAL (operands[2]) > 14
5487       || INTVAL (operands[2]) < 2
5488       || GET_CODE (operands[1]) != REG
5489       || GET_CODE (operands[0]) != MEM
5490       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5491       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5492     FAIL;
5493
5494   operands[3]
5495     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5496                               force_reg (SImode, XEXP (operands[0], 0)),
5497                               TRUE, FALSE, operands[0], &offset);
5498 })
5499
5500 ;; Store multiple with write-back
5501
5502 (define_insn "*stmsi_postinc4"
5503   [(match_parallel 0 "store_multiple_operation"
5504     [(set (match_operand:SI 1 "s_register_operand" "=r")
5505           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5506                    (const_int 16)))
5507      (set (mem:SI (match_dup 2))
5508           (match_operand:SI 3 "arm_hard_register_operand" ""))
5509      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5510           (match_operand:SI 4 "arm_hard_register_operand" ""))
5511      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5512           (match_operand:SI 5 "arm_hard_register_operand" ""))
5513      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5514           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5515   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5516   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5517   [(set_attr "predicable" "yes")
5518    (set_attr "type" "store4")]
5519 )
5520
5521 (define_insn "*stmsi_postinc4_thumb"
5522   [(match_parallel 0 "store_multiple_operation"
5523     [(set (match_operand:SI 1 "s_register_operand" "=l")
5524           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5525                    (const_int 16)))
5526      (set (mem:SI (match_dup 2))
5527           (match_operand:SI 3 "arm_hard_register_operand" ""))
5528      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5529           (match_operand:SI 4 "arm_hard_register_operand" ""))
5530      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5531           (match_operand:SI 5 "arm_hard_register_operand" ""))
5532      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5533           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5534   "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5535   "stmia\\t%1!, {%3, %4, %5, %6}"
5536   [(set_attr "type" "store4")]
5537 )
5538
5539 (define_insn "*stmsi_postinc3"
5540   [(match_parallel 0 "store_multiple_operation"
5541     [(set (match_operand:SI 1 "s_register_operand" "=r")
5542           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5543                    (const_int 12)))
5544      (set (mem:SI (match_dup 2))
5545           (match_operand:SI 3 "arm_hard_register_operand" ""))
5546      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5547           (match_operand:SI 4 "arm_hard_register_operand" ""))
5548      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5549           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5550   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5551   "stm%?ia\\t%1!, {%3, %4, %5}"
5552   [(set_attr "predicable" "yes")
5553    (set_attr "type" "store3")]
5554 )
5555
5556 (define_insn "*stmsi_postinc2"
5557   [(match_parallel 0 "store_multiple_operation"
5558     [(set (match_operand:SI 1 "s_register_operand" "=r")
5559           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5560                    (const_int 8)))
5561      (set (mem:SI (match_dup 2))
5562           (match_operand:SI 3 "arm_hard_register_operand" ""))
5563      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5564           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5565   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5566   "stm%?ia\\t%1!, {%3, %4}"
5567   [(set_attr "predicable" "yes")
5568    (set_attr "type" "store2")]
5569 )
5570
5571 ;; Ordinary store multiple
5572
5573 (define_insn "*stmsi4"
5574   [(match_parallel 0 "store_multiple_operation"
5575     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5576           (match_operand:SI 2 "arm_hard_register_operand" ""))
5577      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5578           (match_operand:SI 3 "arm_hard_register_operand" ""))
5579      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5580           (match_operand:SI 4 "arm_hard_register_operand" ""))
5581      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5582           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5583   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5584   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5585   [(set_attr "predicable" "yes")
5586    (set_attr "type" "store4")]
5587 )
5588
5589 (define_insn "*stmsi3"
5590   [(match_parallel 0 "store_multiple_operation"
5591     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5592           (match_operand:SI 2 "arm_hard_register_operand" ""))
5593      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5594           (match_operand:SI 3 "arm_hard_register_operand" ""))
5595      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5596           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5597   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5598   "stm%?ia\\t%1, {%2, %3, %4}"
5599   [(set_attr "predicable" "yes")
5600    (set_attr "type" "store3")]
5601 )
5602
5603 (define_insn "*stmsi2"
5604   [(match_parallel 0 "store_multiple_operation"
5605     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5606           (match_operand:SI 2 "arm_hard_register_operand" ""))
5607      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5608           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5609   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5610   "stm%?ia\\t%1, {%2, %3}"
5611   [(set_attr "predicable" "yes")
5612    (set_attr "type" "store2")]
5613 )
5614
5615 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5616 ;; We could let this apply for blocks of less than this, but it clobbers so
5617 ;; many registers that there is then probably a better way.
5618
5619 (define_expand "movmemqi"
5620   [(match_operand:BLK 0 "general_operand" "")
5621    (match_operand:BLK 1 "general_operand" "")
5622    (match_operand:SI 2 "const_int_operand" "")
5623    (match_operand:SI 3 "const_int_operand" "")]
5624   "TARGET_EITHER"
5625   "
5626   if (TARGET_ARM)
5627     {
5628       if (arm_gen_movmemqi (operands))
5629         DONE;
5630       FAIL;
5631     }
5632   else /* TARGET_THUMB */
5633     {
5634       if (   INTVAL (operands[3]) != 4
5635           || INTVAL (operands[2]) > 48)
5636         FAIL;
5637
5638       thumb_expand_movmemqi (operands);
5639       DONE;
5640     }
5641   "
5642 )
5643
5644 ;; Thumb block-move insns
5645
5646 (define_insn "movmem12b"
5647   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5648         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5649    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5650         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5651    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5652         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5653    (set (match_operand:SI 0 "register_operand" "=l")
5654         (plus:SI (match_dup 2) (const_int 12)))
5655    (set (match_operand:SI 1 "register_operand" "=l")
5656         (plus:SI (match_dup 3) (const_int 12)))
5657    (clobber (match_scratch:SI 4 "=&l"))
5658    (clobber (match_scratch:SI 5 "=&l"))
5659    (clobber (match_scratch:SI 6 "=&l"))]
5660   "TARGET_THUMB"
5661   "* return thumb_output_move_mem_multiple (3, operands);"
5662   [(set_attr "length" "4")
5663    ; This isn't entirely accurate...  It loads as well, but in terms of
5664    ; scheduling the following insn it is better to consider it as a store
5665    (set_attr "type" "store3")]
5666 )
5667
5668 (define_insn "movmem8b"
5669   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5670         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5671    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5672         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5673    (set (match_operand:SI 0 "register_operand" "=l")
5674         (plus:SI (match_dup 2) (const_int 8)))
5675    (set (match_operand:SI 1 "register_operand" "=l")
5676         (plus:SI (match_dup 3) (const_int 8)))
5677    (clobber (match_scratch:SI 4 "=&l"))
5678    (clobber (match_scratch:SI 5 "=&l"))]
5679   "TARGET_THUMB"
5680   "* return thumb_output_move_mem_multiple (2, operands);"
5681   [(set_attr "length" "4")
5682    ; This isn't entirely accurate...  It loads as well, but in terms of
5683    ; scheduling the following insn it is better to consider it as a store
5684    (set_attr "type" "store2")]
5685 )
5686
5687 \f
5688
5689 ;; Compare & branch insns
5690 ;; The range calculations are based as follows:
5691 ;; For forward branches, the address calculation returns the address of
5692 ;; the next instruction.  This is 2 beyond the branch instruction.
5693 ;; For backward branches, the address calculation returns the address of
5694 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5695 ;; instruction for the shortest sequence, and 4 before the branch instruction
5696 ;; if we have to jump around an unconditional branch.
5697 ;; To the basic branch range the PC offset must be added (this is +4).
5698 ;; So for forward branches we have 
5699 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5700 ;; And for backward branches we have 
5701 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5702 ;;
5703 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5704 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5705
5706 (define_expand "cbranchsi4"
5707   [(set (pc) (if_then_else
5708               (match_operator 0 "arm_comparison_operator"
5709                [(match_operand:SI 1 "s_register_operand" "")
5710                 (match_operand:SI 2 "nonmemory_operand" "")])
5711               (label_ref (match_operand 3 "" ""))
5712               (pc)))]
5713   "TARGET_THUMB"
5714   "
5715   if (thumb_cmpneg_operand (operands[2], SImode))
5716     {
5717       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5718                                               operands[3], operands[0]));
5719       DONE;
5720     }
5721   if (!thumb_cmp_operand (operands[2], SImode))
5722     operands[2] = force_reg (SImode, operands[2]);
5723   ")
5724
5725 (define_insn "*cbranchsi4_insn"
5726   [(set (pc) (if_then_else
5727               (match_operator 0 "arm_comparison_operator"
5728                [(match_operand:SI 1 "s_register_operand" "l,*h")
5729                 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5730               (label_ref (match_operand 3 "" ""))
5731               (pc)))]
5732   "TARGET_THUMB"
5733   "*
5734   output_asm_insn (\"cmp\\t%1, %2\", operands);
5735
5736   switch (get_attr_length (insn))
5737     {
5738     case 4:  return \"b%d0\\t%l3\";
5739     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5740     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5741     }
5742   "
5743   [(set (attr "far_jump")
5744         (if_then_else
5745             (eq_attr "length" "8")
5746             (const_string "yes")
5747             (const_string "no")))
5748    (set (attr "length") 
5749         (if_then_else
5750             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5751                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5752             (const_int 4)
5753             (if_then_else
5754                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5755                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5756                 (const_int 6)
5757                 (const_int 8))))]
5758 )
5759
5760 (define_insn "cbranchsi4_scratch"
5761   [(set (pc) (if_then_else
5762               (match_operator 4 "arm_comparison_operator"
5763                [(match_operand:SI 1 "s_register_operand" "l,0")
5764                 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5765               (label_ref (match_operand 3 "" ""))
5766               (pc)))
5767    (clobber (match_scratch:SI 0 "=l,l"))]
5768   "TARGET_THUMB"
5769   "*
5770   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5771
5772   switch (get_attr_length (insn))
5773     {
5774     case 4:  return \"b%d4\\t%l3\";
5775     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5776     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5777     }
5778   "
5779   [(set (attr "far_jump")
5780         (if_then_else
5781             (eq_attr "length" "8")
5782             (const_string "yes")
5783             (const_string "no")))
5784    (set (attr "length") 
5785         (if_then_else
5786             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5787                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5788             (const_int 4)
5789             (if_then_else
5790                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5791                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5792                 (const_int 6)
5793                 (const_int 8))))]
5794 )
5795 (define_insn "*movsi_cbranchsi4"
5796   [(set (pc)
5797         (if_then_else
5798          (match_operator 3 "arm_comparison_operator"
5799           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5800            (const_int 0)])
5801          (label_ref (match_operand 2 "" ""))
5802          (pc)))
5803    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5804         (match_dup 1))]
5805   "TARGET_THUMB"
5806   "*{
5807   if (which_alternative == 0)
5808     output_asm_insn (\"cmp\t%0, #0\", operands);
5809   else if (which_alternative == 1)
5810     output_asm_insn (\"sub\t%0, %1, #0\", operands);
5811   else
5812     {
5813       output_asm_insn (\"cmp\t%1, #0\", operands);
5814       if (which_alternative == 2)
5815         output_asm_insn (\"mov\t%0, %1\", operands);
5816       else
5817         output_asm_insn (\"str\t%1, %0\", operands);
5818     }
5819   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5820     {
5821     case 4:  return \"b%d3\\t%l2\";
5822     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5823     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5824     }
5825   }"
5826   [(set (attr "far_jump")
5827         (if_then_else
5828             (ior (and (gt (symbol_ref ("which_alternative"))
5829                           (const_int 1))
5830                       (eq_attr "length" "8"))
5831                  (eq_attr "length" "10"))
5832             (const_string "yes")
5833             (const_string "no")))
5834    (set (attr "length")
5835      (if_then_else
5836        (le (symbol_ref ("which_alternative"))
5837                        (const_int 1))
5838        (if_then_else
5839          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5840               (le (minus (match_dup 2) (pc)) (const_int 256)))
5841          (const_int 4)
5842          (if_then_else
5843            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5844                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5845            (const_int 6)
5846            (const_int 8)))
5847        (if_then_else
5848          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5849               (le (minus (match_dup 2) (pc)) (const_int 256)))
5850          (const_int 6)
5851          (if_then_else
5852            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5853                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5854            (const_int 8)
5855            (const_int 10)))))]
5856 )
5857
5858 (define_insn "*negated_cbranchsi4"
5859   [(set (pc)
5860         (if_then_else
5861          (match_operator 0 "equality_operator"
5862           [(match_operand:SI 1 "s_register_operand" "l")
5863            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5864          (label_ref (match_operand 3 "" ""))
5865          (pc)))]
5866   "TARGET_THUMB"
5867   "*
5868   output_asm_insn (\"cmn\\t%1, %2\", operands);
5869   switch (get_attr_length (insn))
5870     {
5871     case 4:  return \"b%d0\\t%l3\";
5872     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5873     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5874     }
5875   "
5876   [(set (attr "far_jump")
5877         (if_then_else
5878             (eq_attr "length" "8")
5879             (const_string "yes")
5880             (const_string "no")))
5881    (set (attr "length") 
5882         (if_then_else
5883             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5884                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5885             (const_int 4)
5886             (if_then_else
5887                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5888                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5889                 (const_int 6)
5890                 (const_int 8))))]
5891 )
5892
5893 (define_insn "*tbit_cbranch"
5894   [(set (pc)
5895         (if_then_else
5896          (match_operator 0 "equality_operator"
5897           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5898                             (const_int 1)
5899                             (match_operand:SI 2 "const_int_operand" "i"))
5900            (const_int 0)])
5901          (label_ref (match_operand 3 "" ""))
5902          (pc)))
5903    (clobber (match_scratch:SI 4 "=l"))]
5904   "TARGET_THUMB"
5905   "*
5906   {
5907   rtx op[3];
5908   op[0] = operands[4];
5909   op[1] = operands[1];
5910   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5911
5912   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5913   switch (get_attr_length (insn))
5914     {
5915     case 4:  return \"b%d0\\t%l3\";
5916     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5917     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5918     }
5919   }"
5920   [(set (attr "far_jump")
5921         (if_then_else
5922             (eq_attr "length" "8")
5923             (const_string "yes")
5924             (const_string "no")))
5925    (set (attr "length") 
5926         (if_then_else
5927             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5928                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5929             (const_int 4)
5930             (if_then_else
5931                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5932                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5933                 (const_int 6)
5934                 (const_int 8))))]
5935 )
5936   
5937 (define_insn "*tstsi3_cbranch"
5938   [(set (pc)
5939         (if_then_else
5940          (match_operator 3 "equality_operator"
5941           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5942                    (match_operand:SI 1 "s_register_operand" "l"))
5943            (const_int 0)])
5944          (label_ref (match_operand 2 "" ""))
5945          (pc)))]
5946   "TARGET_THUMB"
5947   "*
5948   {
5949   output_asm_insn (\"tst\\t%0, %1\", operands);
5950   switch (get_attr_length (insn))
5951     {
5952     case 4:  return \"b%d3\\t%l2\";
5953     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5954     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5955     }
5956   }"
5957   [(set (attr "far_jump")
5958         (if_then_else
5959             (eq_attr "length" "8")
5960             (const_string "yes")
5961             (const_string "no")))
5962    (set (attr "length") 
5963         (if_then_else
5964             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5965                  (le (minus (match_dup 2) (pc)) (const_int 256)))
5966             (const_int 4)
5967             (if_then_else
5968                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5969                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
5970                 (const_int 6)
5971                 (const_int 8))))]
5972 )
5973   
5974 (define_insn "*andsi3_cbranch"
5975   [(set (pc)
5976         (if_then_else
5977          (match_operator 5 "equality_operator"
5978           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5979                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5980            (const_int 0)])
5981          (label_ref (match_operand 4 "" ""))
5982          (pc)))
5983    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5984         (and:SI (match_dup 2) (match_dup 3)))
5985    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5986   "TARGET_THUMB"
5987   "*
5988   {
5989   if (which_alternative == 0)
5990     output_asm_insn (\"and\\t%0, %3\", operands);
5991   else if (which_alternative == 1)
5992     {
5993       output_asm_insn (\"and\\t%1, %3\", operands);
5994       output_asm_insn (\"mov\\t%0, %1\", operands);
5995     }
5996   else
5997     {
5998       output_asm_insn (\"and\\t%1, %3\", operands);
5999       output_asm_insn (\"str\\t%1, %0\", operands);
6000     }
6001
6002   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6003     {
6004     case 4:  return \"b%d5\\t%l4\";
6005     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6006     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6007     }
6008   }"
6009   [(set (attr "far_jump")
6010         (if_then_else
6011             (ior (and (eq (symbol_ref ("which_alternative"))
6012                           (const_int 0))
6013                       (eq_attr "length" "8"))
6014                  (eq_attr "length" "10"))
6015             (const_string "yes")
6016             (const_string "no")))
6017    (set (attr "length")
6018      (if_then_else
6019        (eq (symbol_ref ("which_alternative"))
6020                        (const_int 0))
6021        (if_then_else
6022          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6023               (le (minus (match_dup 4) (pc)) (const_int 256)))
6024          (const_int 4)
6025          (if_then_else
6026            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6027                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6028            (const_int 6)
6029            (const_int 8)))
6030        (if_then_else
6031          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6032               (le (minus (match_dup 4) (pc)) (const_int 256)))
6033          (const_int 6)
6034          (if_then_else
6035            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6036                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6037            (const_int 8)
6038            (const_int 10)))))]
6039 )
6040
6041 (define_insn "*orrsi3_cbranch_scratch"
6042   [(set (pc)
6043         (if_then_else
6044          (match_operator 4 "equality_operator"
6045           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6046                    (match_operand:SI 2 "s_register_operand" "l"))
6047            (const_int 0)])
6048          (label_ref (match_operand 3 "" ""))
6049          (pc)))
6050    (clobber (match_scratch:SI 0 "=l"))]
6051   "TARGET_THUMB"
6052   "*
6053   {
6054   output_asm_insn (\"orr\\t%0, %2\", operands);
6055   switch (get_attr_length (insn))
6056     {
6057     case 4:  return \"b%d4\\t%l3\";
6058     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6059     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6060     }
6061   }"
6062   [(set (attr "far_jump")
6063         (if_then_else
6064             (eq_attr "length" "8")
6065             (const_string "yes")
6066             (const_string "no")))
6067    (set (attr "length") 
6068         (if_then_else
6069             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6070                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6071             (const_int 4)
6072             (if_then_else
6073                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6074                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6075                 (const_int 6)
6076                 (const_int 8))))]
6077 )
6078   
6079 (define_insn "*orrsi3_cbranch"
6080   [(set (pc)
6081         (if_then_else
6082          (match_operator 5 "equality_operator"
6083           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6084                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6085            (const_int 0)])
6086          (label_ref (match_operand 4 "" ""))
6087          (pc)))
6088    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6089         (ior:SI (match_dup 2) (match_dup 3)))
6090    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6091   "TARGET_THUMB"
6092   "*
6093   {
6094   if (which_alternative == 0)
6095     output_asm_insn (\"orr\\t%0, %3\", operands);
6096   else if (which_alternative == 1)
6097     {
6098       output_asm_insn (\"orr\\t%1, %3\", operands);
6099       output_asm_insn (\"mov\\t%0, %1\", operands);
6100     }
6101   else
6102     {
6103       output_asm_insn (\"orr\\t%1, %3\", operands);
6104       output_asm_insn (\"str\\t%1, %0\", operands);
6105     }
6106
6107   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6108     {
6109     case 4:  return \"b%d5\\t%l4\";
6110     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6111     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6112     }
6113   }"
6114   [(set (attr "far_jump")
6115         (if_then_else
6116             (ior (and (eq (symbol_ref ("which_alternative"))
6117                           (const_int 0))
6118                       (eq_attr "length" "8"))
6119                  (eq_attr "length" "10"))
6120             (const_string "yes")
6121             (const_string "no")))
6122    (set (attr "length")
6123      (if_then_else
6124        (eq (symbol_ref ("which_alternative"))
6125                        (const_int 0))
6126        (if_then_else
6127          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6128               (le (minus (match_dup 4) (pc)) (const_int 256)))
6129          (const_int 4)
6130          (if_then_else
6131            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6132                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6133            (const_int 6)
6134            (const_int 8)))
6135        (if_then_else
6136          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6137               (le (minus (match_dup 4) (pc)) (const_int 256)))
6138          (const_int 6)
6139          (if_then_else
6140            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6141                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6142            (const_int 8)
6143            (const_int 10)))))]
6144 )
6145
6146 (define_insn "*xorsi3_cbranch_scratch"
6147   [(set (pc)
6148         (if_then_else
6149          (match_operator 4 "equality_operator"
6150           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6151                    (match_operand:SI 2 "s_register_operand" "l"))
6152            (const_int 0)])
6153          (label_ref (match_operand 3 "" ""))
6154          (pc)))
6155    (clobber (match_scratch:SI 0 "=l"))]
6156   "TARGET_THUMB"
6157   "*
6158   {
6159   output_asm_insn (\"eor\\t%0, %2\", operands);
6160   switch (get_attr_length (insn))
6161     {
6162     case 4:  return \"b%d4\\t%l3\";
6163     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6164     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6165     }
6166   }"
6167   [(set (attr "far_jump")
6168         (if_then_else
6169             (eq_attr "length" "8")
6170             (const_string "yes")
6171             (const_string "no")))
6172    (set (attr "length") 
6173         (if_then_else
6174             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6175                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6176             (const_int 4)
6177             (if_then_else
6178                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6179                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6180                 (const_int 6)
6181                 (const_int 8))))]
6182 )
6183   
6184 (define_insn "*xorsi3_cbranch"
6185   [(set (pc)
6186         (if_then_else
6187          (match_operator 5 "equality_operator"
6188           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6189                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6190            (const_int 0)])
6191          (label_ref (match_operand 4 "" ""))
6192          (pc)))
6193    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6194         (xor:SI (match_dup 2) (match_dup 3)))
6195    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6196   "TARGET_THUMB"
6197   "*
6198   {
6199   if (which_alternative == 0)
6200     output_asm_insn (\"eor\\t%0, %3\", operands);
6201   else if (which_alternative == 1)
6202     {
6203       output_asm_insn (\"eor\\t%1, %3\", operands);
6204       output_asm_insn (\"mov\\t%0, %1\", operands);
6205     }
6206   else
6207     {
6208       output_asm_insn (\"eor\\t%1, %3\", operands);
6209       output_asm_insn (\"str\\t%1, %0\", operands);
6210     }
6211
6212   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6213     {
6214     case 4:  return \"b%d5\\t%l4\";
6215     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6216     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6217     }
6218   }"
6219   [(set (attr "far_jump")
6220         (if_then_else
6221             (ior (and (eq (symbol_ref ("which_alternative"))
6222                           (const_int 0))
6223                       (eq_attr "length" "8"))
6224                  (eq_attr "length" "10"))
6225             (const_string "yes")
6226             (const_string "no")))
6227    (set (attr "length")
6228      (if_then_else
6229        (eq (symbol_ref ("which_alternative"))
6230                        (const_int 0))
6231        (if_then_else
6232          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6233               (le (minus (match_dup 4) (pc)) (const_int 256)))
6234          (const_int 4)
6235          (if_then_else
6236            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6237                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6238            (const_int 6)
6239            (const_int 8)))
6240        (if_then_else
6241          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6242               (le (minus (match_dup 4) (pc)) (const_int 256)))
6243          (const_int 6)
6244          (if_then_else
6245            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6246                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6247            (const_int 8)
6248            (const_int 10)))))]
6249 )
6250
6251 (define_insn "*bicsi3_cbranch_scratch"
6252   [(set (pc)
6253         (if_then_else
6254          (match_operator 4 "equality_operator"
6255           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6256                    (match_operand:SI 1 "s_register_operand" "0"))
6257            (const_int 0)])
6258          (label_ref (match_operand 3 "" ""))
6259          (pc)))
6260    (clobber (match_scratch:SI 0 "=l"))]
6261   "TARGET_THUMB"
6262   "*
6263   {
6264   output_asm_insn (\"bic\\t%0, %2\", operands);
6265   switch (get_attr_length (insn))
6266     {
6267     case 4:  return \"b%d4\\t%l3\";
6268     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6269     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6270     }
6271   }"
6272   [(set (attr "far_jump")
6273         (if_then_else
6274             (eq_attr "length" "8")
6275             (const_string "yes")
6276             (const_string "no")))
6277    (set (attr "length") 
6278         (if_then_else
6279             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6280                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6281             (const_int 4)
6282             (if_then_else
6283                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6284                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6285                 (const_int 6)
6286                 (const_int 8))))]
6287 )
6288   
6289 (define_insn "*bicsi3_cbranch"
6290   [(set (pc)
6291         (if_then_else
6292          (match_operator 5 "equality_operator"
6293           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6294                    (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6295            (const_int 0)])
6296          (label_ref (match_operand 4 "" ""))
6297          (pc)))
6298    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6299         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6300    (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6301   "TARGET_THUMB"
6302   "*
6303   {
6304   if (which_alternative == 0)
6305     output_asm_insn (\"bic\\t%0, %3\", operands);
6306   else if (which_alternative <= 2)
6307     {
6308       output_asm_insn (\"bic\\t%1, %3\", operands);
6309       /* It's ok if OP0 is a lo-reg, even though the mov will set the
6310          conditions again, since we're only testing for equality.  */
6311       output_asm_insn (\"mov\\t%0, %1\", operands);
6312     }
6313   else
6314     {
6315       output_asm_insn (\"bic\\t%1, %3\", operands);
6316       output_asm_insn (\"str\\t%1, %0\", operands);
6317     }
6318
6319   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6320     {
6321     case 4:  return \"b%d5\\t%l4\";
6322     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6323     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6324     }
6325   }"
6326   [(set (attr "far_jump")
6327         (if_then_else
6328             (ior (and (eq (symbol_ref ("which_alternative"))
6329                           (const_int 0))
6330                       (eq_attr "length" "8"))
6331                  (eq_attr "length" "10"))
6332             (const_string "yes")
6333             (const_string "no")))
6334    (set (attr "length")
6335      (if_then_else
6336        (eq (symbol_ref ("which_alternative"))
6337                        (const_int 0))
6338        (if_then_else
6339          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6340               (le (minus (match_dup 4) (pc)) (const_int 256)))
6341          (const_int 4)
6342          (if_then_else
6343            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6344                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6345            (const_int 6)
6346            (const_int 8)))
6347        (if_then_else
6348          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6349               (le (minus (match_dup 4) (pc)) (const_int 256)))
6350          (const_int 6)
6351          (if_then_else
6352            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6353                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6354            (const_int 8)
6355            (const_int 10)))))]
6356 )
6357
6358 (define_insn "*cbranchne_decr1"
6359   [(set (pc)
6360         (if_then_else (match_operator 3 "equality_operator"
6361                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6362                         (const_int 0)])
6363                       (label_ref (match_operand 4 "" ""))
6364                       (pc)))
6365    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6366         (plus:SI (match_dup 2) (const_int -1)))
6367    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6368   "TARGET_THUMB"
6369   "*
6370    {
6371      rtx cond[2];
6372      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6373                                 ? GEU : LTU),
6374                                VOIDmode, operands[2], const1_rtx);
6375      cond[1] = operands[4];
6376
6377      if (which_alternative == 0)
6378        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6379      else if (which_alternative == 1)
6380        {
6381          /* We must provide an alternative for a hi reg because reload 
6382             cannot handle output reloads on a jump instruction, but we
6383             can't subtract into that.  Fortunately a mov from lo to hi
6384             does not clobber the condition codes.  */
6385          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6386          output_asm_insn (\"mov\\t%0, %1\", operands);
6387        }
6388      else
6389        {
6390          /* Similarly, but the target is memory.  */
6391          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6392          output_asm_insn (\"str\\t%1, %0\", operands);
6393        }
6394
6395      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6396        {
6397          case 4:
6398            output_asm_insn (\"b%d0\\t%l1\", cond);
6399            return \"\";
6400          case 6:
6401            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6402            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6403          default:
6404            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6405            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6406        }
6407    }
6408   "
6409   [(set (attr "far_jump")
6410         (if_then_else
6411             (ior (and (eq (symbol_ref ("which_alternative"))
6412                           (const_int 0))
6413                       (eq_attr "length" "8"))
6414                  (eq_attr "length" "10"))
6415             (const_string "yes")
6416             (const_string "no")))
6417    (set_attr_alternative "length"
6418       [
6419        ;; Alternative 0
6420        (if_then_else
6421          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6422               (le (minus (match_dup 4) (pc)) (const_int 256)))
6423          (const_int 4)
6424          (if_then_else
6425            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6426                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6427            (const_int 6)
6428            (const_int 8)))
6429        ;; Alternative 1
6430        (if_then_else
6431          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6432               (le (minus (match_dup 4) (pc)) (const_int 256)))
6433          (const_int 6)
6434          (if_then_else
6435            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6436                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6437            (const_int 8)
6438            (const_int 10)))
6439        ;; Alternative 2
6440        (if_then_else
6441          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6442               (le (minus (match_dup 4) (pc)) (const_int 256)))
6443          (const_int 6)
6444          (if_then_else
6445            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6446                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6447            (const_int 8)
6448            (const_int 10)))
6449        ;; Alternative 3
6450        (if_then_else
6451          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6452               (le (minus (match_dup 4) (pc)) (const_int 256)))
6453          (const_int 6)
6454          (if_then_else
6455            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6456                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6457            (const_int 8)
6458            (const_int 10)))])]
6459 )
6460
6461 (define_insn "*addsi3_cbranch"
6462   [(set (pc)
6463         (if_then_else
6464          (match_operator 4 "comparison_operator"
6465           [(plus:SI
6466             (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6467             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6468            (const_int 0)])
6469          (label_ref (match_operand 5 "" ""))
6470          (pc)))
6471    (set
6472     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6473     (plus:SI (match_dup 2) (match_dup 3)))
6474    (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6475   "TARGET_THUMB
6476    && (GET_CODE (operands[4]) == EQ
6477        || GET_CODE (operands[4]) == NE
6478        || GET_CODE (operands[4]) == GE
6479        || GET_CODE (operands[4]) == LT)"
6480   "*
6481    {
6482      rtx cond[3];
6483
6484      
6485      cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6486      cond[1] = operands[2];
6487      cond[2] = operands[3];
6488
6489      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6490        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6491      else
6492        output_asm_insn (\"add\\t%0, %1, %2\", cond);
6493
6494      if (which_alternative >= 3
6495          && which_alternative < 4)
6496        output_asm_insn (\"mov\\t%0, %1\", operands);
6497      else if (which_alternative >= 4)
6498        output_asm_insn (\"str\\t%1, %0\", operands);
6499
6500      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6501        {
6502          case 4:
6503            return \"b%d4\\t%l5\";
6504          case 6:
6505            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6506          default:
6507            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6508        }
6509    }
6510   "
6511   [(set (attr "far_jump")
6512         (if_then_else
6513             (ior (and (lt (symbol_ref ("which_alternative"))
6514                           (const_int 3))
6515                       (eq_attr "length" "8"))
6516                  (eq_attr "length" "10"))
6517             (const_string "yes")
6518             (const_string "no")))
6519    (set (attr "length")
6520      (if_then_else
6521        (lt (symbol_ref ("which_alternative"))
6522                        (const_int 3))
6523        (if_then_else
6524          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6525               (le (minus (match_dup 5) (pc)) (const_int 256)))
6526          (const_int 4)
6527          (if_then_else
6528            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6529                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6530            (const_int 6)
6531            (const_int 8)))
6532        (if_then_else
6533          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6534               (le (minus (match_dup 5) (pc)) (const_int 256)))
6535          (const_int 6)
6536          (if_then_else
6537            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6538                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6539            (const_int 8)
6540            (const_int 10)))))]
6541 )
6542
6543 (define_insn "*addsi3_cbranch_scratch"
6544   [(set (pc)
6545         (if_then_else
6546          (match_operator 3 "comparison_operator"
6547           [(plus:SI
6548             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6549             (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
6550            (const_int 0)])
6551          (label_ref (match_operand 4 "" ""))
6552          (pc)))
6553    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6554   "TARGET_THUMB
6555    && (GET_CODE (operands[3]) == EQ
6556        || GET_CODE (operands[3]) == NE
6557        || GET_CODE (operands[3]) == GE
6558        || GET_CODE (operands[3]) == LT)"
6559   "*
6560    {
6561      switch (which_alternative)
6562        {
6563        case 0:
6564          output_asm_insn (\"cmp\t%1, #%n2\", operands);
6565          break;
6566        case 1:
6567          output_asm_insn (\"cmn\t%1, %2\", operands);
6568          break;
6569        case 2:
6570          if (INTVAL (operands[2]) < 0)
6571            output_asm_insn (\"sub\t%0, %1, %2\", operands);
6572          else
6573            output_asm_insn (\"add\t%0, %1, %2\", operands);
6574          break;
6575        case 3:
6576          if (INTVAL (operands[2]) < 0)
6577            output_asm_insn (\"sub\t%0, %0, %2\", operands);
6578          else
6579            output_asm_insn (\"add\t%0, %0, %2\", operands);
6580          break;
6581        }
6582
6583      switch (get_attr_length (insn))
6584        {
6585          case 4:
6586            return \"b%d3\\t%l4\";
6587          case 6:
6588            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6589          default:
6590            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6591        }
6592    }
6593   "
6594   [(set (attr "far_jump")
6595         (if_then_else
6596             (eq_attr "length" "8")
6597             (const_string "yes")
6598             (const_string "no")))
6599    (set (attr "length")
6600        (if_then_else
6601          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6602               (le (minus (match_dup 4) (pc)) (const_int 256)))
6603          (const_int 4)
6604          (if_then_else
6605            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6606                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6607            (const_int 6)
6608            (const_int 8))))]
6609 )
6610
6611 (define_insn "*subsi3_cbranch"
6612   [(set (pc)
6613         (if_then_else
6614          (match_operator 4 "comparison_operator"
6615           [(minus:SI
6616             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6617             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6618            (const_int 0)])
6619          (label_ref (match_operand 5 "" ""))
6620          (pc)))
6621    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6622         (minus:SI (match_dup 2) (match_dup 3)))
6623    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6624   "TARGET_THUMB
6625    && (GET_CODE (operands[4]) == EQ
6626        || GET_CODE (operands[4]) == NE
6627        || GET_CODE (operands[4]) == GE
6628        || GET_CODE (operands[4]) == LT)"
6629   "*
6630    {
6631      if (which_alternative == 0)
6632        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6633      else if (which_alternative == 1)
6634        {
6635          /* We must provide an alternative for a hi reg because reload 
6636             cannot handle output reloads on a jump instruction, but we
6637             can't subtract into that.  Fortunately a mov from lo to hi
6638             does not clobber the condition codes.  */
6639          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6640          output_asm_insn (\"mov\\t%0, %1\", operands);
6641        }
6642      else
6643        {
6644          /* Similarly, but the target is memory.  */
6645          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6646          output_asm_insn (\"str\\t%1, %0\", operands);
6647        }
6648
6649      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6650        {
6651          case 4:
6652            return \"b%d4\\t%l5\";
6653          case 6:
6654            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6655          default:
6656            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6657        }
6658    }
6659   "
6660   [(set (attr "far_jump")
6661         (if_then_else
6662             (ior (and (eq (symbol_ref ("which_alternative"))
6663                           (const_int 0))
6664                       (eq_attr "length" "8"))
6665                  (eq_attr "length" "10"))
6666             (const_string "yes")
6667             (const_string "no")))
6668    (set (attr "length")
6669      (if_then_else
6670        (eq (symbol_ref ("which_alternative"))
6671                        (const_int 0))
6672        (if_then_else
6673          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6674               (le (minus (match_dup 5) (pc)) (const_int 256)))
6675          (const_int 4)
6676          (if_then_else
6677            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6678                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6679            (const_int 6)
6680            (const_int 8)))
6681        (if_then_else
6682          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6683               (le (minus (match_dup 5) (pc)) (const_int 256)))
6684          (const_int 6)
6685          (if_then_else
6686            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6687                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6688            (const_int 8)
6689            (const_int 10)))))]
6690 )
6691
6692 (define_insn "*subsi3_cbranch_scratch"
6693   [(set (pc)
6694         (if_then_else
6695          (match_operator 0 "arm_comparison_operator"
6696           [(minus:SI (match_operand:SI 1 "register_operand" "l")
6697                      (match_operand:SI 2 "nonmemory_operand" "l"))
6698            (const_int 0)])
6699          (label_ref (match_operand 3 "" ""))
6700          (pc)))]
6701   "TARGET_THUMB
6702    && (GET_CODE (operands[0]) == EQ
6703        || GET_CODE (operands[0]) == NE
6704        || GET_CODE (operands[0]) == GE
6705        || GET_CODE (operands[0]) == LT)"
6706   "*
6707   output_asm_insn (\"cmp\\t%1, %2\", operands);
6708   switch (get_attr_length (insn))
6709     {
6710     case 4:  return \"b%d0\\t%l3\";
6711     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6712     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6713     }
6714   "
6715   [(set (attr "far_jump")
6716         (if_then_else
6717             (eq_attr "length" "8")
6718             (const_string "yes")
6719             (const_string "no")))
6720    (set (attr "length") 
6721         (if_then_else
6722             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6723                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6724             (const_int 4)
6725             (if_then_else
6726                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6727                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6728                 (const_int 6)
6729                 (const_int 8))))]
6730 )
6731
6732 ;; Comparison and test insns
6733
6734 (define_expand "cmpsi"
6735   [(match_operand:SI 0 "s_register_operand" "")
6736    (match_operand:SI 1 "arm_add_operand" "")]
6737   "TARGET_ARM"
6738   "{
6739     arm_compare_op0 = operands[0];
6740     arm_compare_op1 = operands[1];
6741     DONE;
6742   }"
6743 )
6744
6745 (define_expand "cmpsf"
6746   [(match_operand:SF 0 "s_register_operand" "")
6747    (match_operand:SF 1 "arm_float_compare_operand" "")]
6748   "TARGET_ARM && TARGET_HARD_FLOAT"
6749   "
6750   arm_compare_op0 = operands[0];
6751   arm_compare_op1 = operands[1];
6752   DONE;
6753   "
6754 )
6755
6756 (define_expand "cmpdf"
6757   [(match_operand:DF 0 "s_register_operand" "")
6758    (match_operand:DF 1 "arm_float_compare_operand" "")]
6759   "TARGET_ARM && TARGET_HARD_FLOAT"
6760   "
6761   arm_compare_op0 = operands[0];
6762   arm_compare_op1 = operands[1];
6763   DONE;
6764   "
6765 )
6766
6767 (define_insn "*arm_cmpsi_insn"
6768   [(set (reg:CC CC_REGNUM)
6769         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6770                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
6771   "TARGET_ARM"
6772   "@
6773    cmp%?\\t%0, %1
6774    cmn%?\\t%0, #%n1"
6775   [(set_attr "conds" "set")]
6776 )
6777
6778 (define_insn "*cmpsi_shiftsi"
6779   [(set (reg:CC CC_REGNUM)
6780         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
6781                     (match_operator:SI  3 "shift_operator"
6782                      [(match_operand:SI 1 "s_register_operand" "r")
6783                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
6784   "TARGET_ARM"
6785   "cmp%?\\t%0, %1%S3"
6786   [(set_attr "conds" "set")
6787    (set_attr "shift" "1")
6788    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6789                       (const_string "alu_shift")
6790                       (const_string "alu_shift_reg")))]
6791 )
6792
6793 (define_insn "*cmpsi_shiftsi_swp"
6794   [(set (reg:CC_SWP CC_REGNUM)
6795         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6796                          [(match_operand:SI 1 "s_register_operand" "r")
6797                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
6798                         (match_operand:SI 0 "s_register_operand" "r")))]
6799   "TARGET_ARM"
6800   "cmp%?\\t%0, %1%S3"
6801   [(set_attr "conds" "set")
6802    (set_attr "shift" "1")
6803    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6804                       (const_string "alu_shift")
6805                       (const_string "alu_shift_reg")))]
6806 )
6807
6808 (define_insn "*cmpsi_negshiftsi_si"
6809   [(set (reg:CC_Z CC_REGNUM)
6810         (compare:CC_Z
6811          (neg:SI (match_operator:SI 1 "shift_operator"
6812                     [(match_operand:SI 2 "s_register_operand" "r")
6813                      (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6814          (match_operand:SI 0 "s_register_operand" "r")))]
6815   "TARGET_ARM"
6816   "cmn%?\\t%0, %2%S1"
6817   [(set_attr "conds" "set")
6818    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
6819                                     (const_string "alu_shift")
6820                                     (const_string "alu_shift_reg")))]
6821 )
6822
6823 ;; Cirrus SF compare instruction
6824 (define_insn "*cirrus_cmpsf"
6825   [(set (reg:CCFP CC_REGNUM)
6826         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6827                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
6828   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6829   "cfcmps%?\\tr15, %V0, %V1"
6830   [(set_attr "type"   "mav_farith")
6831    (set_attr "cirrus" "compare")]
6832 )
6833
6834 ;; Cirrus DF compare instruction
6835 (define_insn "*cirrus_cmpdf"
6836   [(set (reg:CCFP CC_REGNUM)
6837         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6838                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
6839   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6840   "cfcmpd%?\\tr15, %V0, %V1"
6841   [(set_attr "type"   "mav_farith")
6842    (set_attr "cirrus" "compare")]
6843 )
6844
6845 ;; Cirrus DI compare instruction
6846 (define_expand "cmpdi"
6847   [(match_operand:DI 0 "cirrus_fp_register" "")
6848    (match_operand:DI 1 "cirrus_fp_register" "")]
6849   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6850   "{
6851      arm_compare_op0 = operands[0];
6852      arm_compare_op1 = operands[1];
6853      DONE;
6854    }")
6855
6856 (define_insn "*cirrus_cmpdi"
6857   [(set (reg:CC CC_REGNUM)
6858         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6859                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
6860   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6861   "cfcmp64%?\\tr15, %V0, %V1"
6862   [(set_attr "type"   "mav_farith")
6863    (set_attr "cirrus" "compare")]
6864 )
6865
6866 ; This insn allows redundant compares to be removed by cse, nothing should
6867 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6868 ; is deleted later on. The match_dup will match the mode here, so that
6869 ; mode changes of the condition codes aren't lost by this even though we don't
6870 ; specify what they are.
6871
6872 (define_insn "*deleted_compare"
6873   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6874   "TARGET_ARM"
6875   "\\t%@ deleted compare"
6876   [(set_attr "conds" "set")
6877    (set_attr "length" "0")]
6878 )
6879
6880 \f
6881 ;; Conditional branch insns
6882
6883 (define_expand "beq"
6884   [(set (pc)
6885         (if_then_else (eq (match_dup 1) (const_int 0))
6886                       (label_ref (match_operand 0 "" ""))
6887                       (pc)))]
6888   "TARGET_ARM"
6889   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6890 )
6891
6892 (define_expand "bne"
6893   [(set (pc)
6894         (if_then_else (ne (match_dup 1) (const_int 0))
6895                       (label_ref (match_operand 0 "" ""))
6896                       (pc)))]
6897   "TARGET_ARM"
6898   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6899 )
6900
6901 (define_expand "bgt"
6902   [(set (pc)
6903         (if_then_else (gt (match_dup 1) (const_int 0))
6904                       (label_ref (match_operand 0 "" ""))
6905                       (pc)))]
6906   "TARGET_ARM"
6907   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6908 )
6909
6910 (define_expand "ble"
6911   [(set (pc)
6912         (if_then_else (le (match_dup 1) (const_int 0))
6913                       (label_ref (match_operand 0 "" ""))
6914                       (pc)))]
6915   "TARGET_ARM"
6916   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6917 )
6918
6919 (define_expand "bge"
6920   [(set (pc)
6921         (if_then_else (ge (match_dup 1) (const_int 0))
6922                       (label_ref (match_operand 0 "" ""))
6923                       (pc)))]
6924   "TARGET_ARM"
6925   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6926 )
6927
6928 (define_expand "blt"
6929   [(set (pc)
6930         (if_then_else (lt (match_dup 1) (const_int 0))
6931                       (label_ref (match_operand 0 "" ""))
6932                       (pc)))]
6933   "TARGET_ARM"
6934   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6935 )
6936
6937 (define_expand "bgtu"
6938   [(set (pc)
6939         (if_then_else (gtu (match_dup 1) (const_int 0))
6940                       (label_ref (match_operand 0 "" ""))
6941                       (pc)))]
6942   "TARGET_ARM"
6943   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6944 )
6945
6946 (define_expand "bleu"
6947   [(set (pc)
6948         (if_then_else (leu (match_dup 1) (const_int 0))
6949                       (label_ref (match_operand 0 "" ""))
6950                       (pc)))]
6951   "TARGET_ARM"
6952   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6953 )
6954
6955 (define_expand "bgeu"
6956   [(set (pc)
6957         (if_then_else (geu (match_dup 1) (const_int 0))
6958                       (label_ref (match_operand 0 "" ""))
6959                       (pc)))]
6960   "TARGET_ARM"
6961   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6962 )
6963
6964 (define_expand "bltu"
6965   [(set (pc)
6966         (if_then_else (ltu (match_dup 1) (const_int 0))
6967                       (label_ref (match_operand 0 "" ""))
6968                       (pc)))]
6969   "TARGET_ARM"
6970   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6971 )
6972
6973 (define_expand "bunordered"
6974   [(set (pc)
6975         (if_then_else (unordered (match_dup 1) (const_int 0))
6976                       (label_ref (match_operand 0 "" ""))
6977                       (pc)))]
6978   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
6979   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6980                                       arm_compare_op1);"
6981 )
6982
6983 (define_expand "bordered"
6984   [(set (pc)
6985         (if_then_else (ordered (match_dup 1) (const_int 0))
6986                       (label_ref (match_operand 0 "" ""))
6987                       (pc)))]
6988   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
6989   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6990                                       arm_compare_op1);"
6991 )
6992
6993 (define_expand "bungt"
6994   [(set (pc)
6995         (if_then_else (ungt (match_dup 1) (const_int 0))
6996                       (label_ref (match_operand 0 "" ""))
6997                       (pc)))]
6998   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
6999   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
7000 )
7001
7002 (define_expand "bunlt"
7003   [(set (pc)
7004         (if_then_else (unlt (match_dup 1) (const_int 0))
7005                       (label_ref (match_operand 0 "" ""))
7006                       (pc)))]
7007   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7008   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
7009 )
7010
7011 (define_expand "bunge"
7012   [(set (pc)
7013         (if_then_else (unge (match_dup 1) (const_int 0))
7014                       (label_ref (match_operand 0 "" ""))
7015                       (pc)))]
7016   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7017   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
7018 )
7019
7020 (define_expand "bunle"
7021   [(set (pc)
7022         (if_then_else (unle (match_dup 1) (const_int 0))
7023                       (label_ref (match_operand 0 "" ""))
7024                       (pc)))]
7025   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7026   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
7027 )
7028
7029 ;; The following two patterns need two branch instructions, since there is
7030 ;; no single instruction that will handle all cases.
7031 (define_expand "buneq"
7032   [(set (pc)
7033         (if_then_else (uneq (match_dup 1) (const_int 0))
7034                       (label_ref (match_operand 0 "" ""))
7035                       (pc)))]
7036   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7037   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
7038 )
7039
7040 (define_expand "bltgt"
7041   [(set (pc)
7042         (if_then_else (ltgt (match_dup 1) (const_int 0))
7043                       (label_ref (match_operand 0 "" ""))
7044                       (pc)))]
7045   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7046   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
7047 )
7048
7049 ;;
7050 ;; Patterns to match conditional branch insns.
7051 ;;
7052
7053 ; Special pattern to match UNEQ.
7054 (define_insn "*arm_buneq"
7055   [(set (pc)
7056         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7057                       (label_ref (match_operand 0 "" ""))
7058                       (pc)))]
7059   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7060   "*
7061   gcc_assert (!arm_ccfsm_state);
7062
7063   return \"bvs\\t%l0\;beq\\t%l0\";
7064   "
7065   [(set_attr "conds" "jump_clob")
7066    (set_attr "length" "8")]
7067 )
7068
7069 ; Special pattern to match LTGT.
7070 (define_insn "*arm_bltgt"
7071   [(set (pc)
7072         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7073                       (label_ref (match_operand 0 "" ""))
7074                       (pc)))]
7075   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7076   "*
7077   gcc_assert (!arm_ccfsm_state);
7078
7079   return \"bmi\\t%l0\;bgt\\t%l0\";
7080   "
7081   [(set_attr "conds" "jump_clob")
7082    (set_attr "length" "8")]
7083 )
7084
7085 (define_insn "*arm_cond_branch"
7086   [(set (pc)
7087         (if_then_else (match_operator 1 "arm_comparison_operator"
7088                        [(match_operand 2 "cc_register" "") (const_int 0)])
7089                       (label_ref (match_operand 0 "" ""))
7090                       (pc)))]
7091   "TARGET_ARM"
7092   "*
7093   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7094     {
7095       arm_ccfsm_state += 2;
7096       return \"\";
7097     }
7098   return \"b%d1\\t%l0\";
7099   "
7100   [(set_attr "conds" "use")
7101    (set_attr "type" "branch")]
7102 )
7103
7104 ; Special pattern to match reversed UNEQ.
7105 (define_insn "*arm_buneq_reversed"
7106   [(set (pc)
7107         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7108                       (pc)
7109                       (label_ref (match_operand 0 "" ""))))]
7110   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7111   "*
7112   gcc_assert (!arm_ccfsm_state);
7113
7114   return \"bmi\\t%l0\;bgt\\t%l0\";
7115   "
7116   [(set_attr "conds" "jump_clob")
7117    (set_attr "length" "8")]
7118 )
7119
7120 ; Special pattern to match reversed LTGT.
7121 (define_insn "*arm_bltgt_reversed"
7122   [(set (pc)
7123         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7124                       (pc)
7125                       (label_ref (match_operand 0 "" ""))))]
7126   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7127   "*
7128   gcc_assert (!arm_ccfsm_state);
7129
7130   return \"bvs\\t%l0\;beq\\t%l0\";
7131   "
7132   [(set_attr "conds" "jump_clob")
7133    (set_attr "length" "8")]
7134 )
7135
7136 (define_insn "*arm_cond_branch_reversed"
7137   [(set (pc)
7138         (if_then_else (match_operator 1 "arm_comparison_operator"
7139                        [(match_operand 2 "cc_register" "") (const_int 0)])
7140                       (pc)
7141                       (label_ref (match_operand 0 "" ""))))]
7142   "TARGET_ARM"
7143   "*
7144   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7145     {
7146       arm_ccfsm_state += 2;
7147       return \"\";
7148     }
7149   return \"b%D1\\t%l0\";
7150   "
7151   [(set_attr "conds" "use")
7152    (set_attr "type" "branch")]
7153 )
7154
7155 \f
7156
7157 ; scc insns
7158
7159 (define_expand "seq"
7160   [(set (match_operand:SI 0 "s_register_operand" "")
7161         (eq:SI (match_dup 1) (const_int 0)))]
7162   "TARGET_ARM"
7163   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7164 )
7165
7166 (define_expand "sne"
7167   [(set (match_operand:SI 0 "s_register_operand" "")
7168         (ne:SI (match_dup 1) (const_int 0)))]
7169   "TARGET_ARM"
7170   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7171 )
7172
7173 (define_expand "sgt"
7174   [(set (match_operand:SI 0 "s_register_operand" "")
7175         (gt:SI (match_dup 1) (const_int 0)))]
7176   "TARGET_ARM"
7177   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7178 )
7179
7180 (define_expand "sle"
7181   [(set (match_operand:SI 0 "s_register_operand" "")
7182         (le:SI (match_dup 1) (const_int 0)))]
7183   "TARGET_ARM"
7184   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7185 )
7186
7187 (define_expand "sge"
7188   [(set (match_operand:SI 0 "s_register_operand" "")
7189         (ge:SI (match_dup 1) (const_int 0)))]
7190   "TARGET_ARM"
7191   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7192 )
7193
7194 (define_expand "slt"
7195   [(set (match_operand:SI 0 "s_register_operand" "")
7196         (lt:SI (match_dup 1) (const_int 0)))]
7197   "TARGET_ARM"
7198   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7199 )
7200
7201 (define_expand "sgtu"
7202   [(set (match_operand:SI 0 "s_register_operand" "")
7203         (gtu:SI (match_dup 1) (const_int 0)))]
7204   "TARGET_ARM"
7205   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7206 )
7207
7208 (define_expand "sleu"
7209   [(set (match_operand:SI 0 "s_register_operand" "")
7210         (leu:SI (match_dup 1) (const_int 0)))]
7211   "TARGET_ARM"
7212   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7213 )
7214
7215 (define_expand "sgeu"
7216   [(set (match_operand:SI 0 "s_register_operand" "")
7217         (geu:SI (match_dup 1) (const_int 0)))]
7218   "TARGET_ARM"
7219   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7220 )
7221
7222 (define_expand "sltu"
7223   [(set (match_operand:SI 0 "s_register_operand" "")
7224         (ltu:SI (match_dup 1) (const_int 0)))]
7225   "TARGET_ARM"
7226   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7227 )
7228
7229 (define_expand "sunordered"
7230   [(set (match_operand:SI 0 "s_register_operand" "")
7231         (unordered:SI (match_dup 1) (const_int 0)))]
7232   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7233   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7234                                       arm_compare_op1);"
7235 )
7236
7237 (define_expand "sordered"
7238   [(set (match_operand:SI 0 "s_register_operand" "")
7239         (ordered:SI (match_dup 1) (const_int 0)))]
7240   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7241   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7242                                       arm_compare_op1);"
7243 )
7244
7245 (define_expand "sungt"
7246   [(set (match_operand:SI 0 "s_register_operand" "")
7247         (ungt:SI (match_dup 1) (const_int 0)))]
7248   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7249   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7250                                       arm_compare_op1);"
7251 )
7252
7253 (define_expand "sunge"
7254   [(set (match_operand:SI 0 "s_register_operand" "")
7255         (unge:SI (match_dup 1) (const_int 0)))]
7256   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7257   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7258                                       arm_compare_op1);"
7259 )
7260
7261 (define_expand "sunlt"
7262   [(set (match_operand:SI 0 "s_register_operand" "")
7263         (unlt:SI (match_dup 1) (const_int 0)))]
7264   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7265   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7266                                       arm_compare_op1);"
7267 )
7268
7269 (define_expand "sunle"
7270   [(set (match_operand:SI 0 "s_register_operand" "")
7271         (unle:SI (match_dup 1) (const_int 0)))]
7272   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7273   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7274                                       arm_compare_op1);"
7275 )
7276
7277 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7278 ;;; simple ARM instructions. 
7279 ;
7280 ; (define_expand "suneq"
7281 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7282 ;       (uneq:SI (match_dup 1) (const_int 0)))]
7283 ;   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7284 ;   "gcc_unreachable ();"
7285 ; )
7286 ;
7287 ; (define_expand "sltgt"
7288 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7289 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
7290 ;   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7291 ;   "gcc_unreachable ();"
7292 ; )
7293
7294 (define_insn "*mov_scc"
7295   [(set (match_operand:SI 0 "s_register_operand" "=r")
7296         (match_operator:SI 1 "arm_comparison_operator"
7297          [(match_operand 2 "cc_register" "") (const_int 0)]))]
7298   "TARGET_ARM"
7299   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7300   [(set_attr "conds" "use")
7301    (set_attr "length" "8")]
7302 )
7303
7304 (define_insn "*mov_negscc"
7305   [(set (match_operand:SI 0 "s_register_operand" "=r")
7306         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7307                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7308   "TARGET_ARM"
7309   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7310   [(set_attr "conds" "use")
7311    (set_attr "length" "8")]
7312 )
7313
7314 (define_insn "*mov_notscc"
7315   [(set (match_operand:SI 0 "s_register_operand" "=r")
7316         (not:SI (match_operator:SI 1 "arm_comparison_operator"
7317                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7318   "TARGET_ARM"
7319   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7320   [(set_attr "conds" "use")
7321    (set_attr "length" "8")]
7322 )
7323
7324 \f
7325 ;; Conditional move insns
7326
7327 (define_expand "movsicc"
7328   [(set (match_operand:SI 0 "s_register_operand" "")
7329         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7330                          (match_operand:SI 2 "arm_not_operand" "")
7331                          (match_operand:SI 3 "arm_not_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     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7342     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7343   }"
7344 )
7345
7346 (define_expand "movsfcc"
7347   [(set (match_operand:SF 0 "s_register_operand" "")
7348         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7349                          (match_operand:SF 2 "s_register_operand" "")
7350                          (match_operand:SF 3 "nonmemory_operand" "")))]
7351   "TARGET_ARM"
7352   "
7353   {
7354     enum rtx_code code = GET_CODE (operands[1]);
7355     rtx ccreg;
7356
7357     if (code == UNEQ || code == LTGT)
7358       FAIL;
7359
7360     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
7361        Otherwise, ensure it is a valid FP add operand */
7362     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7363         || (!arm_float_add_operand (operands[3], SFmode)))
7364       operands[3] = force_reg (SFmode, operands[3]);
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_expand "movdfcc"
7372   [(set (match_operand:DF 0 "s_register_operand" "")
7373         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7374                          (match_operand:DF 2 "s_register_operand" "")
7375                          (match_operand:DF 3 "arm_float_add_operand" "")))]
7376   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7377   "
7378   {
7379     enum rtx_code code = GET_CODE (operands[1]);
7380     rtx ccreg;
7381
7382     if (code == UNEQ || code == LTGT)
7383       FAIL;
7384
7385     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7386     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7387   }"
7388 )
7389
7390 (define_insn "*movsicc_insn"
7391   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7392         (if_then_else:SI
7393          (match_operator 3 "arm_comparison_operator"
7394           [(match_operand 4 "cc_register" "") (const_int 0)])
7395          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7396          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7397   "TARGET_ARM"
7398   "@
7399    mov%D3\\t%0, %2
7400    mvn%D3\\t%0, #%B2
7401    mov%d3\\t%0, %1
7402    mvn%d3\\t%0, #%B1
7403    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7404    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7405    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7406    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7407   [(set_attr "length" "4,4,4,4,8,8,8,8")
7408    (set_attr "conds" "use")]
7409 )
7410
7411 (define_insn "*movsfcc_soft_insn"
7412   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7413         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7414                           [(match_operand 4 "cc_register" "") (const_int 0)])
7415                          (match_operand:SF 1 "s_register_operand" "0,r")
7416                          (match_operand:SF 2 "s_register_operand" "r,0")))]
7417   "TARGET_ARM && TARGET_SOFT_FLOAT"
7418   "@
7419    mov%D3\\t%0, %2
7420    mov%d3\\t%0, %1"
7421   [(set_attr "conds" "use")]
7422 )
7423
7424 \f
7425 ;; Jump and linkage insns
7426
7427 (define_expand "jump"
7428   [(set (pc)
7429         (label_ref (match_operand 0 "" "")))]
7430   "TARGET_EITHER"
7431   ""
7432 )
7433
7434 (define_insn "*arm_jump"
7435   [(set (pc)
7436         (label_ref (match_operand 0 "" "")))]
7437   "TARGET_ARM"
7438   "*
7439   {
7440     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7441       {
7442         arm_ccfsm_state += 2;
7443         return \"\";
7444       }
7445     return \"b%?\\t%l0\";
7446   }
7447   "
7448   [(set_attr "predicable" "yes")]
7449 )
7450
7451 (define_insn "*thumb_jump"
7452   [(set (pc)
7453         (label_ref (match_operand 0 "" "")))]
7454   "TARGET_THUMB"
7455   "*
7456   if (get_attr_length (insn) == 2)
7457     return \"b\\t%l0\";
7458   return \"bl\\t%l0\\t%@ far jump\";
7459   "
7460   [(set (attr "far_jump")
7461         (if_then_else
7462             (eq_attr "length" "4")
7463             (const_string "yes")
7464             (const_string "no")))
7465    (set (attr "length") 
7466         (if_then_else
7467             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7468                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
7469             (const_int 2)
7470             (const_int 4)))]
7471 )
7472
7473 (define_expand "call"
7474   [(parallel [(call (match_operand 0 "memory_operand" "")
7475                     (match_operand 1 "general_operand" ""))
7476               (use (match_operand 2 "" ""))
7477               (clobber (reg:SI LR_REGNUM))])]
7478   "TARGET_EITHER"
7479   "
7480   {
7481     rtx callee;
7482     
7483     /* In an untyped call, we can get NULL for operand 2.  */
7484     if (operands[2] == NULL_RTX)
7485       operands[2] = const0_rtx;
7486       
7487     /* This is to decide if we should generate indirect calls by loading the
7488        32 bit address of the callee into a register before performing the
7489        branch and link.  operand[2] encodes the long_call/short_call
7490        attribute of the function being called.  This attribute is set whenever
7491        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7492        is used, and the short_call attribute can also be set if function is
7493        declared as static or if it has already been defined in the current
7494        compilation unit.  See arm.c and arm.h for info about this.  The third
7495        parameter to arm_is_longcall_p is used to tell it which pattern
7496        invoked it.  */
7497     callee  = XEXP (operands[0], 0);
7498     
7499     if (GET_CODE (callee) != REG
7500        && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7501       XEXP (operands[0], 0) = force_reg (Pmode, callee);
7502   }"
7503 )
7504
7505 (define_insn "*call_reg_armv5"
7506   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7507          (match_operand 1 "" ""))
7508    (use (match_operand 2 "" ""))
7509    (clobber (reg:SI LR_REGNUM))]
7510   "TARGET_ARM && arm_arch5"
7511   "blx%?\\t%0"
7512   [(set_attr "type" "call")]
7513 )
7514
7515 (define_insn "*call_reg_arm"
7516   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7517          (match_operand 1 "" ""))
7518    (use (match_operand 2 "" ""))
7519    (clobber (reg:SI LR_REGNUM))]
7520   "TARGET_ARM && !arm_arch5"
7521   "*
7522   return output_call (operands);
7523   "
7524   ;; length is worst case, normally it is only two
7525   [(set_attr "length" "12")
7526    (set_attr "type" "call")]
7527 )
7528
7529 (define_insn "*call_mem"
7530   [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7531          (match_operand 1 "" ""))
7532    (use (match_operand 2 "" ""))
7533    (clobber (reg:SI LR_REGNUM))]
7534   "TARGET_ARM"
7535   "*
7536   return output_call_mem (operands);
7537   "
7538   [(set_attr "length" "12")
7539    (set_attr "type" "call")]
7540 )
7541
7542 (define_insn "*call_reg_thumb_v5"
7543   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7544          (match_operand 1 "" ""))
7545    (use (match_operand 2 "" ""))
7546    (clobber (reg:SI LR_REGNUM))]
7547   "TARGET_THUMB && arm_arch5"
7548   "blx\\t%0"
7549   [(set_attr "length" "2")
7550    (set_attr "type" "call")]
7551 )
7552
7553 (define_insn "*call_reg_thumb"
7554   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7555          (match_operand 1 "" ""))
7556    (use (match_operand 2 "" ""))
7557    (clobber (reg:SI LR_REGNUM))]
7558   "TARGET_THUMB && !arm_arch5"
7559   "*
7560   {
7561     if (!TARGET_CALLER_INTERWORKING)
7562       return thumb_call_via_reg (operands[0]);
7563     else if (operands[1] == const0_rtx)
7564       return \"bl\\t%__interwork_call_via_%0\";
7565     else if (frame_pointer_needed)
7566       return \"bl\\t%__interwork_r7_call_via_%0\";
7567     else
7568       return \"bl\\t%__interwork_r11_call_via_%0\";
7569   }"
7570   [(set_attr "type" "call")]
7571 )
7572
7573 (define_expand "call_value"
7574   [(parallel [(set (match_operand       0 "" "")
7575                    (call (match_operand 1 "memory_operand" "")
7576                          (match_operand 2 "general_operand" "")))
7577               (use (match_operand 3 "" ""))
7578               (clobber (reg:SI LR_REGNUM))])]
7579   "TARGET_EITHER"
7580   "
7581   {
7582     rtx callee = XEXP (operands[1], 0);
7583     
7584     /* In an untyped call, we can get NULL for operand 2.  */
7585     if (operands[3] == 0)
7586       operands[3] = const0_rtx;
7587       
7588     /* See the comment in define_expand \"call\".  */
7589     if (GET_CODE (callee) != REG
7590         && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7591       XEXP (operands[1], 0) = force_reg (Pmode, callee);
7592   }"
7593 )
7594
7595 (define_insn "*call_value_reg_armv5"
7596   [(set (match_operand 0 "" "")
7597         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7598               (match_operand 2 "" "")))
7599    (use (match_operand 3 "" ""))
7600    (clobber (reg:SI LR_REGNUM))]
7601   "TARGET_ARM && arm_arch5"
7602   "blx%?\\t%1"
7603   [(set_attr "type" "call")]
7604 )
7605
7606 (define_insn "*call_value_reg_arm"
7607   [(set (match_operand 0 "" "")
7608         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7609               (match_operand 2 "" "")))
7610    (use (match_operand 3 "" ""))
7611    (clobber (reg:SI LR_REGNUM))]
7612   "TARGET_ARM && !arm_arch5"
7613   "*
7614   return output_call (&operands[1]);
7615   "
7616   [(set_attr "length" "12")
7617    (set_attr "type" "call")]
7618 )
7619
7620 (define_insn "*call_value_mem"
7621   [(set (match_operand 0 "" "")
7622         (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7623               (match_operand 2 "" "")))
7624    (use (match_operand 3 "" ""))
7625    (clobber (reg:SI LR_REGNUM))]
7626   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7627   "*
7628   return output_call_mem (&operands[1]);
7629   "
7630   [(set_attr "length" "12")
7631    (set_attr "type" "call")]
7632 )
7633
7634 (define_insn "*call_value_reg_thumb_v5"
7635   [(set (match_operand 0 "" "")
7636         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7637               (match_operand 2 "" "")))
7638    (use (match_operand 3 "" ""))
7639    (clobber (reg:SI LR_REGNUM))]
7640   "TARGET_THUMB && arm_arch5"
7641   "blx\\t%1"
7642   [(set_attr "length" "2")
7643    (set_attr "type" "call")]
7644 )
7645
7646 (define_insn "*call_value_reg_thumb"
7647   [(set (match_operand 0 "" "")
7648         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7649               (match_operand 2 "" "")))
7650    (use (match_operand 3 "" ""))
7651    (clobber (reg:SI LR_REGNUM))]
7652   "TARGET_THUMB && !arm_arch5"
7653   "*
7654   {
7655     if (!TARGET_CALLER_INTERWORKING)
7656       return thumb_call_via_reg (operands[1]);
7657     else if (operands[2] == const0_rtx)
7658       return \"bl\\t%__interwork_call_via_%1\";
7659     else if (frame_pointer_needed)
7660       return \"bl\\t%__interwork_r7_call_via_%1\";
7661     else
7662       return \"bl\\t%__interwork_r11_call_via_%1\";
7663   }"
7664   [(set_attr "type" "call")]
7665 )
7666
7667 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7668 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7669
7670 (define_insn "*call_symbol"
7671   [(call (mem:SI (match_operand:SI 0 "" ""))
7672          (match_operand 1 "" ""))
7673    (use (match_operand 2 "" ""))
7674    (clobber (reg:SI LR_REGNUM))]
7675   "TARGET_ARM
7676    && (GET_CODE (operands[0]) == SYMBOL_REF)
7677    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7678   "*
7679   {
7680     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7681   }"
7682   [(set_attr "type" "call")]
7683 )
7684
7685 (define_insn "*call_value_symbol"
7686   [(set (match_operand 0 "" "")
7687         (call (mem:SI (match_operand:SI 1 "" ""))
7688         (match_operand:SI 2 "" "")))
7689    (use (match_operand 3 "" ""))
7690    (clobber (reg:SI LR_REGNUM))]
7691   "TARGET_ARM
7692    && (GET_CODE (operands[1]) == SYMBOL_REF)
7693    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7694   "*
7695   {
7696     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7697   }"
7698   [(set_attr "type" "call")]
7699 )
7700
7701 (define_insn "*call_insn"
7702   [(call (mem:SI (match_operand:SI 0 "" ""))
7703          (match_operand:SI 1 "" ""))
7704    (use (match_operand 2 "" ""))
7705    (clobber (reg:SI LR_REGNUM))]
7706   "TARGET_THUMB
7707    && GET_CODE (operands[0]) == SYMBOL_REF
7708    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7709   "bl\\t%a0"
7710   [(set_attr "length" "4")
7711    (set_attr "type" "call")]
7712 )
7713
7714 (define_insn "*call_value_insn"
7715   [(set (match_operand 0 "" "")
7716         (call (mem:SI (match_operand 1 "" ""))
7717               (match_operand 2 "" "")))
7718    (use (match_operand 3 "" ""))
7719    (clobber (reg:SI LR_REGNUM))]
7720   "TARGET_THUMB
7721    && GET_CODE (operands[1]) == SYMBOL_REF
7722    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7723   "bl\\t%a1"
7724   [(set_attr "length" "4")
7725    (set_attr "type" "call")]
7726 )
7727
7728 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7729 (define_expand "sibcall"
7730   [(parallel [(call (match_operand 0 "memory_operand" "")
7731                     (match_operand 1 "general_operand" ""))
7732               (return)
7733               (use (match_operand 2 "" ""))])]
7734   "TARGET_ARM"
7735   "
7736   {
7737     if (operands[2] == NULL_RTX)
7738       operands[2] = const0_rtx;
7739   }"
7740 )
7741
7742 (define_expand "sibcall_value"
7743   [(parallel [(set (match_operand 0 "" "")
7744                    (call (match_operand 1 "memory_operand" "")
7745                          (match_operand 2 "general_operand" "")))
7746               (return)
7747               (use (match_operand 3 "" ""))])]
7748   "TARGET_ARM"
7749   "
7750   {
7751     if (operands[3] == NULL_RTX)
7752       operands[3] = const0_rtx;
7753   }"
7754 )
7755
7756 (define_insn "*sibcall_insn"
7757  [(call (mem:SI (match_operand:SI 0 "" "X"))
7758         (match_operand 1 "" ""))
7759   (return)
7760   (use (match_operand 2 "" ""))]
7761   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7762   "*
7763   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7764   "
7765   [(set_attr "type" "call")]
7766 )
7767
7768 (define_insn "*sibcall_value_insn"
7769  [(set (match_operand 0 "" "")
7770        (call (mem:SI (match_operand:SI 1 "" "X"))
7771              (match_operand 2 "" "")))
7772   (return)
7773   (use (match_operand 3 "" ""))]
7774   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7775   "*
7776   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7777   "
7778   [(set_attr "type" "call")]
7779 )
7780
7781 ;; Often the return insn will be the same as loading from memory, so set attr
7782 (define_insn "return"
7783   [(return)]
7784   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7785   "*
7786   {
7787     if (arm_ccfsm_state == 2)
7788       {
7789         arm_ccfsm_state += 2;
7790         return \"\";
7791       }
7792     return output_return_instruction (const_true_rtx, TRUE, FALSE);
7793   }"
7794   [(set_attr "type" "load1")
7795    (set_attr "length" "12")
7796    (set_attr "predicable" "yes")]
7797 )
7798
7799 (define_insn "*cond_return"
7800   [(set (pc)
7801         (if_then_else (match_operator 0 "arm_comparison_operator"
7802                        [(match_operand 1 "cc_register" "") (const_int 0)])
7803                       (return)
7804                       (pc)))]
7805   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7806   "*
7807   {
7808     if (arm_ccfsm_state == 2)
7809       {
7810         arm_ccfsm_state += 2;
7811         return \"\";
7812       }
7813     return output_return_instruction (operands[0], TRUE, FALSE);
7814   }"
7815   [(set_attr "conds" "use")
7816    (set_attr "length" "12")
7817    (set_attr "type" "load1")]
7818 )
7819
7820 (define_insn "*cond_return_inverted"
7821   [(set (pc)
7822         (if_then_else (match_operator 0 "arm_comparison_operator"
7823                        [(match_operand 1 "cc_register" "") (const_int 0)])
7824                       (pc)
7825                       (return)))]
7826   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7827   "*
7828   {
7829     if (arm_ccfsm_state == 2)
7830       {
7831         arm_ccfsm_state += 2;
7832         return \"\";
7833       }
7834     return output_return_instruction (operands[0], TRUE, TRUE);
7835   }"
7836   [(set_attr "conds" "use")
7837    (set_attr "length" "12")
7838    (set_attr "type" "load1")]
7839 )
7840
7841 ;; Generate a sequence of instructions to determine if the processor is
7842 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7843 ;; mask.
7844
7845 (define_expand "return_addr_mask"
7846   [(set (match_dup 1)
7847       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7848                        (const_int 0)))
7849    (set (match_operand:SI 0 "s_register_operand" "")
7850       (if_then_else:SI (eq (match_dup 1) (const_int 0))
7851                        (const_int -1)
7852                        (const_int 67108860)))] ; 0x03fffffc
7853   "TARGET_ARM"
7854   "
7855   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7856   ")
7857
7858 (define_insn "*check_arch2"
7859   [(set (match_operand:CC_NOOV 0 "cc_register" "")
7860       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7861                        (const_int 0)))]
7862   "TARGET_ARM"
7863   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7864   [(set_attr "length" "8")
7865    (set_attr "conds" "set")]
7866 )
7867
7868 ;; Call subroutine returning any type.
7869
7870 (define_expand "untyped_call"
7871   [(parallel [(call (match_operand 0 "" "")
7872                     (const_int 0))
7873               (match_operand 1 "" "")
7874               (match_operand 2 "" "")])]
7875   "TARGET_EITHER"
7876   "
7877   {
7878     int i;
7879     rtx par = gen_rtx_PARALLEL (VOIDmode,
7880                                 rtvec_alloc (XVECLEN (operands[2], 0)));
7881     rtx addr = gen_reg_rtx (Pmode);
7882     rtx mem;
7883     int size = 0;
7884
7885     emit_move_insn (addr, XEXP (operands[1], 0));
7886     mem = change_address (operands[1], BLKmode, addr);
7887
7888     for (i = 0; i < XVECLEN (operands[2], 0); i++)
7889       {
7890         rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
7891
7892         /* Default code only uses r0 as a return value, but we could
7893            be using anything up to 4 registers.  */
7894         if (REGNO (src) == R0_REGNUM)
7895           src = gen_rtx_REG (TImode, R0_REGNUM);
7896
7897         XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
7898                                                  GEN_INT (size));
7899         size += GET_MODE_SIZE (GET_MODE (src));
7900       }
7901
7902     emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
7903                                     const0_rtx));
7904
7905     size = 0;
7906
7907     for (i = 0; i < XVECLEN (par, 0); i++)
7908       {
7909         HOST_WIDE_INT offset = 0;
7910         rtx reg = XEXP (XVECEXP (par, 0, i), 0);
7911
7912         if (size != 0)
7913           emit_move_insn (addr, plus_constant (addr, size));
7914
7915         mem = change_address (mem, GET_MODE (reg), NULL);
7916         if (REGNO (reg) == R0_REGNUM)
7917           {
7918             /* On thumb we have to use a write-back instruction.  */
7919             emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
7920                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7921             size = TARGET_ARM ? 16 : 0;
7922           }
7923         else
7924           {
7925             emit_move_insn (mem, reg);
7926             size = GET_MODE_SIZE (GET_MODE (reg));
7927           }
7928       }
7929
7930     /* The optimizer does not know that the call sets the function value
7931        registers we stored in the result block.  We avoid problems by
7932        claiming that all hard registers are used and clobbered at this
7933        point.  */
7934     emit_insn (gen_blockage ());
7935
7936     DONE;
7937   }"
7938 )
7939
7940 (define_expand "untyped_return"
7941   [(match_operand:BLK 0 "memory_operand" "")
7942    (match_operand 1 "" "")]
7943   "TARGET_EITHER"
7944   "
7945   {
7946     int i;
7947     rtx addr = gen_reg_rtx (Pmode);
7948     rtx mem;
7949     int size = 0;
7950
7951     emit_move_insn (addr, XEXP (operands[0], 0));
7952     mem = change_address (operands[0], BLKmode, addr);
7953
7954     for (i = 0; i < XVECLEN (operands[1], 0); i++)
7955       {
7956         HOST_WIDE_INT offset = 0;
7957         rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
7958
7959         if (size != 0)
7960           emit_move_insn (addr, plus_constant (addr, size));
7961
7962         mem = change_address (mem, GET_MODE (reg), NULL);
7963         if (REGNO (reg) == R0_REGNUM)
7964           {
7965             /* On thumb we have to use a write-back instruction.  */
7966             emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
7967                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7968             size = TARGET_ARM ? 16 : 0;
7969           }
7970         else
7971           {
7972             emit_move_insn (reg, mem);
7973             size = GET_MODE_SIZE (GET_MODE (reg));
7974           }
7975       }
7976
7977     /* Emit USE insns before the return.  */
7978     for (i = 0; i < XVECLEN (operands[1], 0); i++)
7979       emit_insn (gen_rtx_USE (VOIDmode,
7980                               SET_DEST (XVECEXP (operands[1], 0, i))));
7981
7982     /* Construct the return.  */
7983     expand_naked_return ();
7984
7985     DONE;
7986   }"
7987 )
7988
7989 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7990 ;; all of memory.  This blocks insns from being moved across this point.
7991
7992 (define_insn "blockage"
7993   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
7994   "TARGET_EITHER"
7995   ""
7996   [(set_attr "length" "0")
7997    (set_attr "type" "block")]
7998 )
7999
8000 (define_expand "casesi"
8001   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
8002    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
8003    (match_operand:SI 2 "const_int_operand" "")  ; total range
8004    (match_operand:SI 3 "" "")                   ; table label
8005    (match_operand:SI 4 "" "")]                  ; Out of range label
8006   "TARGET_ARM"
8007   "
8008   {
8009     rtx reg;
8010     if (operands[1] != const0_rtx)
8011       {
8012         reg = gen_reg_rtx (SImode);
8013
8014         emit_insn (gen_addsi3 (reg, operands[0],
8015                                GEN_INT (-INTVAL (operands[1]))));
8016         operands[0] = reg;
8017       }
8018
8019     if (!const_ok_for_arm (INTVAL (operands[2])))
8020       operands[2] = force_reg (SImode, operands[2]);
8021
8022     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
8023                                          operands[4]));
8024     DONE;
8025   }"
8026 )
8027
8028 ;; The USE in this pattern is needed to tell flow analysis that this is
8029 ;; a CASESI insn.  It has no other purpose.
8030 (define_insn "casesi_internal"
8031   [(parallel [(set (pc)
8032                (if_then_else
8033                 (leu (match_operand:SI 0 "s_register_operand" "r")
8034                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
8035                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8036                                  (label_ref (match_operand 2 "" ""))))
8037                 (label_ref (match_operand 3 "" ""))))
8038               (clobber (reg:CC CC_REGNUM))
8039               (use (label_ref (match_dup 2)))])]
8040   "TARGET_ARM"
8041   "*
8042     if (flag_pic)
8043       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8044     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8045   "
8046   [(set_attr "conds" "clob")
8047    (set_attr "length" "12")]
8048 )
8049
8050 (define_expand "indirect_jump"
8051   [(set (pc)
8052         (match_operand:SI 0 "s_register_operand" ""))]
8053   "TARGET_EITHER"
8054   ""
8055 )
8056
8057 ;; NB Never uses BX.
8058 (define_insn "*arm_indirect_jump"
8059   [(set (pc)
8060         (match_operand:SI 0 "s_register_operand" "r"))]
8061   "TARGET_ARM"
8062   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
8063   [(set_attr "predicable" "yes")]
8064 )
8065
8066 (define_insn "*load_indirect_jump"
8067   [(set (pc)
8068         (match_operand:SI 0 "memory_operand" "m"))]
8069   "TARGET_ARM"
8070   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
8071   [(set_attr "type" "load1")
8072    (set_attr "pool_range" "4096")
8073    (set_attr "neg_pool_range" "4084")
8074    (set_attr "predicable" "yes")]
8075 )
8076
8077 ;; NB Never uses BX.
8078 (define_insn "*thumb_indirect_jump"
8079   [(set (pc)
8080         (match_operand:SI 0 "register_operand" "l*r"))]
8081   "TARGET_THUMB"
8082   "mov\\tpc, %0"
8083   [(set_attr "conds" "clob")
8084    (set_attr "length" "2")]
8085 )
8086
8087 \f
8088 ;; Misc insns
8089
8090 (define_insn "nop"
8091   [(const_int 0)]
8092   "TARGET_EITHER"
8093   "*
8094   if (TARGET_ARM)
8095     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8096   return  \"mov\\tr8, r8\";
8097   "
8098   [(set (attr "length")
8099         (if_then_else (eq_attr "is_thumb" "yes")
8100                       (const_int 2)
8101                       (const_int 4)))]
8102 )
8103
8104 \f
8105 ;; Patterns to allow combination of arithmetic, cond code and shifts
8106
8107 (define_insn "*arith_shiftsi"
8108   [(set (match_operand:SI 0 "s_register_operand" "=r")
8109         (match_operator:SI 1 "shiftable_operator"
8110           [(match_operator:SI 3 "shift_operator"
8111              [(match_operand:SI 4 "s_register_operand" "r")
8112               (match_operand:SI 5 "reg_or_int_operand" "rI")])
8113            (match_operand:SI 2 "s_register_operand" "r")]))]
8114   "TARGET_ARM"
8115   "%i1%?\\t%0, %2, %4%S3"
8116   [(set_attr "predicable" "yes")
8117    (set_attr "shift" "4")
8118    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8119                       (const_string "alu_shift")
8120                       (const_string "alu_shift_reg")))]
8121 )
8122
8123 (define_split
8124   [(set (match_operand:SI 0 "s_register_operand" "")
8125         (match_operator:SI 1 "shiftable_operator"
8126          [(match_operator:SI 2 "shiftable_operator"
8127            [(match_operator:SI 3 "shift_operator"
8128              [(match_operand:SI 4 "s_register_operand" "")
8129               (match_operand:SI 5 "reg_or_int_operand" "")])
8130             (match_operand:SI 6 "s_register_operand" "")])
8131           (match_operand:SI 7 "arm_rhs_operand" "")]))
8132    (clobber (match_operand:SI 8 "s_register_operand" ""))]
8133   "TARGET_ARM"
8134   [(set (match_dup 8)
8135         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8136                          (match_dup 6)]))
8137    (set (match_dup 0)
8138         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8139   "")
8140
8141 (define_insn "*arith_shiftsi_compare0"
8142   [(set (reg:CC_NOOV CC_REGNUM)
8143         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8144                           [(match_operator:SI 3 "shift_operator"
8145                             [(match_operand:SI 4 "s_register_operand" "r")
8146                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8147                            (match_operand:SI 2 "s_register_operand" "r")])
8148                          (const_int 0)))
8149    (set (match_operand:SI 0 "s_register_operand" "=r")
8150         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8151                          (match_dup 2)]))]
8152   "TARGET_ARM"
8153   "%i1%?s\\t%0, %2, %4%S3"
8154   [(set_attr "conds" "set")
8155    (set_attr "shift" "4")
8156    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8157                       (const_string "alu_shift")
8158                       (const_string "alu_shift_reg")))]
8159 )
8160
8161 (define_insn "*arith_shiftsi_compare0_scratch"
8162   [(set (reg:CC_NOOV CC_REGNUM)
8163         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8164                           [(match_operator:SI 3 "shift_operator"
8165                             [(match_operand:SI 4 "s_register_operand" "r")
8166                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8167                            (match_operand:SI 2 "s_register_operand" "r")])
8168                          (const_int 0)))
8169    (clobber (match_scratch:SI 0 "=r"))]
8170   "TARGET_ARM"
8171   "%i1%?s\\t%0, %2, %4%S3"
8172   [(set_attr "conds" "set")
8173    (set_attr "shift" "4")
8174    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8175                       (const_string "alu_shift")
8176                       (const_string "alu_shift_reg")))]
8177 )
8178
8179 (define_insn "*sub_shiftsi"
8180   [(set (match_operand:SI 0 "s_register_operand" "=r")
8181         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8182                   (match_operator:SI 2 "shift_operator"
8183                    [(match_operand:SI 3 "s_register_operand" "r")
8184                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
8185   "TARGET_ARM"
8186   "sub%?\\t%0, %1, %3%S2"
8187   [(set_attr "predicable" "yes")
8188    (set_attr "shift" "3")
8189    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8190                       (const_string "alu_shift")
8191                       (const_string "alu_shift_reg")))]
8192 )
8193
8194 (define_insn "*sub_shiftsi_compare0"
8195   [(set (reg:CC_NOOV CC_REGNUM)
8196         (compare:CC_NOOV
8197          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8198                    (match_operator:SI 2 "shift_operator"
8199                     [(match_operand:SI 3 "s_register_operand" "r")
8200                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8201          (const_int 0)))
8202    (set (match_operand:SI 0 "s_register_operand" "=r")
8203         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8204                                                  (match_dup 4)])))]
8205   "TARGET_ARM"
8206   "sub%?s\\t%0, %1, %3%S2"
8207   [(set_attr "conds" "set")
8208    (set_attr "shift" "3")
8209    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8210                       (const_string "alu_shift")
8211                       (const_string "alu_shift_reg")))]
8212 )
8213
8214 (define_insn "*sub_shiftsi_compare0_scratch"
8215   [(set (reg:CC_NOOV CC_REGNUM)
8216         (compare:CC_NOOV
8217          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8218                    (match_operator:SI 2 "shift_operator"
8219                     [(match_operand:SI 3 "s_register_operand" "r")
8220                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8221          (const_int 0)))
8222    (clobber (match_scratch:SI 0 "=r"))]
8223   "TARGET_ARM"
8224   "sub%?s\\t%0, %1, %3%S2"
8225   [(set_attr "conds" "set")
8226    (set_attr "shift" "3")
8227    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8228                       (const_string "alu_shift")
8229                       (const_string "alu_shift_reg")))]
8230 )
8231
8232 \f
8233
8234 (define_insn "*and_scc"
8235   [(set (match_operand:SI 0 "s_register_operand" "=r")
8236         (and:SI (match_operator:SI 1 "arm_comparison_operator"
8237                  [(match_operand 3 "cc_register" "") (const_int 0)])
8238                 (match_operand:SI 2 "s_register_operand" "r")))]
8239   "TARGET_ARM"
8240   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8241   [(set_attr "conds" "use")
8242    (set_attr "length" "8")]
8243 )
8244
8245 (define_insn "*ior_scc"
8246   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8247         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8248                  [(match_operand 3 "cc_register" "") (const_int 0)])
8249                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8250   "TARGET_ARM"
8251   "@
8252    orr%d2\\t%0, %1, #1
8253    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8254   [(set_attr "conds" "use")
8255    (set_attr "length" "4,8")]
8256 )
8257
8258 (define_insn "*compare_scc"
8259   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8260         (match_operator:SI 1 "arm_comparison_operator"
8261          [(match_operand:SI 2 "s_register_operand" "r,r")
8262           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8263    (clobber (reg:CC CC_REGNUM))]
8264   "TARGET_ARM"
8265   "*
8266     if (operands[3] == const0_rtx)
8267       {
8268         if (GET_CODE (operands[1]) == LT)
8269           return \"mov\\t%0, %2, lsr #31\";
8270
8271         if (GET_CODE (operands[1]) == GE)
8272           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8273
8274         if (GET_CODE (operands[1]) == EQ)
8275           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8276       }
8277
8278     if (GET_CODE (operands[1]) == NE)
8279       {
8280         if (which_alternative == 1)
8281           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8282         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8283       }
8284     if (which_alternative == 1)
8285       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8286     else
8287       output_asm_insn (\"cmp\\t%2, %3\", operands);
8288     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8289   "
8290   [(set_attr "conds" "clob")
8291    (set_attr "length" "12")]
8292 )
8293
8294 (define_insn "*cond_move"
8295   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8296         (if_then_else:SI (match_operator 3 "equality_operator"
8297                           [(match_operator 4 "arm_comparison_operator"
8298                             [(match_operand 5 "cc_register" "") (const_int 0)])
8299                            (const_int 0)])
8300                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8301                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8302   "TARGET_ARM"
8303   "*
8304     if (GET_CODE (operands[3]) == NE)
8305       {
8306         if (which_alternative != 1)
8307           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8308         if (which_alternative != 0)
8309           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8310         return \"\";
8311       }
8312     if (which_alternative != 0)
8313       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8314     if (which_alternative != 1)
8315       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8316     return \"\";
8317   "
8318   [(set_attr "conds" "use")
8319    (set_attr "length" "4,4,8")]
8320 )
8321
8322 (define_insn "*cond_arith"
8323   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8324         (match_operator:SI 5 "shiftable_operator" 
8325          [(match_operator:SI 4 "arm_comparison_operator"
8326            [(match_operand:SI 2 "s_register_operand" "r,r")
8327             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8328           (match_operand:SI 1 "s_register_operand" "0,?r")]))
8329    (clobber (reg:CC CC_REGNUM))]
8330   "TARGET_ARM"
8331   "*
8332     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8333       return \"%i5\\t%0, %1, %2, lsr #31\";
8334
8335     output_asm_insn (\"cmp\\t%2, %3\", operands);
8336     if (GET_CODE (operands[5]) == AND)
8337       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8338     else if (GET_CODE (operands[5]) == MINUS)
8339       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8340     else if (which_alternative != 0)
8341       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8342     return \"%i5%d4\\t%0, %1, #1\";
8343   "
8344   [(set_attr "conds" "clob")
8345    (set_attr "length" "12")]
8346 )
8347
8348 (define_insn "*cond_sub"
8349   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8350         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8351                   (match_operator:SI 4 "arm_comparison_operator"
8352                    [(match_operand:SI 2 "s_register_operand" "r,r")
8353                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8354    (clobber (reg:CC CC_REGNUM))]
8355   "TARGET_ARM"
8356   "*
8357     output_asm_insn (\"cmp\\t%2, %3\", operands);
8358     if (which_alternative != 0)
8359       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8360     return \"sub%d4\\t%0, %1, #1\";
8361   "
8362   [(set_attr "conds" "clob")
8363    (set_attr "length" "8,12")]
8364 )
8365
8366 (define_insn "*cmp_ite0"
8367   [(set (match_operand 6 "dominant_cc_register" "")
8368         (compare
8369          (if_then_else:SI
8370           (match_operator 4 "arm_comparison_operator"
8371            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8372             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8373           (match_operator:SI 5 "arm_comparison_operator"
8374            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8375             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8376           (const_int 0))
8377          (const_int 0)))]
8378   "TARGET_ARM"
8379   "*
8380   {
8381     static const char * const opcodes[4][2] =
8382     {
8383       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8384        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8385       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8386        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8387       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8388        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8389       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8390        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8391     };
8392     int swap =
8393       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8394
8395     return opcodes[which_alternative][swap];
8396   }"
8397   [(set_attr "conds" "set")
8398    (set_attr "length" "8")]
8399 )
8400
8401 (define_insn "*cmp_ite1"
8402   [(set (match_operand 6 "dominant_cc_register" "")
8403         (compare
8404          (if_then_else:SI
8405           (match_operator 4 "arm_comparison_operator"
8406            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8407             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8408           (match_operator:SI 5 "arm_comparison_operator"
8409            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8410             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8411           (const_int 1))
8412          (const_int 0)))]
8413   "TARGET_ARM"
8414   "*
8415   {
8416     static const char * const opcodes[4][2] =
8417     {
8418       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8419        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8420       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8421        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8422       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8423        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8424       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8425        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8426     };
8427     int swap =
8428       comparison_dominates_p (GET_CODE (operands[5]),
8429                               reverse_condition (GET_CODE (operands[4])));
8430
8431     return opcodes[which_alternative][swap];
8432   }"
8433   [(set_attr "conds" "set")
8434    (set_attr "length" "8")]
8435 )
8436
8437 (define_insn "*cmp_and"
8438   [(set (match_operand 6 "dominant_cc_register" "")
8439         (compare
8440          (and:SI
8441           (match_operator 4 "arm_comparison_operator"
8442            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8443             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8444           (match_operator:SI 5 "arm_comparison_operator"
8445            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8446             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8447          (const_int 0)))]
8448   "TARGET_ARM"
8449   "*
8450   {
8451     static const char *const opcodes[4][2] =
8452     {
8453       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8454        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8455       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8456        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8457       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8458        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8459       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8460        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8461     };
8462     int swap =
8463       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8464
8465     return opcodes[which_alternative][swap];
8466   }"
8467   [(set_attr "conds" "set")
8468    (set_attr "predicable" "no")
8469    (set_attr "length" "8")]
8470 )
8471
8472 (define_insn "*cmp_ior"
8473   [(set (match_operand 6 "dominant_cc_register" "")
8474         (compare
8475          (ior:SI
8476           (match_operator 4 "arm_comparison_operator"
8477            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8478             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8479           (match_operator:SI 5 "arm_comparison_operator"
8480            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8481             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8482          (const_int 0)))]
8483   "TARGET_ARM"
8484   "*
8485 {
8486   static const char *const opcodes[4][2] =
8487   {
8488     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8489      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8490     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8491      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8492     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8493      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8494     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8495      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8496   };
8497   int swap =
8498     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8499
8500   return opcodes[which_alternative][swap];
8501 }
8502 "
8503   [(set_attr "conds" "set")
8504    (set_attr "length" "8")]
8505 )
8506
8507 (define_insn_and_split "*ior_scc_scc"
8508   [(set (match_operand:SI 0 "s_register_operand" "=r")
8509         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8510                  [(match_operand:SI 1 "s_register_operand" "r")
8511                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8512                 (match_operator:SI 6 "arm_comparison_operator"
8513                  [(match_operand:SI 4 "s_register_operand" "r")
8514                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8515    (clobber (reg:CC CC_REGNUM))]
8516   "TARGET_ARM
8517    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8518        != CCmode)"
8519   "#"
8520   "TARGET_ARM && reload_completed"
8521   [(set (match_dup 7)
8522         (compare
8523          (ior:SI
8524           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8525           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8526          (const_int 0)))
8527    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8528   "operands[7]
8529      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8530                                                   DOM_CC_X_OR_Y),
8531                     CC_REGNUM);"
8532   [(set_attr "conds" "clob")
8533    (set_attr "length" "16")])
8534
8535 ; If the above pattern is followed by a CMP insn, then the compare is 
8536 ; redundant, since we can rework the conditional instruction that follows.
8537 (define_insn_and_split "*ior_scc_scc_cmp"
8538   [(set (match_operand 0 "dominant_cc_register" "")
8539         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8540                           [(match_operand:SI 1 "s_register_operand" "r")
8541                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8542                          (match_operator:SI 6 "arm_comparison_operator"
8543                           [(match_operand:SI 4 "s_register_operand" "r")
8544                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8545                  (const_int 0)))
8546    (set (match_operand:SI 7 "s_register_operand" "=r")
8547         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8548                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8549   "TARGET_ARM"
8550   "#"
8551   "TARGET_ARM && reload_completed"
8552   [(set (match_dup 0)
8553         (compare
8554          (ior:SI
8555           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8556           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8557          (const_int 0)))
8558    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8559   ""
8560   [(set_attr "conds" "set")
8561    (set_attr "length" "16")])
8562
8563 (define_insn_and_split "*and_scc_scc"
8564   [(set (match_operand:SI 0 "s_register_operand" "=r")
8565         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8566                  [(match_operand:SI 1 "s_register_operand" "r")
8567                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8568                 (match_operator:SI 6 "arm_comparison_operator"
8569                  [(match_operand:SI 4 "s_register_operand" "r")
8570                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8571    (clobber (reg:CC CC_REGNUM))]
8572   "TARGET_ARM
8573    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8574        != CCmode)"
8575   "#"
8576   "TARGET_ARM && reload_completed
8577    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8578        != CCmode)"
8579   [(set (match_dup 7)
8580         (compare
8581          (and:SI
8582           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8583           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8584          (const_int 0)))
8585    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8586   "operands[7]
8587      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8588                                                   DOM_CC_X_AND_Y),
8589                     CC_REGNUM);"
8590   [(set_attr "conds" "clob")
8591    (set_attr "length" "16")])
8592
8593 ; If the above pattern is followed by a CMP insn, then the compare is 
8594 ; redundant, since we can rework the conditional instruction that follows.
8595 (define_insn_and_split "*and_scc_scc_cmp"
8596   [(set (match_operand 0 "dominant_cc_register" "")
8597         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8598                           [(match_operand:SI 1 "s_register_operand" "r")
8599                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8600                          (match_operator:SI 6 "arm_comparison_operator"
8601                           [(match_operand:SI 4 "s_register_operand" "r")
8602                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8603                  (const_int 0)))
8604    (set (match_operand:SI 7 "s_register_operand" "=r")
8605         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8606                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8607   "TARGET_ARM"
8608   "#"
8609   "TARGET_ARM && reload_completed"
8610   [(set (match_dup 0)
8611         (compare
8612          (and:SI
8613           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8614           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8615          (const_int 0)))
8616    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8617   ""
8618   [(set_attr "conds" "set")
8619    (set_attr "length" "16")])
8620
8621 ;; If there is no dominance in the comparison, then we can still save an
8622 ;; instruction in the AND case, since we can know that the second compare
8623 ;; need only zero the value if false (if true, then the value is already
8624 ;; correct).
8625 (define_insn_and_split "*and_scc_scc_nodom"
8626   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8627         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8628                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
8629                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8630                 (match_operator:SI 6 "arm_comparison_operator"
8631                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
8632                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8633    (clobber (reg:CC CC_REGNUM))]
8634   "TARGET_ARM
8635    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8636        == CCmode)"
8637   "#"
8638   "TARGET_ARM && reload_completed"
8639   [(parallel [(set (match_dup 0)
8640                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8641               (clobber (reg:CC CC_REGNUM))])
8642    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8643    (set (match_dup 0)
8644         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8645                          (match_dup 0)
8646                          (const_int 0)))]
8647   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8648                                               operands[4], operands[5]),
8649                               CC_REGNUM);
8650    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8651                                   operands[5]);"
8652   [(set_attr "conds" "clob")
8653    (set_attr "length" "20")])
8654
8655 (define_split
8656   [(set (reg:CC_NOOV CC_REGNUM)
8657         (compare:CC_NOOV (ior:SI
8658                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8659                                   (const_int 1))
8660                           (match_operator:SI 1 "comparison_operator"
8661                            [(match_operand:SI 2 "s_register_operand" "")
8662                             (match_operand:SI 3 "arm_add_operand" "")]))
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_split
8675   [(set (reg:CC_NOOV CC_REGNUM)
8676         (compare:CC_NOOV (ior:SI
8677                           (match_operator:SI 1 "comparison_operator"
8678                            [(match_operand:SI 2 "s_register_operand" "")
8679                             (match_operand:SI 3 "arm_add_operand" "")])
8680                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8681                                   (const_int 1)))
8682                          (const_int 0)))
8683    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8684   "TARGET_ARM"
8685   [(set (match_dup 4)
8686         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8687                 (match_dup 0)))
8688    (set (reg:CC_NOOV CC_REGNUM)
8689         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8690                          (const_int 0)))]
8691   "")
8692
8693 (define_insn "*negscc"
8694   [(set (match_operand:SI 0 "s_register_operand" "=r")
8695         (neg:SI (match_operator 3 "arm_comparison_operator"
8696                  [(match_operand:SI 1 "s_register_operand" "r")
8697                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8698    (clobber (reg:CC CC_REGNUM))]
8699   "TARGET_ARM"
8700   "*
8701   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8702     return \"mov\\t%0, %1, asr #31\";
8703
8704   if (GET_CODE (operands[3]) == NE)
8705     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8706
8707   if (GET_CODE (operands[3]) == GT)
8708     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8709
8710   output_asm_insn (\"cmp\\t%1, %2\", operands);
8711   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8712   return \"mvn%d3\\t%0, #0\";
8713   "
8714   [(set_attr "conds" "clob")
8715    (set_attr "length" "12")]
8716 )
8717
8718 (define_insn "movcond"
8719   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8720         (if_then_else:SI
8721          (match_operator 5 "arm_comparison_operator"
8722           [(match_operand:SI 3 "s_register_operand" "r,r,r")
8723            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8724          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8725          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8726    (clobber (reg:CC CC_REGNUM))]
8727   "TARGET_ARM"
8728   "*
8729   if (GET_CODE (operands[5]) == LT
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 \"and\\t%0, %1, %3, asr #31\";
8736           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8737         }
8738       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8739         {
8740           if (operands[1] == const0_rtx)
8741             return \"bic\\t%0, %2, %3, asr #31\";
8742           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8743         }
8744       /* The only case that falls through to here is when both ops 1 & 2
8745          are constants.  */
8746     }
8747
8748   if (GET_CODE (operands[5]) == GE
8749       && (operands[4] == const0_rtx))
8750     {
8751       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8752         {
8753           if (operands[2] == const0_rtx)
8754             return \"bic\\t%0, %1, %3, asr #31\";
8755           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8756         }
8757       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8758         {
8759           if (operands[1] == const0_rtx)
8760             return \"and\\t%0, %2, %3, asr #31\";
8761           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8762         }
8763       /* The only case that falls through to here is when both ops 1 & 2
8764          are constants.  */
8765     }
8766   if (GET_CODE (operands[4]) == CONST_INT
8767       && !const_ok_for_arm (INTVAL (operands[4])))
8768     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8769   else
8770     output_asm_insn (\"cmp\\t%3, %4\", operands);
8771   if (which_alternative != 0)
8772     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8773   if (which_alternative != 1)
8774     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8775   return \"\";
8776   "
8777   [(set_attr "conds" "clob")
8778    (set_attr "length" "8,8,12")]
8779 )
8780
8781 (define_insn "*ifcompare_plus_move"
8782   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8783         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8784                           [(match_operand:SI 4 "s_register_operand" "r,r")
8785                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8786                          (plus:SI
8787                           (match_operand:SI 2 "s_register_operand" "r,r")
8788                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8789                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8790    (clobber (reg:CC CC_REGNUM))]
8791   "TARGET_ARM"
8792   "#"
8793   [(set_attr "conds" "clob")
8794    (set_attr "length" "8,12")]
8795 )
8796
8797 (define_insn "*if_plus_move"
8798   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8799         (if_then_else:SI
8800          (match_operator 4 "arm_comparison_operator"
8801           [(match_operand 5 "cc_register" "") (const_int 0)])
8802          (plus:SI
8803           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8804           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8805          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8806   "TARGET_ARM"
8807   "@
8808    add%d4\\t%0, %2, %3
8809    sub%d4\\t%0, %2, #%n3
8810    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8811    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8812   [(set_attr "conds" "use")
8813    (set_attr "length" "4,4,8,8")
8814    (set_attr "type" "*,*,*,*")]
8815 )
8816
8817 (define_insn "*ifcompare_move_plus"
8818   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8819         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8820                           [(match_operand:SI 4 "s_register_operand" "r,r")
8821                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8822                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8823                          (plus:SI
8824                           (match_operand:SI 2 "s_register_operand" "r,r")
8825                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8826    (clobber (reg:CC CC_REGNUM))]
8827   "TARGET_ARM"
8828   "#"
8829   [(set_attr "conds" "clob")
8830    (set_attr "length" "8,12")]
8831 )
8832
8833 (define_insn "*if_move_plus"
8834   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8835         (if_then_else:SI
8836          (match_operator 4 "arm_comparison_operator"
8837           [(match_operand 5 "cc_register" "") (const_int 0)])
8838          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8839          (plus:SI
8840           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8841           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8842   "TARGET_ARM"
8843   "@
8844    add%D4\\t%0, %2, %3
8845    sub%D4\\t%0, %2, #%n3
8846    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8847    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8848   [(set_attr "conds" "use")
8849    (set_attr "length" "4,4,8,8")
8850    (set_attr "type" "*,*,*,*")]
8851 )
8852
8853 (define_insn "*ifcompare_arith_arith"
8854   [(set (match_operand:SI 0 "s_register_operand" "=r")
8855         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8856                           [(match_operand:SI 5 "s_register_operand" "r")
8857                            (match_operand:SI 6 "arm_add_operand" "rIL")])
8858                          (match_operator:SI 8 "shiftable_operator"
8859                           [(match_operand:SI 1 "s_register_operand" "r")
8860                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8861                          (match_operator:SI 7 "shiftable_operator"
8862                           [(match_operand:SI 3 "s_register_operand" "r")
8863                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8864    (clobber (reg:CC CC_REGNUM))]
8865   "TARGET_ARM"
8866   "#"
8867   [(set_attr "conds" "clob")
8868    (set_attr "length" "12")]
8869 )
8870
8871 (define_insn "*if_arith_arith"
8872   [(set (match_operand:SI 0 "s_register_operand" "=r")
8873         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8874                           [(match_operand 8 "cc_register" "") (const_int 0)])
8875                          (match_operator:SI 6 "shiftable_operator"
8876                           [(match_operand:SI 1 "s_register_operand" "r")
8877                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8878                          (match_operator:SI 7 "shiftable_operator"
8879                           [(match_operand:SI 3 "s_register_operand" "r")
8880                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8881   "TARGET_ARM"
8882   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8883   [(set_attr "conds" "use")
8884    (set_attr "length" "8")]
8885 )
8886
8887 (define_insn "*ifcompare_arith_move"
8888   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8889         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8890                           [(match_operand:SI 2 "s_register_operand" "r,r")
8891                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8892                          (match_operator:SI 7 "shiftable_operator"
8893                           [(match_operand:SI 4 "s_register_operand" "r,r")
8894                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8895                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8896    (clobber (reg:CC CC_REGNUM))]
8897   "TARGET_ARM"
8898   "*
8899   /* If we have an operation where (op x 0) is the identity operation and
8900      the conditional operator is LT or GE and we are comparing against zero and
8901      everything is in registers then we can do this in two instructions.  */
8902   if (operands[3] == const0_rtx
8903       && GET_CODE (operands[7]) != AND
8904       && GET_CODE (operands[5]) == REG
8905       && GET_CODE (operands[1]) == REG 
8906       && REGNO (operands[1]) == REGNO (operands[4])
8907       && REGNO (operands[4]) != REGNO (operands[0]))
8908     {
8909       if (GET_CODE (operands[6]) == LT)
8910         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8911       else if (GET_CODE (operands[6]) == GE)
8912         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8913     }
8914   if (GET_CODE (operands[3]) == CONST_INT
8915       && !const_ok_for_arm (INTVAL (operands[3])))
8916     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8917   else
8918     output_asm_insn (\"cmp\\t%2, %3\", operands);
8919   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8920   if (which_alternative != 0)
8921     return \"mov%D6\\t%0, %1\";
8922   return \"\";
8923   "
8924   [(set_attr "conds" "clob")
8925    (set_attr "length" "8,12")]
8926 )
8927
8928 (define_insn "*if_arith_move"
8929   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8930         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8931                           [(match_operand 6 "cc_register" "") (const_int 0)])
8932                          (match_operator:SI 5 "shiftable_operator"
8933                           [(match_operand:SI 2 "s_register_operand" "r,r")
8934                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8935                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8936   "TARGET_ARM"
8937   "@
8938    %I5%d4\\t%0, %2, %3
8939    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8940   [(set_attr "conds" "use")
8941    (set_attr "length" "4,8")
8942    (set_attr "type" "*,*")]
8943 )
8944
8945 (define_insn "*ifcompare_move_arith"
8946   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8947         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8948                           [(match_operand:SI 4 "s_register_operand" "r,r")
8949                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8950                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8951                          (match_operator:SI 7 "shiftable_operator"
8952                           [(match_operand:SI 2 "s_register_operand" "r,r")
8953                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8954    (clobber (reg:CC CC_REGNUM))]
8955   "TARGET_ARM"
8956   "*
8957   /* If we have an operation where (op x 0) is the identity operation and
8958      the conditional operator is LT or GE and we are comparing against zero and
8959      everything is in registers then we can do this in two instructions */
8960   if (operands[5] == const0_rtx
8961       && GET_CODE (operands[7]) != AND
8962       && GET_CODE (operands[3]) == REG
8963       && GET_CODE (operands[1]) == REG 
8964       && REGNO (operands[1]) == REGNO (operands[2])
8965       && REGNO (operands[2]) != REGNO (operands[0]))
8966     {
8967       if (GET_CODE (operands[6]) == GE)
8968         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8969       else if (GET_CODE (operands[6]) == LT)
8970         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8971     }
8972
8973   if (GET_CODE (operands[5]) == CONST_INT
8974       && !const_ok_for_arm (INTVAL (operands[5])))
8975     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
8976   else
8977     output_asm_insn (\"cmp\\t%4, %5\", operands);
8978
8979   if (which_alternative != 0)
8980     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
8981   return \"%I7%D6\\t%0, %2, %3\";
8982   "
8983   [(set_attr "conds" "clob")
8984    (set_attr "length" "8,12")]
8985 )
8986
8987 (define_insn "*if_move_arith"
8988   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8989         (if_then_else:SI
8990          (match_operator 4 "arm_comparison_operator"
8991           [(match_operand 6 "cc_register" "") (const_int 0)])
8992          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8993          (match_operator:SI 5 "shiftable_operator"
8994           [(match_operand:SI 2 "s_register_operand" "r,r")
8995            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
8996   "TARGET_ARM"
8997   "@
8998    %I5%D4\\t%0, %2, %3
8999    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
9000   [(set_attr "conds" "use")
9001    (set_attr "length" "4,8")
9002    (set_attr "type" "*,*")]
9003 )
9004
9005 (define_insn "*ifcompare_move_not"
9006   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9007         (if_then_else:SI
9008          (match_operator 5 "arm_comparison_operator"
9009           [(match_operand:SI 3 "s_register_operand" "r,r")
9010            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9011          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9012          (not:SI
9013           (match_operand:SI 2 "s_register_operand" "r,r"))))
9014    (clobber (reg:CC CC_REGNUM))]
9015   "TARGET_ARM"
9016   "#"
9017   [(set_attr "conds" "clob")
9018    (set_attr "length" "8,12")]
9019 )
9020
9021 (define_insn "*if_move_not"
9022   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9023         (if_then_else:SI
9024          (match_operator 4 "arm_comparison_operator"
9025           [(match_operand 3 "cc_register" "") (const_int 0)])
9026          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9027          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9028   "TARGET_ARM"
9029   "@
9030    mvn%D4\\t%0, %2
9031    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9032    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
9033   [(set_attr "conds" "use")
9034    (set_attr "length" "4,8,8")]
9035 )
9036
9037 (define_insn "*ifcompare_not_move"
9038   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9039         (if_then_else:SI 
9040          (match_operator 5 "arm_comparison_operator"
9041           [(match_operand:SI 3 "s_register_operand" "r,r")
9042            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9043          (not:SI
9044           (match_operand:SI 2 "s_register_operand" "r,r"))
9045          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9046    (clobber (reg:CC CC_REGNUM))]
9047   "TARGET_ARM"
9048   "#"
9049   [(set_attr "conds" "clob")
9050    (set_attr "length" "8,12")]
9051 )
9052
9053 (define_insn "*if_not_move"
9054   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9055         (if_then_else:SI
9056          (match_operator 4 "arm_comparison_operator"
9057           [(match_operand 3 "cc_register" "") (const_int 0)])
9058          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9059          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9060   "TARGET_ARM"
9061   "@
9062    mvn%d4\\t%0, %2
9063    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9064    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
9065   [(set_attr "conds" "use")
9066    (set_attr "length" "4,8,8")]
9067 )
9068
9069 (define_insn "*ifcompare_shift_move"
9070   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9071         (if_then_else:SI
9072          (match_operator 6 "arm_comparison_operator"
9073           [(match_operand:SI 4 "s_register_operand" "r,r")
9074            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9075          (match_operator:SI 7 "shift_operator"
9076           [(match_operand:SI 2 "s_register_operand" "r,r")
9077            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9078          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9079    (clobber (reg:CC CC_REGNUM))]
9080   "TARGET_ARM"
9081   "#"
9082   [(set_attr "conds" "clob")
9083    (set_attr "length" "8,12")]
9084 )
9085
9086 (define_insn "*if_shift_move"
9087   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9088         (if_then_else:SI
9089          (match_operator 5 "arm_comparison_operator"
9090           [(match_operand 6 "cc_register" "") (const_int 0)])
9091          (match_operator:SI 4 "shift_operator"
9092           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9093            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9094          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9095   "TARGET_ARM"
9096   "@
9097    mov%d5\\t%0, %2%S4
9098    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9099    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
9100   [(set_attr "conds" "use")
9101    (set_attr "shift" "2")
9102    (set_attr "length" "4,8,8")
9103    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9104                       (const_string "alu_shift")
9105                       (const_string "alu_shift_reg")))]
9106 )
9107
9108 (define_insn "*ifcompare_move_shift"
9109   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9110         (if_then_else:SI
9111          (match_operator 6 "arm_comparison_operator"
9112           [(match_operand:SI 4 "s_register_operand" "r,r")
9113            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9114          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9115          (match_operator:SI 7 "shift_operator"
9116           [(match_operand:SI 2 "s_register_operand" "r,r")
9117            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
9118    (clobber (reg:CC CC_REGNUM))]
9119   "TARGET_ARM"
9120   "#"
9121   [(set_attr "conds" "clob")
9122    (set_attr "length" "8,12")]
9123 )
9124
9125 (define_insn "*if_move_shift"
9126   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9127         (if_then_else:SI
9128          (match_operator 5 "arm_comparison_operator"
9129           [(match_operand 6 "cc_register" "") (const_int 0)])
9130          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9131          (match_operator:SI 4 "shift_operator"
9132           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9133            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
9134   "TARGET_ARM"
9135   "@
9136    mov%D5\\t%0, %2%S4
9137    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9138    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
9139   [(set_attr "conds" "use")
9140    (set_attr "shift" "2")
9141    (set_attr "length" "4,8,8")
9142    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9143                       (const_string "alu_shift")
9144                       (const_string "alu_shift_reg")))]
9145 )
9146
9147 (define_insn "*ifcompare_shift_shift"
9148   [(set (match_operand:SI 0 "s_register_operand" "=r")
9149         (if_then_else:SI
9150          (match_operator 7 "arm_comparison_operator"
9151           [(match_operand:SI 5 "s_register_operand" "r")
9152            (match_operand:SI 6 "arm_add_operand" "rIL")])
9153          (match_operator:SI 8 "shift_operator"
9154           [(match_operand:SI 1 "s_register_operand" "r")
9155            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9156          (match_operator:SI 9 "shift_operator"
9157           [(match_operand:SI 3 "s_register_operand" "r")
9158            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
9159    (clobber (reg:CC CC_REGNUM))]
9160   "TARGET_ARM"
9161   "#"
9162   [(set_attr "conds" "clob")
9163    (set_attr "length" "12")]
9164 )
9165
9166 (define_insn "*if_shift_shift"
9167   [(set (match_operand:SI 0 "s_register_operand" "=r")
9168         (if_then_else:SI
9169          (match_operator 5 "arm_comparison_operator"
9170           [(match_operand 8 "cc_register" "") (const_int 0)])
9171          (match_operator:SI 6 "shift_operator"
9172           [(match_operand:SI 1 "s_register_operand" "r")
9173            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9174          (match_operator:SI 7 "shift_operator"
9175           [(match_operand:SI 3 "s_register_operand" "r")
9176            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
9177   "TARGET_ARM"
9178   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
9179   [(set_attr "conds" "use")
9180    (set_attr "shift" "1")
9181    (set_attr "length" "8")
9182    (set (attr "type") (if_then_else
9183                         (and (match_operand 2 "const_int_operand" "")
9184                              (match_operand 4 "const_int_operand" ""))
9185                       (const_string "alu_shift")
9186                       (const_string "alu_shift_reg")))]
9187 )
9188
9189 (define_insn "*ifcompare_not_arith"
9190   [(set (match_operand:SI 0 "s_register_operand" "=r")
9191         (if_then_else:SI
9192          (match_operator 6 "arm_comparison_operator"
9193           [(match_operand:SI 4 "s_register_operand" "r")
9194            (match_operand:SI 5 "arm_add_operand" "rIL")])
9195          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9196          (match_operator:SI 7 "shiftable_operator"
9197           [(match_operand:SI 2 "s_register_operand" "r")
9198            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
9199    (clobber (reg:CC CC_REGNUM))]
9200   "TARGET_ARM"
9201   "#"
9202   [(set_attr "conds" "clob")
9203    (set_attr "length" "12")]
9204 )
9205
9206 (define_insn "*if_not_arith"
9207   [(set (match_operand:SI 0 "s_register_operand" "=r")
9208         (if_then_else:SI
9209          (match_operator 5 "arm_comparison_operator"
9210           [(match_operand 4 "cc_register" "") (const_int 0)])
9211          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9212          (match_operator:SI 6 "shiftable_operator"
9213           [(match_operand:SI 2 "s_register_operand" "r")
9214            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
9215   "TARGET_ARM"
9216   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
9217   [(set_attr "conds" "use")
9218    (set_attr "length" "8")]
9219 )
9220
9221 (define_insn "*ifcompare_arith_not"
9222   [(set (match_operand:SI 0 "s_register_operand" "=r")
9223         (if_then_else:SI
9224          (match_operator 6 "arm_comparison_operator"
9225           [(match_operand:SI 4 "s_register_operand" "r")
9226            (match_operand:SI 5 "arm_add_operand" "rIL")])
9227          (match_operator:SI 7 "shiftable_operator"
9228           [(match_operand:SI 2 "s_register_operand" "r")
9229            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9230          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9231    (clobber (reg:CC CC_REGNUM))]
9232   "TARGET_ARM"
9233   "#"
9234   [(set_attr "conds" "clob")
9235    (set_attr "length" "12")]
9236 )
9237
9238 (define_insn "*if_arith_not"
9239   [(set (match_operand:SI 0 "s_register_operand" "=r")
9240         (if_then_else:SI
9241          (match_operator 5 "arm_comparison_operator"
9242           [(match_operand 4 "cc_register" "") (const_int 0)])
9243          (match_operator:SI 6 "shiftable_operator"
9244           [(match_operand:SI 2 "s_register_operand" "r")
9245            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9246          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9247   "TARGET_ARM"
9248   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9249   [(set_attr "conds" "use")
9250    (set_attr "length" "8")]
9251 )
9252
9253 (define_insn "*ifcompare_neg_move"
9254   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9255         (if_then_else:SI
9256          (match_operator 5 "arm_comparison_operator"
9257           [(match_operand:SI 3 "s_register_operand" "r,r")
9258            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9259          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9260          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9261    (clobber (reg:CC CC_REGNUM))]
9262   "TARGET_ARM"
9263   "#"
9264   [(set_attr "conds" "clob")
9265    (set_attr "length" "8,12")]
9266 )
9267
9268 (define_insn "*if_neg_move"
9269   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9270         (if_then_else:SI
9271          (match_operator 4 "arm_comparison_operator"
9272           [(match_operand 3 "cc_register" "") (const_int 0)])
9273          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9274          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9275   "TARGET_ARM"
9276   "@
9277    rsb%d4\\t%0, %2, #0
9278    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9279    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9280   [(set_attr "conds" "use")
9281    (set_attr "length" "4,8,8")]
9282 )
9283
9284 (define_insn "*ifcompare_move_neg"
9285   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9286         (if_then_else:SI
9287          (match_operator 5 "arm_comparison_operator"
9288           [(match_operand:SI 3 "s_register_operand" "r,r")
9289            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9290          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9291          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9292    (clobber (reg:CC CC_REGNUM))]
9293   "TARGET_ARM"
9294   "#"
9295   [(set_attr "conds" "clob")
9296    (set_attr "length" "8,12")]
9297 )
9298
9299 (define_insn "*if_move_neg"
9300   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9301         (if_then_else:SI
9302          (match_operator 4 "arm_comparison_operator"
9303           [(match_operand 3 "cc_register" "") (const_int 0)])
9304          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9305          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9306   "TARGET_ARM"
9307   "@
9308    rsb%D4\\t%0, %2, #0
9309    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9310    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9311   [(set_attr "conds" "use")
9312    (set_attr "length" "4,8,8")]
9313 )
9314
9315 (define_insn "*arith_adjacentmem"
9316   [(set (match_operand:SI 0 "s_register_operand" "=r")
9317         (match_operator:SI 1 "shiftable_operator"
9318          [(match_operand:SI 2 "memory_operand" "m")
9319           (match_operand:SI 3 "memory_operand" "m")]))
9320    (clobber (match_scratch:SI 4 "=r"))]
9321   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9322   "*
9323   {
9324     rtx ldm[3];
9325     rtx arith[4];
9326     rtx base_reg;
9327     HOST_WIDE_INT val1 = 0, val2 = 0;
9328
9329     if (REGNO (operands[0]) > REGNO (operands[4]))
9330       {
9331         ldm[1] = operands[4];
9332         ldm[2] = operands[0];
9333       }
9334     else
9335       {
9336         ldm[1] = operands[0];
9337         ldm[2] = operands[4];
9338       }
9339
9340     base_reg = XEXP (operands[2], 0);
9341
9342     if (!REG_P (base_reg))
9343       {
9344         val1 = INTVAL (XEXP (base_reg, 1));
9345         base_reg = XEXP (base_reg, 0);
9346       }
9347
9348     if (!REG_P (XEXP (operands[3], 0)))
9349       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9350
9351     arith[0] = operands[0];
9352     arith[3] = operands[1];
9353
9354     if (val1 < val2)
9355       {
9356         arith[1] = ldm[1];
9357         arith[2] = ldm[2];
9358       }
9359     else
9360       {
9361         arith[1] = ldm[2];
9362         arith[2] = ldm[1];
9363       }
9364
9365     ldm[0] = base_reg;
9366     if (val1 !=0 && val2 != 0)
9367       {
9368         if (val1 == 4 || val2 == 4)
9369           /* Other val must be 8, since we know they are adjacent and neither
9370              is zero.  */
9371           output_asm_insn (\"ldm%?ib\\t%0, {%1, %2}\", ldm);
9372         else
9373           {
9374             rtx ops[3];
9375
9376             ldm[0] = ops[0] = operands[4];
9377             ops[1] = base_reg;
9378             ops[2] = GEN_INT (val1);
9379             output_add_immediate (ops);
9380             if (val1 < val2)
9381               output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9382             else
9383               output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9384           }
9385       }
9386     else if (val1 != 0)
9387       {
9388         if (val1 < val2)
9389           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9390         else
9391           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9392       }
9393     else
9394       {
9395         if (val1 < val2)
9396           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9397         else
9398           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9399       }
9400     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9401     return \"\";
9402   }"
9403   [(set_attr "length" "12")
9404    (set_attr "predicable" "yes")
9405    (set_attr "type" "load1")]
9406 )
9407
9408 ;; the arm can support extended pre-inc instructions
9409
9410 ;; In all these cases, we use operands 0 and 1 for the register being
9411 ;; incremented because those are the operands that local-alloc will
9412 ;; tie and these are the pair most likely to be tieable (and the ones
9413 ;; that will benefit the most).
9414
9415 ;; We reject the frame pointer if it occurs anywhere in these patterns since
9416 ;; elimination will cause too many headaches.
9417
9418 (define_insn "*strqi_preinc"
9419   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9420                          (match_operand:SI 2 "index_operand" "rJ")))
9421         (match_operand:QI 3 "s_register_operand" "r"))
9422    (set (match_operand:SI 0 "s_register_operand" "=r")
9423         (plus:SI (match_dup 1) (match_dup 2)))]
9424   "TARGET_ARM
9425    && !arm_eliminable_register (operands[0])
9426    && !arm_eliminable_register (operands[1])
9427    && !arm_eliminable_register (operands[2])"
9428   "str%?b\\t%3, [%0, %2]!"
9429   [(set_attr "type" "store1")
9430    (set_attr "predicable" "yes")]
9431 )
9432
9433 (define_insn "*strqi_predec"
9434   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9435                           (match_operand:SI 2 "s_register_operand" "r")))
9436         (match_operand:QI 3 "s_register_operand" "r"))
9437    (set (match_operand:SI 0 "s_register_operand" "=r")
9438         (minus:SI (match_dup 1) (match_dup 2)))]
9439   "TARGET_ARM
9440    && !arm_eliminable_register (operands[0])
9441    && !arm_eliminable_register (operands[1])
9442    && !arm_eliminable_register (operands[2])"
9443   "str%?b\\t%3, [%0, -%2]!"
9444   [(set_attr "type" "store1")
9445    (set_attr "predicable" "yes")]
9446 )
9447
9448 (define_insn "*loadqi_preinc"
9449   [(set (match_operand:QI 3 "s_register_operand" "=r")
9450         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9451                          (match_operand:SI 2 "index_operand" "rJ"))))
9452    (set (match_operand:SI 0 "s_register_operand" "=r")
9453         (plus:SI (match_dup 1) (match_dup 2)))]
9454   "TARGET_ARM
9455    && !arm_eliminable_register (operands[0])
9456    && !arm_eliminable_register (operands[1])
9457    && !arm_eliminable_register (operands[2])"
9458   "ldr%?b\\t%3, [%0, %2]!"
9459   [(set_attr "type" "load_byte")
9460    (set_attr "predicable" "yes")]
9461 )
9462
9463 (define_insn "*loadqi_predec"
9464   [(set (match_operand:QI 3 "s_register_operand" "=r")
9465         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9466                           (match_operand:SI 2 "s_register_operand" "r"))))
9467    (set (match_operand:SI 0 "s_register_operand" "=r")
9468         (minus:SI (match_dup 1) (match_dup 2)))]
9469   "TARGET_ARM
9470    && !arm_eliminable_register (operands[0])
9471    && !arm_eliminable_register (operands[1])
9472    && !arm_eliminable_register (operands[2])"
9473   "ldr%?b\\t%3, [%0, -%2]!"
9474   [(set_attr "type" "load_byte")
9475    (set_attr "predicable" "yes")]
9476 )
9477
9478 (define_insn "*loadqisi_preinc"
9479   [(set (match_operand:SI 3 "s_register_operand" "=r")
9480         (zero_extend:SI
9481          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9482                           (match_operand:SI 2 "index_operand" "rJ")))))
9483    (set (match_operand:SI 0 "s_register_operand" "=r")
9484         (plus:SI (match_dup 1) (match_dup 2)))]
9485   "TARGET_ARM
9486    && !arm_eliminable_register (operands[0])
9487    && !arm_eliminable_register (operands[1])
9488    && !arm_eliminable_register (operands[2])"
9489   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
9490   [(set_attr "type" "load_byte")
9491    (set_attr "predicable" "yes")]
9492 )
9493
9494 (define_insn "*loadqisi_predec"
9495   [(set (match_operand:SI 3 "s_register_operand" "=r")
9496         (zero_extend:SI
9497          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9498                            (match_operand:SI 2 "s_register_operand" "r")))))
9499    (set (match_operand:SI 0 "s_register_operand" "=r")
9500         (minus:SI (match_dup 1) (match_dup 2)))]
9501   "TARGET_ARM
9502    && !arm_eliminable_register (operands[0])
9503    && !arm_eliminable_register (operands[1])
9504    && !arm_eliminable_register (operands[2])"
9505   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
9506   [(set_attr "type" "load_byte")
9507    (set_attr "predicable" "yes")]
9508 )
9509
9510 (define_insn "*strsi_preinc"
9511   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9512                          (match_operand:SI 2 "index_operand" "rJ")))
9513         (match_operand:SI 3 "s_register_operand" "r"))
9514    (set (match_operand:SI 0 "s_register_operand" "=r")
9515         (plus:SI (match_dup 1) (match_dup 2)))]
9516   "TARGET_ARM
9517    && !arm_eliminable_register (operands[0])
9518    && !arm_eliminable_register (operands[1])
9519    && !arm_eliminable_register (operands[2])"
9520   "str%?\\t%3, [%0, %2]!"
9521   [(set_attr "type" "store1")
9522    (set_attr "predicable" "yes")]
9523 )
9524
9525 (define_insn "*strsi_predec"
9526   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9527                           (match_operand:SI 2 "s_register_operand" "r")))
9528         (match_operand:SI 3 "s_register_operand" "r"))
9529    (set (match_operand:SI 0 "s_register_operand" "=r")
9530         (minus:SI (match_dup 1) (match_dup 2)))]
9531   "TARGET_ARM
9532    && !arm_eliminable_register (operands[0])
9533    && !arm_eliminable_register (operands[1])
9534    && !arm_eliminable_register (operands[2])"
9535   "str%?\\t%3, [%0, -%2]!"
9536   [(set_attr "type" "store1")
9537    (set_attr "predicable" "yes")]
9538 )
9539
9540 (define_insn "*loadsi_preinc"
9541   [(set (match_operand:SI 3 "s_register_operand" "=r")
9542         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9543                          (match_operand:SI 2 "index_operand" "rJ"))))
9544    (set (match_operand:SI 0 "s_register_operand" "=r")
9545         (plus:SI (match_dup 1) (match_dup 2)))]
9546   "TARGET_ARM
9547    && !arm_eliminable_register (operands[0])
9548    && !arm_eliminable_register (operands[1])
9549    && !arm_eliminable_register (operands[2])"
9550   "ldr%?\\t%3, [%0, %2]!"
9551   [(set_attr "type" "load1")
9552    (set_attr "predicable" "yes")]
9553 )
9554
9555 (define_insn "*loadsi_predec"
9556   [(set (match_operand:SI 3 "s_register_operand" "=r")
9557         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9558                           (match_operand:SI 2 "s_register_operand" "r"))))
9559    (set (match_operand:SI 0 "s_register_operand" "=r")
9560         (minus:SI (match_dup 1) (match_dup 2)))]
9561   "TARGET_ARM
9562    && !arm_eliminable_register (operands[0])
9563    && !arm_eliminable_register (operands[1])
9564    && !arm_eliminable_register (operands[2])"
9565   "ldr%?\\t%3, [%0, -%2]!"
9566   [(set_attr "type" "load1")
9567    (set_attr "predicable" "yes")]
9568 )
9569
9570 (define_insn "*strqi_shiftpreinc"
9571   [(set (mem:QI (plus:SI (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:SI 1 "s_register_operand" "0")))
9575         (match_operand:QI 5 "s_register_operand" "r"))
9576    (set (match_operand:SI 0 "s_register_operand" "=r")
9577         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9578                  (match_dup 1)))]
9579   "TARGET_ARM
9580    && !arm_eliminable_register (operands[0])
9581    && !arm_eliminable_register (operands[1])
9582    && !arm_eliminable_register (operands[3])"
9583   "str%?b\\t%5, [%0, %3%S2]!"
9584   [(set_attr "type" "store1")
9585    (set_attr "predicable" "yes")]
9586 )
9587
9588 (define_insn "*strqi_shiftpredec"
9589   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9590                           (match_operator:SI 2 "shift_operator"
9591                            [(match_operand:SI 3 "s_register_operand" "r")
9592                             (match_operand:SI 4 "const_shift_operand" "n")])))
9593         (match_operand:QI 5 "s_register_operand" "r"))
9594    (set (match_operand:SI 0 "s_register_operand" "=r")
9595         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9596                                                  (match_dup 4)])))]
9597   "TARGET_ARM
9598    && !arm_eliminable_register (operands[0])
9599    && !arm_eliminable_register (operands[1])
9600    && !arm_eliminable_register (operands[3])"
9601   "str%?b\\t%5, [%0, -%3%S2]!"
9602   [(set_attr "type" "store1")
9603    (set_attr "predicable" "yes")]
9604 )
9605
9606 (define_insn "*loadqi_shiftpreinc"
9607   [(set (match_operand:QI 5 "s_register_operand" "=r")
9608         (mem:QI (plus:SI (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                          (match_operand:SI 1 "s_register_operand" "0"))))
9612    (set (match_operand:SI 0 "s_register_operand" "=r")
9613         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9614                  (match_dup 1)))]
9615   "TARGET_ARM
9616    && !arm_eliminable_register (operands[0])
9617    && !arm_eliminable_register (operands[1])
9618    && !arm_eliminable_register (operands[3])"
9619   "ldr%?b\\t%5, [%0, %3%S2]!"
9620   [(set_attr "type" "load_byte")
9621    (set_attr "predicable" "yes")]
9622 )
9623
9624 (define_insn "*loadqi_shiftpredec"
9625   [(set (match_operand:QI 5 "s_register_operand" "=r")
9626         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9627                           (match_operator:SI 2 "shift_operator"
9628                            [(match_operand:SI 3 "s_register_operand" "r")
9629                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9630    (set (match_operand:SI 0 "s_register_operand" "=r")
9631         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9632                                                  (match_dup 4)])))]
9633   "TARGET_ARM
9634    && !arm_eliminable_register (operands[0])
9635    && !arm_eliminable_register (operands[1])
9636    && !arm_eliminable_register (operands[3])"
9637   "ldr%?b\\t%5, [%0, -%3%S2]!"
9638   [(set_attr "type" "load_byte")
9639    (set_attr "predicable" "yes")]
9640 )
9641
9642 (define_insn "*strsi_shiftpreinc"
9643   [(set (mem:SI (plus:SI (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 1 "s_register_operand" "0")))
9647         (match_operand:SI 5 "s_register_operand" "r"))
9648    (set (match_operand:SI 0 "s_register_operand" "=r")
9649         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9650                  (match_dup 1)))]
9651   "TARGET_ARM
9652    && !arm_eliminable_register (operands[0])
9653    && !arm_eliminable_register (operands[1])
9654    && !arm_eliminable_register (operands[3])"
9655   "str%?\\t%5, [%0, %3%S2]!"
9656   [(set_attr "type" "store1")
9657    (set_attr "predicable" "yes")]
9658 )
9659
9660 (define_insn "*strsi_shiftpredec"
9661   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9662                           (match_operator:SI 2 "shift_operator"
9663                            [(match_operand:SI 3 "s_register_operand" "r")
9664                             (match_operand:SI 4 "const_shift_operand" "n")])))
9665         (match_operand:SI 5 "s_register_operand" "r"))
9666    (set (match_operand:SI 0 "s_register_operand" "=r")
9667         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9668                                                  (match_dup 4)])))]
9669   "TARGET_ARM
9670    && !arm_eliminable_register (operands[0])
9671    && !arm_eliminable_register (operands[1])
9672    && !arm_eliminable_register (operands[3])"
9673   "str%?\\t%5, [%0, -%3%S2]!"
9674   [(set_attr "type" "store1")
9675    (set_attr "predicable" "yes")]
9676 )
9677
9678 (define_insn "*loadsi_shiftpreinc"
9679   [(set (match_operand:SI 5 "s_register_operand" "=r")
9680         (mem:SI (plus:SI (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                          (match_operand:SI 1 "s_register_operand" "0"))))
9684    (set (match_operand:SI 0 "s_register_operand" "=r")
9685         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9686                  (match_dup 1)))]
9687   "TARGET_ARM
9688    && !arm_eliminable_register (operands[0])
9689    && !arm_eliminable_register (operands[1])
9690    && !arm_eliminable_register (operands[3])"
9691   "ldr%?\\t%5, [%0, %3%S2]!"
9692   [(set_attr "type" "load1")
9693    (set_attr "predicable" "yes")]
9694 )
9695
9696 (define_insn "*loadsi_shiftpredec"
9697   [(set (match_operand:SI 5 "s_register_operand" "=r")
9698         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9699                           (match_operator:SI 2 "shift_operator"
9700                            [(match_operand:SI 3 "s_register_operand" "r")
9701                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9702    (set (match_operand:SI 0 "s_register_operand" "=r")
9703         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9704                                                  (match_dup 4)])))]
9705   "TARGET_ARM
9706    && !arm_eliminable_register (operands[0])
9707    && !arm_eliminable_register (operands[1])
9708    && !arm_eliminable_register (operands[3])"
9709   "ldr%?\\t%5, [%0, -%3%S2]!"
9710   [(set_attr "type" "load1")
9711    (set_attr "predicable" "yes")])
9712
9713 ; It can also support extended post-inc expressions, but combine doesn't
9714 ; try these....
9715 ; It doesn't seem worth adding peepholes for anything but the most common
9716 ; cases since, unlike combine, the increment must immediately follow the load
9717 ; for this pattern to match.
9718 ; We must watch to see that the source/destination register isn't also the
9719 ; same as the base address register, and that if the index is a register,
9720 ; that it is not the same as the base address register.  In such cases the
9721 ; instruction that we would generate would have UNPREDICTABLE behavior so 
9722 ; we cannot use it.
9723
9724 (define_peephole
9725   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9726         (match_operand:QI 2 "s_register_operand" "r"))
9727    (set (match_dup 0)
9728         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9729   "TARGET_ARM
9730    && (REGNO (operands[2]) != REGNO (operands[0]))
9731    && (GET_CODE (operands[1]) != REG
9732        || (REGNO (operands[1]) != REGNO (operands[0])))"
9733   "str%?b\\t%2, [%0], %1"
9734 )
9735
9736 (define_peephole
9737   [(set (match_operand:QI 0 "s_register_operand" "=r")
9738         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9739    (set (match_dup 1)
9740         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9741   "TARGET_ARM
9742    && REGNO (operands[0]) != REGNO(operands[1])
9743    && (GET_CODE (operands[2]) != REG
9744        || REGNO(operands[0]) != REGNO (operands[2]))"
9745   "ldr%?b\\t%0, [%1], %2"
9746 )
9747
9748 (define_peephole
9749   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9750         (match_operand:SI 2 "s_register_operand" "r"))
9751    (set (match_dup 0)
9752         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9753   "TARGET_ARM
9754    && (REGNO (operands[2]) != REGNO (operands[0]))
9755    && (GET_CODE (operands[1]) != REG
9756        || (REGNO (operands[1]) != REGNO (operands[0])))"
9757   "str%?\\t%2, [%0], %1"
9758 )
9759
9760 (define_peephole
9761   [(set (match_operand:SI 0 "s_register_operand" "=r")
9762         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9763    (set (match_dup 1)
9764         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9765   "TARGET_ARM
9766    && REGNO (operands[0]) != REGNO(operands[1])
9767    && (GET_CODE (operands[2]) != REG
9768        || REGNO(operands[0]) != REGNO (operands[2]))"
9769   "ldr%?\\t%0, [%1], %2"
9770 )
9771
9772 (define_peephole
9773   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9774                          (match_operand:SI 1 "index_operand" "rJ")))
9775         (match_operand:QI 2 "s_register_operand" "r"))
9776    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
9777   "TARGET_ARM
9778    && (REGNO (operands[2]) != REGNO (operands[0]))
9779    && (GET_CODE (operands[1]) != REG
9780        || (REGNO (operands[1]) != REGNO (operands[0])))"
9781   "str%?b\\t%2, [%0, %1]!"
9782 )
9783
9784 (define_peephole
9785   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9786                           [(match_operand:SI 0 "s_register_operand" "r")
9787                            (match_operand:SI 1 "const_int_operand" "n")])
9788                          (match_operand:SI 2 "s_register_operand" "+r")))
9789         (match_operand:QI 3 "s_register_operand" "r"))
9790    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9791                                (match_dup 2)))]
9792   "TARGET_ARM
9793    && (REGNO (operands[3]) != REGNO (operands[2]))
9794    && (REGNO (operands[0]) != REGNO (operands[2]))"
9795   "str%?b\\t%3, [%2, %0%S4]!"
9796 )
9797
9798 ; This pattern is never tried by combine, so do it as a peephole
9799
9800 (define_peephole2
9801   [(set (match_operand:SI 0 "arm_general_register_operand" "")
9802         (match_operand:SI 1 "arm_general_register_operand" ""))
9803    (set (reg:CC CC_REGNUM)
9804         (compare:CC (match_dup 1) (const_int 0)))]
9805   "TARGET_ARM"
9806   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9807               (set (match_dup 0) (match_dup 1))])]
9808   ""
9809 )
9810
9811 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9812 ; reversed, check that the memory references aren't volatile.
9813
9814 (define_peephole
9815   [(set (match_operand:SI 0 "s_register_operand" "=r")
9816         (match_operand:SI 4 "memory_operand" "m"))
9817    (set (match_operand:SI 1 "s_register_operand" "=r")
9818         (match_operand:SI 5 "memory_operand" "m"))
9819    (set (match_operand:SI 2 "s_register_operand" "=r")
9820         (match_operand:SI 6 "memory_operand" "m"))
9821    (set (match_operand:SI 3 "s_register_operand" "=r")
9822         (match_operand:SI 7 "memory_operand" "m"))]
9823   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9824   "*
9825   return emit_ldm_seq (operands, 4);
9826   "
9827 )
9828
9829 (define_peephole
9830   [(set (match_operand:SI 0 "s_register_operand" "=r")
9831         (match_operand:SI 3 "memory_operand" "m"))
9832    (set (match_operand:SI 1 "s_register_operand" "=r")
9833         (match_operand:SI 4 "memory_operand" "m"))
9834    (set (match_operand:SI 2 "s_register_operand" "=r")
9835         (match_operand:SI 5 "memory_operand" "m"))]
9836   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9837   "*
9838   return emit_ldm_seq (operands, 3);
9839   "
9840 )
9841
9842 (define_peephole
9843   [(set (match_operand:SI 0 "s_register_operand" "=r")
9844         (match_operand:SI 2 "memory_operand" "m"))
9845    (set (match_operand:SI 1 "s_register_operand" "=r")
9846         (match_operand:SI 3 "memory_operand" "m"))]
9847   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9848   "*
9849   return emit_ldm_seq (operands, 2);
9850   "
9851 )
9852
9853 (define_peephole
9854   [(set (match_operand:SI 4 "memory_operand" "=m")
9855         (match_operand:SI 0 "s_register_operand" "r"))
9856    (set (match_operand:SI 5 "memory_operand" "=m")
9857         (match_operand:SI 1 "s_register_operand" "r"))
9858    (set (match_operand:SI 6 "memory_operand" "=m")
9859         (match_operand:SI 2 "s_register_operand" "r"))
9860    (set (match_operand:SI 7 "memory_operand" "=m")
9861         (match_operand:SI 3 "s_register_operand" "r"))]
9862   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9863   "*
9864   return emit_stm_seq (operands, 4);
9865   "
9866 )
9867
9868 (define_peephole
9869   [(set (match_operand:SI 3 "memory_operand" "=m")
9870         (match_operand:SI 0 "s_register_operand" "r"))
9871    (set (match_operand:SI 4 "memory_operand" "=m")
9872         (match_operand:SI 1 "s_register_operand" "r"))
9873    (set (match_operand:SI 5 "memory_operand" "=m")
9874         (match_operand:SI 2 "s_register_operand" "r"))]
9875   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9876   "*
9877   return emit_stm_seq (operands, 3);
9878   "
9879 )
9880
9881 (define_peephole
9882   [(set (match_operand:SI 2 "memory_operand" "=m")
9883         (match_operand:SI 0 "s_register_operand" "r"))
9884    (set (match_operand:SI 3 "memory_operand" "=m")
9885         (match_operand:SI 1 "s_register_operand" "r"))]
9886   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9887   "*
9888   return emit_stm_seq (operands, 2);
9889   "
9890 )
9891
9892 (define_split
9893   [(set (match_operand:SI 0 "s_register_operand" "")
9894         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9895                        (const_int 0))
9896                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9897                          [(match_operand:SI 3 "s_register_operand" "")
9898                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
9899    (clobber (match_operand:SI 5 "s_register_operand" ""))]
9900   "TARGET_ARM"
9901   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9902    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9903                               (match_dup 5)))]
9904   ""
9905 )
9906
9907 ;; This split can be used because CC_Z mode implies that the following
9908 ;; branch will be an equality, or an unsigned inequality, so the sign
9909 ;; extension is not needed.
9910
9911 (define_split
9912   [(set (reg:CC_Z CC_REGNUM)
9913         (compare:CC_Z
9914          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9915                     (const_int 24))
9916          (match_operand 1 "const_int_operand" "")))
9917    (clobber (match_scratch:SI 2 ""))]
9918   "TARGET_ARM
9919    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9920        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9921   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9922    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9923   "
9924   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9925   "
9926 )
9927
9928 (define_expand "prologue"
9929   [(clobber (const_int 0))]
9930   "TARGET_EITHER"
9931   "if (TARGET_ARM)
9932      arm_expand_prologue ();
9933    else
9934      thumb_expand_prologue ();
9935   DONE;
9936   "
9937 )
9938
9939 (define_expand "epilogue"
9940   [(clobber (const_int 0))]
9941   "TARGET_EITHER"
9942   "
9943   if (current_function_calls_eh_return)
9944     emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
9945   if (TARGET_THUMB)
9946     thumb_expand_epilogue ();
9947   else if (USE_RETURN_INSN (FALSE))
9948     {
9949       emit_jump_insn (gen_return ());
9950       DONE;
9951     }
9952   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9953         gen_rtvec (1,
9954                 gen_rtx_RETURN (VOIDmode)),
9955         VUNSPEC_EPILOGUE));
9956   DONE;
9957   "
9958 )
9959
9960 ;; Note - although unspec_volatile's USE all hard registers,
9961 ;; USEs are ignored after relaod has completed.  Thus we need
9962 ;; to add an unspec of the link register to ensure that flow
9963 ;; does not think that it is unused by the sibcall branch that
9964 ;; will replace the standard function epilogue.
9965 (define_insn "sibcall_epilogue"
9966   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9967               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9968   "TARGET_ARM"
9969   "*
9970   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9971     return output_return_instruction (const_true_rtx, FALSE, FALSE);
9972   return arm_output_epilogue (next_nonnote_insn (insn));
9973   "
9974 ;; Length is absolute worst case
9975   [(set_attr "length" "44")
9976    (set_attr "type" "block")
9977    ;; We don't clobber the conditions, but the potential length of this
9978    ;; operation is sufficient to make conditionalizing the sequence 
9979    ;; unlikely to be profitable.
9980    (set_attr "conds" "clob")]
9981 )
9982
9983 (define_insn "*epilogue_insns"
9984   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9985   "TARGET_EITHER"
9986   "*
9987   if (TARGET_ARM)
9988     return arm_output_epilogue (NULL);
9989   else /* TARGET_THUMB */
9990     return thumb_unexpanded_epilogue ();
9991   "
9992   ; Length is absolute worst case
9993   [(set_attr "length" "44")
9994    (set_attr "type" "block")
9995    ;; We don't clobber the conditions, but the potential length of this
9996    ;; operation is sufficient to make conditionalizing the sequence 
9997    ;; unlikely to be profitable.
9998    (set_attr "conds" "clob")]
9999 )
10000
10001 (define_expand "eh_epilogue"
10002   [(use (match_operand:SI 0 "register_operand" ""))
10003    (use (match_operand:SI 1 "register_operand" ""))
10004    (use (match_operand:SI 2 "register_operand" ""))]
10005   "TARGET_EITHER"
10006   "
10007   {
10008     cfun->machine->eh_epilogue_sp_ofs = operands[1];
10009     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10010       {
10011         rtx ra = gen_rtx_REG (Pmode, 2);
10012
10013         emit_move_insn (ra, operands[2]);
10014         operands[2] = ra;
10015       }
10016     /* This is a hack -- we may have crystalized the function type too
10017        early.  */
10018     cfun->machine->func_type = 0;
10019   }"
10020 )
10021
10022 ;; This split is only used during output to reduce the number of patterns
10023 ;; that need assembler instructions adding to them.  We allowed the setting
10024 ;; of the conditions to be implicit during rtl generation so that
10025 ;; the conditional compare patterns would work.  However this conflicts to
10026 ;; some extent with the conditional data operations, so we have to split them
10027 ;; up again here.
10028
10029 (define_split
10030   [(set (match_operand:SI 0 "s_register_operand" "")
10031         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10032                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10033                          (match_dup 0)
10034                          (match_operand 4 "" "")))
10035    (clobber (reg:CC CC_REGNUM))]
10036   "TARGET_ARM && reload_completed"
10037   [(set (match_dup 5) (match_dup 6))
10038    (cond_exec (match_dup 7)
10039               (set (match_dup 0) (match_dup 4)))]
10040   "
10041   {
10042     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10043                                              operands[2], operands[3]);
10044     enum rtx_code rc = GET_CODE (operands[1]);
10045
10046     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10047     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10048     if (mode == CCFPmode || mode == CCFPEmode)
10049       rc = reverse_condition_maybe_unordered (rc);
10050     else
10051       rc = reverse_condition (rc);
10052
10053     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10054   }"
10055 )
10056
10057 (define_split
10058   [(set (match_operand:SI 0 "s_register_operand" "")
10059         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10060                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10061                          (match_operand 4 "" "")
10062                          (match_dup 0)))
10063    (clobber (reg:CC CC_REGNUM))]
10064   "TARGET_ARM && reload_completed"
10065   [(set (match_dup 5) (match_dup 6))
10066    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10067               (set (match_dup 0) (match_dup 4)))]
10068   "
10069   {
10070     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10071                                              operands[2], operands[3]);
10072
10073     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10074     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10075   }"
10076 )
10077
10078 (define_split
10079   [(set (match_operand:SI 0 "s_register_operand" "")
10080         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10081                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10082                          (match_operand 4 "" "")
10083                          (match_operand 5 "" "")))
10084    (clobber (reg:CC CC_REGNUM))]
10085   "TARGET_ARM && reload_completed"
10086   [(set (match_dup 6) (match_dup 7))
10087    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10088               (set (match_dup 0) (match_dup 4)))
10089    (cond_exec (match_dup 8)
10090               (set (match_dup 0) (match_dup 5)))]
10091   "
10092   {
10093     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10094                                              operands[2], operands[3]);
10095     enum rtx_code rc = GET_CODE (operands[1]);
10096
10097     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10098     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10099     if (mode == CCFPmode || mode == CCFPEmode)
10100       rc = reverse_condition_maybe_unordered (rc);
10101     else
10102       rc = reverse_condition (rc);
10103
10104     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10105   }"
10106 )
10107
10108 (define_split
10109   [(set (match_operand:SI 0 "s_register_operand" "")
10110         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10111                           [(match_operand:SI 2 "s_register_operand" "")
10112                            (match_operand:SI 3 "arm_add_operand" "")])
10113                          (match_operand:SI 4 "arm_rhs_operand" "")
10114                          (not:SI
10115                           (match_operand:SI 5 "s_register_operand" ""))))
10116    (clobber (reg:CC CC_REGNUM))]
10117   "TARGET_ARM && reload_completed"
10118   [(set (match_dup 6) (match_dup 7))
10119    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10120               (set (match_dup 0) (match_dup 4)))
10121    (cond_exec (match_dup 8)
10122               (set (match_dup 0) (not:SI (match_dup 5))))]
10123   "
10124   {
10125     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10126                                              operands[2], operands[3]);
10127     enum rtx_code rc = GET_CODE (operands[1]);
10128
10129     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10130     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10131     if (mode == CCFPmode || mode == CCFPEmode)
10132       rc = reverse_condition_maybe_unordered (rc);
10133     else
10134       rc = reverse_condition (rc);
10135
10136     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10137   }"
10138 )
10139
10140 (define_insn "*cond_move_not"
10141   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10142         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10143                           [(match_operand 3 "cc_register" "") (const_int 0)])
10144                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10145                          (not:SI
10146                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
10147   "TARGET_ARM"
10148   "@
10149    mvn%D4\\t%0, %2
10150    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
10151   [(set_attr "conds" "use")
10152    (set_attr "length" "4,8")]
10153 )
10154
10155 ;; The next two patterns occur when an AND operation is followed by a
10156 ;; scc insn sequence 
10157
10158 (define_insn "*sign_extract_onebit"
10159   [(set (match_operand:SI 0 "s_register_operand" "=r")
10160         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10161                          (const_int 1)
10162                          (match_operand:SI 2 "const_int_operand" "n")))
10163     (clobber (reg:CC CC_REGNUM))]
10164   "TARGET_ARM"
10165   "*
10166     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10167     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10168     return \"mvnne\\t%0, #0\";
10169   "
10170   [(set_attr "conds" "clob")
10171    (set_attr "length" "8")]
10172 )
10173
10174 (define_insn "*not_signextract_onebit"
10175   [(set (match_operand:SI 0 "s_register_operand" "=r")
10176         (not:SI
10177          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10178                           (const_int 1)
10179                           (match_operand:SI 2 "const_int_operand" "n"))))
10180    (clobber (reg:CC CC_REGNUM))]
10181   "TARGET_ARM"
10182   "*
10183     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10184     output_asm_insn (\"tst\\t%1, %2\", operands);
10185     output_asm_insn (\"mvneq\\t%0, #0\", operands);
10186     return \"movne\\t%0, #0\";
10187   "
10188   [(set_attr "conds" "clob")
10189    (set_attr "length" "12")]
10190 )
10191
10192 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
10193 ;; expressions.  For simplicity, the first register is also in the unspec
10194 ;; part.
10195 (define_insn "*push_multi"
10196   [(match_parallel 2 "multi_register_push"
10197     [(set (match_operand:BLK 0 "memory_operand" "=m")
10198           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
10199                       UNSPEC_PUSH_MULT))])]
10200   "TARGET_ARM"
10201   "*
10202   {
10203     int num_saves = XVECLEN (operands[2], 0);
10204      
10205     /* For the StrongARM at least it is faster to
10206        use STR to store only a single register.  */
10207     if (num_saves == 1)
10208       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10209     else
10210       {
10211         int i;
10212         char pattern[100];
10213
10214         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10215
10216         for (i = 1; i < num_saves; i++)
10217           {
10218             strcat (pattern, \", %|\");
10219             strcat (pattern,
10220                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10221           }
10222
10223         strcat (pattern, \"}\");
10224         output_asm_insn (pattern, operands);
10225       }
10226
10227     return \"\";
10228   }"
10229   [(set_attr "type" "store4")]
10230 )
10231
10232 (define_insn "stack_tie"
10233   [(set (mem:BLK (scratch))
10234         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
10235                      (match_operand:SI 1 "s_register_operand" "r")]
10236                     UNSPEC_PRLG_STK))]
10237   ""
10238   ""
10239   [(set_attr "length" "0")]
10240 )
10241
10242 ;; Similarly for the floating point registers
10243 (define_insn "*push_fp_multi"
10244   [(match_parallel 2 "multi_register_push"
10245     [(set (match_operand:BLK 0 "memory_operand" "=m")
10246           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10247                       UNSPEC_PUSH_MULT))])]
10248   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
10249   "*
10250   {
10251     char pattern[100];
10252
10253     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10254     output_asm_insn (pattern, operands);
10255     return \"\";
10256   }"
10257   [(set_attr "type" "f_store")]
10258 )
10259
10260 ;; Special patterns for dealing with the constant pool
10261
10262 (define_insn "align_4"
10263   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10264   "TARGET_EITHER"
10265   "*
10266   assemble_align (32);
10267   return \"\";
10268   "
10269 )
10270
10271 (define_insn "align_8"
10272   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10273   "TARGET_EITHER"
10274   "*
10275   assemble_align (64);
10276   return \"\";
10277   "
10278 )
10279
10280 (define_insn "consttable_end"
10281   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10282   "TARGET_EITHER"
10283   "*
10284   making_const_table = FALSE;
10285   return \"\";
10286   "
10287 )
10288
10289 (define_insn "consttable_1"
10290   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10291   "TARGET_THUMB"
10292   "*
10293   making_const_table = TRUE;
10294   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10295   assemble_zeros (3);
10296   return \"\";
10297   "
10298   [(set_attr "length" "4")]
10299 )
10300
10301 (define_insn "consttable_2"
10302   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10303   "TARGET_THUMB"
10304   "*
10305   making_const_table = TRUE;
10306   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10307   assemble_zeros (2);
10308   return \"\";
10309   "
10310   [(set_attr "length" "4")]
10311 )
10312
10313 (define_insn "consttable_4"
10314   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10315   "TARGET_EITHER"
10316   "*
10317   {
10318     making_const_table = TRUE;
10319     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10320       {
10321       case MODE_FLOAT:
10322       {
10323         REAL_VALUE_TYPE r;
10324         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10325         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10326         break;
10327       }
10328       default:
10329         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
10330         break;
10331       }
10332     return \"\";
10333   }"
10334   [(set_attr "length" "4")]
10335 )
10336
10337 (define_insn "consttable_8"
10338   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10339   "TARGET_EITHER"
10340   "*
10341   {
10342     making_const_table = TRUE;
10343     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10344       {
10345        case MODE_FLOAT:
10346         {
10347           REAL_VALUE_TYPE r;
10348           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10349           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10350           break;
10351         }
10352       default:
10353         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10354         break;
10355       }
10356     return \"\";
10357   }"
10358   [(set_attr "length" "8")]
10359 )
10360
10361 ;; Miscellaneous Thumb patterns
10362
10363 (define_expand "tablejump"
10364   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10365               (use (label_ref (match_operand 1 "" "")))])]
10366   "TARGET_THUMB"
10367   "
10368   if (flag_pic)
10369     {
10370       /* Hopefully, CSE will eliminate this copy.  */
10371       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10372       rtx reg2 = gen_reg_rtx (SImode);
10373
10374       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10375       operands[0] = reg2;
10376     }
10377   "
10378 )
10379
10380 ;; NB never uses BX.
10381 (define_insn "*thumb_tablejump"
10382   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10383    (use (label_ref (match_operand 1 "" "")))]
10384   "TARGET_THUMB"
10385   "mov\\t%|pc, %0"
10386   [(set_attr "length" "2")]
10387 )
10388
10389 ;; V5 Instructions,
10390
10391 (define_insn "clzsi2"
10392   [(set (match_operand:SI 0 "s_register_operand" "=r")
10393         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10394   "TARGET_ARM && arm_arch5"
10395   "clz%?\\t%0, %1"
10396   [(set_attr "predicable" "yes")])
10397
10398 (define_expand "ffssi2"
10399   [(set (match_operand:SI 0 "s_register_operand" "")
10400         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10401   "TARGET_ARM && arm_arch5"
10402   "
10403   {
10404     rtx t1, t2, t3;
10405
10406     t1 = gen_reg_rtx (SImode);
10407     t2 = gen_reg_rtx (SImode);
10408     t3 = gen_reg_rtx (SImode);
10409
10410     emit_insn (gen_negsi2 (t1, operands[1]));
10411     emit_insn (gen_andsi3 (t2, operands[1], t1));
10412     emit_insn (gen_clzsi2 (t3, t2));
10413     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10414     DONE;
10415   }"
10416 )
10417
10418 (define_expand "ctzsi2"
10419   [(set (match_operand:SI 0 "s_register_operand" "")
10420         (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10421   "TARGET_ARM && arm_arch5"
10422   "
10423   {
10424     rtx t1, t2, t3;
10425
10426     t1 = gen_reg_rtx (SImode);
10427     t2 = gen_reg_rtx (SImode);
10428     t3 = gen_reg_rtx (SImode);
10429
10430     emit_insn (gen_negsi2 (t1, operands[1]));
10431     emit_insn (gen_andsi3 (t2, operands[1], t1));
10432     emit_insn (gen_clzsi2 (t3, t2));
10433     emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10434     DONE;
10435   }"
10436 )
10437
10438 ;; V5E instructions.
10439
10440 (define_insn "prefetch"
10441   [(prefetch (match_operand:SI 0 "address_operand" "p")
10442              (match_operand:SI 1 "" "")
10443              (match_operand:SI 2 "" ""))]
10444   "TARGET_ARM && arm_arch5e"
10445   "pld\\t%a0")
10446
10447 ;; General predication pattern
10448
10449 (define_cond_exec
10450   [(match_operator 0 "arm_comparison_operator"
10451     [(match_operand 1 "cc_register" "")
10452      (const_int 0)])]
10453   "TARGET_ARM"
10454   ""
10455 )
10456
10457 (define_insn "prologue_use"
10458   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10459   ""
10460   "%@ %0 needed for prologue"
10461 )
10462
10463
10464 ;; Patterns for exception handling
10465
10466 (define_expand "eh_return"
10467   [(use (match_operand 0 "general_operand" ""))]
10468   "TARGET_EITHER"
10469   "
10470   {
10471     if (TARGET_ARM)
10472       emit_insn (gen_arm_eh_return (operands[0]));
10473     else
10474       emit_insn (gen_thumb_eh_return (operands[0]));
10475     DONE;
10476   }"
10477 )
10478                                    
10479 ;; We can't expand this before we know where the link register is stored.
10480 (define_insn_and_split "arm_eh_return"
10481   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10482                     VUNSPEC_EH_RETURN)
10483    (clobber (match_scratch:SI 1 "=&r"))]
10484   "TARGET_ARM"
10485   "#"
10486   "&& reload_completed"
10487   [(const_int 0)]
10488   "
10489   {
10490     arm_set_return_address (operands[0], operands[1]);
10491     DONE;
10492   }"
10493 )
10494
10495 (define_insn_and_split "thumb_eh_return"
10496   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10497                     VUNSPEC_EH_RETURN)
10498    (clobber (match_scratch:SI 1 "=&l"))]
10499   "TARGET_THUMB"
10500   "#"
10501   "&& reload_completed"
10502   [(const_int 0)]
10503   "
10504   {
10505     thumb_set_return_address (operands[0], operands[1]);
10506     DONE;
10507   }"
10508 )
10509
10510 ;; Load the FPA co-processor patterns
10511 (include "fpa.md")
10512 ;; Load the Maverick co-processor patterns
10513 (include "cirrus.md")
10514 ;; Load the Intel Wireless Multimedia Extension patterns
10515 (include "iwmmxt.md")
10516 ;; Load the VFP co-processor patterns
10517 (include "vfp.md")
10518