OSDN Git Service

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