OSDN Git Service

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