OSDN Git Service

* arm.md (movqi): On thumb when optimizing, handle loading from
[pf3gnuchains/gcc-fork.git] / gcc / config / arm / arm.md
1 ;;- Machine description for ARM for GNU compiler
2 ;;  Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;;  2001, 2002, 2003, 2004, 2005  Free Software Foundation, Inc.
4 ;;  Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
5 ;;  and Martin Simmons (@harleqn.co.uk).
6 ;;  More major hacks by Richard Earnshaw (rearnsha@arm.com).
7
8 ;; This file is part of GCC.
9
10 ;; GCC is free software; you can redistribute it and/or modify it
11 ;; under the terms of the GNU General Public License as published
12 ;; by the Free Software Foundation; either version 2, or (at your
13 ;; option) any later version.
14
15 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
16 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
18 ;; License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GCC; see the file COPYING.  If not, write to
22 ;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23 ;; Boston, MA 02110-1301, USA.
24
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26
27 \f
28 ;;---------------------------------------------------------------------------
29 ;; Constants
30
31 ;; Register numbers
32 (define_constants
33   [(R0_REGNUM        0)         ; First CORE register
34    (IP_REGNUM       12)         ; Scratch register
35    (SP_REGNUM       13)         ; Stack pointer
36    (LR_REGNUM       14)         ; Return address register
37    (PC_REGNUM       15)         ; Program counter
38    (CC_REGNUM       24)         ; Condition code pseudo register
39    (LAST_ARM_REGNUM 15)         ;
40    (FPA_F0_REGNUM   16)         ; FIRST_FPA_REGNUM
41    (FPA_F7_REGNUM   23)         ; LAST_FPA_REGNUM
42   ]
43 )
44 ;; 3rd operand to select_dominance_cc_mode
45 (define_constants
46   [(DOM_CC_X_AND_Y  0)
47    (DOM_CC_NX_OR_Y  1)
48    (DOM_CC_X_OR_Y   2)
49   ]
50 )
51
52 ;; UNSPEC Usage:
53 ;; Note: sin and cos are no-longer used.
54
55 (define_constants
56   [(UNSPEC_SIN       0) ; `sin' operation (MODE_FLOAT):
57                         ;   operand 0 is the result,
58                         ;   operand 1 the parameter.
59    (UNPSEC_COS       1) ; `cos' operation (MODE_FLOAT):
60                         ;   operand 0 is the result,
61                         ;   operand 1 the parameter.
62    (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
63                         ;   operand 0 is the first register,
64                         ;   subsequent registers are in parallel (use ...)
65                         ;   expressions.
66    (UNSPEC_PIC_SYM   3) ; A symbol that has been treated properly for pic
67                         ;   usage, that is, we will add the pic_register
68                         ;   value to it before trying to dereference it.
69    (UNSPEC_PIC_BASE  4) ; Adding the PC value to the offset to the
70                         ;   GLOBAL_OFFSET_TABLE.  The operation is fully
71                         ;   described by the RTL but must be wrapped to
72                         ;   prevent combine from trying to rip it apart.
73    (UNSPEC_PRLG_STK  5) ; A special barrier that prevents frame accesses 
74                         ;   being scheduled before the stack adjustment insn.
75    (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
76                         ; this unspec is used to prevent the deletion of
77                         ; instructions setting registers for EH handling
78                         ; and stack frame generation.  Operand 0 is the
79                         ; register to "use".
80    (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
81    (UNSPEC_WSHUFH    8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
82    (UNSPEC_WACC      9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
83    (UNSPEC_TMOVMSK  10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
84    (UNSPEC_WSAD     11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
85    (UNSPEC_WSADZ    12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
86    (UNSPEC_WMACS    13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
87    (UNSPEC_WMACU    14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
88    (UNSPEC_WMACSZ   15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
89    (UNSPEC_WMACUZ   16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
90    (UNSPEC_CLRDI    17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
91    (UNSPEC_WMADDS   18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
92    (UNSPEC_WMADDU   19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
93   ]
94 )
95
96 ;; UNSPEC_VOLATILE Usage:
97
98 (define_constants
99   [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
100                         ;   insn in the code.
101    (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
102                         ;   instruction epilogue sequence that isn't expanded
103                         ;   into normal RTL.  Used for both normal and sibcall
104                         ;   epilogues.
105    (VUNSPEC_ALIGN    2) ; `align' insn.  Used at the head of a minipool table 
106                         ;   for inlined constants.
107    (VUNSPEC_POOL_END 3) ; `end-of-table'.  Used to mark the end of a minipool
108                         ;   table.
109    (VUNSPEC_POOL_1   4) ; `pool-entry(1)'.  An entry in the constant pool for
110                         ;   an 8-bit object.
111    (VUNSPEC_POOL_2   5) ; `pool-entry(2)'.  An entry in the constant pool for
112                         ;   a 16-bit object.
113    (VUNSPEC_POOL_4   6) ; `pool-entry(4)'.  An entry in the constant pool for
114                         ;   a 32-bit object.
115    (VUNSPEC_POOL_8   7) ; `pool-entry(8)'.  An entry in the constant pool for
116                         ;   a 64-bit object.
117    (VUNSPEC_TMRC     8) ; Used by the iWMMXt TMRC instruction.
118    (VUNSPEC_TMCR     9) ; Used by the iWMMXt TMCR instruction.
119    (VUNSPEC_ALIGN8   10) ; 8-byte alignment version of VUNSPEC_ALIGN
120    (VUNSPEC_WCMP_EQ  11) ; Used by the iWMMXt WCMPEQ instructions
121    (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
122    (VUNSPEC_WCMP_GT  13) ; Used by the iwMMXT WCMPGT instructions
123    (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
124                          ; handling.
125   ]
126 )
127 \f
128 ;;---------------------------------------------------------------------------
129 ;; Attributes
130
131 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
132 ; generating ARM code.  This is used to control the length of some insn
133 ; patterns that share the same RTL in both ARM and Thumb code.
134 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
135
136 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
137 ; scheduling decisions for the load unit and the multiplier.
138 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_tune_strongarm")))
139
140 ; IS_XSCALE is set to 'yes' when compiling for XScale.
141 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
142
143 ;; Operand number of an input operand that is shifted.  Zero if the
144 ;; given instruction does not shift one of its input operands.
145 (define_attr "shift" "" (const_int 0))
146
147 ; Floating Point Unit.  If we only have floating point emulation, then there
148 ; is no point in scheduling the floating point insns.  (Well, for best
149 ; performance we should try and group them together).
150 (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
151   (const (symbol_ref "arm_fpu_attr")))
152
153 ; LENGTH of an instruction (in bytes)
154 (define_attr "length" "" (const_int 4))
155
156 ; POOL_RANGE is how far away from a constant pool entry that this insn
157 ; can be placed.  If the distance is zero, then this insn will never
158 ; reference the pool.
159 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
160 ; before its address.
161 (define_attr "pool_range" "" (const_int 0))
162 (define_attr "neg_pool_range" "" (const_int 0))
163
164 ; An assembler sequence may clobber the condition codes without us knowing.
165 ; If such an insn references the pool, then we have no way of knowing how,
166 ; so use the most conservative value for pool_range.
167 (define_asm_attributes
168  [(set_attr "conds" "clob")
169   (set_attr "length" "4")
170   (set_attr "pool_range" "250")])
171
172 ;; The instruction used to implement a particular pattern.  This
173 ;; information is used by pipeline descriptions to provide accurate
174 ;; scheduling information.
175
176 (define_attr "insn"
177         "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals,smlawy,smuad,smuadx,smlad,smladx,smusd,smusdx,smlsd,smlsdx,smmul,smmulr,other"
178         (const_string "other"))
179
180 ; TYPE attribute is used to detect floating point instructions which, if
181 ; running on a co-processor can run in parallel with other, basic instructions
182 ; If write-buffer scheduling is enabled then it can also be used in the
183 ; scheduling of writes.
184
185 ; Classification of each insn
186 ; alu           any alu  instruction that doesn't hit memory or fp
187 ;               regs or have a shifted source operand
188 ; alu_shift     any data instruction that doesn't hit memory or fp
189 ;               regs, but has a source operand shifted by a constant
190 ; alu_shift_reg any data instruction that doesn't hit memory or fp
191 ;               regs, but has a source operand shifted by a register value
192 ; mult          a multiply instruction
193 ; block         blockage insn, this blocks all functional units
194 ; float         a floating point arithmetic operation (subject to expansion)
195 ; fdivd         DFmode floating point division
196 ; fdivs         SFmode floating point division
197 ; fmul          Floating point multiply
198 ; ffmul         Fast floating point multiply
199 ; farith        Floating point arithmetic (4 cycle)
200 ; ffarith       Fast floating point arithmetic (2 cycle)
201 ; float_em      a floating point arithmetic operation that is normally emulated
202 ;               even on a machine with an fpa.
203 ; f_load        a floating point load from memory
204 ; f_store       a floating point store to memory
205 ; f_load[sd]    single/double load from memory
206 ; f_store[sd]   single/double store to memory
207 ; f_flag        a transfer of co-processor flags to the CPSR
208 ; f_mem_r       a transfer of a floating point register to a real reg via mem
209 ; r_mem_f       the reverse of f_mem_r
210 ; f_2_r         fast transfer float to arm (no memory needed)
211 ; r_2_f         fast transfer arm to float
212 ; f_cvt         convert floating<->integral
213 ; branch        a branch
214 ; call          a subroutine call
215 ; load_byte     load byte(s) from memory to arm registers
216 ; load1         load 1 word from memory to arm registers
217 ; load2         load 2 words from memory to arm registers
218 ; load3         load 3 words from memory to arm registers
219 ; load4         load 4 words from memory to arm registers
220 ; store         store 1 word to memory from arm registers
221 ; store2        store 2 words
222 ; store3        store 3 words
223 ; store4        store 4 (or more) words
224 ;  Additions for Cirrus Maverick co-processor:
225 ; mav_farith    Floating point arithmetic (4 cycle)
226 ; mav_dmult     Double multiplies (7 cycle)
227 ;
228 (define_attr "type"
229         "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,f_flag,float_em,f_load,f_store,f_loads,f_loadd,f_stores,f_stored,f_mem_r,r_mem_f,f_2_r,r_2_f,f_cvt,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult" 
230         (if_then_else 
231          (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
232          (const_string "mult")
233          (const_string "alu")))
234
235 ; Load scheduling, set from the arm_ld_sched variable
236 ; initialized by arm_override_options() 
237 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
238
239 ; condition codes: this one is used by final_prescan_insn to speed up
240 ; conditionalizing instructions.  It saves having to scan the rtl to see if
241 ; it uses or alters the condition codes.
242
243 ; USE means that the condition codes are used by the insn in the process of
244 ;   outputting code, this means (at present) that we can't use the insn in
245 ;   inlined branches
246 ;
247 ; SET means that the purpose of the insn is to set the condition codes in a
248 ;   well defined manner.
249 ;
250 ; CLOB means that the condition codes are altered in an undefined manner, if
251 ;   they are altered at all
252 ;
253 ; JUMP_CLOB is used when the condition cannot be represented by a single
254 ;   instruction (UNEQ and LTGT).  These cannot be predicated.
255 ;
256 ; NOCOND means that the condition codes are neither altered nor affect the
257 ;   output of this insn
258
259 (define_attr "conds" "use,set,clob,jump_clob,nocond"
260         (if_then_else (eq_attr "type" "call")
261          (const_string "clob")
262          (const_string "nocond")))
263
264 ; Predicable means that the insn can be conditionally executed based on
265 ; an automatically added predicate (additional patterns are generated by 
266 ; gen...).  We default to 'no' because no Thumb patterns match this rule
267 ; and not all ARM patterns do.
268 (define_attr "predicable" "no,yes" (const_string "no"))
269
270 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
271 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
272 ; suffer blockages enough to warrant modelling this (and it can adversely
273 ; affect the schedule).
274 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
275
276 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
277 ; to stall the processor.  Used with model_wbuf above.
278 (define_attr "write_conflict" "no,yes"
279   (if_then_else (eq_attr "type"
280                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
281                 (const_string "yes")
282                 (const_string "no")))
283
284 ; Classify the insns into those that take one cycle and those that take more
285 ; than one on the main cpu execution unit.
286 (define_attr "core_cycles" "single,multi"
287   (if_then_else (eq_attr "type"
288                  "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
289                 (const_string "single")
290                 (const_string "multi")))
291
292 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
293 ;; distant label.  Only applicable to Thumb code.
294 (define_attr "far_jump" "yes,no" (const_string "no"))
295
296
297 ;;---------------------------------------------------------------------------
298 ;; Mode macros
299
300 ; A list of modes that are exactly 64 bits in size.  We use this to expand
301 ; some splits that are the same for all modes when operating on ARM 
302 ; registers.
303 (define_mode_macro ANY64 [DI DF V8QI V4HI V2SI V2SF])
304
305 ;;---------------------------------------------------------------------------
306 ;; Predicates
307
308 (include "predicates.md")
309
310 ;;---------------------------------------------------------------------------
311 ;; Pipeline descriptions
312
313 ;; Processor type.  This is created automatically from arm-cores.def.
314 (include "arm-tune.md")
315
316 ;; True if the generic scheduling description should be used.
317
318 (define_attr "generic_sched" "yes,no"
319   (const (if_then_else 
320           (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs") 
321           (const_string "no")
322           (const_string "yes"))))
323
324 (define_attr "generic_vfp" "yes,no"
325   (const (if_then_else
326           (and (eq_attr "fpu" "vfp")
327                (eq_attr "tune" "!arm1020e,arm1022e"))
328           (const_string "yes")
329           (const_string "no"))))
330
331 (include "arm-generic.md")
332 (include "arm926ejs.md")
333 (include "arm1020e.md")
334 (include "arm1026ejs.md")
335 (include "arm1136jfs.md")
336
337 \f
338 ;;---------------------------------------------------------------------------
339 ;; Insn patterns
340 ;;
341 ;; Addition insns.
342
343 ;; Note: For DImode insns, there is normally no reason why operands should
344 ;; not be in the same register, what we don't want is for something being
345 ;; written to partially overlap something that is an input.
346 ;; Cirrus 64bit additions should not be split because we have a native
347 ;; 64bit addition instructions.
348
349 (define_expand "adddi3"
350  [(parallel
351    [(set (match_operand:DI           0 "s_register_operand" "")
352           (plus:DI (match_operand:DI 1 "s_register_operand" "")
353                    (match_operand:DI 2 "s_register_operand" "")))
354     (clobber (reg:CC CC_REGNUM))])]
355   "TARGET_EITHER"
356   "
357   if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
358     {
359       if (!cirrus_fp_register (operands[0], DImode))
360         operands[0] = force_reg (DImode, operands[0]);
361       if (!cirrus_fp_register (operands[1], DImode))
362         operands[1] = force_reg (DImode, operands[1]);
363       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
364       DONE;
365     }
366
367   if (TARGET_THUMB)
368     {
369       if (GET_CODE (operands[1]) != REG)
370         operands[1] = force_reg (SImode, operands[1]);
371       if (GET_CODE (operands[2]) != REG)
372         operands[2] = force_reg (SImode, operands[2]);
373      }
374   "
375 )
376
377 (define_insn "*thumb_adddi3"
378   [(set (match_operand:DI          0 "register_operand" "=l")
379         (plus:DI (match_operand:DI 1 "register_operand" "%0")
380                  (match_operand:DI 2 "register_operand" "l")))
381    (clobber (reg:CC CC_REGNUM))
382   ]
383   "TARGET_THUMB"
384   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
385   [(set_attr "length" "4")]
386 )
387
388 (define_insn_and_split "*arm_adddi3"
389   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
390         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
391                  (match_operand:DI 2 "s_register_operand" "r,  0")))
392    (clobber (reg:CC CC_REGNUM))]
393   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
394   "#"
395   "TARGET_ARM && reload_completed"
396   [(parallel [(set (reg:CC_C CC_REGNUM)
397                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
398                                  (match_dup 1)))
399               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
400    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
401                                (plus:SI (match_dup 4) (match_dup 5))))]
402   "
403   {
404     operands[3] = gen_highpart (SImode, operands[0]);
405     operands[0] = gen_lowpart (SImode, operands[0]);
406     operands[4] = gen_highpart (SImode, operands[1]);
407     operands[1] = gen_lowpart (SImode, operands[1]);
408     operands[5] = gen_highpart (SImode, operands[2]);
409     operands[2] = gen_lowpart (SImode, operands[2]);
410   }"
411   [(set_attr "conds" "clob")
412    (set_attr "length" "8")]
413 )
414
415 (define_insn_and_split "*adddi_sesidi_di"
416   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
417         (plus:DI (sign_extend:DI
418                   (match_operand:SI 2 "s_register_operand" "r,r"))
419                  (match_operand:DI 1 "s_register_operand" "r,0")))
420    (clobber (reg:CC CC_REGNUM))]
421   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
422   "#"
423   "TARGET_ARM && reload_completed"
424   [(parallel [(set (reg:CC_C CC_REGNUM)
425                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
426                                  (match_dup 1)))
427               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
428    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
429                                (plus:SI (ashiftrt:SI (match_dup 2)
430                                                      (const_int 31))
431                                         (match_dup 4))))]
432   "
433   {
434     operands[3] = gen_highpart (SImode, operands[0]);
435     operands[0] = gen_lowpart (SImode, operands[0]);
436     operands[4] = gen_highpart (SImode, operands[1]);
437     operands[1] = gen_lowpart (SImode, operands[1]);
438     operands[2] = gen_lowpart (SImode, operands[2]);
439   }"
440   [(set_attr "conds" "clob")
441    (set_attr "length" "8")]
442 )
443
444 (define_insn_and_split "*adddi_zesidi_di"
445   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
446         (plus:DI (zero_extend:DI
447                   (match_operand:SI 2 "s_register_operand" "r,r"))
448                  (match_operand:DI 1 "s_register_operand" "r,0")))
449    (clobber (reg:CC CC_REGNUM))]
450   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
451   "#"
452   "TARGET_ARM && reload_completed"
453   [(parallel [(set (reg:CC_C CC_REGNUM)
454                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
455                                  (match_dup 1)))
456               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
457    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
458                                (plus:SI (match_dup 4) (const_int 0))))]
459   "
460   {
461     operands[3] = gen_highpart (SImode, operands[0]);
462     operands[0] = gen_lowpart (SImode, operands[0]);
463     operands[4] = gen_highpart (SImode, operands[1]);
464     operands[1] = gen_lowpart (SImode, operands[1]);
465     operands[2] = gen_lowpart (SImode, operands[2]);
466   }"
467   [(set_attr "conds" "clob")
468    (set_attr "length" "8")]
469 )
470
471 (define_expand "addsi3"
472   [(set (match_operand:SI          0 "s_register_operand" "")
473         (plus:SI (match_operand:SI 1 "s_register_operand" "")
474                  (match_operand:SI 2 "reg_or_int_operand" "")))]
475   "TARGET_EITHER"
476   "
477   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
478     {
479       arm_split_constant (PLUS, SImode, NULL_RTX,
480                           INTVAL (operands[2]), operands[0], operands[1],
481                           optimize && !no_new_pseudos);
482       DONE;
483     }
484   "
485 )
486
487 ; If there is a scratch available, this will be faster than synthesizing the
488 ; addition.
489 (define_peephole2
490   [(match_scratch:SI 3 "r")
491    (set (match_operand:SI          0 "arm_general_register_operand" "")
492         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
493                  (match_operand:SI 2 "const_int_operand"  "")))]
494   "TARGET_ARM &&
495    !(const_ok_for_arm (INTVAL (operands[2]))
496      || const_ok_for_arm (-INTVAL (operands[2])))
497     && const_ok_for_arm (~INTVAL (operands[2]))"
498   [(set (match_dup 3) (match_dup 2))
499    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
500   ""
501 )
502
503 (define_insn_and_split "*arm_addsi3"
504   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
505         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
506                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
507   "TARGET_ARM"
508   "@
509    add%?\\t%0, %1, %2
510    sub%?\\t%0, %1, #%n2
511    #"
512   "TARGET_ARM &&
513    GET_CODE (operands[2]) == CONST_INT
514    && !(const_ok_for_arm (INTVAL (operands[2]))
515         || const_ok_for_arm (-INTVAL (operands[2])))"
516   [(clobber (const_int 0))]
517   "
518   arm_split_constant (PLUS, SImode, curr_insn,
519                       INTVAL (operands[2]), operands[0],
520                       operands[1], 0);
521   DONE;
522   "
523   [(set_attr "length" "4,4,16")
524    (set_attr "predicable" "yes")]
525 )
526
527 ;; Register group 'k' is a single register group containing only the stack
528 ;; register.  Trying to reload it will always fail catastrophically,
529 ;; so never allow those alternatives to match if reloading is needed.
530
531 (define_insn "*thumb_addsi3"
532   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
533         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
534                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
535   "TARGET_THUMB"
536   "*
537    static const char * const asms[] = 
538    {
539      \"add\\t%0, %0, %2\",
540      \"sub\\t%0, %0, #%n2\",
541      \"add\\t%0, %1, %2\",
542      \"add\\t%0, %0, %2\",
543      \"add\\t%0, %0, %2\",
544      \"add\\t%0, %1, %2\",
545      \"add\\t%0, %1, %2\"
546    };
547    if ((which_alternative == 2 || which_alternative == 6)
548        && GET_CODE (operands[2]) == CONST_INT
549        && INTVAL (operands[2]) < 0)
550      return \"sub\\t%0, %1, #%n2\";
551    return asms[which_alternative];
552   "
553   [(set_attr "length" "2")]
554 )
555
556 ;; Reloading and elimination of the frame pointer can
557 ;; sometimes cause this optimization to be missed.
558 (define_peephole2
559   [(set (match_operand:SI 0 "arm_general_register_operand" "")
560         (match_operand:SI 1 "const_int_operand" ""))
561    (set (match_dup 0)
562         (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
563   "TARGET_THUMB
564    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
565    && (INTVAL (operands[1]) & 3) == 0"
566   [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
567   ""
568 )
569
570 (define_insn "*addsi3_compare0"
571   [(set (reg:CC_NOOV CC_REGNUM)
572         (compare:CC_NOOV
573          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
574                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
575          (const_int 0)))
576    (set (match_operand:SI 0 "s_register_operand" "=r,r")
577         (plus:SI (match_dup 1) (match_dup 2)))]
578   "TARGET_ARM"
579   "@
580    add%?s\\t%0, %1, %2
581    sub%?s\\t%0, %1, #%n2"
582   [(set_attr "conds" "set")]
583 )
584
585 (define_insn "*addsi3_compare0_scratch"
586   [(set (reg:CC_NOOV CC_REGNUM)
587         (compare:CC_NOOV
588          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
589                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
590          (const_int 0)))]
591   "TARGET_ARM"
592   "@
593    cmn%?\\t%0, %1
594    cmp%?\\t%0, #%n1"
595   [(set_attr "conds" "set")]
596 )
597
598 (define_insn "*compare_negsi_si"
599   [(set (reg:CC_Z CC_REGNUM)
600         (compare:CC_Z
601          (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
602          (match_operand:SI 1 "s_register_operand" "r")))]
603   "TARGET_ARM"
604   "cmn%?\\t%1, %0"
605   [(set_attr "conds" "set")]
606 )
607
608 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
609 ;; addend is a constant.
610 (define_insn "*cmpsi2_addneg"
611   [(set (reg:CC CC_REGNUM)
612         (compare:CC
613          (match_operand:SI 1 "s_register_operand" "r,r")
614          (match_operand:SI 2 "arm_addimm_operand" "I,L")))
615    (set (match_operand:SI 0 "s_register_operand" "=r,r")
616         (plus:SI (match_dup 1)
617                  (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
618   "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
619   "@
620    sub%?s\\t%0, %1, %2
621    add%?s\\t%0, %1, #%n2"
622   [(set_attr "conds" "set")]
623 )
624
625 ;; Convert the sequence
626 ;;  sub  rd, rn, #1
627 ;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
628 ;;  bne  dest
629 ;; into
630 ;;  subs rd, rn, #1
631 ;;  bcs  dest   ((unsigned)rn >= 1)
632 ;; similarly for the beq variant using bcc.
633 ;; This is a common looping idiom (while (n--))
634 (define_peephole2
635   [(set (match_operand:SI 0 "arm_general_register_operand" "")
636         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
637                  (const_int -1)))
638    (set (match_operand 2 "cc_register" "")
639         (compare (match_dup 0) (const_int -1)))
640    (set (pc)
641         (if_then_else (match_operator 3 "equality_operator"
642                        [(match_dup 2) (const_int 0)])
643                       (match_operand 4 "" "")
644                       (match_operand 5 "" "")))]
645   "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
646   [(parallel[
647     (set (match_dup 2)
648          (compare:CC
649           (match_dup 1) (const_int 1)))
650     (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
651    (set (pc)
652         (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
653                       (match_dup 4)
654                       (match_dup 5)))]
655   "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
656    operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
657                                   ? GEU : LTU),
658                                  VOIDmode, 
659                                  operands[2], const0_rtx);"
660 )
661
662 ;; The next four insns work because they compare the result with one of
663 ;; the operands, and we know that the use of the condition code is
664 ;; either GEU or LTU, so we can use the carry flag from the addition
665 ;; instead of doing the compare a second time.
666 (define_insn "*addsi3_compare_op1"
667   [(set (reg:CC_C CC_REGNUM)
668         (compare:CC_C
669          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
670                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
671          (match_dup 1)))
672    (set (match_operand:SI 0 "s_register_operand" "=r,r")
673         (plus:SI (match_dup 1) (match_dup 2)))]
674   "TARGET_ARM"
675   "@
676    add%?s\\t%0, %1, %2
677    sub%?s\\t%0, %1, #%n2"
678   [(set_attr "conds" "set")]
679 )
680
681 (define_insn "*addsi3_compare_op2"
682   [(set (reg:CC_C CC_REGNUM)
683         (compare:CC_C
684          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
685                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
686          (match_dup 2)))
687    (set (match_operand:SI 0 "s_register_operand" "=r,r")
688         (plus:SI (match_dup 1) (match_dup 2)))]
689   "TARGET_ARM"
690   "@
691    add%?s\\t%0, %1, %2
692    sub%?s\\t%0, %1, #%n2"
693   [(set_attr "conds" "set")]
694 )
695
696 (define_insn "*compare_addsi2_op0"
697   [(set (reg:CC_C CC_REGNUM)
698         (compare:CC_C
699          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
700                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
701          (match_dup 0)))]
702   "TARGET_ARM"
703   "@
704    cmn%?\\t%0, %1
705    cmp%?\\t%0, #%n1"
706   [(set_attr "conds" "set")]
707 )
708
709 (define_insn "*compare_addsi2_op1"
710   [(set (reg:CC_C CC_REGNUM)
711         (compare:CC_C
712          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
713                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
714          (match_dup 1)))]
715   "TARGET_ARM"
716   "@
717    cmn%?\\t%0, %1
718    cmp%?\\t%0, #%n1"
719   [(set_attr "conds" "set")]
720 )
721
722 (define_insn "*addsi3_carryin"
723   [(set (match_operand:SI 0 "s_register_operand" "=r")
724         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
725                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
726                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
727   "TARGET_ARM"
728   "adc%?\\t%0, %1, %2"
729   [(set_attr "conds" "use")]
730 )
731
732 (define_insn "*addsi3_carryin_shift"
733   [(set (match_operand:SI 0 "s_register_operand" "=r")
734         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
735                  (plus:SI
736                    (match_operator:SI 2 "shift_operator"
737                       [(match_operand:SI 3 "s_register_operand" "r")
738                        (match_operand:SI 4 "reg_or_int_operand" "rM")])
739                     (match_operand:SI 1 "s_register_operand" "r"))))]
740   "TARGET_ARM"
741   "adc%?\\t%0, %1, %3%S2"
742   [(set_attr "conds" "use")
743    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
744                       (const_string "alu_shift")
745                       (const_string "alu_shift_reg")))]
746 )
747
748 (define_insn "*addsi3_carryin_alt1"
749   [(set (match_operand:SI 0 "s_register_operand" "=r")
750         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
751                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
752                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
753   "TARGET_ARM"
754   "adc%?\\t%0, %1, %2"
755   [(set_attr "conds" "use")]
756 )
757
758 (define_insn "*addsi3_carryin_alt2"
759   [(set (match_operand:SI 0 "s_register_operand" "=r")
760         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
761                           (match_operand:SI 1 "s_register_operand" "r"))
762                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
763   "TARGET_ARM"
764   "adc%?\\t%0, %1, %2"
765   [(set_attr "conds" "use")]
766 )
767
768 (define_insn "*addsi3_carryin_alt3"
769   [(set (match_operand:SI 0 "s_register_operand" "=r")
770         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
771                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
772                  (match_operand:SI 1 "s_register_operand" "r")))]
773   "TARGET_ARM"
774   "adc%?\\t%0, %1, %2"
775   [(set_attr "conds" "use")]
776 )
777
778 (define_insn "incscc"
779   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
780         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
781                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
782                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
783   "TARGET_ARM"
784   "@
785   add%d2\\t%0, %1, #1
786   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
787   [(set_attr "conds" "use")
788    (set_attr "length" "4,8")]
789 )
790
791 ; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
792 (define_split
793   [(set (match_operand:SI 0 "s_register_operand" "")
794         (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
795                             (match_operand:SI 2 "s_register_operand" ""))
796                  (const_int -1)))
797    (clobber (match_operand:SI 3 "s_register_operand" ""))]
798   "TARGET_ARM"
799   [(set (match_dup 3) (match_dup 1))
800    (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
801   "
802   operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
803 ")
804
805 (define_expand "addsf3"
806   [(set (match_operand:SF          0 "s_register_operand" "")
807         (plus:SF (match_operand:SF 1 "s_register_operand" "")
808                  (match_operand:SF 2 "arm_float_add_operand" "")))]
809   "TARGET_ARM && TARGET_HARD_FLOAT"
810   "
811   if (TARGET_MAVERICK
812       && !cirrus_fp_register (operands[2], SFmode))
813     operands[2] = force_reg (SFmode, operands[2]);
814 ")
815
816 (define_expand "adddf3"
817   [(set (match_operand:DF          0 "s_register_operand" "")
818         (plus:DF (match_operand:DF 1 "s_register_operand" "")
819                  (match_operand:DF 2 "arm_float_add_operand" "")))]
820   "TARGET_ARM && TARGET_HARD_FLOAT"
821   "
822   if (TARGET_MAVERICK
823       && !cirrus_fp_register (operands[2], DFmode))
824     operands[2] = force_reg (DFmode, operands[2]);
825 ")
826
827 (define_expand "subdi3"
828  [(parallel
829    [(set (match_operand:DI            0 "s_register_operand" "")
830           (minus:DI (match_operand:DI 1 "s_register_operand" "")
831                     (match_operand:DI 2 "s_register_operand" "")))
832     (clobber (reg:CC CC_REGNUM))])]
833   "TARGET_EITHER"
834   "
835   if (TARGET_HARD_FLOAT && TARGET_MAVERICK
836       && TARGET_ARM
837       && cirrus_fp_register (operands[0], DImode)
838       && cirrus_fp_register (operands[1], DImode))
839     {
840       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
841       DONE;
842     }
843
844   if (TARGET_THUMB)
845     {
846       if (GET_CODE (operands[1]) != REG)
847         operands[1] = force_reg (SImode, operands[1]);
848       if (GET_CODE (operands[2]) != REG)
849         operands[2] = force_reg (SImode, operands[2]);
850      }  
851   "
852 )
853
854 (define_insn "*arm_subdi3"
855   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
856         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
857                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
858    (clobber (reg:CC CC_REGNUM))]
859   "TARGET_ARM"
860   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
861   [(set_attr "conds" "clob")
862    (set_attr "length" "8")]
863 )
864
865 (define_insn "*thumb_subdi3"
866   [(set (match_operand:DI           0 "register_operand" "=l")
867         (minus:DI (match_operand:DI 1 "register_operand"  "0")
868                   (match_operand:DI 2 "register_operand"  "l")))
869    (clobber (reg:CC CC_REGNUM))]
870   "TARGET_THUMB"
871   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
872   [(set_attr "length" "4")]
873 )
874
875 (define_insn "*subdi_di_zesidi"
876   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
877         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
878                   (zero_extend:DI
879                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
880    (clobber (reg:CC CC_REGNUM))]
881   "TARGET_ARM"
882   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
883   [(set_attr "conds" "clob")
884    (set_attr "length" "8")]
885 )
886
887 (define_insn "*subdi_di_sesidi"
888   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
889         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
890                   (sign_extend:DI
891                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
892    (clobber (reg:CC CC_REGNUM))]
893   "TARGET_ARM"
894   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
895   [(set_attr "conds" "clob")
896    (set_attr "length" "8")]
897 )
898
899 (define_insn "*subdi_zesidi_di"
900   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
901         (minus:DI (zero_extend:DI
902                    (match_operand:SI 2 "s_register_operand"  "r,r"))
903                   (match_operand:DI  1 "s_register_operand" "?r,0")))
904    (clobber (reg:CC CC_REGNUM))]
905   "TARGET_ARM"
906   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
907   [(set_attr "conds" "clob")
908    (set_attr "length" "8")]
909 )
910
911 (define_insn "*subdi_sesidi_di"
912   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
913         (minus:DI (sign_extend:DI
914                    (match_operand:SI 2 "s_register_operand"   "r,r"))
915                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
916    (clobber (reg:CC CC_REGNUM))]
917   "TARGET_ARM"
918   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
919   [(set_attr "conds" "clob")
920    (set_attr "length" "8")]
921 )
922
923 (define_insn "*subdi_zesidi_zesidi"
924   [(set (match_operand:DI            0 "s_register_operand" "=r")
925         (minus:DI (zero_extend:DI
926                    (match_operand:SI 1 "s_register_operand"  "r"))
927                   (zero_extend:DI
928                    (match_operand:SI 2 "s_register_operand"  "r"))))
929    (clobber (reg:CC CC_REGNUM))]
930   "TARGET_ARM"
931   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
932   [(set_attr "conds" "clob")
933    (set_attr "length" "8")]
934 )
935
936 (define_expand "subsi3"
937   [(set (match_operand:SI           0 "s_register_operand" "")
938         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
939                   (match_operand:SI 2 "s_register_operand" "")))]
940   "TARGET_EITHER"
941   "
942   if (GET_CODE (operands[1]) == CONST_INT)
943     {
944       if (TARGET_ARM)
945         {
946           arm_split_constant (MINUS, SImode, NULL_RTX,
947                               INTVAL (operands[1]), operands[0],
948                               operands[2], optimize && !no_new_pseudos);
949           DONE;
950         }
951       else /* TARGET_THUMB */
952         operands[1] = force_reg (SImode, operands[1]);
953     }
954   "
955 )
956
957 (define_insn "*thumb_subsi3_insn"
958   [(set (match_operand:SI           0 "register_operand" "=l")
959         (minus:SI (match_operand:SI 1 "register_operand" "l")
960                   (match_operand:SI 2 "register_operand" "l")))]
961   "TARGET_THUMB"
962   "sub\\t%0, %1, %2"
963   [(set_attr "length" "2")]
964 )
965
966 (define_insn_and_split "*arm_subsi3_insn"
967   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
968         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
969                   (match_operand:SI 2 "s_register_operand" "r,r")))]
970   "TARGET_ARM"
971   "@
972    rsb%?\\t%0, %2, %1
973    #"
974   "TARGET_ARM
975    && GET_CODE (operands[1]) == CONST_INT
976    && !const_ok_for_arm (INTVAL (operands[1]))"
977   [(clobber (const_int 0))]
978   "
979   arm_split_constant (MINUS, SImode, curr_insn,
980                       INTVAL (operands[1]), operands[0], operands[2], 0);
981   DONE;
982   "
983   [(set_attr "length" "4,16")
984    (set_attr "predicable" "yes")]
985 )
986
987 (define_peephole2
988   [(match_scratch:SI 3 "r")
989    (set (match_operand:SI 0 "arm_general_register_operand" "")
990         (minus:SI (match_operand:SI 1 "const_int_operand" "")
991                   (match_operand:SI 2 "arm_general_register_operand" "")))]
992   "TARGET_ARM
993    && !const_ok_for_arm (INTVAL (operands[1]))
994    && const_ok_for_arm (~INTVAL (operands[1]))"
995   [(set (match_dup 3) (match_dup 1))
996    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
997   ""
998 )
999
1000 (define_insn "*subsi3_compare0"
1001   [(set (reg:CC_NOOV CC_REGNUM)
1002         (compare:CC_NOOV
1003          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1004                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1005          (const_int 0)))
1006    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1007         (minus:SI (match_dup 1) (match_dup 2)))]
1008   "TARGET_ARM"
1009   "@
1010    sub%?s\\t%0, %1, %2
1011    rsb%?s\\t%0, %2, %1"
1012   [(set_attr "conds" "set")]
1013 )
1014
1015 (define_insn "decscc"
1016   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1017         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1018                   (match_operator:SI 2 "arm_comparison_operator"
1019                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1020   "TARGET_ARM"
1021   "@
1022    sub%d2\\t%0, %1, #1
1023    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1024   [(set_attr "conds" "use")
1025    (set_attr "length" "*,8")]
1026 )
1027
1028 (define_expand "subsf3"
1029   [(set (match_operand:SF           0 "s_register_operand" "")
1030         (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1031                   (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1032   "TARGET_ARM && TARGET_HARD_FLOAT"
1033   "
1034   if (TARGET_MAVERICK)
1035     {
1036       if (!cirrus_fp_register (operands[1], SFmode))
1037         operands[1] = force_reg (SFmode, operands[1]);
1038       if (!cirrus_fp_register (operands[2], SFmode))
1039         operands[2] = force_reg (SFmode, operands[2]);
1040     }
1041 ")
1042
1043 (define_expand "subdf3"
1044   [(set (match_operand:DF           0 "s_register_operand" "")
1045         (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1046                   (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1047   "TARGET_ARM && TARGET_HARD_FLOAT"
1048   "
1049   if (TARGET_MAVERICK)
1050     {
1051        if (!cirrus_fp_register (operands[1], DFmode))
1052          operands[1] = force_reg (DFmode, operands[1]);
1053        if (!cirrus_fp_register (operands[2], DFmode))
1054          operands[2] = force_reg (DFmode, operands[2]);
1055     }
1056 ")
1057
1058 \f
1059 ;; Multiplication insns
1060
1061 (define_expand "mulsi3"
1062   [(set (match_operand:SI          0 "s_register_operand" "")
1063         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1064                  (match_operand:SI 1 "s_register_operand" "")))]
1065   "TARGET_EITHER"
1066   ""
1067 )
1068
1069 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1070 (define_insn "*arm_mulsi3"
1071   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1072         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1073                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1074   "TARGET_ARM"
1075   "mul%?\\t%0, %2, %1"
1076   [(set_attr "insn" "mul")
1077    (set_attr "predicable" "yes")]
1078 )
1079
1080 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1081 ; 1 and 2; are the same, because reload will make operand 0 match 
1082 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1083 ; this by adding another alternative to match this case, and then `reload' 
1084 ; it ourselves.  This alternative must come first.
1085 (define_insn "*thumb_mulsi3"
1086   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1087         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1088                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1089   "TARGET_THUMB"
1090   "*
1091   if (which_alternative < 2)
1092     return \"mov\\t%0, %1\;mul\\t%0, %2\";
1093   else
1094     return \"mul\\t%0, %2\";
1095   "
1096   [(set_attr "length" "4,4,2")
1097    (set_attr "insn" "mul")]
1098 )
1099
1100 (define_insn "*mulsi3_compare0"
1101   [(set (reg:CC_NOOV CC_REGNUM)
1102         (compare:CC_NOOV (mult:SI
1103                           (match_operand:SI 2 "s_register_operand" "r,r")
1104                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1105                          (const_int 0)))
1106    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1107         (mult:SI (match_dup 2) (match_dup 1)))]
1108   "TARGET_ARM"
1109   "mul%?s\\t%0, %2, %1"
1110   [(set_attr "conds" "set")
1111    (set_attr "insn" "muls")]
1112 )
1113
1114 (define_insn "*mulsi_compare0_scratch"
1115   [(set (reg:CC_NOOV CC_REGNUM)
1116         (compare:CC_NOOV (mult:SI
1117                           (match_operand:SI 2 "s_register_operand" "r,r")
1118                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1119                          (const_int 0)))
1120    (clobber (match_scratch:SI 0 "=&r,&r"))]
1121   "TARGET_ARM"
1122   "mul%?s\\t%0, %2, %1"
1123   [(set_attr "conds" "set")
1124    (set_attr "insn" "muls")]
1125 )
1126
1127 ;; Unnamed templates to match MLA instruction.
1128
1129 (define_insn "*mulsi3addsi"
1130   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1131         (plus:SI
1132           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1133                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1134           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1135   "TARGET_ARM"
1136   "mla%?\\t%0, %2, %1, %3"
1137   [(set_attr "insn" "mla")
1138    (set_attr "predicable" "yes")]
1139 )
1140
1141 (define_insn "*mulsi3addsi_compare0"
1142   [(set (reg:CC_NOOV CC_REGNUM)
1143         (compare:CC_NOOV
1144          (plus:SI (mult:SI
1145                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1146                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1147                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1148          (const_int 0)))
1149    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1150         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1151                  (match_dup 3)))]
1152   "TARGET_ARM"
1153   "mla%?s\\t%0, %2, %1, %3"
1154   [(set_attr "conds" "set")
1155    (set_attr "insn" "mlas")]
1156 )
1157
1158 (define_insn "*mulsi3addsi_compare0_scratch"
1159   [(set (reg:CC_NOOV CC_REGNUM)
1160         (compare:CC_NOOV
1161          (plus:SI (mult:SI
1162                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1163                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1164                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1165          (const_int 0)))
1166    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1167   "TARGET_ARM"
1168   "mla%?s\\t%0, %2, %1, %3"
1169   [(set_attr "conds" "set")
1170    (set_attr "insn" "mlas")]
1171 )
1172
1173 ;; Unnamed template to match long long multiply-accumulate (smlal)
1174
1175 (define_insn "*mulsidi3adddi"
1176   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1177         (plus:DI
1178          (mult:DI
1179           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1180           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1181          (match_operand:DI 1 "s_register_operand" "0")))]
1182   "TARGET_ARM && arm_arch3m"
1183   "smlal%?\\t%Q0, %R0, %3, %2"
1184   [(set_attr "insn" "smlal")
1185    (set_attr "predicable" "yes")]
1186 )
1187
1188 (define_insn "mulsidi3"
1189   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1190         (mult:DI
1191          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1192          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1193   "TARGET_ARM && arm_arch3m"
1194   "smull%?\\t%Q0, %R0, %1, %2"
1195   [(set_attr "insn" "smull")
1196    (set_attr "predicable" "yes")]
1197 )
1198
1199 (define_insn "umulsidi3"
1200   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1201         (mult:DI
1202          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1203          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1204   "TARGET_ARM && arm_arch3m"
1205   "umull%?\\t%Q0, %R0, %1, %2"
1206   [(set_attr "insn" "umull")
1207    (set_attr "predicable" "yes")]
1208 )
1209
1210 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1211
1212 (define_insn "*umulsidi3adddi"
1213   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1214         (plus:DI
1215          (mult:DI
1216           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1217           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1218          (match_operand:DI 1 "s_register_operand" "0")))]
1219   "TARGET_ARM && arm_arch3m"
1220   "umlal%?\\t%Q0, %R0, %3, %2"
1221   [(set_attr "insn" "umlal")
1222    (set_attr "predicable" "yes")]
1223 )
1224
1225 (define_insn "smulsi3_highpart"
1226   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1227         (truncate:SI
1228          (lshiftrt:DI
1229           (mult:DI
1230            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1231            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1232           (const_int 32))))
1233    (clobber (match_scratch:SI 3 "=&r,&r"))]
1234   "TARGET_ARM && arm_arch3m"
1235   "smull%?\\t%3, %0, %2, %1"
1236   [(set_attr "insn" "smull")
1237    (set_attr "predicable" "yes")]
1238 )
1239
1240 (define_insn "umulsi3_highpart"
1241   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1242         (truncate:SI
1243          (lshiftrt:DI
1244           (mult:DI
1245            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1246            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1247           (const_int 32))))
1248    (clobber (match_scratch:SI 3 "=&r,&r"))]
1249   "TARGET_ARM && arm_arch3m"
1250   "umull%?\\t%3, %0, %2, %1"
1251   [(set_attr "insn" "umull")
1252    (set_attr "predicable" "yes")]
1253 )
1254
1255 (define_insn "mulhisi3"
1256   [(set (match_operand:SI 0 "s_register_operand" "=r")
1257         (mult:SI (sign_extend:SI
1258                   (match_operand:HI 1 "s_register_operand" "%r"))
1259                  (sign_extend:SI
1260                   (match_operand:HI 2 "s_register_operand" "r"))))]
1261   "TARGET_ARM && arm_arch5e"
1262   "smulbb%?\\t%0, %1, %2"
1263   [(set_attr "insn" "smulxy")
1264    (set_attr "predicable" "yes")]
1265 )
1266
1267 (define_insn "*mulhisi3tb"
1268   [(set (match_operand:SI 0 "s_register_operand" "=r")
1269         (mult:SI (ashiftrt:SI
1270                   (match_operand:SI 1 "s_register_operand" "r")
1271                   (const_int 16))
1272                  (sign_extend:SI
1273                   (match_operand:HI 2 "s_register_operand" "r"))))]
1274   "TARGET_ARM && arm_arch5e"
1275   "smultb%?\\t%0, %1, %2"
1276   [(set_attr "insn" "smulxy")
1277    (set_attr "predicable" "yes")]
1278 )
1279
1280 (define_insn "*mulhisi3bt"
1281   [(set (match_operand:SI 0 "s_register_operand" "=r")
1282         (mult:SI (sign_extend:SI
1283                   (match_operand:HI 1 "s_register_operand" "r"))
1284                  (ashiftrt:SI
1285                   (match_operand:SI 2 "s_register_operand" "r")
1286                   (const_int 16))))]
1287   "TARGET_ARM && arm_arch5e"
1288   "smulbt%?\\t%0, %1, %2"
1289   [(set_attr "insn" "smulxy")
1290    (set_attr "predicable" "yes")]
1291 )
1292
1293 (define_insn "*mulhisi3tt"
1294   [(set (match_operand:SI 0 "s_register_operand" "=r")
1295         (mult:SI (ashiftrt:SI
1296                   (match_operand:SI 1 "s_register_operand" "r")
1297                   (const_int 16))
1298                  (ashiftrt:SI
1299                   (match_operand:SI 2 "s_register_operand" "r")
1300                   (const_int 16))))]
1301   "TARGET_ARM && arm_arch5e"
1302   "smultt%?\\t%0, %1, %2"
1303   [(set_attr "insn" "smulxy")
1304    (set_attr "predicable" "yes")]
1305 )
1306
1307 (define_insn "*mulhisi3addsi"
1308   [(set (match_operand:SI 0 "s_register_operand" "=r")
1309         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1310                  (mult:SI (sign_extend:SI
1311                            (match_operand:HI 2 "s_register_operand" "%r"))
1312                           (sign_extend:SI
1313                            (match_operand:HI 3 "s_register_operand" "r")))))]
1314   "TARGET_ARM && arm_arch5e"
1315   "smlabb%?\\t%0, %2, %3, %1"
1316   [(set_attr "insn" "smlaxy")
1317    (set_attr "predicable" "yes")]
1318 )
1319
1320 (define_insn "*mulhidi3adddi"
1321   [(set (match_operand:DI 0 "s_register_operand" "=r")
1322         (plus:DI
1323           (match_operand:DI 1 "s_register_operand" "0")
1324           (mult:DI (sign_extend:DI
1325                     (match_operand:HI 2 "s_register_operand" "%r"))
1326                    (sign_extend:DI
1327                     (match_operand:HI 3 "s_register_operand" "r")))))]
1328   "TARGET_ARM && arm_arch5e"
1329   "smlalbb%?\\t%Q0, %R0, %2, %3"
1330   [(set_attr "insn" "smlalxy")
1331    (set_attr "predicable" "yes")])
1332
1333 (define_expand "mulsf3"
1334   [(set (match_operand:SF          0 "s_register_operand" "")
1335         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1336                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1337   "TARGET_ARM && TARGET_HARD_FLOAT"
1338   "
1339   if (TARGET_MAVERICK
1340       && !cirrus_fp_register (operands[2], SFmode))
1341     operands[2] = force_reg (SFmode, operands[2]);
1342 ")
1343
1344 (define_expand "muldf3"
1345   [(set (match_operand:DF          0 "s_register_operand" "")
1346         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1347                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1348   "TARGET_ARM && TARGET_HARD_FLOAT"
1349   "
1350   if (TARGET_MAVERICK
1351       && !cirrus_fp_register (operands[2], DFmode))
1352     operands[2] = force_reg (DFmode, operands[2]);
1353 ")
1354 \f
1355 ;; Division insns
1356
1357 (define_expand "divsf3"
1358   [(set (match_operand:SF 0 "s_register_operand" "")
1359         (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1360                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1361   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1362   "")
1363
1364 (define_expand "divdf3"
1365   [(set (match_operand:DF 0 "s_register_operand" "")
1366         (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1367                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1368   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1369   "")
1370 \f
1371 ;; Modulo insns
1372
1373 (define_expand "modsf3"
1374   [(set (match_operand:SF 0 "s_register_operand" "")
1375         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1376                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1377   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1378   "")
1379
1380 (define_expand "moddf3"
1381   [(set (match_operand:DF 0 "s_register_operand" "")
1382         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1383                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1384   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1385   "")
1386 \f
1387 ;; Boolean and,ior,xor insns
1388
1389 ;; Split up double word logical operations
1390
1391 ;; Split up simple DImode logical operations.  Simply perform the logical
1392 ;; operation on the upper and lower halves of the registers.
1393 (define_split
1394   [(set (match_operand:DI 0 "s_register_operand" "")
1395         (match_operator:DI 6 "logical_binary_operator"
1396           [(match_operand:DI 1 "s_register_operand" "")
1397            (match_operand:DI 2 "s_register_operand" "")]))]
1398   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1399   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1400    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1401   "
1402   {
1403     operands[3] = gen_highpart (SImode, operands[0]);
1404     operands[0] = gen_lowpart (SImode, operands[0]);
1405     operands[4] = gen_highpart (SImode, operands[1]);
1406     operands[1] = gen_lowpart (SImode, operands[1]);
1407     operands[5] = gen_highpart (SImode, operands[2]);
1408     operands[2] = gen_lowpart (SImode, operands[2]);
1409   }"
1410 )
1411
1412 (define_split
1413   [(set (match_operand:DI 0 "s_register_operand" "")
1414         (match_operator:DI 6 "logical_binary_operator"
1415           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1416            (match_operand:DI 1 "s_register_operand" "")]))]
1417   "TARGET_ARM && reload_completed"
1418   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1419    (set (match_dup 3) (match_op_dup:SI 6
1420                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1421                          (match_dup 4)]))]
1422   "
1423   {
1424     operands[3] = gen_highpart (SImode, operands[0]);
1425     operands[0] = gen_lowpart (SImode, operands[0]);
1426     operands[4] = gen_highpart (SImode, operands[1]);
1427     operands[1] = gen_lowpart (SImode, operands[1]);
1428     operands[5] = gen_highpart (SImode, operands[2]);
1429     operands[2] = gen_lowpart (SImode, operands[2]);
1430   }"
1431 )
1432
1433 ;; The zero extend of operand 2 means we can just copy the high part of
1434 ;; operand1 into operand0.
1435 (define_split
1436   [(set (match_operand:DI 0 "s_register_operand" "")
1437         (ior:DI
1438           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1439           (match_operand:DI 1 "s_register_operand" "")))]
1440   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1441   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1442    (set (match_dup 3) (match_dup 4))]
1443   "
1444   {
1445     operands[4] = gen_highpart (SImode, operands[1]);
1446     operands[3] = gen_highpart (SImode, operands[0]);
1447     operands[0] = gen_lowpart (SImode, operands[0]);
1448     operands[1] = gen_lowpart (SImode, operands[1]);
1449   }"
1450 )
1451
1452 ;; The zero extend of operand 2 means we can just copy the high part of
1453 ;; operand1 into operand0.
1454 (define_split
1455   [(set (match_operand:DI 0 "s_register_operand" "")
1456         (xor:DI
1457           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1458           (match_operand:DI 1 "s_register_operand" "")))]
1459   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1460   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1461    (set (match_dup 3) (match_dup 4))]
1462   "
1463   {
1464     operands[4] = gen_highpart (SImode, operands[1]);
1465     operands[3] = gen_highpart (SImode, operands[0]);
1466     operands[0] = gen_lowpart (SImode, operands[0]);
1467     operands[1] = gen_lowpart (SImode, operands[1]);
1468   }"
1469 )
1470
1471 (define_insn "anddi3"
1472   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1473         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1474                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1475   "TARGET_ARM && ! TARGET_IWMMXT"
1476   "#"
1477   [(set_attr "length" "8")]
1478 )
1479
1480 (define_insn_and_split "*anddi_zesidi_di"
1481   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1482         (and:DI (zero_extend:DI
1483                  (match_operand:SI 2 "s_register_operand" "r,r"))
1484                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1485   "TARGET_ARM"
1486   "#"
1487   "TARGET_ARM && reload_completed"
1488   ; The zero extend of operand 2 clears the high word of the output
1489   ; operand.
1490   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1491    (set (match_dup 3) (const_int 0))]
1492   "
1493   {
1494     operands[3] = gen_highpart (SImode, operands[0]);
1495     operands[0] = gen_lowpart (SImode, operands[0]);
1496     operands[1] = gen_lowpart (SImode, operands[1]);
1497   }"
1498   [(set_attr "length" "8")]
1499 )
1500
1501 (define_insn "*anddi_sesdi_di"
1502   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1503         (and:DI (sign_extend:DI
1504                  (match_operand:SI 2 "s_register_operand" "r,r"))
1505                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1506   "TARGET_ARM"
1507   "#"
1508   [(set_attr "length" "8")]
1509 )
1510
1511 (define_expand "andsi3"
1512   [(set (match_operand:SI         0 "s_register_operand" "")
1513         (and:SI (match_operand:SI 1 "s_register_operand" "")
1514                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1515   "TARGET_EITHER"
1516   "
1517   if (TARGET_ARM)
1518     {
1519       if (GET_CODE (operands[2]) == CONST_INT)
1520         {
1521           arm_split_constant (AND, SImode, NULL_RTX,
1522                               INTVAL (operands[2]), operands[0],
1523                               operands[1], optimize && !no_new_pseudos);
1524
1525           DONE;
1526         }
1527     }
1528   else /* TARGET_THUMB */
1529     {
1530       if (GET_CODE (operands[2]) != CONST_INT)
1531         operands[2] = force_reg (SImode, operands[2]);
1532       else
1533         {
1534           int i;
1535           
1536           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1537             {
1538               operands[2] = force_reg (SImode,
1539                                        GEN_INT (~INTVAL (operands[2])));
1540               
1541               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1542               
1543               DONE;
1544             }
1545
1546           for (i = 9; i <= 31; i++)
1547             {
1548               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1549                 {
1550                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1551                                         const0_rtx));
1552                   DONE;
1553                 }
1554               else if ((((HOST_WIDE_INT) 1) << i) - 1
1555                        == ~INTVAL (operands[2]))
1556                 {
1557                   rtx shift = GEN_INT (i);
1558                   rtx reg = gen_reg_rtx (SImode);
1559                 
1560                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1561                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1562                   
1563                   DONE;
1564                 }
1565             }
1566
1567           operands[2] = force_reg (SImode, operands[2]);
1568         }
1569     }
1570   "
1571 )
1572
1573 (define_insn_and_split "*arm_andsi3_insn"
1574   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1575         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1576                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1577   "TARGET_ARM"
1578   "@
1579    and%?\\t%0, %1, %2
1580    bic%?\\t%0, %1, #%B2
1581    #"
1582   "TARGET_ARM
1583    && GET_CODE (operands[2]) == CONST_INT
1584    && !(const_ok_for_arm (INTVAL (operands[2]))
1585         || const_ok_for_arm (~INTVAL (operands[2])))"
1586   [(clobber (const_int 0))]
1587   "
1588   arm_split_constant  (AND, SImode, curr_insn, 
1589                        INTVAL (operands[2]), operands[0], operands[1], 0);
1590   DONE;
1591   "
1592   [(set_attr "length" "4,4,16")
1593    (set_attr "predicable" "yes")]
1594 )
1595
1596 (define_insn "*thumb_andsi3_insn"
1597   [(set (match_operand:SI         0 "register_operand" "=l")
1598         (and:SI (match_operand:SI 1 "register_operand" "%0")
1599                 (match_operand:SI 2 "register_operand" "l")))]
1600   "TARGET_THUMB"
1601   "and\\t%0, %0, %2"
1602   [(set_attr "length" "2")]
1603 )
1604
1605 (define_insn "*andsi3_compare0"
1606   [(set (reg:CC_NOOV CC_REGNUM)
1607         (compare:CC_NOOV
1608          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1609                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1610          (const_int 0)))
1611    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1612         (and:SI (match_dup 1) (match_dup 2)))]
1613   "TARGET_ARM"
1614   "@
1615    and%?s\\t%0, %1, %2
1616    bic%?s\\t%0, %1, #%B2"
1617   [(set_attr "conds" "set")]
1618 )
1619
1620 (define_insn "*andsi3_compare0_scratch"
1621   [(set (reg:CC_NOOV CC_REGNUM)
1622         (compare:CC_NOOV
1623          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1624                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1625          (const_int 0)))
1626    (clobber (match_scratch:SI 2 "=X,r"))]
1627   "TARGET_ARM"
1628   "@
1629    tst%?\\t%0, %1
1630    bic%?s\\t%2, %0, #%B1"
1631   [(set_attr "conds" "set")]
1632 )
1633
1634 (define_insn "*zeroextractsi_compare0_scratch"
1635   [(set (reg:CC_NOOV CC_REGNUM)
1636         (compare:CC_NOOV (zero_extract:SI
1637                           (match_operand:SI 0 "s_register_operand" "r")
1638                           (match_operand 1 "const_int_operand" "n")
1639                           (match_operand 2 "const_int_operand" "n"))
1640                          (const_int 0)))]
1641   "TARGET_ARM
1642   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1643       && INTVAL (operands[1]) > 0 
1644       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1645       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1646   "*
1647   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1648                          << INTVAL (operands[2]));
1649   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1650   return \"\";
1651   "
1652   [(set_attr "conds" "set")]
1653 )
1654
1655 (define_insn_and_split "*ne_zeroextractsi"
1656   [(set (match_operand:SI 0 "s_register_operand" "=r")
1657         (ne:SI (zero_extract:SI
1658                 (match_operand:SI 1 "s_register_operand" "r")
1659                 (match_operand:SI 2 "const_int_operand" "n")
1660                 (match_operand:SI 3 "const_int_operand" "n"))
1661                (const_int 0)))
1662    (clobber (reg:CC CC_REGNUM))]
1663   "TARGET_ARM
1664    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1665        && INTVAL (operands[2]) > 0 
1666        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1667        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1668   "#"
1669   "TARGET_ARM
1670    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1671        && INTVAL (operands[2]) > 0 
1672        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1673        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1674   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1675                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1676                                     (const_int 0)))
1677               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1678    (set (match_dup 0)
1679         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1680                          (match_dup 0) (const_int 1)))]
1681   "
1682   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1683                          << INTVAL (operands[3])); 
1684   "
1685   [(set_attr "conds" "clob")
1686    (set_attr "length" "8")]
1687 )
1688
1689 (define_insn_and_split "*ne_zeroextractsi_shifted"
1690   [(set (match_operand:SI 0 "s_register_operand" "=r")
1691         (ne:SI (zero_extract:SI
1692                 (match_operand:SI 1 "s_register_operand" "r")
1693                 (match_operand:SI 2 "const_int_operand" "n")
1694                 (const_int 0))
1695                (const_int 0)))
1696    (clobber (reg:CC CC_REGNUM))]
1697   "TARGET_ARM"
1698   "#"
1699   "TARGET_ARM"
1700   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1701                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1702                                     (const_int 0)))
1703               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1704    (set (match_dup 0)
1705         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1706                          (match_dup 0) (const_int 1)))]
1707   "
1708   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1709   "
1710   [(set_attr "conds" "clob")
1711    (set_attr "length" "8")]
1712 )
1713
1714 (define_insn_and_split "*ite_ne_zeroextractsi"
1715   [(set (match_operand:SI 0 "s_register_operand" "=r")
1716         (if_then_else:SI (ne (zero_extract:SI
1717                               (match_operand:SI 1 "s_register_operand" "r")
1718                               (match_operand:SI 2 "const_int_operand" "n")
1719                               (match_operand:SI 3 "const_int_operand" "n"))
1720                              (const_int 0))
1721                          (match_operand:SI 4 "arm_not_operand" "rIK")
1722                          (const_int 0)))
1723    (clobber (reg:CC CC_REGNUM))]
1724   "TARGET_ARM
1725    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1726        && INTVAL (operands[2]) > 0 
1727        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1728        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1729    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1730   "#"
1731   "TARGET_ARM
1732    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1733        && INTVAL (operands[2]) > 0 
1734        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1735        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1736    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1737   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1738                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1739                                     (const_int 0)))
1740               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1741    (set (match_dup 0)
1742         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1743                          (match_dup 0) (match_dup 4)))]
1744   "
1745   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1746                          << INTVAL (operands[3])); 
1747   "
1748   [(set_attr "conds" "clob")
1749    (set_attr "length" "8")]
1750 )
1751
1752 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1753   [(set (match_operand:SI 0 "s_register_operand" "=r")
1754         (if_then_else:SI (ne (zero_extract:SI
1755                               (match_operand:SI 1 "s_register_operand" "r")
1756                               (match_operand:SI 2 "const_int_operand" "n")
1757                               (const_int 0))
1758                              (const_int 0))
1759                          (match_operand:SI 3 "arm_not_operand" "rIK")
1760                          (const_int 0)))
1761    (clobber (reg:CC CC_REGNUM))]
1762   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1763   "#"
1764   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1765   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1766                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1767                                     (const_int 0)))
1768               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1769    (set (match_dup 0)
1770         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1771                          (match_dup 0) (match_dup 3)))]
1772   "
1773   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1774   "
1775   [(set_attr "conds" "clob")
1776    (set_attr "length" "8")]
1777 )
1778
1779 (define_split
1780   [(set (match_operand:SI 0 "s_register_operand" "")
1781         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1782                          (match_operand:SI 2 "const_int_operand" "")
1783                          (match_operand:SI 3 "const_int_operand" "")))
1784    (clobber (match_operand:SI 4 "s_register_operand" ""))]
1785   "TARGET_THUMB"
1786   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1787    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1788   "{
1789      HOST_WIDE_INT temp = INTVAL (operands[2]);
1790
1791      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1792      operands[3] = GEN_INT (32 - temp);
1793    }"
1794 )
1795
1796 (define_split
1797   [(set (match_operand:SI 0 "s_register_operand" "")
1798         (match_operator:SI 1 "shiftable_operator"
1799          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1800                            (match_operand:SI 3 "const_int_operand" "")
1801                            (match_operand:SI 4 "const_int_operand" ""))
1802           (match_operand:SI 5 "s_register_operand" "")]))
1803    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1804   "TARGET_ARM"
1805   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1806    (set (match_dup 0)
1807         (match_op_dup 1
1808          [(lshiftrt:SI (match_dup 6) (match_dup 4))
1809           (match_dup 5)]))]
1810   "{
1811      HOST_WIDE_INT temp = INTVAL (operands[3]);
1812
1813      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1814      operands[4] = GEN_INT (32 - temp);
1815    }"
1816 )
1817   
1818 (define_split
1819   [(set (match_operand:SI 0 "s_register_operand" "")
1820         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1821                          (match_operand:SI 2 "const_int_operand" "")
1822                          (match_operand:SI 3 "const_int_operand" "")))]
1823   "TARGET_THUMB"
1824   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1825    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1826   "{
1827      HOST_WIDE_INT temp = INTVAL (operands[2]);
1828
1829      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1830      operands[3] = GEN_INT (32 - temp);
1831    }"
1832 )
1833
1834 (define_split
1835   [(set (match_operand:SI 0 "s_register_operand" "")
1836         (match_operator:SI 1 "shiftable_operator"
1837          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1838                            (match_operand:SI 3 "const_int_operand" "")
1839                            (match_operand:SI 4 "const_int_operand" ""))
1840           (match_operand:SI 5 "s_register_operand" "")]))
1841    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1842   "TARGET_ARM"
1843   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1844    (set (match_dup 0)
1845         (match_op_dup 1
1846          [(ashiftrt:SI (match_dup 6) (match_dup 4))
1847           (match_dup 5)]))]
1848   "{
1849      HOST_WIDE_INT temp = INTVAL (operands[3]);
1850
1851      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1852      operands[4] = GEN_INT (32 - temp);
1853    }"
1854 )
1855   
1856 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1857 ;;; represented by the bitfield, then this will produce incorrect results.
1858 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1859 ;;; which have a real bit-field insert instruction, the truncation happens
1860 ;;; in the bit-field insert instruction itself.  Since arm does not have a
1861 ;;; bit-field insert instruction, we would have to emit code here to truncate
1862 ;;; the value before we insert.  This loses some of the advantage of having
1863 ;;; this insv pattern, so this pattern needs to be reevalutated.
1864
1865 (define_expand "insv"
1866   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1867                          (match_operand:SI 1 "general_operand" "")
1868                          (match_operand:SI 2 "general_operand" ""))
1869         (match_operand:SI 3 "reg_or_int_operand" ""))]
1870   "TARGET_ARM"
1871   "
1872   {
1873     int start_bit = INTVAL (operands[2]);
1874     int width = INTVAL (operands[1]);
1875     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1876     rtx target, subtarget;
1877
1878     target = operands[0];
1879     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1880        subreg as the final target.  */
1881     if (GET_CODE (target) == SUBREG)
1882       {
1883         subtarget = gen_reg_rtx (SImode);
1884         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1885             < GET_MODE_SIZE (SImode))
1886           target = SUBREG_REG (target);
1887       }
1888     else
1889       subtarget = target;    
1890
1891     if (GET_CODE (operands[3]) == CONST_INT)
1892       {
1893         /* Since we are inserting a known constant, we may be able to
1894            reduce the number of bits that we have to clear so that
1895            the mask becomes simple.  */
1896         /* ??? This code does not check to see if the new mask is actually
1897            simpler.  It may not be.  */
1898         rtx op1 = gen_reg_rtx (SImode);
1899         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1900            start of this pattern.  */
1901         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1902         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1903
1904         emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1905         emit_insn (gen_iorsi3 (subtarget, op1,
1906                                gen_int_mode (op3_value << start_bit, SImode)));
1907       }
1908     else if (start_bit == 0
1909              && !(const_ok_for_arm (mask)
1910                   || const_ok_for_arm (~mask)))
1911       {
1912         /* A Trick, since we are setting the bottom bits in the word,
1913            we can shift operand[3] up, operand[0] down, OR them together
1914            and rotate the result back again.  This takes 3 insns, and
1915            the third might be mergeable into another op.  */
1916         /* The shift up copes with the possibility that operand[3] is
1917            wider than the bitfield.  */
1918         rtx op0 = gen_reg_rtx (SImode);
1919         rtx op1 = gen_reg_rtx (SImode);
1920
1921         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1922         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1923         emit_insn (gen_iorsi3  (op1, op1, op0));
1924         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1925       }
1926     else if ((width + start_bit == 32)
1927              && !(const_ok_for_arm (mask)
1928                   || const_ok_for_arm (~mask)))
1929       {
1930         /* Similar trick, but slightly less efficient.  */
1931
1932         rtx op0 = gen_reg_rtx (SImode);
1933         rtx op1 = gen_reg_rtx (SImode);
1934
1935         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1936         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1937         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1938         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1939       }
1940     else
1941       {
1942         rtx op0 = GEN_INT (mask);
1943         rtx op1 = gen_reg_rtx (SImode);
1944         rtx op2 = gen_reg_rtx (SImode);
1945
1946         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1947           {
1948             rtx tmp = gen_reg_rtx (SImode);
1949
1950             emit_insn (gen_movsi (tmp, op0));
1951             op0 = tmp;
1952           }
1953
1954         /* Mask out any bits in operand[3] that are not needed.  */
1955            emit_insn (gen_andsi3 (op1, operands[3], op0));
1956
1957         if (GET_CODE (op0) == CONST_INT
1958             && (const_ok_for_arm (mask << start_bit)
1959                 || const_ok_for_arm (~(mask << start_bit))))
1960           {
1961             op0 = GEN_INT (~(mask << start_bit));
1962             emit_insn (gen_andsi3 (op2, operands[0], op0));
1963           }
1964         else
1965           {
1966             if (GET_CODE (op0) == CONST_INT)
1967               {
1968                 rtx tmp = gen_reg_rtx (SImode);
1969
1970                 emit_insn (gen_movsi (tmp, op0));
1971                 op0 = tmp;
1972               }
1973
1974             if (start_bit != 0)
1975               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1976             
1977             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1978           }
1979
1980         if (start_bit != 0)
1981           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1982
1983         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1984       }
1985
1986     if (subtarget != target)
1987       {
1988         /* If TARGET is still a SUBREG, then it must be wider than a word,
1989            so we must be careful only to set the subword we were asked to.  */
1990         if (GET_CODE (target) == SUBREG)
1991           emit_move_insn (target, subtarget);
1992         else
1993           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1994       }
1995
1996     DONE;
1997   }"
1998 )
1999
2000 ; constants for op 2 will never be given to these patterns.
2001 (define_insn_and_split "*anddi_notdi_di"
2002   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2003         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2004                 (match_operand:DI 2 "s_register_operand" "0,r")))]
2005   "TARGET_ARM"
2006   "#"
2007   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2008   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2009    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2010   "
2011   {
2012     operands[3] = gen_highpart (SImode, operands[0]);
2013     operands[0] = gen_lowpart (SImode, operands[0]);
2014     operands[4] = gen_highpart (SImode, operands[1]);
2015     operands[1] = gen_lowpart (SImode, operands[1]);
2016     operands[5] = gen_highpart (SImode, operands[2]);
2017     operands[2] = gen_lowpart (SImode, operands[2]);
2018   }"
2019   [(set_attr "length" "8")
2020    (set_attr "predicable" "yes")]
2021 )
2022   
2023 (define_insn_and_split "*anddi_notzesidi_di"
2024   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2025         (and:DI (not:DI (zero_extend:DI
2026                          (match_operand:SI 2 "s_register_operand" "r,r")))
2027                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2028   "TARGET_ARM"
2029   "@
2030    bic%?\\t%Q0, %Q1, %2
2031    #"
2032   ; (not (zero_extend ...)) allows us to just copy the high word from
2033   ; operand1 to operand0.
2034   "TARGET_ARM
2035    && reload_completed
2036    && operands[0] != operands[1]"
2037   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2038    (set (match_dup 3) (match_dup 4))]
2039   "
2040   {
2041     operands[3] = gen_highpart (SImode, operands[0]);
2042     operands[0] = gen_lowpart (SImode, operands[0]);
2043     operands[4] = gen_highpart (SImode, operands[1]);
2044     operands[1] = gen_lowpart (SImode, operands[1]);
2045   }"
2046   [(set_attr "length" "4,8")
2047    (set_attr "predicable" "yes")]
2048 )
2049   
2050 (define_insn_and_split "*anddi_notsesidi_di"
2051   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2052         (and:DI (not:DI (sign_extend:DI
2053                          (match_operand:SI 2 "s_register_operand" "r,r")))
2054                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2055   "TARGET_ARM"
2056   "#"
2057   "TARGET_ARM && reload_completed"
2058   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2059    (set (match_dup 3) (and:SI (not:SI
2060                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2061                                (match_dup 4)))]
2062   "
2063   {
2064     operands[3] = gen_highpart (SImode, operands[0]);
2065     operands[0] = gen_lowpart (SImode, operands[0]);
2066     operands[4] = gen_highpart (SImode, operands[1]);
2067     operands[1] = gen_lowpart (SImode, operands[1]);
2068   }"
2069   [(set_attr "length" "8")
2070    (set_attr "predicable" "yes")]
2071 )
2072   
2073 (define_insn "andsi_notsi_si"
2074   [(set (match_operand:SI 0 "s_register_operand" "=r")
2075         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2076                 (match_operand:SI 1 "s_register_operand" "r")))]
2077   "TARGET_ARM"
2078   "bic%?\\t%0, %1, %2"
2079   [(set_attr "predicable" "yes")]
2080 )
2081
2082 (define_insn "bicsi3"
2083   [(set (match_operand:SI                 0 "register_operand" "=l")
2084         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2085                 (match_operand:SI         2 "register_operand" "0")))]
2086   "TARGET_THUMB"
2087   "bic\\t%0, %0, %1"
2088   [(set_attr "length" "2")]
2089 )
2090
2091 (define_insn "andsi_not_shiftsi_si"
2092   [(set (match_operand:SI 0 "s_register_operand" "=r")
2093         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2094                          [(match_operand:SI 2 "s_register_operand" "r")
2095                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2096                 (match_operand:SI 1 "s_register_operand" "r")))]
2097   "TARGET_ARM"
2098   "bic%?\\t%0, %1, %2%S4"
2099   [(set_attr "predicable" "yes")
2100    (set_attr "shift" "2")
2101    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2102                       (const_string "alu_shift")
2103                       (const_string "alu_shift_reg")))]
2104 )
2105
2106 (define_insn "*andsi_notsi_si_compare0"
2107   [(set (reg:CC_NOOV CC_REGNUM)
2108         (compare:CC_NOOV
2109          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2110                  (match_operand:SI 1 "s_register_operand" "r"))
2111          (const_int 0)))
2112    (set (match_operand:SI 0 "s_register_operand" "=r")
2113         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2114   "TARGET_ARM"
2115   "bic%?s\\t%0, %1, %2"
2116   [(set_attr "conds" "set")]
2117 )
2118
2119 (define_insn "*andsi_notsi_si_compare0_scratch"
2120   [(set (reg:CC_NOOV CC_REGNUM)
2121         (compare:CC_NOOV
2122          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2123                  (match_operand:SI 1 "s_register_operand" "r"))
2124          (const_int 0)))
2125    (clobber (match_scratch:SI 0 "=r"))]
2126   "TARGET_ARM"
2127   "bic%?s\\t%0, %1, %2"
2128   [(set_attr "conds" "set")]
2129 )
2130
2131 (define_insn "iordi3"
2132   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2133         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2134                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2135   "TARGET_ARM && ! TARGET_IWMMXT"
2136   "#"
2137   [(set_attr "length" "8")
2138    (set_attr "predicable" "yes")]
2139 )
2140
2141 (define_insn "*iordi_zesidi_di"
2142   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2143         (ior:DI (zero_extend:DI
2144                  (match_operand:SI 2 "s_register_operand" "r,r"))
2145                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2146   "TARGET_ARM"
2147   "@
2148    orr%?\\t%Q0, %Q1, %2
2149    #"
2150   [(set_attr "length" "4,8")
2151    (set_attr "predicable" "yes")]
2152 )
2153
2154 (define_insn "*iordi_sesidi_di"
2155   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2156         (ior:DI (sign_extend:DI
2157                  (match_operand:SI 2 "s_register_operand" "r,r"))
2158                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2159   "TARGET_ARM"
2160   "#"
2161   [(set_attr "length" "8")
2162    (set_attr "predicable" "yes")]
2163 )
2164
2165 (define_expand "iorsi3"
2166   [(set (match_operand:SI         0 "s_register_operand" "")
2167         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2168                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2169   "TARGET_EITHER"
2170   "
2171   if (GET_CODE (operands[2]) == CONST_INT)
2172     {
2173       if (TARGET_ARM)
2174         {
2175           arm_split_constant (IOR, SImode, NULL_RTX,
2176                               INTVAL (operands[2]), operands[0], operands[1],
2177                               optimize && !no_new_pseudos);
2178           DONE;
2179         }
2180       else /* TARGET_THUMB */
2181         operands [2] = force_reg (SImode, operands [2]);
2182     }
2183   "
2184 )
2185
2186 (define_insn_and_split "*arm_iorsi3"
2187   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2188         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2189                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2190   "TARGET_ARM"
2191   "@
2192    orr%?\\t%0, %1, %2
2193    #"
2194   "TARGET_ARM
2195    && GET_CODE (operands[2]) == CONST_INT
2196    && !const_ok_for_arm (INTVAL (operands[2]))"
2197   [(clobber (const_int 0))]
2198   "
2199   arm_split_constant (IOR, SImode, curr_insn, 
2200                       INTVAL (operands[2]), operands[0], operands[1], 0);
2201   DONE;
2202   "
2203   [(set_attr "length" "4,16")
2204    (set_attr "predicable" "yes")]
2205 )
2206
2207 (define_insn "*thumb_iorsi3"
2208   [(set (match_operand:SI         0 "register_operand" "=l")
2209         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2210                 (match_operand:SI 2 "register_operand" "l")))]
2211   "TARGET_THUMB"
2212   "orr\\t%0, %0, %2"
2213   [(set_attr "length" "2")]
2214 )
2215
2216 (define_peephole2
2217   [(match_scratch:SI 3 "r")
2218    (set (match_operand:SI 0 "arm_general_register_operand" "")
2219         (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2220                 (match_operand:SI 2 "const_int_operand" "")))]
2221   "TARGET_ARM
2222    && !const_ok_for_arm (INTVAL (operands[2]))
2223    && const_ok_for_arm (~INTVAL (operands[2]))"
2224   [(set (match_dup 3) (match_dup 2))
2225    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2226   ""
2227 )
2228
2229 (define_insn "*iorsi3_compare0"
2230   [(set (reg:CC_NOOV CC_REGNUM)
2231         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2232                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2233                          (const_int 0)))
2234    (set (match_operand:SI 0 "s_register_operand" "=r")
2235         (ior:SI (match_dup 1) (match_dup 2)))]
2236   "TARGET_ARM"
2237   "orr%?s\\t%0, %1, %2"
2238   [(set_attr "conds" "set")]
2239 )
2240
2241 (define_insn "*iorsi3_compare0_scratch"
2242   [(set (reg:CC_NOOV CC_REGNUM)
2243         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2244                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2245                          (const_int 0)))
2246    (clobber (match_scratch:SI 0 "=r"))]
2247   "TARGET_ARM"
2248   "orr%?s\\t%0, %1, %2"
2249   [(set_attr "conds" "set")]
2250 )
2251
2252 (define_insn "xordi3"
2253   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2254         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2255                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2256   "TARGET_ARM && !TARGET_IWMMXT"
2257   "#"
2258   [(set_attr "length" "8")
2259    (set_attr "predicable" "yes")]
2260 )
2261
2262 (define_insn "*xordi_zesidi_di"
2263   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2264         (xor:DI (zero_extend:DI
2265                  (match_operand:SI 2 "s_register_operand" "r,r"))
2266                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2267   "TARGET_ARM"
2268   "@
2269    eor%?\\t%Q0, %Q1, %2
2270    #"
2271   [(set_attr "length" "4,8")
2272    (set_attr "predicable" "yes")]
2273 )
2274
2275 (define_insn "*xordi_sesidi_di"
2276   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2277         (xor:DI (sign_extend:DI
2278                  (match_operand:SI 2 "s_register_operand" "r,r"))
2279                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2280   "TARGET_ARM"
2281   "#"
2282   [(set_attr "length" "8")
2283    (set_attr "predicable" "yes")]
2284 )
2285
2286 (define_expand "xorsi3"
2287   [(set (match_operand:SI         0 "s_register_operand" "")
2288         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2289                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2290   "TARGET_EITHER"
2291   "if (TARGET_THUMB)
2292      if (GET_CODE (operands[2]) == CONST_INT)
2293        operands[2] = force_reg (SImode, operands[2]);
2294   "
2295 )
2296
2297 (define_insn "*arm_xorsi3"
2298   [(set (match_operand:SI         0 "s_register_operand" "=r")
2299         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2300                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2301   "TARGET_ARM"
2302   "eor%?\\t%0, %1, %2"
2303   [(set_attr "predicable" "yes")]
2304 )
2305
2306 (define_insn "*thumb_xorsi3"
2307   [(set (match_operand:SI         0 "register_operand" "=l")
2308         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2309                 (match_operand:SI 2 "register_operand" "l")))]
2310   "TARGET_THUMB"
2311   "eor\\t%0, %0, %2"
2312   [(set_attr "length" "2")]
2313 )
2314
2315 (define_insn "*xorsi3_compare0"
2316   [(set (reg:CC_NOOV CC_REGNUM)
2317         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2318                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2319                          (const_int 0)))
2320    (set (match_operand:SI 0 "s_register_operand" "=r")
2321         (xor:SI (match_dup 1) (match_dup 2)))]
2322   "TARGET_ARM"
2323   "eor%?s\\t%0, %1, %2"
2324   [(set_attr "conds" "set")]
2325 )
2326
2327 (define_insn "*xorsi3_compare0_scratch"
2328   [(set (reg:CC_NOOV CC_REGNUM)
2329         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2330                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2331                          (const_int 0)))]
2332   "TARGET_ARM"
2333   "teq%?\\t%0, %1"
2334   [(set_attr "conds" "set")]
2335 )
2336
2337 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2338 ; (NOT D) we can sometimes merge the final NOT into one of the following
2339 ; insns.
2340
2341 (define_split
2342   [(set (match_operand:SI 0 "s_register_operand" "")
2343         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2344                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2345                 (match_operand:SI 3 "arm_rhs_operand" "")))
2346    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2347   "TARGET_ARM"
2348   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2349                               (not:SI (match_dup 3))))
2350    (set (match_dup 0) (not:SI (match_dup 4)))]
2351   ""
2352 )
2353
2354 (define_insn "*andsi_iorsi3_notsi"
2355   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2356         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2357                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2358                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2359   "TARGET_ARM"
2360   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2361   [(set_attr "length" "8")
2362    (set_attr "predicable" "yes")]
2363 )
2364
2365 (define_split
2366   [(set (match_operand:SI 0 "s_register_operand" "")
2367         (match_operator:SI 1 "logical_binary_operator"
2368          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2369                            (match_operand:SI 3 "const_int_operand" "")
2370                            (match_operand:SI 4 "const_int_operand" ""))
2371           (match_operator:SI 9 "logical_binary_operator"
2372            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2373                          (match_operand:SI 6 "const_int_operand" ""))
2374             (match_operand:SI 7 "s_register_operand" "")])]))
2375    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2376   "TARGET_ARM
2377    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2378    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2379   [(set (match_dup 8)
2380         (match_op_dup 1
2381          [(ashift:SI (match_dup 2) (match_dup 4))
2382           (match_dup 5)]))
2383    (set (match_dup 0)
2384         (match_op_dup 1
2385          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2386           (match_dup 7)]))]
2387   "
2388   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2389 ")
2390
2391 (define_split
2392   [(set (match_operand:SI 0 "s_register_operand" "")
2393         (match_operator:SI 1 "logical_binary_operator"
2394          [(match_operator:SI 9 "logical_binary_operator"
2395            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2396                          (match_operand:SI 6 "const_int_operand" ""))
2397             (match_operand:SI 7 "s_register_operand" "")])
2398           (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2399                            (match_operand:SI 3 "const_int_operand" "")
2400                            (match_operand:SI 4 "const_int_operand" ""))]))
2401    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2402   "TARGET_ARM
2403    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2404    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2405   [(set (match_dup 8)
2406         (match_op_dup 1
2407          [(ashift:SI (match_dup 2) (match_dup 4))
2408           (match_dup 5)]))
2409    (set (match_dup 0)
2410         (match_op_dup 1
2411          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2412           (match_dup 7)]))]
2413   "
2414   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2415 ")
2416
2417 (define_split
2418   [(set (match_operand:SI 0 "s_register_operand" "")
2419         (match_operator:SI 1 "logical_binary_operator"
2420          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2421                            (match_operand:SI 3 "const_int_operand" "")
2422                            (match_operand:SI 4 "const_int_operand" ""))
2423           (match_operator:SI 9 "logical_binary_operator"
2424            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2425                          (match_operand:SI 6 "const_int_operand" ""))
2426             (match_operand:SI 7 "s_register_operand" "")])]))
2427    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2428   "TARGET_ARM
2429    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2430    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2431   [(set (match_dup 8)
2432         (match_op_dup 1
2433          [(ashift:SI (match_dup 2) (match_dup 4))
2434           (match_dup 5)]))
2435    (set (match_dup 0)
2436         (match_op_dup 1
2437          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2438           (match_dup 7)]))]
2439   "
2440   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2441 ")
2442
2443 (define_split
2444   [(set (match_operand:SI 0 "s_register_operand" "")
2445         (match_operator:SI 1 "logical_binary_operator"
2446          [(match_operator:SI 9 "logical_binary_operator"
2447            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2448                          (match_operand:SI 6 "const_int_operand" ""))
2449             (match_operand:SI 7 "s_register_operand" "")])
2450           (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2451                            (match_operand:SI 3 "const_int_operand" "")
2452                            (match_operand:SI 4 "const_int_operand" ""))]))
2453    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2454   "TARGET_ARM
2455    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2456    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2457   [(set (match_dup 8)
2458         (match_op_dup 1
2459          [(ashift:SI (match_dup 2) (match_dup 4))
2460           (match_dup 5)]))
2461    (set (match_dup 0)
2462         (match_op_dup 1
2463          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2464           (match_dup 7)]))]
2465   "
2466   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2467 ")
2468 \f
2469
2470 ;; Minimum and maximum insns
2471
2472 (define_insn "smaxsi3"
2473   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2474         (smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2475                  (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2476    (clobber (reg:CC CC_REGNUM))]
2477   "TARGET_ARM"
2478   "@
2479    cmp\\t%1, %2\;movlt\\t%0, %2
2480    cmp\\t%1, %2\;movge\\t%0, %1
2481    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2482   [(set_attr "conds" "clob")
2483    (set_attr "length" "8,8,12")]
2484 )
2485
2486 (define_insn "sminsi3"
2487   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2488         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2489                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2490    (clobber (reg:CC CC_REGNUM))]
2491   "TARGET_ARM"
2492   "@
2493    cmp\\t%1, %2\;movge\\t%0, %2
2494    cmp\\t%1, %2\;movlt\\t%0, %1
2495    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2496   [(set_attr "conds" "clob")
2497    (set_attr "length" "8,8,12")]
2498 )
2499
2500 (define_insn "umaxsi3"
2501   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2502         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2503                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2504    (clobber (reg:CC CC_REGNUM))]
2505   "TARGET_ARM"
2506   "@
2507    cmp\\t%1, %2\;movcc\\t%0, %2
2508    cmp\\t%1, %2\;movcs\\t%0, %1
2509    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2510   [(set_attr "conds" "clob")
2511    (set_attr "length" "8,8,12")]
2512 )
2513
2514 (define_insn "uminsi3"
2515   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2516         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2517                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2518    (clobber (reg:CC CC_REGNUM))]
2519   "TARGET_ARM"
2520   "@
2521    cmp\\t%1, %2\;movcs\\t%0, %2
2522    cmp\\t%1, %2\;movcc\\t%0, %1
2523    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2524   [(set_attr "conds" "clob")
2525    (set_attr "length" "8,8,12")]
2526 )
2527
2528 (define_insn "*store_minmaxsi"
2529   [(set (match_operand:SI 0 "memory_operand" "=m")
2530         (match_operator:SI 3 "minmax_operator"
2531          [(match_operand:SI 1 "s_register_operand" "r")
2532           (match_operand:SI 2 "s_register_operand" "r")]))
2533    (clobber (reg:CC CC_REGNUM))]
2534   "TARGET_ARM"
2535   "*
2536   operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2537                                 operands[1], operands[2]);
2538   output_asm_insn (\"cmp\\t%1, %2\", operands);
2539   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2540   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2541   return \"\";
2542   "
2543   [(set_attr "conds" "clob")
2544    (set_attr "length" "12")
2545    (set_attr "type" "store1")]
2546 )
2547
2548 ; Reject the frame pointer in operand[1], since reloading this after
2549 ; it has been eliminated can cause carnage.
2550 (define_insn "*minmax_arithsi"
2551   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2552         (match_operator:SI 4 "shiftable_operator"
2553          [(match_operator:SI 5 "minmax_operator"
2554            [(match_operand:SI 2 "s_register_operand" "r,r")
2555             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2556           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2557    (clobber (reg:CC CC_REGNUM))]
2558   "TARGET_ARM && !arm_eliminable_register (operands[1])"
2559   "*
2560   {
2561     enum rtx_code code = GET_CODE (operands[4]);
2562
2563     operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2564                                   operands[2], operands[3]);
2565     output_asm_insn (\"cmp\\t%2, %3\", operands);
2566     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2567     if (which_alternative != 0 || operands[3] != const0_rtx
2568         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2569       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2570     return \"\";
2571   }"
2572   [(set_attr "conds" "clob")
2573    (set_attr "length" "12")]
2574 )
2575
2576 \f
2577 ;; Shift and rotation insns
2578
2579 (define_expand "ashldi3"
2580   [(set (match_operand:DI            0 "s_register_operand" "")
2581         (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2582                    (match_operand:SI 2 "reg_or_int_operand" "")))]
2583   "TARGET_ARM"
2584   "
2585   if (GET_CODE (operands[2]) == CONST_INT)
2586     {
2587       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2588         {
2589           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2590           DONE;
2591         }
2592         /* Ideally we shouldn't fail here if we could know that operands[1] 
2593            ends up already living in an iwmmxt register. Otherwise it's
2594            cheaper to have the alternate code being generated than moving
2595            values to iwmmxt regs and back.  */
2596         FAIL;
2597     }
2598   else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2599     FAIL;
2600   "
2601 )
2602
2603 (define_insn "arm_ashldi3_1bit"
2604   [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
2605         (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2606                    (const_int 1)))
2607    (clobber (reg:CC CC_REGNUM))]
2608   "TARGET_ARM"
2609   "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2610   [(set_attr "conds" "clob")
2611    (set_attr "length" "8")]
2612 )
2613
2614 (define_expand "ashlsi3"
2615   [(set (match_operand:SI            0 "s_register_operand" "")
2616         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2617                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2618   "TARGET_EITHER"
2619   "
2620   if (GET_CODE (operands[2]) == CONST_INT
2621       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2622     {
2623       emit_insn (gen_movsi (operands[0], const0_rtx));
2624       DONE;
2625     }
2626   "
2627 )
2628
2629 (define_insn "*thumb_ashlsi3"
2630   [(set (match_operand:SI            0 "register_operand" "=l,l")
2631         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2632                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2633   "TARGET_THUMB"
2634   "lsl\\t%0, %1, %2"
2635   [(set_attr "length" "2")]
2636 )
2637
2638 (define_expand "ashrdi3"
2639   [(set (match_operand:DI              0 "s_register_operand" "")
2640         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2641                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2642   "TARGET_ARM"
2643   "
2644   if (GET_CODE (operands[2]) == CONST_INT)
2645     {
2646       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2647         {
2648           emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2649           DONE;
2650         }
2651         /* Ideally we shouldn't fail here if we could know that operands[1] 
2652            ends up already living in an iwmmxt register. Otherwise it's
2653            cheaper to have the alternate code being generated than moving
2654            values to iwmmxt regs and back.  */
2655         FAIL;
2656     }
2657   else if (!TARGET_REALLY_IWMMXT)
2658     FAIL;
2659   "
2660 )
2661
2662 (define_insn "arm_ashrdi3_1bit"
2663   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2664         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2665                      (const_int 1)))
2666    (clobber (reg:CC CC_REGNUM))]
2667   "TARGET_ARM"
2668   "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2669   [(set_attr "conds" "clob")
2670    (set_attr "length" "8")]
2671 )
2672
2673 (define_expand "ashrsi3"
2674   [(set (match_operand:SI              0 "s_register_operand" "")
2675         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2676                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2677   "TARGET_EITHER"
2678   "
2679   if (GET_CODE (operands[2]) == CONST_INT
2680       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2681     operands[2] = GEN_INT (31);
2682   "
2683 )
2684
2685 (define_insn "*thumb_ashrsi3"
2686   [(set (match_operand:SI              0 "register_operand" "=l,l")
2687         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2688                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2689   "TARGET_THUMB"
2690   "asr\\t%0, %1, %2"
2691   [(set_attr "length" "2")]
2692 )
2693
2694 (define_expand "lshrdi3"
2695   [(set (match_operand:DI              0 "s_register_operand" "")
2696         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2697                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2698   "TARGET_ARM"
2699   "
2700   if (GET_CODE (operands[2]) == CONST_INT)
2701     {
2702       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2703         {
2704           emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2705           DONE;
2706         }
2707         /* Ideally we shouldn't fail here if we could know that operands[1] 
2708            ends up already living in an iwmmxt register. Otherwise it's
2709            cheaper to have the alternate code being generated than moving
2710            values to iwmmxt regs and back.  */
2711         FAIL;
2712     }
2713   else if (!TARGET_REALLY_IWMMXT)
2714     FAIL;
2715   "
2716 )
2717
2718 (define_insn "arm_lshrdi3_1bit"
2719   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2720         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2721                      (const_int 1)))
2722    (clobber (reg:CC CC_REGNUM))]
2723   "TARGET_ARM"
2724   "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2725   [(set_attr "conds" "clob")
2726    (set_attr "length" "8")]
2727 )
2728
2729 (define_expand "lshrsi3"
2730   [(set (match_operand:SI              0 "s_register_operand" "")
2731         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2732                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2733   "TARGET_EITHER"
2734   "
2735   if (GET_CODE (operands[2]) == CONST_INT
2736       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2737     {
2738       emit_insn (gen_movsi (operands[0], const0_rtx));
2739       DONE;
2740     }
2741   "
2742 )
2743
2744 (define_insn "*thumb_lshrsi3"
2745   [(set (match_operand:SI              0 "register_operand" "=l,l")
2746         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2747                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2748   "TARGET_THUMB"
2749   "lsr\\t%0, %1, %2"
2750   [(set_attr "length" "2")]
2751 )
2752
2753 (define_expand "rotlsi3"
2754   [(set (match_operand:SI              0 "s_register_operand" "")
2755         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2756                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2757   "TARGET_ARM"
2758   "
2759   if (GET_CODE (operands[2]) == CONST_INT)
2760     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2761   else
2762     {
2763       rtx reg = gen_reg_rtx (SImode);
2764       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2765       operands[2] = reg;
2766     }
2767   "
2768 )
2769
2770 (define_expand "rotrsi3"
2771   [(set (match_operand:SI              0 "s_register_operand" "")
2772         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2773                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2774   "TARGET_EITHER"
2775   "
2776   if (TARGET_ARM)
2777     {
2778       if (GET_CODE (operands[2]) == CONST_INT
2779           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2780         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2781     }
2782   else /* TARGET_THUMB */
2783     {
2784       if (GET_CODE (operands [2]) == CONST_INT)
2785         operands [2] = force_reg (SImode, operands[2]);
2786     }
2787   "
2788 )
2789
2790 (define_insn "*thumb_rotrsi3"
2791   [(set (match_operand:SI              0 "register_operand" "=l")
2792         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2793                      (match_operand:SI 2 "register_operand" "l")))]
2794   "TARGET_THUMB"
2795   "ror\\t%0, %0, %2"
2796   [(set_attr "length" "2")]
2797 )
2798
2799 (define_insn "*arm_shiftsi3"
2800   [(set (match_operand:SI   0 "s_register_operand" "=r")
2801         (match_operator:SI  3 "shift_operator"
2802          [(match_operand:SI 1 "s_register_operand"  "r")
2803           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2804   "TARGET_ARM"
2805   "mov%?\\t%0, %1%S3"
2806   [(set_attr "predicable" "yes")
2807    (set_attr "shift" "1")
2808    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2809                       (const_string "alu_shift")
2810                       (const_string "alu_shift_reg")))]
2811 )
2812
2813 (define_insn "*shiftsi3_compare0"
2814   [(set (reg:CC_NOOV CC_REGNUM)
2815         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2816                           [(match_operand:SI 1 "s_register_operand" "r")
2817                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2818                          (const_int 0)))
2819    (set (match_operand:SI 0 "s_register_operand" "=r")
2820         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2821   "TARGET_ARM"
2822   "mov%?s\\t%0, %1%S3"
2823   [(set_attr "conds" "set")
2824    (set_attr "shift" "1")
2825    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2826                       (const_string "alu_shift")
2827                       (const_string "alu_shift_reg")))]
2828 )
2829
2830 (define_insn "*shiftsi3_compare0_scratch"
2831   [(set (reg:CC_NOOV CC_REGNUM)
2832         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2833                           [(match_operand:SI 1 "s_register_operand" "r")
2834                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2835                          (const_int 0)))
2836    (clobber (match_scratch:SI 0 "=r"))]
2837   "TARGET_ARM"
2838   "mov%?s\\t%0, %1%S3"
2839   [(set_attr "conds" "set")
2840    (set_attr "shift" "1")]
2841 )
2842
2843 (define_insn "*notsi_shiftsi"
2844   [(set (match_operand:SI 0 "s_register_operand" "=r")
2845         (not:SI (match_operator:SI 3 "shift_operator"
2846                  [(match_operand:SI 1 "s_register_operand" "r")
2847                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2848   "TARGET_ARM"
2849   "mvn%?\\t%0, %1%S3"
2850   [(set_attr "predicable" "yes")
2851    (set_attr "shift" "1")
2852    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2853                       (const_string "alu_shift")
2854                       (const_string "alu_shift_reg")))]
2855 )
2856
2857 (define_insn "*notsi_shiftsi_compare0"
2858   [(set (reg:CC_NOOV CC_REGNUM)
2859         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2860                           [(match_operand:SI 1 "s_register_operand" "r")
2861                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2862                          (const_int 0)))
2863    (set (match_operand:SI 0 "s_register_operand" "=r")
2864         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2865   "TARGET_ARM"
2866   "mvn%?s\\t%0, %1%S3"
2867   [(set_attr "conds" "set")
2868    (set_attr "shift" "1")
2869    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2870                       (const_string "alu_shift")
2871                       (const_string "alu_shift_reg")))]
2872 )
2873
2874 (define_insn "*not_shiftsi_compare0_scratch"
2875   [(set (reg:CC_NOOV CC_REGNUM)
2876         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2877                           [(match_operand:SI 1 "s_register_operand" "r")
2878                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2879                          (const_int 0)))
2880    (clobber (match_scratch:SI 0 "=r"))]
2881   "TARGET_ARM"
2882   "mvn%?s\\t%0, %1%S3"
2883   [(set_attr "conds" "set")
2884    (set_attr "shift" "1")
2885    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2886                       (const_string "alu_shift")
2887                       (const_string "alu_shift_reg")))]
2888 )
2889
2890 ;; We don't really have extzv, but defining this using shifts helps
2891 ;; to reduce register pressure later on.
2892
2893 (define_expand "extzv"
2894   [(set (match_dup 4)
2895         (ashift:SI (match_operand:SI   1 "register_operand" "")
2896                    (match_operand:SI   2 "const_int_operand" "")))
2897    (set (match_operand:SI              0 "register_operand" "")
2898         (lshiftrt:SI (match_dup 4)
2899                      (match_operand:SI 3 "const_int_operand" "")))]
2900   "TARGET_THUMB"
2901   "
2902   {
2903     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2904     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2905     
2906     operands[3] = GEN_INT (rshift);
2907     
2908     if (lshift == 0)
2909       {
2910         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2911         DONE;
2912       }
2913       
2914     operands[2] = GEN_INT (lshift);
2915     operands[4] = gen_reg_rtx (SImode);
2916   }"
2917 )
2918
2919 \f
2920 ;; Unary arithmetic insns
2921
2922 (define_expand "negdi2"
2923  [(parallel
2924    [(set (match_operand:DI          0 "s_register_operand" "")
2925           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2926     (clobber (reg:CC CC_REGNUM))])]
2927   "TARGET_EITHER"
2928   "
2929   if (TARGET_THUMB)
2930     {
2931       if (GET_CODE (operands[1]) != REG)
2932         operands[1] = force_reg (SImode, operands[1]);
2933      }
2934   "
2935 )
2936
2937 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2938 ;; The second alternative is to allow the common case of a *full* overlap.
2939 (define_insn "*arm_negdi2"
2940   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2941         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2942    (clobber (reg:CC CC_REGNUM))]
2943   "TARGET_ARM"
2944   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2945   [(set_attr "conds" "clob")
2946    (set_attr "length" "8")]
2947 )
2948
2949 (define_insn "*thumb_negdi2"
2950   [(set (match_operand:DI         0 "register_operand" "=&l")
2951         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
2952    (clobber (reg:CC CC_REGNUM))]
2953   "TARGET_THUMB"
2954   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2955   [(set_attr "length" "6")]
2956 )
2957
2958 (define_expand "negsi2"
2959   [(set (match_operand:SI         0 "s_register_operand" "")
2960         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2961   "TARGET_EITHER"
2962   ""
2963 )
2964
2965 (define_insn "*arm_negsi2"
2966   [(set (match_operand:SI         0 "s_register_operand" "=r")
2967         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2968   "TARGET_ARM"
2969   "rsb%?\\t%0, %1, #0"
2970   [(set_attr "predicable" "yes")]
2971 )
2972
2973 (define_insn "*thumb_negsi2"
2974   [(set (match_operand:SI         0 "register_operand" "=l")
2975         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2976   "TARGET_THUMB"
2977   "neg\\t%0, %1"
2978   [(set_attr "length" "2")]
2979 )
2980
2981 (define_expand "negsf2"
2982   [(set (match_operand:SF         0 "s_register_operand" "")
2983         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2984   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
2985   ""
2986 )
2987
2988 (define_expand "negdf2"
2989   [(set (match_operand:DF         0 "s_register_operand" "")
2990         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2991   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
2992   "")
2993
2994 ;; abssi2 doesn't really clobber the condition codes if a different register
2995 ;; is being set.  To keep things simple, assume during rtl manipulations that
2996 ;; it does, but tell the final scan operator the truth.  Similarly for
2997 ;; (neg (abs...))
2998
2999 (define_expand "abssi2"
3000   [(parallel
3001     [(set (match_operand:SI         0 "s_register_operand" "")
3002           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3003      (clobber (reg:CC CC_REGNUM))])]
3004   "TARGET_ARM"
3005   "")
3006
3007 (define_insn "*arm_abssi2"
3008   [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
3009         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3010    (clobber (reg:CC CC_REGNUM))]
3011   "TARGET_ARM"
3012   "@
3013    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3014    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3015   [(set_attr "conds" "clob,*")
3016    (set_attr "shift" "1")
3017    ;; predicable can't be set based on the variant, so left as no
3018    (set_attr "length" "8")]
3019 )
3020
3021 (define_insn "*neg_abssi2"
3022   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3023         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3024    (clobber (reg:CC CC_REGNUM))]
3025   "TARGET_ARM"
3026   "@
3027    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3028    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3029   [(set_attr "conds" "clob,*")
3030    (set_attr "shift" "1")
3031    ;; predicable can't be set based on the variant, so left as no
3032    (set_attr "length" "8")]
3033 )
3034
3035 (define_expand "abssf2"
3036   [(set (match_operand:SF         0 "s_register_operand" "")
3037         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3038   "TARGET_ARM && TARGET_HARD_FLOAT"
3039   "")
3040
3041 (define_expand "absdf2"
3042   [(set (match_operand:DF         0 "s_register_operand" "")
3043         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3044   "TARGET_ARM && TARGET_HARD_FLOAT"
3045   "")
3046
3047 (define_expand "sqrtsf2"
3048   [(set (match_operand:SF 0 "s_register_operand" "")
3049         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3050   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3051   "")
3052
3053 (define_expand "sqrtdf2"
3054   [(set (match_operand:DF 0 "s_register_operand" "")
3055         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3056   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3057   "")
3058
3059 (define_insn_and_split "one_cmpldi2"
3060   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3061         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3062   "TARGET_ARM"
3063   "#"
3064   "TARGET_ARM && reload_completed"
3065   [(set (match_dup 0) (not:SI (match_dup 1)))
3066    (set (match_dup 2) (not:SI (match_dup 3)))]
3067   "
3068   {
3069     operands[2] = gen_highpart (SImode, operands[0]);
3070     operands[0] = gen_lowpart (SImode, operands[0]);
3071     operands[3] = gen_highpart (SImode, operands[1]);
3072     operands[1] = gen_lowpart (SImode, operands[1]);
3073   }"
3074   [(set_attr "length" "8")
3075    (set_attr "predicable" "yes")]
3076 )
3077
3078 (define_expand "one_cmplsi2"
3079   [(set (match_operand:SI         0 "s_register_operand" "")
3080         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3081   "TARGET_EITHER"
3082   ""
3083 )
3084
3085 (define_insn "*arm_one_cmplsi2"
3086   [(set (match_operand:SI         0 "s_register_operand" "=r")
3087         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3088   "TARGET_ARM"
3089   "mvn%?\\t%0, %1"
3090   [(set_attr "predicable" "yes")]
3091 )
3092
3093 (define_insn "*thumb_one_cmplsi2"
3094   [(set (match_operand:SI         0 "register_operand" "=l")
3095         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3096   "TARGET_THUMB"
3097   "mvn\\t%0, %1"
3098   [(set_attr "length" "2")]
3099 )
3100
3101 (define_insn "*notsi_compare0"
3102   [(set (reg:CC_NOOV CC_REGNUM)
3103         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3104                          (const_int 0)))
3105    (set (match_operand:SI 0 "s_register_operand" "=r")
3106         (not:SI (match_dup 1)))]
3107   "TARGET_ARM"
3108   "mvn%?s\\t%0, %1"
3109   [(set_attr "conds" "set")]
3110 )
3111
3112 (define_insn "*notsi_compare0_scratch"
3113   [(set (reg:CC_NOOV CC_REGNUM)
3114         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3115                          (const_int 0)))
3116    (clobber (match_scratch:SI 0 "=r"))]
3117   "TARGET_ARM"
3118   "mvn%?s\\t%0, %1"
3119   [(set_attr "conds" "set")]
3120 )
3121 \f
3122 ;; Fixed <--> Floating conversion insns
3123
3124 (define_expand "floatsisf2"
3125   [(set (match_operand:SF           0 "s_register_operand" "")
3126         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3127   "TARGET_ARM && TARGET_HARD_FLOAT"
3128   "
3129   if (TARGET_MAVERICK)
3130     {
3131       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3132       DONE;
3133     }
3134 ")
3135
3136 (define_expand "floatsidf2"
3137   [(set (match_operand:DF           0 "s_register_operand" "")
3138         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3139   "TARGET_ARM && TARGET_HARD_FLOAT"
3140   "
3141   if (TARGET_MAVERICK)
3142     {
3143       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3144       DONE;
3145     }
3146 ")
3147
3148 (define_expand "fix_truncsfsi2"
3149   [(set (match_operand:SI         0 "s_register_operand" "")
3150         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3151   "TARGET_ARM && TARGET_HARD_FLOAT"
3152   "
3153   if (TARGET_MAVERICK)
3154     {
3155       if (!cirrus_fp_register (operands[0], SImode))
3156         operands[0] = force_reg (SImode, operands[0]);
3157       if (!cirrus_fp_register (operands[1], SFmode))
3158         operands[1] = force_reg (SFmode, operands[0]);
3159       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3160       DONE;
3161     }
3162 ")
3163
3164 (define_expand "fix_truncdfsi2"
3165   [(set (match_operand:SI         0 "s_register_operand" "")
3166         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3167   "TARGET_ARM && TARGET_HARD_FLOAT"
3168   "
3169   if (TARGET_MAVERICK)
3170     {
3171       if (!cirrus_fp_register (operands[1], DFmode))
3172         operands[1] = force_reg (DFmode, operands[0]);
3173       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3174       DONE;
3175     }
3176 ")
3177
3178 ;; Truncation insns
3179
3180 (define_expand "truncdfsf2"
3181   [(set (match_operand:SF  0 "s_register_operand" "")
3182         (float_truncate:SF
3183          (match_operand:DF 1 "s_register_operand" "")))]
3184   "TARGET_ARM && TARGET_HARD_FLOAT"
3185   ""
3186 )
3187 \f
3188 ;; Zero and sign extension instructions.
3189
3190 (define_insn "zero_extendsidi2"
3191   [(set (match_operand:DI 0 "s_register_operand" "=r")
3192         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3193   "TARGET_ARM"
3194   "*
3195     if (REGNO (operands[1])
3196         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3197       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3198     return \"mov%?\\t%R0, #0\";
3199   "
3200   [(set_attr "length" "8")
3201    (set_attr "predicable" "yes")]
3202 )
3203
3204 (define_insn "zero_extendqidi2"
3205   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3206         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3207   "TARGET_ARM"
3208   "@
3209    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3210    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3211   [(set_attr "length" "8")
3212    (set_attr "predicable" "yes")
3213    (set_attr "type" "*,load_byte")
3214    (set_attr "pool_range" "*,4092")
3215    (set_attr "neg_pool_range" "*,4084")]
3216 )
3217
3218 (define_insn "extendsidi2"
3219   [(set (match_operand:DI 0 "s_register_operand" "=r")
3220         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3221   "TARGET_ARM"
3222   "*
3223     if (REGNO (operands[1])
3224         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3225       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3226     return \"mov%?\\t%R0, %Q0, asr #31\";
3227   "
3228   [(set_attr "length" "8")
3229    (set_attr "shift" "1")
3230    (set_attr "predicable" "yes")]
3231 )
3232
3233 (define_expand "zero_extendhisi2"
3234   [(set (match_dup 2)
3235         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3236                    (const_int 16)))
3237    (set (match_operand:SI 0 "s_register_operand" "")
3238         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3239   "TARGET_EITHER"
3240   "
3241   {
3242     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3243       {
3244         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3245                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3246         DONE;
3247       }
3248
3249     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3250       {
3251         emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3252         DONE;
3253       }
3254
3255     if (!s_register_operand (operands[1], HImode))
3256       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3257
3258     if (arm_arch6)
3259       {
3260         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3261                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3262         DONE;
3263       }
3264
3265     operands[1] = gen_lowpart (SImode, operands[1]);
3266     operands[2] = gen_reg_rtx (SImode);
3267   }"
3268 )
3269
3270 (define_insn "*thumb_zero_extendhisi2"
3271   [(set (match_operand:SI 0 "register_operand" "=l")
3272         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3273   "TARGET_THUMB && !arm_arch6"
3274   "*
3275   rtx mem = XEXP (operands[1], 0);
3276
3277   if (GET_CODE (mem) == CONST)
3278     mem = XEXP (mem, 0);
3279     
3280   if (GET_CODE (mem) == LABEL_REF)
3281     return \"ldr\\t%0, %1\";
3282     
3283   if (GET_CODE (mem) == PLUS)
3284     {
3285       rtx a = XEXP (mem, 0);
3286       rtx b = XEXP (mem, 1);
3287
3288       /* This can happen due to bugs in reload.  */
3289       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3290         {
3291           rtx ops[2];
3292           ops[0] = operands[0];
3293           ops[1] = a;
3294       
3295           output_asm_insn (\"mov        %0, %1\", ops);
3296
3297           XEXP (mem, 0) = operands[0];
3298        }
3299
3300       else if (   GET_CODE (a) == LABEL_REF
3301                && GET_CODE (b) == CONST_INT)
3302         return \"ldr\\t%0, %1\";
3303     }
3304     
3305   return \"ldrh\\t%0, %1\";
3306   "
3307   [(set_attr "length" "4")
3308    (set_attr "type" "load_byte")
3309    (set_attr "pool_range" "60")]
3310 )
3311
3312 (define_insn "*thumb_zero_extendhisi2_v6"
3313   [(set (match_operand:SI 0 "register_operand" "=l,l")
3314         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3315   "TARGET_THUMB && arm_arch6"
3316   "*
3317   rtx mem;
3318
3319   if (which_alternative == 0)
3320     return \"uxth\\t%0, %1\";
3321
3322   mem = XEXP (operands[1], 0);
3323
3324   if (GET_CODE (mem) == CONST)
3325     mem = XEXP (mem, 0);
3326     
3327   if (GET_CODE (mem) == LABEL_REF)
3328     return \"ldr\\t%0, %1\";
3329     
3330   if (GET_CODE (mem) == PLUS)
3331     {
3332       rtx a = XEXP (mem, 0);
3333       rtx b = XEXP (mem, 1);
3334
3335       /* This can happen due to bugs in reload.  */
3336       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3337         {
3338           rtx ops[2];
3339           ops[0] = operands[0];
3340           ops[1] = a;
3341       
3342           output_asm_insn (\"mov        %0, %1\", ops);
3343
3344           XEXP (mem, 0) = operands[0];
3345        }
3346
3347       else if (   GET_CODE (a) == LABEL_REF
3348                && GET_CODE (b) == CONST_INT)
3349         return \"ldr\\t%0, %1\";
3350     }
3351     
3352   return \"ldrh\\t%0, %1\";
3353   "
3354   [(set_attr "length" "2,4")
3355    (set_attr "type" "alu_shift,load_byte")
3356    (set_attr "pool_range" "*,60")]
3357 )
3358
3359 (define_insn "*arm_zero_extendhisi2"
3360   [(set (match_operand:SI 0 "s_register_operand" "=r")
3361         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3362   "TARGET_ARM && arm_arch4 && !arm_arch6"
3363   "ldr%?h\\t%0, %1"
3364   [(set_attr "type" "load_byte")
3365    (set_attr "predicable" "yes")
3366    (set_attr "pool_range" "256")
3367    (set_attr "neg_pool_range" "244")]
3368 )
3369
3370 (define_insn "*arm_zero_extendhisi2_v6"
3371   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3372         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3373   "TARGET_ARM && arm_arch6"
3374   "@
3375    uxth%?\\t%0, %1
3376    ldr