OSDN Git Service

* config/arm/arm.c (pic_labelno): New.
[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    (UNSPEC_PIC_LABEL 21) ; A label used for PIC access that does not appear in the
95                          ; instruction stream.
96   ]
97 )
98
99 ;; UNSPEC_VOLATILE Usage:
100
101 (define_constants
102   [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
103                         ;   insn in the code.
104    (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
105                         ;   instruction epilogue sequence that isn't expanded
106                         ;   into normal RTL.  Used for both normal and sibcall
107                         ;   epilogues.
108    (VUNSPEC_ALIGN    2) ; `align' insn.  Used at the head of a minipool table 
109                         ;   for inlined constants.
110    (VUNSPEC_POOL_END 3) ; `end-of-table'.  Used to mark the end of a minipool
111                         ;   table.
112    (VUNSPEC_POOL_1   4) ; `pool-entry(1)'.  An entry in the constant pool for
113                         ;   an 8-bit object.
114    (VUNSPEC_POOL_2   5) ; `pool-entry(2)'.  An entry in the constant pool for
115                         ;   a 16-bit object.
116    (VUNSPEC_POOL_4   6) ; `pool-entry(4)'.  An entry in the constant pool for
117                         ;   a 32-bit object.
118    (VUNSPEC_POOL_8   7) ; `pool-entry(8)'.  An entry in the constant pool for
119                         ;   a 64-bit object.
120    (VUNSPEC_TMRC     8) ; Used by the iWMMXt TMRC instruction.
121    (VUNSPEC_TMCR     9) ; Used by the iWMMXt TMCR instruction.
122    (VUNSPEC_ALIGN8   10) ; 8-byte alignment version of VUNSPEC_ALIGN
123    (VUNSPEC_WCMP_EQ  11) ; Used by the iWMMXt WCMPEQ instructions
124    (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
125    (VUNSPEC_WCMP_GT  13) ; Used by the iwMMXT WCMPGT instructions
126    (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
127                          ; handling.
128   ]
129 )
130 \f
131 ;;---------------------------------------------------------------------------
132 ;; Attributes
133
134 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
135 ; generating ARM code.  This is used to control the length of some insn
136 ; patterns that share the same RTL in both ARM and Thumb code.
137 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
138
139 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
140 ; scheduling decisions for the load unit and the multiplier.
141 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_tune_strongarm")))
142
143 ; IS_XSCALE is set to 'yes' when compiling for XScale.
144 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
145
146 ;; Operand number of an input operand that is shifted.  Zero if the
147 ;; given instruction does not shift one of its input operands.
148 (define_attr "shift" "" (const_int 0))
149
150 ; Floating Point Unit.  If we only have floating point emulation, then there
151 ; is no point in scheduling the floating point insns.  (Well, for best
152 ; performance we should try and group them together).
153 (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
154   (const (symbol_ref "arm_fpu_attr")))
155
156 ; LENGTH of an instruction (in bytes)
157 (define_attr "length" "" (const_int 4))
158
159 ; POOL_RANGE is how far away from a constant pool entry that this insn
160 ; can be placed.  If the distance is zero, then this insn will never
161 ; reference the pool.
162 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
163 ; before its address.
164 (define_attr "pool_range" "" (const_int 0))
165 (define_attr "neg_pool_range" "" (const_int 0))
166
167 ; An assembler sequence may clobber the condition codes without us knowing.
168 ; If such an insn references the pool, then we have no way of knowing how,
169 ; so use the most conservative value for pool_range.
170 (define_asm_attributes
171  [(set_attr "conds" "clob")
172   (set_attr "length" "4")
173   (set_attr "pool_range" "250")])
174
175 ;; The instruction used to implement a particular pattern.  This
176 ;; information is used by pipeline descriptions to provide accurate
177 ;; scheduling information.
178
179 (define_attr "insn"
180         "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"
181         (const_string "other"))
182
183 ; TYPE attribute is used to detect floating point instructions which, if
184 ; running on a co-processor can run in parallel with other, basic instructions
185 ; If write-buffer scheduling is enabled then it can also be used in the
186 ; scheduling of writes.
187
188 ; Classification of each insn
189 ; alu           any alu  instruction that doesn't hit memory or fp
190 ;               regs or have a shifted source operand
191 ; alu_shift     any data instruction that doesn't hit memory or fp
192 ;               regs, but has a source operand shifted by a constant
193 ; alu_shift_reg any data instruction that doesn't hit memory or fp
194 ;               regs, but has a source operand shifted by a register value
195 ; mult          a multiply instruction
196 ; block         blockage insn, this blocks all functional units
197 ; float         a floating point arithmetic operation (subject to expansion)
198 ; fdivd         DFmode floating point division
199 ; fdivs         SFmode floating point division
200 ; fmul          Floating point multiply
201 ; ffmul         Fast floating point multiply
202 ; farith        Floating point arithmetic (4 cycle)
203 ; ffarith       Fast floating point arithmetic (2 cycle)
204 ; float_em      a floating point arithmetic operation that is normally emulated
205 ;               even on a machine with an fpa.
206 ; f_load        a floating point load from memory
207 ; f_store       a floating point store to memory
208 ; f_load[sd]    single/double load from memory
209 ; f_store[sd]   single/double store to memory
210 ; f_flag        a transfer of co-processor flags to the CPSR
211 ; f_mem_r       a transfer of a floating point register to a real reg via mem
212 ; r_mem_f       the reverse of f_mem_r
213 ; f_2_r         fast transfer float to arm (no memory needed)
214 ; r_2_f         fast transfer arm to float
215 ; f_cvt         convert floating<->integral
216 ; branch        a branch
217 ; call          a subroutine call
218 ; load_byte     load byte(s) from memory to arm registers
219 ; load1         load 1 word from memory to arm registers
220 ; load2         load 2 words from memory to arm registers
221 ; load3         load 3 words from memory to arm registers
222 ; load4         load 4 words from memory to arm registers
223 ; store         store 1 word to memory from arm registers
224 ; store2        store 2 words
225 ; store3        store 3 words
226 ; store4        store 4 (or more) words
227 ;  Additions for Cirrus Maverick co-processor:
228 ; mav_farith    Floating point arithmetic (4 cycle)
229 ; mav_dmult     Double multiplies (7 cycle)
230 ;
231 (define_attr "type"
232         "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" 
233         (if_then_else 
234          (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
235          (const_string "mult")
236          (const_string "alu")))
237
238 ; Load scheduling, set from the arm_ld_sched variable
239 ; initialized by arm_override_options() 
240 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
241
242 ; condition codes: this one is used by final_prescan_insn to speed up
243 ; conditionalizing instructions.  It saves having to scan the rtl to see if
244 ; it uses or alters the condition codes.
245
246 ; USE means that the condition codes are used by the insn in the process of
247 ;   outputting code, this means (at present) that we can't use the insn in
248 ;   inlined branches
249 ;
250 ; SET means that the purpose of the insn is to set the condition codes in a
251 ;   well defined manner.
252 ;
253 ; CLOB means that the condition codes are altered in an undefined manner, if
254 ;   they are altered at all
255 ;
256 ; JUMP_CLOB is used when the condition cannot be represented by a single
257 ;   instruction (UNEQ and LTGT).  These cannot be predicated.
258 ;
259 ; NOCOND means that the condition codes are neither altered nor affect the
260 ;   output of this insn
261
262 (define_attr "conds" "use,set,clob,jump_clob,nocond"
263         (if_then_else (eq_attr "type" "call")
264          (const_string "clob")
265          (const_string "nocond")))
266
267 ; Predicable means that the insn can be conditionally executed based on
268 ; an automatically added predicate (additional patterns are generated by 
269 ; gen...).  We default to 'no' because no Thumb patterns match this rule
270 ; and not all ARM patterns do.
271 (define_attr "predicable" "no,yes" (const_string "no"))
272
273 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
274 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
275 ; suffer blockages enough to warrant modelling this (and it can adversely
276 ; affect the schedule).
277 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
278
279 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
280 ; to stall the processor.  Used with model_wbuf above.
281 (define_attr "write_conflict" "no,yes"
282   (if_then_else (eq_attr "type"
283                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
284                 (const_string "yes")
285                 (const_string "no")))
286
287 ; Classify the insns into those that take one cycle and those that take more
288 ; than one on the main cpu execution unit.
289 (define_attr "core_cycles" "single,multi"
290   (if_then_else (eq_attr "type"
291                  "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
292                 (const_string "single")
293                 (const_string "multi")))
294
295 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
296 ;; distant label.  Only applicable to Thumb code.
297 (define_attr "far_jump" "yes,no" (const_string "no"))
298
299
300 ;;---------------------------------------------------------------------------
301 ;; Mode macros
302
303 ; A list of modes that are exactly 64 bits in size.  We use this to expand
304 ; some splits that are the same for all modes when operating on ARM 
305 ; registers.
306 (define_mode_macro ANY64 [DI DF V8QI V4HI V2SI V2SF])
307
308 ;;---------------------------------------------------------------------------
309 ;; Predicates
310
311 (include "predicates.md")
312
313 ;;---------------------------------------------------------------------------
314 ;; Pipeline descriptions
315
316 ;; Processor type.  This is created automatically from arm-cores.def.
317 (include "arm-tune.md")
318
319 ;; True if the generic scheduling description should be used.
320
321 (define_attr "generic_sched" "yes,no"
322   (const (if_then_else 
323           (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs") 
324           (const_string "no")
325           (const_string "yes"))))
326
327 (define_attr "generic_vfp" "yes,no"
328   (const (if_then_else
329           (and (eq_attr "fpu" "vfp")
330                (eq_attr "tune" "!arm1020e,arm1022e"))
331           (const_string "yes")
332           (const_string "no"))))
333
334 (include "arm-generic.md")
335 (include "arm926ejs.md")
336 (include "arm1020e.md")
337 (include "arm1026ejs.md")
338 (include "arm1136jfs.md")
339
340 \f
341 ;;---------------------------------------------------------------------------
342 ;; Insn patterns
343 ;;
344 ;; Addition insns.
345
346 ;; Note: For DImode insns, there is normally no reason why operands should
347 ;; not be in the same register, what we don't want is for something being
348 ;; written to partially overlap something that is an input.
349 ;; Cirrus 64bit additions should not be split because we have a native
350 ;; 64bit addition instructions.
351
352 (define_expand "adddi3"
353  [(parallel
354    [(set (match_operand:DI           0 "s_register_operand" "")
355           (plus:DI (match_operand:DI 1 "s_register_operand" "")
356                    (match_operand:DI 2 "s_register_operand" "")))
357     (clobber (reg:CC CC_REGNUM))])]
358   "TARGET_EITHER"
359   "
360   if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
361     {
362       if (!cirrus_fp_register (operands[0], DImode))
363         operands[0] = force_reg (DImode, operands[0]);
364       if (!cirrus_fp_register (operands[1], DImode))
365         operands[1] = force_reg (DImode, operands[1]);
366       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
367       DONE;
368     }
369
370   if (TARGET_THUMB)
371     {
372       if (GET_CODE (operands[1]) != REG)
373         operands[1] = force_reg (SImode, operands[1]);
374       if (GET_CODE (operands[2]) != REG)
375         operands[2] = force_reg (SImode, operands[2]);
376      }
377   "
378 )
379
380 (define_insn "*thumb_adddi3"
381   [(set (match_operand:DI          0 "register_operand" "=l")
382         (plus:DI (match_operand:DI 1 "register_operand" "%0")
383                  (match_operand:DI 2 "register_operand" "l")))
384    (clobber (reg:CC CC_REGNUM))
385   ]
386   "TARGET_THUMB"
387   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
388   [(set_attr "length" "4")]
389 )
390
391 (define_insn_and_split "*arm_adddi3"
392   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
393         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
394                  (match_operand:DI 2 "s_register_operand" "r,  0")))
395    (clobber (reg:CC CC_REGNUM))]
396   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
397   "#"
398   "TARGET_ARM && reload_completed"
399   [(parallel [(set (reg:CC_C CC_REGNUM)
400                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
401                                  (match_dup 1)))
402               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
403    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
404                                (plus:SI (match_dup 4) (match_dup 5))))]
405   "
406   {
407     operands[3] = gen_highpart (SImode, operands[0]);
408     operands[0] = gen_lowpart (SImode, operands[0]);
409     operands[4] = gen_highpart (SImode, operands[1]);
410     operands[1] = gen_lowpart (SImode, operands[1]);
411     operands[5] = gen_highpart (SImode, operands[2]);
412     operands[2] = gen_lowpart (SImode, operands[2]);
413   }"
414   [(set_attr "conds" "clob")
415    (set_attr "length" "8")]
416 )
417
418 (define_insn_and_split "*adddi_sesidi_di"
419   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
420         (plus:DI (sign_extend:DI
421                   (match_operand:SI 2 "s_register_operand" "r,r"))
422                  (match_operand:DI 1 "s_register_operand" "r,0")))
423    (clobber (reg:CC CC_REGNUM))]
424   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
425   "#"
426   "TARGET_ARM && reload_completed"
427   [(parallel [(set (reg:CC_C CC_REGNUM)
428                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
429                                  (match_dup 1)))
430               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
431    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
432                                (plus:SI (ashiftrt:SI (match_dup 2)
433                                                      (const_int 31))
434                                         (match_dup 4))))]
435   "
436   {
437     operands[3] = gen_highpart (SImode, operands[0]);
438     operands[0] = gen_lowpart (SImode, operands[0]);
439     operands[4] = gen_highpart (SImode, operands[1]);
440     operands[1] = gen_lowpart (SImode, operands[1]);
441     operands[2] = gen_lowpart (SImode, operands[2]);
442   }"
443   [(set_attr "conds" "clob")
444    (set_attr "length" "8")]
445 )
446
447 (define_insn_and_split "*adddi_zesidi_di"
448   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
449         (plus:DI (zero_extend:DI
450                   (match_operand:SI 2 "s_register_operand" "r,r"))
451                  (match_operand:DI 1 "s_register_operand" "r,0")))
452    (clobber (reg:CC CC_REGNUM))]
453   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
454   "#"
455   "TARGET_ARM && reload_completed"
456   [(parallel [(set (reg:CC_C CC_REGNUM)
457                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
458                                  (match_dup 1)))
459               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
460    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
461                                (plus:SI (match_dup 4) (const_int 0))))]
462   "
463   {
464     operands[3] = gen_highpart (SImode, operands[0]);
465     operands[0] = gen_lowpart (SImode, operands[0]);
466     operands[4] = gen_highpart (SImode, operands[1]);
467     operands[1] = gen_lowpart (SImode, operands[1]);
468     operands[2] = gen_lowpart (SImode, operands[2]);
469   }"
470   [(set_attr "conds" "clob")
471    (set_attr "length" "8")]
472 )
473
474 (define_expand "addsi3"
475   [(set (match_operand:SI          0 "s_register_operand" "")
476         (plus:SI (match_operand:SI 1 "s_register_operand" "")
477                  (match_operand:SI 2 "reg_or_int_operand" "")))]
478   "TARGET_EITHER"
479   "
480   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
481     {
482       arm_split_constant (PLUS, SImode, NULL_RTX,
483                           INTVAL (operands[2]), operands[0], operands[1],
484                           optimize && !no_new_pseudos);
485       DONE;
486     }
487   "
488 )
489
490 ; If there is a scratch available, this will be faster than synthesizing the
491 ; addition.
492 (define_peephole2
493   [(match_scratch:SI 3 "r")
494    (set (match_operand:SI          0 "arm_general_register_operand" "")
495         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
496                  (match_operand:SI 2 "const_int_operand"  "")))]
497   "TARGET_ARM &&
498    !(const_ok_for_arm (INTVAL (operands[2]))
499      || const_ok_for_arm (-INTVAL (operands[2])))
500     && const_ok_for_arm (~INTVAL (operands[2]))"
501   [(set (match_dup 3) (match_dup 2))
502    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
503   ""
504 )
505
506 (define_insn_and_split "*arm_addsi3"
507   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
508         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
509                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
510   "TARGET_ARM"
511   "@
512    add%?\\t%0, %1, %2
513    sub%?\\t%0, %1, #%n2
514    #"
515   "TARGET_ARM &&
516    GET_CODE (operands[2]) == CONST_INT
517    && !(const_ok_for_arm (INTVAL (operands[2]))
518         || const_ok_for_arm (-INTVAL (operands[2])))"
519   [(clobber (const_int 0))]
520   "
521   arm_split_constant (PLUS, SImode, curr_insn,
522                       INTVAL (operands[2]), operands[0],
523                       operands[1], 0);
524   DONE;
525   "
526   [(set_attr "length" "4,4,16")
527    (set_attr "predicable" "yes")]
528 )
529
530 ;; Register group 'k' is a single register group containing only the stack
531 ;; register.  Trying to reload it will always fail catastrophically,
532 ;; so never allow those alternatives to match if reloading is needed.
533
534 (define_insn "*thumb_addsi3"
535   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
536         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
537                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
538   "TARGET_THUMB"
539   "*
540    static const char * const asms[] = 
541    {
542      \"add\\t%0, %0, %2\",
543      \"sub\\t%0, %0, #%n2\",
544      \"add\\t%0, %1, %2\",
545      \"add\\t%0, %0, %2\",
546      \"add\\t%0, %0, %2\",
547      \"add\\t%0, %1, %2\",
548      \"add\\t%0, %1, %2\"
549    };
550    if ((which_alternative == 2 || which_alternative == 6)
551        && GET_CODE (operands[2]) == CONST_INT
552        && INTVAL (operands[2]) < 0)
553      return \"sub\\t%0, %1, #%n2\";
554    return asms[which_alternative];
555   "
556   [(set_attr "length" "2")]
557 )
558
559 ;; Reloading and elimination of the frame pointer can
560 ;; sometimes cause this optimization to be missed.
561 (define_peephole2
562   [(set (match_operand:SI 0 "arm_general_register_operand" "")
563         (match_operand:SI 1 "const_int_operand" ""))
564    (set (match_dup 0)
565         (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
566   "TARGET_THUMB
567    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
568    && (INTVAL (operands[1]) & 3) == 0"
569   [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
570   ""
571 )
572
573 (define_insn "*addsi3_compare0"
574   [(set (reg:CC_NOOV CC_REGNUM)
575         (compare:CC_NOOV
576          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
577                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
578          (const_int 0)))
579    (set (match_operand:SI 0 "s_register_operand" "=r,r")
580         (plus:SI (match_dup 1) (match_dup 2)))]
581   "TARGET_ARM"
582   "@
583    add%?s\\t%0, %1, %2
584    sub%?s\\t%0, %1, #%n2"
585   [(set_attr "conds" "set")]
586 )
587
588 (define_insn "*addsi3_compare0_scratch"
589   [(set (reg:CC_NOOV CC_REGNUM)
590         (compare:CC_NOOV
591          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
592                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
593          (const_int 0)))]
594   "TARGET_ARM"
595   "@
596    cmn%?\\t%0, %1
597    cmp%?\\t%0, #%n1"
598   [(set_attr "conds" "set")]
599 )
600
601 (define_insn "*compare_negsi_si"
602   [(set (reg:CC_Z CC_REGNUM)
603         (compare:CC_Z
604          (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
605          (match_operand:SI 1 "s_register_operand" "r")))]
606   "TARGET_ARM"
607   "cmn%?\\t%1, %0"
608   [(set_attr "conds" "set")]
609 )
610
611 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
612 ;; addend is a constant.
613 (define_insn "*cmpsi2_addneg"
614   [(set (reg:CC CC_REGNUM)
615         (compare:CC
616          (match_operand:SI 1 "s_register_operand" "r,r")
617          (match_operand:SI 2 "arm_addimm_operand" "I,L")))
618    (set (match_operand:SI 0 "s_register_operand" "=r,r")
619         (plus:SI (match_dup 1)
620                  (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
621   "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
622   "@
623    sub%?s\\t%0, %1, %2
624    add%?s\\t%0, %1, #%n2"
625   [(set_attr "conds" "set")]
626 )
627
628 ;; Convert the sequence
629 ;;  sub  rd, rn, #1
630 ;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
631 ;;  bne  dest
632 ;; into
633 ;;  subs rd, rn, #1
634 ;;  bcs  dest   ((unsigned)rn >= 1)
635 ;; similarly for the beq variant using bcc.
636 ;; This is a common looping idiom (while (n--))
637 (define_peephole2
638   [(set (match_operand:SI 0 "arm_general_register_operand" "")
639         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
640                  (const_int -1)))
641    (set (match_operand 2 "cc_register" "")
642         (compare (match_dup 0) (const_int -1)))
643    (set (pc)
644         (if_then_else (match_operator 3 "equality_operator"
645                        [(match_dup 2) (const_int 0)])
646                       (match_operand 4 "" "")
647                       (match_operand 5 "" "")))]
648   "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
649   [(parallel[
650     (set (match_dup 2)
651          (compare:CC
652           (match_dup 1) (const_int 1)))
653     (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
654    (set (pc)
655         (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
656                       (match_dup 4)
657                       (match_dup 5)))]
658   "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
659    operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
660                                   ? GEU : LTU),
661                                  VOIDmode, 
662                                  operands[2], const0_rtx);"
663 )
664
665 ;; The next four insns work because they compare the result with one of
666 ;; the operands, and we know that the use of the condition code is
667 ;; either GEU or LTU, so we can use the carry flag from the addition
668 ;; instead of doing the compare a second time.
669 (define_insn "*addsi3_compare_op1"
670   [(set (reg:CC_C CC_REGNUM)
671         (compare:CC_C
672          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
673                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
674          (match_dup 1)))
675    (set (match_operand:SI 0 "s_register_operand" "=r,r")
676         (plus:SI (match_dup 1) (match_dup 2)))]
677   "TARGET_ARM"
678   "@
679    add%?s\\t%0, %1, %2
680    sub%?s\\t%0, %1, #%n2"
681   [(set_attr "conds" "set")]
682 )
683
684 (define_insn "*addsi3_compare_op2"
685   [(set (reg:CC_C CC_REGNUM)
686         (compare:CC_C
687          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
688                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
689          (match_dup 2)))
690    (set (match_operand:SI 0 "s_register_operand" "=r,r")
691         (plus:SI (match_dup 1) (match_dup 2)))]
692   "TARGET_ARM"
693   "@
694    add%?s\\t%0, %1, %2
695    sub%?s\\t%0, %1, #%n2"
696   [(set_attr "conds" "set")]
697 )
698
699 (define_insn "*compare_addsi2_op0"
700   [(set (reg:CC_C CC_REGNUM)
701         (compare:CC_C
702          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
703                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
704          (match_dup 0)))]
705   "TARGET_ARM"
706   "@
707    cmn%?\\t%0, %1
708    cmp%?\\t%0, #%n1"
709   [(set_attr "conds" "set")]
710 )
711
712 (define_insn "*compare_addsi2_op1"
713   [(set (reg:CC_C CC_REGNUM)
714         (compare:CC_C
715          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
716                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
717          (match_dup 1)))]
718   "TARGET_ARM"
719   "@
720    cmn%?\\t%0, %1
721    cmp%?\\t%0, #%n1"
722   [(set_attr "conds" "set")]
723 )
724
725 (define_insn "*addsi3_carryin"
726   [(set (match_operand:SI 0 "s_register_operand" "=r")
727         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
728                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
729                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
730   "TARGET_ARM"
731   "adc%?\\t%0, %1, %2"
732   [(set_attr "conds" "use")]
733 )
734
735 (define_insn "*addsi3_carryin_shift"
736   [(set (match_operand:SI 0 "s_register_operand" "=r")
737         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
738                  (plus:SI
739                    (match_operator:SI 2 "shift_operator"
740                       [(match_operand:SI 3 "s_register_operand" "r")
741                        (match_operand:SI 4 "reg_or_int_operand" "rM")])
742                     (match_operand:SI 1 "s_register_operand" "r"))))]
743   "TARGET_ARM"
744   "adc%?\\t%0, %1, %3%S2"
745   [(set_attr "conds" "use")
746    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
747                       (const_string "alu_shift")
748                       (const_string "alu_shift_reg")))]
749 )
750
751 (define_insn "*addsi3_carryin_alt1"
752   [(set (match_operand:SI 0 "s_register_operand" "=r")
753         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
754                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
755                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
756   "TARGET_ARM"
757   "adc%?\\t%0, %1, %2"
758   [(set_attr "conds" "use")]
759 )
760
761 (define_insn "*addsi3_carryin_alt2"
762   [(set (match_operand:SI 0 "s_register_operand" "=r")
763         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
764                           (match_operand:SI 1 "s_register_operand" "r"))
765                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
766   "TARGET_ARM"
767   "adc%?\\t%0, %1, %2"
768   [(set_attr "conds" "use")]
769 )
770
771 (define_insn "*addsi3_carryin_alt3"
772   [(set (match_operand:SI 0 "s_register_operand" "=r")
773         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
774                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
775                  (match_operand:SI 1 "s_register_operand" "r")))]
776   "TARGET_ARM"
777   "adc%?\\t%0, %1, %2"
778   [(set_attr "conds" "use")]
779 )
780
781 (define_insn "incscc"
782   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
783         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
784                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
785                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
786   "TARGET_ARM"
787   "@
788   add%d2\\t%0, %1, #1
789   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
790   [(set_attr "conds" "use")
791    (set_attr "length" "4,8")]
792 )
793
794 ; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
795 (define_split
796   [(set (match_operand:SI 0 "s_register_operand" "")
797         (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
798                             (match_operand:SI 2 "s_register_operand" ""))
799                  (const_int -1)))
800    (clobber (match_operand:SI 3 "s_register_operand" ""))]
801   "TARGET_ARM"
802   [(set (match_dup 3) (match_dup 1))
803    (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
804   "
805   operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
806 ")
807
808 (define_expand "addsf3"
809   [(set (match_operand:SF          0 "s_register_operand" "")
810         (plus:SF (match_operand:SF 1 "s_register_operand" "")
811                  (match_operand:SF 2 "arm_float_add_operand" "")))]
812   "TARGET_ARM && TARGET_HARD_FLOAT"
813   "
814   if (TARGET_MAVERICK
815       && !cirrus_fp_register (operands[2], SFmode))
816     operands[2] = force_reg (SFmode, operands[2]);
817 ")
818
819 (define_expand "adddf3"
820   [(set (match_operand:DF          0 "s_register_operand" "")
821         (plus:DF (match_operand:DF 1 "s_register_operand" "")
822                  (match_operand:DF 2 "arm_float_add_operand" "")))]
823   "TARGET_ARM && TARGET_HARD_FLOAT"
824   "
825   if (TARGET_MAVERICK
826       && !cirrus_fp_register (operands[2], DFmode))
827     operands[2] = force_reg (DFmode, operands[2]);
828 ")
829
830 (define_expand "subdi3"
831  [(parallel
832    [(set (match_operand:DI            0 "s_register_operand" "")
833           (minus:DI (match_operand:DI 1 "s_register_operand" "")
834                     (match_operand:DI 2 "s_register_operand" "")))
835     (clobber (reg:CC CC_REGNUM))])]
836   "TARGET_EITHER"
837   "
838   if (TARGET_HARD_FLOAT && TARGET_MAVERICK
839       && TARGET_ARM
840       && cirrus_fp_register (operands[0], DImode)
841       && cirrus_fp_register (operands[1], DImode))
842     {
843       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
844       DONE;
845     }
846
847   if (TARGET_THUMB)
848     {
849       if (GET_CODE (operands[1]) != REG)
850         operands[1] = force_reg (SImode, operands[1]);
851       if (GET_CODE (operands[2]) != REG)
852         operands[2] = force_reg (SImode, operands[2]);
853      }  
854   "
855 )
856
857 (define_insn "*arm_subdi3"
858   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
859         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
860                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
861    (clobber (reg:CC CC_REGNUM))]
862   "TARGET_ARM"
863   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
864   [(set_attr "conds" "clob")
865    (set_attr "length" "8")]
866 )
867
868 (define_insn "*thumb_subdi3"
869   [(set (match_operand:DI           0 "register_operand" "=l")
870         (minus:DI (match_operand:DI 1 "register_operand"  "0")
871                   (match_operand:DI 2 "register_operand"  "l")))
872    (clobber (reg:CC CC_REGNUM))]
873   "TARGET_THUMB"
874   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
875   [(set_attr "length" "4")]
876 )
877
878 (define_insn "*subdi_di_zesidi"
879   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
880         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
881                   (zero_extend:DI
882                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
883    (clobber (reg:CC CC_REGNUM))]
884   "TARGET_ARM"
885   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
886   [(set_attr "conds" "clob")
887    (set_attr "length" "8")]
888 )
889
890 (define_insn "*subdi_di_sesidi"
891   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
892         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
893                   (sign_extend:DI
894                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
895    (clobber (reg:CC CC_REGNUM))]
896   "TARGET_ARM"
897   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
898   [(set_attr "conds" "clob")
899    (set_attr "length" "8")]
900 )
901
902 (define_insn "*subdi_zesidi_di"
903   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
904         (minus:DI (zero_extend:DI
905                    (match_operand:SI 2 "s_register_operand"  "r,r"))
906                   (match_operand:DI  1 "s_register_operand" "?r,0")))
907    (clobber (reg:CC CC_REGNUM))]
908   "TARGET_ARM"
909   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
910   [(set_attr "conds" "clob")
911    (set_attr "length" "8")]
912 )
913
914 (define_insn "*subdi_sesidi_di"
915   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
916         (minus:DI (sign_extend:DI
917                    (match_operand:SI 2 "s_register_operand"   "r,r"))
918                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
919    (clobber (reg:CC CC_REGNUM))]
920   "TARGET_ARM"
921   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
922   [(set_attr "conds" "clob")
923    (set_attr "length" "8")]
924 )
925
926 (define_insn "*subdi_zesidi_zesidi"
927   [(set (match_operand:DI            0 "s_register_operand" "=r")
928         (minus:DI (zero_extend:DI
929                    (match_operand:SI 1 "s_register_operand"  "r"))
930                   (zero_extend:DI
931                    (match_operand:SI 2 "s_register_operand"  "r"))))
932    (clobber (reg:CC CC_REGNUM))]
933   "TARGET_ARM"
934   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
935   [(set_attr "conds" "clob")
936    (set_attr "length" "8")]
937 )
938
939 (define_expand "subsi3"
940   [(set (match_operand:SI           0 "s_register_operand" "")
941         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
942                   (match_operand:SI 2 "s_register_operand" "")))]
943   "TARGET_EITHER"
944   "
945   if (GET_CODE (operands[1]) == CONST_INT)
946     {
947       if (TARGET_ARM)
948         {
949           arm_split_constant (MINUS, SImode, NULL_RTX,
950                               INTVAL (operands[1]), operands[0],
951                               operands[2], optimize && !no_new_pseudos);
952           DONE;
953         }
954       else /* TARGET_THUMB */
955         operands[1] = force_reg (SImode, operands[1]);
956     }
957   "
958 )
959
960 (define_insn "*thumb_subsi3_insn"
961   [(set (match_operand:SI           0 "register_operand" "=l")
962         (minus:SI (match_operand:SI 1 "register_operand" "l")
963                   (match_operand:SI 2 "register_operand" "l")))]
964   "TARGET_THUMB"
965   "sub\\t%0, %1, %2"
966   [(set_attr "length" "2")]
967 )
968
969 (define_insn_and_split "*arm_subsi3_insn"
970   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
971         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
972                   (match_operand:SI 2 "s_register_operand" "r,r")))]
973   "TARGET_ARM"
974   "@
975    rsb%?\\t%0, %2, %1
976    #"
977   "TARGET_ARM
978    && GET_CODE (operands[1]) == CONST_INT
979    && !const_ok_for_arm (INTVAL (operands[1]))"
980   [(clobber (const_int 0))]
981   "
982   arm_split_constant (MINUS, SImode, curr_insn,
983                       INTVAL (operands[1]), operands[0], operands[2], 0);
984   DONE;
985   "
986   [(set_attr "length" "4,16")
987    (set_attr "predicable" "yes")]
988 )
989
990 (define_peephole2
991   [(match_scratch:SI 3 "r")
992    (set (match_operand:SI 0 "arm_general_register_operand" "")
993         (minus:SI (match_operand:SI 1 "const_int_operand" "")
994                   (match_operand:SI 2 "arm_general_register_operand" "")))]
995   "TARGET_ARM
996    && !const_ok_for_arm (INTVAL (operands[1]))
997    && const_ok_for_arm (~INTVAL (operands[1]))"
998   [(set (match_dup 3) (match_dup 1))
999    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1000   ""
1001 )
1002
1003 (define_insn "*subsi3_compare0"
1004   [(set (reg:CC_NOOV CC_REGNUM)
1005         (compare:CC_NOOV
1006          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1007                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1008          (const_int 0)))
1009    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1010         (minus:SI (match_dup 1) (match_dup 2)))]
1011   "TARGET_ARM"
1012   "@
1013    sub%?s\\t%0, %1, %2
1014    rsb%?s\\t%0, %2, %1"
1015   [(set_attr "conds" "set")]
1016 )
1017
1018 (define_insn "decscc"
1019   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1020         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1021                   (match_operator:SI 2 "arm_comparison_operator"
1022                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1023   "TARGET_ARM"
1024   "@
1025    sub%d2\\t%0, %1, #1
1026    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1027   [(set_attr "conds" "use")
1028    (set_attr "length" "*,8")]
1029 )
1030
1031 (define_expand "subsf3"
1032   [(set (match_operand:SF           0 "s_register_operand" "")
1033         (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1034                   (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1035   "TARGET_ARM && TARGET_HARD_FLOAT"
1036   "
1037   if (TARGET_MAVERICK)
1038     {
1039       if (!cirrus_fp_register (operands[1], SFmode))
1040         operands[1] = force_reg (SFmode, operands[1]);
1041       if (!cirrus_fp_register (operands[2], SFmode))
1042         operands[2] = force_reg (SFmode, operands[2]);
1043     }
1044 ")
1045
1046 (define_expand "subdf3"
1047   [(set (match_operand:DF           0 "s_register_operand" "")
1048         (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1049                   (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1050   "TARGET_ARM && TARGET_HARD_FLOAT"
1051   "
1052   if (TARGET_MAVERICK)
1053     {
1054        if (!cirrus_fp_register (operands[1], DFmode))
1055          operands[1] = force_reg (DFmode, operands[1]);
1056        if (!cirrus_fp_register (operands[2], DFmode))
1057          operands[2] = force_reg (DFmode, operands[2]);
1058     }
1059 ")
1060
1061 \f
1062 ;; Multiplication insns
1063
1064 (define_expand "mulsi3"
1065   [(set (match_operand:SI          0 "s_register_operand" "")
1066         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1067                  (match_operand:SI 1 "s_register_operand" "")))]
1068   "TARGET_EITHER"
1069   ""
1070 )
1071
1072 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1073 (define_insn "*arm_mulsi3"
1074   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1075         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1076                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1077   "TARGET_ARM"
1078   "mul%?\\t%0, %2, %1"
1079   [(set_attr "insn" "mul")
1080    (set_attr "predicable" "yes")]
1081 )
1082
1083 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1084 ; 1 and 2; are the same, because reload will make operand 0 match 
1085 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1086 ; this by adding another alternative to match this case, and then `reload' 
1087 ; it ourselves.  This alternative must come first.
1088 (define_insn "*thumb_mulsi3"
1089   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1090         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1091                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1092   "TARGET_THUMB"
1093   "*
1094   if (which_alternative < 2)
1095     return \"mov\\t%0, %1\;mul\\t%0, %2\";
1096   else
1097     return \"mul\\t%0, %2\";
1098   "
1099   [(set_attr "length" "4,4,2")
1100    (set_attr "insn" "mul")]
1101 )
1102
1103 (define_insn "*mulsi3_compare0"
1104   [(set (reg:CC_NOOV CC_REGNUM)
1105         (compare:CC_NOOV (mult:SI
1106                           (match_operand:SI 2 "s_register_operand" "r,r")
1107                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1108                          (const_int 0)))
1109    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1110         (mult:SI (match_dup 2) (match_dup 1)))]
1111   "TARGET_ARM"
1112   "mul%?s\\t%0, %2, %1"
1113   [(set_attr "conds" "set")
1114    (set_attr "insn" "muls")]
1115 )
1116
1117 (define_insn "*mulsi_compare0_scratch"
1118   [(set (reg:CC_NOOV CC_REGNUM)
1119         (compare:CC_NOOV (mult:SI
1120                           (match_operand:SI 2 "s_register_operand" "r,r")
1121                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1122                          (const_int 0)))
1123    (clobber (match_scratch:SI 0 "=&r,&r"))]
1124   "TARGET_ARM"
1125   "mul%?s\\t%0, %2, %1"
1126   [(set_attr "conds" "set")
1127    (set_attr "insn" "muls")]
1128 )
1129
1130 ;; Unnamed templates to match MLA instruction.
1131
1132 (define_insn "*mulsi3addsi"
1133   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1134         (plus:SI
1135           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1136                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1137           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1138   "TARGET_ARM"
1139   "mla%?\\t%0, %2, %1, %3"
1140   [(set_attr "insn" "mla")
1141    (set_attr "predicable" "yes")]
1142 )
1143
1144 (define_insn "*mulsi3addsi_compare0"
1145   [(set (reg:CC_NOOV CC_REGNUM)
1146         (compare:CC_NOOV
1147          (plus:SI (mult:SI
1148                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1149                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1150                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1151          (const_int 0)))
1152    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1153         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1154                  (match_dup 3)))]
1155   "TARGET_ARM"
1156   "mla%?s\\t%0, %2, %1, %3"
1157   [(set_attr "conds" "set")
1158    (set_attr "insn" "mlas")]
1159 )
1160
1161 (define_insn "*mulsi3addsi_compare0_scratch"
1162   [(set (reg:CC_NOOV CC_REGNUM)
1163         (compare:CC_NOOV
1164          (plus:SI (mult:SI
1165                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1166                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1167                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1168          (const_int 0)))
1169    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1170   "TARGET_ARM"
1171   "mla%?s\\t%0, %2, %1, %3"
1172   [(set_attr "conds" "set")
1173    (set_attr "insn" "mlas")]
1174 )
1175
1176 ;; Unnamed template to match long long multiply-accumulate (smlal)
1177
1178 (define_insn "*mulsidi3adddi"
1179   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1180         (plus:DI
1181          (mult:DI
1182           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1183           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1184          (match_operand:DI 1 "s_register_operand" "0")))]
1185   "TARGET_ARM && arm_arch3m"
1186   "smlal%?\\t%Q0, %R0, %3, %2"
1187   [(set_attr "insn" "smlal")
1188    (set_attr "predicable" "yes")]
1189 )
1190
1191 (define_insn "mulsidi3"
1192   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1193         (mult:DI
1194          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1195          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1196   "TARGET_ARM && arm_arch3m"
1197   "smull%?\\t%Q0, %R0, %1, %2"
1198   [(set_attr "insn" "smull")
1199    (set_attr "predicable" "yes")]
1200 )
1201
1202 (define_insn "umulsidi3"
1203   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1204         (mult:DI
1205          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1206          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1207   "TARGET_ARM && arm_arch3m"
1208   "umull%?\\t%Q0, %R0, %1, %2"
1209   [(set_attr "insn" "umull")
1210    (set_attr "predicable" "yes")]
1211 )
1212
1213 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1214
1215 (define_insn "*umulsidi3adddi"
1216   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1217         (plus:DI
1218          (mult:DI
1219           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1220           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1221          (match_operand:DI 1 "s_register_operand" "0")))]
1222   "TARGET_ARM && arm_arch3m"
1223   "umlal%?\\t%Q0, %R0, %3, %2"
1224   [(set_attr "insn" "umlal")
1225    (set_attr "predicable" "yes")]
1226 )
1227
1228 (define_insn "smulsi3_highpart"
1229   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1230         (truncate:SI
1231          (lshiftrt:DI
1232           (mult:DI
1233            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1234            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1235           (const_int 32))))
1236    (clobber (match_scratch:SI 3 "=&r,&r"))]
1237   "TARGET_ARM && arm_arch3m"
1238   "smull%?\\t%3, %0, %2, %1"
1239   [(set_attr "insn" "smull")
1240    (set_attr "predicable" "yes")]
1241 )
1242
1243 (define_insn "umulsi3_highpart"
1244   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1245         (truncate:SI
1246          (lshiftrt:DI
1247           (mult:DI
1248            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1249            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1250           (const_int 32))))
1251    (clobber (match_scratch:SI 3 "=&r,&r"))]
1252   "TARGET_ARM && arm_arch3m"
1253   "umull%?\\t%3, %0, %2, %1"
1254   [(set_attr "insn" "umull")
1255    (set_attr "predicable" "yes")]
1256 )
1257
1258 (define_insn "mulhisi3"
1259   [(set (match_operand:SI 0 "s_register_operand" "=r")
1260         (mult:SI (sign_extend:SI
1261                   (match_operand:HI 1 "s_register_operand" "%r"))
1262                  (sign_extend:SI
1263                   (match_operand:HI 2 "s_register_operand" "r"))))]
1264   "TARGET_ARM && arm_arch5e"
1265   "smulbb%?\\t%0, %1, %2"
1266   [(set_attr "insn" "smulxy")
1267    (set_attr "predicable" "yes")]
1268 )
1269
1270 (define_insn "*mulhisi3tb"
1271   [(set (match_operand:SI 0 "s_register_operand" "=r")
1272         (mult:SI (ashiftrt:SI
1273                   (match_operand:SI 1 "s_register_operand" "r")
1274                   (const_int 16))
1275                  (sign_extend:SI
1276                   (match_operand:HI 2 "s_register_operand" "r"))))]
1277   "TARGET_ARM && arm_arch5e"
1278   "smultb%?\\t%0, %1, %2"
1279   [(set_attr "insn" "smulxy")
1280    (set_attr "predicable" "yes")]
1281 )
1282
1283 (define_insn "*mulhisi3bt"
1284   [(set (match_operand:SI 0 "s_register_operand" "=r")
1285         (mult:SI (sign_extend:SI
1286                   (match_operand:HI 1 "s_register_operand" "r"))
1287                  (ashiftrt:SI
1288                   (match_operand:SI 2 "s_register_operand" "r")
1289                   (const_int 16))))]
1290   "TARGET_ARM && arm_arch5e"
1291   "smulbt%?\\t%0, %1, %2"
1292   [(set_attr "insn" "smulxy")
1293    (set_attr "predicable" "yes")]
1294 )
1295
1296 (define_insn "*mulhisi3tt"
1297   [(set (match_operand:SI 0 "s_register_operand" "=r")
1298         (mult:SI (ashiftrt:SI
1299                   (match_operand:SI 1 "s_register_operand" "r")
1300                   (const_int 16))
1301                  (ashiftrt:SI
1302                   (match_operand:SI 2 "s_register_operand" "r")
1303                   (const_int 16))))]
1304   "TARGET_ARM && arm_arch5e"
1305   "smultt%?\\t%0, %1, %2"
1306   [(set_attr "insn" "smulxy")
1307    (set_attr "predicable" "yes")]
1308 )
1309
1310 (define_insn "*mulhisi3addsi"
1311   [(set (match_operand:SI 0 "s_register_operand" "=r")
1312         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1313                  (mult:SI (sign_extend:SI
1314                            (match_operand:HI 2 "s_register_operand" "%r"))
1315                           (sign_extend:SI
1316                            (match_operand:HI 3 "s_register_operand" "r")))))]
1317   "TARGET_ARM && arm_arch5e"
1318   "smlabb%?\\t%0, %2, %3, %1"
1319   [(set_attr "insn" "smlaxy")
1320    (set_attr "predicable" "yes")]
1321 )
1322
1323 (define_insn "*mulhidi3adddi"
1324   [(set (match_operand:DI 0 "s_register_operand" "=r")
1325         (plus:DI
1326           (match_operand:DI 1 "s_register_operand" "0")
1327           (mult:DI (sign_extend:DI
1328                     (match_operand:HI 2 "s_register_operand" "%r"))
1329                    (sign_extend:DI
1330                     (match_operand:HI 3 "s_register_operand" "r")))))]
1331   "TARGET_ARM && arm_arch5e"
1332   "smlalbb%?\\t%Q0, %R0, %2, %3"
1333   [(set_attr "insn" "smlalxy")
1334    (set_attr "predicable" "yes")])
1335
1336 (define_expand "mulsf3"
1337   [(set (match_operand:SF          0 "s_register_operand" "")
1338         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1339                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1340   "TARGET_ARM && TARGET_HARD_FLOAT"
1341   "
1342   if (TARGET_MAVERICK
1343       && !cirrus_fp_register (operands[2], SFmode))
1344     operands[2] = force_reg (SFmode, operands[2]);
1345 ")
1346
1347 (define_expand "muldf3"
1348   [(set (match_operand:DF          0 "s_register_operand" "")
1349         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1350                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1351   "TARGET_ARM && TARGET_HARD_FLOAT"
1352   "
1353   if (TARGET_MAVERICK
1354       && !cirrus_fp_register (operands[2], DFmode))
1355     operands[2] = force_reg (DFmode, operands[2]);
1356 ")
1357 \f
1358 ;; Division insns
1359
1360 (define_expand "divsf3"
1361   [(set (match_operand:SF 0 "s_register_operand" "")
1362         (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1363                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1364   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1365   "")
1366
1367 (define_expand "divdf3"
1368   [(set (match_operand:DF 0 "s_register_operand" "")
1369         (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1370                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1371   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1372   "")
1373 \f
1374 ;; Modulo insns
1375
1376 (define_expand "modsf3"
1377   [(set (match_operand:SF 0 "s_register_operand" "")
1378         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1379                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1380   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1381   "")
1382
1383 (define_expand "moddf3"
1384   [(set (match_operand:DF 0 "s_register_operand" "")
1385         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1386                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1387   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1388   "")
1389 \f
1390 ;; Boolean and,ior,xor insns
1391
1392 ;; Split up double word logical operations
1393
1394 ;; Split up simple DImode logical operations.  Simply perform the logical
1395 ;; operation on the upper and lower halves of the registers.
1396 (define_split
1397   [(set (match_operand:DI 0 "s_register_operand" "")
1398         (match_operator:DI 6 "logical_binary_operator"
1399           [(match_operand:DI 1 "s_register_operand" "")
1400            (match_operand:DI 2 "s_register_operand" "")]))]
1401   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1402   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1403    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1404   "
1405   {
1406     operands[3] = gen_highpart (SImode, operands[0]);
1407     operands[0] = gen_lowpart (SImode, operands[0]);
1408     operands[4] = gen_highpart (SImode, operands[1]);
1409     operands[1] = gen_lowpart (SImode, operands[1]);
1410     operands[5] = gen_highpart (SImode, operands[2]);
1411     operands[2] = gen_lowpart (SImode, operands[2]);
1412   }"
1413 )
1414
1415 (define_split
1416   [(set (match_operand:DI 0 "s_register_operand" "")
1417         (match_operator:DI 6 "logical_binary_operator"
1418           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1419            (match_operand:DI 1 "s_register_operand" "")]))]
1420   "TARGET_ARM && reload_completed"
1421   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1422    (set (match_dup 3) (match_op_dup:SI 6
1423                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1424                          (match_dup 4)]))]
1425   "
1426   {
1427     operands[3] = gen_highpart (SImode, operands[0]);
1428     operands[0] = gen_lowpart (SImode, operands[0]);
1429     operands[4] = gen_highpart (SImode, operands[1]);
1430     operands[1] = gen_lowpart (SImode, operands[1]);
1431     operands[5] = gen_highpart (SImode, operands[2]);
1432     operands[2] = gen_lowpart (SImode, operands[2]);
1433   }"
1434 )
1435
1436 ;; The zero extend of operand 2 means we can just copy the high part of
1437 ;; operand1 into operand0.
1438 (define_split
1439   [(set (match_operand:DI 0 "s_register_operand" "")
1440         (ior:DI
1441           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1442           (match_operand:DI 1 "s_register_operand" "")))]
1443   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1444   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1445    (set (match_dup 3) (match_dup 4))]
1446   "
1447   {
1448     operands[4] = gen_highpart (SImode, operands[1]);
1449     operands[3] = gen_highpart (SImode, operands[0]);
1450     operands[0] = gen_lowpart (SImode, operands[0]);
1451     operands[1] = gen_lowpart (SImode, operands[1]);
1452   }"
1453 )
1454
1455 ;; The zero extend of operand 2 means we can just copy the high part of
1456 ;; operand1 into operand0.
1457 (define_split
1458   [(set (match_operand:DI 0 "s_register_operand" "")
1459         (xor:DI
1460           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1461           (match_operand:DI 1 "s_register_operand" "")))]
1462   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1463   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1464    (set (match_dup 3) (match_dup 4))]
1465   "
1466   {
1467     operands[4] = gen_highpart (SImode, operands[1]);
1468     operands[3] = gen_highpart (SImode, operands[0]);
1469     operands[0] = gen_lowpart (SImode, operands[0]);
1470     operands[1] = gen_lowpart (SImode, operands[1]);
1471   }"
1472 )
1473
1474 (define_insn "anddi3"
1475   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1476         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1477                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1478   "TARGET_ARM && ! TARGET_IWMMXT"
1479   "#"
1480   [(set_attr "length" "8")]
1481 )
1482
1483 (define_insn_and_split "*anddi_zesidi_di"
1484   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1485         (and:DI (zero_extend:DI
1486                  (match_operand:SI 2 "s_register_operand" "r,r"))
1487                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1488   "TARGET_ARM"
1489   "#"
1490   "TARGET_ARM && reload_completed"
1491   ; The zero extend of operand 2 clears the high word of the output
1492   ; operand.
1493   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1494    (set (match_dup 3) (const_int 0))]
1495   "
1496   {
1497     operands[3] = gen_highpart (SImode, operands[0]);
1498     operands[0] = gen_lowpart (SImode, operands[0]);
1499     operands[1] = gen_lowpart (SImode, operands[1]);
1500   }"
1501   [(set_attr "length" "8")]
1502 )
1503
1504 (define_insn "*anddi_sesdi_di"
1505   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1506         (and:DI (sign_extend:DI
1507                  (match_operand:SI 2 "s_register_operand" "r,r"))
1508                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1509   "TARGET_ARM"
1510   "#"
1511   [(set_attr "length" "8")]
1512 )
1513
1514 (define_expand "andsi3"
1515   [(set (match_operand:SI         0 "s_register_operand" "")
1516         (and:SI (match_operand:SI 1 "s_register_operand" "")
1517                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1518   "TARGET_EITHER"
1519   "
1520   if (TARGET_ARM)
1521     {
1522       if (GET_CODE (operands[2]) == CONST_INT)
1523         {
1524           arm_split_constant (AND, SImode, NULL_RTX,
1525                               INTVAL (operands[2]), operands[0],
1526                               operands[1], optimize && !no_new_pseudos);
1527
1528           DONE;
1529         }
1530     }
1531   else /* TARGET_THUMB */
1532     {
1533       if (GET_CODE (operands[2]) != CONST_INT)
1534         operands[2] = force_reg (SImode, operands[2]);
1535       else
1536         {
1537           int i;
1538           
1539           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1540             {
1541               operands[2] = force_reg (SImode,
1542                                        GEN_INT (~INTVAL (operands[2])));
1543               
1544               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1545               
1546               DONE;
1547             }
1548
1549           for (i = 9; i <= 31; i++)
1550             {
1551               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1552                 {
1553                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1554                                         const0_rtx));
1555                   DONE;
1556                 }
1557               else if ((((HOST_WIDE_INT) 1) << i) - 1
1558                        == ~INTVAL (operands[2]))
1559                 {
1560                   rtx shift = GEN_INT (i);
1561                   rtx reg = gen_reg_rtx (SImode);
1562                 
1563                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1564                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1565                   
1566                   DONE;
1567                 }
1568             }
1569
1570           operands[2] = force_reg (SImode, operands[2]);
1571         }
1572     }
1573   "
1574 )
1575
1576 (define_insn_and_split "*arm_andsi3_insn"
1577   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1578         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1579                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1580   "TARGET_ARM"
1581   "@
1582    and%?\\t%0, %1, %2
1583    bic%?\\t%0, %1, #%B2
1584    #"
1585   "TARGET_ARM
1586    && GET_CODE (operands[2]) == CONST_INT
1587    && !(const_ok_for_arm (INTVAL (operands[2]))
1588         || const_ok_for_arm (~INTVAL (operands[2])))"
1589   [(clobber (const_int 0))]
1590   "
1591   arm_split_constant  (AND, SImode, curr_insn, 
1592                        INTVAL (operands[2]), operands[0], operands[1], 0);
1593   DONE;
1594   "
1595   [(set_attr "length" "4,4,16")
1596    (set_attr "predicable" "yes")]
1597 )
1598
1599 (define_insn "*thumb_andsi3_insn"
1600   [(set (match_operand:SI         0 "register_operand" "=l")
1601         (and:SI (match_operand:SI 1 "register_operand" "%0")
1602                 (match_operand:SI 2 "register_operand" "l")))]
1603   "TARGET_THUMB"
1604   "and\\t%0, %0, %2"
1605   [(set_attr "length" "2")]
1606 )
1607
1608 (define_insn "*andsi3_compare0"
1609   [(set (reg:CC_NOOV CC_REGNUM)
1610         (compare:CC_NOOV
1611          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1612                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1613          (const_int 0)))
1614    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1615         (and:SI (match_dup 1) (match_dup 2)))]
1616   "TARGET_ARM"
1617   "@
1618    and%?s\\t%0, %1, %2
1619    bic%?s\\t%0, %1, #%B2"
1620   [(set_attr "conds" "set")]
1621 )
1622
1623 (define_insn "*andsi3_compare0_scratch"
1624   [(set (reg:CC_NOOV CC_REGNUM)
1625         (compare:CC_NOOV
1626          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1627                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1628          (const_int 0)))
1629    (clobber (match_scratch:SI 2 "=X,r"))]
1630   "TARGET_ARM"
1631   "@
1632    tst%?\\t%0, %1
1633    bic%?s\\t%2, %0, #%B1"
1634   [(set_attr "conds" "set")]
1635 )
1636
1637 (define_insn "*zeroextractsi_compare0_scratch"
1638   [(set (reg:CC_NOOV CC_REGNUM)
1639         (compare:CC_NOOV (zero_extract:SI
1640                           (match_operand:SI 0 "s_register_operand" "r")
1641                           (match_operand 1 "const_int_operand" "n")
1642                           (match_operand 2 "const_int_operand" "n"))
1643                          (const_int 0)))]
1644   "TARGET_ARM
1645   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1646       && INTVAL (operands[1]) > 0 
1647       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1648       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1649   "*
1650   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1651                          << INTVAL (operands[2]));
1652   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1653   return \"\";
1654   "
1655   [(set_attr "conds" "set")]
1656 )
1657
1658 (define_insn_and_split "*ne_zeroextractsi"
1659   [(set (match_operand:SI 0 "s_register_operand" "=r")
1660         (ne:SI (zero_extract:SI
1661                 (match_operand:SI 1 "s_register_operand" "r")
1662                 (match_operand:SI 2 "const_int_operand" "n")
1663                 (match_operand:SI 3 "const_int_operand" "n"))
1664                (const_int 0)))
1665    (clobber (reg:CC CC_REGNUM))]
1666   "TARGET_ARM
1667    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1668        && INTVAL (operands[2]) > 0 
1669        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1670        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1671   "#"
1672   "TARGET_ARM
1673    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1674        && INTVAL (operands[2]) > 0 
1675        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1676        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1677   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1678                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1679                                     (const_int 0)))
1680               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1681    (set (match_dup 0)
1682         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1683                          (match_dup 0) (const_int 1)))]
1684   "
1685   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1686                          << INTVAL (operands[3])); 
1687   "
1688   [(set_attr "conds" "clob")
1689    (set_attr "length" "8")]
1690 )
1691
1692 (define_insn_and_split "*ne_zeroextractsi_shifted"
1693   [(set (match_operand:SI 0 "s_register_operand" "=r")
1694         (ne:SI (zero_extract:SI
1695                 (match_operand:SI 1 "s_register_operand" "r")
1696                 (match_operand:SI 2 "const_int_operand" "n")
1697                 (const_int 0))
1698                (const_int 0)))
1699    (clobber (reg:CC CC_REGNUM))]
1700   "TARGET_ARM"
1701   "#"
1702   "TARGET_ARM"
1703   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1704                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1705                                     (const_int 0)))
1706               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1707    (set (match_dup 0)
1708         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1709                          (match_dup 0) (const_int 1)))]
1710   "
1711   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1712   "
1713   [(set_attr "conds" "clob")
1714    (set_attr "length" "8")]
1715 )
1716
1717 (define_insn_and_split "*ite_ne_zeroextractsi"
1718   [(set (match_operand:SI 0 "s_register_operand" "=r")
1719         (if_then_else:SI (ne (zero_extract:SI
1720                               (match_operand:SI 1 "s_register_operand" "r")
1721                               (match_operand:SI 2 "const_int_operand" "n")
1722                               (match_operand:SI 3 "const_int_operand" "n"))
1723                              (const_int 0))
1724                          (match_operand:SI 4 "arm_not_operand" "rIK")
1725                          (const_int 0)))
1726    (clobber (reg:CC CC_REGNUM))]
1727   "TARGET_ARM
1728    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1729        && INTVAL (operands[2]) > 0 
1730        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1731        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1732    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1733   "#"
1734   "TARGET_ARM
1735    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1736        && INTVAL (operands[2]) > 0 
1737        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1738        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1739    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1740   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1741                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1742                                     (const_int 0)))
1743               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1744    (set (match_dup 0)
1745         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1746                          (match_dup 0) (match_dup 4)))]
1747   "
1748   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1749                          << INTVAL (operands[3])); 
1750   "
1751   [(set_attr "conds" "clob")
1752    (set_attr "length" "8")]
1753 )
1754
1755 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1756   [(set (match_operand:SI 0 "s_register_operand" "=r")
1757         (if_then_else:SI (ne (zero_extract:SI
1758                               (match_operand:SI 1 "s_register_operand" "r")
1759                               (match_operand:SI 2 "const_int_operand" "n")
1760                               (const_int 0))
1761                              (const_int 0))
1762                          (match_operand:SI 3 "arm_not_operand" "rIK")
1763                          (const_int 0)))
1764    (clobber (reg:CC CC_REGNUM))]
1765   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1766   "#"
1767   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1768   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1769                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1770                                     (const_int 0)))
1771               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1772    (set (match_dup 0)
1773         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1774                          (match_dup 0) (match_dup 3)))]
1775   "
1776   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1777   "
1778   [(set_attr "conds" "clob")
1779    (set_attr "length" "8")]
1780 )
1781
1782 (define_split
1783   [(set (match_operand:SI 0 "s_register_operand" "")
1784         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1785                          (match_operand:SI 2 "const_int_operand" "")
1786                          (match_operand:SI 3 "const_int_operand" "")))
1787    (clobber (match_operand:SI 4 "s_register_operand" ""))]
1788   "TARGET_THUMB"
1789   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1790    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1791   "{
1792      HOST_WIDE_INT temp = INTVAL (operands[2]);
1793
1794      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1795      operands[3] = GEN_INT (32 - temp);
1796    }"
1797 )
1798
1799 (define_split
1800   [(set (match_operand:SI 0 "s_register_operand" "")
1801         (match_operator:SI 1 "shiftable_operator"
1802          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1803                            (match_operand:SI 3 "const_int_operand" "")
1804                            (match_operand:SI 4 "const_int_operand" ""))
1805           (match_operand:SI 5 "s_register_operand" "")]))
1806    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1807   "TARGET_ARM"
1808   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1809    (set (match_dup 0)
1810         (match_op_dup 1
1811          [(lshiftrt:SI (match_dup 6) (match_dup 4))
1812           (match_dup 5)]))]
1813   "{
1814      HOST_WIDE_INT temp = INTVAL (operands[3]);
1815
1816      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1817      operands[4] = GEN_INT (32 - temp);
1818    }"
1819 )
1820   
1821 (define_split
1822   [(set (match_operand:SI 0 "s_register_operand" "")
1823         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1824                          (match_operand:SI 2 "const_int_operand" "")
1825                          (match_operand:SI 3 "const_int_operand" "")))]
1826   "TARGET_THUMB"
1827   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1828    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1829   "{
1830      HOST_WIDE_INT temp = INTVAL (operands[2]);
1831
1832      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1833      operands[3] = GEN_INT (32 - temp);
1834    }"
1835 )
1836
1837 (define_split
1838   [(set (match_operand:SI 0 "s_register_operand" "")
1839         (match_operator:SI 1 "shiftable_operator"
1840          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1841                            (match_operand:SI 3 "const_int_operand" "")
1842                            (match_operand:SI 4 "const_int_operand" ""))
1843           (match_operand:SI 5 "s_register_operand" "")]))
1844    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1845   "TARGET_ARM"
1846   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1847    (set (match_dup 0)
1848         (match_op_dup 1
1849          [(ashiftrt:SI (match_dup 6) (match_dup 4))
1850           (match_dup 5)]))]
1851   "{
1852      HOST_WIDE_INT temp = INTVAL (operands[3]);
1853
1854      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1855      operands[4] = GEN_INT (32 - temp);
1856    }"
1857 )
1858   
1859 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1860 ;;; represented by the bitfield, then this will produce incorrect results.
1861 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1862 ;;; which have a real bit-field insert instruction, the truncation happens
1863 ;;; in the bit-field insert instruction itself.  Since arm does not have a
1864 ;;; bit-field insert instruction, we would have to emit code here to truncate
1865 ;;; the value before we insert.  This loses some of the advantage of having
1866 ;;; this insv pattern, so this pattern needs to be reevalutated.
1867
1868 (define_expand "insv"
1869   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1870                          (match_operand:SI 1 "general_operand" "")
1871                          (match_operand:SI 2 "general_operand" ""))
1872         (match_operand:SI 3 "reg_or_int_operand" ""))]
1873   "TARGET_ARM"
1874   "
1875   {
1876     int start_bit = INTVAL (operands[2]);
1877     int width = INTVAL (operands[1]);
1878     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1879     rtx target, subtarget;
1880
1881     target = operands[0];
1882     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1883        subreg as the final target.  */
1884     if (GET_CODE (target) == SUBREG)
1885       {
1886         subtarget = gen_reg_rtx (SImode);
1887         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1888             < GET_MODE_SIZE (SImode))
1889           target = SUBREG_REG (target);
1890       }
1891     else
1892       subtarget = target;    
1893
1894     if (GET_CODE (operands[3]) == CONST_INT)
1895       {
1896         /* Since we are inserting a known constant, we may be able to
1897            reduce the number of bits that we have to clear so that
1898            the mask becomes simple.  */
1899         /* ??? This code does not check to see if the new mask is actually
1900            simpler.  It may not be.  */
1901         rtx op1 = gen_reg_rtx (SImode);
1902         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1903            start of this pattern.  */
1904         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1905         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1906
1907         emit_insn (gen_andsi3 (op1, operands[0],
1908                                gen_int_mode (~mask2, SImode)));
1909         emit_insn (gen_iorsi3 (subtarget, op1,
1910                                gen_int_mode (op3_value << start_bit, SImode)));
1911       }
1912     else if (start_bit == 0
1913              && !(const_ok_for_arm (mask)
1914                   || const_ok_for_arm (~mask)))
1915       {
1916         /* A Trick, since we are setting the bottom bits in the word,
1917            we can shift operand[3] up, operand[0] down, OR them together
1918            and rotate the result back again.  This takes 3 insns, and
1919            the third might be mergeable into another op.  */
1920         /* The shift up copes with the possibility that operand[3] is
1921            wider than the bitfield.  */
1922         rtx op0 = gen_reg_rtx (SImode);
1923         rtx op1 = gen_reg_rtx (SImode);
1924
1925         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1926         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1927         emit_insn (gen_iorsi3  (op1, op1, op0));
1928         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1929       }
1930     else if ((width + start_bit == 32)
1931              && !(const_ok_for_arm (mask)
1932                   || const_ok_for_arm (~mask)))
1933       {
1934         /* Similar trick, but slightly less efficient.  */
1935
1936         rtx op0 = gen_reg_rtx (SImode);
1937         rtx op1 = gen_reg_rtx (SImode);
1938
1939         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1940         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1941         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1942         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1943       }
1944     else
1945       {
1946         rtx op0 = gen_int_mode (mask, SImode);
1947         rtx op1 = gen_reg_rtx (SImode);
1948         rtx op2 = gen_reg_rtx (SImode);
1949
1950         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1951           {
1952             rtx tmp = gen_reg_rtx (SImode);
1953
1954             emit_insn (gen_movsi (tmp, op0));
1955             op0 = tmp;
1956           }
1957
1958         /* Mask out any bits in operand[3] that are not needed.  */
1959            emit_insn (gen_andsi3 (op1, operands[3], op0));
1960
1961         if (GET_CODE (op0) == CONST_INT
1962             && (const_ok_for_arm (mask << start_bit)
1963                 || const_ok_for_arm (~(mask << start_bit))))
1964           {
1965             op0 = gen_int_mode (~(mask << start_bit), SImode);
1966             emit_insn (gen_andsi3 (op2, operands[0], op0));
1967           }
1968         else
1969           {
1970             if (GET_CODE (op0) == CONST_INT)
1971               {
1972                 rtx tmp = gen_reg_rtx (SImode);
1973
1974                 emit_insn (gen_movsi (tmp, op0));
1975                 op0 = tmp;
1976               }
1977
1978             if (start_bit != 0)
1979               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1980             
1981             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1982           }
1983
1984         if (start_bit != 0)
1985           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1986
1987         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1988       }
1989
1990     if (subtarget != target)
1991       {
1992         /* If TARGET is still a SUBREG, then it must be wider than a word,
1993            so we must be careful only to set the subword we were asked to.  */
1994         if (GET_CODE (target) == SUBREG)
1995           emit_move_insn (target, subtarget);
1996         else
1997           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1998       }
1999
2000     DONE;
2001   }"
2002 )
2003
2004 ; constants for op 2 will never be given to these patterns.
2005 (define_insn_and_split "*anddi_notdi_di"
2006   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2007         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2008                 (match_operand:DI 2 "s_register_operand" "0,r")))]
2009   "TARGET_ARM"
2010   "#"
2011   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2012   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2013    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2014   "
2015   {
2016     operands[3] = gen_highpart (SImode, operands[0]);
2017     operands[0] = gen_lowpart (SImode, operands[0]);
2018     operands[4] = gen_highpart (SImode, operands[1]);
2019     operands[1] = gen_lowpart (SImode, operands[1]);
2020     operands[5] = gen_highpart (SImode, operands[2]);
2021     operands[2] = gen_lowpart (SImode, operands[2]);
2022   }"
2023   [(set_attr "length" "8")
2024    (set_attr "predicable" "yes")]
2025 )
2026   
2027 (define_insn_and_split "*anddi_notzesidi_di"
2028   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2029         (and:DI (not:DI (zero_extend:DI
2030                          (match_operand:SI 2 "s_register_operand" "r,r")))
2031                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2032   "TARGET_ARM"
2033   "@
2034    bic%?\\t%Q0, %Q1, %2
2035    #"
2036   ; (not (zero_extend ...)) allows us to just copy the high word from
2037   ; operand1 to operand0.
2038   "TARGET_ARM
2039    && reload_completed
2040    && operands[0] != operands[1]"
2041   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2042    (set (match_dup 3) (match_dup 4))]
2043   "
2044   {
2045     operands[3] = gen_highpart (SImode, operands[0]);
2046     operands[0] = gen_lowpart (SImode, operands[0]);
2047     operands[4] = gen_highpart (SImode, operands[1]);
2048     operands[1] = gen_lowpart (SImode, operands[1]);
2049   }"
2050   [(set_attr "length" "4,8")
2051    (set_attr "predicable" "yes")]
2052 )
2053   
2054 (define_insn_and_split "*anddi_notsesidi_di"
2055   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2056         (and:DI (not:DI (sign_extend:DI
2057                          (match_operand:SI 2 "s_register_operand" "r,r")))
2058                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2059   "TARGET_ARM"
2060   "#"
2061   "TARGET_ARM && reload_completed"
2062   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2063    (set (match_dup 3) (and:SI (not:SI
2064                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2065                                (match_dup 4)))]
2066   "
2067   {
2068     operands[3] = gen_highpart (SImode, operands[0]);
2069     operands[0] = gen_lowpart (SImode, operands[0]);
2070     operands[4] = gen_highpart (SImode, operands[1]);
2071     operands[1] = gen_lowpart (SImode, operands[1]);
2072   }"
2073   [(set_attr "length" "8")
2074    (set_attr "predicable" "yes")]
2075 )
2076   
2077 (define_insn "andsi_notsi_si"
2078   [(set (match_operand:SI 0 "s_register_operand" "=r")
2079         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2080                 (match_operand:SI 1 "s_register_operand" "r")))]
2081   "TARGET_ARM"
2082   "bic%?\\t%0, %1, %2"
2083   [(set_attr "predicable" "yes")]
2084 )
2085
2086 (define_insn "bicsi3"
2087   [(set (match_operand:SI                 0 "register_operand" "=l")
2088         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2089                 (match_operand:SI         2 "register_operand" "0")))]
2090   "TARGET_THUMB"
2091   "bic\\t%0, %0, %1"
2092   [(set_attr "length" "2")]
2093 )
2094
2095 (define_insn "andsi_not_shiftsi_si"
2096   [(set (match_operand:SI 0 "s_register_operand" "=r")
2097         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2098                          [(match_operand:SI 2 "s_register_operand" "r")
2099                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2100                 (match_operand:SI 1 "s_register_operand" "r")))]
2101   "TARGET_ARM"
2102   "bic%?\\t%0, %1, %2%S4"
2103   [(set_attr "predicable" "yes")
2104    (set_attr "shift" "2")
2105    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2106                       (const_string "alu_shift")
2107                       (const_string "alu_shift_reg")))]
2108 )
2109
2110 (define_insn "*andsi_notsi_si_compare0"
2111   [(set (reg:CC_NOOV CC_REGNUM)
2112         (compare:CC_NOOV
2113          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2114                  (match_operand:SI 1 "s_register_operand" "r"))
2115          (const_int 0)))
2116    (set (match_operand:SI 0 "s_register_operand" "=r")
2117         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2118   "TARGET_ARM"
2119   "bic%?s\\t%0, %1, %2"
2120   [(set_attr "conds" "set")]
2121 )
2122
2123 (define_insn "*andsi_notsi_si_compare0_scratch"
2124   [(set (reg:CC_NOOV CC_REGNUM)
2125         (compare:CC_NOOV
2126          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2127                  (match_operand:SI 1 "s_register_operand" "r"))
2128          (const_int 0)))
2129    (clobber (match_scratch:SI 0 "=r"))]
2130   "TARGET_ARM"
2131   "bic%?s\\t%0, %1, %2"
2132   [(set_attr "conds" "set")]
2133 )
2134
2135 (define_insn "iordi3"
2136   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2137         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2138                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2139   "TARGET_ARM && ! TARGET_IWMMXT"
2140   "#"
2141   [(set_attr "length" "8")
2142    (set_attr "predicable" "yes")]
2143 )
2144
2145 (define_insn "*iordi_zesidi_di"
2146   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2147         (ior:DI (zero_extend:DI
2148                  (match_operand:SI 2 "s_register_operand" "r,r"))
2149                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2150   "TARGET_ARM"
2151   "@
2152    orr%?\\t%Q0, %Q1, %2
2153    #"
2154   [(set_attr "length" "4,8")
2155    (set_attr "predicable" "yes")]
2156 )
2157
2158 (define_insn "*iordi_sesidi_di"
2159   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2160         (ior:DI (sign_extend:DI
2161                  (match_operand:SI 2 "s_register_operand" "r,r"))
2162                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2163   "TARGET_ARM"
2164   "#"
2165   [(set_attr "length" "8")
2166    (set_attr "predicable" "yes")]
2167 )
2168
2169 (define_expand "iorsi3"
2170   [(set (match_operand:SI         0 "s_register_operand" "")
2171         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2172                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2173   "TARGET_EITHER"
2174   "
2175   if (GET_CODE (operands[2]) == CONST_INT)
2176     {
2177       if (TARGET_ARM)
2178         {
2179           arm_split_constant (IOR, SImode, NULL_RTX,
2180                               INTVAL (operands[2]), operands[0], operands[1],
2181                               optimize && !no_new_pseudos);
2182           DONE;
2183         }
2184       else /* TARGET_THUMB */
2185         operands [2] = force_reg (SImode, operands [2]);
2186     }
2187   "
2188 )
2189
2190 (define_insn_and_split "*arm_iorsi3"
2191   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2192         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2193                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2194   "TARGET_ARM"
2195   "@
2196    orr%?\\t%0, %1, %2
2197    #"
2198   "TARGET_ARM
2199    && GET_CODE (operands[2]) == CONST_INT
2200    && !const_ok_for_arm (INTVAL (operands[2]))"
2201   [(clobber (const_int 0))]
2202   "
2203   arm_split_constant (IOR, SImode, curr_insn, 
2204                       INTVAL (operands[2]), operands[0], operands[1], 0);
2205   DONE;
2206   "
2207   [(set_attr "length" "4,16")
2208    (set_attr "predicable" "yes")]
2209 )
2210
2211 (define_insn "*thumb_iorsi3"
2212   [(set (match_operand:SI         0 "register_operand" "=l")
2213         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2214                 (match_operand:SI 2 "register_operand" "l")))]
2215   "TARGET_THUMB"
2216   "orr\\t%0, %0, %2"
2217   [(set_attr "length" "2")]
2218 )
2219
2220 (define_peephole2
2221   [(match_scratch:SI 3 "r")
2222    (set (match_operand:SI 0 "arm_general_register_operand" "")
2223         (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2224                 (match_operand:SI 2 "const_int_operand" "")))]
2225   "TARGET_ARM
2226    && !const_ok_for_arm (INTVAL (operands[2]))
2227    && const_ok_for_arm (~INTVAL (operands[2]))"
2228   [(set (match_dup 3) (match_dup 2))
2229    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2230   ""
2231 )
2232
2233 (define_insn "*iorsi3_compare0"
2234   [(set (reg:CC_NOOV CC_REGNUM)
2235         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2236                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2237                          (const_int 0)))
2238    (set (match_operand:SI 0 "s_register_operand" "=r")
2239         (ior:SI (match_dup 1) (match_dup 2)))]
2240   "TARGET_ARM"
2241   "orr%?s\\t%0, %1, %2"
2242   [(set_attr "conds" "set")]
2243 )
2244
2245 (define_insn "*iorsi3_compare0_scratch"
2246   [(set (reg:CC_NOOV CC_REGNUM)
2247         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2248                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2249                          (const_int 0)))
2250    (clobber (match_scratch:SI 0 "=r"))]
2251   "TARGET_ARM"
2252   "orr%?s\\t%0, %1, %2"
2253   [(set_attr "conds" "set")]
2254 )
2255
2256 (define_insn "xordi3"
2257   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2258         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2259                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2260   "TARGET_ARM && !TARGET_IWMMXT"
2261   "#"
2262   [(set_attr "length" "8")
2263    (set_attr "predicable" "yes")]
2264 )
2265
2266 (define_insn "*xordi_zesidi_di"
2267   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2268         (xor:DI (zero_extend:DI
2269                  (match_operand:SI 2 "s_register_operand" "r,r"))
2270                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2271   "TARGET_ARM"
2272   "@
2273    eor%?\\t%Q0, %Q1, %2
2274    #"
2275   [(set_attr "length" "4,8")
2276    (set_attr "predicable" "yes")]
2277 )
2278
2279 (define_insn "*xordi_sesidi_di"
2280   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2281         (xor:DI (sign_extend:DI
2282                  (match_operand:SI 2 "s_register_operand" "r,r"))
2283                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2284   "TARGET_ARM"
2285   "#"
2286   [(set_attr "length" "8")
2287    (set_attr "predicable" "yes")]
2288 )
2289
2290 (define_expand "xorsi3"
2291   [(set (match_operand:SI         0 "s_register_operand" "")
2292         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2293                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2294   "TARGET_EITHER"
2295   "if (TARGET_THUMB)
2296      if (GET_CODE (operands[2]) == CONST_INT)
2297        operands[2] = force_reg (SImode, operands[2]);
2298   "
2299 )
2300
2301 (define_insn "*arm_xorsi3"
2302   [(set (match_operand:SI         0 "s_register_operand" "=r")
2303         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2304                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2305   "TARGET_ARM"
2306   "eor%?\\t%0, %1, %2"
2307   [(set_attr "predicable" "yes")]
2308 )
2309
2310 (define_insn "*thumb_xorsi3"
2311   [(set (match_operand:SI         0 "register_operand" "=l")
2312         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2313                 (match_operand:SI 2 "register_operand" "l")))]
2314   "TARGET_THUMB"
2315   "eor\\t%0, %0, %2"
2316   [(set_attr "length" "2")]
2317 )
2318
2319 (define_insn "*xorsi3_compare0"
2320   [(set (reg:CC_NOOV CC_REGNUM)
2321         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2322                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2323                          (const_int 0)))
2324    (set (match_operand:SI 0 "s_register_operand" "=r")
2325         (xor:SI (match_dup 1) (match_dup 2)))]
2326   "TARGET_ARM"
2327   "eor%?s\\t%0, %1, %2"
2328   [(set_attr "conds" "set")]
2329 )
2330
2331 (define_insn "*xorsi3_compare0_scratch"
2332   [(set (reg:CC_NOOV CC_REGNUM)
2333         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2334                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2335                          (const_int 0)))]
2336   "TARGET_ARM"
2337   "teq%?\\t%0, %1"
2338   [(set_attr "conds" "set")]
2339 )
2340
2341 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2342 ; (NOT D) we can sometimes merge the final NOT into one of the following
2343 ; insns.
2344
2345 (define_split
2346   [(set (match_operand:SI 0 "s_register_operand" "")
2347         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2348                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2349                 (match_operand:SI 3 "arm_rhs_operand" "")))
2350    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2351   "TARGET_ARM"
2352   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2353                               (not:SI (match_dup 3))))
2354    (set (match_dup 0) (not:SI (match_dup 4)))]
2355   ""
2356 )
2357
2358 (define_insn "*andsi_iorsi3_notsi"
2359   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2360         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2361                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2362                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2363   "TARGET_ARM"
2364   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2365   [(set_attr "length" "8")
2366    (set_attr "predicable" "yes")]
2367 )
2368
2369 (define_split
2370   [(set (match_operand:SI 0 "s_register_operand" "")
2371         (match_operator:SI 1 "logical_binary_operator"
2372          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2373                            (match_operand:SI 3 "const_int_operand" "")
2374                            (match_operand:SI 4 "const_int_operand" ""))
2375           (match_operator:SI 9 "logical_binary_operator"
2376            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2377                          (match_operand:SI 6 "const_int_operand" ""))
2378             (match_operand:SI 7 "s_register_operand" "")])]))
2379    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2380   "TARGET_ARM
2381    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2382    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2383   [(set (match_dup 8)
2384         (match_op_dup 1
2385          [(ashift:SI (match_dup 2) (match_dup 4))
2386           (match_dup 5)]))
2387    (set (match_dup 0)
2388         (match_op_dup 1
2389          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2390           (match_dup 7)]))]
2391   "
2392   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2393 ")
2394
2395 (define_split
2396   [(set (match_operand:SI 0 "s_register_operand" "")
2397         (match_operator:SI 1 "logical_binary_operator"
2398          [(match_operator:SI 9 "logical_binary_operator"
2399            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2400                          (match_operand:SI 6 "const_int_operand" ""))
2401             (match_operand:SI 7 "s_register_operand" "")])
2402           (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2403                            (match_operand:SI 3 "const_int_operand" "")
2404                            (match_operand:SI 4 "const_int_operand" ""))]))
2405    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2406   "TARGET_ARM
2407    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2408    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2409   [(set (match_dup 8)
2410         (match_op_dup 1
2411          [(ashift:SI (match_dup 2) (match_dup 4))
2412           (match_dup 5)]))
2413    (set (match_dup 0)
2414         (match_op_dup 1
2415          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2416           (match_dup 7)]))]
2417   "
2418   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2419 ")
2420
2421 (define_split
2422   [(set (match_operand:SI 0 "s_register_operand" "")
2423         (match_operator:SI 1 "logical_binary_operator"
2424          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2425                            (match_operand:SI 3 "const_int_operand" "")
2426                            (match_operand:SI 4 "const_int_operand" ""))
2427           (match_operator:SI 9 "logical_binary_operator"
2428            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2429                          (match_operand:SI 6 "const_int_operand" ""))
2430             (match_operand:SI 7 "s_register_operand" "")])]))
2431    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2432   "TARGET_ARM
2433    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2434    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2435   [(set (match_dup 8)
2436         (match_op_dup 1
2437          [(ashift:SI (match_dup 2) (match_dup 4))
2438           (match_dup 5)]))
2439    (set (match_dup 0)
2440         (match_op_dup 1
2441          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2442           (match_dup 7)]))]
2443   "
2444   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2445 ")
2446
2447 (define_split
2448   [(set (match_operand:SI 0 "s_register_operand" "")
2449         (match_operator:SI 1 "logical_binary_operator"
2450          [(match_operator:SI 9 "logical_binary_operator"
2451            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2452                          (match_operand:SI 6 "const_int_operand" ""))
2453             (match_operand:SI 7 "s_register_operand" "")])
2454           (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2455                            (match_operand:SI 3 "const_int_operand" "")
2456                            (match_operand:SI 4 "const_int_operand" ""))]))
2457    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2458   "TARGET_ARM
2459    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2460    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2461   [(set (match_dup 8)
2462         (match_op_dup 1
2463          [(ashift:SI (match_dup 2) (match_dup 4))
2464           (match_dup 5)]))
2465    (set (match_dup 0)
2466         (match_op_dup 1
2467          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2468           (match_dup 7)]))]
2469   "
2470   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2471 ")
2472 \f
2473
2474 ;; Minimum and maximum insns
2475
2476 (define_insn "smaxsi3"
2477   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2478         (smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2479                  (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2480    (clobber (reg:CC CC_REGNUM))]
2481   "TARGET_ARM"
2482   "@
2483    cmp\\t%1, %2\;movlt\\t%0, %2
2484    cmp\\t%1, %2\;movge\\t%0, %1
2485    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2486   [(set_attr "conds" "clob")
2487    (set_attr "length" "8,8,12")]
2488 )
2489
2490 (define_insn "sminsi3"
2491   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2492         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2493                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2494    (clobber (reg:CC CC_REGNUM))]
2495   "TARGET_ARM"
2496   "@
2497    cmp\\t%1, %2\;movge\\t%0, %2
2498    cmp\\t%1, %2\;movlt\\t%0, %1
2499    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2500   [(set_attr "conds" "clob")
2501    (set_attr "length" "8,8,12")]
2502 )
2503
2504 (define_insn "umaxsi3"
2505   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2506         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2507                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2508    (clobber (reg:CC CC_REGNUM))]
2509   "TARGET_ARM"
2510   "@
2511    cmp\\t%1, %2\;movcc\\t%0, %2
2512    cmp\\t%1, %2\;movcs\\t%0, %1
2513    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2514   [(set_attr "conds" "clob")
2515    (set_attr "length" "8,8,12")]
2516 )
2517
2518 (define_insn "uminsi3"
2519   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2520         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2521                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2522    (clobber (reg:CC CC_REGNUM))]
2523   "TARGET_ARM"
2524   "@
2525    cmp\\t%1, %2\;movcs\\t%0, %2
2526    cmp\\t%1, %2\;movcc\\t%0, %1
2527    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2528   [(set_attr "conds" "clob")
2529    (set_attr "length" "8,8,12")]
2530 )
2531
2532 (define_insn "*store_minmaxsi"
2533   [(set (match_operand:SI 0 "memory_operand" "=m")
2534         (match_operator:SI 3 "minmax_operator"
2535          [(match_operand:SI 1 "s_register_operand" "r")
2536           (match_operand:SI 2 "s_register_operand" "r")]))
2537    (clobber (reg:CC CC_REGNUM))]
2538   "TARGET_ARM"
2539   "*
2540   operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2541                                 operands[1], operands[2]);
2542   output_asm_insn (\"cmp\\t%1, %2\", operands);
2543   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2544   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2545   return \"\";
2546   "
2547   [(set_attr "conds" "clob")
2548    (set_attr "length" "12")
2549    (set_attr "type" "store1")]
2550 )
2551
2552 ; Reject the frame pointer in operand[1], since reloading this after
2553 ; it has been eliminated can cause carnage.
2554 (define_insn "*minmax_arithsi"
2555   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2556         (match_operator:SI 4 "shiftable_operator"
2557          [(match_operator:SI 5 "minmax_operator"
2558            [(match_operand:SI 2 "s_register_operand" "r,r")
2559             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2560           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2561    (clobber (reg:CC CC_REGNUM))]
2562   "TARGET_ARM && !arm_eliminable_register (operands[1])"
2563   "*
2564   {
2565     enum rtx_code code = GET_CODE (operands[4]);
2566
2567     operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2568                                   operands[2], operands[3]);
2569     output_asm_insn (\"cmp\\t%2, %3\", operands);
2570     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2571     if (which_alternative != 0 || operands[3] != const0_rtx
2572         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2573       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2574     return \"\";
2575   }"
2576   [(set_attr "conds" "clob")
2577    (set_attr "length" "12")]
2578 )
2579
2580 \f
2581 ;; Shift and rotation insns
2582
2583 (define_expand "ashldi3"
2584   [(set (match_operand:DI            0 "s_register_operand" "")
2585         (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2586                    (match_operand:SI 2 "reg_or_int_operand" "")))]
2587   "TARGET_ARM"
2588   "
2589   if (GET_CODE (operands[2]) == CONST_INT)
2590     {
2591       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2592         {
2593           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2594           DONE;
2595         }
2596         /* Ideally we shouldn't fail here if we could know that operands[1] 
2597            ends up already living in an iwmmxt register. Otherwise it's
2598            cheaper to have the alternate code being generated than moving
2599            values to iwmmxt regs and back.  */
2600         FAIL;
2601     }
2602   else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2603     FAIL;
2604   "
2605 )
2606
2607 (define_insn "arm_ashldi3_1bit"
2608   [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
2609         (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2610                    (const_int 1)))
2611    (clobber (reg:CC CC_REGNUM))]
2612   "TARGET_ARM"
2613   "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2614   [(set_attr "conds" "clob")
2615    (set_attr "length" "8")]
2616 )
2617
2618 (define_expand "ashlsi3"
2619   [(set (match_operand:SI            0 "s_register_operand" "")
2620         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2621                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2622   "TARGET_EITHER"
2623   "
2624   if (GET_CODE (operands[2]) == CONST_INT
2625       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2626     {
2627       emit_insn (gen_movsi (operands[0], const0_rtx));
2628       DONE;
2629     }
2630   "
2631 )
2632
2633 (define_insn "*thumb_ashlsi3"
2634   [(set (match_operand:SI            0 "register_operand" "=l,l")
2635         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2636                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2637   "TARGET_THUMB"
2638   "lsl\\t%0, %1, %2"
2639   [(set_attr "length" "2")]
2640 )
2641
2642 (define_expand "ashrdi3"
2643   [(set (match_operand:DI              0 "s_register_operand" "")
2644         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2645                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2646   "TARGET_ARM"
2647   "
2648   if (GET_CODE (operands[2]) == CONST_INT)
2649     {
2650       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2651         {
2652           emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2653           DONE;
2654         }
2655         /* Ideally we shouldn't fail here if we could know that operands[1] 
2656            ends up already living in an iwmmxt register. Otherwise it's
2657            cheaper to have the alternate code being generated than moving
2658            values to iwmmxt regs and back.  */
2659         FAIL;
2660     }
2661   else if (!TARGET_REALLY_IWMMXT)
2662     FAIL;
2663   "
2664 )
2665
2666 (define_insn "arm_ashrdi3_1bit"
2667   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2668         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2669                      (const_int 1)))
2670    (clobber (reg:CC CC_REGNUM))]
2671   "TARGET_ARM"
2672   "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2673   [(set_attr "conds" "clob")
2674    (set_attr "length" "8")]
2675 )
2676
2677 (define_expand "ashrsi3"
2678   [(set (match_operand:SI              0 "s_register_operand" "")
2679         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2680                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2681   "TARGET_EITHER"
2682   "
2683   if (GET_CODE (operands[2]) == CONST_INT
2684       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2685     operands[2] = GEN_INT (31);
2686   "
2687 )
2688
2689 (define_insn "*thumb_ashrsi3"
2690   [(set (match_operand:SI              0 "register_operand" "=l,l")
2691         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2692                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2693   "TARGET_THUMB"
2694   "asr\\t%0, %1, %2"
2695   [(set_attr "length" "2")]
2696 )
2697
2698 (define_expand "lshrdi3"
2699   [(set (match_operand:DI              0 "s_register_operand" "")
2700         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2701                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2702   "TARGET_ARM"
2703   "
2704   if (GET_CODE (operands[2]) == CONST_INT)
2705     {
2706       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2707         {
2708           emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2709           DONE;
2710         }
2711         /* Ideally we shouldn't fail here if we could know that operands[1] 
2712            ends up already living in an iwmmxt register. Otherwise it's
2713            cheaper to have the alternate code being generated than moving
2714            values to iwmmxt regs and back.  */
2715         FAIL;
2716     }
2717   else if (!TARGET_REALLY_IWMMXT)
2718     FAIL;
2719   "
2720 )
2721
2722 (define_insn "arm_lshrdi3_1bit"
2723   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2724         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2725                      (const_int 1)))
2726    (clobber (reg:CC CC_REGNUM))]
2727   "TARGET_ARM"
2728   "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2729   [(set_attr "conds" "clob")
2730    (set_attr "length" "8")]
2731 )
2732
2733 (define_expand "lshrsi3"
2734   [(set (match_operand:SI              0 "s_register_operand" "")
2735         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2736                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2737   "TARGET_EITHER"
2738   "
2739   if (GET_CODE (operands[2]) == CONST_INT
2740       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2741     {
2742       emit_insn (gen_movsi (operands[0], const0_rtx));
2743       DONE;
2744     }
2745   "
2746 )
2747
2748 (define_insn "*thumb_lshrsi3"
2749   [(set (match_operand:SI              0 "register_operand" "=l,l")
2750         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2751                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2752   "TARGET_THUMB"
2753   "lsr\\t%0, %1, %2"
2754   [(set_attr "length" "2")]
2755 )
2756
2757 (define_expand "rotlsi3"
2758   [(set (match_operand:SI              0 "s_register_operand" "")
2759         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2760                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2761   "TARGET_ARM"
2762   "
2763   if (GET_CODE (operands[2]) == CONST_INT)
2764     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2765   else
2766     {
2767       rtx reg = gen_reg_rtx (SImode);
2768       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2769       operands[2] = reg;
2770     }
2771   "
2772 )
2773
2774 (define_expand "rotrsi3"
2775   [(set (match_operand:SI              0 "s_register_operand" "")
2776         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2777                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2778   "TARGET_EITHER"
2779   "
2780   if (TARGET_ARM)
2781     {
2782       if (GET_CODE (operands[2]) == CONST_INT
2783           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2784         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2785     }
2786   else /* TARGET_THUMB */
2787     {
2788       if (GET_CODE (operands [2]) == CONST_INT)
2789         operands [2] = force_reg (SImode, operands[2]);
2790     }
2791   "
2792 )
2793
2794 (define_insn "*thumb_rotrsi3"
2795   [(set (match_operand:SI              0 "register_operand" "=l")
2796         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2797                      (match_operand:SI 2 "register_operand" "l")))]
2798   "TARGET_THUMB"
2799   "ror\\t%0, %0, %2"
2800   [(set_attr "length" "2")]
2801 )
2802
2803 (define_insn "*arm_shiftsi3"
2804   [(set (match_operand:SI   0 "s_register_operand" "=r")
2805         (match_operator:SI  3 "shift_operator"
2806          [(match_operand:SI 1 "s_register_operand"  "r")
2807           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2808   "TARGET_ARM"
2809   "mov%?\\t%0, %1%S3"
2810   [(set_attr "predicable" "yes")
2811    (set_attr "shift" "1")
2812    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2813                       (const_string "alu_shift")
2814                       (const_string "alu_shift_reg")))]
2815 )
2816
2817 (define_insn "*shiftsi3_compare0"
2818   [(set (reg:CC_NOOV CC_REGNUM)
2819         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2820                           [(match_operand:SI 1 "s_register_operand" "r")
2821                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2822                          (const_int 0)))
2823    (set (match_operand:SI 0 "s_register_operand" "=r")
2824         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2825   "TARGET_ARM"
2826   "mov%?s\\t%0, %1%S3"
2827   [(set_attr "conds" "set")
2828    (set_attr "shift" "1")
2829    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2830                       (const_string "alu_shift")
2831                       (const_string "alu_shift_reg")))]
2832 )
2833
2834 (define_insn "*shiftsi3_compare0_scratch"
2835   [(set (reg:CC_NOOV CC_REGNUM)
2836         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2837                           [(match_operand:SI 1 "s_register_operand" "r")
2838                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2839                          (const_int 0)))
2840    (clobber (match_scratch:SI 0 "=r"))]
2841   "TARGET_ARM"
2842   "mov%?s\\t%0, %1%S3"
2843   [(set_attr "conds" "set")
2844    (set_attr "shift" "1")]
2845 )
2846
2847 (define_insn "*notsi_shiftsi"
2848   [(set (match_operand:SI 0 "s_register_operand" "=r")
2849         (not:SI (match_operator:SI 3 "shift_operator"
2850                  [(match_operand:SI 1 "s_register_operand" "r")
2851                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2852   "TARGET_ARM"
2853   "mvn%?\\t%0, %1%S3"
2854   [(set_attr "predicable" "yes")
2855    (set_attr "shift" "1")
2856    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2857                       (const_string "alu_shift")
2858                       (const_string "alu_shift_reg")))]
2859 )
2860
2861 (define_insn "*notsi_shiftsi_compare0"
2862   [(set (reg:CC_NOOV CC_REGNUM)
2863         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2864                           [(match_operand:SI 1 "s_register_operand" "r")
2865                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2866                          (const_int 0)))
2867    (set (match_operand:SI 0 "s_register_operand" "=r")
2868         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2869   "TARGET_ARM"
2870   "mvn%?s\\t%0, %1%S3"
2871   [(set_attr "conds" "set")
2872    (set_attr "shift" "1")
2873    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2874                       (const_string "alu_shift")
2875                       (const_string "alu_shift_reg")))]
2876 )
2877
2878 (define_insn "*not_shiftsi_compare0_scratch"
2879   [(set (reg:CC_NOOV CC_REGNUM)
2880         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2881                           [(match_operand:SI 1 "s_register_operand" "r")
2882                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2883                          (const_int 0)))
2884    (clobber (match_scratch:SI 0 "=r"))]
2885   "TARGET_ARM"
2886   "mvn%?s\\t%0, %1%S3"
2887   [(set_attr "conds" "set")
2888    (set_attr "shift" "1")
2889    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2890                       (const_string "alu_shift")
2891                       (const_string "alu_shift_reg")))]
2892 )
2893
2894 ;; We don't really have extzv, but defining this using shifts helps
2895 ;; to reduce register pressure later on.
2896
2897 (define_expand "extzv"
2898   [(set (match_dup 4)
2899         (ashift:SI (match_operand:SI   1 "register_operand" "")
2900                    (match_operand:SI   2 "const_int_operand" "")))
2901    (set (match_operand:SI              0 "register_operand" "")
2902         (lshiftrt:SI (match_dup 4)
2903                      (match_operand:SI 3 "const_int_operand" "")))]
2904   "TARGET_THUMB"
2905   "
2906   {
2907     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2908     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2909     
2910     operands[3] = GEN_INT (rshift);
2911     
2912     if (lshift == 0)
2913       {
2914         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2915         DONE;
2916       }
2917       
2918     operands[2] = GEN_INT (lshift);
2919     operands[4] = gen_reg_rtx (SImode);
2920   }"
2921 )
2922
2923 \f
2924 ;; Unary arithmetic insns
2925
2926 (define_expand "negdi2"
2927  [(parallel
2928    [(set (match_operand:DI          0 "s_register_operand" "")
2929           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2930     (clobber (reg:CC CC_REGNUM))])]
2931   "TARGET_EITHER"
2932   "
2933   if (TARGET_THUMB)
2934     {
2935       if (GET_CODE (operands[1]) != REG)
2936         operands[1] = force_reg (SImode, operands[1]);
2937      }
2938   "
2939 )
2940
2941 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2942 ;; The second alternative is to allow the common case of a *full* overlap.
2943 (define_insn "*arm_negdi2"
2944   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2945         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2946    (clobber (reg:CC CC_REGNUM))]
2947   "TARGET_ARM"
2948   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2949   [(set_attr "conds" "clob")
2950    (set_attr "length" "8")]
2951 )
2952
2953 (define_insn "*thumb_negdi2"
2954   [(set (match_operand:DI         0 "register_operand" "=&l")
2955         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
2956    (clobber (reg:CC CC_REGNUM))]
2957   "TARGET_THUMB"
2958   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2959   [(set_attr "length" "6")]
2960 )
2961
2962 (define_expand "negsi2"
2963   [(set (match_operand:SI         0 "s_register_operand" "")
2964         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2965   "TARGET_EITHER"
2966   ""
2967 )
2968
2969 (define_insn "*arm_negsi2"
2970   [(set (match_operand:SI         0 "s_register_operand" "=r")
2971         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2972   "TARGET_ARM"
2973   "rsb%?\\t%0, %1, #0"
2974   [(set_attr "predicable" "yes")]
2975 )
2976
2977 (define_insn "*thumb_negsi2"
2978   [(set (match_operand:SI         0 "register_operand" "=l")
2979         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2980   "TARGET_THUMB"
2981   "neg\\t%0, %1"
2982   [(set_attr "length" "2")]
2983 )
2984
2985 (define_expand "negsf2"
2986   [(set (match_operand:SF         0 "s_register_operand" "")
2987         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2988   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
2989   ""
2990 )
2991
2992 (define_expand "negdf2"
2993   [(set (match_operand:DF         0 "s_register_operand" "")
2994         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2995   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
2996   "")
2997
2998 ;; abssi2 doesn't really clobber the condition codes if a different register
2999 ;; is being set.  To keep things simple, assume during rtl manipulations that
3000 ;; it does, but tell the final scan operator the truth.  Similarly for
3001 ;; (neg (abs...))
3002
3003 (define_expand "abssi2"
3004   [(parallel
3005     [(set (match_operand:SI         0 "s_register_operand" "")
3006           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3007      (clobber (reg:CC CC_REGNUM))])]
3008   "TARGET_ARM"
3009   "")
3010
3011 (define_insn "*arm_abssi2"
3012   [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
3013         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3014    (clobber (reg:CC CC_REGNUM))]
3015   "TARGET_ARM"
3016   "@
3017    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3018    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3019   [(set_attr "conds" "clob,*")
3020    (set_attr "shift" "1")
3021    ;; predicable can't be set based on the variant, so left as no
3022    (set_attr "length" "8")]
3023 )
3024
3025 (define_insn "*neg_abssi2"
3026   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3027         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3028    (clobber (reg:CC CC_REGNUM))]
3029   "TARGET_ARM"
3030   "@
3031    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3032    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3033   [(set_attr "conds" "clob,*")
3034    (set_attr "shift" "1")
3035    ;; predicable can't be set based on the variant, so left as no
3036    (set_attr "length" "8")]
3037 )
3038
3039 (define_expand "abssf2"
3040   [(set (match_operand:SF         0 "s_register_operand" "")
3041         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3042   "TARGET_ARM && TARGET_HARD_FLOAT"
3043   "")
3044
3045 (define_expand "absdf2"
3046   [(set (match_operand:DF         0 "s_register_operand" "")
3047         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3048   "TARGET_ARM && TARGET_HARD_FLOAT"
3049   "")
3050
3051 (define_expand "sqrtsf2"
3052   [(set (match_operand:SF 0 "s_register_operand" "")
3053         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3054   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3055   "")
3056
3057 (define_expand "sqrtdf2"
3058   [(set (match_operand:DF 0 "s_register_operand" "")
3059         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3060   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3061   "")
3062
3063 (define_insn_and_split "one_cmpldi2"
3064   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3065         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3066   "TARGET_ARM"
3067   "#"
3068   "TARGET_ARM && reload_completed"
3069   [(set (match_dup 0) (not:SI (match_dup 1)))
3070    (set (match_dup 2) (not:SI (match_dup 3)))]
3071   "
3072   {
3073     operands[2] = gen_highpart (SImode, operands[0]);
3074     operands[0] = gen_lowpart (SImode, operands[0]);
3075     operands[3] = gen_highpart (SImode, operands[1]);
3076     operands[1] = gen_lowpart (SImode, operands[1]);
3077   }"
3078   [(set_attr "length" "8")
3079    (set_attr "predicable" "yes")]
3080 )
3081
3082 (define_expand "one_cmplsi2"
3083   [(set (match_operand:SI         0 "s_register_operand" "")
3084         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3085   "TARGET_EITHER"
3086   ""
3087 )
3088
3089 (define_insn "*arm_one_cmplsi2"
3090   [(set (match_operand:SI         0 "s_register_operand" "=r")
3091         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3092   "TARGET_ARM"
3093   "mvn%?\\t%0, %1"
3094   [(set_attr "predicable" "yes")]
3095 )
3096
3097 (define_insn "*thumb_one_cmplsi2"
3098   [(set (match_operand:SI         0 "register_operand" "=l")
3099         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3100   "TARGET_THUMB"
3101   "mvn\\t%0, %1"
3102   [(set_attr "length" "2")]
3103 )
3104
3105 (define_insn "*notsi_compare0"
3106   [(set (reg:CC_NOOV CC_REGNUM)
3107         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3108                          (const_int 0)))
3109    (set (match_operand:SI 0 "s_register_operand" "=r")
3110         (not:SI (match_dup 1)))]
3111   "TARGET_ARM"
3112   "mvn%?s\\t%0, %1"
3113   [(set_attr "conds" "set")]
3114 )
3115
3116 (define_insn "*notsi_compare0_scratch"
3117   [(set (reg:CC_NOOV CC_REGNUM)
3118         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3119                          (const_int 0)))
3120    (clobber (match_scratch:SI 0 "=r"))]
3121   "TARGET_ARM"
3122   "mvn%?s\\t%0, %1"
3123   [(set_attr "conds" "set")]
3124 )
3125 \f
3126 ;; Fixed <--> Floating conversion insns
3127
3128 (define_expand "floatsisf2"
3129   [(set (match_operand:SF           0 "s_register_operand" "")
3130         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3131   "TARGET_ARM && TARGET_HARD_FLOAT"
3132   "
3133   if (TARGET_MAVERICK)
3134     {
3135       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3136       DONE;
3137     }
3138 ")
3139
3140 (define_expand "floatsidf2"
3141   [(set (match_operand:DF           0 "s_register_operand" "")
3142         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3143   "TARGET_ARM && TARGET_HARD_FLOAT"
3144   "
3145   if (TARGET_MAVERICK)
3146     {
3147       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3148       DONE;
3149     }
3150 ")
3151
3152 (define_expand "fix_truncsfsi2"
3153   [(set (match_operand:SI         0 "s_register_operand" "")
3154         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3155   "TARGET_ARM && TARGET_HARD_FLOAT"
3156   "
3157   if (TARGET_MAVERICK)
3158     {
3159       if (!cirrus_fp_register (operands[0], SImode))
3160         operands[0] = force_reg (SImode, operands[0]);
3161       if (!cirrus_fp_register (operands[1], SFmode))
3162         operands[1] = force_reg (SFmode, operands[0]);
3163       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3164       DONE;
3165     }
3166 ")
3167
3168 (define_expand "fix_truncdfsi2"
3169   [(set (match_operand:SI         0 "s_register_operand" "")
3170         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3171   "TARGET_ARM && TARGET_HARD_FLOAT"
3172   "
3173   if (TARGET_MAVERICK)
3174     {
3175       if (!cirrus_fp_register (operands[1], DFmode))
3176         operands[1] = force_reg (DFmode, operands[0]);
3177       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3178       DONE;
3179     }
3180 ")
3181
3182 ;; Truncation insns
3183
3184 (define_expand "truncdfsf2"
3185   [(set (match_operand:SF  0 "s_register_operand" "")
3186         (float_truncate:SF
3187          (match_operand:DF 1 "s_register_operand" "")))]
3188   "TARGET_ARM && TARGET_HARD_FLOAT"
3189   ""
3190 )
3191 \f
3192 ;; Zero and sign extension instructions.
3193
3194 (define_insn "zero_extendsidi2"
3195   [(set (match_operand:DI 0 "s_register_operand" "=r")
3196         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3197   "TARGET_ARM"
3198   "*
3199     if (REGNO (operands[1])
3200         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3201       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3202     return \"mov%?\\t%R0, #0\";
3203   "
3204   [(set_attr "length" "8")
3205    (set_attr "predicable" "yes")]
3206 )
3207
3208 (define_insn "zero_extendqidi2"
3209   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3210         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3211   "TARGET_ARM"
3212   "@
3213    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3214    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3215   [(set_attr "length" "8")
3216    (set_attr "predicable" "yes")
3217    (set_attr "type" "*,load_byte")
3218    (set_attr "pool_range" "*,4092")
3219    (set_attr "neg_pool_range" "*,4084")]
3220 )
3221
3222 (define_insn "extendsidi2"
3223   [(set (match_operand:DI 0 "s_register_operand" "=r")
3224         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3225   "TARGET_ARM"
3226   "*
3227     if (REGNO (operands[1])
3228         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3229       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3230     return \"mov%?\\t%R0, %Q0, asr #31\";
3231   "
3232   [(set_attr "length" "8")
3233    (set_attr "shift" "1")
3234    (set_attr "predicable" "yes")]
3235 )
3236
3237 (define_expand "zero_extendhisi2"
3238   [(set (match_dup 2)
3239         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3240                    (const_int 16)))
3241    (set (match_operand:SI 0 "s_register_operand" "")
3242         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3243   "TARGET_EITHER"
3244   "
3245   {
3246     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3247       {
3248         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3249                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3250         DONE;
3251       }
3252
3253     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3254       {
3255         emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3256         DONE;
3257       }
3258
3259     if (!s_register_operand (operands[1], HImode))
3260       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3261
3262     if (arm_arch6)
3263       {
3264         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3265                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3266         DONE;
3267       }
3268
3269     operands[1] = gen_lowpart (SImode, operands[1]);
3270     operands[2] = gen_reg_rtx (SImode);
3271   }"
3272 )
3273
3274 (define_insn "*thumb_zero_extendhisi2"
3275   [(set (match_operand:SI 0 "register_operand" "=l")
3276         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3277   "TARGET_THUMB && !arm_arch6"
3278   "*
3279   rtx mem = XEXP (operands[1], 0);
3280
3281   if (GET_CODE (mem) == CONST)
3282     mem = XEXP (mem, 0);
3283     
3284   if (GET_CODE (mem) == LABEL_REF)
3285     return \"ldr\\t%0, %1\";
3286     
3287   if (GET_CODE (mem) == PLUS)
3288     {
3289       rtx a = XEXP (mem, 0);
3290       rtx b = XEXP (mem, 1);
3291
3292       /* This can happen due to bugs in reload.  */
3293       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3294         {
3295           rtx ops[2];
3296           ops[0] = operands[0];
3297           ops[1] = a;
3298       
3299           output_asm_insn (\"mov        %0, %1\", ops);
3300
3301           XEXP (mem, 0) = operands[0];
3302        }
3303
3304       else if (   GET_CODE (a) == LABEL_REF
3305                && GET_CODE (b) == CONST_INT)
3306         return \"ldr\\t%0, %1\";
3307     }
3308     
3309   return \"ldrh\\t%0, %1\";
3310   "
3311   [(set_attr "length" "4")
3312    (set_attr "type" "load_byte")
3313    (set_attr "pool_range" "60")]
3314 )
3315
3316 (define_insn "*thumb_zero_extendhisi2_v6"
3317   [(set (match_operand:SI 0 "register_operand" "=l,l")
3318         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3319   "TARGET_THUMB && arm_arch6"
3320   "*
3321   rtx mem;
3322
3323   if (which_alternative == 0)
3324     return \"uxth\\t%0, %1\";
3325
3326   mem = XEXP (operands[1], 0);
3327
3328   if (GET_CODE (mem) == CONST)
3329     mem = XEXP (mem, 0);
3330     
3331   if (GET_CODE (mem) == LABEL_REF)
3332     return \"ldr\\t%0, %1\";
3333     
3334   if (GET_CODE (mem) == PLUS)
3335     {
3336       rtx a = XEXP (mem, 0);
3337       rtx b = XEXP (mem, 1);
3338
3339       /* This can happen due to bugs in reload.  */
3340       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3341         {
3342           rtx ops[2];
3343           ops[0] = operands[0];
3344           ops[1] = a;
3345       
3346           output_asm_insn (\"mov        %0, %1\", ops);
3347
3348           XEXP (mem, 0) = operands[0];
3349        }
3350
3351       else if (   GET_CODE (a) == LABEL_REF
3352                && GET_CODE (b) == CONST_INT)
3353         return \"ldr\\t%0, %1\";
3354     }
3355     
3356   return \"ldrh\\t%0, %1\";
3357   "
3358   [(set_attr "length" "2,4")
3359    (set_attr "type" "alu_shift,load_byte")
3360    (set_attr "pool_range" "*,60")]
3361 )
3362
3363 (define_insn "*arm_zero_extendhisi2"
3364   [(set (match_operand:SI 0 "s_register_operand" "=r")
3365         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3366   "TARGET_ARM && arm_arch4 && !arm_arch6"
3367   "ldr%?h\\t%0, %1"
3368   [(set_attr "type" "load_byte")
3369    (set_attr "predicable" "yes")
3370    (set_attr "pool_range" "256")
3371    (set_attr "neg_pool_range" "244")]
3372 )
3373
3374 (define_insn "*arm_zero_extendhisi2_v6"
3375   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3376         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3377   "TARGET_ARM && arm_arch6"
3378   "@
3379    uxth%?\\t%0, %1
3380    ldr%?h\\t%0, %1"
3381   [(set_attr "type" "alu_shift,load_byte")
3382    (set_attr "predicable" "yes")
3383    (set_attr "pool_range" "*,256")
3384    (set_attr "neg_pool_range" "*,244")]
3385 )
3386
3387 (define_insn "*arm_zero_extendhisi2addsi"
3388   [(set (match_operand:SI 0 "s_register_operand" "=r")
3389         (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3390                  (match_operand:SI 2 "s_register_operand" "r")))]
3391   "TARGET_ARM && arm_arch6"
3392   "uxtah%?\\t%0, %2, %1"
3393   [(set_attr "type" "alu_shift")
3394    (set_attr "predicable" "yes")]
3395 )
3396
3397 (define_expand "zero_extendqisi2"
3398   [(set (match_operand:SI 0 "s_register_operand" "")
3399         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3400   "TARGET_EITHER"
3401   "
3402   if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3403     {
3404       if (TARGET_ARM)
3405         {
3406           emit_insn (gen_andsi3 (operands[0],
3407                                  gen_lowpart (SImode, operands[1]),
3408                                  GEN_INT (255)));
3409         }
3410       else /* TARGET_THUMB */
3411         {
3412           rtx temp = gen_reg_rtx (SImode);
3413           rtx ops[3];
3414           
3415           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3416           operands[1] = gen_lowpart (SImode, operands[1]);
3417
3418           ops[0] = temp;
3419           ops[1] = operands[1];
3420           ops[2] = GEN_INT (24);
3421
3422           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3423                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3424           
3425           ops[0] = operands[0];
3426           ops[1] = temp;
3427           ops[2] = GEN_INT (24);
3428
3429           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3430                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3431         }
3432       DONE;
3433     }
3434   "
3435 )
3436
3437 (define_insn "*thumb_zero_extendqisi2"
3438   [(set (match_operand:SI 0 "register_operand" "=l")
3439         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3440   "TARGET_THUMB && !arm_arch6"
3441   "ldrb\\t%0, %1"
3442   [(set_attr "length" "2")
3443    (set_attr "type" "load_byte")
3444    (set_attr "pool_range" "32")]
3445 )
3446
3447 (define_insn "*thumb_zero_extendqisi2_v6"
3448   [(set (match_operand:SI 0 "register_operand" "=l,l")
3449         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3450   "TARGET_THUMB && arm_arch6"
3451   "@
3452    uxtb\\t%0, %1
3453    ldrb\\t%0, %1"
3454   [(set_attr "length" "2,2")
3455    (set_attr "type" "alu_shift,load_byte")
3456    (set_attr "pool_range" "*,32")]
3457 )
3458
3459 (define_insn "*arm_zero_extendqisi2"
3460   [(set (match_operand:SI 0 "s_register_operand" "=r")
3461         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3462   "TARGET_ARM && !arm_arch6"
3463   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3464   [(set_attr "type" "load_byte")
3465    (set_attr "predicable" "yes")
3466    (set_attr "pool_range" "4096")
3467    (set_attr "neg_pool_range" "4084")]
3468 )
3469
3470 (define_insn "*arm_zero_extendqisi2_v6"
3471   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3472         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3473   "TARGET_ARM && arm_arch6"
3474   "@
3475    uxtb%?\\t%0, %1
3476    ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3477   [(set_attr "type" "alu_shift,load_byte")
3478    (set_attr "predicable" "yes")
3479    (set_attr "pool_range" "*,4096")
3480    (set_attr "neg_pool_range" "*,4084")]
3481 )
3482
3483 (define_insn "*arm_zero_extendqisi2addsi"
3484   [(set (match_operand:SI 0 "s_register_operand" "=r")
3485         (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3486                  (match_operand:SI 2 "s_register_operand" "r")))]
3487   "TARGET_ARM && arm_arch6"
3488   "uxtab%?\\t%0, %2, %1"
3489   [(set_attr "predicable" "yes")
3490    (set_attr "type" "alu_shift")]
3491 )
3492
3493 (define_split
3494   [(set (match_operand:SI 0 "s_register_operand" "")
3495         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3496    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3497   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3498   [(set (match_dup 2) (match_dup 1))
3499    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3500   ""
3501 )
3502
3503 (define_insn "*compareqi_eq0"
3504   [(set (reg:CC_Z CC_REGNUM)
3505         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3506                          (const_int 0)))]
3507   "TARGET_ARM"
3508   "tst\\t%0, #255"
3509   [(set_attr "conds" "set")]
3510 )
3511
3512 (define_expand "extendhisi2"
3513   [(set (match_dup 2)
3514         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3515                    (const_int 16)))
3516    (set (match_operand:SI 0 "s_register_operand" "")
3517         (ashiftrt:SI (match_dup 2)
3518                      (const_int 16)))]
3519   "TARGET_EITHER"
3520   "
3521   {
3522     if (GET_CODE (operands[1]) == MEM)
3523       {
3524         if (TARGET_THUMB)
3525           {
3526             emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3527             DONE;
3528           }
3529         else if (arm_arch4)
3530           {
3531             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3532                        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3533             DONE;
3534           }
3535       }
3536
3537     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3538       {
3539         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3540         DONE;
3541       }
3542
3543     if (!s_register_operand (operands[1], HImode))
3544       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3545
3546     if (arm_arch6)
3547       {
3548         if (TARGET_THUMB)
3549           emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3550         else
3551           emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3552                      gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3553
3554         DONE;
3555       }
3556
3557     operands[1] = gen_lowpart (SImode, operands[1]);
3558     operands[2] = gen_reg_rtx (SImode);
3559   }"
3560 )
3561
3562 (define_insn "thumb_extendhisi2"
3563   [(set (match_operand:SI 0 "register_operand" "=l")
3564         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3565    (clobber (match_scratch:SI 2 "=&l"))]
3566   "TARGET_THUMB && !arm_arch6"
3567   "*
3568   {
3569     rtx ops[4];
3570     rtx mem = XEXP (operands[1], 0);
3571
3572     /* This code used to try to use 'V', and fix the address only if it was
3573        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3574        range of QImode offsets, and offsettable_address_p does a QImode
3575        address check.  */
3576        
3577     if (GET_CODE (mem) == CONST)
3578       mem = XEXP (mem, 0);
3579     
3580     if (GET_CODE (mem) == LABEL_REF)
3581       return \"ldr\\t%0, %1\";
3582     
3583     if (GET_CODE (mem) == PLUS)
3584       {
3585         rtx a = XEXP (mem, 0);
3586         rtx b = XEXP (mem, 1);
3587
3588         if (GET_CODE (a) == LABEL_REF
3589             && GET_CODE (b) == CONST_INT)
3590           return \"ldr\\t%0, %1\";
3591
3592         if (GET_CODE (b) == REG)
3593           return \"ldrsh\\t%0, %1\";
3594           
3595         ops[1] = a;
3596         ops[2] = b;
3597       }
3598     else
3599       {
3600         ops[1] = mem;
3601         ops[2] = const0_rtx;
3602       }
3603
3604     gcc_assert (GET_CODE (ops[1]) == REG);
3605
3606     ops[0] = operands[0];
3607     ops[3] = operands[2];
3608     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3609     return \"\";
3610   }"
3611   [(set_attr "length" "4")
3612    (set_attr "type" "load_byte")
3613    (set_attr "pool_range" "1020")]
3614 )
3615
3616 ;; We used to have an early-clobber on the scratch register here.
3617 ;; However, there's a bug somewhere in reload which means that this
3618 ;; can be partially ignored during spill allocation if the memory
3619 ;; address also needs reloading; this causes us to die later on when
3620 ;; we try to verify the operands.  Fortunately, we don't really need
3621 ;; the early-clobber: we can always use operand 0 if operand 2
3622 ;; overlaps the address.
3623 (define_insn "*thumb_extendhisi2_insn_v6"
3624   [(set (match_operand:SI 0 "register_operand" "=l,l")
3625         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3626    (clobber (match_scratch:SI 2 "=X,l"))]
3627   "TARGET_THUMB && arm_arch6"
3628   "*
3629   {
3630     rtx ops[4];
3631     rtx mem;
3632
3633     if (which_alternative == 0)
3634       return \"sxth\\t%0, %1\";
3635
3636     mem = XEXP (operands[1], 0);
3637
3638     /* This code used to try to use 'V', and fix the address only if it was
3639        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3640        range of QImode offsets, and offsettable_address_p does a QImode
3641        address check.  */
3642        
3643     if (GET_CODE (mem) == CONST)
3644       mem = XEXP (mem, 0);
3645     
3646     if (GET_CODE (mem) == LABEL_REF)
3647       return \"ldr\\t%0, %1\";
3648     
3649     if (GET_CODE (mem) == PLUS)
3650       {
3651         rtx a = XEXP (mem, 0);
3652         rtx b = XEXP (mem, 1);
3653
3654         if (GET_CODE (a) == LABEL_REF
3655             && GET_CODE (b) == CONST_INT)
3656           return \"ldr\\t%0, %1\";
3657
3658         if (GET_CODE (b) == REG)
3659           return \"ldrsh\\t%0, %1\";
3660           
3661         ops[1] = a;
3662         ops[2] = b;
3663       }
3664     else
3665       {
3666         ops[1] = mem;
3667         ops[2] = const0_rtx;
3668       }
3669       
3670     gcc_assert (GET_CODE (ops[1]) == REG);
3671
3672     ops[0] = operands[0];
3673     if (reg_mentioned_p (operands[2], ops[1]))
3674       ops[3] = ops[0];
3675     else
3676       ops[3] = operands[2];
3677     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3678     return \"\";
3679   }"
3680   [(set_attr "length" "2,4")
3681    (set_attr "type" "alu_shift,load_byte")
3682    (set_attr "pool_range" "*,1020")]
3683 )
3684
3685 (define_expand "extendhisi2_mem"
3686   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3687    (set (match_dup 3)
3688         (zero_extend:SI (match_dup 7)))
3689    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3690    (set (match_operand:SI 0 "" "")
3691         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3692   "TARGET_ARM"
3693   "
3694   {
3695     rtx mem1, mem2;
3696     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3697
3698     mem1 = change_address (operands[1], QImode, addr);
3699     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
3700     operands[0] = gen_lowpart (SImode, operands[0]);
3701     operands[1] = mem1;
3702     operands[2] = gen_reg_rtx (SImode);
3703     operands[3] = gen_reg_rtx (SImode);
3704     operands[6] = gen_reg_rtx (SImode);
3705     operands[7] = mem2;
3706
3707     if (BYTES_BIG_ENDIAN)
3708       {
3709         operands[4] = operands[2];
3710         operands[5] = operands[3];
3711       }
3712     else
3713       {
3714         operands[4] = operands[3];
3715         operands[5] = operands[2];
3716       }
3717   }"
3718 )
3719
3720 (define_insn "*arm_extendhisi2"
3721   [(set (match_operand:SI 0 "s_register_operand" "=r")
3722         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3723   "TARGET_ARM && arm_arch4 && !arm_arch6"
3724   "ldr%?sh\\t%0, %1"
3725   [(set_attr "type" "load_byte")
3726    (set_attr "predicable" "yes")
3727    (set_attr "pool_range" "256")
3728    (set_attr "neg_pool_range" "244")]
3729 )
3730
3731 (define_insn "*arm_extendhisi2_v6"
3732   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3733         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3734   "TARGET_ARM && arm_arch6"
3735   "@
3736    sxth%?\\t%0, %1
3737    ldr%?sh\\t%0, %1"
3738   [(set_attr "type" "alu_shift,load_byte")
3739    (set_attr "predicable" "yes")
3740    (set_attr "pool_range" "*,256")
3741    (set_attr "neg_pool_range" "*,244")]
3742 )
3743
3744 (define_insn "*arm_extendhisi2addsi"
3745   [(set (match_operand:SI 0 "s_register_operand" "=r")
3746         (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3747                  (match_operand:SI 2 "s_register_operand" "r")))]
3748   "TARGET_ARM && arm_arch6"
3749   "sxtah%?\\t%0, %2, %1"
3750 )
3751
3752 (define_expand "extendqihi2"
3753   [(set (match_dup 2)
3754         (ashift:SI (match_operand:QI 1 "general_operand" "")
3755                    (const_int 24)))
3756    (set (match_operand:HI 0 "s_register_operand" "")
3757         (ashiftrt:SI (match_dup 2)
3758                      (const_int 24)))]
3759   "TARGET_ARM"
3760   "
3761   {
3762     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3763       {
3764         emit_insn (gen_rtx_SET (VOIDmode,
3765                                 operands[0],
3766                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3767         DONE;
3768       }
3769     if (!s_register_operand (operands[1], QImode))
3770       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3771     operands[0] = gen_lowpart (SImode, operands[0]);
3772     operands[1] = gen_lowpart (SImode, operands[1]);
3773     operands[2] = gen_reg_rtx (SImode);
3774   }"
3775 )
3776
3777 (define_insn "*extendqihi_insn"
3778   [(set (match_operand:HI 0 "s_register_operand" "=r")
3779         (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3780   "TARGET_ARM && arm_arch4"
3781   "ldr%?sb\\t%0, %1"
3782   [(set_attr "type" "load_byte")
3783    (set_attr "predicable" "yes")
3784    (set_attr "pool_range" "256")
3785    (set_attr "neg_pool_range" "244")]
3786 )
3787
3788 (define_expand "extendqisi2"
3789   [(set (match_dup 2)
3790         (ashift:SI (match_operand:QI 1 "general_operand" "")
3791                    (const_int 24)))
3792    (set (match_operand:SI 0 "s_register_operand" "")
3793         (ashiftrt:SI (match_dup 2)
3794                      (const_int 24)))]
3795   "TARGET_EITHER"
3796   "
3797   {
3798     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3799       {
3800         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3801                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3802         DONE;
3803       }
3804
3805     if (!s_register_operand (operands[1], QImode))
3806       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3807
3808     if (arm_arch6)
3809       {
3810         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3811                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3812         DONE;
3813       }
3814
3815     operands[1] = gen_lowpart (SImode, operands[1]);
3816     operands[2] = gen_reg_rtx (SImode);
3817   }"
3818 )
3819
3820 (define_insn "*arm_extendqisi"
3821   [(set (match_operand:SI 0 "s_register_operand" "=r")
3822         (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3823   "TARGET_ARM && arm_arch4 && !arm_arch6"
3824   "ldr%?sb\\t%0, %1"
3825   [(set_attr "type" "load_byte")
3826    (set_attr "predicable" "yes")
3827    (set_attr "pool_range" "256")
3828    (set_attr "neg_pool_range" "244")]
3829 )
3830
3831 (define_insn "*arm_extendqisi_v6"
3832   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3833         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3834   "TARGET_ARM && arm_arch6"
3835   "@
3836    sxtb%?\\t%0, %1
3837    ldr%?sb\\t%0, %1"
3838   [(set_attr "type" "alu_shift,load_byte")
3839    (set_attr "predicable" "yes")
3840    (set_attr "pool_range" "*,256")
3841    (set_attr "neg_pool_range" "*,244")]
3842 )
3843
3844 (define_insn "*arm_extendqisi2addsi"
3845   [(set (match_operand:SI 0 "s_register_operand" "=r")
3846         (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3847                  (match_operand:SI 2 "s_register_operand" "r")))]
3848   "TARGET_ARM && arm_arch6"
3849   "sxtab%?\\t%0, %2, %1"
3850   [(set_attr "type" "alu_shift")
3851    (set_attr "predicable" "yes")]
3852 )
3853
3854 (define_insn "*thumb_extendqisi2"
3855   [(set (match_operand:SI 0 "register_operand" "=l,l")
3856         (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3857   "TARGET_THUMB && !arm_arch6"
3858   "*
3859   {
3860     rtx ops[3];
3861     rtx mem = XEXP (operands[1], 0);
3862     
3863     if (GET_CODE (mem) == CONST)
3864       mem = XEXP (mem, 0);
3865     
3866     if (GET_CODE (mem) == LABEL_REF)
3867       return \"ldr\\t%0, %1\";
3868
3869     if (GET_CODE (mem) == PLUS
3870         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3871       return \"ldr\\t%0, %1\";
3872       
3873     if (which_alternative == 0)
3874       return \"ldrsb\\t%0, %1\";
3875       
3876     ops[0] = operands[0];
3877     
3878     if (GET_CODE (mem) == PLUS)
3879       {
3880         rtx a = XEXP (mem, 0);
3881         rtx b = XEXP (mem, 1);
3882         
3883         ops[1] = a;
3884         ops[2] = b;
3885
3886         if (GET_CODE (a) == REG)
3887           {
3888             if (GET_CODE (b) == REG)
3889               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3890             else if (REGNO (a) == REGNO (ops[0]))
3891               {
3892                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3893                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3894                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3895               }
3896             else
3897               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3898           }
3899         else
3900           {
3901             gcc_assert (GET_CODE (b) == REG);
3902             if (REGNO (b) == REGNO (ops[0]))
3903               {
3904                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3905                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3906                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3907               }
3908             else
3909               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3910           }
3911       }
3912     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3913       {
3914         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3915         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3916         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3917       }
3918     else
3919       {
3920         ops[1] = mem;
3921         ops[2] = const0_rtx;
3922         
3923         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3924       }
3925     return \"\";
3926   }"
3927   [(set_attr "length" "2,6")
3928    (set_attr "type" "load_byte,load_byte")
3929    (set_attr "pool_range" "32,32")]
3930 )
3931
3932 (define_insn "*thumb_extendqisi2_v6"
3933   [(set (match_operand:SI 0 "register_operand" "=l,l,l")
3934         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
3935   "TARGET_THUMB && arm_arch6"
3936   "*
3937   {
3938     rtx ops[3];
3939     rtx mem;
3940
3941     if (which_alternative == 0)
3942       return \"sxtb\\t%0, %1\";
3943
3944     mem = XEXP (operands[1], 0);
3945     
3946     if (GET_CODE (mem) == CONST)
3947       mem = XEXP (mem, 0);
3948     
3949     if (GET_CODE (mem) == LABEL_REF)
3950       return \"ldr\\t%0, %1\";
3951
3952     if (GET_CODE (mem) == PLUS
3953         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3954       return \"ldr\\t%0, %1\";
3955       
3956     if (which_alternative == 0)
3957       return \"ldrsb\\t%0, %1\";
3958       
3959     ops[0] = operands[0];
3960     
3961     if (GET_CODE (mem) == PLUS)
3962       {
3963         rtx a = XEXP (mem, 0);
3964         rtx b = XEXP (mem, 1);
3965         
3966         ops[1] = a;
3967         ops[2] = b;
3968
3969         if (GET_CODE (a) == REG)
3970           {
3971             if (GET_CODE (b) == REG)
3972               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3973             else if (REGNO (a) == REGNO (ops[0]))
3974               {
3975                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3976                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
3977               }
3978             else
3979               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3980           }
3981         else
3982           {
3983             gcc_assert (GET_CODE (b) == REG);
3984             if (REGNO (b) == REGNO (ops[0]))
3985               {
3986                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3987                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
3988               }
3989             else
3990               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3991           }
3992       }
3993     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3994       {
3995         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3996         output_asm_insn (\"sxtb\\t%0, %0\", ops);
3997       }
3998     else
3999       {
4000         ops[1] = mem;
4001         ops[2] = const0_rtx;
4002         
4003         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4004       }
4005     return \"\";
4006   }"
4007   [(set_attr "length" "2,2,4")
4008    (set_attr "type" "alu_shift,load_byte,load_byte")
4009    (set_attr "pool_range" "*,32,32")]
4010 )
4011
4012 (define_expand "extendsfdf2"
4013   [(set (match_operand:DF                  0 "s_register_operand" "")
4014         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
4015   "TARGET_ARM && TARGET_HARD_FLOAT"
4016   ""
4017 )
4018 \f
4019 ;; Move insns (including loads and stores)
4020
4021 ;; XXX Just some ideas about movti.
4022 ;; I don't think these are a good idea on the arm, there just aren't enough
4023 ;; registers
4024 ;;(define_expand "loadti"
4025 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
4026 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
4027 ;;  "" "")
4028
4029 ;;(define_expand "storeti"
4030 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4031 ;;      (match_operand:TI 1 "s_register_operand" ""))]
4032 ;;  "" "")
4033
4034 ;;(define_expand "movti"
4035 ;;  [(set (match_operand:TI 0 "general_operand" "")
4036 ;;      (match_operand:TI 1 "general_operand" ""))]
4037 ;;  ""
4038 ;;  "
4039 ;;{
4040 ;;  rtx insn;
4041 ;;
4042 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4043 ;;    operands[1] = copy_to_reg (operands[1]);
4044 ;;  if (GET_CODE (operands[0]) == MEM)
4045 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4046 ;;  else if (GET_CODE (operands[1]) == MEM)
4047 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4048 ;;  else
4049 ;;    FAIL;
4050 ;;
4051 ;;  emit_insn (insn);
4052 ;;  DONE;
4053 ;;}")
4054
4055 ;; Recognize garbage generated above.
4056
4057 ;;(define_insn ""
4058 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4059 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4060 ;;  ""
4061 ;;  "*
4062 ;;  {
4063 ;;    register mem = (which_alternative < 3);
4064 ;;    register const char *template;
4065 ;;
4066 ;;    operands[mem] = XEXP (operands[mem], 0);
4067 ;;    switch (which_alternative)
4068 ;;      {
4069 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4070 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
4071 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
4072 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
4073 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
4074 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
4075 ;;      }
4076 ;;    output_asm_insn (template, operands);
4077 ;;    return \"\";
4078 ;;  }")
4079
4080 (define_expand "movdi"
4081   [(set (match_operand:DI 0 "general_operand" "")
4082         (match_operand:DI 1 "general_operand" ""))]
4083   "TARGET_EITHER"
4084   "
4085   if (TARGET_THUMB)
4086     {
4087       if (!no_new_pseudos)
4088         {
4089           if (GET_CODE (operands[0]) != REG)
4090             operands[1] = force_reg (DImode, operands[1]);
4091         }
4092     }
4093   "
4094 )
4095
4096 (define_insn "*arm_movdi"
4097   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4098         (match_operand:DI 1 "di_operand"              "rDa,Db,Dc,mi,r"))]
4099   "TARGET_ARM
4100   && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4101   && !TARGET_IWMMXT"
4102   "*
4103   switch (which_alternative)
4104     {
4105     case 0:
4106     case 1:
4107     case 2:
4108       return \"#\";
4109     default:
4110       return output_move_double (operands);
4111     }
4112   "
4113   [(set_attr "length" "8,12,16,8,8")
4114    (set_attr "type" "*,*,*,load2,store2")
4115    (set_attr "pool_range" "*,*,*,1020,*")
4116    (set_attr "neg_pool_range" "*,*,*,1008,*")]
4117 )
4118
4119 (define_split
4120   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4121         (match_operand:ANY64 1 "const_double_operand" ""))]
4122   "TARGET_ARM
4123    && reload_completed
4124    && (arm_const_double_inline_cost (operands[1])
4125        <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4126   [(const_int 0)]
4127   "
4128   arm_split_constant (SET, SImode, curr_insn,
4129                       INTVAL (gen_lowpart (SImode, operands[1])),
4130                       gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4131   arm_split_constant (SET, SImode, curr_insn,
4132                       INTVAL (gen_highpart_mode (SImode,
4133                                                  GET_MODE (operands[0]),
4134                                                  operands[1])),
4135                       gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4136   DONE;
4137   "
4138 )
4139
4140 ; If optimizing for size, or if we have load delay slots, then 
4141 ; we want to split the constant into two separate operations. 
4142 ; In both cases this may split a trivial part into a single data op
4143 ; leaving a single complex constant to load.  We can also get longer
4144 ; offsets in a LDR which means we get better chances of sharing the pool
4145 ; entries.  Finally, we can normally do a better job of scheduling
4146 ; LDR instructions than we can with LDM.
4147 ; This pattern will only match if the one above did not.
4148 (define_split
4149   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4150         (match_operand:ANY64 1 "const_double_operand" ""))]
4151   "TARGET_ARM && reload_completed
4152    && arm_const_double_by_parts (operands[1])"
4153   [(set (match_dup 0) (match_dup 1))
4154    (set (match_dup 2) (match_dup 3))]
4155   "
4156   operands[2] = gen_highpart (SImode, operands[0]);
4157   operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4158                                    operands[1]);
4159   operands[0] = gen_lowpart (SImode, operands[0]);
4160   operands[1] = gen_lowpart (SImode, operands[1]);
4161   "
4162 )
4163
4164 (define_split
4165   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4166         (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4167   "TARGET_EITHER && reload_completed"
4168   [(set (match_dup 0) (match_dup 1))
4169    (set (match_dup 2) (match_dup 3))]
4170   "
4171   operands[2] = gen_highpart (SImode, operands[0]);
4172   operands[3] = gen_highpart (SImode, operands[1]);
4173   operands[0] = gen_lowpart (SImode, operands[0]);
4174   operands[1] = gen_lowpart (SImode, operands[1]);
4175
4176   /* Handle a partial overlap.  */
4177   if (rtx_equal_p (operands[0], operands[3]))
4178     {
4179       rtx tmp0 = operands[0];
4180       rtx tmp1 = operands[1];
4181
4182       operands[0] = operands[2];
4183       operands[1] = operands[3];
4184       operands[2] = tmp0;
4185       operands[3] = tmp1;
4186     }
4187   "
4188 )
4189
4190 ;; We can't actually do base+index doubleword loads if the index and
4191 ;; destination overlap.  Split here so that we at least have chance to
4192 ;; schedule.
4193 (define_split
4194   [(set (match_operand:DI 0 "s_register_operand" "")
4195         (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4196                          (match_operand:SI 2 "s_register_operand" ""))))]
4197   "TARGET_LDRD
4198   && reg_overlap_mentioned_p (operands[0], operands[1])
4199   && reg_overlap_mentioned_p (operands[0], operands[2])"
4200   [(set (match_dup 4)
4201         (plus:SI (match_dup 1)
4202                  (match_dup 2)))
4203    (set (match_dup 0)
4204         (mem:DI (match_dup 4)))]
4205   "
4206   operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4207   "
4208 )
4209
4210 ;;; ??? This should have alternatives for constants.
4211 ;;; ??? This was originally identical to the movdf_insn pattern.
4212 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4213 ;;; thumb_reorg with a memory reference.
4214 (define_insn "*thumb_movdi_insn"
4215   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4216         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
4217   "TARGET_THUMB
4218    && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4219    && (   register_operand (operands[0], DImode)
4220        || register_operand (operands[1], DImode))"
4221   "*
4222   {
4223   switch (which_alternative)
4224     {
4225     default:
4226     case 0:
4227       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4228         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
4229       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
4230     case 1:
4231       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4232     case 2:
4233       operands[1] = GEN_INT (- INTVAL (operands[1]));
4234       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4235     case 3:
4236       return \"ldmia\\t%1, {%0, %H0}\";
4237     case 4:
4238       return \"stmia\\t%0, {%1, %H1}\";
4239     case 5:
4240       return thumb_load_double_from_address (operands);
4241     case 6:
4242       operands[2] = gen_rtx_MEM (SImode,
4243                              plus_constant (XEXP (operands[0], 0), 4));
4244       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4245       return \"\";
4246     case 7:
4247       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4248         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4249       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4250     }
4251   }"
4252   [(set_attr "length" "4,4,6,2,2,6,4,4")
4253    (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4254    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4255 )
4256
4257 (define_expand "movsi"
4258   [(set (match_operand:SI 0 "general_operand" "")
4259         (match_operand:SI 1 "general_operand" ""))]
4260   "TARGET_EITHER"
4261   "
4262   if (TARGET_ARM)
4263     {
4264       /* Everything except mem = const or mem = mem can be done easily.  */
4265       if (GET_CODE (operands[0]) == MEM)
4266         operands[1] = force_reg (SImode, operands[1]);
4267       if (arm_general_register_operand (operands[0], SImode)
4268           && GET_CODE (operands[1]) == CONST_INT
4269           && !(const_ok_for_arm (INTVAL (operands[1]))
4270                || const_ok_for_arm (~INTVAL (operands[1]))))
4271         {
4272            arm_split_constant (SET, SImode, NULL_RTX,
4273                                INTVAL (operands[1]), operands[0], NULL_RTX,
4274                                optimize && !no_new_pseudos);
4275           DONE;
4276         }
4277     }
4278   else /* TARGET_THUMB....  */
4279     {
4280       if (!no_new_pseudos)
4281         {
4282           if (GET_CODE (operands[0]) != REG)
4283             operands[1] = force_reg (SImode, operands[1]);
4284         }
4285     }
4286
4287   /* Recognize the case where operand[1] is a reference to thread-local
4288      data and load its address to a register.  */
4289   if (arm_tls_referenced_p (operands[1]))
4290     {
4291       rtx tmp = operands[1];
4292       rtx addend = NULL;
4293
4294       if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
4295         {
4296           addend = XEXP (XEXP (tmp, 0), 1);
4297           tmp = XEXP (XEXP (tmp, 0), 0);
4298         }
4299
4300       gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
4301       gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
4302
4303       tmp = legitimize_tls_address (tmp, no_new_pseudos ? operands[0] : 0);
4304       if (addend)
4305         {
4306           tmp = gen_rtx_PLUS (SImode, tmp, addend);
4307           tmp = force_operand (tmp, operands[0]);
4308         }
4309       operands[1] = tmp;
4310     }
4311   else if (flag_pic
4312            && (CONSTANT_P (operands[1])
4313                || symbol_mentioned_p (operands[1])
4314                || label_mentioned_p (operands[1])))
4315       operands[1] = legitimize_pic_address (operands[1], SImode,
4316                                             (no_new_pseudos ? operands[0] : 0));
4317   "
4318 )
4319
4320 (define_insn "*arm_movsi_insn"
4321   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4322         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
4323   "TARGET_ARM && ! TARGET_IWMMXT
4324    && !(TARGET_HARD_FLOAT && TARGET_VFP)
4325    && (   register_operand (operands[0], SImode)
4326        || register_operand (operands[1], SImode))"
4327   "@
4328    mov%?\\t%0, %1
4329    mvn%?\\t%0, #%B1
4330    ldr%?\\t%0, %1
4331    str%?\\t%1, %0"
4332   [(set_attr "type" "*,*,load1,store1")
4333    (set_attr "predicable" "yes")
4334    (set_attr "pool_range" "*,*,4096,*")
4335    (set_attr "neg_pool_range" "*,*,4084,*")]
4336 )
4337
4338 (define_split
4339   [(set (match_operand:SI 0 "arm_general_register_operand" "")
4340         (match_operand:SI 1 "const_int_operand" ""))]
4341   "TARGET_ARM
4342   && (!(const_ok_for_arm (INTVAL (operands[1]))
4343         || const_ok_for_arm (~INTVAL (operands[1]))))"
4344   [(clobber (const_int 0))]
4345   "
4346   arm_split_constant (SET, SImode, NULL_RTX, 
4347                       INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4348   DONE;
4349   "
4350 )
4351
4352 (define_insn "*thumb_movsi_insn"
4353   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4354         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4355   "TARGET_THUMB
4356    && (   register_operand (operands[0], SImode) 
4357        || register_operand (operands[1], SImode))"
4358   "@
4359    mov  %0, %1
4360    mov  %0, %1
4361    #
4362    #
4363    ldmia\\t%1, {%0}
4364    stmia\\t%0, {%1}
4365    ldr\\t%0, %1
4366    str\\t%1, %0
4367    mov\\t%0, %1"
4368   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4369    (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4370    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4371 )
4372
4373 (define_split 
4374   [(set (match_operand:SI 0 "register_operand" "")
4375         (match_operand:SI 1 "const_int_operand" ""))]
4376   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4377   [(set (match_dup 0) (match_dup 1))
4378    (set (match_dup 0) (neg:SI (match_dup 0)))]
4379   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4380 )
4381
4382 (define_split 
4383   [(set (match_operand:SI 0 "register_operand" "")
4384         (match_operand:SI 1 "const_int_operand" ""))]
4385   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4386   [(set (match_dup 0) (match_dup 1))
4387    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4388   "
4389   {
4390     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4391     unsigned HOST_WIDE_INT mask = 0xff;
4392     int i;
4393     
4394     for (i = 0; i < 25; i++)
4395       if ((val & (mask << i)) == val)
4396         break;
4397
4398     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4399     if (i == 0)
4400       FAIL;
4401
4402     operands[1] = GEN_INT (val >> i);
4403     operands[2] = GEN_INT (i);
4404   }"
4405 )
4406
4407 ;; When generating pic, we need to load the symbol offset into a register.
4408 ;; So that the optimizer does not confuse this with a normal symbol load
4409 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
4410 ;; since that is the only type of relocation we can use.
4411
4412 ;; The rather odd constraints on the following are to force reload to leave
4413 ;; the insn alone, and to force the minipool generation pass to then move
4414 ;; the GOT symbol to memory.
4415
4416 (define_insn "pic_load_addr_arm"
4417   [(set (match_operand:SI 0 "s_register_operand" "=r")
4418         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4419   "TARGET_ARM && flag_pic"
4420   "ldr%?\\t%0, %1"
4421   [(set_attr "type" "load1")
4422    (set (attr "pool_range")     (const_int 4096))
4423    (set (attr "neg_pool_range") (const_int 4084))]
4424 )
4425
4426 (define_insn "pic_load_addr_thumb"
4427   [(set (match_operand:SI 0 "s_register_operand" "=l")
4428         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4429   "TARGET_THUMB && flag_pic"
4430   "ldr\\t%0, %1"
4431   [(set_attr "type" "load1")
4432    (set (attr "pool_range") (const_int 1024))]
4433 )
4434
4435 ;; This variant is used for AOF assembly, since it needs to mention the
4436 ;; pic register in the rtl.
4437 (define_expand "pic_load_addr_based"
4438   [(set (match_operand:SI 0 "s_register_operand" "")
4439         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4440   "TARGET_ARM && flag_pic"
4441   "operands[2] = pic_offset_table_rtx;"
4442 )
4443
4444 (define_insn "*pic_load_addr_based_insn"
4445   [(set (match_operand:SI 0 "s_register_operand" "=r")
4446         (unspec:SI [(match_operand 1 "" "")
4447                     (match_operand 2 "s_register_operand" "r")]
4448                    UNSPEC_PIC_SYM))]
4449   "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4450   "*
4451 #ifdef AOF_ASSEMBLER
4452   operands[1] = aof_pic_entry (operands[1]);
4453 #endif
4454   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4455   return \"\";
4456   "
4457   [(set_attr "type" "load1")
4458    (set (attr "pool_range")
4459         (if_then_else (eq_attr "is_thumb" "yes")
4460                       (const_int 1024)
4461                       (const_int 4096)))
4462    (set (attr "neg_pool_range")
4463         (if_then_else (eq_attr "is_thumb" "yes")
4464                       (const_int 0)
4465                       (const_int 4084)))]
4466 )
4467
4468 (define_insn "pic_add_dot_plus_four"
4469   [(set (match_operand:SI 0 "register_operand" "=r")
4470         (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "0")
4471                              (const (plus:SI (pc) (const_int 4))))]
4472                    UNSPEC_PIC_BASE))
4473    (use (match_operand 2 "" ""))]
4474   "TARGET_THUMB"
4475   "*
4476   (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4477                                      INTVAL (operands[2]));
4478   return \"add\\t%0, %|pc\";
4479   "
4480   [(set_attr "length" "2")]
4481 )
4482
4483 (define_insn "pic_add_dot_plus_eight"
4484   [(set (match_operand:SI 0 "register_operand" "=r")
4485         (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
4486                              (const (plus:SI (pc) (const_int 8))))]
4487                    UNSPEC_PIC_BASE))
4488    (use (match_operand 2 "" ""))]
4489   "TARGET_ARM"
4490   "*
4491     (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4492                                        INTVAL (operands[2]));
4493     return \"add%?\\t%0, %|pc, %1\";
4494   "
4495   [(set_attr "predicable" "yes")]
4496 )
4497
4498 (define_insn "tls_load_dot_plus_eight"
4499   [(set (match_operand:SI 0 "register_operand" "+r")
4500         (mem:SI (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
4501                                      (const (plus:SI (pc) (const_int 8))))]
4502                            UNSPEC_PIC_BASE)))
4503    (use (match_operand 2 "" ""))]
4504   "TARGET_ARM"
4505   "*
4506     (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4507                                        INTVAL (operands[2]));
4508     return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
4509   "
4510   [(set_attr "predicable" "yes")]
4511 )
4512
4513 ;; PIC references to local variables can generate pic_add_dot_plus_eight
4514 ;; followed by a load.  These sequences can be crunched down to
4515 ;; tls_load_dot_plus_eight by a peephole.
4516
4517 (define_peephole2
4518   [(parallel [(set (match_operand:SI 0 "register_operand" "")
4519                    (unspec:SI [(plus:SI (match_operand:SI 3 "register_operand" "")
4520                                         (const (plus:SI (pc) (const_int 8))))]
4521                               UNSPEC_PIC_BASE))
4522               (use (label_ref (match_operand 1 "" "")))])
4523    (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
4524   "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
4525   [(parallel [(set (match_dup 2)
4526                    (mem:SI (unspec:SI [(plus:SI (match_dup 3)
4527                                                 (const (plus:SI (pc) (const_int 8))))]
4528                                       UNSPEC_PIC_BASE)))
4529               (use (label_ref (match_dup 1)))])]
4530   ""
4531 )
4532
4533 (define_expand "builtin_setjmp_receiver"
4534   [(label_ref (match_operand 0 "" ""))]
4535   "flag_pic"
4536   "
4537 {
4538   /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4539      register.  */
4540   arm_load_pic_register (3);
4541   DONE;
4542 }")
4543
4544 ;; If copying one reg to another we can set the condition codes according to
4545 ;; its value.  Such a move is common after a return from subroutine and the
4546 ;; result is being tested against zero.
4547
4548 (define_insn "*movsi_compare0"
4549   [(set (reg:CC CC_REGNUM)
4550         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4551                     (const_int 0)))
4552    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4553         (match_dup 1))]
4554   "TARGET_ARM"
4555   "@
4556    cmp%?\\t%0, #0
4557    sub%?s\\t%0, %1, #0"
4558   [(set_attr "conds" "set")]
4559 )
4560
4561 ;; Subroutine to store a half word from a register into memory.
4562 ;; Operand 0 is the source register (HImode)
4563 ;; Operand 1 is the destination address in a register (SImode)
4564
4565 ;; In both this routine and the next, we must be careful not to spill
4566 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4567 ;; can generate unrecognizable rtl.
4568
4569 (define_expand "storehi"
4570   [;; store the low byte
4571    (set (match_operand 1 "" "") (match_dup 3))
4572    ;; extract the high byte
4573    (set (match_dup 2)
4574         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4575    ;; store the high byte
4576    (set (match_dup 4) (match_dup 5))]
4577   "TARGET_ARM"
4578   "
4579   {
4580     rtx op1 = operands[1];
4581     rtx addr = XEXP (op1, 0);
4582     enum rtx_code code = GET_CODE (addr);
4583
4584     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4585         || code == MINUS)
4586       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4587
4588     operands[4] = adjust_address (op1, QImode, 1);
4589     operands[1] = adjust_address (operands[1], QImode, 0);
4590     operands[3] = gen_lowpart (QImode, operands[0]);
4591     operands[0] = gen_lowpart (SImode, operands[0]);
4592     operands[2] = gen_reg_rtx (SImode);
4593     operands[5] = gen_lowpart (QImode, operands[2]);
4594   }"
4595 )
4596
4597 (define_expand "storehi_bigend"
4598   [(set (match_dup 4) (match_dup 3))
4599    (set (match_dup 2)
4600         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4601    (set (match_operand 1 "" "") (match_dup 5))]
4602   "TARGET_ARM"
4603   "
4604   {
4605     rtx op1 = operands[1];
4606     rtx addr = XEXP (op1, 0);
4607     enum rtx_code code = GET_CODE (addr);
4608
4609     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4610         || code == MINUS)
4611       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4612
4613     operands[4] = adjust_address (op1, QImode, 1);
4614     operands[1] = adjust_address (operands[1], QImode, 0);
4615     operands[3] = gen_lowpart (QImode, operands[0]);
4616     operands[0] = gen_lowpart (SImode, operands[0]);
4617     operands[2] = gen_reg_rtx (SImode);
4618     operands[5] = gen_lowpart (QImode, operands[2]);
4619   }"
4620 )
4621
4622 ;; Subroutine to store a half word integer constant into memory.
4623 (define_expand "storeinthi"
4624   [(set (match_operand 0 "" "")
4625         (match_operand 1 "" ""))
4626    (set (match_dup 3) (match_dup 2))]
4627   "TARGET_ARM"
4628   "
4629   {
4630     HOST_WIDE_INT value = INTVAL (operands[1]);
4631     rtx addr = XEXP (operands[0], 0);
4632     rtx op0 = operands[0];
4633     enum rtx_code code = GET_CODE (addr);
4634
4635     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4636         || code == MINUS)
4637       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4638
4639     operands[1] = gen_reg_rtx (SImode);
4640     if (BYTES_BIG_ENDIAN)
4641       {
4642         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4643         if ((value & 255) == ((value >> 8) & 255))
4644           operands[2] = operands[1];
4645         else
4646           {
4647             operands[2] = gen_reg_rtx (SImode);
4648             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4649           }
4650       }
4651     else
4652       {
4653         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4654         if ((value & 255) == ((value >> 8) & 255))
4655           operands[2] = operands[1];
4656         else
4657           {
4658             operands[2] = gen_reg_rtx (SImode);
4659             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4660           }
4661       }
4662
4663     operands[3] = adjust_address (op0, QImode, 1);
4664     operands[0] = adjust_address (operands[0], QImode, 0);
4665     operands[2] = gen_lowpart (QImode, operands[2]);
4666     operands[1] = gen_lowpart (QImode, operands[1]);
4667   }"
4668 )
4669
4670 (define_expand "storehi_single_op"
4671   [(set (match_operand:HI 0 "memory_operand" "")
4672         (match_operand:HI 1 "general_operand" ""))]
4673   "TARGET_ARM && arm_arch4"
4674   "
4675   if (!s_register_operand (operands[1], HImode))
4676     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4677   "
4678 )
4679
4680 (define_expand "movhi"
4681   [(set (match_operand:HI 0 "general_operand" "")
4682         (match_operand:HI 1 "general_operand" ""))]
4683   "TARGET_EITHER"
4684   "
4685   if (TARGET_ARM)
4686     {
4687       if (!no_new_pseudos)
4688         {
4689           if (GET_CODE (operands[0]) == MEM)
4690             {
4691               if (arm_arch4)
4692                 {
4693                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4694                   DONE;
4695                 }
4696               if (GET_CODE (operands[1]) == CONST_INT)
4697                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4698               else
4699                 {
4700                   if (GET_CODE (operands[1]) == MEM)
4701                     operands[1] = force_reg (HImode, operands[1]);
4702                   if (BYTES_BIG_ENDIAN)
4703                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4704                   else
4705                    emit_insn (gen_storehi (operands[1], operands[0]));
4706                 }
4707               DONE;
4708             }
4709           /* Sign extend a constant, and keep it in an SImode reg.  */
4710           else if (GET_CODE (operands[1]) == CONST_INT)
4711             {
4712               rtx reg = gen_reg_rtx (SImode);
4713               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4714
4715               /* If the constant is already valid, leave it alone.  */
4716               if (!const_ok_for_arm (val))
4717                 {
4718                   /* If setting all the top bits will make the constant 
4719                      loadable in a single instruction, then set them.  
4720                      Otherwise, sign extend the number.  */
4721
4722                   if (const_ok_for_arm (~(val | ~0xffff)))
4723                     val |= ~0xffff;
4724                   else if (val & 0x8000)
4725                     val |= ~0xffff;
4726                 }
4727
4728               emit_insn (gen_movsi (reg, GEN_INT (val)));
4729               operands[1] = gen_lowpart (HImode, reg);
4730             }
4731           else if (arm_arch4 && optimize && !no_new_pseudos
4732                    && GET_CODE (operands[1]) == MEM)
4733             {
4734               rtx reg = gen_reg_rtx (SImode);
4735
4736               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4737               operands[1] = gen_lowpart (HImode, reg);
4738             }
4739           else if (!arm_arch4)
4740             {
4741               if (GET_CODE (operands[1]) == MEM)
4742                 {
4743                   rtx base;
4744                   rtx offset = const0_rtx;
4745                   rtx reg = gen_reg_rtx (SImode);
4746
4747                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4748                        || (GET_CODE (base) == PLUS
4749                            && (GET_CODE (offset = XEXP (base, 1))
4750                                == CONST_INT)
4751                            && ((INTVAL(offset) & 1) != 1)
4752                            && GET_CODE (base = XEXP (base, 0)) == REG))
4753                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4754                     {
4755                       rtx new;
4756
4757                       new = widen_memory_access (operands[1], SImode,
4758                                                  ((INTVAL (offset) & ~3)
4759                                                   - INTVAL (offset)));
4760                       emit_insn (gen_movsi (reg, new));
4761                       if (((INTVAL (offset) & 2) != 0)
4762                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4763                         {
4764                           rtx reg2 = gen_reg_rtx (SImode);
4765
4766                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4767                           reg = reg2;
4768                         }
4769                     }
4770                   else
4771                     emit_insn (gen_movhi_bytes (reg, operands[1]));
4772
4773                   operands[1] = gen_lowpart (HImode, reg);
4774                }
4775            }
4776         }
4777       /* Handle loading a large integer during reload.  */
4778       else if (GET_CODE (operands[1]) == CONST_INT
4779                && !const_ok_for_arm (INTVAL (operands[1]))
4780                && !const_ok_for_arm (~INTVAL (operands[1])))
4781         {
4782           /* Writing a constant to memory needs a scratch, which should
4783              be handled with SECONDARY_RELOADs.  */
4784           gcc_assert (GET_CODE (operands[0]) == REG);
4785
4786           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4787           emit_insn (gen_movsi (operands[0], operands[1]));
4788           DONE;
4789        }
4790     }
4791   else /* TARGET_THUMB */
4792     {
4793       if (!no_new_pseudos)
4794         {
4795           if (GET_CODE (operands[1]) == CONST_INT)
4796             {
4797               rtx reg = gen_reg_rtx (SImode);
4798
4799               emit_insn (gen_movsi (reg, operands[1]));
4800               operands[1] = gen_lowpart (HImode, reg);
4801             }
4802
4803           /* ??? We shouldn't really get invalid addresses here, but this can
4804              happen if we are passed a SP (never OK for HImode/QImode) or 
4805              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4806              HImode/QImode) relative address.  */
4807           /* ??? This should perhaps be fixed elsewhere, for instance, in
4808              fixup_stack_1, by checking for other kinds of invalid addresses,
4809              e.g. a bare reference to a virtual register.  This may confuse the
4810              alpha though, which must handle this case differently.  */
4811           if (GET_CODE (operands[0]) == MEM
4812               && !memory_address_p (GET_MODE (operands[0]),
4813                                     XEXP (operands[0], 0)))
4814             operands[0]
4815               = replace_equiv_address (operands[0],
4816                                        copy_to_reg (XEXP (operands[0], 0)));
4817    
4818           if (GET_CODE (operands[1]) == MEM
4819               && !memory_address_p (GET_MODE (operands[1]),
4820                                     XEXP (operands[1], 0)))
4821             operands[1]
4822               = replace_equiv_address (operands[1],
4823                                        copy_to_reg (XEXP (operands[1], 0)));
4824
4825           if (GET_CODE (operands[1]) == MEM && optimize > 0)
4826             {
4827               rtx reg = gen_reg_rtx (SImode);
4828
4829               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4830               operands[1] = gen_lowpart (HImode, reg);
4831             }
4832
4833           if (GET_CODE (operands[0]) == MEM)
4834             operands[1] = force_reg (HImode, operands[1]);
4835         }
4836       else if (GET_CODE (operands[1]) == CONST_INT
4837                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4838         {
4839           /* Handle loading a large integer during reload.  */
4840
4841           /* Writing a constant to memory needs a scratch, which should
4842              be handled with SECONDARY_RELOADs.  */
4843           gcc_assert (GET_CODE (operands[0]) == REG);
4844
4845           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4846           emit_insn (gen_movsi (operands[0], operands[1]));
4847           DONE;
4848         }
4849     }
4850   "
4851 )
4852
4853 (define_insn "*thumb_movhi_insn"
4854   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4855         (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
4856   "TARGET_THUMB
4857    && (   register_operand (operands[0], HImode)
4858        || register_operand (operands[1], HImode))"
4859   "*
4860   switch (which_alternative)
4861     {
4862     case 0: return \"add        %0, %1, #0\";
4863     case 2: return \"strh       %1, %0\";
4864     case 3: return \"mov        %0, %1\";
4865     case 4: return \"mov        %0, %1\";
4866     case 5: return \"mov        %0, %1\";
4867     default: gcc_unreachable ();
4868     case 1:
4869       /* The stack pointer can end up being taken as an index register.
4870           Catch this case here and deal with it.  */
4871       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4872           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4873           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4874         {
4875           rtx ops[2];
4876           ops[0] = operands[0];
4877           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4878       
4879           output_asm_insn (\"mov        %0, %1\", ops);
4880
4881           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4882     
4883         }
4884       return \"ldrh     %0, %1\";
4885     }"
4886   [(set_attr "length" "2,4,2,2,2,2")
4887    (set_attr "type" "*,load1,store1,*,*,*")]
4888 )
4889
4890
4891 (define_expand "movhi_bytes"
4892   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4893    (set (match_dup 3)
4894         (zero_extend:SI (match_dup 6)))
4895    (set (match_operand:SI 0 "" "")
4896          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4897   "TARGET_ARM"
4898   "
4899   {
4900     rtx mem1, mem2;
4901     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4902
4903     mem1 = change_address (operands[1], QImode, addr);
4904     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
4905     operands[0] = gen_lowpart (SImode, operands[0]);
4906     operands[1] = mem1;
4907     operands[2] = gen_reg_rtx (SImode);
4908     operands[3] = gen_reg_rtx (SImode);
4909     operands[6] = mem2;
4910
4911     if (BYTES_BIG_ENDIAN)
4912       {
4913         operands[4] = operands[2];
4914         operands[5] = operands[3];
4915       }
4916     else
4917       {
4918         operands[4] = operands[3];
4919         operands[5] = operands[2];
4920       }
4921   }"
4922 )
4923
4924 (define_expand "movhi_bigend"
4925   [(set (match_dup 2)
4926         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4927                    (const_int 16)))
4928    (set (match_dup 3)
4929         (ashiftrt:SI (match_dup 2) (const_int 16)))
4930    (set (match_operand:HI 0 "s_register_operand" "")
4931         (match_dup 4))]
4932   "TARGET_ARM"
4933   "
4934   operands[2] = gen_reg_rtx (SImode);
4935   operands[3] = gen_reg_rtx (SImode);
4936   operands[4] = gen_lowpart (HImode, operands[3]);
4937   "
4938 )
4939
4940 ;; Pattern to recognize insn generated default case above
4941 (define_insn "*movhi_insn_arch4"
4942   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4943         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4944   "TARGET_ARM
4945    && arm_arch4
4946    && (GET_CODE (operands[1]) != CONST_INT
4947        || const_ok_for_arm (INTVAL (operands[1]))
4948        || const_ok_for_arm (~INTVAL (operands[1])))"
4949   "@
4950    mov%?\\t%0, %1\\t%@ movhi
4951    mvn%?\\t%0, #%B1\\t%@ movhi
4952    str%?h\\t%1, %0\\t%@ movhi
4953    ldr%?h\\t%0, %1\\t%@ movhi"
4954   [(set_attr "type" "*,*,store1,load1")
4955    (set_attr "predicable" "yes")
4956    (set_attr "pool_range" "*,*,*,256")
4957    (set_attr "neg_pool_range" "*,*,*,244")]
4958 )
4959
4960 (define_insn "*movhi_bytes"
4961   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4962         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4963   "TARGET_ARM"
4964   "@
4965    mov%?\\t%0, %1\\t%@ movhi
4966    mvn%?\\t%0, #%B1\\t%@ movhi"
4967   [(set_attr "predicable" "yes")]
4968 )
4969
4970 (define_expand "thumb_movhi_clobber"
4971   [(set (match_operand:HI     0 "memory_operand"   "")
4972         (match_operand:HI     1 "register_operand" ""))
4973    (clobber (match_operand:DI 2 "register_operand" ""))]
4974   "TARGET_THUMB"
4975   "
4976   if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
4977       && REGNO (operands[1]) <= LAST_LO_REGNUM)
4978     {
4979       emit_insn (gen_movhi (operands[0], operands[1]));
4980       DONE;
4981     }
4982   /* XXX Fixme, need to handle other cases here as well.  */
4983   gcc_unreachable ();
4984   "
4985 )
4986         
4987 ;; We use a DImode scratch because we may occasionally need an additional
4988 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4989 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4990 (define_expand "reload_outhi"
4991   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4992               (match_operand:HI 1 "s_register_operand"        "r")
4993               (match_operand:DI 2 "s_register_operand"        "=&l")])]
4994   "TARGET_EITHER"
4995   "if (TARGET_ARM)
4996      arm_reload_out_hi (operands);
4997    else
4998      thumb_reload_out_hi (operands);
4999   DONE;
5000   "
5001 )
5002
5003 (define_expand "reload_inhi"
5004   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
5005               (match_operand:HI 1 "arm_reload_memory_operand" "o")
5006               (match_operand:DI 2 "s_register_operand" "=&r")])]
5007   "TARGET_EITHER"
5008   "
5009   if (TARGET_ARM)
5010     arm_reload_in_hi (operands);
5011   else
5012     thumb_reload_out_hi (operands);
5013   DONE;
5014 ")
5015
5016 (define_expand "movqi"
5017   [(set (match_operand:QI 0 "general_operand" "")
5018         (match_operand:QI 1 "general_operand" ""))]
5019   "TARGET_EITHER"
5020   "
5021   /* Everything except mem = const or mem = mem can be done easily */
5022
5023   if (!no_new_pseudos)
5024     {
5025       if (GET_CODE (operands[1]) == CONST_INT)
5026         {
5027           rtx reg = gen_reg_rtx (SImode);
5028
5029           emit_insn (gen_movsi (reg, operands[1]));
5030           operands[1] = gen_lowpart (QImode, reg);
5031         }
5032
5033       if (TARGET_THUMB)
5034         {
5035           /* ??? We shouldn't really get invalid addresses here, but this can
5036              happen if we are passed a SP (never OK for HImode/QImode) or
5037              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
5038              HImode/QImode) relative address.  */
5039           /* ??? This should perhaps be fixed elsewhere, for instance, in
5040              fixup_stack_1, by checking for other kinds of invalid addresses,
5041              e.g. a bare reference to a virtual register.  This may confuse the
5042              alpha though, which must handle this case differently.  */
5043           if (GET_CODE (operands[0]) == MEM
5044               && !memory_address_p (GET_MODE (operands[0]),
5045                                      XEXP (operands[0], 0)))
5046             operands[0]
5047               = replace_equiv_address (operands[0],
5048                                        copy_to_reg (XEXP (operands[0], 0)));
5049           if (GET_CODE (operands[1]) == MEM
5050               && !memory_address_p (GET_MODE (operands[1]),
5051                                     XEXP (operands[1], 0)))
5052              operands[1]
5053                = replace_equiv_address (operands[1],
5054                                         copy_to_reg (XEXP (operands[1], 0)));
5055         }
5056
5057       if (GET_CODE (operands[1]) == MEM && optimize > 0)
5058         {
5059           rtx reg = gen_reg_rtx (SImode);
5060
5061           emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5062           operands[1] = gen_lowpart (QImode, reg);
5063         }
5064
5065       if (GET_CODE (operands[0]) == MEM)
5066         operands[1] = force_reg (QImode, operands[1]);
5067     }
5068   else if (TARGET_THUMB
5069            && GET_CODE (operands[1]) == CONST_INT
5070            && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
5071     {
5072       /* Handle loading a large integer during reload.  */
5073
5074       /* Writing a constant to memory needs a scratch, which should
5075          be handled with SECONDARY_RELOADs.  */
5076       gcc_assert (GET_CODE (operands[0]) == REG);
5077
5078       operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5079       emit_insn (gen_movsi (operands[0], operands[1]));
5080       DONE;
5081     }
5082   "
5083 )
5084
5085
5086 (define_insn "*arm_movqi_insn"
5087   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5088         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5089   "TARGET_ARM
5090    && (   register_operand (operands[0], QImode)
5091        || register_operand (operands[1], QImode))"
5092   "@
5093    mov%?\\t%0, %1
5094    mvn%?\\t%0, #%B1
5095    ldr%?b\\t%0, %1
5096    str%?b\\t%1, %0"
5097   [(set_attr "type" "*,*,load1,store1")
5098    (set_attr "predicable" "yes")]
5099 )
5100
5101 (define_insn "*thumb_movqi_insn"
5102   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5103         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
5104   "TARGET_THUMB
5105    && (   register_operand (operands[0], QImode)
5106        || register_operand (operands[1], QImode))"
5107   "@
5108    add\\t%0, %1, #0
5109    ldrb\\t%0, %1
5110    strb\\t%1, %0
5111    mov\\t%0, %1
5112    mov\\t%0, %1
5113    mov\\t%0, %1"
5114   [(set_attr "length" "2")
5115    (set_attr "type" "*,load1,store1,*,*,*")
5116    (set_attr "pool_range" "*,32,*,*,*,*")]
5117 )
5118
5119 (define_expand "movsf"
5120   [(set (match_operand:SF 0 "general_operand" "")
5121         (match_operand:SF 1 "general_operand" ""))]
5122   "TARGET_EITHER"
5123   "
5124   if (TARGET_ARM)
5125     {
5126       if (GET_CODE (operands[0]) == MEM)
5127         operands[1] = force_reg (SFmode, operands[1]);
5128     }
5129   else /* TARGET_THUMB */
5130     {
5131       if (!no_new_pseudos)
5132         {
5133            if (GET_CODE (operands[0]) != REG)
5134              operands[1] = force_reg (SFmode, operands[1]);
5135         }
5136     }
5137   "
5138 )
5139
5140 (define_split
5141   [(set (match_operand:SF 0 "nonimmediate_operand" "")
5142         (match_operand:SF 1 "immediate_operand" ""))]
5143   "TARGET_ARM
5144    && !(TARGET_HARD_FLOAT && TARGET_FPA)
5145    && reload_completed
5146    && GET_CODE (operands[1]) == CONST_DOUBLE"
5147   [(set (match_dup 2) (match_dup 3))]
5148   "
5149   operands[2] = gen_lowpart (SImode, operands[0]);
5150   operands[3] = gen_lowpart (SImode, operands[1]);
5151   if (operands[2] == 0 || operands[3] == 0)
5152     FAIL;
5153   "
5154 )
5155
5156 (define_insn "*arm_movsf_soft_insn"
5157   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5158         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
5159   "TARGET_ARM
5160    && TARGET_SOFT_FLOAT
5161    && (GET_CODE (operands[0]) != MEM
5162        || register_operand (operands[1], SFmode))"
5163   "@
5164    mov%?\\t%0, %1
5165    ldr%?\\t%0, %1\\t%@ float
5166    str%?\\t%1, %0\\t%@ float"
5167   [(set_attr "length" "4,4,4")
5168    (set_attr "predicable" "yes")
5169    (set_attr "type" "*,load1,store1")
5170    (set_attr "pool_range" "*,4096,*")
5171    (set_attr "neg_pool_range" "*,4084,*")]
5172 )
5173
5174 ;;; ??? This should have alternatives for constants.
5175 (define_insn "*thumb_movsf_insn"
5176   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5177         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5178   "TARGET_THUMB
5179    && (   register_operand (operands[0], SFmode) 
5180        || register_operand (operands[1], SFmode))"
5181   "@
5182    add\\t%0, %1, #0
5183    ldmia\\t%1, {%0}
5184    stmia\\t%0, {%1}
5185    ldr\\t%0, %1
5186    str\\t%1, %0
5187    mov\\t%0, %1
5188    mov\\t%0, %1"
5189   [(set_attr "length" "2")
5190    (set_attr "type" "*,load1,store1,load1,store1,*,*")
5191    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5192 )
5193
5194 (define_expand "movdf"
5195   [(set (match_operand:DF 0 "general_operand" "")
5196         (match_operand:DF 1 "general_operand" ""))]
5197   "TARGET_EITHER"
5198   "
5199   if (TARGET_ARM)
5200     {
5201       if (GET_CODE (operands[0]) == MEM)
5202         operands[1] = force_reg (DFmode, operands[1]);
5203     }
5204   else /* TARGET_THUMB */
5205     {
5206       if (!no_new_pseudos)
5207         {
5208           if (GET_CODE (operands[0]) != REG)
5209             operands[1] = force_reg (DFmode, operands[1]);
5210         }
5211     }
5212   "
5213 )
5214
5215 ;; Reloading a df mode value stored in integer regs to memory can require a
5216 ;; scratch reg.
5217 (define_expand "reload_outdf"
5218   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5219    (match_operand:DF 1 "s_register_operand" "r")
5220    (match_operand:SI 2 "s_register_operand" "=&r")]
5221   "TARGET_ARM"
5222   "
5223   {
5224     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5225
5226     if (code == REG)
5227       operands[2] = XEXP (operands[0], 0);
5228     else if (code == POST_INC || code == PRE_DEC)
5229       {
5230         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5231         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5232         emit_insn (gen_movdi (operands[0], operands[1]));
5233         DONE;
5234       }
5235     else if (code == PRE_INC)
5236       {
5237         rtx reg = XEXP (XEXP (operands[0], 0), 0);
5238
5239         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5240         operands[2] = reg;
5241       }
5242     else if (code == POST_DEC)
5243       operands[2] = XEXP (XEXP (operands[0], 0), 0);
5244     else
5245       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5246                              XEXP (XEXP (operands[0], 0), 1)));
5247
5248     emit_insn (gen_rtx_SET (VOIDmode,
5249                             replace_equiv_address (operands[0], operands[2]),
5250                             operands[1]));
5251
5252     if (code == POST_DEC)
5253       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5254
5255     DONE;
5256   }"
5257 )
5258
5259 (define_insn "*movdf_soft_insn"
5260   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5261         (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
5262   "TARGET_ARM && TARGET_SOFT_FLOAT
5263   "
5264   "*
5265   switch (which_alternative)
5266     {
5267     case 0:
5268     case 1:
5269     case 2:
5270       return \"#\";
5271     default:
5272       return output_move_double (operands);
5273     }
5274   "
5275   [(set_attr "length" "8,12,16,8,8")
5276    (set_attr "type" "*,*,*,load2,store2")
5277    (set_attr "pool_range" "1020")
5278    (set_attr "neg_pool_range" "1008")]
5279 )
5280
5281 ;;; ??? This should have alternatives for constants.
5282 ;;; ??? This was originally identical to the movdi_insn pattern.
5283 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5284 ;;; thumb_reorg with a memory reference.
5285 (define_insn "*thumb_movdf_insn"
5286   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5287         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5288   "TARGET_THUMB
5289    && (   register_operand (operands[0], DFmode)
5290        || register_operand (operands[1], DFmode))"
5291   "*
5292   switch (which_alternative)
5293     {
5294     default:
5295     case 0:
5296       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5297         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5298       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5299     case 1:
5300       return \"ldmia\\t%1, {%0, %H0}\";
5301     case 2:
5302       return \"stmia\\t%0, {%1, %H1}\";
5303     case 3:
5304       return thumb_load_double_from_address (operands);
5305     case 4:
5306       operands[2] = gen_rtx_MEM (SImode,
5307                                  plus_constant (XEXP (operands[0], 0), 4));
5308       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5309       return \"\";
5310     case 5:
5311       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5312         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5313       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5314     }
5315   "
5316   [(set_attr "length" "4,2,2,6,4,4")
5317    (set_attr "type" "*,load2,store2,load2,store2,*")
5318    (set_attr "pool_range" "*,*,*,1020,*,*")]
5319 )
5320
5321 (define_expand "movxf"
5322   [(set (match_operand:XF 0 "general_operand" "")
5323         (match_operand:XF 1 "general_operand" ""))]
5324   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
5325   "
5326   if (GET_CODE (operands[0]) == MEM)
5327     operands[1] = force_reg (XFmode, operands[1]);
5328   "
5329 )
5330
5331 ;; Vector Moves
5332 (define_expand "movv2si"
5333   [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5334         (match_operand:V2SI 1 "general_operand" ""))]
5335   "TARGET_REALLY_IWMMXT"
5336 {
5337 })
5338
5339 (define_expand "movv4hi"
5340   [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5341         (match_operand:V4HI 1 "general_operand" ""))]
5342   "TARGET_REALLY_IWMMXT"
5343 {
5344 })
5345
5346 (define_expand "movv8qi"
5347   [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5348         (match_operand:V8QI 1 "general_operand" ""))]
5349   "TARGET_REALLY_IWMMXT"
5350 {
5351 })
5352 \f
5353
5354 ;; load- and store-multiple insns
5355 ;; The arm can load/store any set of registers, provided that they are in
5356 ;; ascending order; but that is beyond GCC so stick with what it knows.
5357
5358 (define_expand "load_multiple"
5359   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5360                           (match_operand:SI 1 "" ""))
5361                      (use (match_operand:SI 2 "" ""))])]
5362   "TARGET_ARM"
5363 {
5364   HOST_WIDE_INT offset = 0;
5365
5366   /* Support only fixed point registers.  */
5367   if (GET_CODE (operands[2]) != CONST_INT
5368       || INTVAL (operands[2]) > 14
5369       || INTVAL (operands[2]) < 2
5370       || GET_CODE (operands[1]) != MEM
5371       || GET_CODE (operands[0]) != REG
5372       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5373       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5374     FAIL;
5375
5376   operands[3]
5377     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5378                              force_reg (SImode, XEXP (operands[1], 0)),
5379                              TRUE, FALSE, operands[1], &offset);
5380 })
5381
5382 ;; Load multiple with write-back
5383
5384 (define_insn "*ldmsi_postinc4"
5385   [(match_parallel 0 "load_multiple_operation"
5386     [(set (match_operand:SI 1 "s_register_operand" "=r")
5387           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5388                    (const_int 16)))
5389      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5390           (mem:SI (match_dup 2)))
5391      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5392           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5393      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5394           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5395      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5396           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5397   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5398   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5399   [(set_attr "type" "load4")
5400    (set_attr "predicable" "yes")]
5401 )
5402
5403 (define_insn "*ldmsi_postinc4_thumb"
5404   [(match_parallel 0 "load_multiple_operation"
5405     [(set (match_operand:SI 1 "s_register_operand" "=l")
5406           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5407                    (const_int 16)))
5408      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5409           (mem:SI (match_dup 2)))
5410      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5411           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5412      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5413           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5414      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5415           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5416   "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5417   "ldmia\\t%1!, {%3, %4, %5, %6}"
5418   [(set_attr "type" "load4")]
5419 )
5420
5421 (define_insn "*ldmsi_postinc3"
5422   [(match_parallel 0 "load_multiple_operation"
5423     [(set (match_operand:SI 1 "s_register_operand" "=r")
5424           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5425                    (const_int 12)))
5426      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5427           (mem:SI (match_dup 2)))
5428      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5429           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5430      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5431           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5432   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5433   "ldm%?ia\\t%1!, {%3, %4, %5}"
5434   [(set_attr "type" "load3")
5435    (set_attr "predicable" "yes")]
5436 )
5437
5438 (define_insn "*ldmsi_postinc2"
5439   [(match_parallel 0 "load_multiple_operation"
5440     [(set (match_operand:SI 1 "s_register_operand" "=r")
5441           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5442                    (const_int 8)))
5443      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5444           (mem:SI (match_dup 2)))
5445      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5446           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5447   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5448   "ldm%?ia\\t%1!, {%3, %4}"
5449   [(set_attr "type" "load2")
5450    (set_attr "predicable" "yes")]
5451 )
5452
5453 ;; Ordinary load multiple
5454
5455 (define_insn "*ldmsi4"
5456   [(match_parallel 0 "load_multiple_operation"
5457     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5458           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5459      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5460           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5461      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5462           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5463      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5464           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5465   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5466   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5467   [(set_attr "type" "load4")
5468    (set_attr "predicable" "yes")]
5469 )
5470
5471 (define_insn "*ldmsi3"
5472   [(match_parallel 0 "load_multiple_operation"
5473     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5474           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5475      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5476           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5477      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5478           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5479   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5480   "ldm%?ia\\t%1, {%2, %3, %4}"
5481   [(set_attr "type" "load3")
5482    (set_attr "predicable" "yes")]
5483 )
5484
5485 (define_insn "*ldmsi2"
5486   [(match_parallel 0 "load_multiple_operation"
5487     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5488           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5489      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5490           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5491   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5492   "ldm%?ia\\t%1, {%2, %3}"
5493   [(set_attr "type" "load2")
5494    (set_attr "predicable" "yes")]
5495 )
5496
5497 (define_expand "store_multiple"
5498   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5499                           (match_operand:SI 1 "" ""))
5500                      (use (match_operand:SI 2 "" ""))])]
5501   "TARGET_ARM"
5502 {
5503   HOST_WIDE_INT offset = 0;
5504
5505   /* Support only fixed point registers.  */
5506   if (GET_CODE (operands[2]) != CONST_INT
5507       || INTVAL (operands[2]) > 14
5508       || INTVAL (operands[2]) < 2
5509       || GET_CODE (operands[1]) != REG
5510       || GET_CODE (operands[0]) != MEM
5511       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5512       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5513     FAIL;
5514
5515   operands[3]
5516     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5517                               force_reg (SImode, XEXP (operands[0], 0)),
5518                               TRUE, FALSE, operands[0], &offset);
5519 })
5520
5521 ;; Store multiple with write-back
5522
5523 (define_insn "*stmsi_postinc4"
5524   [(match_parallel 0 "store_multiple_operation"
5525     [(set (match_operand:SI 1 "s_register_operand" "=r")
5526           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5527                    (const_int 16)))
5528      (set (mem:SI (match_dup 2))
5529           (match_operand:SI 3 "arm_hard_register_operand" ""))
5530      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5531           (match_operand:SI 4 "arm_hard_register_operand" ""))
5532      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5533           (match_operand:SI 5 "arm_hard_register_operand" ""))
5534      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5535           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5536   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5537   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5538   [(set_attr "predicable" "yes")
5539    (set_attr "type" "store4")]
5540 )
5541
5542 (define_insn "*stmsi_postinc4_thumb"
5543   [(match_parallel 0 "store_multiple_operation"
5544     [(set (match_operand:SI 1 "s_register_operand" "=l")
5545           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5546                    (const_int 16)))
5547      (set (mem:SI (match_dup 2))
5548           (match_operand:SI 3 "arm_hard_register_operand" ""))
5549      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5550           (match_operand:SI 4 "arm_hard_register_operand" ""))
5551      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5552           (match_operand:SI 5 "arm_hard_register_operand" ""))
5553      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5554           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5555   "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5556   "stmia\\t%1!, {%3, %4, %5, %6}"
5557   [(set_attr "type" "store4")]
5558 )
5559
5560 (define_insn "*stmsi_postinc3"
5561   [(match_parallel 0 "store_multiple_operation"
5562     [(set (match_operand:SI 1 "s_register_operand" "=r")
5563           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5564                    (const_int 12)))
5565      (set (mem:SI (match_dup 2))
5566           (match_operand:SI 3 "arm_hard_register_operand" ""))
5567      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5568           (match_operand:SI 4 "arm_hard_register_operand" ""))
5569      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5570           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5571   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5572   "stm%?ia\\t%1!, {%3, %4, %5}"
5573   [(set_attr "predicable" "yes")
5574    (set_attr "type" "store3")]
5575 )
5576
5577 (define_insn "*stmsi_postinc2"
5578   [(match_parallel 0 "store_multiple_operation"
5579     [(set (match_operand:SI 1 "s_register_operand" "=r")
5580           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5581                    (const_int 8)))
5582      (set (mem:SI (match_dup 2))
5583           (match_operand:SI 3 "arm_hard_register_operand" ""))
5584      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5585           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5586   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5587   "stm%?ia\\t%1!, {%3, %4}"
5588   [(set_attr "predicable" "yes")
5589    (set_attr "type" "store2")]
5590 )
5591
5592 ;; Ordinary store multiple
5593
5594 (define_insn "*stmsi4"
5595   [(match_parallel 0 "store_multiple_operation"
5596     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5597           (match_operand:SI 2 "arm_hard_register_operand" ""))
5598      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5599           (match_operand:SI 3 "arm_hard_register_operand" ""))
5600      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5601           (match_operand:SI 4 "arm_hard_register_operand" ""))
5602      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5603           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5604   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5605   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5606   [(set_attr "predicable" "yes")
5607    (set_attr "type" "store4")]
5608 )
5609
5610 (define_insn "*stmsi3"
5611   [(match_parallel 0 "store_multiple_operation"
5612     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5613           (match_operand:SI 2 "arm_hard_register_operand" ""))
5614      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5615           (match_operand:SI 3 "arm_hard_register_operand" ""))
5616      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5617           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5618   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5619   "stm%?ia\\t%1, {%2, %3, %4}"
5620   [(set_attr "predicable" "yes")
5621    (set_attr "type" "store3")]
5622 )
5623
5624 (define_insn "*stmsi2"
5625   [(match_parallel 0 "store_multiple_operation"
5626     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5627           (match_operand:SI 2 "arm_hard_register_operand" ""))
5628      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5629           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5630   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5631   "stm%?ia\\t%1, {%2, %3}"
5632   [(set_attr "predicable" "yes")
5633    (set_attr "type" "store2")]
5634 )
5635
5636 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5637 ;; We could let this apply for blocks of less than this, but it clobbers so
5638 ;; many registers that there is then probably a better way.
5639
5640 (define_expand "movmemqi"
5641   [(match_operand:BLK 0 "general_operand" "")
5642    (match_operand:BLK 1 "general_operand" "")
5643    (match_operand:SI 2 "const_int_operand" "")
5644    (match_operand:SI 3 "const_int_operand" "")]
5645   "TARGET_EITHER"
5646   "
5647   if (TARGET_ARM)
5648     {
5649       if (arm_gen_movmemqi (operands))
5650         DONE;
5651       FAIL;
5652     }
5653   else /* TARGET_THUMB */
5654     {
5655       if (   INTVAL (operands[3]) != 4
5656           || INTVAL (operands[2]) > 48)
5657         FAIL;
5658
5659       thumb_expand_movmemqi (operands);
5660       DONE;
5661     }
5662   "
5663 )
5664
5665 ;; Thumb block-move insns
5666
5667 (define_insn "movmem12b"
5668   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5669         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5670    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5671         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5672    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5673         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5674    (set (match_operand:SI 0 "register_operand" "=l")
5675         (plus:SI (match_dup 2) (const_int 12)))
5676    (set (match_operand:SI 1 "register_operand" "=l")
5677         (plus:SI (match_dup 3) (const_int 12)))
5678    (clobber (match_scratch:SI 4 "=&l"))
5679    (clobber (match_scratch:SI 5 "=&l"))
5680    (clobber (match_scratch:SI 6 "=&l"))]
5681   "TARGET_THUMB"
5682   "* return thumb_output_move_mem_multiple (3, operands);"
5683   [(set_attr "length" "4")
5684    ; This isn't entirely accurate...  It loads as well, but in terms of
5685    ; scheduling the following insn it is better to consider it as a store
5686    (set_attr "type" "store3")]
5687 )
5688
5689 (define_insn "movmem8b"
5690   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5691         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5692    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5693         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5694    (set (match_operand:SI 0 "register_operand" "=l")
5695         (plus:SI (match_dup 2) (const_int 8)))
5696    (set (match_operand:SI 1 "register_operand" "=l")
5697         (plus:SI (match_dup 3) (const_int 8)))
5698    (clobber (match_scratch:SI 4 "=&l"))
5699    (clobber (match_scratch:SI 5 "=&l"))]
5700   "TARGET_THUMB"
5701   "* return thumb_output_move_mem_multiple (2, operands);"
5702   [(set_attr "length" "4")
5703    ; This isn't entirely accurate...  It loads as well, but in terms of
5704    ; scheduling the following insn it is better to consider it as a store
5705    (set_attr "type" "store2")]
5706 )
5707
5708 \f
5709
5710 ;; Compare & branch insns
5711 ;; The range calculations are based as follows:
5712 ;; For forward branches, the address calculation returns the address of
5713 ;; the next instruction.  This is 2 beyond the branch instruction.
5714 ;; For backward branches, the address calculation returns the address of
5715 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5716 ;; instruction for the shortest sequence, and 4 before the branch instruction
5717 ;; if we have to jump around an unconditional branch.
5718 ;; To the basic branch range the PC offset must be added (this is +4).
5719 ;; So for forward branches we have 
5720 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5721 ;; And for backward branches we have 
5722 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5723 ;;
5724 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5725 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5726
5727 (define_expand "cbranchsi4"
5728   [(set (pc) (if_then_else
5729               (match_operator 0 "arm_comparison_operator"
5730                [(match_operand:SI 1 "s_register_operand" "")
5731                 (match_operand:SI 2 "nonmemory_operand" "")])
5732               (label_ref (match_operand 3 "" ""))
5733               (pc)))]
5734   "TARGET_THUMB"
5735   "
5736   if (thumb_cmpneg_operand (operands[2], SImode))
5737     {
5738       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5739                                               operands[3], operands[0]));
5740       DONE;
5741     }
5742   if (!thumb_cmp_operand (operands[2], SImode))
5743     operands[2] = force_reg (SImode, operands[2]);
5744   ")
5745
5746 (define_insn "*cbranchsi4_insn"
5747   [(set (pc) (if_then_else
5748               (match_operator 0 "arm_comparison_operator"
5749                [(match_operand:SI 1 "s_register_operand" "l,*h")
5750                 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5751               (label_ref (match_operand 3 "" ""))
5752               (pc)))]
5753   "TARGET_THUMB"
5754   "*
5755   output_asm_insn (\"cmp\\t%1, %2\", operands);
5756
5757   switch (get_attr_length (insn))
5758     {
5759     case 4:  return \"b%d0\\t%l3\";
5760     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5761     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5762     }
5763   "
5764   [(set (attr "far_jump")
5765         (if_then_else
5766             (eq_attr "length" "8")
5767             (const_string "yes")
5768             (const_string "no")))
5769    (set (attr "length") 
5770         (if_then_else
5771             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5772                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5773             (const_int 4)
5774             (if_then_else
5775                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5776                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5777                 (const_int 6)
5778                 (const_int 8))))]
5779 )
5780
5781 (define_insn "cbranchsi4_scratch"
5782   [(set (pc) (if_then_else
5783               (match_operator 4 "arm_comparison_operator"
5784                [(match_operand:SI 1 "s_register_operand" "l,0")
5785                 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5786               (label_ref (match_operand 3 "" ""))
5787               (pc)))
5788    (clobber (match_scratch:SI 0 "=l,l"))]
5789   "TARGET_THUMB"
5790   "*
5791   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5792
5793   switch (get_attr_length (insn))
5794     {
5795     case 4:  return \"b%d4\\t%l3\";
5796     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5797     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5798     }
5799   "
5800   [(set (attr "far_jump")
5801         (if_then_else
5802             (eq_attr "length" "8")
5803             (const_string "yes")
5804             (const_string "no")))
5805    (set (attr "length") 
5806         (if_then_else
5807             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5808                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5809             (const_int 4)
5810             (if_then_else
5811                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5812                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5813                 (const_int 6)
5814                 (const_int 8))))]
5815 )
5816 (define_insn "*movsi_cbranchsi4"
5817   [(set (pc)
5818         (if_then_else
5819          (match_operator 3 "arm_comparison_operator"
5820           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5821            (const_int 0)])
5822          (label_ref (match_operand 2 "" ""))
5823          (pc)))
5824    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5825         (match_dup 1))]
5826   "TARGET_THUMB"
5827   "*{
5828   if (which_alternative == 0)
5829     output_asm_insn (\"cmp\t%0, #0\", operands);
5830   else if (which_alternative == 1)
5831     output_asm_insn (\"sub\t%0, %1, #0\", operands);
5832   else
5833     {
5834       output_asm_insn (\"cmp\t%1, #0\", operands);
5835       if (which_alternative == 2)
5836         output_asm_insn (\"mov\t%0, %1\", operands);
5837       else
5838         output_asm_insn (\"str\t%1, %0\", operands);
5839     }
5840   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5841     {
5842     case 4:  return \"b%d3\\t%l2\";
5843     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5844     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5845     }
5846   }"
5847   [(set (attr "far_jump")
5848         (if_then_else
5849             (ior (and (gt (symbol_ref ("which_alternative"))
5850                           (const_int 1))
5851                       (eq_attr "length" "8"))
5852                  (eq_attr "length" "10"))
5853             (const_string "yes")
5854             (const_string "no")))
5855    (set (attr "length")
5856      (if_then_else
5857        (le (symbol_ref ("which_alternative"))
5858                        (const_int 1))
5859        (if_then_else
5860          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5861               (le (minus (match_dup 2) (pc)) (const_int 256)))
5862          (const_int 4)
5863          (if_then_else
5864            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5865                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5866            (const_int 6)
5867            (const_int 8)))
5868        (if_then_else
5869          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5870               (le (minus (match_dup 2) (pc)) (const_int 256)))
5871          (const_int 6)
5872          (if_then_else
5873            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5874                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5875            (const_int 8)
5876            (const_int 10)))))]
5877 )
5878
5879 (define_insn "*negated_cbranchsi4"
5880   [(set (pc)
5881         (if_then_else
5882          (match_operator 0 "equality_operator"
5883           [(match_operand:SI 1 "s_register_operand" "l")
5884            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5885          (label_ref (match_operand 3 "" ""))
5886          (pc)))]
5887   "TARGET_THUMB"
5888   "*
5889   output_asm_insn (\"cmn\\t%1, %2\", operands);
5890   switch (get_attr_length (insn))
5891     {
5892     case 4:  return \"b%d0\\t%l3\";
5893     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5894     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5895     }
5896   "
5897   [(set (attr "far_jump")
5898         (if_then_else
5899             (eq_attr "length" "8")
5900             (const_string "yes")
5901             (const_string "no")))
5902    (set (attr "length") 
5903         (if_then_else
5904             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5905                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5906             (const_int 4)
5907             (if_then_else
5908                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5909                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5910                 (const_int 6)
5911                 (const_int 8))))]
5912 )
5913
5914 (define_insn "*tbit_cbranch"
5915   [(set (pc)
5916         (if_then_else
5917          (match_operator 0 "equality_operator"
5918           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5919                             (const_int 1)
5920                             (match_operand:SI 2 "const_int_operand" "i"))
5921            (const_int 0)])
5922          (label_ref (match_operand 3 "" ""))
5923          (pc)))
5924    (clobber (match_scratch:SI 4 "=l"))]
5925   "TARGET_THUMB"
5926   "*
5927   {
5928   rtx op[3];
5929   op[0] = operands[4];
5930   op[1] = operands[1];
5931   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5932
5933   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5934   switch (get_attr_length (insn))
5935     {
5936     case 4:  return \"b%d0\\t%l3\";
5937     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5938     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5939     }
5940   }"
5941   [(set (attr "far_jump")
5942         (if_then_else
5943             (eq_attr "length" "8")
5944             (const_string "yes")
5945             (const_string "no")))
5946    (set (attr "length") 
5947         (if_then_else
5948             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5949                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5950             (const_int 4)
5951             (if_then_else
5952                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5953                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5954                 (const_int 6)
5955                 (const_int 8))))]
5956 )
5957   
5958 (define_insn "*tstsi3_cbranch"
5959   [(set (pc)
5960         (if_then_else
5961          (match_operator 3 "equality_operator"
5962           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5963                    (match_operand:SI 1 "s_register_operand" "l"))
5964            (const_int 0)])
5965          (label_ref (match_operand 2 "" ""))
5966          (pc)))]
5967   "TARGET_THUMB"
5968   "*
5969   {
5970   output_asm_insn (\"tst\\t%0, %1\", operands);
5971   switch (get_attr_length (insn))
5972     {
5973     case 4:  return \"b%d3\\t%l2\";
5974     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5975     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5976     }
5977   }"
5978   [(set (attr "far_jump")
5979         (if_then_else
5980             (eq_attr "length" "8")
5981             (const_string "yes")
5982             (const_string "no")))
5983    (set (attr "length") 
5984         (if_then_else
5985             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5986                  (le (minus (match_dup 2) (pc)) (const_int 256)))
5987             (const_int 4)
5988             (if_then_else
5989                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5990                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
5991                 (const_int 6)
5992                 (const_int 8))))]
5993 )
5994   
5995 (define_insn "*andsi3_cbranch"
5996   [(set (pc)
5997         (if_then_else
5998          (match_operator 5 "equality_operator"
5999           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6000                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6001            (const_int 0)])
6002          (label_ref (match_operand 4 "" ""))
6003          (pc)))
6004    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6005         (and:SI (match_dup 2) (match_dup 3)))
6006    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6007   "TARGET_THUMB"
6008   "*
6009   {
6010   if (which_alternative == 0)
6011     output_asm_insn (\"and\\t%0, %3\", operands);
6012   else if (which_alternative == 1)
6013     {
6014       output_asm_insn (\"and\\t%1, %3\", operands);
6015       output_asm_insn (\"mov\\t%0, %1\", operands);
6016     }
6017   else
6018     {
6019       output_asm_insn (\"and\\t%1, %3\", operands);
6020       output_asm_insn (\"str\\t%1, %0\", operands);
6021     }
6022
6023   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6024     {
6025     case 4:  return \"b%d5\\t%l4\";
6026     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6027     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6028     }
6029   }"
6030   [(set (attr "far_jump")
6031         (if_then_else
6032             (ior (and (eq (symbol_ref ("which_alternative"))
6033                           (const_int 0))
6034                       (eq_attr "length" "8"))
6035                  (eq_attr "length" "10"))
6036             (const_string "yes")
6037             (const_string "no")))
6038    (set (attr "length")
6039      (if_then_else
6040        (eq (symbol_ref ("which_alternative"))
6041                        (const_int 0))
6042        (if_then_else
6043          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6044               (le (minus (match_dup 4) (pc)) (const_int 256)))
6045          (const_int 4)
6046          (if_then_else
6047            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6048                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6049            (const_int 6)
6050            (const_int 8)))
6051        (if_then_else
6052          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6053               (le (minus (match_dup 4) (pc)) (const_int 256)))
6054          (const_int 6)
6055          (if_then_else
6056            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6057                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6058            (const_int 8)
6059            (const_int 10)))))]
6060 )
6061
6062 (define_insn "*orrsi3_cbranch_scratch"
6063   [(set (pc)
6064         (if_then_else
6065          (match_operator 4 "equality_operator"
6066           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6067                    (match_operand:SI 2 "s_register_operand" "l"))
6068            (const_int 0)])
6069          (label_ref (match_operand 3 "" ""))
6070          (pc)))
6071    (clobber (match_scratch:SI 0 "=l"))]
6072   "TARGET_THUMB"
6073   "*
6074   {
6075   output_asm_insn (\"orr\\t%0, %2\", operands);
6076   switch (get_attr_length (insn))
6077     {
6078     case 4:  return \"b%d4\\t%l3\";
6079     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6080     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6081     }
6082   }"
6083   [(set (attr "far_jump")
6084         (if_then_else
6085             (eq_attr "length" "8")
6086             (const_string "yes")
6087             (const_string "no")))
6088    (set (attr "length") 
6089         (if_then_else
6090             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6091                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6092             (const_int 4)
6093             (if_then_else
6094                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6095                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6096                 (const_int 6)
6097                 (const_int 8))))]
6098 )
6099   
6100 (define_insn "*orrsi3_cbranch"
6101   [(set (pc)
6102         (if_then_else
6103          (match_operator 5 "equality_operator"
6104           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6105                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6106            (const_int 0)])
6107          (label_ref (match_operand 4 "" ""))
6108          (pc)))
6109    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6110         (ior:SI (match_dup 2) (match_dup 3)))
6111    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6112   "TARGET_THUMB"
6113   "*
6114   {
6115   if (which_alternative == 0)
6116     output_asm_insn (\"orr\\t%0, %3\", operands);
6117   else if (which_alternative == 1)
6118     {
6119       output_asm_insn (\"orr\\t%1, %3\", operands);
6120       output_asm_insn (\"mov\\t%0, %1\", operands);
6121     }
6122   else
6123     {
6124       output_asm_insn (\"orr\\t%1, %3\", operands);
6125       output_asm_insn (\"str\\t%1, %0\", operands);
6126     }
6127
6128   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6129     {
6130     case 4:  return \"b%d5\\t%l4\";
6131     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6132     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6133     }
6134   }"
6135   [(set (attr "far_jump")
6136         (if_then_else
6137             (ior (and (eq (symbol_ref ("which_alternative"))
6138                           (const_int 0))
6139                       (eq_attr "length" "8"))
6140                  (eq_attr "length" "10"))
6141             (const_string "yes")
6142             (const_string "no")))
6143    (set (attr "length")
6144      (if_then_else
6145        (eq (symbol_ref ("which_alternative"))
6146                        (const_int 0))
6147        (if_then_else
6148          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6149               (le (minus (match_dup 4) (pc)) (const_int 256)))
6150          (const_int 4)
6151          (if_then_else
6152            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6153                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6154            (const_int 6)
6155            (const_int 8)))
6156        (if_then_else
6157          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6158               (le (minus (match_dup 4) (pc)) (const_int 256)))
6159          (const_int 6)
6160          (if_then_else
6161            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6162                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6163            (const_int 8)
6164            (const_int 10)))))]
6165 )
6166
6167 (define_insn "*xorsi3_cbranch_scratch"
6168   [(set (pc)
6169         (if_then_else
6170          (match_operator 4 "equality_operator"
6171           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6172                    (match_operand:SI 2 "s_register_operand" "l"))
6173            (const_int 0)])
6174          (label_ref (match_operand 3 "" ""))
6175          (pc)))
6176    (clobber (match_scratch:SI 0 "=l"))]
6177   "TARGET_THUMB"
6178   "*
6179   {
6180   output_asm_insn (\"eor\\t%0, %2\", operands);
6181   switch (get_attr_length (insn))
6182     {
6183     case 4:  return \"b%d4\\t%l3\";
6184     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6185     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6186     }
6187   }"
6188   [(set (attr "far_jump")
6189         (if_then_else
6190             (eq_attr "length" "8")
6191             (const_string "yes")
6192             (const_string "no")))
6193    (set (attr "length") 
6194         (if_then_else
6195             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6196                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6197             (const_int 4)
6198             (if_then_else
6199                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6200                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6201                 (const_int 6)
6202                 (const_int 8))))]
6203 )
6204   
6205 (define_insn "*xorsi3_cbranch"
6206   [(set (pc)
6207         (if_then_else
6208          (match_operator 5 "equality_operator"
6209           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6210                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6211            (const_int 0)])
6212          (label_ref (match_operand 4 "" ""))
6213          (pc)))
6214    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6215         (xor:SI (match_dup 2) (match_dup 3)))
6216    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6217   "TARGET_THUMB"
6218   "*
6219   {
6220   if (which_alternative == 0)
6221     output_asm_insn (\"eor\\t%0, %3\", operands);
6222   else if (which_alternative == 1)
6223     {
6224       output_asm_insn (\"eor\\t%1, %3\", operands);
6225       output_asm_insn (\"mov\\t%0, %1\", operands);
6226     }
6227   else
6228     {
6229       output_asm_insn (\"eor\\t%1, %3\", operands);
6230       output_asm_insn (\"str\\t%1, %0\", operands);
6231     }
6232
6233   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6234     {
6235     case 4:  return \"b%d5\\t%l4\";
6236     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6237     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6238     }
6239   }"
6240   [(set (attr "far_jump")
6241         (if_then_else
6242             (ior (and (eq (symbol_ref ("which_alternative"))
6243                           (const_int 0))
6244                       (eq_attr "length" "8"))
6245                  (eq_attr "length" "10"))
6246             (const_string "yes")
6247             (const_string "no")))
6248    (set (attr "length")
6249      (if_then_else
6250        (eq (symbol_ref ("which_alternative"))
6251                        (const_int 0))
6252        (if_then_else
6253          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6254               (le (minus (match_dup 4) (pc)) (const_int 256)))
6255          (const_int 4)
6256          (if_then_else
6257            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6258                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6259            (const_int 6)
6260            (const_int 8)))
6261        (if_then_else
6262          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6263               (le (minus (match_dup 4) (pc)) (const_int 256)))
6264          (const_int 6)
6265          (if_then_else
6266            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6267                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6268            (const_int 8)
6269            (const_int 10)))))]
6270 )
6271
6272 (define_insn "*bicsi3_cbranch_scratch"
6273   [(set (pc)
6274         (if_then_else
6275          (match_operator 4 "equality_operator"
6276           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6277                    (match_operand:SI 1 "s_register_operand" "0"))
6278            (const_int 0)])
6279          (label_ref (match_operand 3 "" ""))
6280          (pc)))
6281    (clobber (match_scratch:SI 0 "=l"))]
6282   "TARGET_THUMB"
6283   "*
6284   {
6285   output_asm_insn (\"bic\\t%0, %2\", operands);
6286   switch (get_attr_length (insn))
6287     {
6288     case 4:  return \"b%d4\\t%l3\";
6289     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6290     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6291     }
6292   }"
6293   [(set (attr "far_jump")
6294         (if_then_else
6295             (eq_attr "length" "8")
6296             (const_string "yes")
6297             (const_string "no")))
6298    (set (attr "length") 
6299         (if_then_else
6300             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6301                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6302             (const_int 4)
6303             (if_then_else
6304                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6305                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6306                 (const_int 6)
6307                 (const_int 8))))]
6308 )
6309   
6310 (define_insn "*bicsi3_cbranch"
6311   [(set (pc)
6312         (if_then_else
6313          (match_operator 5 "equality_operator"
6314           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6315                    (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6316            (const_int 0)])
6317          (label_ref (match_operand 4 "" ""))
6318          (pc)))
6319    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6320         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6321    (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6322   "TARGET_THUMB"
6323   "*
6324   {
6325   if (which_alternative == 0)
6326     output_asm_insn (\"bic\\t%0, %3\", operands);
6327   else if (which_alternative <= 2)
6328     {
6329       output_asm_insn (\"bic\\t%1, %3\", operands);
6330       /* It's ok if OP0 is a lo-reg, even though the mov will set the
6331          conditions again, since we're only testing for equality.  */
6332       output_asm_insn (\"mov\\t%0, %1\", operands);
6333     }
6334   else
6335     {
6336       output_asm_insn (\"bic\\t%1, %3\", operands);
6337       output_asm_insn (\"str\\t%1, %0\", operands);
6338     }
6339
6340   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6341     {
6342     case 4:  return \"b%d5\\t%l4\";
6343     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6344     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6345     }
6346   }"
6347   [(set (attr "far_jump")
6348         (if_then_else
6349             (ior (and (eq (symbol_ref ("which_alternative"))
6350                           (const_int 0))
6351                       (eq_attr "length" "8"))
6352                  (eq_attr "length" "10"))
6353             (const_string "yes")
6354             (const_string "no")))
6355    (set (attr "length")
6356      (if_then_else
6357        (eq (symbol_ref ("which_alternative"))
6358                        (const_int 0))
6359        (if_then_else
6360          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6361               (le (minus (match_dup 4) (pc)) (const_int 256)))
6362          (const_int 4)
6363          (if_then_else
6364            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6365                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6366            (const_int 6)
6367            (const_int 8)))
6368        (if_then_else
6369          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6370               (le (minus (match_dup 4) (pc)) (const_int 256)))
6371          (const_int 6)
6372          (if_then_else
6373            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6374                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6375            (const_int 8)
6376            (const_int 10)))))]
6377 )
6378
6379 (define_insn "*cbranchne_decr1"
6380   [(set (pc)
6381         (if_then_else (match_operator 3 "equality_operator"
6382                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6383                         (const_int 0)])
6384                       (label_ref (match_operand 4 "" ""))
6385                       (pc)))
6386    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6387         (plus:SI (match_dup 2) (const_int -1)))
6388    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6389   "TARGET_THUMB"
6390   "*
6391    {
6392      rtx cond[2];
6393      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6394                                 ? GEU : LTU),
6395                                VOIDmode, operands[2], const1_rtx);
6396      cond[1] = operands[4];
6397
6398      if (which_alternative == 0)
6399        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6400      else if (which_alternative == 1)
6401        {
6402          /* We must provide an alternative for a hi reg because reload 
6403             cannot handle output reloads on a jump instruction, but we
6404             can't subtract into that.  Fortunately a mov from lo to hi
6405             does not clobber the condition codes.  */
6406          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6407          output_asm_insn (\"mov\\t%0, %1\", operands);
6408        }
6409      else
6410        {
6411          /* Similarly, but the target is memory.  */
6412          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6413          output_asm_insn (\"str\\t%1, %0\", operands);
6414        }
6415
6416      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6417        {
6418          case 4:
6419            output_asm_insn (\"b%d0\\t%l1\", cond);
6420            return \"\";
6421          case 6:
6422            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6423            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6424          default:
6425            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6426            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6427        }
6428    }
6429   "
6430   [(set (attr "far_jump")
6431         (if_then_else
6432             (ior (and (eq (symbol_ref ("which_alternative"))
6433                           (const_int 0))
6434                       (eq_attr "length" "8"))
6435                  (eq_attr "length" "10"))
6436             (const_string "yes")
6437             (const_string "no")))
6438    (set_attr_alternative "length"
6439       [
6440        ;; Alternative 0
6441        (if_then_else
6442          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6443               (le (minus (match_dup 4) (pc)) (const_int 256)))
6444          (const_int 4)
6445          (if_then_else
6446            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6447                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6448            (const_int 6)
6449            (const_int 8)))
6450        ;; Alternative 1
6451        (if_then_else
6452          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6453               (le (minus (match_dup 4) (pc)) (const_int 256)))
6454          (const_int 6)
6455          (if_then_else
6456            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6457                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6458            (const_int 8)
6459            (const_int 10)))
6460        ;; Alternative 2
6461        (if_then_else
6462          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6463               (le (minus (match_dup 4) (pc)) (const_int 256)))
6464          (const_int 6)
6465          (if_then_else
6466            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6467                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6468            (const_int 8)
6469            (const_int 10)))
6470        ;; Alternative 3
6471        (if_then_else
6472          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6473               (le (minus (match_dup 4) (pc)) (const_int 256)))
6474          (const_int 6)
6475          (if_then_else
6476            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6477                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6478            (const_int 8)
6479            (const_int 10)))])]
6480 )
6481
6482 (define_insn "*addsi3_cbranch"
6483   [(set (pc)
6484         (if_then_else
6485          (match_operator 4 "comparison_operator"
6486           [(plus:SI
6487             (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6488             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6489            (const_int 0)])
6490          (label_ref (match_operand 5 "" ""))
6491          (pc)))
6492    (set
6493     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6494     (plus:SI (match_dup 2) (match_dup 3)))
6495    (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6496   "TARGET_THUMB
6497    && (GET_CODE (operands[4]) == EQ
6498        || GET_CODE (operands[4]) == NE
6499        || GET_CODE (operands[4]) == GE
6500        || GET_CODE (operands[4]) == LT)"
6501   "*
6502    {
6503      rtx cond[3];
6504
6505      
6506      cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6507      cond[1] = operands[2];
6508      cond[2] = operands[3];
6509
6510      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6511        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6512      else
6513        output_asm_insn (\"add\\t%0, %1, %2\", cond);
6514
6515      if (which_alternative >= 3
6516          && which_alternative < 4)
6517        output_asm_insn (\"mov\\t%0, %1\", operands);
6518      else if (which_alternative >= 4)
6519        output_asm_insn (\"str\\t%1, %0\", operands);
6520
6521      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6522        {
6523          case 4:
6524            return \"b%d4\\t%l5\";
6525          case 6:
6526            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6527          default:
6528            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6529        }
6530    }
6531   "
6532   [(set (attr "far_jump")
6533         (if_then_else
6534             (ior (and (lt (symbol_ref ("which_alternative"))
6535                           (const_int 3))
6536                       (eq_attr "length" "8"))
6537                  (eq_attr "length" "10"))
6538             (const_string "yes")
6539             (const_string "no")))
6540    (set (attr "length")
6541      (if_then_else
6542        (lt (symbol_ref ("which_alternative"))
6543                        (const_int 3))
6544        (if_then_else
6545          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6546               (le (minus (match_dup 5) (pc)) (const_int 256)))
6547          (const_int 4)
6548          (if_then_else
6549            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6550                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6551            (const_int 6)
6552            (const_int 8)))
6553        (if_then_else
6554          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6555               (le (minus (match_dup 5) (pc)) (const_int 256)))
6556          (const_int 6)
6557          (if_then_else
6558            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6559                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6560            (const_int 8)
6561            (const_int 10)))))]
6562 )
6563
6564 (define_insn "*addsi3_cbranch_scratch"
6565   [(set (pc)
6566         (if_then_else
6567          (match_operator 3 "comparison_operator"
6568           [(plus:SI
6569             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6570             (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
6571            (const_int 0)])
6572          (label_ref (match_operand 4 "" ""))
6573          (pc)))
6574    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6575   "TARGET_THUMB
6576    && (GET_CODE (operands[3]) == EQ
6577        || GET_CODE (operands[3]) == NE
6578        || GET_CODE (operands[3]) == GE
6579        || GET_CODE (operands[3]) == LT)"
6580   "*
6581    {
6582      switch (which_alternative)
6583        {
6584        case 0:
6585          output_asm_insn (\"cmp\t%1, #%n2\", operands);
6586          break;
6587        case 1:
6588          output_asm_insn (\"cmn\t%1, %2\", operands);
6589          break;
6590        case 2:
6591          if (INTVAL (operands[2]) < 0)
6592            output_asm_insn (\"sub\t%0, %1, %2\", operands);
6593          else
6594            output_asm_insn (\"add\t%0, %1, %2\", operands);
6595          break;
6596        case 3:
6597          if (INTVAL (operands[2]) < 0)
6598            output_asm_insn (\"sub\t%0, %0, %2\", operands);
6599          else
6600            output_asm_insn (\"add\t%0, %0, %2\", operands);
6601          break;
6602        }
6603
6604      switch (get_attr_length (insn))
6605        {
6606          case 4:
6607            return \"b%d3\\t%l4\";
6608          case 6:
6609            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6610          default:
6611            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6612        }
6613    }
6614   "
6615   [(set (attr "far_jump")
6616         (if_then_else
6617             (eq_attr "length" "8")
6618             (const_string "yes")
6619             (const_string "no")))
6620    (set (attr "length")
6621        (if_then_else
6622          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6623               (le (minus (match_dup 4) (pc)) (const_int 256)))
6624          (const_int 4)
6625          (if_then_else
6626            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6627                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6628            (const_int 6)
6629            (const_int 8))))]
6630 )
6631
6632 (define_insn "*subsi3_cbranch"
6633   [(set (pc)
6634         (if_then_else
6635          (match_operator 4 "comparison_operator"
6636           [(minus:SI
6637             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6638             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6639            (const_int 0)])
6640          (label_ref (match_operand 5 "" ""))
6641          (pc)))
6642    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6643         (minus:SI (match_dup 2) (match_dup 3)))
6644    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6645   "TARGET_THUMB
6646    && (GET_CODE (operands[4]) == EQ
6647        || GET_CODE (operands[4]) == NE
6648        || GET_CODE (operands[4]) == GE
6649        || GET_CODE (operands[4]) == LT)"
6650   "*
6651    {
6652      if (which_alternative == 0)
6653        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6654      else if (which_alternative == 1)
6655        {
6656          /* We must provide an alternative for a hi reg because reload 
6657             cannot handle output reloads on a jump instruction, but we
6658             can't subtract into that.  Fortunately a mov from lo to hi
6659             does not clobber the condition codes.  */
6660          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6661          output_asm_insn (\"mov\\t%0, %1\", operands);
6662        }
6663      else
6664        {
6665          /* Similarly, but the target is memory.  */
6666          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6667          output_asm_insn (\"str\\t%1, %0\", operands);
6668        }
6669
6670      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6671        {
6672          case 4:
6673            return \"b%d4\\t%l5\";
6674          case 6:
6675            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6676          default:
6677            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6678        }
6679    }
6680   "
6681   [(set (attr "far_jump")
6682         (if_then_else
6683             (ior (and (eq (symbol_ref ("which_alternative"))
6684                           (const_int 0))
6685                       (eq_attr "length" "8"))
6686                  (eq_attr "length" "10"))
6687             (const_string "yes")
6688             (const_string "no")))
6689    (set (attr "length")
6690      (if_then_else
6691        (eq (symbol_ref ("which_alternative"))
6692                        (const_int 0))
6693        (if_then_else
6694          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6695               (le (minus (match_dup 5) (pc)) (const_int 256)))
6696          (const_int 4)
6697          (if_then_else
6698            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6699                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6700            (const_int 6)
6701            (const_int 8)))
6702        (if_then_else
6703          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6704               (le (minus (match_dup 5) (pc)) (const_int 256)))
6705          (const_int 6)
6706          (if_then_else
6707            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6708                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6709            (const_int 8)
6710            (const_int 10)))))]
6711 )
6712
6713 (define_insn "*subsi3_cbranch_scratch"
6714   [(set (pc)
6715         (if_then_else
6716          (match_operator 0 "arm_comparison_operator"
6717           [(minus:SI (match_operand:SI 1 "register_operand" "l")
6718                      (match_operand:SI 2 "nonmemory_operand" "l"))
6719            (const_int 0)])
6720          (label_ref (match_operand 3 "" ""))
6721          (pc)))]
6722   "TARGET_THUMB
6723    && (GET_CODE (operands[0]) == EQ
6724        || GET_CODE (operands[0]) == NE
6725        || GET_CODE (operands[0]) == GE
6726        || GET_CODE (operands[0]) == LT)"
6727   "*
6728   output_asm_insn (\"cmp\\t%1, %2\", operands);
6729   switch (get_attr_length (insn))
6730     {
6731     case 4:  return \"b%d0\\t%l3\";
6732     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6733     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6734     }
6735   "
6736   [(set (attr "far_jump")
6737         (if_then_else
6738             (eq_attr "length" "8")
6739             (const_string "yes")
6740             (const_string "no")))
6741    (set (attr "length") 
6742         (if_then_else
6743             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6744                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6745             (const_int 4)
6746             (if_then_else
6747                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6748                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6749                 (const_int 6)
6750                 (const_int 8))))]
6751 )
6752
6753 ;; Comparison and test insns
6754
6755 (define_expand "cmpsi"
6756   [(match_operand:SI 0 "s_register_operand" "")
6757    (match_operand:SI 1 "arm_add_operand" "")]
6758   "TARGET_ARM"
6759   "{
6760     arm_compare_op0 = operands[0];
6761     arm_compare_op1 = operands[1];
6762     DONE;
6763   }"
6764 )
6765
6766 (define_expand "cmpsf"
6767   [(match_operand:SF 0 "s_register_operand" "")
6768    (match_operand:SF 1 "arm_float_compare_operand" "")]
6769   "TARGET_ARM && TARGET_HARD_FLOAT"
6770   "
6771   arm_compare_op0 = operands[0];
6772   arm_compare_op1 = operands[1];
6773   DONE;
6774   "
6775 )
6776
6777 (define_expand "cmpdf"
6778   [(match_operand:DF 0 "s_register_operand" "")
6779    (match_operand:DF 1 "arm_float_compare_operand" "")]
6780   "TARGET_ARM && TARGET_HARD_FLOAT"
6781   "
6782   arm_compare_op0 = operands[0];
6783   arm_compare_op1 = operands[1];
6784   DONE;
6785   "
6786 )
6787
6788 (define_insn "*arm_cmpsi_insn"
6789   [(set (reg:CC CC_REGNUM)
6790         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6791                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
6792   "TARGET_ARM"
6793   "@
6794    cmp%?\\t%0, %1
6795    cmn%?\\t%0, #%n1"
6796   [(set_attr "conds" "set")]
6797 )
6798
6799 (define_insn "*cmpsi_shiftsi"
6800   [(set (reg:CC CC_REGNUM)
6801         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
6802                     (match_operator:SI  3 "shift_operator"
6803                      [(match_operand:SI 1 "s_register_operand" "r")
6804                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
6805   "TARGET_ARM"
6806   "cmp%?\\t%0, %1%S3"
6807   [(set_attr "conds" "set")
6808    (set_attr "shift" "1")
6809    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6810                       (const_string "alu_shift")
6811                       (const_string "alu_shift_reg")))]
6812 )
6813
6814 (define_insn "*cmpsi_shiftsi_swp"
6815   [(set (reg:CC_SWP CC_REGNUM)
6816         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6817                          [(match_operand:SI 1 "s_register_operand" "r")
6818                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
6819                         (match_operand:SI 0 "s_register_operand" "r")))]
6820   "TARGET_ARM"
6821   "cmp%?\\t%0, %1%S3"
6822   [(set_attr "conds" "set")
6823    (set_attr "shift" "1")
6824    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6825                       (const_string "alu_shift")
6826                       (const_string "alu_shift_reg")))]
6827 )
6828
6829 (define_insn "*cmpsi_negshiftsi_si"
6830   [(set (reg:CC_Z CC_REGNUM)
6831         (compare:CC_Z
6832          (neg:SI (match_operator:SI 1 "shift_operator"
6833                     [(match_operand:SI 2 "s_register_operand" "r")
6834                      (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6835          (match_operand:SI 0 "s_register_operand" "r")))]
6836   "TARGET_ARM"
6837   "cmn%?\\t%0, %2%S1"
6838   [(set_attr "conds" "set")
6839    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
6840                                     (const_string "alu_shift")
6841                                     (const_string "alu_shift_reg")))]
6842 )
6843
6844 ;; Cirrus SF compare instruction
6845 (define_insn "*cirrus_cmpsf"
6846   [(set (reg:CCFP CC_REGNUM)
6847         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6848                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
6849   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6850   "cfcmps%?\\tr15, %V0, %V1"
6851   [(set_attr "type"   "mav_farith")
6852    (set_attr "cirrus" "compare")]
6853 )
6854
6855 ;; Cirrus DF compare instruction
6856 (define_insn "*cirrus_cmpdf"
6857   [(set (reg:CCFP CC_REGNUM)
6858         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6859                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
6860   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6861   "cfcmpd%?\\tr15, %V0, %V1"
6862   [(set_attr "type"   "mav_farith")
6863    (set_attr "cirrus" "compare")]
6864 )
6865
6866 ;; Cirrus DI compare instruction
6867 (define_expand "cmpdi"
6868   [(match_operand:DI 0 "cirrus_fp_register" "")
6869    (match_operand:DI 1 "cirrus_fp_register" "")]
6870   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6871   "{
6872      arm_compare_op0 = operands[0];
6873      arm_compare_op1 = operands[1];
6874      DONE;
6875    }")
6876
6877 (define_insn "*cirrus_cmpdi"
6878   [(set (reg:CC CC_REGNUM)
6879         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6880                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
6881   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6882   "cfcmp64%?\\tr15, %V0, %V1"
6883   [(set_attr "type"   "mav_farith")
6884    (set_attr "cirrus" "compare")]
6885 )
6886
6887 ; This insn allows redundant compares to be removed by cse, nothing should
6888 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6889 ; is deleted later on. The match_dup will match the mode here, so that
6890 ; mode changes of the condition codes aren't lost by this even though we don't
6891 ; specify what they are.
6892
6893 (define_insn "*deleted_compare"
6894   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6895   "TARGET_ARM"
6896   "\\t%@ deleted compare"
6897   [(set_attr "conds" "set")
6898    (set_attr "length" "0")]
6899 )
6900
6901 \f
6902 ;; Conditional branch insns
6903
6904 (define_expand "beq"
6905   [(set (pc)
6906         (if_then_else (eq (match_dup 1) (const_int 0))
6907                       (label_ref (match_operand 0 "" ""))
6908                       (pc)))]
6909   "TARGET_ARM"
6910   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6911 )
6912
6913 (define_expand "bne"
6914   [(set (pc)
6915         (if_then_else (ne (match_dup 1) (const_int 0))
6916                       (label_ref (match_operand 0 "" ""))
6917                       (pc)))]
6918   "TARGET_ARM"
6919   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6920 )
6921
6922 (define_expand "bgt"
6923   [(set (pc)
6924         (if_then_else (gt (match_dup 1) (const_int 0))
6925                       (label_ref (match_operand 0 "" ""))
6926                       (pc)))]
6927   "TARGET_ARM"
6928   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6929 )
6930
6931 (define_expand "ble"
6932   [(set (pc)
6933         (if_then_else (le (match_dup 1) (const_int 0))
6934                       (label_ref (match_operand 0 "" ""))
6935                       (pc)))]
6936   "TARGET_ARM"
6937   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6938 )
6939
6940 (define_expand "bge"
6941   [(set (pc)
6942         (if_then_else (ge (match_dup 1) (const_int 0))
6943                       (label_ref (match_operand 0 "" ""))
6944                       (pc)))]
6945   "TARGET_ARM"
6946   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6947 )
6948
6949 (define_expand "blt"
6950   [(set (pc)
6951         (if_then_else (lt (match_dup 1) (const_int 0))
6952                       (label_ref (match_operand 0 "" ""))
6953                       (pc)))]
6954   "TARGET_ARM"
6955   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6956 )
6957
6958 (define_expand "bgtu"
6959   [(set (pc)
6960         (if_then_else (gtu (match_dup 1) (const_int 0))
6961                       (label_ref (match_operand 0 "" ""))
6962                       (pc)))]
6963   "TARGET_ARM"
6964   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6965 )
6966
6967 (define_expand "bleu"
6968   [(set (pc)
6969         (if_then_else (leu (match_dup 1) (const_int 0))
6970                       (label_ref (match_operand 0 "" ""))
6971                       (pc)))]
6972   "TARGET_ARM"
6973   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6974 )
6975
6976 (define_expand "bgeu"
6977   [(set (pc)
6978         (if_then_else (geu (match_dup 1) (const_int 0))
6979                       (label_ref (match_operand 0 "" ""))
6980                       (pc)))]
6981   "TARGET_ARM"
6982   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6983 )
6984
6985 (define_expand "bltu"
6986   [(set (pc)
6987         (if_then_else (ltu (match_dup 1) (const_int 0))
6988                       (label_ref (match_operand 0 "" ""))
6989                       (pc)))]
6990   "TARGET_ARM"
6991   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6992 )
6993
6994 (define_expand "bunordered"
6995   [(set (pc)
6996         (if_then_else (unordered (match_dup 1) (const_int 0))
6997                       (label_ref (match_operand 0 "" ""))
6998                       (pc)))]
6999   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7000   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7001                                       arm_compare_op1);"
7002 )
7003
7004 (define_expand "bordered"
7005   [(set (pc)
7006         (if_then_else (ordered (match_dup 1) (const_int 0))
7007                       (label_ref (match_operand 0 "" ""))
7008                       (pc)))]
7009   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7010   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7011                                       arm_compare_op1);"
7012 )
7013
7014 (define_expand "bungt"
7015   [(set (pc)
7016         (if_then_else (ungt (match_dup 1) (const_int 0))
7017                       (label_ref (match_operand 0 "" ""))
7018                       (pc)))]
7019   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7020   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
7021 )
7022
7023 (define_expand "bunlt"
7024   [(set (pc)
7025         (if_then_else (unlt (match_dup 1) (const_int 0))
7026                       (label_ref (match_operand 0 "" ""))
7027                       (pc)))]
7028   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7029   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
7030 )
7031
7032 (define_expand "bunge"
7033   [(set (pc)
7034         (if_then_else (unge (match_dup 1) (const_int 0))
7035                       (label_ref (match_operand 0 "" ""))
7036                       (pc)))]
7037   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7038   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
7039 )
7040
7041 (define_expand "bunle"
7042   [(set (pc)
7043         (if_then_else (unle (match_dup 1) (const_int 0))
7044                       (label_ref (match_operand 0 "" ""))
7045                       (pc)))]
7046   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7047   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
7048 )
7049
7050 ;; The following two patterns need two branch instructions, since there is
7051 ;; no single instruction that will handle all cases.
7052 (define_expand "buneq"
7053   [(set (pc)
7054         (if_then_else (uneq (match_dup 1) (const_int 0))
7055                       (label_ref (match_operand 0 "" ""))
7056                       (pc)))]
7057   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7058   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
7059 )
7060
7061 (define_expand "bltgt"
7062   [(set (pc)
7063         (if_then_else (ltgt (match_dup 1) (const_int 0))
7064                       (label_ref (match_operand 0 "" ""))
7065                       (pc)))]
7066   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7067   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
7068 )
7069
7070 ;;
7071 ;; Patterns to match conditional branch insns.
7072 ;;
7073
7074 ; Special pattern to match UNEQ.
7075 (define_insn "*arm_buneq"
7076   [(set (pc)
7077         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7078                       (label_ref (match_operand 0 "" ""))
7079                       (pc)))]
7080   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7081   "*
7082   gcc_assert (!arm_ccfsm_state);
7083
7084   return \"bvs\\t%l0\;beq\\t%l0\";
7085   "
7086   [(set_attr "conds" "jump_clob")
7087    (set_attr "length" "8")]
7088 )
7089
7090 ; Special pattern to match LTGT.
7091 (define_insn "*arm_bltgt"
7092   [(set (pc)
7093         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7094                       (label_ref (match_operand 0 "" ""))
7095                       (pc)))]
7096   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7097   "*
7098   gcc_assert (!arm_ccfsm_state);
7099
7100   return \"bmi\\t%l0\;bgt\\t%l0\";
7101   "
7102   [(set_attr "conds" "jump_clob")
7103    (set_attr "length" "8")]
7104 )
7105
7106 (define_insn "*arm_cond_branch"
7107   [(set (pc)
7108         (if_then_else (match_operator 1 "arm_comparison_operator"
7109                        [(match_operand 2 "cc_register" "") (const_int 0)])
7110                       (label_ref (match_operand 0 "" ""))
7111                       (pc)))]
7112   "TARGET_ARM"
7113   "*
7114   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7115     {
7116       arm_ccfsm_state += 2;
7117       return \"\";
7118     }
7119   return \"b%d1\\t%l0\";
7120   "
7121   [(set_attr "conds" "use")
7122    (set_attr "type" "branch")]
7123 )
7124
7125 ; Special pattern to match reversed UNEQ.
7126 (define_insn "*arm_buneq_reversed"
7127   [(set (pc)
7128         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7129                       (pc)
7130                       (label_ref (match_operand 0 "" ""))))]
7131   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7132   "*
7133   gcc_assert (!arm_ccfsm_state);
7134
7135   return \"bmi\\t%l0\;bgt\\t%l0\";
7136   "
7137   [(set_attr "conds" "jump_clob")
7138    (set_attr "length" "8")]
7139 )
7140
7141 ; Special pattern to match reversed LTGT.
7142 (define_insn "*arm_bltgt_reversed"
7143   [(set (pc)
7144         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7145                       (pc)
7146                       (label_ref (match_operand 0 "" ""))))]
7147   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7148   "*
7149   gcc_assert (!arm_ccfsm_state);
7150
7151   return \"bvs\\t%l0\;beq\\t%l0\";
7152   "
7153   [(set_attr "conds" "jump_clob")
7154    (set_attr "length" "8")]
7155 )
7156
7157 (define_insn "*arm_cond_branch_reversed"
7158   [(set (pc)
7159         (if_then_else (match_operator 1 "arm_comparison_operator"
7160                        [(match_operand 2 "cc_register" "") (const_int 0)])
7161                       (pc)
7162                       (label_ref (match_operand 0 "" ""))))]
7163   "TARGET_ARM"
7164   "*
7165   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7166     {
7167       arm_ccfsm_state += 2;
7168       return \"\";
7169     }
7170   return \"b%D1\\t%l0\";
7171   "
7172   [(set_attr "conds" "use")
7173    (set_attr "type" "branch")]
7174 )
7175
7176 \f
7177
7178 ; scc insns
7179
7180 (define_expand "seq"
7181   [(set (match_operand:SI 0 "s_register_operand" "")
7182         (eq:SI (match_dup 1) (const_int 0)))]
7183   "TARGET_ARM"
7184   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7185 )
7186
7187 (define_expand "sne"
7188   [(set (match_operand:SI 0 "s_register_operand" "")
7189         (ne:SI (match_dup 1) (const_int 0)))]
7190   "TARGET_ARM"
7191   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7192 )
7193
7194 (define_expand "sgt"
7195   [(set (match_operand:SI 0 "s_register_operand" "")
7196         (gt:SI (match_dup 1) (const_int 0)))]
7197   "TARGET_ARM"
7198   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7199 )
7200
7201 (define_expand "sle"
7202   [(set (match_operand:SI 0 "s_register_operand" "")
7203         (le:SI (match_dup 1) (const_int 0)))]
7204   "TARGET_ARM"
7205   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7206 )
7207
7208 (define_expand "sge"
7209   [(set (match_operand:SI 0 "s_register_operand" "")
7210         (ge:SI (match_dup 1) (const_int 0)))]
7211   "TARGET_ARM"
7212   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7213 )
7214
7215 (define_expand "slt"
7216   [(set (match_operand:SI 0 "s_register_operand" "")
7217         (lt:SI (match_dup 1) (const_int 0)))]
7218   "TARGET_ARM"
7219   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7220 )
7221
7222 (define_expand "sgtu"
7223   [(set (match_operand:SI 0 "s_register_operand" "")
7224         (gtu:SI (match_dup 1) (const_int 0)))]
7225   "TARGET_ARM"
7226   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7227 )
7228
7229 (define_expand "sleu"
7230   [(set (match_operand:SI 0 "s_register_operand" "")
7231         (leu:SI (match_dup 1) (const_int 0)))]
7232   "TARGET_ARM"
7233   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7234 )
7235
7236 (define_expand "sgeu"
7237   [(set (match_operand:SI 0 "s_register_operand" "")
7238         (geu:SI (match_dup 1) (const_int 0)))]
7239   "TARGET_ARM"
7240   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7241 )
7242
7243 (define_expand "sltu"
7244   [(set (match_operand:SI 0 "s_register_operand" "")
7245         (ltu:SI (match_dup 1) (const_int 0)))]
7246   "TARGET_ARM"
7247   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7248 )
7249
7250 (define_expand "sunordered"
7251   [(set (match_operand:SI 0 "s_register_operand" "")
7252         (unordered:SI (match_dup 1) (const_int 0)))]
7253   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7254   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7255                                       arm_compare_op1);"
7256 )
7257
7258 (define_expand "sordered"
7259   [(set (match_operand:SI 0 "s_register_operand" "")
7260         (ordered:SI (match_dup 1) (const_int 0)))]
7261   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7262   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7263                                       arm_compare_op1);"
7264 )
7265
7266 (define_expand "sungt"
7267   [(set (match_operand:SI 0 "s_register_operand" "")
7268         (ungt:SI (match_dup 1) (const_int 0)))]
7269   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7270   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7271                                       arm_compare_op1);"
7272 )
7273
7274 (define_expand "sunge"
7275   [(set (match_operand:SI 0 "s_register_operand" "")
7276         (unge:SI (match_dup 1) (const_int 0)))]
7277   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7278   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7279                                       arm_compare_op1);"
7280 )
7281
7282 (define_expand "sunlt"
7283   [(set (match_operand:SI 0 "s_register_operand" "")
7284         (unlt:SI (match_dup 1) (const_int 0)))]
7285   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7286   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7287                                       arm_compare_op1);"
7288 )
7289
7290 (define_expand "sunle"
7291   [(set (match_operand:SI 0 "s_register_operand" "")
7292         (unle:SI (match_dup 1) (const_int 0)))]
7293   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7294   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7295                                       arm_compare_op1);"
7296 )
7297
7298 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7299 ;;; simple ARM instructions. 
7300 ;
7301 ; (define_expand "suneq"
7302 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7303 ;       (uneq:SI (match_dup 1) (const_int 0)))]
7304 ;   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7305 ;   "gcc_unreachable ();"
7306 ; )
7307 ;
7308 ; (define_expand "sltgt"
7309 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7310 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
7311 ;   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7312 ;   "gcc_unreachable ();"
7313 ; )
7314
7315 (define_insn "*mov_scc"
7316   [(set (match_operand:SI 0 "s_register_operand" "=r")
7317         (match_operator:SI 1 "arm_comparison_operator"
7318          [(match_operand 2 "cc_register" "") (const_int 0)]))]
7319   "TARGET_ARM"
7320   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7321   [(set_attr "conds" "use")
7322    (set_attr "length" "8")]
7323 )
7324
7325 (define_insn "*mov_negscc"
7326   [(set (match_operand:SI 0 "s_register_operand" "=r")
7327         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7328                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7329   "TARGET_ARM"
7330   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7331   [(set_attr "conds" "use")
7332    (set_attr "length" "8")]
7333 )
7334
7335 (define_insn "*mov_notscc"
7336   [(set (match_operand:SI 0 "s_register_operand" "=r")
7337         (not:SI (match_operator:SI 1 "arm_comparison_operator"
7338                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7339   "TARGET_ARM"
7340   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7341   [(set_attr "conds" "use")
7342    (set_attr "length" "8")]
7343 )
7344
7345 \f
7346 ;; Conditional move insns
7347
7348 (define_expand "movsicc"
7349   [(set (match_operand:SI 0 "s_register_operand" "")
7350         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7351                          (match_operand:SI 2 "arm_not_operand" "")
7352                          (match_operand:SI 3 "arm_not_operand" "")))]
7353   "TARGET_ARM"
7354   "
7355   {
7356     enum rtx_code code = GET_CODE (operands[1]);
7357     rtx ccreg;
7358
7359     if (code == UNEQ || code == LTGT)
7360       FAIL;
7361
7362     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7363     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7364   }"
7365 )
7366
7367 (define_expand "movsfcc"
7368   [(set (match_operand:SF 0 "s_register_operand" "")
7369         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7370                          (match_operand:SF 2 "s_register_operand" "")
7371                          (match_operand:SF 3 "nonmemory_operand" "")))]
7372   "TARGET_ARM"
7373   "
7374   {
7375     enum rtx_code code = GET_CODE (operands[1]);
7376     rtx ccreg;
7377
7378     if (code == UNEQ || code == LTGT)
7379       FAIL;
7380
7381     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
7382        Otherwise, ensure it is a valid FP add operand */
7383     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7384         || (!arm_float_add_operand (operands[3], SFmode)))
7385       operands[3] = force_reg (SFmode, operands[3]);
7386
7387     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7388     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7389   }"
7390 )
7391
7392 (define_expand "movdfcc"
7393   [(set (match_operand:DF 0 "s_register_operand" "")
7394         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7395                          (match_operand:DF 2 "s_register_operand" "")
7396                          (match_operand:DF 3 "arm_float_add_operand" "")))]
7397   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7398   "
7399   {
7400     enum rtx_code code = GET_CODE (operands[1]);
7401     rtx ccreg;
7402
7403     if (code == UNEQ || code == LTGT)
7404       FAIL;
7405
7406     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7407     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7408   }"
7409 )
7410
7411 (define_insn "*movsicc_insn"
7412   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7413         (if_then_else:SI
7414          (match_operator 3 "arm_comparison_operator"
7415           [(match_operand 4 "cc_register" "") (const_int 0)])
7416          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7417          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7418   "TARGET_ARM"
7419   "@
7420    mov%D3\\t%0, %2
7421    mvn%D3\\t%0, #%B2
7422    mov%d3\\t%0, %1
7423    mvn%d3\\t%0, #%B1
7424    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7425    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7426    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7427    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7428   [(set_attr "length" "4,4,4,4,8,8,8,8")
7429    (set_attr "conds" "use")]
7430 )
7431
7432 (define_insn "*movsfcc_soft_insn"
7433   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7434         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7435                           [(match_operand 4 "cc_register" "") (const_int 0)])
7436                          (match_operand:SF 1 "s_register_operand" "0,r")
7437                          (match_operand:SF 2 "s_register_operand" "r,0")))]
7438   "TARGET_ARM && TARGET_SOFT_FLOAT"
7439   "@
7440    mov%D3\\t%0, %2
7441    mov%d3\\t%0, %1"
7442   [(set_attr "conds" "use")]
7443 )
7444
7445 \f
7446 ;; Jump and linkage insns
7447
7448 (define_expand "jump"
7449   [(set (pc)
7450         (label_ref (match_operand 0 "" "")))]
7451   "TARGET_EITHER"
7452   ""
7453 )
7454
7455 (define_insn "*arm_jump"
7456   [(set (pc)
7457         (label_ref (match_operand 0 "" "")))]
7458   "TARGET_ARM"
7459   "*
7460   {
7461     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7462       {
7463         arm_ccfsm_state += 2;
7464         return \"\";
7465       }
7466     return \"b%?\\t%l0\";
7467   }
7468   "
7469   [(set_attr "predicable" "yes")]
7470 )
7471
7472 (define_insn "*thumb_jump"
7473   [(set (pc)
7474         (label_ref (match_operand 0 "" "")))]
7475   "TARGET_THUMB"
7476   "*
7477   if (get_attr_length (insn) == 2)
7478     return \"b\\t%l0\";
7479   return \"bl\\t%l0\\t%@ far jump\";
7480   "
7481   [(set (attr "far_jump")
7482         (if_then_else
7483             (eq_attr "length" "4")
7484             (const_string "yes")
7485             (const_string "no")))
7486    (set (attr "length") 
7487         (if_then_else
7488             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7489                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
7490             (const_int 2)
7491             (const_int 4)))]
7492 )
7493
7494 (define_expand "call"
7495   [(parallel [(call (match_operand 0 "memory_operand" "")
7496                     (match_operand 1 "general_operand" ""))
7497               (use (match_operand 2 "" ""))
7498               (clobber (reg:SI LR_REGNUM))])]
7499   "TARGET_EITHER"
7500   "
7501   {
7502     rtx callee;
7503     
7504     /* In an untyped call, we can get NULL for operand 2.  */
7505     if (operands[2] == NULL_RTX)
7506       operands[2] = const0_rtx;
7507       
7508     /* This is to decide if we should generate indirect calls by loading the
7509        32 bit address of the callee into a register before performing the
7510        branch and link.  operand[2] encodes the long_call/short_call
7511        attribute of the function being called.  This attribute is set whenever
7512        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7513        is used, and the short_call attribute can also be set if function is
7514        declared as static or if it has already been defined in the current
7515        compilation unit.  See arm.c and arm.h for info about this.  The third
7516        parameter to arm_is_longcall_p is used to tell it which pattern
7517        invoked it.  */
7518     callee  = XEXP (operands[0], 0);
7519     
7520     if ((GET_CODE (callee) == SYMBOL_REF
7521          && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7522         || (GET_CODE (callee) != SYMBOL_REF
7523             && GET_CODE (callee) != REG))
7524       XEXP (operands[0], 0) = force_reg (Pmode, callee);
7525   }"
7526 )
7527
7528 (define_insn "*call_reg_armv5"
7529   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7530          (match_operand 1 "" ""))
7531    (use (match_operand 2 "" ""))
7532    (clobber (reg:SI LR_REGNUM))]
7533   "TARGET_ARM && arm_arch5"
7534   "blx%?\\t%0"
7535   [(set_attr "type" "call")]
7536 )
7537
7538 (define_insn "*call_reg_arm"
7539   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7540          (match_operand 1 "" ""))
7541    (use (match_operand 2 "" ""))
7542    (clobber (reg:SI LR_REGNUM))]
7543   "TARGET_ARM && !arm_arch5"
7544   "*
7545   return output_call (operands);
7546   "
7547   ;; length is worst case, normally it is only two
7548   [(set_attr "length" "12")
7549    (set_attr "type" "call")]
7550 )
7551
7552 (define_insn "*call_mem"
7553   [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7554          (match_operand 1 "" ""))
7555    (use (match_operand 2 "" ""))
7556    (clobber (reg:SI LR_REGNUM))]
7557   "TARGET_ARM"
7558   "*
7559   return output_call_mem (operands);
7560   "
7561   [(set_attr "length" "12")
7562    (set_attr "type" "call")]
7563 )
7564
7565 (define_insn "*call_reg_thumb_v5"
7566   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7567          (match_operand 1 "" ""))
7568    (use (match_operand 2 "" ""))
7569    (clobber (reg:SI LR_REGNUM))]
7570   "TARGET_THUMB && arm_arch5"
7571   "blx\\t%0"
7572   [(set_attr "length" "2")
7573    (set_attr "type" "call")]
7574 )
7575
7576 (define_insn "*call_reg_thumb"
7577   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7578          (match_operand 1 "" ""))
7579    (use (match_operand 2 "" ""))
7580    (clobber (reg:SI LR_REGNUM))]
7581   "TARGET_THUMB && !arm_arch5"
7582   "*
7583   {
7584     if (!TARGET_CALLER_INTERWORKING)
7585       return thumb_call_via_reg (operands[0]);
7586     else if (operands[1] == const0_rtx)
7587       return \"bl\\t%__interwork_call_via_%0\";
7588     else if (frame_pointer_needed)
7589       return \"bl\\t%__interwork_r7_call_via_%0\";
7590     else
7591       return \"bl\\t%__interwork_r11_call_via_%0\";
7592   }"
7593   [(set_attr "type" "call")]
7594 )
7595
7596 (define_expand "call_value"
7597   [(parallel [(set (match_operand       0 "" "")
7598                    (call (match_operand 1 "memory_operand" "")
7599                          (match_operand 2 "general_operand" "")))
7600               (use (match_operand 3 "" ""))
7601               (clobber (reg:SI LR_REGNUM))])]
7602   "TARGET_EITHER"
7603   "
7604   {
7605     rtx callee = XEXP (operands[1], 0);
7606     
7607     /* In an untyped call, we can get NULL for operand 2.  */
7608     if (operands[3] == 0)
7609       operands[3] = const0_rtx;
7610       
7611     /* See the comment in define_expand \"call\".  */
7612     if ((GET_CODE (callee) == SYMBOL_REF
7613          && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7614         || (GET_CODE (callee) != SYMBOL_REF
7615             && GET_CODE (callee) != REG))
7616       XEXP (operands[1], 0) = force_reg (Pmode, callee);
7617   }"
7618 )
7619
7620 (define_insn "*call_value_reg_armv5"
7621   [(set (match_operand 0 "" "")
7622         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7623               (match_operand 2 "" "")))
7624    (use (match_operand 3 "" ""))
7625    (clobber (reg:SI LR_REGNUM))]
7626   "TARGET_ARM && arm_arch5"
7627   "blx%?\\t%1"
7628   [(set_attr "type" "call")]
7629 )
7630
7631 (define_insn "*call_value_reg_arm"
7632   [(set (match_operand 0 "" "")
7633         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7634               (match_operand 2 "" "")))
7635    (use (match_operand 3 "" ""))
7636    (clobber (reg:SI LR_REGNUM))]
7637   "TARGET_ARM && !arm_arch5"
7638   "*
7639   return output_call (&operands[1]);
7640   "
7641   [(set_attr "length" "12")
7642    (set_attr "type" "call")]
7643 )
7644
7645 (define_insn "*call_value_mem"
7646   [(set (match_operand 0 "" "")
7647         (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7648               (match_operand 2 "" "")))
7649    (use (match_operand 3 "" ""))
7650    (clobber (reg:SI LR_REGNUM))]
7651   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7652   "*
7653   return output_call_mem (&operands[1]);
7654   "
7655   [(set_attr "length" "12")
7656    (set_attr "type" "call")]
7657 )
7658
7659 (define_insn "*call_value_reg_thumb_v5"
7660   [(set (match_operand 0 "" "")
7661         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7662               (match_operand 2 "" "")))
7663    (use (match_operand 3 "" ""))
7664    (clobber (reg:SI LR_REGNUM))]
7665   "TARGET_THUMB && arm_arch5"
7666   "blx\\t%1"
7667   [(set_attr "length" "2")
7668    (set_attr "type" "call")]
7669 )
7670
7671 (define_insn "*call_value_reg_thumb"
7672   [(set (match_operand 0 "" "")
7673         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7674               (match_operand 2 "" "")))
7675    (use (match_operand 3 "" ""))
7676    (clobber (reg:SI LR_REGNUM))]
7677   "TARGET_THUMB && !arm_arch5"
7678   "*
7679   {
7680     if (!TARGET_CALLER_INTERWORKING)
7681       return thumb_call_via_reg (operands[1]);
7682     else if (operands[2] == const0_rtx)
7683       return \"bl\\t%__interwork_call_via_%1\";
7684     else if (frame_pointer_needed)
7685       return \"bl\\t%__interwork_r7_call_via_%1\";
7686     else
7687       return \"bl\\t%__interwork_r11_call_via_%1\";
7688   }"
7689   [(set_attr "type" "call")]
7690 )
7691
7692 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7693 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7694
7695 (define_insn "*call_symbol"
7696   [(call (mem:SI (match_operand:SI 0 "" ""))
7697          (match_operand 1 "" ""))
7698    (use (match_operand 2 "" ""))
7699    (clobber (reg:SI LR_REGNUM))]
7700   "TARGET_ARM
7701    && (GET_CODE (operands[0]) == SYMBOL_REF)
7702    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7703   "*
7704   {
7705     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7706   }"
7707   [(set_attr "type" "call")]
7708 )
7709
7710 (define_insn "*call_value_symbol"
7711   [(set (match_operand 0 "" "")
7712         (call (mem:SI (match_operand:SI 1 "" ""))
7713         (match_operand:SI 2 "" "")))
7714    (use (match_operand 3 "" ""))
7715    (clobber (reg:SI LR_REGNUM))]
7716   "TARGET_ARM
7717    && (GET_CODE (operands[1]) == SYMBOL_REF)
7718    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7719   "*
7720   {
7721     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7722   }"
7723   [(set_attr "type" "call")]
7724 )
7725
7726 (define_insn "*call_insn"
7727   [(call (mem:SI (match_operand:SI 0 "" ""))
7728          (match_operand:SI 1 "" ""))
7729    (use (match_operand 2 "" ""))
7730    (clobber (reg:SI LR_REGNUM))]
7731   "TARGET_THUMB
7732    && GET_CODE (operands[0]) == SYMBOL_REF
7733    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7734   "bl\\t%a0"
7735   [(set_attr "length" "4")
7736    (set_attr "type" "call")]
7737 )
7738
7739 (define_insn "*call_value_insn"
7740   [(set (match_operand 0 "" "")
7741         (call (mem:SI (match_operand 1 "" ""))
7742               (match_operand 2 "" "")))
7743    (use (match_operand 3 "" ""))
7744    (clobber (reg:SI LR_REGNUM))]
7745   "TARGET_THUMB
7746    && GET_CODE (operands[1]) == SYMBOL_REF
7747    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7748   "bl\\t%a1"
7749   [(set_attr "length" "4")
7750    (set_attr "type" "call")]
7751 )
7752
7753 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7754 (define_expand "sibcall"
7755   [(parallel [(call (match_operand 0 "memory_operand" "")
7756                     (match_operand 1 "general_operand" ""))
7757               (return)
7758               (use (match_operand 2 "" ""))])]
7759   "TARGET_ARM"
7760   "
7761   {
7762     if (operands[2] == NULL_RTX)
7763       operands[2] = const0_rtx;
7764   }"
7765 )
7766
7767 (define_expand "sibcall_value"
7768   [(parallel [(set (match_operand 0 "" "")
7769                    (call (match_operand 1 "memory_operand" "")
7770                          (match_operand 2 "general_operand" "")))
7771               (return)
7772               (use (match_operand 3 "" ""))])]
7773   "TARGET_ARM"
7774   "
7775   {
7776     if (operands[3] == NULL_RTX)
7777       operands[3] = const0_rtx;
7778   }"
7779 )
7780
7781 (define_insn "*sibcall_insn"
7782  [(call (mem:SI (match_operand:SI 0 "" "X"))
7783         (match_operand 1 "" ""))
7784   (return)
7785   (use (match_operand 2 "" ""))]
7786   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7787   "*
7788   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7789   "
7790   [(set_attr "type" "call")]
7791 )
7792
7793 (define_insn "*sibcall_value_insn"
7794  [(set (match_operand 0 "" "")
7795        (call (mem:SI (match_operand:SI 1 "" "X"))
7796              (match_operand 2 "" "")))
7797   (return)
7798   (use (match_operand 3 "" ""))]
7799   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7800   "*
7801   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7802   "
7803   [(set_attr "type" "call")]
7804 )
7805
7806 ;; Often the return insn will be the same as loading from memory, so set attr
7807 (define_insn "return"
7808   [(return)]
7809   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7810   "*
7811   {
7812     if (arm_ccfsm_state == 2)
7813       {
7814         arm_ccfsm_state += 2;
7815         return \"\";
7816       }
7817     return output_return_instruction (const_true_rtx, TRUE, FALSE);
7818   }"
7819   [(set_attr "type" "load1")
7820    (set_attr "length" "12")
7821    (set_attr "predicable" "yes")]
7822 )
7823
7824 (define_insn "*cond_return"
7825   [(set (pc)
7826         (if_then_else (match_operator 0 "arm_comparison_operator"
7827                        [(match_operand 1 "cc_register" "") (const_int 0)])
7828                       (return)
7829                       (pc)))]
7830   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7831   "*
7832   {
7833     if (arm_ccfsm_state == 2)
7834       {
7835         arm_ccfsm_state += 2;
7836         return \"\";
7837       }
7838     return output_return_instruction (operands[0], TRUE, FALSE);
7839   }"
7840   [(set_attr "conds" "use")
7841    (set_attr "length" "12")
7842    (set_attr "type" "load1")]
7843 )
7844
7845 (define_insn "*cond_return_inverted"
7846   [(set (pc)
7847         (if_then_else (match_operator 0 "arm_comparison_operator"
7848                        [(match_operand 1 "cc_register" "") (const_int 0)])
7849                       (pc)
7850                       (return)))]
7851   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7852   "*
7853   {
7854     if (arm_ccfsm_state == 2)
7855       {
7856         arm_ccfsm_state += 2;
7857         return \"\";
7858       }
7859     return output_return_instruction (operands[0], TRUE, TRUE);
7860   }"
7861   [(set_attr "conds" "use")
7862    (set_attr "length" "12")
7863    (set_attr "type" "load1")]
7864 )
7865
7866 ;; Generate a sequence of instructions to determine if the processor is
7867 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7868 ;; mask.
7869
7870 (define_expand "return_addr_mask"
7871   [(set (match_dup 1)
7872       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7873                        (const_int 0)))
7874    (set (match_operand:SI 0 "s_register_operand" "")
7875       (if_then_else:SI (eq (match_dup 1) (const_int 0))
7876                        (const_int -1)
7877                        (const_int 67108860)))] ; 0x03fffffc
7878   "TARGET_ARM"
7879   "
7880   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7881   ")
7882
7883 (define_insn "*check_arch2"
7884   [(set (match_operand:CC_NOOV 0 "cc_register" "")
7885       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7886                        (const_int 0)))]
7887   "TARGET_ARM"
7888   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7889   [(set_attr "length" "8")
7890    (set_attr "conds" "set")]
7891 )
7892
7893 ;; Call subroutine returning any type.
7894
7895 (define_expand "untyped_call"
7896   [(parallel [(call (match_operand 0 "" "")
7897                     (const_int 0))
7898               (match_operand 1 "" "")
7899               (match_operand 2 "" "")])]
7900   "TARGET_EITHER"
7901   "
7902   {
7903     int i;
7904     rtx par = gen_rtx_PARALLEL (VOIDmode,
7905                                 rtvec_alloc (XVECLEN (operands[2], 0)));
7906     rtx addr = gen_reg_rtx (Pmode);
7907     rtx mem;
7908     int size = 0;
7909
7910     emit_move_insn (addr, XEXP (operands[1], 0));
7911     mem = change_address (operands[1], BLKmode, addr);
7912
7913     for (i = 0; i < XVECLEN (operands[2], 0); i++)
7914       {
7915         rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
7916
7917         /* Default code only uses r0 as a return value, but we could
7918            be using anything up to 4 registers.  */
7919         if (REGNO (src) == R0_REGNUM)
7920           src = gen_rtx_REG (TImode, R0_REGNUM);
7921
7922         XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
7923                                                  GEN_INT (size));
7924         size += GET_MODE_SIZE (GET_MODE (src));
7925       }
7926
7927     emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
7928                                     const0_rtx));
7929
7930     size = 0;
7931
7932     for (i = 0; i < XVECLEN (par, 0); i++)
7933       {
7934         HOST_WIDE_INT offset = 0;
7935         rtx reg = XEXP (XVECEXP (par, 0, i), 0);
7936
7937         if (size != 0)
7938           emit_move_insn (addr, plus_constant (addr, size));
7939
7940         mem = change_address (mem, GET_MODE (reg), NULL);
7941         if (REGNO (reg) == R0_REGNUM)
7942           {
7943             /* On thumb we have to use a write-back instruction.  */
7944             emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
7945                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7946             size = TARGET_ARM ? 16 : 0;
7947           }
7948         else
7949           {
7950             emit_move_insn (mem, reg);
7951             size = GET_MODE_SIZE (GET_MODE (reg));
7952           }
7953       }
7954
7955     /* The optimizer does not know that the call sets the function value
7956        registers we stored in the result block.  We avoid problems by
7957        claiming that all hard registers are used and clobbered at this
7958        point.  */
7959     emit_insn (gen_blockage ());
7960
7961     DONE;
7962   }"
7963 )
7964
7965 (define_expand "untyped_return"
7966   [(match_operand:BLK 0 "memory_operand" "")
7967    (match_operand 1 "" "")]
7968   "TARGET_EITHER"
7969   "
7970   {
7971     int i;
7972     rtx addr = gen_reg_rtx (Pmode);
7973     rtx mem;
7974     int size = 0;
7975
7976     emit_move_insn (addr, XEXP (operands[0], 0));
7977     mem = change_address (operands[0], BLKmode, addr);
7978
7979     for (i = 0; i < XVECLEN (operands[1], 0); i++)
7980       {
7981         HOST_WIDE_INT offset = 0;
7982         rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
7983
7984         if (size != 0)
7985           emit_move_insn (addr, plus_constant (addr, size));
7986
7987         mem = change_address (mem, GET_MODE (reg), NULL);
7988         if (REGNO (reg) == R0_REGNUM)
7989           {
7990             /* On thumb we have to use a write-back instruction.  */
7991             emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
7992                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7993             size = TARGET_ARM ? 16 : 0;
7994           }
7995         else
7996           {
7997             emit_move_insn (reg, mem);
7998             size = GET_MODE_SIZE (GET_MODE (reg));
7999           }
8000       }
8001
8002     /* Emit USE insns before the return.  */
8003     for (i = 0; i < XVECLEN (operands[1], 0); i++)
8004       emit_insn (gen_rtx_USE (VOIDmode,
8005                               SET_DEST (XVECEXP (operands[1], 0, i))));
8006
8007     /* Construct the return.  */
8008     expand_naked_return ();
8009
8010     DONE;
8011   }"
8012 )
8013
8014 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8015 ;; all of memory.  This blocks insns from being moved across this point.
8016
8017 (define_insn "blockage"
8018   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
8019   "TARGET_EITHER"
8020   ""
8021   [(set_attr "length" "0")
8022    (set_attr "type" "block")]
8023 )
8024
8025 (define_expand "casesi"
8026   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
8027    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
8028    (match_operand:SI 2 "const_int_operand" "")  ; total range
8029    (match_operand:SI 3 "" "")                   ; table label
8030    (match_operand:SI 4 "" "")]                  ; Out of range label
8031   "TARGET_ARM"
8032   "
8033   {
8034     rtx reg;
8035     if (operands[1] != const0_rtx)
8036       {
8037         reg = gen_reg_rtx (SImode);
8038
8039         emit_insn (gen_addsi3 (reg, operands[0],
8040                                GEN_INT (-INTVAL (operands[1]))));
8041         operands[0] = reg;
8042       }
8043
8044     if (!const_ok_for_arm (INTVAL (operands[2])))
8045       operands[2] = force_reg (SImode, operands[2]);
8046
8047     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
8048                                          operands[4]));
8049     DONE;
8050   }"
8051 )
8052
8053 ;; The USE in this pattern is needed to tell flow analysis that this is
8054 ;; a CASESI insn.  It has no other purpose.
8055 (define_insn "casesi_internal"
8056   [(parallel [(set (pc)
8057                (if_then_else
8058                 (leu (match_operand:SI 0 "s_register_operand" "r")
8059                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
8060                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8061                                  (label_ref (match_operand 2 "" ""))))
8062                 (label_ref (match_operand 3 "" ""))))
8063               (clobber (reg:CC CC_REGNUM))
8064               (use (label_ref (match_dup 2)))])]
8065   "TARGET_ARM"
8066   "*
8067     if (flag_pic)
8068       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8069     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8070   "
8071   [(set_attr "conds" "clob")
8072    (set_attr "length" "12")]
8073 )
8074
8075 (define_expand "indirect_jump"
8076   [(set (pc)
8077         (match_operand:SI 0 "s_register_operand" ""))]
8078   "TARGET_EITHER"
8079   ""
8080 )
8081
8082 ;; NB Never uses BX.
8083 (define_insn "*arm_indirect_jump"
8084   [(set (pc)
8085         (match_operand:SI 0 "s_register_operand" "r"))]
8086   "TARGET_ARM"
8087   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
8088   [(set_attr "predicable" "yes")]
8089 )
8090
8091 (define_insn "*load_indirect_jump"
8092   [(set (pc)
8093         (match_operand:SI 0 "memory_operand" "m"))]
8094   "TARGET_ARM"
8095   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
8096   [(set_attr "type" "load1")
8097    (set_attr "pool_range" "4096")
8098    (set_attr "neg_pool_range" "4084")
8099    (set_attr "predicable" "yes")]
8100 )
8101
8102 ;; NB Never uses BX.
8103 (define_insn "*thumb_indirect_jump"
8104   [(set (pc)
8105         (match_operand:SI 0 "register_operand" "l*r"))]
8106   "TARGET_THUMB"
8107   "mov\\tpc, %0"
8108   [(set_attr "conds" "clob")
8109    (set_attr "length" "2")]
8110 )
8111
8112 \f
8113 ;; Misc insns
8114
8115 (define_insn "nop"
8116   [(const_int 0)]
8117   "TARGET_EITHER"
8118   "*
8119   if (TARGET_ARM)
8120     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8121   return  \"mov\\tr8, r8\";
8122   "
8123   [(set (attr "length")
8124         (if_then_else (eq_attr "is_thumb" "yes")
8125                       (const_int 2)
8126                       (const_int 4)))]
8127 )
8128
8129 \f
8130 ;; Patterns to allow combination of arithmetic, cond code and shifts
8131
8132 (define_insn "*arith_shiftsi"
8133   [(set (match_operand:SI 0 "s_register_operand" "=r")
8134         (match_operator:SI 1 "shiftable_operator"
8135           [(match_operator:SI 3 "shift_operator"
8136              [(match_operand:SI 4 "s_register_operand" "r")
8137               (match_operand:SI 5 "reg_or_int_operand" "rI")])
8138            (match_operand:SI 2 "s_register_operand" "r")]))]
8139   "TARGET_ARM"
8140   "%i1%?\\t%0, %2, %4%S3"
8141   [(set_attr "predicable" "yes")
8142    (set_attr "shift" "4")
8143    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8144                       (const_string "alu_shift")
8145                       (const_string "alu_shift_reg")))]
8146 )
8147
8148 (define_split
8149   [(set (match_operand:SI 0 "s_register_operand" "")
8150         (match_operator:SI 1 "shiftable_operator"
8151          [(match_operator:SI 2 "shiftable_operator"
8152            [(match_operator:SI 3 "shift_operator"
8153              [(match_operand:SI 4 "s_register_operand" "")
8154               (match_operand:SI 5 "reg_or_int_operand" "")])
8155             (match_operand:SI 6 "s_register_operand" "")])
8156           (match_operand:SI 7 "arm_rhs_operand" "")]))
8157    (clobber (match_operand:SI 8 "s_register_operand" ""))]
8158   "TARGET_ARM"
8159   [(set (match_dup 8)
8160         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8161                          (match_dup 6)]))
8162    (set (match_dup 0)
8163         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8164   "")
8165
8166 (define_insn "*arith_shiftsi_compare0"
8167   [(set (reg:CC_NOOV CC_REGNUM)
8168         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8169                           [(match_operator:SI 3 "shift_operator"
8170                             [(match_operand:SI 4 "s_register_operand" "r")
8171                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8172                            (match_operand:SI 2 "s_register_operand" "r")])
8173                          (const_int 0)))
8174    (set (match_operand:SI 0 "s_register_operand" "=r")
8175         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8176                          (match_dup 2)]))]
8177   "TARGET_ARM"
8178   "%i1%?s\\t%0, %2, %4%S3"
8179   [(set_attr "conds" "set")
8180    (set_attr "shift" "4")
8181    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8182                       (const_string "alu_shift")
8183                       (const_string "alu_shift_reg")))]
8184 )
8185
8186 (define_insn "*arith_shiftsi_compare0_scratch"
8187   [(set (reg:CC_NOOV CC_REGNUM)
8188         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8189                           [(match_operator:SI 3 "shift_operator"
8190                             [(match_operand:SI 4 "s_register_operand" "r")
8191                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8192                            (match_operand:SI 2 "s_register_operand" "r")])
8193                          (const_int 0)))
8194    (clobber (match_scratch:SI 0 "=r"))]
8195   "TARGET_ARM"
8196   "%i1%?s\\t%0, %2, %4%S3"
8197   [(set_attr "conds" "set")
8198    (set_attr "shift" "4")
8199    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8200                       (const_string "alu_shift")
8201                       (const_string "alu_shift_reg")))]
8202 )
8203
8204 (define_insn "*sub_shiftsi"
8205   [(set (match_operand:SI 0 "s_register_operand" "=r")
8206         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8207                   (match_operator:SI 2 "shift_operator"
8208                    [(match_operand:SI 3 "s_register_operand" "r")
8209                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
8210   "TARGET_ARM"
8211   "sub%?\\t%0, %1, %3%S2"
8212   [(set_attr "predicable" "yes")
8213    (set_attr "shift" "3")
8214    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8215                       (const_string "alu_shift")
8216                       (const_string "alu_shift_reg")))]
8217 )
8218
8219 (define_insn "*sub_shiftsi_compare0"
8220   [(set (reg:CC_NOOV CC_REGNUM)
8221         (compare:CC_NOOV
8222          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8223                    (match_operator:SI 2 "shift_operator"
8224                     [(match_operand:SI 3 "s_register_operand" "r")
8225                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8226          (const_int 0)))
8227    (set (match_operand:SI 0 "s_register_operand" "=r")
8228         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8229                                                  (match_dup 4)])))]
8230   "TARGET_ARM"
8231   "sub%?s\\t%0, %1, %3%S2"
8232   [(set_attr "conds" "set")
8233    (set_attr "shift" "3")
8234    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8235                       (const_string "alu_shift")
8236                       (const_string "alu_shift_reg")))]
8237 )
8238
8239 (define_insn "*sub_shiftsi_compare0_scratch"
8240   [(set (reg:CC_NOOV CC_REGNUM)
8241         (compare:CC_NOOV
8242          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8243                    (match_operator:SI 2 "shift_operator"
8244                     [(match_operand:SI 3 "s_register_operand" "r")
8245                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8246          (const_int 0)))
8247    (clobber (match_scratch:SI 0 "=r"))]
8248   "TARGET_ARM"
8249   "sub%?s\\t%0, %1, %3%S2"
8250   [(set_attr "conds" "set")
8251    (set_attr "shift" "3")
8252    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8253                       (const_string "alu_shift")
8254                       (const_string "alu_shift_reg")))]
8255 )
8256
8257 \f
8258
8259 (define_insn "*and_scc"
8260   [(set (match_operand:SI 0 "s_register_operand" "=r")
8261         (and:SI (match_operator:SI 1 "arm_comparison_operator"
8262                  [(match_operand 3 "cc_register" "") (const_int 0)])
8263                 (match_operand:SI 2 "s_register_operand" "r")))]
8264   "TARGET_ARM"
8265   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8266   [(set_attr "conds" "use")
8267    (set_attr "length" "8")]
8268 )
8269
8270 (define_insn "*ior_scc"
8271   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8272         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8273                  [(match_operand 3 "cc_register" "") (const_int 0)])
8274                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8275   "TARGET_ARM"
8276   "@
8277    orr%d2\\t%0, %1, #1
8278    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8279   [(set_attr "conds" "use")
8280    (set_attr "length" "4,8")]
8281 )
8282
8283 (define_insn "*compare_scc"
8284   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8285         (match_operator:SI 1 "arm_comparison_operator"
8286          [(match_operand:SI 2 "s_register_operand" "r,r")
8287           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8288    (clobber (reg:CC CC_REGNUM))]
8289   "TARGET_ARM"
8290   "*
8291     if (operands[3] == const0_rtx)
8292       {
8293         if (GET_CODE (operands[1]) == LT)
8294           return \"mov\\t%0, %2, lsr #31\";
8295
8296         if (GET_CODE (operands[1]) == GE)
8297           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8298
8299         if (GET_CODE (operands[1]) == EQ)
8300           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8301       }
8302
8303     if (GET_CODE (operands[1]) == NE)
8304       {
8305         if (which_alternative == 1)
8306           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8307         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8308       }
8309     if (which_alternative == 1)
8310       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8311     else
8312       output_asm_insn (\"cmp\\t%2, %3\", operands);
8313     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8314   "
8315   [(set_attr "conds" "clob")
8316    (set_attr "length" "12")]
8317 )
8318
8319 (define_insn "*cond_move"
8320   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8321         (if_then_else:SI (match_operator 3 "equality_operator"
8322                           [(match_operator 4 "arm_comparison_operator"
8323                             [(match_operand 5 "cc_register" "") (const_int 0)])
8324                            (const_int 0)])
8325                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8326                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8327   "TARGET_ARM"
8328   "*
8329     if (GET_CODE (operands[3]) == NE)
8330       {
8331         if (which_alternative != 1)
8332           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8333         if (which_alternative != 0)
8334           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8335         return \"\";
8336       }
8337     if (which_alternative != 0)
8338       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8339     if (which_alternative != 1)
8340       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8341     return \"\";
8342   "
8343   [(set_attr "conds" "use")
8344    (set_attr "length" "4,4,8")]
8345 )
8346
8347 (define_insn "*cond_arith"
8348   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8349         (match_operator:SI 5 "shiftable_operator" 
8350          [(match_operator:SI 4 "arm_comparison_operator"
8351            [(match_operand:SI 2 "s_register_operand" "r,r")
8352             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8353           (match_operand:SI 1 "s_register_operand" "0,?r")]))
8354    (clobber (reg:CC CC_REGNUM))]
8355   "TARGET_ARM"
8356   "*
8357     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8358       return \"%i5\\t%0, %1, %2, lsr #31\";
8359
8360     output_asm_insn (\"cmp\\t%2, %3\", operands);
8361     if (GET_CODE (operands[5]) == AND)
8362       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8363     else if (GET_CODE (operands[5]) == MINUS)
8364       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8365     else if (which_alternative != 0)
8366       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8367     return \"%i5%d4\\t%0, %1, #1\";
8368   "
8369   [(set_attr "conds" "clob")
8370    (set_attr "length" "12")]
8371 )
8372
8373 (define_insn "*cond_sub"
8374   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8375         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8376                   (match_operator:SI 4 "arm_comparison_operator"
8377                    [(match_operand:SI 2 "s_register_operand" "r,r")
8378                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8379    (clobber (reg:CC CC_REGNUM))]
8380   "TARGET_ARM"
8381   "*
8382     output_asm_insn (\"cmp\\t%2, %3\", operands);
8383     if (which_alternative != 0)
8384       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8385     return \"sub%d4\\t%0, %1, #1\";
8386   "
8387   [(set_attr "conds" "clob")
8388    (set_attr "length" "8,12")]
8389 )
8390
8391 (define_insn "*cmp_ite0"
8392   [(set (match_operand 6 "dominant_cc_register" "")
8393         (compare
8394          (if_then_else:SI
8395           (match_operator 4 "arm_comparison_operator"
8396            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8397             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8398           (match_operator:SI 5 "arm_comparison_operator"
8399            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8400             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8401           (const_int 0))
8402          (const_int 0)))]
8403   "TARGET_ARM"
8404   "*
8405   {
8406     static const char * const opcodes[4][2] =
8407     {
8408       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8409        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8410       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8411        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8412       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8413        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8414       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8415        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8416     };
8417     int swap =
8418       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8419
8420     return opcodes[which_alternative][swap];
8421   }"
8422   [(set_attr "conds" "set")
8423    (set_attr "length" "8")]
8424 )
8425
8426 (define_insn "*cmp_ite1"
8427   [(set (match_operand 6 "dominant_cc_register" "")
8428         (compare
8429          (if_then_else:SI
8430           (match_operator 4 "arm_comparison_operator"
8431            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8432             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8433           (match_operator:SI 5 "arm_comparison_operator"
8434            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8435             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8436           (const_int 1))
8437          (const_int 0)))]
8438   "TARGET_ARM"
8439   "*
8440   {
8441     static const char * const opcodes[4][2] =
8442     {
8443       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8444        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8445       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8446        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8447       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8448        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8449       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8450        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8451     };
8452     int swap =
8453       comparison_dominates_p (GET_CODE (operands[5]),
8454                               reverse_condition (GET_CODE (operands[4])));
8455
8456     return opcodes[which_alternative][swap];
8457   }"
8458   [(set_attr "conds" "set")
8459    (set_attr "length" "8")]
8460 )
8461
8462 (define_insn "*cmp_and"
8463   [(set (match_operand 6 "dominant_cc_register" "")
8464         (compare
8465          (and:SI
8466           (match_operator 4 "arm_comparison_operator"
8467            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8468             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8469           (match_operator:SI 5 "arm_comparison_operator"
8470            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8471             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8472          (const_int 0)))]
8473   "TARGET_ARM"
8474   "*
8475   {
8476     static const char *const opcodes[4][2] =
8477     {
8478       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8479        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8480       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8481        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8482       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8483        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8484       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8485        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8486     };
8487     int swap =
8488       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8489
8490     return opcodes[which_alternative][swap];
8491   }"
8492   [(set_attr "conds" "set")
8493    (set_attr "predicable" "no")
8494    (set_attr "length" "8")]
8495 )
8496
8497 (define_insn "*cmp_ior"
8498   [(set (match_operand 6 "dominant_cc_register" "")
8499         (compare
8500          (ior:SI
8501           (match_operator 4 "arm_comparison_operator"
8502            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8503             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8504           (match_operator:SI 5 "arm_comparison_operator"
8505            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8506             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8507          (const_int 0)))]
8508   "TARGET_ARM"
8509   "*
8510 {
8511   static const char *const opcodes[4][2] =
8512   {
8513     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8514      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8515     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8516      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8517     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8518      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8519     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8520      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8521   };
8522   int swap =
8523     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8524
8525   return opcodes[which_alternative][swap];
8526 }
8527 "
8528   [(set_attr "conds" "set")
8529    (set_attr "length" "8")]
8530 )
8531
8532 (define_insn_and_split "*ior_scc_scc"
8533   [(set (match_operand:SI 0 "s_register_operand" "=r")
8534         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8535                  [(match_operand:SI 1 "s_register_operand" "r")
8536                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8537                 (match_operator:SI 6 "arm_comparison_operator"
8538                  [(match_operand:SI 4 "s_register_operand" "r")
8539                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8540    (clobber (reg:CC CC_REGNUM))]
8541   "TARGET_ARM
8542    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8543        != CCmode)"
8544   "#"
8545   "TARGET_ARM && reload_completed"
8546   [(set (match_dup 7)
8547         (compare
8548          (ior:SI
8549           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8550           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8551          (const_int 0)))
8552    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8553   "operands[7]
8554      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8555                                                   DOM_CC_X_OR_Y),
8556                     CC_REGNUM);"
8557   [(set_attr "conds" "clob")
8558    (set_attr "length" "16")])
8559
8560 ; If the above pattern is followed by a CMP insn, then the compare is 
8561 ; redundant, since we can rework the conditional instruction that follows.
8562 (define_insn_and_split "*ior_scc_scc_cmp"
8563   [(set (match_operand 0 "dominant_cc_register" "")
8564         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8565                           [(match_operand:SI 1 "s_register_operand" "r")
8566                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8567                          (match_operator:SI 6 "arm_comparison_operator"
8568                           [(match_operand:SI 4 "s_register_operand" "r")
8569                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8570                  (const_int 0)))
8571    (set (match_operand:SI 7 "s_register_operand" "=r")
8572         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8573                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8574   "TARGET_ARM"
8575   "#"
8576   "TARGET_ARM && reload_completed"
8577   [(set (match_dup 0)
8578         (compare
8579          (ior:SI
8580           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8581           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8582          (const_int 0)))
8583    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8584   ""
8585   [(set_attr "conds" "set")
8586    (set_attr "length" "16")])
8587
8588 (define_insn_and_split "*and_scc_scc"
8589   [(set (match_operand:SI 0 "s_register_operand" "=r")
8590         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8591                  [(match_operand:SI 1 "s_register_operand" "r")
8592                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8593                 (match_operator:SI 6 "arm_comparison_operator"
8594                  [(match_operand:SI 4 "s_register_operand" "r")
8595                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8596    (clobber (reg:CC CC_REGNUM))]
8597   "TARGET_ARM
8598    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8599        != CCmode)"
8600   "#"
8601   "TARGET_ARM && reload_completed
8602    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8603        != CCmode)"
8604   [(set (match_dup 7)
8605         (compare
8606          (and:SI
8607           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8608           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8609          (const_int 0)))
8610    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8611   "operands[7]
8612      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8613                                                   DOM_CC_X_AND_Y),
8614                     CC_REGNUM);"
8615   [(set_attr "conds" "clob")
8616    (set_attr "length" "16")])
8617
8618 ; If the above pattern is followed by a CMP insn, then the compare is 
8619 ; redundant, since we can rework the conditional instruction that follows.
8620 (define_insn_and_split "*and_scc_scc_cmp"
8621   [(set (match_operand 0 "dominant_cc_register" "")
8622         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8623                           [(match_operand:SI 1 "s_register_operand" "r")
8624                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8625                          (match_operator:SI 6 "arm_comparison_operator"
8626                           [(match_operand:SI 4 "s_register_operand" "r")
8627                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8628                  (const_int 0)))
8629    (set (match_operand:SI 7 "s_register_operand" "=r")
8630         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8631                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8632   "TARGET_ARM"
8633   "#"
8634   "TARGET_ARM && reload_completed"
8635   [(set (match_dup 0)
8636         (compare
8637          (and:SI
8638           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8639           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8640          (const_int 0)))
8641    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8642   ""
8643   [(set_attr "conds" "set")
8644    (set_attr "length" "16")])
8645
8646 ;; If there is no dominance in the comparison, then we can still save an
8647 ;; instruction in the AND case, since we can know that the second compare
8648 ;; need only zero the value if false (if true, then the value is already
8649 ;; correct).
8650 (define_insn_and_split "*and_scc_scc_nodom"
8651   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8652         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8653                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
8654                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8655                 (match_operator:SI 6 "arm_comparison_operator"
8656                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
8657                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8658    (clobber (reg:CC CC_REGNUM))]
8659   "TARGET_ARM
8660    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8661        == CCmode)"
8662   "#"
8663   "TARGET_ARM && reload_completed"
8664   [(parallel [(set (match_dup 0)
8665                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8666               (clobber (reg:CC CC_REGNUM))])
8667    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8668    (set (match_dup 0)
8669         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8670                          (match_dup 0)
8671                          (const_int 0)))]
8672   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8673                                               operands[4], operands[5]),
8674                               CC_REGNUM);
8675    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8676                                   operands[5]);"
8677   [(set_attr "conds" "clob")
8678    (set_attr "length" "20")])
8679
8680 (define_split
8681   [(set (reg:CC_NOOV CC_REGNUM)
8682         (compare:CC_NOOV (ior:SI
8683                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8684                                   (const_int 1))
8685                           (match_operator:SI 1 "comparison_operator"
8686                            [(match_operand:SI 2 "s_register_operand" "")
8687                             (match_operand:SI 3 "arm_add_operand" "")]))
8688                          (const_int 0)))
8689    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8690   "TARGET_ARM"
8691   [(set (match_dup 4)
8692         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8693                 (match_dup 0)))
8694    (set (reg:CC_NOOV CC_REGNUM)
8695         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8696                          (const_int 0)))]
8697   "")
8698
8699 (define_split
8700   [(set (reg:CC_NOOV CC_REGNUM)
8701         (compare:CC_NOOV (ior:SI
8702                           (match_operator:SI 1 "comparison_operator"
8703                            [(match_operand:SI 2 "s_register_operand" "")
8704                             (match_operand:SI 3 "arm_add_operand" "")])
8705                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8706                                   (const_int 1)))
8707                          (const_int 0)))
8708    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8709   "TARGET_ARM"
8710   [(set (match_dup 4)
8711         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8712                 (match_dup 0)))
8713    (set (reg:CC_NOOV CC_REGNUM)
8714         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8715                          (const_int 0)))]
8716   "")
8717
8718 (define_insn "*negscc"
8719   [(set (match_operand:SI 0 "s_register_operand" "=r")
8720         (neg:SI (match_operator 3 "arm_comparison_operator"
8721                  [(match_operand:SI 1 "s_register_operand" "r")
8722                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8723    (clobber (reg:CC CC_REGNUM))]
8724   "TARGET_ARM"
8725   "*
8726   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8727     return \"mov\\t%0, %1, asr #31\";
8728
8729   if (GET_CODE (operands[3]) == NE)
8730     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8731
8732   if (GET_CODE (operands[3]) == GT)
8733     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8734
8735   output_asm_insn (\"cmp\\t%1, %2\", operands);
8736   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8737   return \"mvn%d3\\t%0, #0\";
8738   "
8739   [(set_attr "conds" "clob")
8740    (set_attr "length" "12")]
8741 )
8742
8743 (define_insn "movcond"
8744   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8745         (if_then_else:SI
8746          (match_operator 5 "arm_comparison_operator"
8747           [(match_operand:SI 3 "s_register_operand" "r,r,r")
8748            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8749          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8750          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8751    (clobber (reg:CC CC_REGNUM))]
8752   "TARGET_ARM"
8753   "*
8754   if (GET_CODE (operands[5]) == LT
8755       && (operands[4] == const0_rtx))
8756     {
8757       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8758         {
8759           if (operands[2] == const0_rtx)
8760             return \"and\\t%0, %1, %3, asr #31\";
8761           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8762         }
8763       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8764         {
8765           if (operands[1] == const0_rtx)
8766             return \"bic\\t%0, %2, %3, asr #31\";
8767           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8768         }
8769       /* The only case that falls through to here is when both ops 1 & 2
8770          are constants.  */
8771     }
8772
8773   if (GET_CODE (operands[5]) == GE
8774       && (operands[4] == const0_rtx))
8775     {
8776       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8777         {
8778           if (operands[2] == const0_rtx)
8779             return \"bic\\t%0, %1, %3, asr #31\";
8780           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8781         }
8782       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8783         {
8784           if (operands[1] == const0_rtx)
8785             return \"and\\t%0, %2, %3, asr #31\";
8786           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8787         }
8788       /* The only case that falls through to here is when both ops 1 & 2
8789          are constants.  */
8790     }
8791   if (GET_CODE (operands[4]) == CONST_INT
8792       && !const_ok_for_arm (INTVAL (operands[4])))
8793     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8794   else
8795     output_asm_insn (\"cmp\\t%3, %4\", operands);
8796   if (which_alternative != 0)
8797     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8798   if (which_alternative != 1)
8799     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8800   return \"\";
8801   "
8802   [(set_attr "conds" "clob")
8803    (set_attr "length" "8,8,12")]
8804 )
8805
8806 (define_insn "*ifcompare_plus_move"
8807   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8808         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8809                           [(match_operand:SI 4 "s_register_operand" "r,r")
8810                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8811                          (plus:SI
8812                           (match_operand:SI 2 "s_register_operand" "r,r")
8813                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8814                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8815    (clobber (reg:CC CC_REGNUM))]
8816   "TARGET_ARM"
8817   "#"
8818   [(set_attr "conds" "clob")
8819    (set_attr "length" "8,12")]
8820 )
8821
8822 (define_insn "*if_plus_move"
8823   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8824         (if_then_else:SI
8825          (match_operator 4 "arm_comparison_operator"
8826           [(match_operand 5 "cc_register" "") (const_int 0)])
8827          (plus:SI
8828           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8829           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8830          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8831   "TARGET_ARM"
8832   "@
8833    add%d4\\t%0, %2, %3
8834    sub%d4\\t%0, %2, #%n3
8835    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8836    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8837   [(set_attr "conds" "use")
8838    (set_attr "length" "4,4,8,8")
8839    (set_attr "type" "*,*,*,*")]
8840 )
8841
8842 (define_insn "*ifcompare_move_plus"
8843   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8844         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8845                           [(match_operand:SI 4 "s_register_operand" "r,r")
8846                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8847                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8848                          (plus:SI
8849                           (match_operand:SI 2 "s_register_operand" "r,r")
8850                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8851    (clobber (reg:CC CC_REGNUM))]
8852   "TARGET_ARM"
8853   "#"
8854   [(set_attr "conds" "clob")
8855    (set_attr "length" "8,12")]
8856 )
8857
8858 (define_insn "*if_move_plus"
8859   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8860         (if_then_else:SI
8861          (match_operator 4 "arm_comparison_operator"
8862           [(match_operand 5 "cc_register" "") (const_int 0)])
8863          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8864          (plus:SI
8865           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8866           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8867   "TARGET_ARM"
8868   "@
8869    add%D4\\t%0, %2, %3
8870    sub%D4\\t%0, %2, #%n3
8871    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8872    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8873   [(set_attr "conds" "use")
8874    (set_attr "length" "4,4,8,8")
8875    (set_attr "type" "*,*,*,*")]
8876 )
8877
8878 (define_insn "*ifcompare_arith_arith"
8879   [(set (match_operand:SI 0 "s_register_operand" "=r")
8880         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8881                           [(match_operand:SI 5 "s_register_operand" "r")
8882                            (match_operand:SI 6 "arm_add_operand" "rIL")])
8883                          (match_operator:SI 8 "shiftable_operator"
8884                           [(match_operand:SI 1 "s_register_operand" "r")
8885                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8886                          (match_operator:SI 7 "shiftable_operator"
8887                           [(match_operand:SI 3 "s_register_operand" "r")
8888                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8889    (clobber (reg:CC CC_REGNUM))]
8890   "TARGET_ARM"
8891   "#"
8892   [(set_attr "conds" "clob")
8893    (set_attr "length" "12")]
8894 )
8895
8896 (define_insn "*if_arith_arith"
8897   [(set (match_operand:SI 0 "s_register_operand" "=r")
8898         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8899                           [(match_operand 8 "cc_register" "") (const_int 0)])
8900                          (match_operator:SI 6 "shiftable_operator"
8901                           [(match_operand:SI 1 "s_register_operand" "r")
8902                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8903                          (match_operator:SI 7 "shiftable_operator"
8904                           [(match_operand:SI 3 "s_register_operand" "r")
8905                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8906   "TARGET_ARM"
8907   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8908   [(set_attr "conds" "use")
8909    (set_attr "length" "8")]
8910 )
8911
8912 (define_insn "*ifcompare_arith_move"
8913   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8914         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8915                           [(match_operand:SI 2 "s_register_operand" "r,r")
8916                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8917                          (match_operator:SI 7 "shiftable_operator"
8918                           [(match_operand:SI 4 "s_register_operand" "r,r")
8919                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8920                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8921    (clobber (reg:CC CC_REGNUM))]
8922   "TARGET_ARM"
8923   "*
8924   /* If we have an operation where (op x 0) is the identity operation and
8925      the conditional operator is LT or GE and we are comparing against zero and
8926      everything is in registers then we can do this in two instructions.  */
8927   if (operands[3] == const0_rtx
8928       && GET_CODE (operands[7]) != AND
8929       && GET_CODE (operands[5]) == REG
8930       && GET_CODE (operands[1]) == REG 
8931       && REGNO (operands[1]) == REGNO (operands[4])
8932       && REGNO (operands[4]) != REGNO (operands[0]))
8933     {
8934       if (GET_CODE (operands[6]) == LT)
8935         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8936       else if (GET_CODE (operands[6]) == GE)
8937         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8938     }
8939   if (GET_CODE (operands[3]) == CONST_INT
8940       && !const_ok_for_arm (INTVAL (operands[3])))
8941     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8942   else
8943     output_asm_insn (\"cmp\\t%2, %3\", operands);
8944   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8945   if (which_alternative != 0)
8946     return \"mov%D6\\t%0, %1\";
8947   return \"\";
8948   "
8949   [(set_attr "conds" "clob")
8950    (set_attr "length" "8,12")]
8951 )
8952
8953 (define_insn "*if_arith_move"
8954   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8955         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8956                           [(match_operand 6 "cc_register" "") (const_int 0)])
8957                          (match_operator:SI 5 "shiftable_operator"
8958                           [(match_operand:SI 2 "s_register_operand" "r,r")
8959                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8960                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8961   "TARGET_ARM"
8962   "@
8963    %I5%d4\\t%0, %2, %3
8964    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8965   [(set_attr "conds" "use")
8966    (set_attr "length" "4,8")
8967    (set_attr "type" "*,*")]
8968 )
8969
8970 (define_insn "*ifcompare_move_arith"
8971   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8972         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8973                           [(match_operand:SI 4 "s_register_operand" "r,r")
8974                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8975                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8976                          (match_operator:SI 7 "shiftable_operator"
8977                           [(match_operand:SI 2 "s_register_operand" "r,r")
8978                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8979    (clobber (reg:CC CC_REGNUM))]
8980   "TARGET_ARM"
8981   "*
8982   /* If we have an operation where (op x 0) is the identity operation and
8983      the conditional operator is LT or GE and we are comparing against zero and
8984      everything is in registers then we can do this in two instructions */
8985   if (operands[5] == const0_rtx
8986       && GET_CODE (operands[7]) != AND
8987       && GET_CODE (operands[3]) == REG
8988       && GET_CODE (operands[1]) == REG 
8989       && REGNO (operands[1]) == REGNO (operands[2])
8990       && REGNO (operands[2]) != REGNO (operands[0]))
8991     {
8992       if (GET_CODE (operands[6]) == GE)
8993         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8994       else if (GET_CODE (operands[6]) == LT)
8995         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8996     }
8997
8998   if (GET_CODE (operands[5]) == CONST_INT
8999       && !const_ok_for_arm (INTVAL (operands[5])))
9000     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9001   else
9002     output_asm_insn (\"cmp\\t%4, %5\", operands);
9003
9004   if (which_alternative != 0)
9005     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
9006   return \"%I7%D6\\t%0, %2, %3\";
9007   "
9008   [(set_attr "conds" "clob")
9009    (set_attr "length" "8,12")]
9010 )
9011
9012 (define_insn "*if_move_arith"
9013   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9014         (if_then_else:SI
9015          (match_operator 4 "arm_comparison_operator"
9016           [(match_operand 6 "cc_register" "") (const_int 0)])
9017          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9018          (match_operator:SI 5 "shiftable_operator"
9019           [(match_operand:SI 2 "s_register_operand" "r,r")
9020            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
9021   "TARGET_ARM"
9022   "@
9023    %I5%D4\\t%0, %2, %3
9024    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
9025   [(set_attr "conds" "use")
9026    (set_attr "length" "4,8")
9027    (set_attr "type" "*,*")]
9028 )
9029
9030 (define_insn "*ifcompare_move_not"
9031   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9032         (if_then_else:SI
9033          (match_operator 5 "arm_comparison_operator"
9034           [(match_operand:SI 3 "s_register_operand" "r,r")
9035            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9036          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9037          (not:SI
9038           (match_operand:SI 2 "s_register_operand" "r,r"))))
9039    (clobber (reg:CC CC_REGNUM))]
9040   "TARGET_ARM"
9041   "#"
9042   [(set_attr "conds" "clob")
9043    (set_attr "length" "8,12")]
9044 )
9045
9046 (define_insn "*if_move_not"
9047   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9048         (if_then_else:SI
9049          (match_operator 4 "arm_comparison_operator"
9050           [(match_operand 3 "cc_register" "") (const_int 0)])
9051          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9052          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9053   "TARGET_ARM"
9054   "@
9055    mvn%D4\\t%0, %2
9056    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9057    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
9058   [(set_attr "conds" "use")
9059    (set_attr "length" "4,8,8")]
9060 )
9061
9062 (define_insn "*ifcompare_not_move"
9063   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9064         (if_then_else:SI 
9065          (match_operator 5 "arm_comparison_operator"
9066           [(match_operand:SI 3 "s_register_operand" "r,r")
9067            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9068          (not:SI
9069           (match_operand:SI 2 "s_register_operand" "r,r"))
9070          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9071    (clobber (reg:CC CC_REGNUM))]
9072   "TARGET_ARM"
9073   "#"
9074   [(set_attr "conds" "clob")
9075    (set_attr "length" "8,12")]
9076 )
9077
9078 (define_insn "*if_not_move"
9079   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9080         (if_then_else:SI
9081          (match_operator 4 "arm_comparison_operator"
9082           [(match_operand 3 "cc_register" "") (const_int 0)])
9083          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9084          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9085   "TARGET_ARM"
9086   "@
9087    mvn%d4\\t%0, %2
9088    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9089    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
9090   [(set_attr "conds" "use")
9091    (set_attr "length" "4,8,8")]
9092 )
9093
9094 (define_insn "*ifcompare_shift_move"
9095   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9096         (if_then_else:SI
9097          (match_operator 6 "arm_comparison_operator"
9098           [(match_operand:SI 4 "s_register_operand" "r,r")
9099            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9100          (match_operator:SI 7 "shift_operator"
9101           [(match_operand:SI 2 "s_register_operand" "r,r")
9102            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9103          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9104    (clobber (reg:CC CC_REGNUM))]
9105   "TARGET_ARM"
9106   "#"
9107   [(set_attr "conds" "clob")
9108    (set_attr "length" "8,12")]
9109 )
9110
9111 (define_insn "*if_shift_move"
9112   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9113         (if_then_else:SI
9114          (match_operator 5 "arm_comparison_operator"
9115           [(match_operand 6 "cc_register" "") (const_int 0)])
9116          (match_operator:SI 4 "shift_operator"
9117           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9118            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9119          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9120   "TARGET_ARM"
9121   "@
9122    mov%d5\\t%0, %2%S4
9123    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9124    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
9125   [(set_attr "conds" "use")
9126    (set_attr "shift" "2")
9127    (set_attr "length" "4,8,8")
9128    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9129                       (const_string "alu_shift")
9130                       (const_string "alu_shift_reg")))]
9131 )
9132
9133 (define_insn "*ifcompare_move_shift"
9134   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9135         (if_then_else:SI
9136          (match_operator 6 "arm_comparison_operator"
9137           [(match_operand:SI 4 "s_register_operand" "r,r")
9138            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9139          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9140          (match_operator:SI 7 "shift_operator"
9141           [(match_operand:SI 2 "s_register_operand" "r,r")
9142            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
9143    (clobber (reg:CC CC_REGNUM))]
9144   "TARGET_ARM"
9145   "#"
9146   [(set_attr "conds" "clob")
9147    (set_attr "length" "8,12")]
9148 )
9149
9150 (define_insn "*if_move_shift"
9151   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9152         (if_then_else:SI
9153          (match_operator 5 "arm_comparison_operator"
9154           [(match_operand 6 "cc_register" "") (const_int 0)])
9155          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9156          (match_operator:SI 4 "shift_operator"
9157           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9158            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
9159   "TARGET_ARM"
9160   "@
9161    mov%D5\\t%0, %2%S4
9162    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9163    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
9164   [(set_attr "conds" "use")
9165    (set_attr "shift" "2")
9166    (set_attr "length" "4,8,8")
9167    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9168                       (const_string "alu_shift")
9169                       (const_string "alu_shift_reg")))]
9170 )
9171
9172 (define_insn "*ifcompare_shift_shift"
9173   [(set (match_operand:SI 0 "s_register_operand" "=r")
9174         (if_then_else:SI
9175          (match_operator 7 "arm_comparison_operator"
9176           [(match_operand:SI 5 "s_register_operand" "r")
9177            (match_operand:SI 6 "arm_add_operand" "rIL")])
9178          (match_operator:SI 8 "shift_operator"
9179           [(match_operand:SI 1 "s_register_operand" "r")
9180            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9181          (match_operator:SI 9 "shift_operator"
9182           [(match_operand:SI 3 "s_register_operand" "r")
9183            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
9184    (clobber (reg:CC CC_REGNUM))]
9185   "TARGET_ARM"
9186   "#"
9187   [(set_attr "conds" "clob")
9188    (set_attr "length" "12")]
9189 )
9190
9191 (define_insn "*if_shift_shift"
9192   [(set (match_operand:SI 0 "s_register_operand" "=r")
9193         (if_then_else:SI
9194          (match_operator 5 "arm_comparison_operator"
9195           [(match_operand 8 "cc_register" "") (const_int 0)])
9196          (match_operator:SI 6 "shift_operator"
9197           [(match_operand:SI 1 "s_register_operand" "r")
9198            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9199          (match_operator:SI 7 "shift_operator"
9200           [(match_operand:SI 3 "s_register_operand" "r")
9201            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
9202   "TARGET_ARM"
9203   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
9204   [(set_attr "conds" "use")
9205    (set_attr "shift" "1")
9206    (set_attr "length" "8")
9207    (set (attr "type") (if_then_else
9208                         (and (match_operand 2 "const_int_operand" "")
9209                              (match_operand 4 "const_int_operand" ""))
9210                       (const_string "alu_shift")
9211                       (const_string "alu_shift_reg")))]
9212 )
9213
9214 (define_insn "*ifcompare_not_arith"
9215   [(set (match_operand:SI 0 "s_register_operand" "=r")
9216         (if_then_else:SI
9217          (match_operator 6 "arm_comparison_operator"
9218           [(match_operand:SI 4 "s_register_operand" "r")
9219            (match_operand:SI 5 "arm_add_operand" "rIL")])
9220          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9221          (match_operator:SI 7 "shiftable_operator"
9222           [(match_operand:SI 2 "s_register_operand" "r")
9223            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
9224    (clobber (reg:CC CC_REGNUM))]
9225   "TARGET_ARM"
9226   "#"
9227   [(set_attr "conds" "clob")
9228    (set_attr "length" "12")]
9229 )
9230
9231 (define_insn "*if_not_arith"
9232   [(set (match_operand:SI 0 "s_register_operand" "=r")
9233         (if_then_else:SI
9234          (match_operator 5 "arm_comparison_operator"
9235           [(match_operand 4 "cc_register" "") (const_int 0)])
9236          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9237          (match_operator:SI 6 "shiftable_operator"
9238           [(match_operand:SI 2 "s_register_operand" "r")
9239            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
9240   "TARGET_ARM"
9241   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
9242   [(set_attr "conds" "use")
9243    (set_attr "length" "8")]
9244 )
9245
9246 (define_insn "*ifcompare_arith_not"
9247   [(set (match_operand:SI 0 "s_register_operand" "=r")
9248         (if_then_else:SI
9249          (match_operator 6 "arm_comparison_operator"
9250           [(match_operand:SI 4 "s_register_operand" "r")
9251            (match_operand:SI 5 "arm_add_operand" "rIL")])
9252          (match_operator:SI 7 "shiftable_operator"
9253           [(match_operand:SI 2 "s_register_operand" "r")
9254            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9255          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9256    (clobber (reg:CC CC_REGNUM))]
9257   "TARGET_ARM"
9258   "#"
9259   [(set_attr "conds" "clob")
9260    (set_attr "length" "12")]
9261 )
9262
9263 (define_insn "*if_arith_not"
9264   [(set (match_operand:SI 0 "s_register_operand" "=r")
9265         (if_then_else:SI
9266          (match_operator 5 "arm_comparison_operator"
9267           [(match_operand 4 "cc_register" "") (const_int 0)])
9268          (match_operator:SI 6 "shiftable_operator"
9269           [(match_operand:SI 2 "s_register_operand" "r")
9270            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9271          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9272   "TARGET_ARM"
9273   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9274   [(set_attr "conds" "use")
9275    (set_attr "length" "8")]
9276 )
9277
9278 (define_insn "*ifcompare_neg_move"
9279   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9280         (if_then_else:SI
9281          (match_operator 5 "arm_comparison_operator"
9282           [(match_operand:SI 3 "s_register_operand" "r,r")
9283            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9284          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9285          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9286    (clobber (reg:CC CC_REGNUM))]
9287   "TARGET_ARM"
9288   "#"
9289   [(set_attr "conds" "clob")
9290    (set_attr "length" "8,12")]
9291 )
9292
9293 (define_insn "*if_neg_move"
9294   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9295         (if_then_else:SI
9296          (match_operator 4 "arm_comparison_operator"
9297           [(match_operand 3 "cc_register" "") (const_int 0)])
9298          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9299          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9300   "TARGET_ARM"
9301   "@
9302    rsb%d4\\t%0, %2, #0
9303    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9304    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9305   [(set_attr "conds" "use")
9306    (set_attr "length" "4,8,8")]
9307 )
9308
9309 (define_insn "*ifcompare_move_neg"
9310   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9311         (if_then_else:SI
9312          (match_operator 5 "arm_comparison_operator"
9313           [(match_operand:SI 3 "s_register_operand" "r,r")
9314            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9315          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9316          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9317    (clobber (reg:CC CC_REGNUM))]
9318   "TARGET_ARM"
9319   "#"
9320   [(set_attr "conds" "clob")
9321    (set_attr "length" "8,12")]
9322 )
9323
9324 (define_insn "*if_move_neg"
9325   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9326         (if_then_else:SI
9327          (match_operator 4 "arm_comparison_operator"
9328           [(match_operand 3 "cc_register" "") (const_int 0)])
9329          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9330          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9331   "TARGET_ARM"
9332   "@
9333    rsb%D4\\t%0, %2, #0
9334    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9335    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9336   [(set_attr "conds" "use")
9337    (set_attr "length" "4,8,8")]
9338 )
9339
9340 (define_insn "*arith_adjacentmem"
9341   [(set (match_operand:SI 0 "s_register_operand" "=r")
9342         (match_operator:SI 1 "shiftable_operator"
9343          [(match_operand:SI 2 "memory_operand" "m")
9344           (match_operand:SI 3 "memory_operand" "m")]))
9345    (clobber (match_scratch:SI 4 "=r"))]
9346   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9347   "*
9348   {
9349     rtx ldm[3];
9350     rtx arith[4];
9351     rtx base_reg;
9352     HOST_WIDE_INT val1 = 0, val2 = 0;
9353
9354     if (REGNO (operands[0]) > REGNO (operands[4]))
9355       {
9356         ldm[1] = operands[4];
9357         ldm[2] = operands[0];
9358       }
9359     else
9360       {
9361         ldm[1] = operands[0];
9362         ldm[2] = operands[4];
9363       }
9364
9365     base_reg = XEXP (operands[2], 0);
9366
9367     if (!REG_P (base_reg))
9368       {
9369         val1 = INTVAL (XEXP (base_reg, 1));
9370         base_reg = XEXP (base_reg, 0);
9371       }
9372
9373     if (!REG_P (XEXP (operands[3], 0)))
9374       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9375
9376     arith[0] = operands[0];
9377     arith[3] = operands[1];
9378
9379     if (val1 < val2)
9380       {
9381         arith[1] = ldm[1];
9382         arith[2] = ldm[2];
9383       }
9384     else
9385       {
9386         arith[1] = ldm[2];
9387         arith[2] = ldm[1];
9388       }
9389
9390     ldm[0] = base_reg;
9391     if (val1 !=0 && val2 != 0)
9392       {
9393         if (val1 == 4 || val2 == 4)
9394           /* Other val must be 8, since we know they are adjacent and neither
9395              is zero.  */
9396           output_asm_insn (\"ldm%?ib\\t%0, {%1, %2}\", ldm);
9397         else
9398           {
9399             rtx ops[3];
9400
9401             ldm[0] = ops[0] = operands[4];
9402             ops[1] = base_reg;
9403             ops[2] = GEN_INT (val1);
9404             output_add_immediate (ops);
9405             if (val1 < val2)
9406               output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9407             else
9408               output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9409           }
9410       }
9411     else if (val1 != 0)
9412       {
9413         if (val1 < val2)
9414           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9415         else
9416           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9417       }
9418     else
9419       {
9420         if (val1 < val2)
9421           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9422         else
9423           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9424       }
9425     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9426     return \"\";
9427   }"
9428   [(set_attr "length" "12")
9429    (set_attr "predicable" "yes")
9430    (set_attr "type" "load1")]
9431 )
9432
9433 ; This pattern is never tried by combine, so do it as a peephole
9434
9435 (define_peephole2
9436   [(set (match_operand:SI 0 "arm_general_register_operand" "")
9437         (match_operand:SI 1 "arm_general_register_operand" ""))
9438    (set (reg:CC CC_REGNUM)
9439         (compare:CC (match_dup 1) (const_int 0)))]
9440   "TARGET_ARM"
9441   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9442               (set (match_dup 0) (match_dup 1))])]
9443   ""
9444 )
9445
9446 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9447 ; reversed, check that the memory references aren't volatile.
9448
9449 (define_peephole
9450   [(set (match_operand:SI 0 "s_register_operand" "=r")
9451         (match_operand:SI 4 "memory_operand" "m"))
9452    (set (match_operand:SI 1 "s_register_operand" "=r")
9453         (match_operand:SI 5 "memory_operand" "m"))
9454    (set (match_operand:SI 2 "s_register_operand" "=r")
9455         (match_operand:SI 6 "memory_operand" "m"))
9456    (set (match_operand:SI 3 "s_register_operand" "=r")
9457         (match_operand:SI 7 "memory_operand" "m"))]
9458   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9459   "*
9460   return emit_ldm_seq (operands, 4);
9461   "
9462 )
9463
9464 (define_peephole
9465   [(set (match_operand:SI 0 "s_register_operand" "=r")
9466         (match_operand:SI 3 "memory_operand" "m"))
9467    (set (match_operand:SI 1 "s_register_operand" "=r")
9468         (match_operand:SI 4 "memory_operand" "m"))
9469    (set (match_operand:SI 2 "s_register_operand" "=r")
9470         (match_operand:SI 5 "memory_operand" "m"))]
9471   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9472   "*
9473   return emit_ldm_seq (operands, 3);
9474   "
9475 )
9476
9477 (define_peephole
9478   [(set (match_operand:SI 0 "s_register_operand" "=r")
9479         (match_operand:SI 2 "memory_operand" "m"))
9480    (set (match_operand:SI 1 "s_register_operand" "=r")
9481         (match_operand:SI 3 "memory_operand" "m"))]
9482   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9483   "*
9484   return emit_ldm_seq (operands, 2);
9485   "
9486 )
9487
9488 (define_peephole
9489   [(set (match_operand:SI 4 "memory_operand" "=m")
9490         (match_operand:SI 0 "s_register_operand" "r"))
9491    (set (match_operand:SI 5 "memory_operand" "=m")
9492         (match_operand:SI 1 "s_register_operand" "r"))
9493    (set (match_operand:SI 6 "memory_operand" "=m")
9494         (match_operand:SI 2 "s_register_operand" "r"))
9495    (set (match_operand:SI 7 "memory_operand" "=m")
9496         (match_operand:SI 3 "s_register_operand" "r"))]
9497   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9498   "*
9499   return emit_stm_seq (operands, 4);
9500   "
9501 )
9502
9503 (define_peephole
9504   [(set (match_operand:SI 3 "memory_operand" "=m")
9505         (match_operand:SI 0 "s_register_operand" "r"))
9506    (set (match_operand:SI 4 "memory_operand" "=m")
9507         (match_operand:SI 1 "s_register_operand" "r"))
9508    (set (match_operand:SI 5 "memory_operand" "=m")
9509         (match_operand:SI 2 "s_register_operand" "r"))]
9510   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9511   "*
9512   return emit_stm_seq (operands, 3);
9513   "
9514 )
9515
9516 (define_peephole
9517   [(set (match_operand:SI 2 "memory_operand" "=m")
9518         (match_operand:SI 0 "s_register_operand" "r"))
9519    (set (match_operand:SI 3 "memory_operand" "=m")
9520         (match_operand:SI 1 "s_register_operand" "r"))]
9521   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9522   "*
9523   return emit_stm_seq (operands, 2);
9524   "
9525 )
9526
9527 (define_split
9528   [(set (match_operand:SI 0 "s_register_operand" "")
9529         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9530                        (const_int 0))
9531                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9532                          [(match_operand:SI 3 "s_register_operand" "")
9533                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
9534    (clobber (match_operand:SI 5 "s_register_operand" ""))]
9535   "TARGET_ARM"
9536   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9537    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9538                               (match_dup 5)))]
9539   ""
9540 )
9541
9542 ;; This split can be used because CC_Z mode implies that the following
9543 ;; branch will be an equality, or an unsigned inequality, so the sign
9544 ;; extension is not needed.
9545
9546 (define_split
9547   [(set (reg:CC_Z CC_REGNUM)
9548         (compare:CC_Z
9549          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9550                     (const_int 24))
9551          (match_operand 1 "const_int_operand" "")))
9552    (clobber (match_scratch:SI 2 ""))]
9553   "TARGET_ARM
9554    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9555        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9556   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9557    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9558   "
9559   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9560   "
9561 )
9562
9563 (define_expand "prologue"
9564   [(clobber (const_int 0))]
9565   "TARGET_EITHER"
9566   "if (TARGET_ARM)
9567      arm_expand_prologue ();
9568    else
9569      thumb_expand_prologue ();
9570   DONE;
9571   "
9572 )
9573
9574 (define_expand "epilogue"
9575   [(clobber (const_int 0))]
9576   "TARGET_EITHER"
9577   "
9578   if (current_function_calls_eh_return)
9579     emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
9580   if (TARGET_THUMB)
9581     thumb_expand_epilogue ();
9582   else if (USE_RETURN_INSN (FALSE))
9583     {
9584       emit_jump_insn (gen_return ());
9585       DONE;
9586     }
9587   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9588         gen_rtvec (1,
9589                 gen_rtx_RETURN (VOIDmode)),
9590         VUNSPEC_EPILOGUE));
9591   DONE;
9592   "
9593 )
9594
9595 ;; Note - although unspec_volatile's USE all hard registers,
9596 ;; USEs are ignored after relaod has completed.  Thus we need
9597 ;; to add an unspec of the link register to ensure that flow
9598 ;; does not think that it is unused by the sibcall branch that
9599 ;; will replace the standard function epilogue.
9600 (define_insn "sibcall_epilogue"
9601   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9602               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9603   "TARGET_ARM"
9604   "*
9605   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9606     return output_return_instruction (const_true_rtx, FALSE, FALSE);
9607   return arm_output_epilogue (next_nonnote_insn (insn));
9608   "
9609 ;; Length is absolute worst case
9610   [(set_attr "length" "44")
9611    (set_attr "type" "block")
9612    ;; We don't clobber the conditions, but the potential length of this
9613    ;; operation is sufficient to make conditionalizing the sequence 
9614    ;; unlikely to be profitable.
9615    (set_attr "conds" "clob")]
9616 )
9617
9618 (define_insn "*epilogue_insns"
9619   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9620   "TARGET_EITHER"
9621   "*
9622   if (TARGET_ARM)
9623     return arm_output_epilogue (NULL);
9624   else /* TARGET_THUMB */
9625     return thumb_unexpanded_epilogue ();
9626   "
9627   ; Length is absolute worst case
9628   [(set_attr "length" "44")
9629    (set_attr "type" "block")
9630    ;; We don't clobber the conditions, but the potential length of this
9631    ;; operation is sufficient to make conditionalizing the sequence 
9632    ;; unlikely to be profitable.
9633    (set_attr "conds" "clob")]
9634 )
9635
9636 (define_expand "eh_epilogue"
9637   [(use (match_operand:SI 0 "register_operand" ""))
9638    (use (match_operand:SI 1 "register_operand" ""))
9639    (use (match_operand:SI 2 "register_operand" ""))]
9640   "TARGET_EITHER"
9641   "
9642   {
9643     cfun->machine->eh_epilogue_sp_ofs = operands[1];
9644     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9645       {
9646         rtx ra = gen_rtx_REG (Pmode, 2);
9647
9648         emit_move_insn (ra, operands[2]);
9649         operands[2] = ra;
9650       }
9651     /* This is a hack -- we may have crystalized the function type too
9652        early.  */
9653     cfun->machine->func_type = 0;
9654   }"
9655 )
9656
9657 ;; This split is only used during output to reduce the number of patterns
9658 ;; that need assembler instructions adding to them.  We allowed the setting
9659 ;; of the conditions to be implicit during rtl generation so that
9660 ;; the conditional compare patterns would work.  However this conflicts to
9661 ;; some extent with the conditional data operations, so we have to split them
9662 ;; up again here.
9663
9664 (define_split
9665   [(set (match_operand:SI 0 "s_register_operand" "")
9666         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9667                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9668                          (match_dup 0)
9669                          (match_operand 4 "" "")))
9670    (clobber (reg:CC CC_REGNUM))]
9671   "TARGET_ARM && reload_completed"
9672   [(set (match_dup 5) (match_dup 6))
9673    (cond_exec (match_dup 7)
9674               (set (match_dup 0) (match_dup 4)))]
9675   "
9676   {
9677     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9678                                              operands[2], operands[3]);
9679     enum rtx_code rc = GET_CODE (operands[1]);
9680
9681     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9682     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9683     if (mode == CCFPmode || mode == CCFPEmode)
9684       rc = reverse_condition_maybe_unordered (rc);
9685     else
9686       rc = reverse_condition (rc);
9687
9688     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9689   }"
9690 )
9691
9692 (define_split
9693   [(set (match_operand:SI 0 "s_register_operand" "")
9694         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9695                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9696                          (match_operand 4 "" "")
9697                          (match_dup 0)))
9698    (clobber (reg:CC CC_REGNUM))]
9699   "TARGET_ARM && reload_completed"
9700   [(set (match_dup 5) (match_dup 6))
9701    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9702               (set (match_dup 0) (match_dup 4)))]
9703   "
9704   {
9705     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9706                                              operands[2], operands[3]);
9707
9708     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9709     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9710   }"
9711 )
9712
9713 (define_split
9714   [(set (match_operand:SI 0 "s_register_operand" "")
9715         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9716                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9717                          (match_operand 4 "" "")
9718                          (match_operand 5 "" "")))
9719    (clobber (reg:CC CC_REGNUM))]
9720   "TARGET_ARM && reload_completed"
9721   [(set (match_dup 6) (match_dup 7))
9722    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9723               (set (match_dup 0) (match_dup 4)))
9724    (cond_exec (match_dup 8)
9725               (set (match_dup 0) (match_dup 5)))]
9726   "
9727   {
9728     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9729                                              operands[2], operands[3]);
9730     enum rtx_code rc = GET_CODE (operands[1]);
9731
9732     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9733     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9734     if (mode == CCFPmode || mode == CCFPEmode)
9735       rc = reverse_condition_maybe_unordered (rc);
9736     else
9737       rc = reverse_condition (rc);
9738
9739     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9740   }"
9741 )
9742
9743 (define_split
9744   [(set (match_operand:SI 0 "s_register_operand" "")
9745         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9746                           [(match_operand:SI 2 "s_register_operand" "")
9747                            (match_operand:SI 3 "arm_add_operand" "")])
9748                          (match_operand:SI 4 "arm_rhs_operand" "")
9749                          (not:SI
9750                           (match_operand:SI 5 "s_register_operand" ""))))
9751    (clobber (reg:CC CC_REGNUM))]
9752   "TARGET_ARM && reload_completed"
9753   [(set (match_dup 6) (match_dup 7))
9754    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9755               (set (match_dup 0) (match_dup 4)))
9756    (cond_exec (match_dup 8)
9757               (set (match_dup 0) (not:SI (match_dup 5))))]
9758   "
9759   {
9760     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9761                                              operands[2], operands[3]);
9762     enum rtx_code rc = GET_CODE (operands[1]);
9763
9764     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9765     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9766     if (mode == CCFPmode || mode == CCFPEmode)
9767       rc = reverse_condition_maybe_unordered (rc);
9768     else
9769       rc = reverse_condition (rc);
9770
9771     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9772   }"
9773 )
9774
9775 (define_insn "*cond_move_not"
9776   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9777         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9778                           [(match_operand 3 "cc_register" "") (const_int 0)])
9779                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9780                          (not:SI
9781                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
9782   "TARGET_ARM"
9783   "@
9784    mvn%D4\\t%0, %2
9785    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
9786   [(set_attr "conds" "use")
9787    (set_attr "length" "4,8")]
9788 )
9789
9790 ;; The next two patterns occur when an AND operation is followed by a
9791 ;; scc insn sequence 
9792
9793 (define_insn "*sign_extract_onebit"
9794   [(set (match_operand:SI 0 "s_register_operand" "=r")
9795         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9796                          (const_int 1)
9797                          (match_operand:SI 2 "const_int_operand" "n")))
9798     (clobber (reg:CC CC_REGNUM))]
9799   "TARGET_ARM"
9800   "*
9801     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9802     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
9803     return \"mvnne\\t%0, #0\";
9804   "
9805   [(set_attr "conds" "clob")
9806    (set_attr "length" "8")]
9807 )
9808
9809 (define_insn "*not_signextract_onebit"
9810   [(set (match_operand:SI 0 "s_register_operand" "=r")
9811         (not:SI
9812          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9813                           (const_int 1)
9814                           (match_operand:SI 2 "const_int_operand" "n"))))
9815    (clobber (reg:CC CC_REGNUM))]
9816   "TARGET_ARM"
9817   "*
9818     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9819     output_asm_insn (\"tst\\t%1, %2\", operands);
9820     output_asm_insn (\"mvneq\\t%0, #0\", operands);
9821     return \"movne\\t%0, #0\";
9822   "
9823   [(set_attr "conds" "clob")
9824    (set_attr "length" "12")]
9825 )
9826
9827 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
9828 ;; expressions.  For simplicity, the first register is also in the unspec
9829 ;; part.
9830 (define_insn "*push_multi"
9831   [(match_parallel 2 "multi_register_push"
9832     [(set (match_operand:BLK 0 "memory_operand" "=m")
9833           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
9834                       UNSPEC_PUSH_MULT))])]
9835   "TARGET_ARM"
9836   "*
9837   {
9838     int num_saves = XVECLEN (operands[2], 0);
9839      
9840     /* For the StrongARM at least it is faster to
9841        use STR to store only a single register.  */
9842     if (num_saves == 1)
9843       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9844     else
9845       {
9846         int i;
9847         char pattern[100];
9848
9849         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9850
9851         for (i = 1; i < num_saves; i++)
9852           {
9853             strcat (pattern, \", %|\");
9854             strcat (pattern,
9855                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9856           }
9857
9858         strcat (pattern, \"}\");
9859         output_asm_insn (pattern, operands);
9860       }
9861
9862     return \"\";
9863   }"
9864   [(set_attr "type" "store4")]
9865 )
9866
9867 (define_insn "stack_tie"
9868   [(set (mem:BLK (scratch))
9869         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
9870                      (match_operand:SI 1 "s_register_operand" "r")]
9871                     UNSPEC_PRLG_STK))]
9872   ""
9873   ""
9874   [(set_attr "length" "0")]
9875 )
9876
9877 ;; Similarly for the floating point registers
9878 (define_insn "*push_fp_multi"
9879   [(match_parallel 2 "multi_register_push"
9880     [(set (match_operand:BLK 0 "memory_operand" "=m")
9881           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9882                       UNSPEC_PUSH_MULT))])]
9883   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
9884   "*
9885   {
9886     char pattern[100];
9887
9888     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
9889     output_asm_insn (pattern, operands);
9890     return \"\";
9891   }"
9892   [(set_attr "type" "f_store")]
9893 )
9894
9895 ;; Special patterns for dealing with the constant pool
9896
9897 (define_insn "align_4"
9898   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
9899   "TARGET_EITHER"
9900   "*
9901   assemble_align (32);
9902   return \"\";
9903   "
9904 )
9905
9906 (define_insn "align_8"
9907   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
9908   "TARGET_EITHER"
9909   "*
9910   assemble_align (64);
9911   return \"\";
9912   "
9913 )
9914
9915 (define_insn "consttable_end"
9916   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
9917   "TARGET_EITHER"
9918   "*
9919   making_const_table = FALSE;
9920   return \"\";
9921   "
9922 )
9923
9924 (define_insn "consttable_1"
9925   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
9926   "TARGET_THUMB"
9927   "*
9928   making_const_table = TRUE;
9929   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
9930   assemble_zeros (3);
9931   return \"\";
9932   "
9933   [(set_attr "length" "4")]
9934 )
9935
9936 (define_insn "consttable_2"
9937   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
9938   "TARGET_THUMB"
9939   "*
9940   making_const_table = TRUE;
9941   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
9942   assemble_zeros (2);
9943   return \"\";
9944   "
9945   [(set_attr "length" "4")]
9946 )
9947
9948 (define_insn "consttable_4"
9949   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
9950   "TARGET_EITHER"
9951   "*
9952   {
9953     making_const_table = TRUE;
9954     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9955       {
9956       case MODE_FLOAT:
9957       {
9958         REAL_VALUE_TYPE r;
9959         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9960         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9961         break;
9962       }
9963       default:
9964         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
9965         break;
9966       }
9967     return \"\";
9968   }"
9969   [(set_attr "length" "4")]
9970 )
9971
9972 (define_insn "consttable_8"
9973   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9974   "TARGET_EITHER"
9975   "*
9976   {
9977     making_const_table = TRUE;
9978     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9979       {
9980        case MODE_FLOAT:
9981         {
9982           REAL_VALUE_TYPE r;
9983           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9984           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9985           break;
9986         }
9987       default:
9988         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
9989         break;
9990       }
9991     return \"\";
9992   }"
9993   [(set_attr "length" "8")]
9994 )
9995
9996 ;; Miscellaneous Thumb patterns
9997
9998 (define_expand "tablejump"
9999   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10000               (use (label_ref (match_operand 1 "" "")))])]
10001   "TARGET_THUMB"
10002   "
10003   if (flag_pic)
10004     {
10005       /* Hopefully, CSE will eliminate this copy.  */
10006       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10007       rtx reg2 = gen_reg_rtx (SImode);
10008
10009       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10010       operands[0] = reg2;
10011     }
10012   "
10013 )
10014
10015 ;; NB never uses BX.
10016 (define_insn "*thumb_tablejump"
10017   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10018    (use (label_ref (match_operand 1 "" "")))]
10019   "TARGET_THUMB"
10020   "mov\\t%|pc, %0"
10021   [(set_attr "length" "2")]
10022 )
10023
10024 ;; V5 Instructions,
10025
10026 (define_insn "clzsi2"
10027   [(set (match_operand:SI 0 "s_register_operand" "=r")
10028         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10029   "TARGET_ARM && arm_arch5"
10030   "clz%?\\t%0, %1"
10031   [(set_attr "predicable" "yes")])
10032
10033 (define_expand "ffssi2"
10034   [(set (match_operand:SI 0 "s_register_operand" "")
10035         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10036   "TARGET_ARM && arm_arch5"
10037   "
10038   {
10039     rtx t1, t2, t3;
10040
10041     t1 = gen_reg_rtx (SImode);
10042     t2 = gen_reg_rtx (SImode);
10043     t3 = gen_reg_rtx (SImode);
10044
10045     emit_insn (gen_negsi2 (t1, operands[1]));
10046     emit_insn (gen_andsi3 (t2, operands[1], t1));
10047     emit_insn (gen_clzsi2 (t3, t2));
10048     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10049     DONE;
10050   }"
10051 )
10052
10053 (define_expand "ctzsi2"
10054   [(set (match_operand:SI 0 "s_register_operand" "")
10055         (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10056   "TARGET_ARM && arm_arch5"
10057   "
10058   {
10059     rtx t1, t2, t3;
10060
10061     t1 = gen_reg_rtx (SImode);
10062     t2 = gen_reg_rtx (SImode);
10063     t3 = gen_reg_rtx (SImode);
10064
10065     emit_insn (gen_negsi2 (t1, operands[1]));
10066     emit_insn (gen_andsi3 (t2, operands[1], t1));
10067     emit_insn (gen_clzsi2 (t3, t2));
10068     emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10069     DONE;
10070   }"
10071 )
10072
10073 ;; V5E instructions.
10074
10075 (define_insn "prefetch"
10076   [(prefetch (match_operand:SI 0 "address_operand" "p")
10077              (match_operand:SI 1 "" "")
10078              (match_operand:SI 2 "" ""))]
10079   "TARGET_ARM && arm_arch5e"
10080   "pld\\t%a0")
10081
10082 ;; General predication pattern
10083
10084 (define_cond_exec
10085   [(match_operator 0 "arm_comparison_operator"
10086     [(match_operand 1 "cc_register" "")
10087      (const_int 0)])]
10088   "TARGET_ARM"
10089   ""
10090 )
10091
10092 (define_insn "prologue_use"
10093   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10094   ""
10095   "%@ %0 needed for prologue"
10096 )
10097
10098
10099 ;; Patterns for exception handling
10100
10101 (define_expand "eh_return"
10102   [(use (match_operand 0 "general_operand" ""))]
10103   "TARGET_EITHER"
10104   "
10105   {
10106     if (TARGET_ARM)
10107       emit_insn (gen_arm_eh_return (operands[0]));
10108     else
10109       emit_insn (gen_thumb_eh_return (operands[0]));
10110     DONE;
10111   }"
10112 )
10113                                    
10114 ;; We can't expand this before we know where the link register is stored.
10115 (define_insn_and_split "arm_eh_return"
10116   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10117                     VUNSPEC_EH_RETURN)
10118    (clobber (match_scratch:SI 1 "=&r"))]
10119   "TARGET_ARM"
10120   "#"
10121   "&& reload_completed"
10122   [(const_int 0)]
10123   "
10124   {
10125     arm_set_return_address (operands[0], operands[1]);
10126     DONE;
10127   }"
10128 )
10129
10130 (define_insn_and_split "thumb_eh_return"
10131   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10132                     VUNSPEC_EH_RETURN)
10133    (clobber (match_scratch:SI 1 "=&l"))]
10134   "TARGET_THUMB"
10135   "#"
10136   "&& reload_completed"
10137   [(const_int 0)]
10138   "
10139   {
10140     thumb_set_return_address (operands[0], operands[1]);
10141     DONE;
10142   }"
10143 )
10144
10145 \f
10146 ;; TLS support
10147
10148 (define_insn "load_tp_hard"
10149   [(set (match_operand:SI 0 "register_operand" "=r")
10150         (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10151   "TARGET_HARD_TP"
10152   "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
10153   [(set_attr "predicable" "yes")]
10154 )
10155
10156 ;; Doesn't clobber R1-R3.  Must use r0 for the first operand.
10157 (define_insn "load_tp_soft"
10158   [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10159    (clobber (reg:SI LR_REGNUM))
10160    (clobber (reg:SI IP_REGNUM))
10161    (clobber (reg:CC CC_REGNUM))]
10162   "TARGET_SOFT_TP"
10163   "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
10164   [(set_attr "conds" "clob")]
10165 )
10166
10167 ;; Load the FPA co-processor patterns
10168 (include "fpa.md")
10169 ;; Load the Maverick co-processor patterns
10170 (include "cirrus.md")
10171 ;; Load the Intel Wireless Multimedia Extension patterns
10172 (include "iwmmxt.md")
10173 ;; Load the VFP co-processor patterns
10174 (include "vfp.md")
10175