OSDN Git Service

53b633ddc7f072274e31d060ffe5a29018e2bf2d
[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
313 ;;---------------------------------------------------------------------------
314 ;; Pipeline descriptions
315
316 ;; Processor type.  This is created automatically from arm-cores.def.
317 (include "arm-tune.md")
318
319 ;; True if the generic scheduling description should be used.
320
321 (define_attr "generic_sched" "yes,no"
322   (const (if_then_else 
323           (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs") 
324           (const_string "no")
325           (const_string "yes"))))
326
327 (define_attr "generic_vfp" "yes,no"
328   (const (if_then_else
329           (and (eq_attr "fpu" "vfp")
330                (eq_attr "tune" "!arm1020e,arm1022e"))
331           (const_string "yes")
332           (const_string "no"))))
333
334 (include "arm-generic.md")
335 (include "arm926ejs.md")
336 (include "arm1020e.md")
337 (include "arm1026ejs.md")
338 (include "arm1136jfs.md")
339
340 \f
341 ;;---------------------------------------------------------------------------
342 ;; Insn patterns
343 ;;
344 ;; Addition insns.
345
346 ;; Note: For DImode insns, there is normally no reason why operands should
347 ;; not be in the same register, what we don't want is for something being
348 ;; written to partially overlap something that is an input.
349 ;; Cirrus 64bit additions should not be split because we have a native
350 ;; 64bit addition instructions.
351
352 (define_expand "adddi3"
353  [(parallel
354    [(set (match_operand:DI           0 "s_register_operand" "")
355           (plus:DI (match_operand:DI 1 "s_register_operand" "")
356                    (match_operand:DI 2 "s_register_operand" "")))
357     (clobber (reg:CC CC_REGNUM))])]
358   "TARGET_EITHER"
359   "
360   if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
361     {
362       if (!cirrus_fp_register (operands[0], DImode))
363         operands[0] = force_reg (DImode, operands[0]);
364       if (!cirrus_fp_register (operands[1], DImode))
365         operands[1] = force_reg (DImode, operands[1]);
366       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
367       DONE;
368     }
369
370   if (TARGET_THUMB)
371     {
372       if (GET_CODE (operands[1]) != REG)
373         operands[1] = force_reg (SImode, operands[1]);
374       if (GET_CODE (operands[2]) != REG)
375         operands[2] = force_reg (SImode, operands[2]);
376      }
377   "
378 )
379
380 (define_insn "*thumb_adddi3"
381   [(set (match_operand:DI          0 "register_operand" "=l")
382         (plus:DI (match_operand:DI 1 "register_operand" "%0")
383                  (match_operand:DI 2 "register_operand" "l")))
384    (clobber (reg:CC CC_REGNUM))
385   ]
386   "TARGET_THUMB"
387   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
388   [(set_attr "length" "4")]
389 )
390
391 (define_insn_and_split "*arm_adddi3"
392   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
393         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
394                  (match_operand:DI 2 "s_register_operand" "r,  0")))
395    (clobber (reg:CC CC_REGNUM))]
396   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
397   "#"
398   "TARGET_ARM && reload_completed"
399   [(parallel [(set (reg:CC_C CC_REGNUM)
400                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
401                                  (match_dup 1)))
402               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
403    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
404                                (plus:SI (match_dup 4) (match_dup 5))))]
405   "
406   {
407     operands[3] = gen_highpart (SImode, operands[0]);
408     operands[0] = gen_lowpart (SImode, operands[0]);
409     operands[4] = gen_highpart (SImode, operands[1]);
410     operands[1] = gen_lowpart (SImode, operands[1]);
411     operands[5] = gen_highpart (SImode, operands[2]);
412     operands[2] = gen_lowpart (SImode, operands[2]);
413   }"
414   [(set_attr "conds" "clob")
415    (set_attr "length" "8")]
416 )
417
418 (define_insn_and_split "*adddi_sesidi_di"
419   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
420         (plus:DI (sign_extend:DI
421                   (match_operand:SI 2 "s_register_operand" "r,r"))
422                  (match_operand:DI 1 "s_register_operand" "r,0")))
423    (clobber (reg:CC CC_REGNUM))]
424   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
425   "#"
426   "TARGET_ARM && reload_completed"
427   [(parallel [(set (reg:CC_C CC_REGNUM)
428                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
429                                  (match_dup 1)))
430               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
431    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
432                                (plus:SI (ashiftrt:SI (match_dup 2)
433                                                      (const_int 31))
434                                         (match_dup 4))))]
435   "
436   {
437     operands[3] = gen_highpart (SImode, operands[0]);
438     operands[0] = gen_lowpart (SImode, operands[0]);
439     operands[4] = gen_highpart (SImode, operands[1]);
440     operands[1] = gen_lowpart (SImode, operands[1]);
441     operands[2] = gen_lowpart (SImode, operands[2]);
442   }"
443   [(set_attr "conds" "clob")
444    (set_attr "length" "8")]
445 )
446
447 (define_insn_and_split "*adddi_zesidi_di"
448   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
449         (plus:DI (zero_extend:DI
450                   (match_operand:SI 2 "s_register_operand" "r,r"))
451                  (match_operand:DI 1 "s_register_operand" "r,0")))
452    (clobber (reg:CC CC_REGNUM))]
453   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
454   "#"
455   "TARGET_ARM && reload_completed"
456   [(parallel [(set (reg:CC_C CC_REGNUM)
457                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
458                                  (match_dup 1)))
459               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
460    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
461                                (plus:SI (match_dup 4) (const_int 0))))]
462   "
463   {
464     operands[3] = gen_highpart (SImode, operands[0]);
465     operands[0] = gen_lowpart (SImode, operands[0]);
466     operands[4] = gen_highpart (SImode, operands[1]);
467     operands[1] = gen_lowpart (SImode, operands[1]);
468     operands[2] = gen_lowpart (SImode, operands[2]);
469   }"
470   [(set_attr "conds" "clob")
471    (set_attr "length" "8")]
472 )
473
474 (define_expand "addsi3"
475   [(set (match_operand:SI          0 "s_register_operand" "")
476         (plus:SI (match_operand:SI 1 "s_register_operand" "")
477                  (match_operand:SI 2 "reg_or_int_operand" "")))]
478   "TARGET_EITHER"
479   "
480   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
481     {
482       arm_split_constant (PLUS, SImode, NULL_RTX,
483                           INTVAL (operands[2]), operands[0], operands[1],
484                           optimize && !no_new_pseudos);
485       DONE;
486     }
487   "
488 )
489
490 ; If there is a scratch available, this will be faster than synthesizing the
491 ; addition.
492 (define_peephole2
493   [(match_scratch:SI 3 "r")
494    (set (match_operand:SI          0 "arm_general_register_operand" "")
495         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
496                  (match_operand:SI 2 "const_int_operand"  "")))]
497   "TARGET_ARM &&
498    !(const_ok_for_arm (INTVAL (operands[2]))
499      || const_ok_for_arm (-INTVAL (operands[2])))
500     && const_ok_for_arm (~INTVAL (operands[2]))"
501   [(set (match_dup 3) (match_dup 2))
502    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
503   ""
504 )
505
506 (define_insn_and_split "*arm_addsi3"
507   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
508         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
509                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
510   "TARGET_ARM"
511   "@
512    add%?\\t%0, %1, %2
513    sub%?\\t%0, %1, #%n2
514    #"
515   "TARGET_ARM &&
516    GET_CODE (operands[2]) == CONST_INT
517    && !(const_ok_for_arm (INTVAL (operands[2]))
518         || const_ok_for_arm (-INTVAL (operands[2])))"
519   [(clobber (const_int 0))]
520   "
521   arm_split_constant (PLUS, SImode, curr_insn,
522                       INTVAL (operands[2]), operands[0],
523                       operands[1], 0);
524   DONE;
525   "
526   [(set_attr "length" "4,4,16")
527    (set_attr "predicable" "yes")]
528 )
529
530 ;; Register group 'k' is a single register group containing only the stack
531 ;; register.  Trying to reload it will always fail catastrophically,
532 ;; so never allow those alternatives to match if reloading is needed.
533
534 (define_insn "*thumb_addsi3"
535   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
536         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
537                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
538   "TARGET_THUMB"
539   "*
540    static const char * const asms[] = 
541    {
542      \"add\\t%0, %0, %2\",
543      \"sub\\t%0, %0, #%n2\",
544      \"add\\t%0, %1, %2\",
545      \"add\\t%0, %0, %2\",
546      \"add\\t%0, %0, %2\",
547      \"add\\t%0, %1, %2\",
548      \"add\\t%0, %1, %2\"
549    };
550    if ((which_alternative == 2 || which_alternative == 6)
551        && GET_CODE (operands[2]) == CONST_INT
552        && INTVAL (operands[2]) < 0)
553      return \"sub\\t%0, %1, #%n2\";
554    return asms[which_alternative];
555   "
556   [(set_attr "length" "2")]
557 )
558
559 ;; Reloading and elimination of the frame pointer can
560 ;; sometimes cause this optimization to be missed.
561 (define_peephole2
562   [(set (match_operand:SI 0 "arm_general_register_operand" "")
563         (match_operand:SI 1 "const_int_operand" ""))
564    (set (match_dup 0)
565         (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
566   "TARGET_THUMB
567    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
568    && (INTVAL (operands[1]) & 3) == 0"
569   [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
570   ""
571 )
572
573 (define_insn "*addsi3_compare0"
574   [(set (reg:CC_NOOV CC_REGNUM)
575         (compare:CC_NOOV
576          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
577                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
578          (const_int 0)))
579    (set (match_operand:SI 0 "s_register_operand" "=r,r")
580         (plus:SI (match_dup 1) (match_dup 2)))]
581   "TARGET_ARM"
582   "@
583    add%?s\\t%0, %1, %2
584    sub%?s\\t%0, %1, #%n2"
585   [(set_attr "conds" "set")]
586 )
587
588 (define_insn "*addsi3_compare0_scratch"
589   [(set (reg:CC_NOOV CC_REGNUM)
590         (compare:CC_NOOV
591          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
592                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
593          (const_int 0)))]
594   "TARGET_ARM"
595   "@
596    cmn%?\\t%0, %1
597    cmp%?\\t%0, #%n1"
598   [(set_attr "conds" "set")]
599 )
600
601 (define_insn "*compare_negsi_si"
602   [(set (reg:CC_Z CC_REGNUM)
603         (compare:CC_Z
604          (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
605          (match_operand:SI 1 "s_register_operand" "r")))]
606   "TARGET_ARM"
607   "cmn%?\\t%1, %0"
608   [(set_attr "conds" "set")]
609 )
610
611 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
612 ;; addend is a constant.
613 (define_insn "*cmpsi2_addneg"
614   [(set (reg:CC CC_REGNUM)
615         (compare:CC
616          (match_operand:SI 1 "s_register_operand" "r,r")
617          (match_operand:SI 2 "arm_addimm_operand" "I,L")))
618    (set (match_operand:SI 0 "s_register_operand" "=r,r")
619         (plus:SI (match_dup 1)
620                  (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
621   "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
622   "@
623    sub%?s\\t%0, %1, %2
624    add%?s\\t%0, %1, #%n2"
625   [(set_attr "conds" "set")]
626 )
627
628 ;; Convert the sequence
629 ;;  sub  rd, rn, #1
630 ;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
631 ;;  bne  dest
632 ;; into
633 ;;  subs rd, rn, #1
634 ;;  bcs  dest   ((unsigned)rn >= 1)
635 ;; similarly for the beq variant using bcc.
636 ;; This is a common looping idiom (while (n--))
637 (define_peephole2
638   [(set (match_operand:SI 0 "arm_general_register_operand" "")
639         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
640                  (const_int -1)))
641    (set (match_operand 2 "cc_register" "")
642         (compare (match_dup 0) (const_int -1)))
643    (set (pc)
644         (if_then_else (match_operator 3 "equality_operator"
645                        [(match_dup 2) (const_int 0)])
646                       (match_operand 4 "" "")
647                       (match_operand 5 "" "")))]
648   "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
649   [(parallel[
650     (set (match_dup 2)
651          (compare:CC
652           (match_dup 1) (const_int 1)))
653     (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
654    (set (pc)
655         (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
656                       (match_dup 4)
657                       (match_dup 5)))]
658   "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
659    operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
660                                   ? GEU : LTU),
661                                  VOIDmode, 
662                                  operands[2], const0_rtx);"
663 )
664
665 ;; The next four insns work because they compare the result with one of
666 ;; the operands, and we know that the use of the condition code is
667 ;; either GEU or LTU, so we can use the carry flag from the addition
668 ;; instead of doing the compare a second time.
669 (define_insn "*addsi3_compare_op1"
670   [(set (reg:CC_C CC_REGNUM)
671         (compare:CC_C
672          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
673                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
674          (match_dup 1)))
675    (set (match_operand:SI 0 "s_register_operand" "=r,r")
676         (plus:SI (match_dup 1) (match_dup 2)))]
677   "TARGET_ARM"
678   "@
679    add%?s\\t%0, %1, %2
680    sub%?s\\t%0, %1, #%n2"
681   [(set_attr "conds" "set")]
682 )
683
684 (define_insn "*addsi3_compare_op2"
685   [(set (reg:CC_C CC_REGNUM)
686         (compare:CC_C
687          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
688                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
689          (match_dup 2)))
690    (set (match_operand:SI 0 "s_register_operand" "=r,r")
691         (plus:SI (match_dup 1) (match_dup 2)))]
692   "TARGET_ARM"
693   "@
694    add%?s\\t%0, %1, %2
695    sub%?s\\t%0, %1, #%n2"
696   [(set_attr "conds" "set")]
697 )
698
699 (define_insn "*compare_addsi2_op0"
700   [(set (reg:CC_C CC_REGNUM)
701         (compare:CC_C
702          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
703                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
704          (match_dup 0)))]
705   "TARGET_ARM"
706   "@
707    cmn%?\\t%0, %1
708    cmp%?\\t%0, #%n1"
709   [(set_attr "conds" "set")]
710 )
711
712 (define_insn "*compare_addsi2_op1"
713   [(set (reg:CC_C CC_REGNUM)
714         (compare:CC_C
715          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
716                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
717          (match_dup 1)))]
718   "TARGET_ARM"
719   "@
720    cmn%?\\t%0, %1
721    cmp%?\\t%0, #%n1"
722   [(set_attr "conds" "set")]
723 )
724
725 (define_insn "*addsi3_carryin"
726   [(set (match_operand:SI 0 "s_register_operand" "=r")
727         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
728                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
729                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
730   "TARGET_ARM"
731   "adc%?\\t%0, %1, %2"
732   [(set_attr "conds" "use")]
733 )
734
735 (define_insn "*addsi3_carryin_shift"
736   [(set (match_operand:SI 0 "s_register_operand" "=r")
737         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
738                  (plus:SI
739                    (match_operator:SI 2 "shift_operator"
740                       [(match_operand:SI 3 "s_register_operand" "r")
741                        (match_operand:SI 4 "reg_or_int_operand" "rM")])
742                     (match_operand:SI 1 "s_register_operand" "r"))))]
743   "TARGET_ARM"
744   "adc%?\\t%0, %1, %3%S2"
745   [(set_attr "conds" "use")
746    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
747                       (const_string "alu_shift")
748                       (const_string "alu_shift_reg")))]
749 )
750
751 (define_insn "*addsi3_carryin_alt1"
752   [(set (match_operand:SI 0 "s_register_operand" "=r")
753         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
754                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
755                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
756   "TARGET_ARM"
757   "adc%?\\t%0, %1, %2"
758   [(set_attr "conds" "use")]
759 )
760
761 (define_insn "*addsi3_carryin_alt2"
762   [(set (match_operand:SI 0 "s_register_operand" "=r")
763         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
764                           (match_operand:SI 1 "s_register_operand" "r"))
765                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
766   "TARGET_ARM"
767   "adc%?\\t%0, %1, %2"
768   [(set_attr "conds" "use")]
769 )
770
771 (define_insn "*addsi3_carryin_alt3"
772   [(set (match_operand:SI 0 "s_register_operand" "=r")
773         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
774                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
775                  (match_operand:SI 1 "s_register_operand" "r")))]
776   "TARGET_ARM"
777   "adc%?\\t%0, %1, %2"
778   [(set_attr "conds" "use")]
779 )
780
781 (define_insn "incscc"
782   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
783         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
784                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
785                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
786   "TARGET_ARM"
787   "@
788   add%d2\\t%0, %1, #1
789   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
790   [(set_attr "conds" "use")
791    (set_attr "length" "4,8")]
792 )
793
794 ; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
795 (define_split
796   [(set (match_operand:SI 0 "s_register_operand" "")
797         (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
798                             (match_operand:SI 2 "s_register_operand" ""))
799                  (const_int -1)))
800    (clobber (match_operand:SI 3 "s_register_operand" ""))]
801   "TARGET_ARM"
802   [(set (match_dup 3) (match_dup 1))
803    (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
804   "
805   operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
806 ")
807
808 (define_expand "addsf3"
809   [(set (match_operand:SF          0 "s_register_operand" "")
810         (plus:SF (match_operand:SF 1 "s_register_operand" "")
811                  (match_operand:SF 2 "arm_float_add_operand" "")))]
812   "TARGET_ARM && TARGET_HARD_FLOAT"
813   "
814   if (TARGET_MAVERICK
815       && !cirrus_fp_register (operands[2], SFmode))
816     operands[2] = force_reg (SFmode, operands[2]);
817 ")
818
819 (define_expand "adddf3"
820   [(set (match_operand:DF          0 "s_register_operand" "")
821         (plus:DF (match_operand:DF 1 "s_register_operand" "")
822                  (match_operand:DF 2 "arm_float_add_operand" "")))]
823   "TARGET_ARM && TARGET_HARD_FLOAT"
824   "
825   if (TARGET_MAVERICK
826       && !cirrus_fp_register (operands[2], DFmode))
827     operands[2] = force_reg (DFmode, operands[2]);
828 ")
829
830 (define_expand "subdi3"
831  [(parallel
832    [(set (match_operand:DI            0 "s_register_operand" "")
833           (minus:DI (match_operand:DI 1 "s_register_operand" "")
834                     (match_operand:DI 2 "s_register_operand" "")))
835     (clobber (reg:CC CC_REGNUM))])]
836   "TARGET_EITHER"
837   "
838   if (TARGET_HARD_FLOAT && TARGET_MAVERICK
839       && TARGET_ARM
840       && cirrus_fp_register (operands[0], DImode)
841       && cirrus_fp_register (operands[1], DImode))
842     {
843       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
844       DONE;
845     }
846
847   if (TARGET_THUMB)
848     {
849       if (GET_CODE (operands[1]) != REG)
850         operands[1] = force_reg (SImode, operands[1]);
851       if (GET_CODE (operands[2]) != REG)
852         operands[2] = force_reg (SImode, operands[2]);
853      }  
854   "
855 )
856
857 (define_insn "*arm_subdi3"
858   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
859         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
860                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
861    (clobber (reg:CC CC_REGNUM))]
862   "TARGET_ARM"
863   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
864   [(set_attr "conds" "clob")
865    (set_attr "length" "8")]
866 )
867
868 (define_insn "*thumb_subdi3"
869   [(set (match_operand:DI           0 "register_operand" "=l")
870         (minus:DI (match_operand:DI 1 "register_operand"  "0")
871                   (match_operand:DI 2 "register_operand"  "l")))
872    (clobber (reg:CC CC_REGNUM))]
873   "TARGET_THUMB"
874   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
875   [(set_attr "length" "4")]
876 )
877
878 (define_insn "*subdi_di_zesidi"
879   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
880         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
881                   (zero_extend:DI
882                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
883    (clobber (reg:CC CC_REGNUM))]
884   "TARGET_ARM"
885   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
886   [(set_attr "conds" "clob")
887    (set_attr "length" "8")]
888 )
889
890 (define_insn "*subdi_di_sesidi"
891   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
892         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
893                   (sign_extend:DI
894                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
895    (clobber (reg:CC CC_REGNUM))]
896   "TARGET_ARM"
897   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
898   [(set_attr "conds" "clob")
899    (set_attr "length" "8")]
900 )
901
902 (define_insn "*subdi_zesidi_di"
903   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
904         (minus:DI (zero_extend:DI
905                    (match_operand:SI 2 "s_register_operand"  "r,r"))
906                   (match_operand:DI  1 "s_register_operand" "?r,0")))
907    (clobber (reg:CC CC_REGNUM))]
908   "TARGET_ARM"
909   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
910   [(set_attr "conds" "clob")
911    (set_attr "length" "8")]
912 )
913
914 (define_insn "*subdi_sesidi_di"
915   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
916         (minus:DI (sign_extend:DI
917                    (match_operand:SI 2 "s_register_operand"   "r,r"))
918                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
919    (clobber (reg:CC CC_REGNUM))]
920   "TARGET_ARM"
921   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
922   [(set_attr "conds" "clob")
923    (set_attr "length" "8")]
924 )
925
926 (define_insn "*subdi_zesidi_zesidi"
927   [(set (match_operand:DI            0 "s_register_operand" "=r")
928         (minus:DI (zero_extend:DI
929                    (match_operand:SI 1 "s_register_operand"  "r"))
930                   (zero_extend:DI
931                    (match_operand:SI 2 "s_register_operand"  "r"))))
932    (clobber (reg:CC CC_REGNUM))]
933   "TARGET_ARM"
934   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
935   [(set_attr "conds" "clob")
936    (set_attr "length" "8")]
937 )
938
939 (define_expand "subsi3"
940   [(set (match_operand:SI           0 "s_register_operand" "")
941         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
942                   (match_operand:SI 2 "s_register_operand" "")))]
943   "TARGET_EITHER"
944   "
945   if (GET_CODE (operands[1]) == CONST_INT)
946     {
947       if (TARGET_ARM)
948         {
949           arm_split_constant (MINUS, SImode, NULL_RTX,
950                               INTVAL (operands[1]), operands[0],
951                               operands[2], optimize && !no_new_pseudos);
952           DONE;
953         }
954       else /* TARGET_THUMB */
955         operands[1] = force_reg (SImode, operands[1]);
956     }
957   "
958 )
959
960 (define_insn "*thumb_subsi3_insn"
961   [(set (match_operand:SI           0 "register_operand" "=l")
962         (minus:SI (match_operand:SI 1 "register_operand" "l")
963                   (match_operand:SI 2 "register_operand" "l")))]
964   "TARGET_THUMB"
965   "sub\\t%0, %1, %2"
966   [(set_attr "length" "2")]
967 )
968
969 (define_insn_and_split "*arm_subsi3_insn"
970   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
971         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
972                   (match_operand:SI 2 "s_register_operand" "r,r")))]
973   "TARGET_ARM"
974   "@
975    rsb%?\\t%0, %2, %1
976    #"
977   "TARGET_ARM
978    && GET_CODE (operands[1]) == CONST_INT
979    && !const_ok_for_arm (INTVAL (operands[1]))"
980   [(clobber (const_int 0))]
981   "
982   arm_split_constant (MINUS, SImode, curr_insn,
983                       INTVAL (operands[1]), operands[0], operands[2], 0);
984   DONE;
985   "
986   [(set_attr "length" "4,16")
987    (set_attr "predicable" "yes")]
988 )
989
990 (define_peephole2
991   [(match_scratch:SI 3 "r")
992    (set (match_operand:SI 0 "arm_general_register_operand" "")
993         (minus:SI (match_operand:SI 1 "const_int_operand" "")
994                   (match_operand:SI 2 "arm_general_register_operand" "")))]
995   "TARGET_ARM
996    && !const_ok_for_arm (INTVAL (operands[1]))
997    && const_ok_for_arm (~INTVAL (operands[1]))"
998   [(set (match_dup 3) (match_dup 1))
999    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1000   ""
1001 )
1002
1003 (define_insn "*subsi3_compare0"
1004   [(set (reg:CC_NOOV CC_REGNUM)
1005         (compare:CC_NOOV
1006          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1007                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1008          (const_int 0)))
1009    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1010         (minus:SI (match_dup 1) (match_dup 2)))]
1011   "TARGET_ARM"
1012   "@
1013    sub%?s\\t%0, %1, %2
1014    rsb%?s\\t%0, %2, %1"
1015   [(set_attr "conds" "set")]
1016 )
1017
1018 (define_insn "decscc"
1019   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1020         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1021                   (match_operator:SI 2 "arm_comparison_operator"
1022                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1023   "TARGET_ARM"
1024   "@
1025    sub%d2\\t%0, %1, #1
1026    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1027   [(set_attr "conds" "use")
1028    (set_attr "length" "*,8")]
1029 )
1030
1031 (define_expand "subsf3"
1032   [(set (match_operand:SF           0 "s_register_operand" "")
1033         (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1034                   (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1035   "TARGET_ARM && TARGET_HARD_FLOAT"
1036   "
1037   if (TARGET_MAVERICK)
1038     {
1039       if (!cirrus_fp_register (operands[1], SFmode))
1040         operands[1] = force_reg (SFmode, operands[1]);
1041       if (!cirrus_fp_register (operands[2], SFmode))
1042         operands[2] = force_reg (SFmode, operands[2]);
1043     }
1044 ")
1045
1046 (define_expand "subdf3"
1047   [(set (match_operand:DF           0 "s_register_operand" "")
1048         (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1049                   (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1050   "TARGET_ARM && TARGET_HARD_FLOAT"
1051   "
1052   if (TARGET_MAVERICK)
1053     {
1054        if (!cirrus_fp_register (operands[1], DFmode))
1055          operands[1] = force_reg (DFmode, operands[1]);
1056        if (!cirrus_fp_register (operands[2], DFmode))
1057          operands[2] = force_reg (DFmode, operands[2]);
1058     }
1059 ")
1060
1061 \f
1062 ;; Multiplication insns
1063
1064 (define_expand "mulsi3"
1065   [(set (match_operand:SI          0 "s_register_operand" "")
1066         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1067                  (match_operand:SI 1 "s_register_operand" "")))]
1068   "TARGET_EITHER"
1069   ""
1070 )
1071
1072 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1073 (define_insn "*arm_mulsi3"
1074   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1075         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1076                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1077   "TARGET_ARM"
1078   "mul%?\\t%0, %2, %1"
1079   [(set_attr "insn" "mul")
1080    (set_attr "predicable" "yes")]
1081 )
1082
1083 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1084 ; 1 and 2; are the same, because reload will make operand 0 match 
1085 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1086 ; this by adding another alternative to match this case, and then `reload' 
1087 ; it ourselves.  This alternative must come first.
1088 (define_insn "*thumb_mulsi3"
1089   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1090         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1091                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1092   "TARGET_THUMB"
1093   "*
1094   if (which_alternative < 2)
1095     return \"mov\\t%0, %1\;mul\\t%0, %2\";
1096   else
1097     return \"mul\\t%0, %2\";
1098   "
1099   [(set_attr "length" "4,4,2")
1100    (set_attr "insn" "mul")]
1101 )
1102
1103 (define_insn "*mulsi3_compare0"
1104   [(set (reg:CC_NOOV CC_REGNUM)
1105         (compare:CC_NOOV (mult:SI
1106                           (match_operand:SI 2 "s_register_operand" "r,r")
1107                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1108                          (const_int 0)))
1109    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1110         (mult:SI (match_dup 2) (match_dup 1)))]
1111   "TARGET_ARM"
1112   "mul%?s\\t%0, %2, %1"
1113   [(set_attr "conds" "set")
1114    (set_attr "insn" "muls")]
1115 )
1116
1117 (define_insn "*mulsi_compare0_scratch"
1118   [(set (reg:CC_NOOV CC_REGNUM)
1119         (compare:CC_NOOV (mult:SI
1120                           (match_operand:SI 2 "s_register_operand" "r,r")
1121                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1122                          (const_int 0)))
1123    (clobber (match_scratch:SI 0 "=&r,&r"))]
1124   "TARGET_ARM"
1125   "mul%?s\\t%0, %2, %1"
1126   [(set_attr "conds" "set")
1127    (set_attr "insn" "muls")]
1128 )
1129
1130 ;; Unnamed templates to match MLA instruction.
1131
1132 (define_insn "*mulsi3addsi"
1133   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1134         (plus:SI
1135           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1136                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1137           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1138   "TARGET_ARM"
1139   "mla%?\\t%0, %2, %1, %3"
1140   [(set_attr "insn" "mla")
1141    (set_attr "predicable" "yes")]
1142 )
1143
1144 (define_insn "*mulsi3addsi_compare0"
1145   [(set (reg:CC_NOOV CC_REGNUM)
1146         (compare:CC_NOOV
1147          (plus:SI (mult:SI
1148                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1149                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1150                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1151          (const_int 0)))
1152    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1153         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1154                  (match_dup 3)))]
1155   "TARGET_ARM"
1156   "mla%?s\\t%0, %2, %1, %3"
1157   [(set_attr "conds" "set")
1158    (set_attr "insn" "mlas")]
1159 )
1160
1161 (define_insn "*mulsi3addsi_compare0_scratch"
1162   [(set (reg:CC_NOOV CC_REGNUM)
1163         (compare:CC_NOOV
1164          (plus:SI (mult:SI
1165                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1166                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1167                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1168          (const_int 0)))
1169    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1170   "TARGET_ARM"
1171   "mla%?s\\t%0, %2, %1, %3"
1172   [(set_attr "conds" "set")
1173    (set_attr "insn" "mlas")]
1174 )
1175
1176 ;; Unnamed template to match long long multiply-accumulate (smlal)
1177
1178 (define_insn "*mulsidi3adddi"
1179   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1180         (plus:DI
1181          (mult:DI
1182           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1183           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1184          (match_operand:DI 1 "s_register_operand" "0")))]
1185   "TARGET_ARM && arm_arch3m"
1186   "smlal%?\\t%Q0, %R0, %3, %2"
1187   [(set_attr "insn" "smlal")
1188    (set_attr "predicable" "yes")]
1189 )
1190
1191 (define_insn "mulsidi3"
1192   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1193         (mult:DI
1194          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1195          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1196   "TARGET_ARM && arm_arch3m"
1197   "smull%?\\t%Q0, %R0, %1, %2"
1198   [(set_attr "insn" "smull")
1199    (set_attr "predicable" "yes")]
1200 )
1201
1202 (define_insn "umulsidi3"
1203   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1204         (mult:DI
1205          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1206          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1207   "TARGET_ARM && arm_arch3m"
1208   "umull%?\\t%Q0, %R0, %1, %2"
1209   [(set_attr "insn" "umull")
1210    (set_attr "predicable" "yes")]
1211 )
1212
1213 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1214
1215 (define_insn "*umulsidi3adddi"
1216   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1217         (plus:DI
1218          (mult:DI
1219           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1220           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1221          (match_operand:DI 1 "s_register_operand" "0")))]
1222   "TARGET_ARM && arm_arch3m"
1223   "umlal%?\\t%Q0, %R0, %3, %2"
1224   [(set_attr "insn" "umlal")
1225    (set_attr "predicable" "yes")]
1226 )
1227
1228 (define_insn "smulsi3_highpart"
1229   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1230         (truncate:SI
1231          (lshiftrt:DI
1232           (mult:DI
1233            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1234            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1235           (const_int 32))))
1236    (clobber (match_scratch:SI 3 "=&r,&r"))]
1237   "TARGET_ARM && arm_arch3m"
1238   "smull%?\\t%3, %0, %2, %1"
1239   [(set_attr "insn" "smull")
1240    (set_attr "predicable" "yes")]
1241 )
1242
1243 (define_insn "umulsi3_highpart"
1244   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1245         (truncate:SI
1246          (lshiftrt:DI
1247           (mult:DI
1248            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1249            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1250           (const_int 32))))
1251    (clobber (match_scratch:SI 3 "=&r,&r"))]
1252   "TARGET_ARM && arm_arch3m"
1253   "umull%?\\t%3, %0, %2, %1"
1254   [(set_attr "insn" "umull")
1255    (set_attr "predicable" "yes")]
1256 )
1257
1258 (define_insn "mulhisi3"
1259   [(set (match_operand:SI 0 "s_register_operand" "=r")
1260         (mult:SI (sign_extend:SI
1261                   (match_operand:HI 1 "s_register_operand" "%r"))
1262                  (sign_extend:SI
1263                   (match_operand:HI 2 "s_register_operand" "r"))))]
1264   "TARGET_ARM && arm_arch5e"
1265   "smulbb%?\\t%0, %1, %2"
1266   [(set_attr "insn" "smulxy")
1267    (set_attr "predicable" "yes")]
1268 )
1269
1270 (define_insn "*mulhisi3tb"
1271   [(set (match_operand:SI 0 "s_register_operand" "=r")
1272         (mult:SI (ashiftrt:SI
1273                   (match_operand:SI 1 "s_register_operand" "r")
1274                   (const_int 16))
1275                  (sign_extend:SI
1276                   (match_operand:HI 2 "s_register_operand" "r"))))]
1277   "TARGET_ARM && arm_arch5e"
1278   "smultb%?\\t%0, %1, %2"
1279   [(set_attr "insn" "smulxy")
1280    (set_attr "predicable" "yes")]
1281 )
1282
1283 (define_insn "*mulhisi3bt"
1284   [(set (match_operand:SI 0 "s_register_operand" "=r")
1285         (mult:SI (sign_extend:SI
1286                   (match_operand:HI 1 "s_register_operand" "r"))
1287                  (ashiftrt:SI
1288                   (match_operand:SI 2 "s_register_operand" "r")
1289                   (const_int 16))))]
1290   "TARGET_ARM && arm_arch5e"
1291   "smulbt%?\\t%0, %1, %2"
1292   [(set_attr "insn" "smulxy")
1293    (set_attr "predicable" "yes")]
1294 )
1295
1296 (define_insn "*mulhisi3tt"
1297   [(set (match_operand:SI 0 "s_register_operand" "=r")
1298         (mult:SI (ashiftrt:SI
1299                   (match_operand:SI 1 "s_register_operand" "r")
1300                   (const_int 16))
1301                  (ashiftrt:SI
1302                   (match_operand:SI 2 "s_register_operand" "r")
1303                   (const_int 16))))]
1304   "TARGET_ARM && arm_arch5e"
1305   "smultt%?\\t%0, %1, %2"
1306   [(set_attr "insn" "smulxy")
1307    (set_attr "predicable" "yes")]
1308 )
1309
1310 (define_insn "*mulhisi3addsi"
1311   [(set (match_operand:SI 0 "s_register_operand" "=r")
1312         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1313                  (mult:SI (sign_extend:SI
1314                            (match_operand:HI 2 "s_register_operand" "%r"))
1315                           (sign_extend:SI
1316                            (match_operand:HI 3 "s_register_operand" "r")))))]
1317   "TARGET_ARM && arm_arch5e"
1318   "smlabb%?\\t%0, %2, %3, %1"
1319   [(set_attr "insn" "smlaxy")
1320    (set_attr "predicable" "yes")]
1321 )
1322
1323 (define_insn "*mulhidi3adddi"
1324   [(set (match_operand:DI 0 "s_register_operand" "=r")
1325         (plus:DI
1326           (match_operand:DI 1 "s_register_operand" "0")
1327           (mult:DI (sign_extend:DI
1328                     (match_operand:HI 2 "s_register_operand" "%r"))
1329                    (sign_extend:DI
1330                     (match_operand:HI 3 "s_register_operand" "r")))))]
1331   "TARGET_ARM && arm_arch5e"
1332   "smlalbb%?\\t%Q0, %R0, %2, %3"
1333   [(set_attr "insn" "smlalxy")
1334    (set_attr "predicable" "yes")])
1335
1336 (define_expand "mulsf3"
1337   [(set (match_operand:SF          0 "s_register_operand" "")
1338         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1339                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1340   "TARGET_ARM && TARGET_HARD_FLOAT"
1341   "
1342   if (TARGET_MAVERICK
1343       && !cirrus_fp_register (operands[2], SFmode))
1344     operands[2] = force_reg (SFmode, operands[2]);
1345 ")
1346
1347 (define_expand "muldf3"
1348   [(set (match_operand:DF          0 "s_register_operand" "")
1349         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1350                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1351   "TARGET_ARM && TARGET_HARD_FLOAT"
1352   "
1353   if (TARGET_MAVERICK
1354       && !cirrus_fp_register (operands[2], DFmode))
1355     operands[2] = force_reg (DFmode, operands[2]);
1356 ")
1357 \f
1358 ;; Division insns
1359
1360 (define_expand "divsf3"
1361   [(set (match_operand:SF 0 "s_register_operand" "")
1362         (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1363                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1364   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1365   "")
1366
1367 (define_expand "divdf3"
1368   [(set (match_operand:DF 0 "s_register_operand" "")
1369         (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1370                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1371   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1372   "")
1373 \f
1374 ;; Modulo insns
1375
1376 (define_expand "modsf3"
1377   [(set (match_operand:SF 0 "s_register_operand" "")
1378         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1379                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1380   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1381   "")
1382
1383 (define_expand "moddf3"
1384   [(set (match_operand:DF 0 "s_register_operand" "")
1385         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1386                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1387   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1388   "")
1389 \f
1390 ;; Boolean and,ior,xor insns
1391
1392 ;; Split up double word logical operations
1393
1394 ;; Split up simple DImode logical operations.  Simply perform the logical
1395 ;; operation on the upper and lower halves of the registers.
1396 (define_split
1397   [(set (match_operand:DI 0 "s_register_operand" "")
1398         (match_operator:DI 6 "logical_binary_operator"
1399           [(match_operand:DI 1 "s_register_operand" "")
1400            (match_operand:DI 2 "s_register_operand" "")]))]
1401   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1402   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1403    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1404   "
1405   {
1406     operands[3] = gen_highpart (SImode, operands[0]);
1407     operands[0] = gen_lowpart (SImode, operands[0]);
1408     operands[4] = gen_highpart (SImode, operands[1]);
1409     operands[1] = gen_lowpart (SImode, operands[1]);
1410     operands[5] = gen_highpart (SImode, operands[2]);
1411     operands[2] = gen_lowpart (SImode, operands[2]);
1412   }"
1413 )
1414
1415 (define_split
1416   [(set (match_operand:DI 0 "s_register_operand" "")
1417         (match_operator:DI 6 "logical_binary_operator"
1418           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1419            (match_operand:DI 1 "s_register_operand" "")]))]
1420   "TARGET_ARM && reload_completed"
1421   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1422    (set (match_dup 3) (match_op_dup:SI 6
1423                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1424                          (match_dup 4)]))]
1425   "
1426   {
1427     operands[3] = gen_highpart (SImode, operands[0]);
1428     operands[0] = gen_lowpart (SImode, operands[0]);
1429     operands[4] = gen_highpart (SImode, operands[1]);
1430     operands[1] = gen_lowpart (SImode, operands[1]);
1431     operands[5] = gen_highpart (SImode, operands[2]);
1432     operands[2] = gen_lowpart (SImode, operands[2]);
1433   }"
1434 )
1435
1436 ;; The zero extend of operand 2 means we can just copy the high part of
1437 ;; operand1 into operand0.
1438 (define_split
1439   [(set (match_operand:DI 0 "s_register_operand" "")
1440         (ior:DI
1441           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1442           (match_operand:DI 1 "s_register_operand" "")))]
1443   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1444   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1445    (set (match_dup 3) (match_dup 4))]
1446   "
1447   {
1448     operands[4] = gen_highpart (SImode, operands[1]);
1449     operands[3] = gen_highpart (SImode, operands[0]);
1450     operands[0] = gen_lowpart (SImode, operands[0]);
1451     operands[1] = gen_lowpart (SImode, operands[1]);
1452   }"
1453 )
1454
1455 ;; The zero extend of operand 2 means we can just copy the high part of
1456 ;; operand1 into operand0.
1457 (define_split
1458   [(set (match_operand:DI 0 "s_register_operand" "")
1459         (xor:DI
1460           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1461           (match_operand:DI 1 "s_register_operand" "")))]
1462   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1463   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1464    (set (match_dup 3) (match_dup 4))]
1465   "
1466   {
1467     operands[4] = gen_highpart (SImode, operands[1]);
1468     operands[3] = gen_highpart (SImode, operands[0]);
1469     operands[0] = gen_lowpart (SImode, operands[0]);
1470     operands[1] = gen_lowpart (SImode, operands[1]);
1471   }"
1472 )
1473
1474 (define_insn "anddi3"
1475   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1476         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1477                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1478   "TARGET_ARM && ! TARGET_IWMMXT"
1479   "#"
1480   [(set_attr "length" "8")]
1481 )
1482
1483 (define_insn_and_split "*anddi_zesidi_di"
1484   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1485         (and:DI (zero_extend:DI
1486                  (match_operand:SI 2 "s_register_operand" "r,r"))
1487                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1488   "TARGET_ARM"
1489   "#"
1490   "TARGET_ARM && reload_completed"
1491   ; The zero extend of operand 2 clears the high word of the output
1492   ; operand.
1493   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1494    (set (match_dup 3) (const_int 0))]
1495   "
1496   {
1497     operands[3] = gen_highpart (SImode, operands[0]);
1498     operands[0] = gen_lowpart (SImode, operands[0]);
1499     operands[1] = gen_lowpart (SImode, operands[1]);
1500   }"
1501   [(set_attr "length" "8")]
1502 )
1503
1504 (define_insn "*anddi_sesdi_di"
1505   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1506         (and:DI (sign_extend:DI
1507                  (match_operand:SI 2 "s_register_operand" "r,r"))
1508                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1509   "TARGET_ARM"
1510   "#"
1511   [(set_attr "length" "8")]
1512 )
1513
1514 (define_expand "andsi3"
1515   [(set (match_operand:SI         0 "s_register_operand" "")
1516         (and:SI (match_operand:SI 1 "s_register_operand" "")
1517                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1518   "TARGET_EITHER"
1519   "
1520   if (TARGET_ARM)
1521     {
1522       if (GET_CODE (operands[2]) == CONST_INT)
1523         {
1524           arm_split_constant (AND, SImode, NULL_RTX,
1525                               INTVAL (operands[2]), operands[0],
1526                               operands[1], optimize && !no_new_pseudos);
1527
1528           DONE;
1529         }
1530     }
1531   else /* TARGET_THUMB */
1532     {
1533       if (GET_CODE (operands[2]) != CONST_INT)
1534         operands[2] = force_reg (SImode, operands[2]);
1535       else
1536         {
1537           int i;
1538           
1539           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1540             {
1541               operands[2] = force_reg (SImode,
1542                                        GEN_INT (~INTVAL (operands[2])));
1543               
1544               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1545               
1546               DONE;
1547             }
1548
1549           for (i = 9; i <= 31; i++)
1550             {
1551               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1552                 {
1553                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1554                                         const0_rtx));
1555                   DONE;
1556                 }
1557               else if ((((HOST_WIDE_INT) 1) << i) - 1
1558                        == ~INTVAL (operands[2]))
1559                 {
1560                   rtx shift = GEN_INT (i);
1561                   rtx reg = gen_reg_rtx (SImode);
1562                 
1563                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1564                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1565                   
1566                   DONE;
1567                 }
1568             }
1569
1570           operands[2] = force_reg (SImode, operands[2]);
1571         }
1572     }
1573   "
1574 )
1575
1576 (define_insn_and_split "*arm_andsi3_insn"
1577   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1578         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1579                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1580   "TARGET_ARM"
1581   "@
1582    and%?\\t%0, %1, %2
1583    bic%?\\t%0, %1, #%B2
1584    #"
1585   "TARGET_ARM
1586    && GET_CODE (operands[2]) == CONST_INT
1587    && !(const_ok_for_arm (INTVAL (operands[2]))
1588         || const_ok_for_arm (~INTVAL (operands[2])))"
1589   [(clobber (const_int 0))]
1590   "
1591   arm_split_constant  (AND, SImode, curr_insn, 
1592                        INTVAL (operands[2]), operands[0], operands[1], 0);
1593   DONE;
1594   "
1595   [(set_attr "length" "4,4,16")
1596    (set_attr "predicable" "yes")]
1597 )
1598
1599 (define_insn "*thumb_andsi3_insn"
1600   [(set (match_operand:SI         0 "register_operand" "=l")
1601         (and:SI (match_operand:SI 1 "register_operand" "%0")
1602                 (match_operand:SI 2 "register_operand" "l")))]
1603   "TARGET_THUMB"
1604   "and\\t%0, %0, %2"
1605   [(set_attr "length" "2")]
1606 )
1607
1608 (define_insn "*andsi3_compare0"
1609   [(set (reg:CC_NOOV CC_REGNUM)
1610         (compare:CC_NOOV
1611          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1612                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1613          (const_int 0)))
1614    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1615         (and:SI (match_dup 1) (match_dup 2)))]
1616   "TARGET_ARM"
1617   "@
1618    and%?s\\t%0, %1, %2
1619    bic%?s\\t%0, %1, #%B2"
1620   [(set_attr "conds" "set")]
1621 )
1622
1623 (define_insn "*andsi3_compare0_scratch"
1624   [(set (reg:CC_NOOV CC_REGNUM)
1625         (compare:CC_NOOV
1626          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1627                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1628          (const_int 0)))
1629    (clobber (match_scratch:SI 2 "=X,r"))]
1630   "TARGET_ARM"
1631   "@
1632    tst%?\\t%0, %1
1633    bic%?s\\t%2, %0, #%B1"
1634   [(set_attr "conds" "set")]
1635 )
1636
1637 (define_insn "*zeroextractsi_compare0_scratch"
1638   [(set (reg:CC_NOOV CC_REGNUM)
1639         (compare:CC_NOOV (zero_extract:SI
1640                           (match_operand:SI 0 "s_register_operand" "r")
1641                           (match_operand 1 "const_int_operand" "n")
1642                           (match_operand 2 "const_int_operand" "n"))
1643                          (const_int 0)))]
1644   "TARGET_ARM
1645   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1646       && INTVAL (operands[1]) > 0 
1647       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1648       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1649   "*
1650   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1651                          << INTVAL (operands[2]));
1652   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1653   return \"\";
1654   "
1655   [(set_attr "conds" "set")]
1656 )
1657
1658 (define_insn_and_split "*ne_zeroextractsi"
1659   [(set (match_operand:SI 0 "s_register_operand" "=r")
1660         (ne:SI (zero_extract:SI
1661                 (match_operand:SI 1 "s_register_operand" "r")
1662                 (match_operand:SI 2 "const_int_operand" "n")
1663                 (match_operand:SI 3 "const_int_operand" "n"))
1664                (const_int 0)))
1665    (clobber (reg:CC CC_REGNUM))]
1666   "TARGET_ARM
1667    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1668        && INTVAL (operands[2]) > 0 
1669        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1670        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1671   "#"
1672   "TARGET_ARM
1673    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1674        && INTVAL (operands[2]) > 0 
1675        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1676        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1677   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1678                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1679                                     (const_int 0)))
1680               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1681    (set (match_dup 0)
1682         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1683                          (match_dup 0) (const_int 1)))]
1684   "
1685   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1686                          << INTVAL (operands[3])); 
1687   "
1688   [(set_attr "conds" "clob")
1689    (set_attr "length" "8")]
1690 )
1691
1692 (define_insn_and_split "*ne_zeroextractsi_shifted"
1693   [(set (match_operand:SI 0 "s_register_operand" "=r")
1694         (ne:SI (zero_extract:SI
1695                 (match_operand:SI 1 "s_register_operand" "r")
1696                 (match_operand:SI 2 "const_int_operand" "n")
1697                 (const_int 0))
1698                (const_int 0)))
1699    (clobber (reg:CC CC_REGNUM))]
1700   "TARGET_ARM"
1701   "#"
1702   "TARGET_ARM"
1703   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1704                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1705                                     (const_int 0)))
1706               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1707    (set (match_dup 0)
1708         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1709                          (match_dup 0) (const_int 1)))]
1710   "
1711   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1712   "
1713   [(set_attr "conds" "clob")
1714    (set_attr "length" "8")]
1715 )
1716
1717 (define_insn_and_split "*ite_ne_zeroextractsi"
1718   [(set (match_operand:SI 0 "s_register_operand" "=r")
1719         (if_then_else:SI (ne (zero_extract:SI
1720                               (match_operand:SI 1 "s_register_operand" "r")
1721                               (match_operand:SI 2 "const_int_operand" "n")
1722                               (match_operand:SI 3 "const_int_operand" "n"))
1723                              (const_int 0))
1724                          (match_operand:SI 4 "arm_not_operand" "rIK")
1725                          (const_int 0)))
1726    (clobber (reg:CC CC_REGNUM))]
1727   "TARGET_ARM
1728    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1729        && INTVAL (operands[2]) > 0 
1730        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1731        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1732    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1733   "#"
1734   "TARGET_ARM
1735    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1736        && INTVAL (operands[2]) > 0 
1737        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1738        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1739    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1740   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1741                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1742                                     (const_int 0)))
1743               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1744    (set (match_dup 0)
1745         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1746                          (match_dup 0) (match_dup 4)))]
1747   "
1748   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1749                          << INTVAL (operands[3])); 
1750   "
1751   [(set_attr "conds" "clob")
1752    (set_attr "length" "8")]
1753 )
1754
1755 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1756   [(set (match_operand:SI 0 "s_register_operand" "=r")
1757         (if_then_else:SI (ne (zero_extract:SI
1758                               (match_operand:SI 1 "s_register_operand" "r")
1759                               (match_operand:SI 2 "const_int_operand" "n")
1760                               (const_int 0))
1761                              (const_int 0))
1762                          (match_operand:SI 3 "arm_not_operand" "rIK")
1763                          (const_int 0)))
1764    (clobber (reg:CC CC_REGNUM))]
1765   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1766   "#"
1767   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1768   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1769                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1770                                     (const_int 0)))
1771               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1772    (set (match_dup 0)
1773         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1774                          (match_dup 0) (match_dup 3)))]
1775   "
1776   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1777   "
1778   [(set_attr "conds" "clob")
1779    (set_attr "length" "8")]
1780 )
1781
1782 (define_split
1783   [(set (match_operand:SI 0 "s_register_operand" "")
1784         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1785                          (match_operand:SI 2 "const_int_operand" "")
1786                          (match_operand:SI 3 "const_int_operand" "")))
1787    (clobber (match_operand:SI 4 "s_register_operand" ""))]
1788   "TARGET_THUMB"
1789   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1790    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1791   "{
1792      HOST_WIDE_INT temp = INTVAL (operands[2]);
1793
1794      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1795      operands[3] = GEN_INT (32 - temp);
1796    }"
1797 )
1798
1799 (define_split
1800   [(set (match_operand:SI 0 "s_register_operand" "")
1801         (match_operator:SI 1 "shiftable_operator"
1802          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1803                            (match_operand:SI 3 "const_int_operand" "")
1804                            (match_operand:SI 4 "const_int_operand" ""))
1805           (match_operand:SI 5 "s_register_operand" "")]))
1806    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1807   "TARGET_ARM"
1808   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1809    (set (match_dup 0)
1810         (match_op_dup 1
1811          [(lshiftrt:SI (match_dup 6) (match_dup 4))
1812           (match_dup 5)]))]
1813   "{
1814      HOST_WIDE_INT temp = INTVAL (operands[3]);
1815
1816      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1817      operands[4] = GEN_INT (32 - temp);
1818    }"
1819 )
1820   
1821 (define_split
1822   [(set (match_operand:SI 0 "s_register_operand" "")
1823         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1824                          (match_operand:SI 2 "const_int_operand" "")
1825                          (match_operand:SI 3 "const_int_operand" "")))]
1826   "TARGET_THUMB"
1827   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1828    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1829   "{
1830      HOST_WIDE_INT temp = INTVAL (operands[2]);
1831
1832      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1833      operands[3] = GEN_INT (32 - temp);
1834    }"
1835 )
1836
1837 (define_split
1838   [(set (match_operand:SI 0 "s_register_operand" "")
1839         (match_operator:SI 1 "shiftable_operator"
1840          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1841                            (match_operand:SI 3 "const_int_operand" "")
1842                            (match_operand:SI 4 "const_int_operand" ""))
1843           (match_operand:SI 5 "s_register_operand" "")]))
1844    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1845   "TARGET_ARM"
1846   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1847    (set (match_dup 0)
1848         (match_op_dup 1
1849          [(ashiftrt:SI (match_dup 6) (match_dup 4))
1850           (match_dup 5)]))]
1851   "{
1852      HOST_WIDE_INT temp = INTVAL (operands[3]);
1853
1854      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1855      operands[4] = GEN_INT (32 - temp);
1856    }"
1857 )
1858   
1859 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1860 ;;; represented by the bitfield, then this will produce incorrect results.
1861 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1862 ;;; which have a real bit-field insert instruction, the truncation happens
1863 ;;; in the bit-field insert instruction itself.  Since arm does not have a
1864 ;;; bit-field insert instruction, we would have to emit code here to truncate
1865 ;;; the value before we insert.  This loses some of the advantage of having
1866 ;;; this insv pattern, so this pattern needs to be reevalutated.
1867
1868 (define_expand "insv"
1869   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1870                          (match_operand:SI 1 "general_operand" "")
1871                          (match_operand:SI 2 "general_operand" ""))
1872         (match_operand:SI 3 "reg_or_int_operand" ""))]
1873   "TARGET_ARM"
1874   "
1875   {
1876     int start_bit = INTVAL (operands[2]);
1877     int width = INTVAL (operands[1]);
1878     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1879     rtx target, subtarget;
1880
1881     target = operands[0];
1882     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1883        subreg as the final target.  */
1884     if (GET_CODE (target) == SUBREG)
1885       {
1886         subtarget = gen_reg_rtx (SImode);
1887         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1888             < GET_MODE_SIZE (SImode))
1889           target = SUBREG_REG (target);
1890       }
1891     else
1892       subtarget = target;    
1893
1894     if (GET_CODE (operands[3]) == CONST_INT)
1895       {
1896         /* Since we are inserting a known constant, we may be able to
1897            reduce the number of bits that we have to clear so that
1898            the mask becomes simple.  */
1899         /* ??? This code does not check to see if the new mask is actually
1900            simpler.  It may not be.  */
1901         rtx op1 = gen_reg_rtx (SImode);
1902         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1903            start of this pattern.  */
1904         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1905         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1906
1907         emit_insn (gen_andsi3 (op1, operands[0],
1908                                gen_int_mode (~mask2, SImode)));
1909         emit_insn (gen_iorsi3 (subtarget, op1,
1910                                gen_int_mode (op3_value << start_bit, SImode)));
1911       }
1912     else if (start_bit == 0
1913              && !(const_ok_for_arm (mask)
1914                   || const_ok_for_arm (~mask)))
1915       {
1916         /* A Trick, since we are setting the bottom bits in the word,
1917            we can shift operand[3] up, operand[0] down, OR them together
1918            and rotate the result back again.  This takes 3 insns, and
1919            the third might be mergeable into another op.  */
1920         /* The shift up copes with the possibility that operand[3] is
1921            wider than the bitfield.  */
1922         rtx op0 = gen_reg_rtx (SImode);
1923         rtx op1 = gen_reg_rtx (SImode);
1924
1925         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1926         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1927         emit_insn (gen_iorsi3  (op1, op1, op0));
1928         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1929       }
1930     else if ((width + start_bit == 32)
1931              && !(const_ok_for_arm (mask)
1932                   || const_ok_for_arm (~mask)))
1933       {
1934         /* Similar trick, but slightly less efficient.  */
1935
1936         rtx op0 = gen_reg_rtx (SImode);
1937         rtx op1 = gen_reg_rtx (SImode);
1938
1939         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1940         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1941         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1942         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1943       }
1944     else
1945       {
1946         rtx op0 = gen_int_mode (mask, SImode);
1947         rtx op1 = gen_reg_rtx (SImode);
1948         rtx op2 = gen_reg_rtx (SImode);
1949
1950         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1951           {
1952             rtx tmp = gen_reg_rtx (SImode);
1953
1954             emit_insn (gen_movsi (tmp, op0));
1955             op0 = tmp;
1956           }
1957
1958         /* Mask out any bits in operand[3] that are not needed.  */
1959            emit_insn (gen_andsi3 (op1, operands[3], op0));
1960
1961         if (GET_CODE (op0) == CONST_INT
1962             && (const_ok_for_arm (mask << start_bit)
1963                 || const_ok_for_arm (~(mask << start_bit))))
1964           {
1965             op0 = gen_int_mode (~(mask << start_bit), SImode);
1966             emit_insn (gen_andsi3 (op2, operands[0], op0));
1967           }
1968         else
1969           {
1970             if (GET_CODE (op0) == CONST_INT)
1971               {
1972                 rtx tmp = gen_reg_rtx (SImode);
1973
1974                 emit_insn (gen_movsi (tmp, op0));
1975                 op0 = tmp;
1976               }
1977
1978             if (start_bit != 0)
1979               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1980             
1981             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1982           }
1983
1984         if (start_bit != 0)
1985           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1986
1987         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1988       }
1989
1990     if (subtarget != target)
1991       {
1992         /* If TARGET is still a SUBREG, then it must be wider than a word,
1993            so we must be careful only to set the subword we were asked to.  */
1994         if (GET_CODE (target) == SUBREG)
1995           emit_move_insn (target, subtarget);
1996         else
1997           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1998       }
1999
2000     DONE;
2001   }"
2002 )
2003
2004 ; constants for op 2 will never be given to these patterns.
2005 (define_insn_and_split "*anddi_notdi_di"
2006   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2007         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2008                 (match_operand:DI 2 "s_register_operand" "0,r")))]
2009   "TARGET_ARM"
2010   "#"
2011   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2012   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2013    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2014   "
2015   {
2016     operands[3] = gen_highpart (SImode, operands[0]);
2017     operands[0] = gen_lowpart (SImode, operands[0]);
2018     operands[4] = gen_highpart (SImode, operands[1]);
2019     operands[1] = gen_lowpart (SImode, operands[1]);
2020     operands[5] = gen_highpart (SImode, operands[2]);
2021     operands[2] = gen_lowpart (SImode, operands[2]);
2022   }"
2023   [(set_attr "length" "8")
2024    (set_attr "predicable" "yes")]
2025 )
2026   
2027 (define_insn_and_split "*anddi_notzesidi_di"
2028   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2029         (and:DI (not:DI (zero_extend:DI
2030                          (match_operand:SI 2 "s_register_operand" "r,r")))
2031                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2032   "TARGET_ARM"
2033   "@
2034    bic%?\\t%Q0, %Q1, %2
2035    #"
2036   ; (not (zero_extend ...)) allows us to just copy the high word from
2037   ; operand1 to operand0.
2038   "TARGET_ARM
2039    && reload_completed
2040    && operands[0] != operands[1]"
2041   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2042    (set (match_dup 3) (match_dup 4))]
2043   "
2044   {
2045     operands[3] = gen_highpart (SImode, operands[0]);
2046     operands[0] = gen_lowpart (SImode, operands[0]);
2047     operands[4] = gen_highpart (SImode, operands[1]);
2048     operands[1] = gen_lowpart (SImode, operands[1]);
2049   }"
2050   [(set_attr "length" "4,8")
2051    (set_attr "predicable" "yes")]
2052 )
2053   
2054 (define_insn_and_split "*anddi_notsesidi_di"
2055   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2056         (and:DI (not:DI (sign_extend:DI
2057                          (match_operand:SI 2 "s_register_operand" "r,r")))
2058                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2059   "TARGET_ARM"
2060   "#"
2061   "TARGET_ARM && reload_completed"
2062   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2063    (set (match_dup 3) (and:SI (not:SI
2064                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2065                                (match_dup 4)))]
2066   "
2067   {
2068     operands[3] = gen_highpart (SImode, operands[0]);
2069     operands[0] = gen_lowpart (SImode, operands[0]);
2070     operands[4] = gen_highpart (SImode, operands[1]);
2071     operands[1] = gen_lowpart (SImode, operands[1]);
2072   }"
2073   [(set_attr "length" "8")
2074    (set_attr "predicable" "yes")]
2075 )
2076   
2077 (define_insn "andsi_notsi_si"
2078   [(set (match_operand:SI 0 "s_register_operand" "=r")
2079         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2080                 (match_operand:SI 1 "s_register_operand" "r")))]
2081   "TARGET_ARM"
2082   "bic%?\\t%0, %1, %2"
2083   [(set_attr "predicable" "yes")]
2084 )
2085
2086 (define_insn "bicsi3"
2087   [(set (match_operand:SI                 0 "register_operand" "=l")
2088         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2089                 (match_operand:SI         2 "register_operand" "0")))]
2090   "TARGET_THUMB"
2091   "bic\\t%0, %0, %1"
2092   [(set_attr "length" "2")]
2093 )
2094
2095 (define_insn "andsi_not_shiftsi_si"
2096   [(set (match_operand:SI 0 "s_register_operand" "=r")
2097         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2098                          [(match_operand:SI 2 "s_register_operand" "r")
2099                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2100                 (match_operand:SI 1 "s_register_operand" "r")))]
2101   "TARGET_ARM"
2102   "bic%?\\t%0, %1, %2%S4"
2103   [(set_attr "predicable" "yes")
2104    (set_attr "shift" "2")
2105    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2106                       (const_string "alu_shift")
2107                       (const_string "alu_shift_reg")))]
2108 )
2109
2110 (define_insn "*andsi_notsi_si_compare0"
2111   [(set (reg:CC_NOOV CC_REGNUM)
2112         (compare:CC_NOOV
2113          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2114                  (match_operand:SI 1 "s_register_operand" "r"))
2115          (const_int 0)))
2116    (set (match_operand:SI 0 "s_register_operand" "=r")
2117         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2118   "TARGET_ARM"
2119   "bic%?s\\t%0, %1, %2"
2120   [(set_attr "conds" "set")]
2121 )
2122
2123 (define_insn "*andsi_notsi_si_compare0_scratch"
2124   [(set (reg:CC_NOOV CC_REGNUM)
2125         (compare:CC_NOOV
2126          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2127                  (match_operand:SI 1 "s_register_operand" "r"))
2128          (const_int 0)))
2129    (clobber (match_scratch:SI 0 "=r"))]
2130   "TARGET_ARM"
2131   "bic%?s\\t%0, %1, %2"
2132   [(set_attr "conds" "set")]
2133 )
2134
2135 (define_insn "iordi3"
2136   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2137         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2138                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2139   "TARGET_ARM && ! TARGET_IWMMXT"
2140   "#"
2141   [(set_attr "length" "8")
2142    (set_attr "predicable" "yes")]
2143 )
2144
2145 (define_insn "*iordi_zesidi_di"
2146   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2147         (ior:DI (zero_extend:DI
2148                  (match_operand:SI 2 "s_register_operand" "r,r"))
2149                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2150   "TARGET_ARM"
2151   "@
2152    orr%?\\t%Q0, %Q1, %2
2153    #"
2154   [(set_attr "length" "4,8")
2155    (set_attr "predicable" "yes")]
2156 )
2157
2158 (define_insn "*iordi_sesidi_di"
2159   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2160         (ior:DI (sign_extend:DI
2161                  (match_operand:SI 2 "s_register_operand" "r,r"))
2162                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2163   "TARGET_ARM"
2164   "#"
2165   [(set_attr "length" "8")
2166    (set_attr "predicable" "yes")]
2167 )
2168
2169 (define_expand "iorsi3"
2170   [(set (match_operand:SI         0 "s_register_operand" "")
2171         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2172                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2173   "TARGET_EITHER"
2174   "
2175   if (GET_CODE (operands[2]) == CONST_INT)
2176     {
2177       if (TARGET_ARM)
2178         {
2179           arm_split_constant (IOR, SImode, NULL_RTX,
2180                               INTVAL (operands[2]), operands[0], operands[1],
2181                               optimize && !no_new_pseudos);
2182           DONE;
2183         }
2184       else /* TARGET_THUMB */
2185         operands [2] = force_reg (SImode, operands [2]);
2186     }
2187   "
2188 )
2189
2190 (define_insn_and_split "*arm_iorsi3"
2191   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2192         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2193                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2194   "TARGET_ARM"
2195   "@
2196    orr%?\\t%0, %1, %2
2197    #"
2198   "TARGET_ARM
2199    && GET_CODE (operands[2]) == CONST_INT
2200    && !const_ok_for_arm (INTVAL (operands[2]))"
2201   [(clobber (const_int 0))]
2202   "
2203   arm_split_constant (IOR, SImode, curr_insn, 
2204                       INTVAL (operands[2]), operands[0], operands[1], 0);
2205   DONE;
2206   "
2207   [(set_attr "length" "4,16")
2208    (set_attr "predicable" "yes")]
2209 )
2210
2211 (define_insn "*thumb_iorsi3"
2212   [(set (match_operand:SI         0 "register_operand" "=l")
2213         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2214                 (match_operand:SI 2 "register_operand" "l")))]
2215   "TARGET_THUMB"
2216   "orr\\t%0, %0, %2"
2217   [(set_attr "length" "2")]
2218 )
2219
2220 (define_peephole2
2221   [(match_scratch:SI 3 "r")
2222    (set (match_operand:SI 0 "arm_general_register_operand" "")
2223         (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2224                 (match_operand:SI 2 "const_int_operand" "")))]
2225   "TARGET_ARM
2226    && !const_ok_for_arm (INTVAL (operands[2]))
2227    && const_ok_for_arm (~INTVAL (operands[2]))"
2228   [(set (match_dup 3) (match_dup 2))
2229    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2230   ""
2231 )
2232
2233 (define_insn "*iorsi3_compare0"
2234   [(set (reg:CC_NOOV CC_REGNUM)
2235         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2236                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2237                          (const_int 0)))
2238    (set (match_operand:SI 0 "s_register_operand" "=r")
2239         (ior:SI (match_dup 1) (match_dup 2)))]
2240   "TARGET_ARM"
2241   "orr%?s\\t%0, %1, %2"
2242   [(set_attr "conds" "set")]
2243 )
2244
2245 (define_insn "*iorsi3_compare0_scratch"
2246   [(set (reg:CC_NOOV CC_REGNUM)
2247         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2248                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2249                          (const_int 0)))
2250    (clobber (match_scratch:SI 0 "=r"))]
2251   "TARGET_ARM"
2252   "orr%?s\\t%0, %1, %2"
2253   [(set_attr "conds" "set")]
2254 )
2255
2256 (define_insn "xordi3"
2257   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2258         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2259                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2260   "TARGET_ARM && !TARGET_IWMMXT"
2261   "#"
2262   [(set_attr "length" "8")
2263    (set_attr "predicable" "yes")]
2264 )
2265
2266 (define_insn "*xordi_zesidi_di"
2267   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2268         (xor:DI (zero_extend:DI
2269                  (match_operand:SI 2 "s_register_operand" "r,r"))
2270                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2271   "TARGET_ARM"
2272   "@
2273    eor%?\\t%Q0, %Q1, %2
2274    #"
2275   [(set_attr "length" "4,8")
2276    (set_attr "predicable" "yes")]
2277 )
2278
2279 (define_insn "*xordi_sesidi_di"
2280   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2281         (xor:DI (sign_extend:DI
2282                  (match_operand:SI 2 "s_register_operand" "r,r"))
2283                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2284   "TARGET_ARM"
2285   "#"
2286   [(set_attr "length" "8")
2287    (set_attr "predicable" "yes")]
2288 )
2289
2290 (define_expand "xorsi3"
2291   [(set (match_operand:SI         0 "s_register_operand" "")
2292         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2293                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2294   "TARGET_EITHER"
2295   "if (TARGET_THUMB)
2296      if (GET_CODE (operands[2]) == CONST_INT)
2297        operands[2] = force_reg (SImode, operands[2]);
2298   "
2299 )
2300
2301 (define_insn "*arm_xorsi3"
2302   [(set (match_operand:SI         0 "s_register_operand" "=r")
2303         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2304                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2305   "TARGET_ARM"
2306   "eor%?\\t%0, %1, %2"
2307   [(set_attr "predicable" "yes")]
2308 )
2309
2310 (define_insn "*thumb_xorsi3"
2311   [(set (match_operand:SI         0 "register_operand" "=l")
2312         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2313                 (match_operand:SI 2 "register_operand" "l")))]
2314   "TARGET_THUMB"
2315   "eor\\t%0, %0, %2"
2316   [(set_attr "length" "2")]
2317 )
2318
2319 (define_insn "*xorsi3_compare0"
2320   [(set (reg:CC_NOOV CC_REGNUM)
2321         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2322                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2323                          (const_int 0)))
2324    (set (match_operand:SI 0 "s_register_operand" "=r")
2325         (xor:SI (match_dup 1) (match_dup 2)))]
2326   "TARGET_ARM"
2327   "eor%?s\\t%0, %1, %2"
2328   [(set_attr "conds" "set")]
2329 )
2330
2331 (define_insn "*xorsi3_compare0_scratch"
2332   [(set (reg:CC_NOOV CC_REGNUM)
2333         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2334                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2335                          (const_int 0)))]
2336   "TARGET_ARM"
2337   "teq%?\\t%0, %1"
2338   [(set_attr "conds" "set")]
2339 )
2340
2341 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2342 ; (NOT D) we can sometimes merge the final NOT into one of the following
2343 ; insns.
2344
2345 (define_split
2346   [(set (match_operand:SI 0 "s_register_operand" "")
2347         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2348                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2349                 (match_operand:SI 3 "arm_rhs_operand" "")))
2350    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2351   "TARGET_ARM"
2352   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2353                               (not:SI (match_dup 3))))
2354    (set (match_dup 0) (not:SI (match_dup 4)))]
2355   ""
2356 )
2357
2358 (define_insn "*andsi_iorsi3_notsi"
2359   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2360         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2361                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2362                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2363   "TARGET_ARM"
2364   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2365   [(set_attr "length" "8")
2366    (set_attr "predicable" "yes")]
2367 )
2368
2369 (define_split
2370   [(set (match_operand:SI 0 "s_register_operand" "")
2371         (match_operator:SI 1 "logical_binary_operator"
2372          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2373                            (match_operand:SI 3 "const_int_operand" "")
2374                            (match_operand:SI 4 "const_int_operand" ""))
2375           (match_operator:SI 9 "logical_binary_operator"
2376            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2377                          (match_operand:SI 6 "const_int_operand" ""))
2378             (match_operand:SI 7 "s_register_operand" "")])]))
2379    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2380   "TARGET_ARM
2381    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2382    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2383   [(set (match_dup 8)
2384         (match_op_dup 1
2385          [(ashift:SI (match_dup 2) (match_dup 4))
2386           (match_dup 5)]))
2387    (set (match_dup 0)
2388         (match_op_dup 1
2389          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2390           (match_dup 7)]))]
2391   "
2392   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2393 ")
2394
2395 (define_split
2396   [(set (match_operand:SI 0 "s_register_operand" "")
2397         (match_operator:SI 1 "logical_binary_operator"
2398          [(match_operator:SI 9 "logical_binary_operator"
2399            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2400                          (match_operand:SI 6 "const_int_operand" ""))
2401             (match_operand:SI 7 "s_register_operand" "")])
2402           (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2403                            (match_operand:SI 3 "const_int_operand" "")
2404                            (match_operand:SI 4 "const_int_operand" ""))]))
2405    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2406   "TARGET_ARM
2407    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2408    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2409   [(set (match_dup 8)
2410         (match_op_dup 1
2411          [(ashift:SI (match_dup 2) (match_dup 4))
2412           (match_dup 5)]))
2413    (set (match_dup 0)
2414         (match_op_dup 1
2415          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2416           (match_dup 7)]))]
2417   "
2418   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2419 ")
2420
2421 (define_split
2422   [(set (match_operand:SI 0 "s_register_operand" "")
2423         (match_operator:SI 1 "logical_binary_operator"
2424          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2425                            (match_operand:SI 3 "const_int_operand" "")
2426                            (match_operand:SI 4 "const_int_operand" ""))
2427           (match_operator:SI 9 "logical_binary_operator"
2428            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2429                          (match_operand:SI 6 "const_int_operand" ""))
2430             (match_operand:SI 7 "s_register_operand" "")])]))
2431    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2432   "TARGET_ARM
2433    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2434    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2435   [(set (match_dup 8)
2436         (match_op_dup 1
2437          [(ashift:SI (match_dup 2) (match_dup 4))
2438           (match_dup 5)]))
2439    (set (match_dup 0)
2440         (match_op_dup 1
2441          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2442           (match_dup 7)]))]
2443   "
2444   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2445 ")
2446
2447 (define_split
2448   [(set (match_operand:SI 0 "s_register_operand" "")
2449         (match_operator:SI 1 "logical_binary_operator"
2450          [(match_operator:SI 9 "logical_binary_operator"
2451            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2452                          (match_operand:SI 6 "const_int_operand" ""))
2453             (match_operand:SI 7 "s_register_operand" "")])
2454           (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2455                            (match_operand:SI 3 "const_int_operand" "")
2456                            (match_operand:SI 4 "const_int_operand" ""))]))
2457    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2458   "TARGET_ARM
2459    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2460    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2461   [(set (match_dup 8)
2462         (match_op_dup 1
2463          [(ashift:SI (match_dup 2) (match_dup 4))
2464           (match_dup 5)]))
2465    (set (match_dup 0)
2466         (match_op_dup 1
2467          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2468           (match_dup 7)]))]
2469   "
2470   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2471 ")
2472 \f
2473
2474 ;; Minimum and maximum insns
2475
2476 (define_expand "smaxsi3"
2477   [(parallel [
2478     (set (match_operand:SI 0 "s_register_operand" "")
2479          (smax:SI (match_operand:SI 1 "s_register_operand" "")
2480                   (match_operand:SI 2 "arm_rhs_operand" "")))
2481     (clobber (reg:CC CC_REGNUM))])]
2482   "TARGET_ARM"
2483   "
2484   if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
2485     {
2486       /* No need for a clobber of the condition code register here.  */
2487       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2488                               gen_rtx_SMAX (SImode, operands[1],
2489                                             operands[2])));
2490       DONE;
2491     }
2492 ")
2493
2494 (define_insn "*smax_0"
2495   [(set (match_operand:SI 0 "s_register_operand" "=r")
2496         (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2497                  (const_int 0)))]
2498   "TARGET_ARM"
2499   "bic%?\\t%0, %1, %1, asr #31"
2500   [(set_attr "predicable" "yes")]
2501 )
2502
2503 (define_insn "*smax_m1"
2504   [(set (match_operand:SI 0 "s_register_operand" "=r")
2505         (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2506                  (const_int -1)))]
2507   "TARGET_ARM"
2508   "orr%?\\t%0, %1, %1, asr #31"
2509   [(set_attr "predicable" "yes")]
2510 )
2511
2512 (define_insn "*smax_insn"
2513   [(set (match_operand:SI          0 "s_register_operand" "=r,r")
2514         (smax:SI (match_operand:SI 1 "s_register_operand"  "%0,?r")
2515                  (match_operand:SI 2 "arm_rhs_operand"    "rI,rI")))
2516    (clobber (reg:CC CC_REGNUM))]
2517   "TARGET_ARM"
2518   "@
2519    cmp\\t%1, %2\;movlt\\t%0, %2
2520    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2521   [(set_attr "conds" "clob")
2522    (set_attr "length" "8,12")]
2523 )
2524
2525 (define_expand "sminsi3"
2526   [(parallel [
2527     (set (match_operand:SI 0 "s_register_operand" "")
2528          (smin:SI (match_operand:SI 1 "s_register_operand" "")
2529                   (match_operand:SI 2 "arm_rhs_operand" "")))
2530     (clobber (reg:CC CC_REGNUM))])]
2531   "TARGET_ARM"
2532   "
2533   if (operands[2] == const0_rtx)
2534     {
2535       /* No need for a clobber of the condition code register here.  */
2536       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2537                               gen_rtx_SMIN (SImode, operands[1],
2538                                             operands[2])));
2539       DONE;
2540     }
2541 ")
2542
2543 (define_insn "*smin_0"
2544   [(set (match_operand:SI 0 "s_register_operand" "=r")
2545         (smin:SI (match_operand:SI 1 "s_register_operand" "r")
2546                  (const_int 0)))]
2547   "TARGET_ARM"
2548   "and%?\\t%0, %1, %1, asr #31"
2549   [(set_attr "predicable" "yes")]
2550 )
2551
2552 (define_insn "*smin_insn"
2553   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2554         (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
2555                  (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
2556    (clobber (reg:CC CC_REGNUM))]
2557   "TARGET_ARM"
2558   "@
2559    cmp\\t%1, %2\;movge\\t%0, %2
2560    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2561   [(set_attr "conds" "clob")
2562    (set_attr "length" "8,12")]
2563 )
2564
2565 (define_insn "umaxsi3"
2566   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2567         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2568                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2569    (clobber (reg:CC CC_REGNUM))]
2570   "TARGET_ARM"
2571   "@
2572    cmp\\t%1, %2\;movcc\\t%0, %2
2573    cmp\\t%1, %2\;movcs\\t%0, %1
2574    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2575   [(set_attr "conds" "clob")
2576    (set_attr "length" "8,8,12")]
2577 )
2578
2579 (define_insn "uminsi3"
2580   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2581         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2582                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2583    (clobber (reg:CC CC_REGNUM))]
2584   "TARGET_ARM"
2585   "@
2586    cmp\\t%1, %2\;movcs\\t%0, %2
2587    cmp\\t%1, %2\;movcc\\t%0, %1
2588    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2589   [(set_attr "conds" "clob")
2590    (set_attr "length" "8,8,12")]
2591 )
2592
2593 (define_insn "*store_minmaxsi"
2594   [(set (match_operand:SI 0 "memory_operand" "=m")
2595         (match_operator:SI 3 "minmax_operator"
2596          [(match_operand:SI 1 "s_register_operand" "r")
2597           (match_operand:SI 2 "s_register_operand" "r")]))
2598    (clobber (reg:CC CC_REGNUM))]
2599   "TARGET_ARM"
2600   "*
2601   operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2602                                 operands[1], operands[2]);
2603   output_asm_insn (\"cmp\\t%1, %2\", operands);
2604   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2605   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2606   return \"\";
2607   "
2608   [(set_attr "conds" "clob")
2609    (set_attr "length" "12")
2610    (set_attr "type" "store1")]
2611 )
2612
2613 ; Reject the frame pointer in operand[1], since reloading this after
2614 ; it has been eliminated can cause carnage.
2615 (define_insn "*minmax_arithsi"
2616   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2617         (match_operator:SI 4 "shiftable_operator"
2618          [(match_operator:SI 5 "minmax_operator"
2619            [(match_operand:SI 2 "s_register_operand" "r,r")
2620             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2621           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2622    (clobber (reg:CC CC_REGNUM))]
2623   "TARGET_ARM && !arm_eliminable_register (operands[1])"
2624   "*
2625   {
2626     enum rtx_code code = GET_CODE (operands[4]);
2627
2628     operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2629                                   operands[2], operands[3]);
2630     output_asm_insn (\"cmp\\t%2, %3\", operands);
2631     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2632     if (which_alternative != 0 || operands[3] != const0_rtx
2633         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2634       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2635     return \"\";
2636   }"
2637   [(set_attr "conds" "clob")
2638    (set_attr "length" "12")]
2639 )
2640
2641 \f
2642 ;; Shift and rotation insns
2643
2644 (define_expand "ashldi3"
2645   [(set (match_operand:DI            0 "s_register_operand" "")
2646         (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2647                    (match_operand:SI 2 "reg_or_int_operand" "")))]
2648   "TARGET_ARM"
2649   "
2650   if (GET_CODE (operands[2]) == CONST_INT)
2651     {
2652       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2653         {
2654           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2655           DONE;
2656         }
2657         /* Ideally we shouldn't fail here if we could know that operands[1] 
2658            ends up already living in an iwmmxt register. Otherwise it's
2659            cheaper to have the alternate code being generated than moving
2660            values to iwmmxt regs and back.  */
2661         FAIL;
2662     }
2663   else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2664     FAIL;
2665   "
2666 )
2667
2668 (define_insn "arm_ashldi3_1bit"
2669   [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
2670         (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2671                    (const_int 1)))
2672    (clobber (reg:CC CC_REGNUM))]
2673   "TARGET_ARM"
2674   "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2675   [(set_attr "conds" "clob")
2676    (set_attr "length" "8")]
2677 )
2678
2679 (define_expand "ashlsi3"
2680   [(set (match_operand:SI            0 "s_register_operand" "")
2681         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2682                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2683   "TARGET_EITHER"
2684   "
2685   if (GET_CODE (operands[2]) == CONST_INT
2686       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2687     {
2688       emit_insn (gen_movsi (operands[0], const0_rtx));
2689       DONE;
2690     }
2691   "
2692 )
2693
2694 (define_insn "*thumb_ashlsi3"
2695   [(set (match_operand:SI            0 "register_operand" "=l,l")
2696         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2697                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2698   "TARGET_THUMB"
2699   "lsl\\t%0, %1, %2"
2700   [(set_attr "length" "2")]
2701 )
2702
2703 (define_expand "ashrdi3"
2704   [(set (match_operand:DI              0 "s_register_operand" "")
2705         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2706                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2707   "TARGET_ARM"
2708   "
2709   if (GET_CODE (operands[2]) == CONST_INT)
2710     {
2711       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2712         {
2713           emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2714           DONE;
2715         }
2716         /* Ideally we shouldn't fail here if we could know that operands[1] 
2717            ends up already living in an iwmmxt register. Otherwise it's
2718            cheaper to have the alternate code being generated than moving
2719            values to iwmmxt regs and back.  */
2720         FAIL;
2721     }
2722   else if (!TARGET_REALLY_IWMMXT)
2723     FAIL;
2724   "
2725 )
2726
2727 (define_insn "arm_ashrdi3_1bit"
2728   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2729         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2730                      (const_int 1)))
2731    (clobber (reg:CC CC_REGNUM))]
2732   "TARGET_ARM"
2733   "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2734   [(set_attr "conds" "clob")
2735    (set_attr "length" "8")]
2736 )
2737
2738 (define_expand "ashrsi3"
2739   [(set (match_operand:SI              0 "s_register_operand" "")
2740         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2741                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2742   "TARGET_EITHER"
2743   "
2744   if (GET_CODE (operands[2]) == CONST_INT
2745       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2746     operands[2] = GEN_INT (31);
2747   "
2748 )
2749
2750 (define_insn "*thumb_ashrsi3"
2751   [(set (match_operand:SI              0 "register_operand" "=l,l")
2752         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2753                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2754   "TARGET_THUMB"
2755   "asr\\t%0, %1, %2"
2756   [(set_attr "length" "2")]
2757 )
2758
2759 (define_expand "lshrdi3"
2760   [(set (match_operand:DI              0 "s_register_operand" "")
2761         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2762                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2763   "TARGET_ARM"
2764   "
2765   if (GET_CODE (operands[2]) == CONST_INT)
2766     {
2767       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2768         {
2769           emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2770           DONE;
2771         }
2772         /* Ideally we shouldn't fail here if we could know that operands[1] 
2773            ends up already living in an iwmmxt register. Otherwise it's
2774            cheaper to have the alternate code being generated than moving
2775            values to iwmmxt regs and back.  */
2776         FAIL;
2777     }
2778   else if (!TARGET_REALLY_IWMMXT)
2779     FAIL;
2780   "
2781 )
2782
2783 (define_insn "arm_lshrdi3_1bit"
2784   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2785         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2786                      (const_int 1)))
2787    (clobber (reg:CC CC_REGNUM))]
2788   "TARGET_ARM"
2789   "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2790   [(set_attr "conds" "clob")
2791    (set_attr "length" "8")]
2792 )
2793
2794 (define_expand "lshrsi3"
2795   [(set (match_operand:SI              0 "s_register_operand" "")
2796         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2797                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2798   "TARGET_EITHER"
2799   "
2800   if (GET_CODE (operands[2]) == CONST_INT
2801       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2802     {
2803       emit_insn (gen_movsi (operands[0], const0_rtx));
2804       DONE;
2805     }
2806   "
2807 )
2808
2809 (define_insn "*thumb_lshrsi3"
2810   [(set (match_operand:SI              0 "register_operand" "=l,l")
2811         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2812                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2813   "TARGET_THUMB"
2814   "lsr\\t%0, %1, %2"
2815   [(set_attr "length" "2")]
2816 )
2817
2818 (define_expand "rotlsi3"
2819   [(set (match_operand:SI              0 "s_register_operand" "")
2820         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2821                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2822   "TARGET_ARM"
2823   "
2824   if (GET_CODE (operands[2]) == CONST_INT)
2825     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2826   else
2827     {
2828       rtx reg = gen_reg_rtx (SImode);
2829       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2830       operands[2] = reg;
2831     }
2832   "
2833 )
2834
2835 (define_expand "rotrsi3"
2836   [(set (match_operand:SI              0 "s_register_operand" "")
2837         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2838                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2839   "TARGET_EITHER"
2840   "
2841   if (TARGET_ARM)
2842     {
2843       if (GET_CODE (operands[2]) == CONST_INT
2844           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2845         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2846     }
2847   else /* TARGET_THUMB */
2848     {
2849       if (GET_CODE (operands [2]) == CONST_INT)
2850         operands [2] = force_reg (SImode, operands[2]);
2851     }
2852   "
2853 )
2854
2855 (define_insn "*thumb_rotrsi3"
2856   [(set (match_operand:SI              0 "register_operand" "=l")
2857         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2858                      (match_operand:SI 2 "register_operand" "l")))]
2859   "TARGET_THUMB"
2860   "ror\\t%0, %0, %2"
2861   [(set_attr "length" "2")]
2862 )
2863
2864 (define_insn "*arm_shiftsi3"
2865   [(set (match_operand:SI   0 "s_register_operand" "=r")
2866         (match_operator:SI  3 "shift_operator"
2867          [(match_operand:SI 1 "s_register_operand"  "r")
2868           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2869   "TARGET_ARM"
2870   "mov%?\\t%0, %1%S3"
2871   [(set_attr "predicable" "yes")
2872    (set_attr "shift" "1")
2873    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2874                       (const_string "alu_shift")
2875                       (const_string "alu_shift_reg")))]
2876 )
2877
2878 (define_insn "*shiftsi3_compare0"
2879   [(set (reg:CC_NOOV CC_REGNUM)
2880         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2881                           [(match_operand:SI 1 "s_register_operand" "r")
2882                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2883                          (const_int 0)))
2884    (set (match_operand:SI 0 "s_register_operand" "=r")
2885         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2886   "TARGET_ARM"
2887   "mov%?s\\t%0, %1%S3"
2888   [(set_attr "conds" "set")
2889    (set_attr "shift" "1")
2890    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2891                       (const_string "alu_shift")
2892                       (const_string "alu_shift_reg")))]
2893 )
2894
2895 (define_insn "*shiftsi3_compare0_scratch"
2896   [(set (reg:CC_NOOV CC_REGNUM)
2897         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2898                           [(match_operand:SI 1 "s_register_operand" "r")
2899                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2900                          (const_int 0)))
2901    (clobber (match_scratch:SI 0 "=r"))]
2902   "TARGET_ARM"
2903   "mov%?s\\t%0, %1%S3"
2904   [(set_attr "conds" "set")
2905    (set_attr "shift" "1")]
2906 )
2907
2908 (define_insn "*notsi_shiftsi"
2909   [(set (match_operand:SI 0 "s_register_operand" "=r")
2910         (not:SI (match_operator:SI 3 "shift_operator"
2911                  [(match_operand:SI 1 "s_register_operand" "r")
2912                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2913   "TARGET_ARM"
2914   "mvn%?\\t%0, %1%S3"
2915   [(set_attr "predicable" "yes")
2916    (set_attr "shift" "1")
2917    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2918                       (const_string "alu_shift")
2919                       (const_string "alu_shift_reg")))]
2920 )
2921
2922 (define_insn "*notsi_shiftsi_compare0"
2923   [(set (reg:CC_NOOV CC_REGNUM)
2924         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2925                           [(match_operand:SI 1 "s_register_operand" "r")
2926                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2927                          (const_int 0)))
2928    (set (match_operand:SI 0 "s_register_operand" "=r")
2929         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2930   "TARGET_ARM"
2931   "mvn%?s\\t%0, %1%S3"
2932   [(set_attr "conds" "set")
2933    (set_attr "shift" "1")
2934    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2935                       (const_string "alu_shift")
2936                       (const_string "alu_shift_reg")))]
2937 )
2938
2939 (define_insn "*not_shiftsi_compare0_scratch"
2940   [(set (reg:CC_NOOV CC_REGNUM)
2941         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2942                           [(match_operand:SI 1 "s_register_operand" "r")
2943                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2944                          (const_int 0)))
2945    (clobber (match_scratch:SI 0 "=r"))]
2946   "TARGET_ARM"
2947   "mvn%?s\\t%0, %1%S3"
2948   [(set_attr "conds" "set")
2949    (set_attr "shift" "1")
2950    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2951                       (const_string "alu_shift")
2952                       (const_string "alu_shift_reg")))]
2953 )
2954
2955 ;; We don't really have extzv, but defining this using shifts helps
2956 ;; to reduce register pressure later on.
2957
2958 (define_expand "extzv"
2959   [(set (match_dup 4)
2960         (ashift:SI (match_operand:SI   1 "register_operand" "")
2961                    (match_operand:SI   2 "const_int_operand" "")))
2962    (set (match_operand:SI              0 "register_operand" "")
2963         (lshiftrt:SI (match_dup 4)
2964                      (match_operand:SI 3 "const_int_operand" "")))]
2965   "TARGET_THUMB"
2966   "
2967   {
2968     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2969     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2970     
2971     operands[3] = GEN_INT (rshift);
2972     
2973     if (lshift == 0)
2974       {
2975         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2976         DONE;
2977       }
2978       
2979     operands[2] = GEN_INT (lshift);
2980     operands[4] = gen_reg_rtx (SImode);
2981   }"
2982 )
2983
2984 \f
2985 ;; Unary arithmetic insns
2986
2987 (define_expand "negdi2"
2988  [(parallel
2989    [(set (match_operand:DI          0 "s_register_operand" "")
2990           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2991     (clobber (reg:CC CC_REGNUM))])]
2992   "TARGET_EITHER"
2993   "
2994   if (TARGET_THUMB)
2995     {
2996       if (GET_CODE (operands[1]) != REG)
2997         operands[1] = force_reg (SImode, operands[1]);
2998      }
2999   "
3000 )
3001
3002 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
3003 ;; The second alternative is to allow the common case of a *full* overlap.
3004 (define_insn "*arm_negdi2"
3005   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
3006         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
3007    (clobber (reg:CC CC_REGNUM))]
3008   "TARGET_ARM"
3009   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
3010   [(set_attr "conds" "clob")
3011    (set_attr "length" "8")]
3012 )
3013
3014 (define_insn "*thumb_negdi2"
3015   [(set (match_operand:DI         0 "register_operand" "=&l")
3016         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
3017    (clobber (reg:CC CC_REGNUM))]
3018   "TARGET_THUMB"
3019   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
3020   [(set_attr "length" "6")]
3021 )
3022
3023 (define_expand "negsi2"
3024   [(set (match_operand:SI         0 "s_register_operand" "")
3025         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
3026   "TARGET_EITHER"
3027   ""
3028 )
3029
3030 (define_insn "*arm_negsi2"
3031   [(set (match_operand:SI         0 "s_register_operand" "=r")
3032         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
3033   "TARGET_ARM"
3034   "rsb%?\\t%0, %1, #0"
3035   [(set_attr "predicable" "yes")]
3036 )
3037
3038 (define_insn "*thumb_negsi2"
3039   [(set (match_operand:SI         0 "register_operand" "=l")
3040         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
3041   "TARGET_THUMB"
3042   "neg\\t%0, %1"
3043   [(set_attr "length" "2")]
3044 )
3045
3046 (define_expand "negsf2"
3047   [(set (match_operand:SF         0 "s_register_operand" "")
3048         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
3049   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3050   ""
3051 )
3052
3053 (define_expand "negdf2"
3054   [(set (match_operand:DF         0 "s_register_operand" "")
3055         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
3056   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3057   "")
3058
3059 ;; abssi2 doesn't really clobber the condition codes if a different register
3060 ;; is being set.  To keep things simple, assume during rtl manipulations that
3061 ;; it does, but tell the final scan operator the truth.  Similarly for
3062 ;; (neg (abs...))
3063
3064 (define_expand "abssi2"
3065   [(parallel
3066     [(set (match_operand:SI         0 "s_register_operand" "")
3067           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3068      (clobber (reg:CC CC_REGNUM))])]
3069   "TARGET_ARM"
3070   "")
3071
3072 (define_insn "*arm_abssi2"
3073   [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
3074         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3075    (clobber (reg:CC CC_REGNUM))]
3076   "TARGET_ARM"
3077   "@
3078    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3079    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3080   [(set_attr "conds" "clob,*")
3081    (set_attr "shift" "1")
3082    ;; predicable can't be set based on the variant, so left as no
3083    (set_attr "length" "8")]
3084 )
3085
3086 (define_insn "*neg_abssi2"
3087   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3088         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3089    (clobber (reg:CC CC_REGNUM))]
3090   "TARGET_ARM"
3091   "@
3092    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3093    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3094   [(set_attr "conds" "clob,*")
3095    (set_attr "shift" "1")
3096    ;; predicable can't be set based on the variant, so left as no
3097    (set_attr "length" "8")]
3098 )
3099
3100 (define_expand "abssf2"
3101   [(set (match_operand:SF         0 "s_register_operand" "")
3102         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3103   "TARGET_ARM && TARGET_HARD_FLOAT"
3104   "")
3105
3106 (define_expand "absdf2"
3107   [(set (match_operand:DF         0 "s_register_operand" "")
3108         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3109   "TARGET_ARM && TARGET_HARD_FLOAT"
3110   "")
3111
3112 (define_expand "sqrtsf2"
3113   [(set (match_operand:SF 0 "s_register_operand" "")
3114         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3115   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3116   "")
3117
3118 (define_expand "sqrtdf2"
3119   [(set (match_operand:DF 0 "s_register_operand" "")
3120         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3121   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3122   "")
3123
3124 (define_insn_and_split "one_cmpldi2"
3125   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3126         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3127   "TARGET_ARM"
3128   "#"
3129   "TARGET_ARM && reload_completed"
3130   [(set (match_dup 0) (not:SI (match_dup 1)))
3131    (set (match_dup 2) (not:SI (match_dup 3)))]
3132   "
3133   {
3134     operands[2] = gen_highpart (SImode, operands[0]);
3135     operands[0] = gen_lowpart (SImode, operands[0]);
3136     operands[3] = gen_highpart (SImode, operands[1]);
3137     operands[1] = gen_lowpart (SImode, operands[1]);
3138   }"
3139   [(set_attr "length" "8")
3140    (set_attr "predicable" "yes")]
3141 )
3142
3143 (define_expand "one_cmplsi2"
3144   [(set (match_operand:SI         0 "s_register_operand" "")
3145         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3146   "TARGET_EITHER"
3147   ""
3148 )
3149
3150 (define_insn "*arm_one_cmplsi2"
3151   [(set (match_operand:SI         0 "s_register_operand" "=r")
3152         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3153   "TARGET_ARM"
3154   "mvn%?\\t%0, %1"
3155   [(set_attr "predicable" "yes")]
3156 )
3157
3158 (define_insn "*thumb_one_cmplsi2"
3159   [(set (match_operand:SI         0 "register_operand" "=l")
3160         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3161   "TARGET_THUMB"
3162   "mvn\\t%0, %1"
3163   [(set_attr "length" "2")]
3164 )
3165
3166 (define_insn "*notsi_compare0"
3167   [(set (reg:CC_NOOV CC_REGNUM)
3168         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3169                          (const_int 0)))
3170    (set (match_operand:SI 0 "s_register_operand" "=r")
3171         (not:SI (match_dup 1)))]
3172   "TARGET_ARM"
3173   "mvn%?s\\t%0, %1"
3174   [(set_attr "conds" "set")]
3175 )
3176
3177 (define_insn "*notsi_compare0_scratch"
3178   [(set (reg:CC_NOOV CC_REGNUM)
3179         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3180                          (const_int 0)))
3181    (clobber (match_scratch:SI 0 "=r"))]
3182   "TARGET_ARM"
3183   "mvn%?s\\t%0, %1"
3184   [(set_attr "conds" "set")]
3185 )
3186 \f
3187 ;; Fixed <--> Floating conversion insns
3188
3189 (define_expand "floatsisf2"
3190   [(set (match_operand:SF           0 "s_register_operand" "")
3191         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3192   "TARGET_ARM && TARGET_HARD_FLOAT"
3193   "
3194   if (TARGET_MAVERICK)
3195     {
3196       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3197       DONE;
3198     }
3199 ")
3200
3201 (define_expand "floatsidf2"
3202   [(set (match_operand:DF           0 "s_register_operand" "")
3203         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3204   "TARGET_ARM && TARGET_HARD_FLOAT"
3205   "
3206   if (TARGET_MAVERICK)
3207     {
3208       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3209       DONE;
3210     }
3211 ")
3212
3213 (define_expand "fix_truncsfsi2"
3214   [(set (match_operand:SI         0 "s_register_operand" "")
3215         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3216   "TARGET_ARM && TARGET_HARD_FLOAT"
3217   "
3218   if (TARGET_MAVERICK)
3219     {
3220       if (!cirrus_fp_register (operands[0], SImode))
3221         operands[0] = force_reg (SImode, operands[0]);
3222       if (!cirrus_fp_register (operands[1], SFmode))
3223         operands[1] = force_reg (SFmode, operands[0]);
3224       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3225       DONE;
3226     }
3227 ")
3228
3229 (define_expand "fix_truncdfsi2"
3230   [(set (match_operand:SI         0 "s_register_operand" "")
3231         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3232   "TARGET_ARM && TARGET_HARD_FLOAT"
3233   "
3234   if (TARGET_MAVERICK)
3235     {
3236       if (!cirrus_fp_register (operands[1], DFmode))
3237         operands[1] = force_reg (DFmode, operands[0]);
3238       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3239       DONE;
3240     }
3241 ")
3242
3243 ;; Truncation insns
3244
3245 (define_expand "truncdfsf2"
3246   [(set (match_operand:SF  0 "s_register_operand" "")
3247         (float_truncate:SF
3248          (match_operand:DF 1 "s_register_operand" "")))]
3249   "TARGET_ARM && TARGET_HARD_FLOAT"
3250   ""
3251 )
3252 \f
3253 ;; Zero and sign extension instructions.
3254
3255 (define_insn "zero_extendsidi2"
3256   [(set (match_operand:DI 0 "s_register_operand" "=r")
3257         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3258   "TARGET_ARM"
3259   "*
3260     if (REGNO (operands[1])
3261         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3262       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3263     return \"mov%?\\t%R0, #0\";
3264   "
3265   [(set_attr "length" "8")
3266    (set_attr "predicable" "yes")]
3267 )
3268
3269 (define_insn "zero_extendqidi2"
3270   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3271         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3272   "TARGET_ARM"
3273   "@
3274    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3275    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3276   [(set_attr "length" "8")
3277    (set_attr "predicable" "yes")
3278    (set_attr "type" "*,load_byte")
3279    (set_attr "pool_range" "*,4092")
3280    (set_attr "neg_pool_range" "*,4084")]
3281 )
3282
3283 (define_insn "extendsidi2"
3284   [(set (match_operand:DI 0 "s_register_operand" "=r")
3285         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3286   "TARGET_ARM"
3287   "*
3288     if (REGNO (operands[1])
3289         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3290       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3291     return \"mov%?\\t%R0, %Q0, asr #31\";
3292   "
3293   [(set_attr "length" "8")
3294    (set_attr "shift" "1")
3295    (set_attr "predicable" "yes")]
3296 )
3297
3298 (define_expand "zero_extendhisi2"
3299   [(set (match_dup 2)
3300         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3301                    (const_int 16)))
3302    (set (match_operand:SI 0 "s_register_operand" "")
3303         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3304   "TARGET_EITHER"
3305   "
3306   {
3307     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3308       {
3309         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3310                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3311         DONE;
3312       }
3313
3314     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3315       {
3316         emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3317         DONE;
3318       }
3319
3320     if (!s_register_operand (operands[1], HImode))
3321       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3322
3323     if (arm_arch6)
3324       {
3325         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3326                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3327         DONE;
3328       }
3329
3330     operands[1] = gen_lowpart (SImode, operands[1]);
3331     operands[2] = gen_reg_rtx (SImode);
3332   }"
3333 )
3334
3335 (define_insn "*thumb_zero_extendhisi2"
3336   [(set (match_operand:SI 0 "register_operand" "=l")
3337         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3338   "TARGET_THUMB && !arm_arch6"
3339   "*
3340   rtx mem = XEXP (operands[1], 0);
3341
3342   if (GET_CODE (mem) == CONST)
3343     mem = XEXP (mem, 0);
3344     
3345   if (GET_CODE (mem) == LABEL_REF)
3346     return \"ldr\\t%0, %1\";
3347     
3348   if (GET_CODE (mem) == PLUS)
3349     {
3350       rtx a = XEXP (mem, 0);
3351       rtx b = XEXP (mem, 1);
3352
3353       /* This can happen due to bugs in reload.  */
3354       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3355         {
3356           rtx ops[2];
3357           ops[0] = operands[0];
3358           ops[1] = a;
3359       
3360           output_asm_insn (\"mov        %0, %1\", ops);
3361
3362           XEXP (mem, 0) = operands[0];
3363        }
3364
3365       else if (   GET_CODE (a) == LABEL_REF
3366                && GET_CODE (b) == CONST_INT)
3367         return \"ldr\\t%0, %1\";
3368     }
3369     
3370   return \"ldrh\\t%0, %1\";
3371   "
3372   [(set_attr "length" "4")
3373    (set_attr "type" "load_byte")
3374    (set_attr "pool_range" "60")]
3375 )
3376
3377 (define_insn "*thumb_zero_extendhisi2_v6"
3378   [(set (match_operand:SI 0 "register_operand" "=l,l")
3379         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3380   "TARGET_THUMB && arm_arch6"
3381   "*
3382   rtx mem;
3383
3384   if (which_alternative == 0)
3385     return \"uxth\\t%0, %1\";
3386
3387   mem = XEXP (operands[1], 0);
3388
3389   if (GET_CODE (mem) == CONST)
3390     mem = XEXP (mem, 0);
3391     
3392   if (GET_CODE (mem) == LABEL_REF)
3393     return \"ldr\\t%0, %1\";
3394     
3395   if (GET_CODE (mem) == PLUS)
3396     {
3397       rtx a = XEXP (mem, 0);
3398       rtx b = XEXP (mem, 1);
3399
3400       /* This can happen due to bugs in reload.  */
3401       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3402         {
3403           rtx ops[2];
3404           ops[0] = operands[0];
3405           ops[1] = a;
3406       
3407           output_asm_insn (\"mov        %0, %1\", ops);
3408
3409           XEXP (mem, 0) = operands[0];
3410        }
3411
3412       else if (   GET_CODE (a) == LABEL_REF
3413                && GET_CODE (b) == CONST_INT)
3414         return \"ldr\\t%0, %1\";
3415     }
3416     
3417   return \"ldrh\\t%0, %1\";
3418   "
3419   [(set_attr "length" "2,4")
3420    (set_attr "type" "alu_shift,load_byte")
3421    (set_attr "pool_range" "*,60")]
3422 )
3423
3424 (define_insn "*arm_zero_extendhisi2"
3425   [(set (match_operand:SI 0 "s_register_operand" "=r")
3426         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3427   "TARGET_ARM && arm_arch4 && !arm_arch6"
3428   "ldr%?h\\t%0, %1"
3429   [(set_attr "type" "load_byte")
3430    (set_attr "predicable" "yes")
3431    (set_attr "pool_range" "256")
3432    (set_attr "neg_pool_range" "244")]
3433 )
3434
3435 (define_insn "*arm_zero_extendhisi2_v6"
3436   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3437         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3438   "TARGET_ARM && arm_arch6"
3439   "@
3440    uxth%?\\t%0, %1
3441    ldr%?h\\t%0, %1"
3442   [(set_attr "type" "alu_shift,load_byte")
3443    (set_attr "predicable" "yes")
3444    (set_attr "pool_range" "*,256")
3445    (set_attr "neg_pool_range" "*,244")]
3446 )
3447
3448 (define_insn "*arm_zero_extendhisi2addsi"
3449   [(set (match_operand:SI 0 "s_register_operand" "=r")
3450         (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3451                  (match_operand:SI 2 "s_register_operand" "r")))]
3452   "TARGET_ARM && arm_arch6"
3453   "uxtah%?\\t%0, %2, %1"
3454   [(set_attr "type" "alu_shift")
3455    (set_attr "predicable" "yes")]
3456 )
3457
3458 (define_expand "zero_extendqisi2"
3459   [(set (match_operand:SI 0 "s_register_operand" "")
3460         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3461   "TARGET_EITHER"
3462   "
3463   if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3464     {
3465       if (TARGET_ARM)
3466         {
3467           emit_insn (gen_andsi3 (operands[0],
3468                                  gen_lowpart (SImode, operands[1]),
3469                                  GEN_INT (255)));
3470         }
3471       else /* TARGET_THUMB */
3472         {
3473           rtx temp = gen_reg_rtx (SImode);
3474           rtx ops[3];
3475           
3476           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3477           operands[1] = gen_lowpart (SImode, operands[1]);
3478
3479           ops[0] = temp;
3480           ops[1] = operands[1];
3481           ops[2] = GEN_INT (24);
3482
3483           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3484                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3485           
3486           ops[0] = operands[0];
3487           ops[1] = temp;
3488           ops[2] = GEN_INT (24);
3489
3490           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3491                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3492         }
3493       DONE;
3494     }
3495   "
3496 )
3497
3498 (define_insn "*thumb_zero_extendqisi2"
3499   [(set (match_operand:SI 0 "register_operand" "=l")
3500         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3501   "TARGET_THUMB && !arm_arch6"
3502   "ldrb\\t%0, %1"
3503   [(set_attr "length" "2")
3504    (set_attr "type" "load_byte")
3505    (set_attr "pool_range" "32")]
3506 )
3507
3508 (define_insn "*thumb_zero_extendqisi2_v6"
3509   [(set (match_operand:SI 0 "register_operand" "=l,l")
3510         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3511   "TARGET_THUMB && arm_arch6"
3512   "@
3513    uxtb\\t%0, %1
3514    ldrb\\t%0, %1"
3515   [(set_attr "length" "2,2")
3516    (set_attr "type" "alu_shift,load_byte")
3517    (set_attr "pool_range" "*,32")]
3518 )
3519
3520 (define_insn "*arm_zero_extendqisi2"
3521   [(set (match_operand:SI 0 "s_register_operand" "=r")
3522         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3523   "TARGET_ARM && !arm_arch6"
3524   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3525   [(set_attr "type" "load_byte")
3526    (set_attr "predicable" "yes")
3527    (set_attr "pool_range" "4096")
3528    (set_attr "neg_pool_range" "4084")]
3529 )
3530
3531 (define_insn "*arm_zero_extendqisi2_v6"
3532   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3533         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3534   "TARGET_ARM && arm_arch6"
3535   "@
3536    uxtb%?\\t%0, %1
3537    ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3538   [(set_attr "type" "alu_shift,load_byte")
3539    (set_attr "predicable" "yes")
3540    (set_attr "pool_range" "*,4096")
3541    (set_attr "neg_pool_range" "*,4084")]
3542 )
3543
3544 (define_insn "*arm_zero_extendqisi2addsi"
3545   [(set (match_operand:SI 0 "s_register_operand" "=r")
3546         (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3547                  (match_operand:SI 2 "s_register_operand" "r")))]
3548   "TARGET_ARM && arm_arch6"
3549   "uxtab%?\\t%0, %2, %1"
3550   [(set_attr "predicable" "yes")
3551    (set_attr "type" "alu_shift")]
3552 )
3553
3554 (define_split
3555   [(set (match_operand:SI 0 "s_register_operand" "")
3556         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3557    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3558   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3559   [(set (match_dup 2) (match_dup 1))
3560    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3561   ""
3562 )
3563
3564 (define_split
3565   [(set (match_operand:SI 0 "s_register_operand" "")
3566         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
3567    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3568   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
3569   [(set (match_dup 2) (match_dup 1))
3570    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3571   ""
3572 )
3573
3574 (define_insn "*compareqi_eq0"
3575   [(set (reg:CC_Z CC_REGNUM)
3576         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3577                          (const_int 0)))]
3578   "TARGET_ARM"
3579   "tst\\t%0, #255"
3580   [(set_attr "conds" "set")]
3581 )
3582
3583 (define_expand "extendhisi2"
3584   [(set (match_dup 2)
3585         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3586                    (const_int 16)))
3587    (set (match_operand:SI 0 "s_register_operand" "")
3588         (ashiftrt:SI (match_dup 2)
3589                      (const_int 16)))]
3590   "TARGET_EITHER"
3591   "
3592   {
3593     if (GET_CODE (operands[1]) == MEM)
3594       {
3595         if (TARGET_THUMB)
3596           {
3597             emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3598             DONE;
3599           }
3600         else if (arm_arch4)
3601           {
3602             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3603                        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3604             DONE;
3605           }
3606       }
3607
3608     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3609       {
3610         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3611         DONE;
3612       }
3613
3614     if (!s_register_operand (operands[1], HImode))
3615       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3616
3617     if (arm_arch6)
3618       {
3619         if (TARGET_THUMB)
3620           emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3621         else
3622           emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3623                      gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3624
3625         DONE;
3626       }
3627
3628     operands[1] = gen_lowpart (SImode, operands[1]);
3629     operands[2] = gen_reg_rtx (SImode);
3630   }"
3631 )
3632
3633 (define_insn "thumb_extendhisi2"
3634   [(set (match_operand:SI 0 "register_operand" "=l")
3635         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3636    (clobber (match_scratch:SI 2 "=&l"))]
3637   "TARGET_THUMB && !arm_arch6"
3638   "*
3639   {
3640     rtx ops[4];
3641     rtx mem = XEXP (operands[1], 0);
3642
3643     /* This code used to try to use 'V', and fix the address only if it was
3644        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3645        range of QImode offsets, and offsettable_address_p does a QImode
3646        address check.  */
3647        
3648     if (GET_CODE (mem) == CONST)
3649       mem = XEXP (mem, 0);
3650     
3651     if (GET_CODE (mem) == LABEL_REF)
3652       return \"ldr\\t%0, %1\";
3653     
3654     if (GET_CODE (mem) == PLUS)
3655       {
3656         rtx a = XEXP (mem, 0);
3657         rtx b = XEXP (mem, 1);
3658
3659         if (GET_CODE (a) == LABEL_REF
3660             && GET_CODE (b) == CONST_INT)
3661           return \"ldr\\t%0, %1\";
3662
3663         if (GET_CODE (b) == REG)
3664           return \"ldrsh\\t%0, %1\";
3665           
3666         ops[1] = a;
3667         ops[2] = b;
3668       }
3669     else
3670       {
3671         ops[1] = mem;
3672         ops[2] = const0_rtx;
3673       }
3674
3675     gcc_assert (GET_CODE (ops[1]) == REG);
3676
3677     ops[0] = operands[0];
3678     ops[3] = operands[2];
3679     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3680     return \"\";
3681   }"
3682   [(set_attr "length" "4")
3683    (set_attr "type" "load_byte")
3684    (set_attr "pool_range" "1020")]
3685 )
3686
3687 ;; We used to have an early-clobber on the scratch register here.
3688 ;; However, there's a bug somewhere in reload which means that this
3689 ;; can be partially ignored during spill allocation if the memory
3690 ;; address also needs reloading; this causes us to die later on when
3691 ;; we try to verify the operands.  Fortunately, we don't really need
3692 ;; the early-clobber: we can always use operand 0 if operand 2
3693 ;; overlaps the address.
3694 (define_insn "*thumb_extendhisi2_insn_v6"
3695   [(set (match_operand:SI 0 "register_operand" "=l,l")
3696         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3697    (clobber (match_scratch:SI 2 "=X,l"))]
3698   "TARGET_THUMB && arm_arch6"
3699   "*
3700   {
3701     rtx ops[4];
3702     rtx mem;
3703
3704     if (which_alternative == 0)
3705       return \"sxth\\t%0, %1\";
3706
3707     mem = XEXP (operands[1], 0);
3708
3709     /* This code used to try to use 'V', and fix the address only if it was
3710        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3711        range of QImode offsets, and offsettable_address_p does a QImode
3712        address check.  */
3713        
3714     if (GET_CODE (mem) == CONST)
3715       mem = XEXP (mem, 0);
3716     
3717     if (GET_CODE (mem) == LABEL_REF)
3718       return \"ldr\\t%0, %1\";
3719     
3720     if (GET_CODE (mem) == PLUS)
3721       {
3722         rtx a = XEXP (mem, 0);
3723         rtx b = XEXP (mem, 1);
3724
3725         if (GET_CODE (a) == LABEL_REF
3726             && GET_CODE (b) == CONST_INT)
3727           return \"ldr\\t%0, %1\";
3728
3729         if (GET_CODE (b) == REG)
3730           return \"ldrsh\\t%0, %1\";
3731           
3732         ops[1] = a;
3733         ops[2] = b;
3734       }
3735     else
3736       {
3737         ops[1] = mem;
3738         ops[2] = const0_rtx;
3739       }
3740       
3741     gcc_assert (GET_CODE (ops[1]) == REG);
3742
3743     ops[0] = operands[0];
3744     if (reg_mentioned_p (operands[2], ops[1]))
3745       ops[3] = ops[0];
3746     else
3747       ops[3] = operands[2];
3748     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3749     return \"\";
3750   }"
3751   [(set_attr "length" "2,4")
3752    (set_attr "type" "alu_shift,load_byte")
3753    (set_attr "pool_range" "*,1020")]
3754 )
3755
3756 (define_expand "extendhisi2_mem"
3757   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3758    (set (match_dup 3)
3759         (zero_extend:SI (match_dup 7)))
3760    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3761    (set (match_operand:SI 0 "" "")
3762         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3763   "TARGET_ARM"
3764   "
3765   {
3766     rtx mem1, mem2;
3767     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3768
3769     mem1 = change_address (operands[1], QImode, addr);
3770     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
3771     operands[0] = gen_lowpart (SImode, operands[0]);
3772     operands[1] = mem1;
3773     operands[2] = gen_reg_rtx (SImode);
3774     operands[3] = gen_reg_rtx (SImode);
3775     operands[6] = gen_reg_rtx (SImode);
3776     operands[7] = mem2;
3777
3778     if (BYTES_BIG_ENDIAN)
3779       {
3780         operands[4] = operands[2];
3781         operands[5] = operands[3];
3782       }
3783     else
3784       {
3785         operands[4] = operands[3];
3786         operands[5] = operands[2];
3787       }
3788   }"
3789 )
3790
3791 (define_insn "*arm_extendhisi2"
3792   [(set (match_operand:SI 0 "s_register_operand" "=r")
3793         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3794   "TARGET_ARM && arm_arch4 && !arm_arch6"
3795   "ldr%?sh\\t%0, %1"
3796   [(set_attr "type" "load_byte")
3797    (set_attr "predicable" "yes")
3798    (set_attr "pool_range" "256")
3799    (set_attr "neg_pool_range" "244")]
3800 )
3801
3802 (define_insn "*arm_extendhisi2_v6"
3803   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3804         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3805   "TARGET_ARM && arm_arch6"
3806   "@
3807    sxth%?\\t%0, %1
3808    ldr%?sh\\t%0, %1"
3809   [(set_attr "type" "alu_shift,load_byte")
3810    (set_attr "predicable" "yes")
3811    (set_attr "pool_range" "*,256")
3812    (set_attr "neg_pool_range" "*,244")]
3813 )
3814
3815 (define_insn "*arm_extendhisi2addsi"
3816   [(set (match_operand:SI 0 "s_register_operand" "=r")
3817         (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3818                  (match_operand:SI 2 "s_register_operand" "r")))]
3819   "TARGET_ARM && arm_arch6"
3820   "sxtah%?\\t%0, %2, %1"
3821 )
3822
3823 (define_expand "extendqihi2"
3824   [(set (match_dup 2)
3825         (ashift:SI (match_operand:QI 1 "general_operand" "")
3826                    (const_int 24)))
3827    (set (match_operand:HI 0 "s_register_operand" "")
3828         (ashiftrt:SI (match_dup 2)
3829                      (const_int 24)))]
3830   "TARGET_ARM"
3831   "
3832   {
3833     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3834       {
3835         emit_insn (gen_rtx_SET (VOIDmode,
3836                                 operands[0],
3837                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3838         DONE;
3839       }
3840     if (!s_register_operand (operands[1], QImode))
3841       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3842     operands[0] = gen_lowpart (SImode, operands[0]);
3843     operands[1] = gen_lowpart (SImode, operands[1]);
3844     operands[2] = gen_reg_rtx (SImode);
3845   }"
3846 )
3847
3848 (define_insn "*extendqihi_insn"
3849   [(set (match_operand:HI 0 "s_register_operand" "=r")
3850         (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3851   "TARGET_ARM && arm_arch4"
3852   "ldr%?sb\\t%0, %1"
3853   [(set_attr "type" "load_byte")
3854    (set_attr "predicable" "yes")
3855    (set_attr "pool_range" "256")
3856    (set_attr "neg_pool_range" "244")]
3857 )
3858
3859 (define_expand "extendqisi2"
3860   [(set (match_dup 2)
3861         (ashift:SI (match_operand:QI 1 "general_operand" "")
3862                    (const_int 24)))
3863    (set (match_operand:SI 0 "s_register_operand" "")
3864         (ashiftrt:SI (match_dup 2)
3865                      (const_int 24)))]
3866   "TARGET_EITHER"
3867   "
3868   {
3869     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3870       {
3871         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3872                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3873         DONE;
3874       }
3875
3876     if (!s_register_operand (operands[1], QImode))
3877       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3878
3879     if (arm_arch6)
3880       {
3881         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3882                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3883         DONE;
3884       }
3885
3886     operands[1] = gen_lowpart (SImode, operands[1]);
3887     operands[2] = gen_reg_rtx (SImode);
3888   }"
3889 )
3890
3891 (define_insn "*arm_extendqisi"
3892   [(set (match_operand:SI 0 "s_register_operand" "=r")
3893         (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3894   "TARGET_ARM && arm_arch4 && !arm_arch6"
3895   "ldr%?sb\\t%0, %1"
3896   [(set_attr "type" "load_byte")
3897    (set_attr "predicable" "yes")
3898    (set_attr "pool_range" "256")
3899    (set_attr "neg_pool_range" "244")]
3900 )
3901
3902 (define_insn "*arm_extendqisi_v6"
3903   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3904         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3905   "TARGET_ARM && arm_arch6"
3906   "@
3907    sxtb%?\\t%0, %1
3908    ldr%?sb\\t%0, %1"
3909   [(set_attr "type" "alu_shift,load_byte")
3910    (set_attr "predicable" "yes")
3911    (set_attr "pool_range" "*,256")
3912    (set_attr "neg_pool_range" "*,244")]
3913 )
3914
3915 (define_insn "*arm_extendqisi2addsi"
3916   [(set (match_operand:SI 0 "s_register_operand" "=r")
3917         (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3918                  (match_operand:SI 2 "s_register_operand" "r")))]
3919   "TARGET_ARM && arm_arch6"
3920   "sxtab%?\\t%0, %2, %1"
3921   [(set_attr "type" "alu_shift")
3922    (set_attr "predicable" "yes")]
3923 )
3924
3925 (define_insn "*thumb_extendqisi2"
3926   [(set (match_operand:SI 0 "register_operand" "=l,l")
3927         (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3928   "TARGET_THUMB && !arm_arch6"
3929   "*
3930   {
3931     rtx ops[3];
3932     rtx mem = XEXP (operands[1], 0);
3933     
3934     if (GET_CODE (mem) == CONST)
3935       mem = XEXP (mem, 0);
3936     
3937     if (GET_CODE (mem) == LABEL_REF)
3938       return \"ldr\\t%0, %1\";
3939
3940     if (GET_CODE (mem) == PLUS
3941         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3942       return \"ldr\\t%0, %1\";
3943       
3944     if (which_alternative == 0)
3945       return \"ldrsb\\t%0, %1\";
3946       
3947     ops[0] = operands[0];
3948     
3949     if (GET_CODE (mem) == PLUS)
3950       {
3951         rtx a = XEXP (mem, 0);
3952         rtx b = XEXP (mem, 1);
3953         
3954         ops[1] = a;
3955         ops[2] = b;
3956
3957         if (GET_CODE (a) == REG)
3958           {
3959             if (GET_CODE (b) == REG)
3960               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3961             else if (REGNO (a) == REGNO (ops[0]))
3962               {
3963                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3964                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3965                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);