OSDN Git Service

* arm.md (movqi): On thumb when optimizing, handle loading from
[pf3gnuchains/gcc-fork.git] / gcc / config / arm / arm.md
1 ;;- Machine description for ARM for GNU compiler
2 ;;  Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;;  2001, 2002, 2003, 2004, 2005  Free Software Foundation, Inc.
4 ;;  Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
5 ;;  and Martin Simmons (@harleqn.co.uk).
6 ;;  More major hacks by Richard Earnshaw (rearnsha@arm.com).
7
8 ;; This file is part of GCC.
9
10 ;; GCC is free software; you can redistribute it and/or modify it
11 ;; under the terms of the GNU General Public License as published
12 ;; by the Free Software Foundation; either version 2, or (at your
13 ;; option) any later version.
14
15 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
16 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
18 ;; License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GCC; see the file COPYING.  If not, write to
22 ;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23 ;; Boston, MA 02110-1301, USA.
24
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26
27 \f
28 ;;---------------------------------------------------------------------------
29 ;; Constants
30
31 ;; Register numbers
32 (define_constants
33   [(R0_REGNUM        0)         ; First CORE register
34    (IP_REGNUM       12)         ; Scratch register
35    (SP_REGNUM       13)         ; Stack pointer
36    (LR_REGNUM       14)         ; Return address register
37    (PC_REGNUM       15)         ; Program counter
38    (CC_REGNUM       24)         ; Condition code pseudo register
39    (LAST_ARM_REGNUM 15)         ;
40    (FPA_F0_REGNUM   16)         ; FIRST_FPA_REGNUM
41    (FPA_F7_REGNUM   23)         ; LAST_FPA_REGNUM
42   ]
43 )
44 ;; 3rd operand to select_dominance_cc_mode
45 (define_constants
46   [(DOM_CC_X_AND_Y  0)
47    (DOM_CC_NX_OR_Y  1)
48    (DOM_CC_X_OR_Y   2)
49   ]
50 )
51
52 ;; UNSPEC Usage:
53 ;; Note: sin and cos are no-longer used.
54
55 (define_constants
56   [(UNSPEC_SIN       0) ; `sin' operation (MODE_FLOAT):
57                         ;   operand 0 is the result,
58                         ;   operand 1 the parameter.
59    (UNPSEC_COS       1) ; `cos' operation (MODE_FLOAT):
60                         ;   operand 0 is the result,
61                         ;   operand 1 the parameter.
62    (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
63                         ;   operand 0 is the first register,
64                         ;   subsequent registers are in parallel (use ...)
65                         ;   expressions.
66    (UNSPEC_PIC_SYM   3) ; A symbol that has been treated properly for pic
67                         ;   usage, that is, we will add the pic_register
68                         ;   value to it before trying to dereference it.
69    (UNSPEC_PIC_BASE  4) ; Adding the PC value to the offset to the
70                         ;   GLOBAL_OFFSET_TABLE.  The operation is fully
71                         ;   described by the RTL but must be wrapped to
72                         ;   prevent combine from trying to rip it apart.
73    (UNSPEC_PRLG_STK  5) ; A special barrier that prevents frame accesses 
74                         ;   being scheduled before the stack adjustment insn.
75    (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
76                         ; this unspec is used to prevent the deletion of
77                         ; instructions setting registers for EH handling
78                         ; and stack frame generation.  Operand 0 is the
79                         ; register to "use".
80    (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
81    (UNSPEC_WSHUFH    8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
82    (UNSPEC_WACC      9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
83    (UNSPEC_TMOVMSK  10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
84    (UNSPEC_WSAD     11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
85    (UNSPEC_WSADZ    12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
86    (UNSPEC_WMACS    13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
87    (UNSPEC_WMACU    14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
88    (UNSPEC_WMACSZ   15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
89    (UNSPEC_WMACUZ   16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
90    (UNSPEC_CLRDI    17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
91    (UNSPEC_WMADDS   18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
92    (UNSPEC_WMADDU   19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
93   ]
94 )
95
96 ;; UNSPEC_VOLATILE Usage:
97
98 (define_constants
99   [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
100                         ;   insn in the code.
101    (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
102                         ;   instruction epilogue sequence that isn't expanded
103                         ;   into normal RTL.  Used for both normal and sibcall
104                         ;   epilogues.
105    (VUNSPEC_ALIGN    2) ; `align' insn.  Used at the head of a minipool table 
106                         ;   for inlined constants.
107    (VUNSPEC_POOL_END 3) ; `end-of-table'.  Used to mark the end of a minipool
108                         ;   table.
109    (VUNSPEC_POOL_1   4) ; `pool-entry(1)'.  An entry in the constant pool for
110                         ;   an 8-bit object.
111    (VUNSPEC_POOL_2   5) ; `pool-entry(2)'.  An entry in the constant pool for
112                         ;   a 16-bit object.
113    (VUNSPEC_POOL_4   6) ; `pool-entry(4)'.  An entry in the constant pool for
114                         ;   a 32-bit object.
115    (VUNSPEC_POOL_8   7) ; `pool-entry(8)'.  An entry in the constant pool for
116                         ;   a 64-bit object.
117    (VUNSPEC_TMRC     8) ; Used by the iWMMXt TMRC instruction.
118    (VUNSPEC_TMCR     9) ; Used by the iWMMXt TMCR instruction.
119    (VUNSPEC_ALIGN8   10) ; 8-byte alignment version of VUNSPEC_ALIGN
120    (VUNSPEC_WCMP_EQ  11) ; Used by the iWMMXt WCMPEQ instructions
121    (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
122    (VUNSPEC_WCMP_GT  13) ; Used by the iwMMXT WCMPGT instructions
123    (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
124                          ; handling.
125   ]
126 )
127 \f
128 ;;---------------------------------------------------------------------------
129 ;; Attributes
130
131 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
132 ; generating ARM code.  This is used to control the length of some insn
133 ; patterns that share the same RTL in both ARM and Thumb code.
134 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
135
136 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
137 ; scheduling decisions for the load unit and the multiplier.
138 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_tune_strongarm")))
139
140 ; IS_XSCALE is set to 'yes' when compiling for XScale.
141 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
142
143 ;; Operand number of an input operand that is shifted.  Zero if the
144 ;; given instruction does not shift one of its input operands.
145 (define_attr "shift" "" (const_int 0))
146
147 ; Floating Point Unit.  If we only have floating point emulation, then there
148 ; is no point in scheduling the floating point insns.  (Well, for best
149 ; performance we should try and group them together).
150 (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
151   (const (symbol_ref "arm_fpu_attr")))
152
153 ; LENGTH of an instruction (in bytes)
154 (define_attr "length" "" (const_int 4))
155
156 ; POOL_RANGE is how far away from a constant pool entry that this insn
157 ; can be placed.  If the distance is zero, then this insn will never
158 ; reference the pool.
159 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
160 ; before its address.
161 (define_attr "pool_range" "" (const_int 0))
162 (define_attr "neg_pool_range" "" (const_int 0))
163
164 ; An assembler sequence may clobber the condition codes without us knowing.
165 ; If such an insn references the pool, then we have no way of knowing how,
166 ; so use the most conservative value for pool_range.
167 (define_asm_attributes
168  [(set_attr "conds" "clob")
169   (set_attr "length" "4")
170   (set_attr "pool_range" "250")])
171
172 ;; The instruction used to implement a particular pattern.  This
173 ;; information is used by pipeline descriptions to provide accurate
174 ;; scheduling information.
175
176 (define_attr "insn"
177         "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals,smlawy,smuad,smuadx,smlad,smladx,smusd,smusdx,smlsd,smlsdx,smmul,smmulr,other"
178         (const_string "other"))
179
180 ; TYPE attribute is used to detect floating point instructions which, if
181 ; running on a co-processor can run in parallel with other, basic instructions
182 ; If write-buffer scheduling is enabled then it can also be used in the
183 ; scheduling of writes.
184
185 ; Classification of each insn
186 ; alu           any alu  instruction that doesn't hit memory or fp
187 ;               regs or have a shifted source operand
188 ; alu_shift     any data instruction that doesn't hit memory or fp
189 ;               regs, but has a source operand shifted by a constant
190 ; alu_shift_reg any data instruction that doesn't hit memory or fp
191 ;               regs, but has a source operand shifted by a register value
192 ; mult          a multiply instruction
193 ; block         blockage insn, this blocks all functional units
194 ; float         a floating point arithmetic operation (subject to expansion)
195 ; fdivd         DFmode floating point division
196 ; fdivs         SFmode floating point division
197 ; fmul          Floating point multiply
198 ; ffmul         Fast floating point multiply
199 ; farith        Floating point arithmetic (4 cycle)
200 ; ffarith       Fast floating point arithmetic (2 cycle)
201 ; float_em      a floating point arithmetic operation that is normally emulated
202 ;               even on a machine with an fpa.
203 ; f_load        a floating point load from memory
204 ; f_store       a floating point store to memory
205 ; f_load[sd]    single/double load from memory
206 ; f_store[sd]   single/double store to memory
207 ; f_flag        a transfer of co-processor flags to the CPSR
208 ; f_mem_r       a transfer of a floating point register to a real reg via mem
209 ; r_mem_f       the reverse of f_mem_r
210 ; f_2_r         fast transfer float to arm (no memory needed)
211 ; r_2_f         fast transfer arm to float
212 ; f_cvt         convert floating<->integral
213 ; branch        a branch
214 ; call          a subroutine call
215 ; load_byte     load byte(s) from memory to arm registers
216 ; load1         load 1 word from memory to arm registers
217 ; load2         load 2 words from memory to arm registers
218 ; load3         load 3 words from memory to arm registers
219 ; load4         load 4 words from memory to arm registers
220 ; store         store 1 word to memory from arm registers
221 ; store2        store 2 words
222 ; store3        store 3 words
223 ; store4        store 4 (or more) words
224 ;  Additions for Cirrus Maverick co-processor:
225 ; mav_farith    Floating point arithmetic (4 cycle)
226 ; mav_dmult     Double multiplies (7 cycle)
227 ;
228 (define_attr "type"
229         "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,f_flag,float_em,f_load,f_store,f_loads,f_loadd,f_stores,f_stored,f_mem_r,r_mem_f,f_2_r,r_2_f,f_cvt,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult" 
230         (if_then_else 
231          (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
232          (const_string "mult")
233          (const_string "alu")))
234
235 ; Load scheduling, set from the arm_ld_sched variable
236 ; initialized by arm_override_options() 
237 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
238
239 ; condition codes: this one is used by final_prescan_insn to speed up
240 ; conditionalizing instructions.  It saves having to scan the rtl to see if
241 ; it uses or alters the condition codes.
242
243 ; USE means that the condition codes are used by the insn in the process of
244 ;   outputting code, this means (at present) that we can't use the insn in
245 ;   inlined branches
246 ;
247 ; SET means that the purpose of the insn is to set the condition codes in a
248 ;   well defined manner.
249 ;
250 ; CLOB means that the condition codes are altered in an undefined manner, if
251 ;   they are altered at all
252 ;
253 ; JUMP_CLOB is used when the condition cannot be represented by a single
254 ;   instruction (UNEQ and LTGT).  These cannot be predicated.
255 ;
256 ; NOCOND means that the condition codes are neither altered nor affect the
257 ;   output of this insn
258
259 (define_attr "conds" "use,set,clob,jump_clob,nocond"
260         (if_then_else (eq_attr "type" "call")
261          (const_string "clob")
262          (const_string "nocond")))
263
264 ; Predicable means that the insn can be conditionally executed based on
265 ; an automatically added predicate (additional patterns are generated by 
266 ; gen...).  We default to 'no' because no Thumb patterns match this rule
267 ; and not all ARM patterns do.
268 (define_attr "predicable" "no,yes" (const_string "no"))
269
270 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
271 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
272 ; suffer blockages enough to warrant modelling this (and it can adversely
273 ; affect the schedule).
274 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
275
276 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
277 ; to stall the processor.  Used with model_wbuf above.
278 (define_attr "write_conflict" "no,yes"
279   (if_then_else (eq_attr "type"
280                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
281                 (const_string "yes")
282                 (const_string "no")))
283
284 ; Classify the insns into those that take one cycle and those that take more
285 ; than one on the main cpu execution unit.
286 (define_attr "core_cycles" "single,multi"
287   (if_then_else (eq_attr "type"
288                  "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
289                 (const_string "single")
290                 (const_string "multi")))
291
292 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
293 ;; distant label.  Only applicable to Thumb code.
294 (define_attr "far_jump" "yes,no" (const_string "no"))
295
296
297 ;;---------------------------------------------------------------------------
298 ;; Mode macros
299
300 ; A list of modes that are exactly 64 bits in size.  We use this to expand
301 ; some splits that are the same for all modes when operating on ARM 
302 ; registers.
303 (define_mode_macro ANY64 [DI DF V8QI V4HI V2SI V2SF])
304
305 ;;---------------------------------------------------------------------------
306 ;; Predicates
307
308 (include "predicates.md")
309
310 ;;---------------------------------------------------------------------------
311 ;; Pipeline descriptions
312
313 ;; Processor type.  This is created automatically from arm-cores.def.
314 (include "arm-tune.md")
315
316 ;; True if the generic scheduling description should be used.
317
318 (define_attr "generic_sched" "yes,no"
319   (const (if_then_else 
320           (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs") 
321           (const_string "no")
322           (const_string "yes"))))
323
324 (define_attr "generic_vfp" "yes,no"
325   (const (if_then_else
326           (and (eq_attr "fpu" "vfp")
327                (eq_attr "tune" "!arm1020e,arm1022e"))
328           (const_string "yes")
329           (const_string "no"))))
330
331 (include "arm-generic.md")
332 (include "arm926ejs.md")
333 (include "arm1020e.md")
334 (include "arm1026ejs.md")
335 (include "arm1136jfs.md")
336
337 \f
338 ;;---------------------------------------------------------------------------
339 ;; Insn patterns
340 ;;
341 ;; Addition insns.
342
343 ;; Note: For DImode insns, there is normally no reason why operands should
344 ;; not be in the same register, what we don't want is for something being
345 ;; written to partially overlap something that is an input.
346 ;; Cirrus 64bit additions should not be split because we have a native
347 ;; 64bit addition instructions.
348
349 (define_expand "adddi3"
350  [(parallel
351    [(set (match_operand:DI           0 "s_register_operand" "")
352           (plus:DI (match_operand:DI 1 "s_register_operand" "")
353                    (match_operand:DI 2 "s_register_operand" "")))
354     (clobber (reg:CC CC_REGNUM))])]
355   "TARGET_EITHER"
356   "
357   if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
358     {
359       if (!cirrus_fp_register (operands[0], DImode))
360         operands[0] = force_reg (DImode, operands[0]);
361       if (!cirrus_fp_register (operands[1], DImode))
362         operands[1] = force_reg (DImode, operands[1]);
363       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
364       DONE;
365     }
366
367   if (TARGET_THUMB)
368     {
369       if (GET_CODE (operands[1]) != REG)
370         operands[1] = force_reg (SImode, operands[1]);
371       if (GET_CODE (operands[2]) != REG)
372         operands[2] = force_reg (SImode, operands[2]);
373      }
374   "
375 )
376
377 (define_insn "*thumb_adddi3"
378   [(set (match_operand:DI          0 "register_operand" "=l")
379         (plus:DI (match_operand:DI 1 "register_operand" "%0")
380                  (match_operand:DI 2 "register_operand" "l")))
381    (clobber (reg:CC CC_REGNUM))
382   ]
383   "TARGET_THUMB"
384   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
385   [(set_attr "length" "4")]
386 )
387
388 (define_insn_and_split "*arm_adddi3"
389   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
390         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
391                  (match_operand:DI 2 "s_register_operand" "r,  0")))
392    (clobber (reg:CC CC_REGNUM))]
393   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
394   "#"
395   "TARGET_ARM && reload_completed"
396   [(parallel [(set (reg:CC_C CC_REGNUM)
397                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
398                                  (match_dup 1)))
399               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
400    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
401                                (plus:SI (match_dup 4) (match_dup 5))))]
402   "
403   {
404     operands[3] = gen_highpart (SImode, operands[0]);
405     operands[0] = gen_lowpart (SImode, operands[0]);
406     operands[4] = gen_highpart (SImode, operands[1]);
407     operands[1] = gen_lowpart (SImode, operands[1]);
408     operands[5] = gen_highpart (SImode, operands[2]);
409     operands[2] = gen_lowpart (SImode, operands[2]);
410   }"
411   [(set_attr "conds" "clob")
412    (set_attr "length" "8")]
413 )
414
415 (define_insn_and_split "*adddi_sesidi_di"
416   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
417         (plus:DI (sign_extend:DI
418                   (match_operand:SI 2 "s_register_operand" "r,r"))
419                  (match_operand:DI 1 "s_register_operand" "r,0")))
420    (clobber (reg:CC CC_REGNUM))]
421   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
422   "#"
423   "TARGET_ARM && reload_completed"
424   [(parallel [(set (reg:CC_C CC_REGNUM)
425                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
426                                  (match_dup 1)))
427               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
428    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
429                                (plus:SI (ashiftrt:SI (match_dup 2)
430                                                      (const_int 31))
431                                         (match_dup 4))))]
432   "
433   {
434     operands[3] = gen_highpart (SImode, operands[0]);
435     operands[0] = gen_lowpart (SImode, operands[0]);
436     operands[4] = gen_highpart (SImode, operands[1]);
437     operands[1] = gen_lowpart (SImode, operands[1]);
438     operands[2] = gen_lowpart (SImode, operands[2]);
439   }"
440   [(set_attr "conds" "clob")
441    (set_attr "length" "8")]
442 )
443
444 (define_insn_and_split "*adddi_zesidi_di"
445   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
446         (plus:DI (zero_extend:DI
447                   (match_operand:SI 2 "s_register_operand" "r,r"))
448                  (match_operand:DI 1 "s_register_operand" "r,0")))
449    (clobber (reg:CC CC_REGNUM))]
450   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
451   "#"
452   "TARGET_ARM && reload_completed"
453   [(parallel [(set (reg:CC_C CC_REGNUM)
454                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
455                                  (match_dup 1)))
456               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
457    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
458                                (plus:SI (match_dup 4) (const_int 0))))]
459   "
460   {
461     operands[3] = gen_highpart (SImode, operands[0]);
462     operands[0] = gen_lowpart (SImode, operands[0]);
463     operands[4] = gen_highpart (SImode, operands[1]);
464     operands[1] = gen_lowpart (SImode, operands[1]);
465     operands[2] = gen_lowpart (SImode, operands[2]);
466   }"
467   [(set_attr "conds" "clob")
468    (set_attr "length" "8")]
469 )
470
471 (define_expand "addsi3"
472   [(set (match_operand:SI          0 "s_register_operand" "")
473         (plus:SI (match_operand:SI 1 "s_register_operand" "")
474                  (match_operand:SI 2 "reg_or_int_operand" "")))]
475   "TARGET_EITHER"
476   "
477   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
478     {
479       arm_split_constant (PLUS, SImode, NULL_RTX,
480                           INTVAL (operands[2]), operands[0], operands[1],
481                           optimize && !no_new_pseudos);
482       DONE;
483     }
484   "
485 )
486
487 ; If there is a scratch available, this will be faster than synthesizing the
488 ; addition.
489 (define_peephole2
490   [(match_scratch:SI 3 "r")
491    (set (match_operand:SI          0 "arm_general_register_operand" "")
492         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
493                  (match_operand:SI 2 "const_int_operand"  "")))]
494   "TARGET_ARM &&
495    !(const_ok_for_arm (INTVAL (operands[2]))
496      || const_ok_for_arm (-INTVAL (operands[2])))
497     && const_ok_for_arm (~INTVAL (operands[2]))"
498   [(set (match_dup 3) (match_dup 2))
499    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
500   ""
501 )
502
503 (define_insn_and_split "*arm_addsi3"
504   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
505         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
506                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
507   "TARGET_ARM"
508   "@
509    add%?\\t%0, %1, %2
510    sub%?\\t%0, %1, #%n2
511    #"
512   "TARGET_ARM &&
513    GET_CODE (operands[2]) == CONST_INT
514    && !(const_ok_for_arm (INTVAL (operands[2]))
515         || const_ok_for_arm (-INTVAL (operands[2])))"
516   [(clobber (const_int 0))]
517   "
518   arm_split_constant (PLUS, SImode, curr_insn,
519                       INTVAL (operands[2]), operands[0],
520                       operands[1], 0);
521   DONE;
522   "
523   [(set_attr "length" "4,4,16")
524    (set_attr "predicable" "yes")]
525 )
526
527 ;; Register group 'k' is a single register group containing only the stack
528 ;; register.  Trying to reload it will always fail catastrophically,
529 ;; so never allow those alternatives to match if reloading is needed.
530
531 (define_insn "*thumb_addsi3"
532   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
533         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
534                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
535   "TARGET_THUMB"
536   "*
537    static const char * const asms[] = 
538    {
539      \"add\\t%0, %0, %2\",
540      \"sub\\t%0, %0, #%n2\",
541      \"add\\t%0, %1, %2\",
542      \"add\\t%0, %0, %2\",
543      \"add\\t%0, %0, %2\",
544      \"add\\t%0, %1, %2\",
545      \"add\\t%0, %1, %2\"
546    };
547    if ((which_alternative == 2 || which_alternative == 6)
548        && GET_CODE (operands[2]) == CONST_INT
549        && INTVAL (operands[2]) < 0)
550      return \"sub\\t%0, %1, #%n2\";
551    return asms[which_alternative];
552   "
553   [(set_attr "length" "2")]
554 )
555
556 ;; Reloading and elimination of the frame pointer can
557 ;; sometimes cause this optimization to be missed.
558 (define_peephole2
559   [(set (match_operand:SI 0 "arm_general_register_operand" "")
560         (match_operand:SI 1 "const_int_operand" ""))
561    (set (match_dup 0)
562         (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
563   "TARGET_THUMB
564    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
565    && (INTVAL (operands[1]) & 3) == 0"
566   [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
567   ""
568 )
569
570 (define_insn "*addsi3_compare0"
571   [(set (reg:CC_NOOV CC_REGNUM)
572         (compare:CC_NOOV
573          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
574                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
575          (const_int 0)))
576    (set (match_operand:SI 0 "s_register_operand" "=r,r")
577         (plus:SI (match_dup 1) (match_dup 2)))]
578   "TARGET_ARM"
579   "@
580    add%?s\\t%0, %1, %2
581    sub%?s\\t%0, %1, #%n2"
582   [(set_attr "conds" "set")]
583 )
584
585 (define_insn "*addsi3_compare0_scratch"
586   [(set (reg:CC_NOOV CC_REGNUM)
587         (compare:CC_NOOV
588          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
589                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
590          (const_int 0)))]
591   "TARGET_ARM"
592   "@
593    cmn%?\\t%0, %1
594    cmp%?\\t%0, #%n1"
595   [(set_attr "conds" "set")]
596 )
597
598 (define_insn "*compare_negsi_si"
599   [(set (reg:CC_Z CC_REGNUM)
600         (compare:CC_Z
601          (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
602          (match_operand:SI 1 "s_register_operand" "r")))]
603   "TARGET_ARM"
604   "cmn%?\\t%1, %0"
605   [(set_attr "conds" "set")]
606 )
607
608 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
609 ;; addend is a constant.
610 (define_insn "*cmpsi2_addneg"
611   [(set (reg:CC CC_REGNUM)
612         (compare:CC
613          (match_operand:SI 1 "s_register_operand" "r,r")
614          (match_operand:SI 2 "arm_addimm_operand" "I,L")))
615    (set (match_operand:SI 0 "s_register_operand" "=r,r")
616         (plus:SI (match_dup 1)
617                  (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
618   "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
619   "@
620    sub%?s\\t%0, %1, %2
621    add%?s\\t%0, %1, #%n2"
622   [(set_attr "conds" "set")]
623 )
624
625 ;; Convert the sequence
626 ;;  sub  rd, rn, #1
627 ;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
628 ;;  bne  dest
629 ;; into
630 ;;  subs rd, rn, #1
631 ;;  bcs  dest   ((unsigned)rn >= 1)
632 ;; similarly for the beq variant using bcc.
633 ;; This is a common looping idiom (while (n--))
634 (define_peephole2
635   [(set (match_operand:SI 0 "arm_general_register_operand" "")
636         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
637                  (const_int -1)))
638    (set (match_operand 2 "cc_register" "")
639         (compare (match_dup 0) (const_int -1)))
640    (set (pc)
641         (if_then_else (match_operator 3 "equality_operator"
642                        [(match_dup 2) (const_int 0)])
643                       (match_operand 4 "" "")
644                       (match_operand 5 "" "")))]
645   "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
646   [(parallel[
647     (set (match_dup 2)
648          (compare:CC
649           (match_dup 1) (const_int 1)))
650     (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
651    (set (pc)
652         (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
653                       (match_dup 4)
654                       (match_dup 5)))]
655   "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
656    operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
657                                   ? GEU : LTU),
658                                  VOIDmode, 
659                                  operands[2], const0_rtx);"
660 )
661
662 ;; The next four insns work because they compare the result with one of
663 ;; the operands, and we know that the use of the condition code is
664 ;; either GEU or LTU, so we can use the carry flag from the addition
665 ;; instead of doing the compare a second time.
666 (define_insn "*addsi3_compare_op1"
667   [(set (reg:CC_C CC_REGNUM)
668         (compare:CC_C
669          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
670                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
671          (match_dup 1)))
672    (set (match_operand:SI 0 "s_register_operand" "=r,r")
673         (plus:SI (match_dup 1) (match_dup 2)))]
674   "TARGET_ARM"
675   "@
676    add%?s\\t%0, %1, %2
677    sub%?s\\t%0, %1, #%n2"
678   [(set_attr "conds" "set")]
679 )
680
681 (define_insn "*addsi3_compare_op2"
682   [(set (reg:CC_C CC_REGNUM)
683         (compare:CC_C
684          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
685                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
686          (match_dup 2)))
687    (set (match_operand:SI 0 "s_register_operand" "=r,r")
688         (plus:SI (match_dup 1) (match_dup 2)))]
689   "TARGET_ARM"
690   "@
691    add%?s\\t%0, %1, %2
692    sub%?s\\t%0, %1, #%n2"
693   [(set_attr "conds" "set")]
694 )
695
696 (define_insn "*compare_addsi2_op0"
697   [(set (reg:CC_C CC_REGNUM)
698         (compare:CC_C
699          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
700                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
701          (match_dup 0)))]
702   "TARGET_ARM"
703   "@
704    cmn%?\\t%0, %1
705    cmp%?\\t%0, #%n1"
706   [(set_attr "conds" "set")]
707 )
708
709 (define_insn "*compare_addsi2_op1"
710   [(set (reg:CC_C CC_REGNUM)
711         (compare:CC_C
712          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
713                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
714          (match_dup 1)))]
715   "TARGET_ARM"
716   "@
717    cmn%?\\t%0, %1
718    cmp%?\\t%0, #%n1"
719   [(set_attr "conds" "set")]
720 )
721
722 (define_insn "*addsi3_carryin"
723   [(set (match_operand:SI 0 "s_register_operand" "=r")
724         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
725                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
726                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
727   "TARGET_ARM"
728   "adc%?\\t%0, %1, %2"
729   [(set_attr "conds" "use")]
730 )
731
732 (define_insn "*addsi3_carryin_shift"
733   [(set (match_operand:SI 0 "s_register_operand" "=r")
734         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
735                  (plus:SI
736                    (match_operator:SI 2 "shift_operator"
737                       [(match_operand:SI 3 "s_register_operand" "r")
738                        (match_operand:SI 4 "reg_or_int_operand" "rM")])
739                     (match_operand:SI 1 "s_register_operand" "r"))))]
740   "TARGET_ARM"
741   "adc%?\\t%0, %1, %3%S2"
742   [(set_attr "conds" "use")
743    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
744                       (const_string "alu_shift")
745                       (const_string "alu_shift_reg")))]
746 )
747
748 (define_insn "*addsi3_carryin_alt1"
749   [(set (match_operand:SI 0 "s_register_operand" "=r")
750         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
751                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
752                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
753   "TARGET_ARM"
754   "adc%?\\t%0, %1, %2"
755   [(set_attr "conds" "use")]
756 )
757
758 (define_insn "*addsi3_carryin_alt2"
759   [(set (match_operand:SI 0 "s_register_operand" "=r")
760         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
761                           (match_operand:SI 1 "s_register_operand" "r"))
762                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
763   "TARGET_ARM"
764   "adc%?\\t%0, %1, %2"
765   [(set_attr "conds" "use")]
766 )
767
768 (define_insn "*addsi3_carryin_alt3"
769   [(set (match_operand:SI 0 "s_register_operand" "=r")
770         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
771                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
772                  (match_operand:SI 1 "s_register_operand" "r")))]
773   "TARGET_ARM"
774   "adc%?\\t%0, %1, %2"
775   [(set_attr "conds" "use")]
776 )
777
778 (define_insn "incscc"
779   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
780         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
781                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
782                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
783   "TARGET_ARM"
784   "@
785   add%d2\\t%0, %1, #1
786   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
787   [(set_attr "conds" "use")
788    (set_attr "length" "4,8")]
789 )
790
791 ; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
792 (define_split
793   [(set (match_operand:SI 0 "s_register_operand" "")
794         (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
795                             (match_operand:SI 2 "s_register_operand" ""))
796                  (const_int -1)))
797    (clobber (match_operand:SI 3 "s_register_operand" ""))]
798   "TARGET_ARM"
799   [(set (match_dup 3) (match_dup 1))
800    (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
801   "
802   operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
803 ")
804
805 (define_expand "addsf3"
806   [(set (match_operand:SF          0 "s_register_operand" "")
807         (plus:SF (match_operand:SF 1 "s_register_operand" "")
808                  (match_operand:SF 2 "arm_float_add_operand" "")))]
809   "TARGET_ARM && TARGET_HARD_FLOAT"
810   "
811   if (TARGET_MAVERICK
812       && !cirrus_fp_register (operands[2], SFmode))
813     operands[2] = force_reg (SFmode, operands[2]);
814 ")
815
816 (define_expand "adddf3"
817   [(set (match_operand:DF          0 "s_register_operand" "")
818         (plus:DF (match_operand:DF 1 "s_register_operand" "")
819                  (match_operand:DF 2 "arm_float_add_operand" "")))]
820   "TARGET_ARM && TARGET_HARD_FLOAT"
821   "
822   if (TARGET_MAVERICK
823       && !cirrus_fp_register (operands[2], DFmode))
824     operands[2] = force_reg (DFmode, operands[2]);
825 ")
826
827 (define_expand "subdi3"
828  [(parallel
829    [(set (match_operand:DI            0 "s_register_operand" "")
830           (minus:DI (match_operand:DI 1 "s_register_operand" "")
831                     (match_operand:DI 2 "s_register_operand" "")))
832     (clobber (reg:CC CC_REGNUM))])]
833   "TARGET_EITHER"
834   "
835   if (TARGET_HARD_FLOAT && TARGET_MAVERICK
836       && TARGET_ARM
837       && cirrus_fp_register (operands[0], DImode)
838       && cirrus_fp_register (operands[1], DImode))
839     {
840       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
841       DONE;
842     }
843
844   if (TARGET_THUMB)
845     {
846       if (GET_CODE (operands[1]) != REG)
847         operands[1] = force_reg (SImode, operands[1]);
848       if (GET_CODE (operands[2]) != REG)
849         operands[2] = force_reg (SImode, operands[2]);
850      }  
851   "
852 )
853
854 (define_insn "*arm_subdi3"
855   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
856         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
857                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
858    (clobber (reg:CC CC_REGNUM))]
859   "TARGET_ARM"
860   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
861   [(set_attr "conds" "clob")
862    (set_attr "length" "8")]
863 )
864
865 (define_insn "*thumb_subdi3"
866   [(set (match_operand:DI           0 "register_operand" "=l")
867         (minus:DI (match_operand:DI 1 "register_operand"  "0")
868                   (match_operand:DI 2 "register_operand"  "l")))
869    (clobber (reg:CC CC_REGNUM))]
870   "TARGET_THUMB"
871   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
872   [(set_attr "length" "4")]
873 )
874
875 (define_insn "*subdi_di_zesidi"
876   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
877         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
878                   (zero_extend:DI
879                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
880    (clobber (reg:CC CC_REGNUM))]
881   "TARGET_ARM"
882   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
883   [(set_attr "conds" "clob")
884    (set_attr "length" "8")]
885 )
886
887 (define_insn "*subdi_di_sesidi"
888   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
889         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
890                   (sign_extend:DI
891                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
892    (clobber (reg:CC CC_REGNUM))]
893   "TARGET_ARM"
894   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
895   [(set_attr "conds" "clob")
896    (set_attr "length" "8")]
897 )
898
899 (define_insn "*subdi_zesidi_di"
900   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
901         (minus:DI (zero_extend:DI
902                    (match_operand:SI 2 "s_register_operand"  "r,r"))
903                   (match_operand:DI  1 "s_register_operand" "?r,0")))
904    (clobber (reg:CC CC_REGNUM))]
905   "TARGET_ARM"
906   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
907   [(set_attr "conds" "clob")
908    (set_attr "length" "8")]
909 )
910
911 (define_insn "*subdi_sesidi_di"
912   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
913         (minus:DI (sign_extend:DI
914                    (match_operand:SI 2 "s_register_operand"   "r,r"))
915                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
916    (clobber (reg:CC CC_REGNUM))]
917   "TARGET_ARM"
918   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
919   [(set_attr "conds" "clob")
920    (set_attr "length" "8")]
921 )
922
923 (define_insn "*subdi_zesidi_zesidi"
924   [(set (match_operand:DI            0 "s_register_operand" "=r")
925         (minus:DI (zero_extend:DI
926                    (match_operand:SI 1 "s_register_operand"  "r"))
927                   (zero_extend:DI
928                    (match_operand:SI 2 "s_register_operand"  "r"))))
929    (clobber (reg:CC CC_REGNUM))]
930   "TARGET_ARM"
931   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
932   [(set_attr "conds" "clob")
933    (set_attr "length" "8")]
934 )
935
936 (define_expand "subsi3"
937   [(set (match_operand:SI           0 "s_register_operand" "")
938         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
939                   (match_operand:SI 2 "s_register_operand" "")))]
940   "TARGET_EITHER"
941   "
942   if (GET_CODE (operands[1]) == CONST_INT)
943     {
944       if (TARGET_ARM)
945         {
946           arm_split_constant (MINUS, SImode, NULL_RTX,
947                               INTVAL (operands[1]), operands[0],
948                               operands[2], optimize && !no_new_pseudos);
949           DONE;
950         }
951       else /* TARGET_THUMB */
952         operands[1] = force_reg (SImode, operands[1]);
953     }
954   "
955 )
956
957 (define_insn "*thumb_subsi3_insn"
958   [(set (match_operand:SI           0 "register_operand" "=l")
959         (minus:SI (match_operand:SI 1 "register_operand" "l")
960                   (match_operand:SI 2 "register_operand" "l")))]
961   "TARGET_THUMB"
962   "sub\\t%0, %1, %2"
963   [(set_attr "length" "2")]
964 )
965
966 (define_insn_and_split "*arm_subsi3_insn"
967   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
968         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
969                   (match_operand:SI 2 "s_register_operand" "r,r")))]
970   "TARGET_ARM"
971   "@
972    rsb%?\\t%0, %2, %1
973    #"
974   "TARGET_ARM
975    && GET_CODE (operands[1]) == CONST_INT
976    && !const_ok_for_arm (INTVAL (operands[1]))"
977   [(clobber (const_int 0))]
978   "
979   arm_split_constant (MINUS, SImode, curr_insn,
980                       INTVAL (operands[1]), operands[0], operands[2], 0);
981   DONE;
982   "
983   [(set_attr "length" "4,16")
984    (set_attr "predicable" "yes")]
985 )
986
987 (define_peephole2
988   [(match_scratch:SI 3 "r")
989    (set (match_operand:SI 0 "arm_general_register_operand" "")
990         (minus:SI (match_operand:SI 1 "const_int_operand" "")
991                   (match_operand:SI 2 "arm_general_register_operand" "")))]
992   "TARGET_ARM
993    && !const_ok_for_arm (INTVAL (operands[1]))
994    && const_ok_for_arm (~INTVAL (operands[1]))"
995   [(set (match_dup 3) (match_dup 1))
996    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
997   ""
998 )
999
1000 (define_insn "*subsi3_compare0"
1001   [(set (reg:CC_NOOV CC_REGNUM)
1002         (compare:CC_NOOV
1003          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1004                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1005          (const_int 0)))
1006    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1007         (minus:SI (match_dup 1) (match_dup 2)))]
1008   "TARGET_ARM"
1009   "@
1010    sub%?s\\t%0, %1, %2
1011    rsb%?s\\t%0, %2, %1"
1012   [(set_attr "conds" "set")]
1013 )
1014
1015 (define_insn "decscc"
1016   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1017         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1018                   (match_operator:SI 2 "arm_comparison_operator"
1019                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1020   "TARGET_ARM"
1021   "@
1022    sub%d2\\t%0, %1, #1
1023    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1024   [(set_attr "conds" "use")
1025    (set_attr "length" "*,8")]
1026 )
1027
1028 (define_expand "subsf3"
1029   [(set (match_operand:SF           0 "s_register_operand" "")
1030         (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1031                   (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1032   "TARGET_ARM && TARGET_HARD_FLOAT"
1033   "
1034   if (TARGET_MAVERICK)
1035     {
1036       if (!cirrus_fp_register (operands[1], SFmode))
1037         operands[1] = force_reg (SFmode, operands[1]);
1038       if (!cirrus_fp_register (operands[2], SFmode))
1039         operands[2] = force_reg (SFmode, operands[2]);
1040     }
1041 ")
1042
1043 (define_expand "subdf3"
1044   [(set (match_operand:DF           0 "s_register_operand" "")
1045         (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1046                   (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1047   "TARGET_ARM && TARGET_HARD_FLOAT"
1048   "
1049   if (TARGET_MAVERICK)
1050     {
1051        if (!cirrus_fp_register (operands[1], DFmode))
1052          operands[1] = force_reg (DFmode, operands[1]);
1053        if (!cirrus_fp_register (operands[2], DFmode))
1054          operands[2] = force_reg (DFmode, operands[2]);
1055     }
1056 ")
1057
1058 \f
1059 ;; Multiplication insns
1060
1061 (define_expand "mulsi3"
1062   [(set (match_operand:SI          0 "s_register_operand" "")
1063         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1064                  (match_operand:SI 1 "s_register_operand" "")))]
1065   "TARGET_EITHER"
1066   ""
1067 )
1068
1069 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1070 (define_insn "*arm_mulsi3"
1071   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1072         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1073                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1074   "TARGET_ARM"
1075   "mul%?\\t%0, %2, %1"
1076   [(set_attr "insn" "mul")
1077    (set_attr "predicable" "yes")]
1078 )
1079
1080 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1081 ; 1 and 2; are the same, because reload will make operand 0 match 
1082 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1083 ; this by adding another alternative to match this case, and then `reload' 
1084 ; it ourselves.  This alternative must come first.
1085 (define_insn "*thumb_mulsi3"
1086   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1087         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1088                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1089   "TARGET_THUMB"
1090   "*
1091   if (which_alternative < 2)
1092     return \"mov\\t%0, %1\;mul\\t%0, %2\";
1093   else
1094     return \"mul\\t%0, %2\";
1095   "
1096   [(set_attr "length" "4,4,2")
1097    (set_attr "insn" "mul")]
1098 )
1099
1100 (define_insn "*mulsi3_compare0"
1101   [(set (reg:CC_NOOV CC_REGNUM)
1102         (compare:CC_NOOV (mult:SI
1103                           (match_operand:SI 2 "s_register_operand" "r,r")
1104                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1105                          (const_int 0)))
1106    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1107         (mult:SI (match_dup 2) (match_dup 1)))]
1108   "TARGET_ARM"
1109   "mul%?s\\t%0, %2, %1"
1110   [(set_attr "conds" "set")
1111    (set_attr "insn" "muls")]
1112 )
1113
1114 (define_insn "*mulsi_compare0_scratch"
1115   [(set (reg:CC_NOOV CC_REGNUM)
1116         (compare:CC_NOOV (mult:SI
1117                           (match_operand:SI 2 "s_register_operand" "r,r")
1118                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1119                          (const_int 0)))
1120    (clobber (match_scratch:SI 0 "=&r,&r"))]
1121   "TARGET_ARM"
1122   "mul%?s\\t%0, %2, %1"
1123   [(set_attr "conds" "set")
1124    (set_attr "insn" "muls")]
1125 )
1126
1127 ;; Unnamed templates to match MLA instruction.
1128
1129 (define_insn "*mulsi3addsi"
1130   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1131         (plus:SI
1132           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1133                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1134           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1135   "TARGET_ARM"
1136   "mla%?\\t%0, %2, %1, %3"
1137   [(set_attr "insn" "mla")
1138    (set_attr "predicable" "yes")]
1139 )
1140
1141 (define_insn "*mulsi3addsi_compare0"
1142   [(set (reg:CC_NOOV CC_REGNUM)
1143         (compare:CC_NOOV
1144          (plus:SI (mult:SI
1145                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1146                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1147                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1148          (const_int 0)))
1149    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1150         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1151                  (match_dup 3)))]
1152   "TARGET_ARM"
1153   "mla%?s\\t%0, %2, %1, %3"
1154   [(set_attr "conds" "set")
1155    (set_attr "insn" "mlas")]
1156 )
1157
1158 (define_insn "*mulsi3addsi_compare0_scratch"
1159   [(set (reg:CC_NOOV CC_REGNUM)
1160         (compare:CC_NOOV
1161          (plus:SI (mult:SI
1162                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1163                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1164                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1165          (const_int 0)))
1166    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1167   "TARGET_ARM"
1168   "mla%?s\\t%0, %2, %1, %3"
1169   [(set_attr "conds" "set")
1170    (set_attr "insn" "mlas")]
1171 )
1172
1173 ;; Unnamed template to match long long multiply-accumulate (smlal)
1174
1175 (define_insn "*mulsidi3adddi"
1176   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1177         (plus:DI
1178          (mult:DI
1179           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1180           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1181          (match_operand:DI 1 "s_register_operand" "0")))]
1182   "TARGET_ARM && arm_arch3m"
1183   "smlal%?\\t%Q0, %R0, %3, %2"
1184   [(set_attr "insn" "smlal")
1185    (set_attr "predicable" "yes")]
1186 )
1187
1188 (define_insn "mulsidi3"
1189   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1190         (mult:DI
1191          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1192          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1193   "TARGET_ARM && arm_arch3m"
1194   "smull%?\\t%Q0, %R0, %1, %2"
1195   [(set_attr "insn" "smull")
1196    (set_attr "predicable" "yes")]
1197 )
1198
1199 (define_insn "umulsidi3"
1200   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1201         (mult:DI
1202          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1203          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1204   "TARGET_ARM && arm_arch3m"
1205   "umull%?\\t%Q0, %R0, %1, %2"
1206   [(set_attr "insn" "umull")
1207    (set_attr "predicable" "yes")]
1208 )
1209
1210 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1211
1212 (define_insn "*umulsidi3adddi"
1213   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1214         (plus:DI
1215          (mult:DI
1216           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1217           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1218          (match_operand:DI 1 "s_register_operand" "0")))]
1219   "TARGET_ARM && arm_arch3m"
1220   "umlal%?\\t%Q0, %R0, %3, %2"
1221   [(set_attr "insn" "umlal")
1222    (set_attr "predicable" "yes")]
1223 )
1224
1225 (define_insn "smulsi3_highpart"
1226   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1227         (truncate:SI
1228          (lshiftrt:DI
1229           (mult:DI
1230            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1231            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1232           (const_int 32))))
1233    (clobber (match_scratch:SI 3 "=&r,&r"))]
1234   "TARGET_ARM && arm_arch3m"
1235   "smull%?\\t%3, %0, %2, %1"
1236   [(set_attr "insn" "smull")
1237    (set_attr "predicable" "yes")]
1238 )
1239
1240 (define_insn "umulsi3_highpart"
1241   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1242         (truncate:SI
1243          (lshiftrt:DI
1244           (mult:DI
1245            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1246            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1247           (const_int 32))))
1248    (clobber (match_scratch:SI 3 "=&r,&r"))]
1249   "TARGET_ARM && arm_arch3m"
1250   "umull%?\\t%3, %0, %2, %1"
1251   [(set_attr "insn" "umull")
1252    (set_attr "predicable" "yes")]
1253 )
1254
1255 (define_insn "mulhisi3"
1256   [(set (match_operand:SI 0 "s_register_operand" "=r")
1257         (mult:SI (sign_extend:SI
1258                   (match_operand:HI 1 "s_register_operand" "%r"))
1259                  (sign_extend:SI
1260                   (match_operand:HI 2 "s_register_operand" "r"))))]
1261   "TARGET_ARM && arm_arch5e"
1262   "smulbb%?\\t%0, %1, %2"
1263   [(set_attr "insn" "smulxy")
1264    (set_attr "predicable" "yes")]
1265 )
1266
1267 (define_insn "*mulhisi3tb"
1268   [(set (match_operand:SI 0 "s_register_operand" "=r")
1269         (mult:SI (ashiftrt:SI
1270                   (match_operand:SI 1 "s_register_operand" "r")
1271                   (const_int 16))
1272                  (sign_extend:SI
1273                   (match_operand:HI 2 "s_register_operand" "r"))))]
1274   "TARGET_ARM && arm_arch5e"
1275   "smultb%?\\t%0, %1, %2"
1276   [(set_attr "insn" "smulxy")
1277    (set_attr "predicable" "yes")]
1278 )
1279
1280 (define_insn "*mulhisi3bt"
1281   [(set (match_operand:SI 0 "s_register_operand" "=r")
1282         (mult:SI (sign_extend:SI
1283                   (match_operand:HI 1 "s_register_operand" "r"))
1284                  (ashiftrt:SI
1285                   (match_operand:SI 2 "s_register_operand" "r")
1286                   (const_int 16))))]
1287   "TARGET_ARM && arm_arch5e"
1288   "smulbt%?\\t%0, %1, %2"
1289   [(set_attr "insn" "smulxy")
1290    (set_attr "predicable" "yes")]
1291 )
1292
1293 (define_insn "*mulhisi3tt"
1294   [(set (match_operand:SI 0 "s_register_operand" "=r")
1295         (mult:SI (ashiftrt:SI
1296                   (match_operand:SI 1 "s_register_operand" "r")
1297                   (const_int 16))
1298                  (ashiftrt:SI
1299                   (match_operand:SI 2 "s_register_operand" "r")
1300                   (const_int 16))))]
1301   "TARGET_ARM && arm_arch5e"
1302   "smultt%?\\t%0, %1, %2"
1303   [(set_attr "insn" "smulxy")
1304    (set_attr "predicable" "yes")]
1305 )
1306
1307 (define_insn "*mulhisi3addsi"
1308   [(set (match_operand:SI 0 "s_register_operand" "=r")
1309         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1310                  (mult:SI (sign_extend:SI
1311                            (match_operand:HI 2 "s_register_operand" "%r"))
1312                           (sign_extend:SI
1313                            (match_operand:HI 3 "s_register_operand" "r")))))]
1314   "TARGET_ARM && arm_arch5e"
1315   "smlabb%?\\t%0, %2, %3, %1"
1316   [(set_attr "insn" "smlaxy")
1317    (set_attr "predicable" "yes")]
1318 )
1319
1320 (define_insn "*mulhidi3adddi"
1321   [(set (match_operand:DI 0 "s_register_operand" "=r")
1322         (plus:DI
1323           (match_operand:DI 1 "s_register_operand" "0")
1324           (mult:DI (sign_extend:DI
1325                     (match_operand:HI 2 "s_register_operand" "%r"))
1326                    (sign_extend:DI
1327                     (match_operand:HI 3 "s_register_operand" "r")))))]
1328   "TARGET_ARM && arm_arch5e"
1329   "smlalbb%?\\t%Q0, %R0, %2, %3"
1330   [(set_attr "insn" "smlalxy")
1331    (set_attr "predicable" "yes")])
1332
1333 (define_expand "mulsf3"
1334   [(set (match_operand:SF          0 "s_register_operand" "")
1335         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1336                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1337   "TARGET_ARM && TARGET_HARD_FLOAT"
1338   "
1339   if (TARGET_MAVERICK
1340       && !cirrus_fp_register (operands[2], SFmode))
1341     operands[2] = force_reg (SFmode, operands[2]);
1342 ")
1343
1344 (define_expand "muldf3"
1345   [(set (match_operand:DF          0 "s_register_operand" "")
1346         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1347                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1348   "TARGET_ARM && TARGET_HARD_FLOAT"
1349   "
1350   if (TARGET_MAVERICK
1351       && !cirrus_fp_register (operands[2], DFmode))
1352     operands[2] = force_reg (DFmode, operands[2]);
1353 ")
1354 \f
1355 ;; Division insns
1356
1357 (define_expand "divsf3"
1358   [(set (match_operand:SF 0 "s_register_operand" "")
1359         (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1360                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1361   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1362   "")
1363
1364 (define_expand "divdf3"
1365   [(set (match_operand:DF 0 "s_register_operand" "")
1366         (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1367                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1368   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1369   "")
1370 \f
1371 ;; Modulo insns
1372
1373 (define_expand "modsf3"
1374   [(set (match_operand:SF 0 "s_register_operand" "")
1375         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1376                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1377   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1378   "")
1379
1380 (define_expand "moddf3"
1381   [(set (match_operand:DF 0 "s_register_operand" "")
1382         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1383                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1384   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1385   "")
1386 \f
1387 ;; Boolean and,ior,xor insns
1388
1389 ;; Split up double word logical operations
1390
1391 ;; Split up simple DImode logical operations.  Simply perform the logical
1392 ;; operation on the upper and lower halves of the registers.
1393 (define_split
1394   [(set (match_operand:DI 0 "s_register_operand" "")
1395         (match_operator:DI 6 "logical_binary_operator"
1396           [(match_operand:DI 1 "s_register_operand" "")
1397            (match_operand:DI 2 "s_register_operand" "")]))]
1398   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1399   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1400    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1401   "
1402   {
1403     operands[3] = gen_highpart (SImode, operands[0]);
1404     operands[0] = gen_lowpart (SImode, operands[0]);
1405     operands[4] = gen_highpart (SImode, operands[1]);
1406     operands[1] = gen_lowpart (SImode, operands[1]);
1407     operands[5] = gen_highpart (SImode, operands[2]);
1408     operands[2] = gen_lowpart (SImode, operands[2]);
1409   }"
1410 )
1411
1412 (define_split
1413   [(set (match_operand:DI 0 "s_register_operand" "")
1414         (match_operator:DI 6 "logical_binary_operator"
1415           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1416            (match_operand:DI 1 "s_register_operand" "")]))]
1417   "TARGET_ARM && reload_completed"
1418   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1419    (set (match_dup 3) (match_op_dup:SI 6
1420                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1421                          (match_dup 4)]))]
1422   "
1423   {
1424     operands[3] = gen_highpart (SImode, operands[0]);
1425     operands[0] = gen_lowpart (SImode, operands[0]);
1426     operands[4] = gen_highpart (SImode, operands[1]);
1427     operands[1] = gen_lowpart (SImode, operands[1]);
1428     operands[5] = gen_highpart (SImode, operands[2]);
1429     operands[2] = gen_lowpart (SImode, operands[2]);
1430   }"
1431 )
1432
1433 ;; The zero extend of operand 2 means we can just copy the high part of
1434 ;; operand1 into operand0.
1435 (define_split
1436   [(set (match_operand:DI 0 "s_register_operand" "")
1437         (ior:DI
1438           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1439           (match_operand:DI 1 "s_register_operand" "")))]
1440   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1441   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1442    (set (match_dup 3) (match_dup 4))]
1443   "
1444   {
1445     operands[4] = gen_highpart (SImode, operands[1]);
1446     operands[3] = gen_highpart (SImode, operands[0]);
1447     operands[0] = gen_lowpart (SImode, operands[0]);
1448     operands[1] = gen_lowpart (SImode, operands[1]);
1449   }"
1450 )
1451
1452 ;; The zero extend of operand 2 means we can just copy the high part of
1453 ;; operand1 into operand0.
1454 (define_split
1455   [(set (match_operand:DI 0 "s_register_operand" "")
1456         (xor:DI
1457           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1458           (match_operand:DI 1 "s_register_operand" "")))]
1459   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1460   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1461    (set (match_dup 3) (match_dup 4))]
1462   "
1463   {
1464     operands[4] = gen_highpart (SImode, operands[1]);
1465     operands[3] = gen_highpart (SImode, operands[0]);
1466     operands[0] = gen_lowpart (SImode, operands[0]);
1467     operands[1] = gen_lowpart (SImode, operands[1]);
1468   }"
1469 )
1470
1471 (define_insn "anddi3"
1472   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1473         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1474                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1475   "TARGET_ARM && ! TARGET_IWMMXT"
1476   "#"
1477   [(set_attr "length" "8")]
1478 )
1479
1480 (define_insn_and_split "*anddi_zesidi_di"
1481   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1482         (and:DI (zero_extend:DI
1483                  (match_operand:SI 2 "s_register_operand" "r,r"))
1484                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1485   "TARGET_ARM"
1486   "#"
1487   "TARGET_ARM && reload_completed"
1488   ; The zero extend of operand 2 clears the high word of the output
1489   ; operand.
1490   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1491    (set (match_dup 3) (const_int 0))]
1492   "
1493   {
1494     operands[3] = gen_highpart (SImode, operands[0]);
1495     operands[0] = gen_lowpart (SImode, operands[0]);
1496     operands[1] = gen_lowpart (SImode, operands[1]);
1497   }"
1498   [(set_attr "length" "8")]
1499 )
1500
1501 (define_insn "*anddi_sesdi_di"
1502   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1503         (and:DI (sign_extend:DI
1504                  (match_operand:SI 2 "s_register_operand" "r,r"))
1505                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1506   "TARGET_ARM"
1507   "#"
1508   [(set_attr "length" "8")]
1509 )
1510
1511 (define_expand "andsi3"
1512   [(set (match_operand:SI         0 "s_register_operand" "")
1513         (and:SI (match_operand:SI 1 "s_register_operand" "")
1514                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1515   "TARGET_EITHER"
1516   "
1517   if (TARGET_ARM)
1518     {
1519       if (GET_CODE (operands[2]) == CONST_INT)
1520         {
1521           arm_split_constant (AND, SImode, NULL_RTX,
1522                               INTVAL (operands[2]), operands[0],
1523                               operands[1], optimize && !no_new_pseudos);
1524
1525           DONE;
1526         }
1527     }
1528   else /* TARGET_THUMB */
1529     {
1530       if (GET_CODE (operands[2]) != CONST_INT)
1531         operands[2] = force_reg (SImode, operands[2]);
1532       else
1533         {
1534           int i;
1535           
1536           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1537             {
1538               operands[2] = force_reg (SImode,
1539                                        GEN_INT (~INTVAL (operands[2])));
1540               
1541               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1542               
1543               DONE;
1544             }
1545
1546           for (i = 9; i <= 31; i++)
1547             {
1548               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1549                 {
1550                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1551                                         const0_rtx));
1552                   DONE;
1553                 }
1554               else if ((((HOST_WIDE_INT) 1) << i) - 1
1555                        == ~INTVAL (operands[2]))
1556                 {
1557                   rtx shift = GEN_INT (i);
1558                   rtx reg = gen_reg_rtx (SImode);
1559                 
1560                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1561                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1562                   
1563                   DONE;
1564                 }
1565             }
1566
1567           operands[2] = force_reg (SImode, operands[2]);
1568         }
1569     }
1570   "
1571 )
1572
1573 (define_insn_and_split "*arm_andsi3_insn"
1574   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1575         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1576                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1577   "TARGET_ARM"
1578   "@
1579    and%?\\t%0, %1, %2
1580    bic%?\\t%0, %1, #%B2
1581    #"
1582   "TARGET_ARM
1583    && GET_CODE (operands[2]) == CONST_INT
1584    && !(const_ok_for_arm (INTVAL (operands[2]))
1585         || const_ok_for_arm (~INTVAL (operands[2])))"
1586   [(clobber (const_int 0))]
1587   "
1588   arm_split_constant  (AND, SImode, curr_insn, 
1589                        INTVAL (operands[2]), operands[0], operands[1], 0);
1590   DONE;
1591   "
1592   [(set_attr "length" "4,4,16")
1593    (set_attr "predicable" "yes")]
1594 )
1595
1596 (define_insn "*thumb_andsi3_insn"
1597   [(set (match_operand:SI         0 "register_operand" "=l")
1598         (and:SI (match_operand:SI 1 "register_operand" "%0")
1599                 (match_operand:SI 2 "register_operand" "l")))]
1600   "TARGET_THUMB"
1601   "and\\t%0, %0, %2"
1602   [(set_attr "length" "2")]
1603 )
1604
1605 (define_insn "*andsi3_compare0"
1606   [(set (reg:CC_NOOV CC_REGNUM)
1607         (compare:CC_NOOV
1608          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1609                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1610          (const_int 0)))
1611    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1612         (and:SI (match_dup 1) (match_dup 2)))]
1613   "TARGET_ARM"
1614   "@
1615    and%?s\\t%0, %1, %2
1616    bic%?s\\t%0, %1, #%B2"
1617   [(set_attr "conds" "set")]
1618 )
1619
1620 (define_insn "*andsi3_compare0_scratch"
1621   [(set (reg:CC_NOOV CC_REGNUM)
1622         (compare:CC_NOOV
1623          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1624                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1625          (const_int 0)))
1626    (clobber (match_scratch:SI 2 "=X,r"))]
1627   "TARGET_ARM"
1628   "@
1629    tst%?\\t%0, %1
1630    bic%?s\\t%2, %0, #%B1"
1631   [(set_attr "conds" "set")]
1632 )
1633
1634 (define_insn "*zeroextractsi_compare0_scratch"
1635   [(set (reg:CC_NOOV CC_REGNUM)
1636         (compare:CC_NOOV (zero_extract:SI
1637                           (match_operand:SI 0 "s_register_operand" "r")
1638                           (match_operand 1 "const_int_operand" "n")
1639                           (match_operand 2 "const_int_operand" "n"))
1640                          (const_int 0)))]
1641   "TARGET_ARM
1642   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1643       && INTVAL (operands[1]) > 0 
1644       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1645       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1646   "*
1647   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1648                          << INTVAL (operands[2]));
1649   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1650   return \"\";
1651   "
1652   [(set_attr "conds" "set")]
1653 )
1654
1655 (define_insn_and_split "*ne_zeroextractsi"
1656   [(set (match_operand:SI 0 "s_register_operand" "=r")
1657         (ne:SI (zero_extract:SI
1658                 (match_operand:SI 1 "s_register_operand" "r")
1659                 (match_operand:SI 2 "const_int_operand" "n")
1660                 (match_operand:SI 3 "const_int_operand" "n"))
1661                (const_int 0)))
1662    (clobber (reg:CC CC_REGNUM))]
1663   "TARGET_ARM
1664    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1665        && INTVAL (operands[2]) > 0 
1666        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1667        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1668   "#"
1669   "TARGET_ARM
1670    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1671        && INTVAL (operands[2]) > 0 
1672        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1673        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1674   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1675                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1676                                     (const_int 0)))
1677               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1678    (set (match_dup 0)
1679         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1680                          (match_dup 0) (const_int 1)))]
1681   "
1682   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1683                          << INTVAL (operands[3])); 
1684   "
1685   [(set_attr "conds" "clob")
1686    (set_attr "length" "8")]
1687 )
1688
1689 (define_insn_and_split "*ne_zeroextractsi_shifted"
1690   [(set (match_operand:SI 0 "s_register_operand" "=r")
1691         (ne:SI (zero_extract:SI
1692                 (match_operand:SI 1 "s_register_operand" "r")
1693                 (match_operand:SI 2 "const_int_operand" "n")
1694                 (const_int 0))
1695                (const_int 0)))
1696    (clobber (reg:CC CC_REGNUM))]
1697   "TARGET_ARM"
1698   "#"
1699   "TARGET_ARM"
1700   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1701                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1702                                     (const_int 0)))
1703               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1704    (set (match_dup 0)
1705         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1706                          (match_dup 0) (const_int 1)))]
1707   "
1708   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1709   "
1710   [(set_attr "conds" "clob")
1711    (set_attr "length" "8")]
1712 )
1713
1714 (define_insn_and_split "*ite_ne_zeroextractsi"
1715   [(set (match_operand:SI 0 "s_register_operand" "=r")
1716         (if_then_else:SI (ne (zero_extract:SI
1717                               (match_operand:SI 1 "s_register_operand" "r")
1718                               (match_operand:SI 2 "const_int_operand" "n")
1719                               (match_operand:SI 3 "const_int_operand" "n"))
1720                              (const_int 0))
1721                          (match_operand:SI 4 "arm_not_operand" "rIK")
1722                          (const_int 0)))
1723    (clobber (reg:CC CC_REGNUM))]
1724   "TARGET_ARM
1725    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1726        && INTVAL (operands[2]) > 0 
1727        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1728        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1729    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1730   "#"
1731   "TARGET_ARM
1732    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1733        && INTVAL (operands[2]) > 0 
1734        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1735        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1736    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1737   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1738                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1739                                     (const_int 0)))
1740               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1741    (set (match_dup 0)
1742         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1743                          (match_dup 0) (match_dup 4)))]
1744   "
1745   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1746                          << INTVAL (operands[3])); 
1747   "
1748   [(set_attr "conds" "clob")
1749    (set_attr "length" "8")]
1750 )
1751
1752 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1753   [(set (match_operand:SI 0 "s_register_operand" "=r")
1754         (if_then_else:SI (ne (zero_extract:SI
1755                               (match_operand:SI 1 "s_register_operand" "r")
1756                               (match_operand:SI 2 "const_int_operand" "n")
1757                               (const_int 0))
1758                              (const_int 0))
1759                          (match_operand:SI 3 "arm_not_operand" "rIK")
1760                          (const_int 0)))
1761    (clobber (reg:CC CC_REGNUM))]
1762   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1763   "#"
1764   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1765   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1766                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1767                                     (const_int 0)))
1768               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1769    (set (match_dup 0)
1770         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1771                          (match_dup 0) (match_dup 3)))]
1772   "
1773   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1774   "
1775   [(set_attr "conds" "clob")
1776    (set_attr "length" "8")]
1777 )
1778
1779 (define_split
1780   [(set (match_operand:SI 0 "s_register_operand" "")
1781         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1782                          (match_operand:SI 2 "const_int_operand" "")
1783                          (match_operand:SI 3 "const_int_operand" "")))
1784    (clobber (match_operand:SI 4 "s_register_operand" ""))]
1785   "TARGET_THUMB"
1786   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1787    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1788   "{
1789      HOST_WIDE_INT temp = INTVAL (operands[2]);
1790
1791      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1792      operands[3] = GEN_INT (32 - temp);
1793    }"
1794 )
1795
1796 (define_split
1797   [(set (match_operand:SI 0 "s_register_operand" "")
1798         (match_operator:SI 1 "shiftable_operator"
1799          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1800                            (match_operand:SI 3 "const_int_operand" "")
1801                            (match_operand:SI 4 "const_int_operand" ""))
1802           (match_operand:SI 5 "s_register_operand" "")]))
1803    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1804   "TARGET_ARM"
1805   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1806    (set (match_dup 0)
1807         (match_op_dup 1
1808          [(lshiftrt:SI (match_dup 6) (match_dup 4))
1809           (match_dup 5)]))]
1810   "{
1811      HOST_WIDE_INT temp = INTVAL (operands[3]);
1812
1813      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1814      operands[4] = GEN_INT (32 - temp);
1815    }"
1816 )
1817   
1818 (define_split
1819   [(set (match_operand:SI 0 "s_register_operand" "")
1820         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1821                          (match_operand:SI 2 "const_int_operand" "")
1822                          (match_operand:SI 3 "const_int_operand" "")))]
1823   "TARGET_THUMB"
1824   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1825    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1826   "{
1827      HOST_WIDE_INT temp = INTVAL (operands[2]);
1828
1829      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1830      operands[3] = GEN_INT (32 - temp);
1831    }"
1832 )
1833
1834 (define_split
1835   [(set (match_operand:SI 0 "s_register_operand" "")
1836         (match_operator:SI 1 "shiftable_operator"
1837          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1838                            (match_operand:SI 3 "const_int_operand" "")
1839                            (match_operand:SI 4 "const_int_operand" ""))
1840           (match_operand:SI 5 "s_register_operand" "")]))
1841    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1842   "TARGET_ARM"
1843   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1844    (set (match_dup 0)
1845         (match_op_dup 1
1846          [(ashiftrt:SI (match_dup 6) (match_dup 4))
1847           (match_dup 5)]))]
1848   "{
1849      HOST_WIDE_INT temp = INTVAL (operands[3]);
1850
1851      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1852      operands[4] = GEN_INT (32 - temp);
1853    }"
1854 )
1855   
1856 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1857 ;;; represented by the bitfield, then this will produce incorrect results.
1858 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1859 ;;; which have a real bit-field insert instruction, the truncation happens
1860 ;;; in the bit-field insert instruction itself.  Since arm does not have a
1861 ;;; bit-field insert instruction, we would have to emit code here to truncate
1862 ;;; the value before we insert.  This loses some of the advantage of having
1863 ;;; this insv pattern, so this pattern needs to be reevalutated.
1864
1865 (define_expand "insv"
1866   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1867                          (match_operand:SI 1 "general_operand" "")
1868                          (match_operand:SI 2 "general_operand" ""))
1869         (match_operand:SI 3 "reg_or_int_operand" ""))]
1870   "TARGET_ARM"
1871   "
1872   {
1873     int start_bit = INTVAL (operands[2]);
1874     int width = INTVAL (operands[1]);
1875     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1876     rtx target, subtarget;
1877
1878     target = operands[0];
1879     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1880        subreg as the final target.  */
1881     if (GET_CODE (target) == SUBREG)
1882       {
1883         subtarget = gen_reg_rtx (SImode);
1884         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1885             < GET_MODE_SIZE (SImode))
1886           target = SUBREG_REG (target);
1887       }
1888     else
1889       subtarget = target;    
1890
1891     if (GET_CODE (operands[3]) == CONST_INT)
1892       {
1893         /* Since we are inserting a known constant, we may be able to
1894            reduce the number of bits that we have to clear so that
1895            the mask becomes simple.  */
1896         /* ??? This code does not check to see if the new mask is actually
1897            simpler.  It may not be.  */
1898         rtx op1 = gen_reg_rtx (SImode);
1899         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1900            start of this pattern.  */
1901         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1902         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1903
1904         emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1905         emit_insn (gen_iorsi3 (subtarget, op1,
1906                                gen_int_mode (op3_value << start_bit, SImode)));
1907       }
1908     else if (start_bit == 0
1909              && !(const_ok_for_arm (mask)
1910                   || const_ok_for_arm (~mask)))
1911       {
1912         /* A Trick, since we are setting the bottom bits in the word,
1913            we can shift operand[3] up, operand[0] down, OR them together
1914            and rotate the result back again.  This takes 3 insns, and
1915            the third might be mergeable into another op.  */
1916         /* The shift up copes with the possibility that operand[3] is
1917            wider than the bitfield.  */
1918         rtx op0 = gen_reg_rtx (SImode);
1919         rtx op1 = gen_reg_rtx (SImode);
1920
1921         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1922         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1923         emit_insn (gen_iorsi3  (op1, op1, op0));
1924         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1925       }
1926     else if ((width + start_bit == 32)
1927              && !(const_ok_for_arm (mask)
1928                   || const_ok_for_arm (~mask)))
1929       {
1930         /* Similar trick, but slightly less efficient.  */
1931
1932         rtx op0 = gen_reg_rtx (SImode);
1933         rtx op1 = gen_reg_rtx (SImode);
1934
1935         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1936         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1937         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1938         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1939       }
1940     else
1941       {
1942         rtx op0 = GEN_INT (mask);
1943         rtx op1 = gen_reg_rtx (SImode);
1944         rtx op2 = gen_reg_rtx (SImode);
1945
1946         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1947           {
1948             rtx tmp = gen_reg_rtx (SImode);
1949
1950             emit_insn (gen_movsi (tmp, op0));
1951             op0 = tmp;
1952           }
1953
1954         /* Mask out any bits in operand[3] that are not needed.  */
1955            emit_insn (gen_andsi3 (op1, operands[3], op0));
1956
1957         if (GET_CODE (op0) == CONST_INT
1958             && (const_ok_for_arm (mask << start_bit)
1959                 || const_ok_for_arm (~(mask << start_bit))))
1960           {
1961             op0 = GEN_INT (~(mask << start_bit));
1962             emit_insn (gen_andsi3 (op2, operands[0], op0));
1963           }
1964         else
1965           {
1966             if (GET_CODE (op0) == CONST_INT)
1967               {
1968                 rtx tmp = gen_reg_rtx (SImode);
1969
1970                 emit_insn (gen_movsi (tmp, op0));
1971                 op0 = tmp;
1972               }
1973
1974             if (start_bit != 0)
1975               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1976             
1977             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1978           }
1979
1980         if (start_bit != 0)
1981           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1982
1983         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1984       }
1985
1986     if (subtarget != target)
1987       {
1988         /* If TARGET is still a SUBREG, then it must be wider than a word,
1989            so we must be careful only to set the subword we were asked to.  */
1990         if (GET_CODE (target) == SUBREG)
1991           emit_move_insn (target, subtarget);
1992         else
1993           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1994       }
1995
1996     DONE;
1997   }"
1998 )
1999
2000 ; constants for op 2 will never be given to these patterns.
2001 (define_insn_and_split "*anddi_notdi_di"
2002   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2003         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2004                 (match_operand:DI 2 "s_register_operand" "0,r")))]
2005   "TARGET_ARM"
2006   "#"
2007   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2008   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2009    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2010   "
2011   {
2012     operands[3] = gen_highpart (SImode, operands[0]);
2013     operands[0] = gen_lowpart (SImode, operands[0]);
2014     operands[4] = gen_highpart (SImode, operands[1]);
2015     operands[1] = gen_lowpart (SImode, operands[1]);
2016     operands[5] = gen_highpart (SImode, operands[2]);
2017     operands[2] = gen_lowpart (SImode, operands[2]);
2018   }"
2019   [(set_attr "length" "8")
2020    (set_attr "predicable" "yes")]
2021 )
2022   
2023 (define_insn_and_split "*anddi_notzesidi_di"
2024   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2025         (and:DI (not:DI (zero_extend:DI
2026                          (match_operand:SI 2 "s_register_operand" "r,r")))
2027                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2028   "TARGET_ARM"
2029   "@
2030    bic%?\\t%Q0, %Q1, %2
2031    #"
2032   ; (not (zero_extend ...)) allows us to just copy the high word from
2033   ; operand1 to operand0.
2034   "TARGET_ARM
2035    && reload_completed
2036    && operands[0] != operands[1]"
2037   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2038    (set (match_dup 3) (match_dup 4))]
2039   "
2040   {
2041     operands[3] = gen_highpart (SImode, operands[0]);
2042     operands[0] = gen_lowpart (SImode, operands[0]);
2043     operands[4] = gen_highpart (SImode, operands[1]);
2044     operands[1] = gen_lowpart (SImode, operands[1]);
2045   }"
2046   [(set_attr "length" "4,8")
2047    (set_attr "predicable" "yes")]
2048 )
2049   
2050 (define_insn_and_split "*anddi_notsesidi_di"
2051   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2052         (and:DI (not:DI (sign_extend:DI
2053                          (match_operand:SI 2 "s_register_operand" "r,r")))
2054                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2055   "TARGET_ARM"
2056   "#"
2057   "TARGET_ARM && reload_completed"
2058   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2059    (set (match_dup 3) (and:SI (not:SI
2060                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2061                                (match_dup 4)))]
2062   "
2063   {
2064     operands[3] = gen_highpart (SImode, operands[0]);
2065     operands[0] = gen_lowpart (SImode, operands[0]);
2066     operands[4] = gen_highpart (SImode, operands[1]);
2067     operands[1] = gen_lowpart (SImode, operands[1]);
2068   }"
2069   [(set_attr "length" "8")
2070    (set_attr "predicable" "yes")]
2071 )
2072   
2073 (define_insn "andsi_notsi_si"
2074   [(set (match_operand:SI 0 "s_register_operand" "=r")
2075         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2076                 (match_operand:SI 1 "s_register_operand" "r")))]
2077   "TARGET_ARM"
2078   "bic%?\\t%0, %1, %2"
2079   [(set_attr "predicable" "yes")]
2080 )
2081
2082 (define_insn "bicsi3"
2083   [(set (match_operand:SI                 0 "register_operand" "=l")
2084         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2085                 (match_operand:SI         2 "register_operand" "0")))]
2086   "TARGET_THUMB"
2087   "bic\\t%0, %0, %1"
2088   [(set_attr "length" "2")]
2089 )
2090
2091 (define_insn "andsi_not_shiftsi_si"
2092   [(set (match_operand:SI 0 "s_register_operand" "=r")
2093         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2094                          [(match_operand:SI 2 "s_register_operand" "r")
2095                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2096                 (match_operand:SI 1 "s_register_operand" "r")))]
2097   "TARGET_ARM"
2098   "bic%?\\t%0, %1, %2%S4"
2099   [(set_attr "predicable" "yes")
2100    (set_attr "shift" "2")
2101    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2102                       (const_string "alu_shift")
2103                       (const_string "alu_shift_reg")))]
2104 )
2105
2106 (define_insn "*andsi_notsi_si_compare0"
2107   [(set (reg:CC_NOOV CC_REGNUM)
2108         (compare:CC_NOOV
2109          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2110                  (match_operand:SI 1 "s_register_operand" "r"))
2111          (const_int 0)))
2112    (set (match_operand:SI 0 "s_register_operand" "=r")
2113         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2114   "TARGET_ARM"
2115   "bic%?s\\t%0, %1, %2"
2116   [(set_attr "conds" "set")]
2117 )
2118
2119 (define_insn "*andsi_notsi_si_compare0_scratch"
2120   [(set (reg:CC_NOOV CC_REGNUM)
2121         (compare:CC_NOOV
2122          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2123                  (match_operand:SI 1 "s_register_operand" "r"))
2124          (const_int 0)))
2125    (clobber (match_scratch:SI 0 "=r"))]
2126   "TARGET_ARM"
2127   "bic%?s\\t%0, %1, %2"
2128   [(set_attr "conds" "set")]
2129 )
2130
2131 (define_insn "iordi3"
2132   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2133         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2134                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2135   "TARGET_ARM && ! TARGET_IWMMXT"
2136   "#"
2137   [(set_attr "length" "8")
2138    (set_attr "predicable" "yes")]
2139 )
2140
2141 (define_insn "*iordi_zesidi_di"
2142   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2143         (ior:DI (zero_extend:DI
2144                  (match_operand:SI 2 "s_register_operand" "r,r"))
2145                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2146   "TARGET_ARM"
2147   "@
2148    orr%?\\t%Q0, %Q1, %2
2149    #"
2150   [(set_attr "length" "4,8")
2151    (set_attr "predicable" "yes")]
2152 )
2153
2154 (define_insn "*iordi_sesidi_di"
2155   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2156         (ior:DI (sign_extend:DI
2157                  (match_operand:SI 2 "s_register_operand" "r,r"))
2158                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2159   "TARGET_ARM"
2160   "#"
2161   [(set_attr "length" "8")
2162    (set_attr "predicable" "yes")]
2163 )
2164
2165 (define_expand "iorsi3"
2166   [(set (match_operand:SI         0 "s_register_operand" "")
2167         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2168                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2169   "TARGET_EITHER"
2170   "
2171   if (GET_CODE (operands[2]) == CONST_INT)
2172     {
2173       if (TARGET_ARM)
2174         {
2175           arm_split_constant (IOR, SImode, NULL_RTX,
2176                               INTVAL (operands[2]), operands[0], operands[1],
2177                               optimize && !no_new_pseudos);
2178           DONE;
2179         }
2180       else /* TARGET_THUMB */
2181         operands [2] = force_reg (SImode, operands [2]);
2182     }
2183   "
2184 )
2185
2186 (define_insn_and_split "*arm_iorsi3"
2187   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2188         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2189                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2190   "TARGET_ARM"
2191   "@
2192    orr%?\\t%0, %1, %2
2193    #"
2194   "TARGET_ARM
2195    && GET_CODE (operands[2]) == CONST_INT
2196    && !const_ok_for_arm (INTVAL (operands[2]))"
2197   [(clobber (const_int 0))]
2198   "
2199   arm_split_constant (IOR, SImode, curr_insn, 
2200                       INTVAL (operands[2]), operands[0], operands[1], 0);
2201   DONE;
2202   "
2203   [(set_attr "length" "4,16")
2204    (set_attr "predicable" "yes")]
2205 )
2206
2207 (define_insn "*thumb_iorsi3"
2208   [(set (match_operand:SI         0 "register_operand" "=l")
2209         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2210                 (match_operand:SI 2 "register_operand" "l")))]
2211   "TARGET_THUMB"
2212   "orr\\t%0, %0, %2"
2213   [(set_attr "length" "2")]
2214 )
2215
2216 (define_peephole2
2217   [(match_scratch:SI 3 "r")
2218    (set (match_operand:SI 0 "arm_general_register_operand" "")
2219         (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2220                 (match_operand:SI 2 "const_int_operand" "")))]
2221   "TARGET_ARM
2222    && !const_ok_for_arm (INTVAL (operands[2]))
2223    && const_ok_for_arm (~INTVAL (operands[2]))"
2224   [(set (match_dup 3) (match_dup 2))
2225    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2226   ""
2227 )
2228
2229 (define_insn "*iorsi3_compare0"
2230   [(set (reg:CC_NOOV CC_REGNUM)
2231         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2232                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2233                          (const_int 0)))
2234    (set (match_operand:SI 0 "s_register_operand" "=r")
2235         (ior:SI (match_dup 1) (match_dup 2)))]
2236   "TARGET_ARM"
2237   "orr%?s\\t%0, %1, %2"
2238   [(set_attr "conds" "set")]
2239 )
2240
2241 (define_insn "*iorsi3_compare0_scratch"
2242   [(set (reg:CC_NOOV CC_REGNUM)
2243         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2244                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2245                          (const_int 0)))
2246    (clobber (match_scratch:SI 0 "=r"))]
2247   "TARGET_ARM"
2248   "orr%?s\\t%0, %1, %2"
2249   [(set_attr "conds" "set")]
2250 )
2251
2252 (define_insn "xordi3"
2253   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2254         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2255                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2256   "TARGET_ARM && !TARGET_IWMMXT"
2257   "#"
2258   [(set_attr "length" "8")
2259    (set_attr "predicable" "yes")]
2260 )
2261
2262 (define_insn "*xordi_zesidi_di"
2263   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2264         (xor:DI (zero_extend:DI
2265                  (match_operand:SI 2 "s_register_operand" "r,r"))
2266                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2267   "TARGET_ARM"
2268   "@
2269    eor%?\\t%Q0, %Q1, %2
2270    #"
2271   [(set_attr "length" "4,8")
2272    (set_attr "predicable" "yes")]
2273 )
2274
2275 (define_insn "*xordi_sesidi_di"
2276   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2277         (xor:DI (sign_extend:DI
2278                  (match_operand:SI 2 "s_register_operand" "r,r"))
2279                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2280   "TARGET_ARM"
2281   "#"
2282   [(set_attr "length" "8")
2283    (set_attr "predicable" "yes")]
2284 )
2285
2286 (define_expand "xorsi3"
2287   [(set (match_operand:SI         0 "s_register_operand" "")
2288         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2289                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2290   "TARGET_EITHER"
2291   "if (TARGET_THUMB)
2292      if (GET_CODE (operands[2]) == CONST_INT)
2293        operands[2] = force_reg (SImode, operands[2]);
2294   "
2295 )
2296
2297 (define_insn "*arm_xorsi3"
2298   [(set (match_operand:SI         0 "s_register_operand" "=r")
2299         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2300                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2301   "TARGET_ARM"
2302   "eor%?\\t%0, %1, %2"
2303   [(set_attr "predicable" "yes")]
2304 )
2305
2306 (define_insn "*thumb_xorsi3"
2307   [(set (match_operand:SI         0 "register_operand" "=l")
2308         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2309                 (match_operand:SI 2 "register_operand" "l")))]
2310   "TARGET_THUMB"
2311   "eor\\t%0, %0, %2"
2312   [(set_attr "length" "2")]
2313 )
2314
2315 (define_insn "*xorsi3_compare0"
2316   [(set (reg:CC_NOOV CC_REGNUM)
2317         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2318                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2319                          (const_int 0)))
2320    (set (match_operand:SI 0 "s_register_operand" "=r")
2321         (xor:SI (match_dup 1) (match_dup 2)))]
2322   "TARGET_ARM"
2323   "eor%?s\\t%0, %1, %2"
2324   [(set_attr "conds" "set")]
2325 )
2326
2327 (define_insn "*xorsi3_compare0_scratch"
2328   [(set (reg:CC_NOOV CC_REGNUM)
2329         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2330                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2331                          (const_int 0)))]
2332   "TARGET_ARM"
2333   "teq%?\\t%0, %1"
2334   [(set_attr "conds" "set")]
2335 )
2336
2337 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2338 ; (NOT D) we can sometimes merge the final NOT into one of the following
2339 ; insns.
2340
2341 (define_split
2342   [(set (match_operand:SI 0 "s_register_operand" "")
2343         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2344                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2345                 (match_operand:SI 3 "arm_rhs_operand" "")))
2346    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2347   "TARGET_ARM"
2348   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2349                               (not:SI (match_dup 3))))
2350    (set (match_dup 0) (not:SI (match_dup 4)))]
2351   ""
2352 )
2353
2354 (define_insn "*andsi_iorsi3_notsi"
2355   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2356         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2357                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2358                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2359   "TARGET_ARM"
2360   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2361   [(set_attr "length" "8")
2362    (set_attr "predicable" "yes")]
2363 )
2364
2365 (define_split
2366   [(set (match_operand:SI 0 "s_register_operand" "")
2367         (match_operator:SI 1 "logical_binary_operator"
2368          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2369                            (match_operand:SI 3 "const_int_operand" "")
2370                            (match_operand:SI 4 "const_int_operand" ""))
2371           (match_operator:SI 9 "logical_binary_operator"
2372            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2373                          (match_operand:SI 6 "const_int_operand" ""))
2374             (match_operand:SI 7 "s_register_operand" "")])]))
2375    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2376   "TARGET_ARM
2377    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2378    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2379   [(set (match_dup 8)
2380         (match_op_dup 1
2381          [(ashift:SI (match_dup 2) (match_dup 4))
2382           (match_dup 5)]))
2383    (set (match_dup 0)
2384         (match_op_dup 1
2385          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2386           (match_dup 7)]))]
2387   "
2388   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2389 ")
2390
2391 (define_split
2392   [(set (match_operand:SI 0 "s_register_operand" "")
2393         (match_operator:SI 1 "logical_binary_operator"
2394          [(match_operator:SI 9 "logical_binary_operator"
2395            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2396                          (match_operand:SI 6 "const_int_operand" ""))
2397             (match_operand:SI 7 "s_register_operand" "")])
2398           (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2399                            (match_operand:SI 3 "const_int_operand" "")
2400                            (match_operand:SI 4 "const_int_operand" ""))]))
2401    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2402   "TARGET_ARM
2403    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2404    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2405   [(set (match_dup 8)
2406         (match_op_dup 1
2407          [(ashift:SI (match_dup 2) (match_dup 4))
2408           (match_dup 5)]))
2409    (set (match_dup 0)
2410         (match_op_dup 1
2411          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2412           (match_dup 7)]))]
2413   "
2414   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2415 ")
2416
2417 (define_split
2418   [(set (match_operand:SI 0 "s_register_operand" "")
2419         (match_operator:SI 1 "logical_binary_operator"
2420          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2421                            (match_operand:SI 3 "const_int_operand" "")
2422                            (match_operand:SI 4 "const_int_operand" ""))
2423           (match_operator:SI 9 "logical_binary_operator"
2424            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2425                          (match_operand:SI 6 "const_int_operand" ""))
2426             (match_operand:SI 7 "s_register_operand" "")])]))
2427    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2428   "TARGET_ARM
2429    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2430    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2431   [(set (match_dup 8)
2432         (match_op_dup 1
2433          [(ashift:SI (match_dup 2) (match_dup 4))
2434           (match_dup 5)]))
2435    (set (match_dup 0)
2436         (match_op_dup 1
2437          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2438           (match_dup 7)]))]
2439   "
2440   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2441 ")
2442
2443 (define_split
2444   [(set (match_operand:SI 0 "s_register_operand" "")
2445         (match_operator:SI 1 "logical_binary_operator"
2446          [(match_operator:SI 9 "logical_binary_operator"
2447            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2448                          (match_operand:SI 6 "const_int_operand" ""))
2449             (match_operand:SI 7 "s_register_operand" "")])
2450           (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2451                            (match_operand:SI 3 "const_int_operand" "")
2452                            (match_operand:SI 4 "const_int_operand" ""))]))
2453    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2454   "TARGET_ARM
2455    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2456    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2457   [(set (match_dup 8)
2458         (match_op_dup 1
2459          [(ashift:SI (match_dup 2) (match_dup 4))
2460           (match_dup 5)]))
2461    (set (match_dup 0)
2462         (match_op_dup 1
2463          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2464           (match_dup 7)]))]
2465   "
2466   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2467 ")
2468 \f
2469
2470 ;; Minimum and maximum insns
2471
2472 (define_insn "smaxsi3"
2473   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2474         (smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2475                  (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2476    (clobber (reg:CC CC_REGNUM))]
2477   "TARGET_ARM"
2478   "@
2479    cmp\\t%1, %2\;movlt\\t%0, %2
2480    cmp\\t%1, %2\;movge\\t%0, %1
2481    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2482   [(set_attr "conds" "clob")
2483    (set_attr "length" "8,8,12")]
2484 )
2485
2486 (define_insn "sminsi3"
2487   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2488         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2489                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2490    (clobber (reg:CC CC_REGNUM))]
2491   "TARGET_ARM"
2492   "@
2493    cmp\\t%1, %2\;movge\\t%0, %2
2494    cmp\\t%1, %2\;movlt\\t%0, %1
2495    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2496   [(set_attr "conds" "clob")
2497    (set_attr "length" "8,8,12")]
2498 )
2499
2500 (define_insn "umaxsi3"
2501   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2502         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2503                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2504    (clobber (reg:CC CC_REGNUM))]
2505   "TARGET_ARM"
2506   "@
2507    cmp\\t%1, %2\;movcc\\t%0, %2
2508    cmp\\t%1, %2\;movcs\\t%0, %1
2509    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2510   [(set_attr "conds" "clob")
2511    (set_attr "length" "8,8,12")]
2512 )
2513
2514 (define_insn "uminsi3"
2515   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2516         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2517                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2518    (clobber (reg:CC CC_REGNUM))]
2519   "TARGET_ARM"
2520   "@
2521    cmp\\t%1, %2\;movcs\\t%0, %2
2522    cmp\\t%1, %2\;movcc\\t%0, %1
2523    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2524   [(set_attr "conds" "clob")
2525    (set_attr "length" "8,8,12")]
2526 )
2527
2528 (define_insn "*store_minmaxsi"
2529   [(set (match_operand:SI 0 "memory_operand" "=m")
2530         (match_operator:SI 3 "minmax_operator"
2531          [(match_operand:SI 1 "s_register_operand" "r")
2532           (match_operand:SI 2 "s_register_operand" "r")]))
2533    (clobber (reg:CC CC_REGNUM))]
2534   "TARGET_ARM"
2535   "*
2536   operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2537                                 operands[1], operands[2]);
2538   output_asm_insn (\"cmp\\t%1, %2\", operands);
2539   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2540   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2541   return \"\";
2542   "
2543   [(set_attr "conds" "clob")
2544    (set_attr "length" "12")
2545    (set_attr "type" "store1")]
2546 )
2547
2548 ; Reject the frame pointer in operand[1], since reloading this after
2549 ; it has been eliminated can cause carnage.
2550 (define_insn "*minmax_arithsi"
2551   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2552         (match_operator:SI 4 "shiftable_operator"
2553          [(match_operator:SI 5 "minmax_operator"
2554            [(match_operand:SI 2 "s_register_operand" "r,r")
2555             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2556           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2557    (clobber (reg:CC CC_REGNUM))]
2558   "TARGET_ARM && !arm_eliminable_register (operands[1])"
2559   "*
2560   {
2561     enum rtx_code code = GET_CODE (operands[4]);
2562
2563     operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2564                                   operands[2], operands[3]);
2565     output_asm_insn (\"cmp\\t%2, %3\", operands);
2566     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2567     if (which_alternative != 0 || operands[3] != const0_rtx
2568         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2569       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2570     return \"\";
2571   }"
2572   [(set_attr "conds" "clob")
2573    (set_attr "length" "12")]
2574 )
2575
2576 \f
2577 ;; Shift and rotation insns
2578
2579 (define_expand "ashldi3"
2580   [(set (match_operand:DI            0 "s_register_operand" "")
2581         (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2582                    (match_operand:SI 2 "reg_or_int_operand" "")))]
2583   "TARGET_ARM"
2584   "
2585   if (GET_CODE (operands[2]) == CONST_INT)
2586     {
2587       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2588         {
2589           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2590           DONE;
2591         }
2592         /* Ideally we shouldn't fail here if we could know that operands[1] 
2593            ends up already living in an iwmmxt register. Otherwise it's
2594            cheaper to have the alternate code being generated than moving
2595            values to iwmmxt regs and back.  */
2596         FAIL;
2597     }
2598   else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2599     FAIL;
2600   "
2601 )
2602
2603 (define_insn "arm_ashldi3_1bit"
2604   [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
2605         (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2606                    (const_int 1)))
2607    (clobber (reg:CC CC_REGNUM))]
2608   "TARGET_ARM"
2609   "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2610   [(set_attr "conds" "clob")
2611    (set_attr "length" "8")]
2612 )
2613
2614 (define_expand "ashlsi3"
2615   [(set (match_operand:SI            0 "s_register_operand" "")
2616         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2617                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2618   "TARGET_EITHER"
2619   "
2620   if (GET_CODE (operands[2]) == CONST_INT
2621       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2622     {
2623       emit_insn (gen_movsi (operands[0], const0_rtx));
2624       DONE;
2625     }
2626   "
2627 )
2628
2629 (define_insn "*thumb_ashlsi3"
2630   [(set (match_operand:SI            0 "register_operand" "=l,l")
2631         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2632                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2633   "TARGET_THUMB"
2634   "lsl\\t%0, %1, %2"
2635   [(set_attr "length" "2")]
2636 )
2637
2638 (define_expand "ashrdi3"
2639   [(set (match_operand:DI              0 "s_register_operand" "")
2640         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2641                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2642   "TARGET_ARM"
2643   "
2644   if (GET_CODE (operands[2]) == CONST_INT)
2645     {
2646       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2647         {
2648           emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2649           DONE;
2650         }
2651         /* Ideally we shouldn't fail here if we could know that operands[1] 
2652            ends up already living in an iwmmxt register. Otherwise it's
2653            cheaper to have the alternate code being generated than moving
2654            values to iwmmxt regs and back.  */
2655         FAIL;
2656     }
2657   else if (!TARGET_REALLY_IWMMXT)
2658     FAIL;
2659   "
2660 )
2661
2662 (define_insn "arm_ashrdi3_1bit"
2663   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2664         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2665                      (const_int 1)))
2666    (clobber (reg:CC CC_REGNUM))]
2667   "TARGET_ARM"
2668   "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2669   [(set_attr "conds" "clob")
2670    (set_attr "length" "8")]
2671 )
2672
2673 (define_expand "ashrsi3"
2674   [(set (match_operand:SI              0 "s_register_operand" "")
2675         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2676                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2677   "TARGET_EITHER"
2678   "
2679   if (GET_CODE (operands[2]) == CONST_INT
2680       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2681     operands[2] = GEN_INT (31);
2682   "
2683 )
2684
2685 (define_insn "*thumb_ashrsi3"
2686   [(set (match_operand:SI              0 "register_operand" "=l,l")
2687         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2688                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2689   "TARGET_THUMB"
2690   "asr\\t%0, %1, %2"
2691   [(set_attr "length" "2")]
2692 )
2693
2694 (define_expand "lshrdi3"
2695   [(set (match_operand:DI              0 "s_register_operand" "")
2696         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2697                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2698   "TARGET_ARM"
2699   "
2700   if (GET_CODE (operands[2]) == CONST_INT)
2701     {
2702       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2703         {
2704           emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2705           DONE;
2706         }
2707         /* Ideally we shouldn't fail here if we could know that operands[1] 
2708            ends up already living in an iwmmxt register. Otherwise it's
2709            cheaper to have the alternate code being generated than moving
2710            values to iwmmxt regs and back.  */
2711         FAIL;
2712     }
2713   else if (!TARGET_REALLY_IWMMXT)
2714     FAIL;
2715   "
2716 )
2717
2718 (define_insn "arm_lshrdi3_1bit"
2719   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2720         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2721                      (const_int 1)))
2722    (clobber (reg:CC CC_REGNUM))]
2723   "TARGET_ARM"
2724   "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2725   [(set_attr "conds" "clob")
2726    (set_attr "length" "8")]
2727 )
2728
2729 (define_expand "lshrsi3"
2730   [(set (match_operand:SI              0 "s_register_operand" "")
2731         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2732                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2733   "TARGET_EITHER"
2734   "
2735   if (GET_CODE (operands[2]) == CONST_INT
2736       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2737     {
2738       emit_insn (gen_movsi (operands[0], const0_rtx));
2739       DONE;
2740     }
2741   "
2742 )
2743
2744 (define_insn "*thumb_lshrsi3"
2745   [(set (match_operand:SI              0 "register_operand" "=l,l")
2746         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2747                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2748   "TARGET_THUMB"
2749   "lsr\\t%0, %1, %2"
2750   [(set_attr "length" "2")]
2751 )
2752
2753 (define_expand "rotlsi3"
2754   [(set (match_operand:SI              0 "s_register_operand" "")
2755         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2756                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2757   "TARGET_ARM"
2758   "
2759   if (GET_CODE (operands[2]) == CONST_INT)
2760     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2761   else
2762     {
2763       rtx reg = gen_reg_rtx (SImode);
2764       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2765       operands[2] = reg;
2766     }
2767   "
2768 )
2769
2770 (define_expand "rotrsi3"
2771   [(set (match_operand:SI              0 "s_register_operand" "")
2772         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2773                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2774   "TARGET_EITHER"
2775   "
2776   if (TARGET_ARM)
2777     {
2778       if (GET_CODE (operands[2]) == CONST_INT
2779           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2780         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2781     }
2782   else /* TARGET_THUMB */
2783     {
2784       if (GET_CODE (operands [2]) == CONST_INT)
2785         operands [2] = force_reg (SImode, operands[2]);
2786     }
2787   "
2788 )
2789
2790 (define_insn "*thumb_rotrsi3"
2791   [(set (match_operand:SI              0 "register_operand" "=l")
2792         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2793                      (match_operand:SI 2 "register_operand" "l")))]
2794   "TARGET_THUMB"
2795   "ror\\t%0, %0, %2"
2796   [(set_attr "length" "2")]
2797 )
2798
2799 (define_insn "*arm_shiftsi3"
2800   [(set (match_operand:SI   0 "s_register_operand" "=r")
2801         (match_operator:SI  3 "shift_operator"
2802          [(match_operand:SI 1 "s_register_operand"  "r")
2803           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2804   "TARGET_ARM"
2805   "mov%?\\t%0, %1%S3"
2806   [(set_attr "predicable" "yes")
2807    (set_attr "shift" "1")
2808    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2809                       (const_string "alu_shift")
2810                       (const_string "alu_shift_reg")))]
2811 )
2812
2813 (define_insn "*shiftsi3_compare0"
2814   [(set (reg:CC_NOOV CC_REGNUM)
2815         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2816                           [(match_operand:SI 1 "s_register_operand" "r")
2817                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2818                          (const_int 0)))
2819    (set (match_operand:SI 0 "s_register_operand" "=r")
2820         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2821   "TARGET_ARM"
2822   "mov%?s\\t%0, %1%S3"
2823   [(set_attr "conds" "set")
2824    (set_attr "shift" "1")
2825    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2826                       (const_string "alu_shift")
2827                       (const_string "alu_shift_reg")))]
2828 )
2829
2830 (define_insn "*shiftsi3_compare0_scratch"
2831   [(set (reg:CC_NOOV CC_REGNUM)
2832         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2833                           [(match_operand:SI 1 "s_register_operand" "r")
2834                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2835                          (const_int 0)))
2836    (clobber (match_scratch:SI 0 "=r"))]
2837   "TARGET_ARM"
2838   "mov%?s\\t%0, %1%S3"
2839   [(set_attr "conds" "set")
2840    (set_attr "shift" "1")]
2841 )
2842
2843 (define_insn "*notsi_shiftsi"
2844   [(set (match_operand:SI 0 "s_register_operand" "=r")
2845         (not:SI (match_operator:SI 3 "shift_operator"
2846                  [(match_operand:SI 1 "s_register_operand" "r")
2847                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2848   "TARGET_ARM"
2849   "mvn%?\\t%0, %1%S3"
2850   [(set_attr "predicable" "yes")
2851    (set_attr "shift" "1")
2852    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2853                       (const_string "alu_shift")
2854                       (const_string "alu_shift_reg")))]
2855 )
2856
2857 (define_insn "*notsi_shiftsi_compare0"
2858   [(set (reg:CC_NOOV CC_REGNUM)
2859         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2860                           [(match_operand:SI 1 "s_register_operand" "r")
2861                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2862                          (const_int 0)))
2863    (set (match_operand:SI 0 "s_register_operand" "=r")
2864         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2865   "TARGET_ARM"
2866   "mvn%?s\\t%0, %1%S3"
2867   [(set_attr "conds" "set")
2868    (set_attr "shift" "1")
2869    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2870                       (const_string "alu_shift")
2871                       (const_string "alu_shift_reg")))]
2872 )
2873
2874 (define_insn "*not_shiftsi_compare0_scratch"
2875   [(set (reg:CC_NOOV CC_REGNUM)
2876         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2877                           [(match_operand:SI 1 "s_register_operand" "r")
2878                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2879                          (const_int 0)))
2880    (clobber (match_scratch:SI 0 "=r"))]
2881   "TARGET_ARM"
2882   "mvn%?s\\t%0, %1%S3"
2883   [(set_attr "conds" "set")
2884    (set_attr "shift" "1")
2885    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2886                       (const_string "alu_shift")
2887                       (const_string "alu_shift_reg")))]
2888 )
2889
2890 ;; We don't really have extzv, but defining this using shifts helps
2891 ;; to reduce register pressure later on.
2892
2893 (define_expand "extzv"
2894   [(set (match_dup 4)
2895         (ashift:SI (match_operand:SI   1 "register_operand" "")
2896                    (match_operand:SI   2 "const_int_operand" "")))
2897    (set (match_operand:SI              0 "register_operand" "")
2898         (lshiftrt:SI (match_dup 4)
2899                      (match_operand:SI 3 "const_int_operand" "")))]
2900   "TARGET_THUMB"
2901   "
2902   {
2903     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2904     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2905     
2906     operands[3] = GEN_INT (rshift);
2907     
2908     if (lshift == 0)
2909       {
2910         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2911         DONE;
2912       }
2913       
2914     operands[2] = GEN_INT (lshift);
2915     operands[4] = gen_reg_rtx (SImode);
2916   }"
2917 )
2918
2919 \f
2920 ;; Unary arithmetic insns
2921
2922 (define_expand "negdi2"
2923  [(parallel
2924    [(set (match_operand:DI          0 "s_register_operand" "")
2925           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2926     (clobber (reg:CC CC_REGNUM))])]
2927   "TARGET_EITHER"
2928   "
2929   if (TARGET_THUMB)
2930     {
2931       if (GET_CODE (operands[1]) != REG)
2932         operands[1] = force_reg (SImode, operands[1]);
2933      }
2934   "
2935 )
2936
2937 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2938 ;; The second alternative is to allow the common case of a *full* overlap.
2939 (define_insn "*arm_negdi2"
2940   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2941         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2942    (clobber (reg:CC CC_REGNUM))]
2943   "TARGET_ARM"
2944   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2945   [(set_attr "conds" "clob")
2946    (set_attr "length" "8")]
2947 )
2948
2949 (define_insn "*thumb_negdi2"
2950   [(set (match_operand:DI         0 "register_operand" "=&l")
2951         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
2952    (clobber (reg:CC CC_REGNUM))]
2953   "TARGET_THUMB"
2954   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2955   [(set_attr "length" "6")]
2956 )
2957
2958 (define_expand "negsi2"
2959   [(set (match_operand:SI         0 "s_register_operand" "")
2960         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2961   "TARGET_EITHER"
2962   ""
2963 )
2964
2965 (define_insn "*arm_negsi2"
2966   [(set (match_operand:SI         0 "s_register_operand" "=r")
2967         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2968   "TARGET_ARM"
2969   "rsb%?\\t%0, %1, #0"
2970   [(set_attr "predicable" "yes")]
2971 )
2972
2973 (define_insn "*thumb_negsi2"
2974   [(set (match_operand:SI         0 "register_operand" "=l")
2975         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2976   "TARGET_THUMB"
2977   "neg\\t%0, %1"
2978   [(set_attr "length" "2")]
2979 )
2980
2981 (define_expand "negsf2"
2982   [(set (match_operand:SF         0 "s_register_operand" "")
2983         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2984   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
2985   ""
2986 )
2987
2988 (define_expand "negdf2"
2989   [(set (match_operand:DF         0 "s_register_operand" "")
2990         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2991   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
2992   "")
2993
2994 ;; abssi2 doesn't really clobber the condition codes if a different register
2995 ;; is being set.  To keep things simple, assume during rtl manipulations that
2996 ;; it does, but tell the final scan operator the truth.  Similarly for
2997 ;; (neg (abs...))
2998
2999 (define_expand "abssi2"
3000   [(parallel
3001     [(set (match_operand:SI         0 "s_register_operand" "")
3002           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3003      (clobber (reg:CC CC_REGNUM))])]
3004   "TARGET_ARM"
3005   "")
3006
3007 (define_insn "*arm_abssi2"
3008   [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
3009         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3010    (clobber (reg:CC CC_REGNUM))]
3011   "TARGET_ARM"
3012   "@
3013    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3014    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3015   [(set_attr "conds" "clob,*")
3016    (set_attr "shift" "1")
3017    ;; predicable can't be set based on the variant, so left as no
3018    (set_attr "length" "8")]
3019 )
3020
3021 (define_insn "*neg_abssi2"
3022   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3023         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3024    (clobber (reg:CC CC_REGNUM))]
3025   "TARGET_ARM"
3026   "@
3027    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3028    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3029   [(set_attr "conds" "clob,*")
3030    (set_attr "shift" "1")
3031    ;; predicable can't be set based on the variant, so left as no
3032    (set_attr "length" "8")]
3033 )
3034
3035 (define_expand "abssf2"
3036   [(set (match_operand:SF         0 "s_register_operand" "")
3037         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3038   "TARGET_ARM && TARGET_HARD_FLOAT"
3039   "")
3040
3041 (define_expand "absdf2"
3042   [(set (match_operand:DF         0 "s_register_operand" "")
3043         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3044   "TARGET_ARM && TARGET_HARD_FLOAT"
3045   "")
3046
3047 (define_expand "sqrtsf2"
3048   [(set (match_operand:SF 0 "s_register_operand" "")
3049         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3050   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3051   "")
3052
3053 (define_expand "sqrtdf2"
3054   [(set (match_operand:DF 0 "s_register_operand" "")
3055         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3056   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3057   "")
3058
3059 (define_insn_and_split "one_cmpldi2"
3060   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3061         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3062   "TARGET_ARM"
3063   "#"
3064   "TARGET_ARM && reload_completed"
3065   [(set (match_dup 0) (not:SI (match_dup 1)))
3066    (set (match_dup 2) (not:SI (match_dup 3)))]
3067   "
3068   {
3069     operands[2] = gen_highpart (SImode, operands[0]);
3070     operands[0] = gen_lowpart (SImode, operands[0]);
3071     operands[3] = gen_highpart (SImode, operands[1]);
3072     operands[1] = gen_lowpart (SImode, operands[1]);
3073   }"
3074   [(set_attr "length" "8")
3075    (set_attr "predicable" "yes")]
3076 )
3077
3078 (define_expand "one_cmplsi2"
3079   [(set (match_operand:SI         0 "s_register_operand" "")
3080         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3081   "TARGET_EITHER"
3082   ""
3083 )
3084
3085 (define_insn "*arm_one_cmplsi2"
3086   [(set (match_operand:SI         0 "s_register_operand" "=r")
3087         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3088   "TARGET_ARM"
3089   "mvn%?\\t%0, %1"
3090   [(set_attr "predicable" "yes")]
3091 )
3092
3093 (define_insn "*thumb_one_cmplsi2"
3094   [(set (match_operand:SI         0 "register_operand" "=l")
3095         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3096   "TARGET_THUMB"
3097   "mvn\\t%0, %1"
3098   [(set_attr "length" "2")]
3099 )
3100
3101 (define_insn "*notsi_compare0"
3102   [(set (reg:CC_NOOV CC_REGNUM)
3103         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3104                          (const_int 0)))
3105    (set (match_operand:SI 0 "s_register_operand" "=r")
3106         (not:SI (match_dup 1)))]
3107   "TARGET_ARM"
3108   "mvn%?s\\t%0, %1"
3109   [(set_attr "conds" "set")]
3110 )
3111
3112 (define_insn "*notsi_compare0_scratch"
3113   [(set (reg:CC_NOOV CC_REGNUM)
3114         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3115                          (const_int 0)))
3116    (clobber (match_scratch:SI 0 "=r"))]
3117   "TARGET_ARM"
3118   "mvn%?s\\t%0, %1"
3119   [(set_attr "conds" "set")]
3120 )
3121 \f
3122 ;; Fixed <--> Floating conversion insns
3123
3124 (define_expand "floatsisf2"
3125   [(set (match_operand:SF           0 "s_register_operand" "")
3126         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3127   "TARGET_ARM && TARGET_HARD_FLOAT"
3128   "
3129   if (TARGET_MAVERICK)
3130     {
3131       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3132       DONE;
3133     }
3134 ")
3135
3136 (define_expand "floatsidf2"
3137   [(set (match_operand:DF           0 "s_register_operand" "")
3138         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3139   "TARGET_ARM && TARGET_HARD_FLOAT"
3140   "
3141   if (TARGET_MAVERICK)
3142     {
3143       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3144       DONE;
3145     }
3146 ")
3147
3148 (define_expand "fix_truncsfsi2"
3149   [(set (match_operand:SI         0 "s_register_operand" "")
3150         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3151   "TARGET_ARM && TARGET_HARD_FLOAT"
3152   "
3153   if (TARGET_MAVERICK)
3154     {
3155       if (!cirrus_fp_register (operands[0], SImode))
3156         operands[0] = force_reg (SImode, operands[0]);
3157       if (!cirrus_fp_register (operands[1], SFmode))
3158         operands[1] = force_reg (SFmode, operands[0]);
3159       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3160       DONE;
3161     }
3162 ")
3163
3164 (define_expand "fix_truncdfsi2"
3165   [(set (match_operand:SI         0 "s_register_operand" "")
3166         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3167   "TARGET_ARM && TARGET_HARD_FLOAT"
3168   "
3169   if (TARGET_MAVERICK)
3170     {
3171       if (!cirrus_fp_register (operands[1], DFmode))
3172         operands[1] = force_reg (DFmode, operands[0]);
3173       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3174       DONE;
3175     }
3176 ")
3177
3178 ;; Truncation insns
3179
3180 (define_expand "truncdfsf2"
3181   [(set (match_operand:SF  0 "s_register_operand" "")
3182         (float_truncate:SF
3183          (match_operand:DF 1 "s_register_operand" "")))]
3184   "TARGET_ARM && TARGET_HARD_FLOAT"
3185   ""
3186 )
3187 \f
3188 ;; Zero and sign extension instructions.
3189
3190 (define_insn "zero_extendsidi2"
3191   [(set (match_operand:DI 0 "s_register_operand" "=r")
3192         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3193   "TARGET_ARM"
3194   "*
3195     if (REGNO (operands[1])
3196         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3197       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3198     return \"mov%?\\t%R0, #0\";
3199   "
3200   [(set_attr "length" "8")
3201    (set_attr "predicable" "yes")]
3202 )
3203
3204 (define_insn "zero_extendqidi2"
3205   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3206         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3207   "TARGET_ARM"
3208   "@
3209    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3210    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3211   [(set_attr "length" "8")
3212    (set_attr "predicable" "yes")
3213    (set_attr "type" "*,load_byte")
3214    (set_attr "pool_range" "*,4092")
3215    (set_attr "neg_pool_range" "*,4084")]
3216 )
3217
3218 (define_insn "extendsidi2"
3219   [(set (match_operand:DI 0 "s_register_operand" "=r")
3220         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3221   "TARGET_ARM"
3222   "*
3223     if (REGNO (operands[1])
3224         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3225       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3226     return \"mov%?\\t%R0, %Q0, asr #31\";
3227   "
3228   [(set_attr "length" "8")
3229    (set_attr "shift" "1")
3230    (set_attr "predicable" "yes")]
3231 )
3232
3233 (define_expand "zero_extendhisi2"
3234   [(set (match_dup 2)
3235         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3236                    (const_int 16)))
3237    (set (match_operand:SI 0 "s_register_operand" "")
3238         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3239   "TARGET_EITHER"
3240   "
3241   {
3242     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3243       {
3244         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3245                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3246         DONE;
3247       }
3248
3249     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3250       {
3251         emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3252         DONE;
3253       }
3254
3255     if (!s_register_operand (operands[1], HImode))
3256       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3257
3258     if (arm_arch6)
3259       {
3260         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3261                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3262         DONE;
3263       }
3264
3265     operands[1] = gen_lowpart (SImode, operands[1]);
3266     operands[2] = gen_reg_rtx (SImode);
3267   }"
3268 )
3269
3270 (define_insn "*thumb_zero_extendhisi2"
3271   [(set (match_operand:SI 0 "register_operand" "=l")
3272         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3273   "TARGET_THUMB && !arm_arch6"
3274   "*
3275   rtx mem = XEXP (operands[1], 0);
3276
3277   if (GET_CODE (mem) == CONST)
3278     mem = XEXP (mem, 0);
3279     
3280   if (GET_CODE (mem) == LABEL_REF)
3281     return \"ldr\\t%0, %1\";
3282     
3283   if (GET_CODE (mem) == PLUS)
3284     {
3285       rtx a = XEXP (mem, 0);
3286       rtx b = XEXP (mem, 1);
3287
3288       /* This can happen due to bugs in reload.  */
3289       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3290         {
3291           rtx ops[2];
3292           ops[0] = operands[0];
3293           ops[1] = a;
3294       
3295           output_asm_insn (\"mov        %0, %1\", ops);
3296
3297           XEXP (mem, 0) = operands[0];
3298        }
3299
3300       else if (   GET_CODE (a) == LABEL_REF
3301                && GET_CODE (b) == CONST_INT)
3302         return \"ldr\\t%0, %1\";
3303     }
3304     
3305   return \"ldrh\\t%0, %1\";
3306   "
3307   [(set_attr "length" "4")
3308    (set_attr "type" "load_byte")
3309    (set_attr "pool_range" "60")]
3310 )
3311
3312 (define_insn "*thumb_zero_extendhisi2_v6"
3313   [(set (match_operand:SI 0 "register_operand" "=l,l")
3314         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3315   "TARGET_THUMB && arm_arch6"
3316   "*
3317   rtx mem;
3318
3319   if (which_alternative == 0)
3320     return \"uxth\\t%0, %1\";
3321
3322   mem = XEXP (operands[1], 0);
3323
3324   if (GET_CODE (mem) == CONST)
3325     mem = XEXP (mem, 0);
3326     
3327   if (GET_CODE (mem) == LABEL_REF)
3328     return \"ldr\\t%0, %1\";
3329     
3330   if (GET_CODE (mem) == PLUS)
3331     {
3332       rtx a = XEXP (mem, 0);
3333       rtx b = XEXP (mem, 1);
3334
3335       /* This can happen due to bugs in reload.  */
3336       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3337         {
3338           rtx ops[2];
3339           ops[0] = operands[0];
3340           ops[1] = a;
3341       
3342           output_asm_insn (\"mov        %0, %1\", ops);
3343
3344           XEXP (mem, 0) = operands[0];
3345        }
3346
3347       else if (   GET_CODE (a) == LABEL_REF
3348                && GET_CODE (b) == CONST_INT)
3349         return \"ldr\\t%0, %1\";
3350     }
3351     
3352   return \"ldrh\\t%0, %1\";
3353   "
3354   [(set_attr "length" "2,4")
3355    (set_attr "type" "alu_shift,load_byte")
3356    (set_attr "pool_range" "*,60")]
3357 )
3358
3359 (define_insn "*arm_zero_extendhisi2"
3360   [(set (match_operand:SI 0 "s_register_operand" "=r")
3361         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3362   "TARGET_ARM && arm_arch4 && !arm_arch6"
3363   "ldr%?h\\t%0, %1"
3364   [(set_attr "type" "load_byte")
3365    (set_attr "predicable" "yes")
3366    (set_attr "pool_range" "256")
3367    (set_attr "neg_pool_range" "244")]
3368 )
3369
3370 (define_insn "*arm_zero_extendhisi2_v6"
3371   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3372         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3373   "TARGET_ARM && arm_arch6"
3374   "@
3375    uxth%?\\t%0, %1
3376    ldr%?h\\t%0, %1"
3377   [(set_attr "type" "alu_shift,load_byte")
3378    (set_attr "predicable" "yes")
3379    (set_attr "pool_range" "*,256")
3380    (set_attr "neg_pool_range" "*,244")]
3381 )
3382
3383 (define_insn "*arm_zero_extendhisi2addsi"
3384   [(set (match_operand:SI 0 "s_register_operand" "=r")
3385         (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3386                  (match_operand:SI 2 "s_register_operand" "r")))]
3387   "TARGET_ARM && arm_arch6"
3388   "uxtah%?\\t%0, %2, %1"
3389   [(set_attr "type" "alu_shift")
3390    (set_attr "predicable" "yes")]
3391 )
3392
3393 (define_expand "zero_extendqisi2"
3394   [(set (match_operand:SI 0 "s_register_operand" "")
3395         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3396   "TARGET_EITHER"
3397   "
3398   if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3399     {
3400       if (TARGET_ARM)
3401         {
3402           emit_insn (gen_andsi3 (operands[0],
3403                                  gen_lowpart (SImode, operands[1]),
3404                                  GEN_INT (255)));
3405         }
3406       else /* TARGET_THUMB */
3407         {
3408           rtx temp = gen_reg_rtx (SImode);
3409           rtx ops[3];
3410           
3411           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3412           operands[1] = gen_lowpart (SImode, operands[1]);
3413
3414           ops[0] = temp;
3415           ops[1] = operands[1];
3416           ops[2] = GEN_INT (24);
3417
3418           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3419                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3420           
3421           ops[0] = operands[0];
3422           ops[1] = temp;
3423           ops[2] = GEN_INT (24);
3424
3425           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3426                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3427         }
3428       DONE;
3429     }
3430   "
3431 )
3432
3433 (define_insn "*thumb_zero_extendqisi2"
3434   [(set (match_operand:SI 0 "register_operand" "=l")
3435         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3436   "TARGET_THUMB && !arm_arch6"
3437   "ldrb\\t%0, %1"
3438   [(set_attr "length" "2")
3439    (set_attr "type" "load_byte")
3440    (set_attr "pool_range" "32")]
3441 )
3442
3443 (define_insn "*thumb_zero_extendqisi2_v6"
3444   [(set (match_operand:SI 0 "register_operand" "=l,l")
3445         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3446   "TARGET_THUMB && arm_arch6"
3447   "@
3448    uxtb\\t%0, %1
3449    ldrb\\t%0, %1"
3450   [(set_attr "length" "2,2")
3451    (set_attr "type" "alu_shift,load_byte")
3452    (set_attr "pool_range" "*,32")]
3453 )
3454
3455 (define_insn "*arm_zero_extendqisi2"
3456   [(set (match_operand:SI 0 "s_register_operand" "=r")
3457         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3458   "TARGET_ARM && !arm_arch6"
3459   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3460   [(set_attr "type" "load_byte")
3461    (set_attr "predicable" "yes")
3462    (set_attr "pool_range" "4096")
3463    (set_attr "neg_pool_range" "4084")]
3464 )
3465
3466 (define_insn "*arm_zero_extendqisi2_v6"
3467   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3468         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3469   "TARGET_ARM && arm_arch6"
3470   "@
3471    uxtb%?\\t%0, %1
3472    ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3473   [(set_attr "type" "alu_shift,load_byte")
3474    (set_attr "predicable" "yes")
3475    (set_attr "pool_range" "*,4096")
3476    (set_attr "neg_pool_range" "*,4084")]
3477 )
3478
3479 (define_insn "*arm_zero_extendqisi2addsi"
3480   [(set (match_operand:SI 0 "s_register_operand" "=r")
3481         (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3482                  (match_operand:SI 2 "s_register_operand" "r")))]
3483   "TARGET_ARM && arm_arch6"
3484   "uxtab%?\\t%0, %2, %1"
3485   [(set_attr "predicable" "yes")
3486    (set_attr "type" "alu_shift")]
3487 )
3488
3489 (define_split
3490   [(set (match_operand:SI 0 "s_register_operand" "")
3491         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3492    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3493   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3494   [(set (match_dup 2) (match_dup 1))
3495    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3496   ""
3497 )
3498
3499 (define_insn "*compareqi_eq0"
3500   [(set (reg:CC_Z CC_REGNUM)
3501         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3502                          (const_int 0)))]
3503   "TARGET_ARM"
3504   "tst\\t%0, #255"
3505   [(set_attr "conds" "set")]
3506 )
3507
3508 (define_expand "extendhisi2"
3509   [(set (match_dup 2)
3510         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3511                    (const_int 16)))
3512    (set (match_operand:SI 0 "s_register_operand" "")
3513         (ashiftrt:SI (match_dup 2)
3514                      (const_int 16)))]
3515   "TARGET_EITHER"
3516   "
3517   {
3518     if (GET_CODE (operands[1]) == MEM)
3519       {
3520         if (TARGET_THUMB)
3521           {
3522             emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3523             DONE;
3524           }
3525         else if (arm_arch4)
3526           {
3527             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3528                        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3529             DONE;
3530           }
3531       }
3532
3533     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3534       {
3535         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3536         DONE;
3537       }
3538
3539     if (!s_register_operand (operands[1], HImode))
3540       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3541
3542     if (arm_arch6)
3543       {
3544         if (TARGET_THUMB)
3545           emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3546         else
3547           emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3548                      gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3549
3550         DONE;
3551       }
3552
3553     operands[1] = gen_lowpart (SImode, operands[1]);
3554     operands[2] = gen_reg_rtx (SImode);
3555   }"
3556 )
3557
3558 (define_insn "thumb_extendhisi2"
3559   [(set (match_operand:SI 0 "register_operand" "=l")
3560         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3561    (clobber (match_scratch:SI 2 "=&l"))]
3562   "TARGET_THUMB && !arm_arch6"
3563   "*
3564   {
3565     rtx ops[4];
3566     rtx mem = XEXP (operands[1], 0);
3567
3568     /* This code used to try to use 'V', and fix the address only if it was
3569        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3570        range of QImode offsets, and offsettable_address_p does a QImode
3571        address check.  */
3572        
3573     if (GET_CODE (mem) == CONST)
3574       mem = XEXP (mem, 0);
3575     
3576     if (GET_CODE (mem) == LABEL_REF)
3577       return \"ldr\\t%0, %1\";
3578     
3579     if (GET_CODE (mem) == PLUS)
3580       {
3581         rtx a = XEXP (mem, 0);
3582         rtx b = XEXP (mem, 1);
3583
3584         if (GET_CODE (a) == LABEL_REF
3585             && GET_CODE (b) == CONST_INT)
3586           return \"ldr\\t%0, %1\";
3587
3588         if (GET_CODE (b) == REG)
3589           return \"ldrsh\\t%0, %1\";
3590           
3591         ops[1] = a;
3592         ops[2] = b;
3593       }
3594     else
3595       {
3596         ops[1] = mem;
3597         ops[2] = const0_rtx;
3598       }
3599
3600     gcc_assert (GET_CODE (ops[1]) == REG);
3601
3602     ops[0] = operands[0];
3603     ops[3] = operands[2];
3604     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3605     return \"\";
3606   }"
3607   [(set_attr "length" "4")
3608    (set_attr "type" "load_byte")
3609    (set_attr "pool_range" "1020")]
3610 )
3611
3612 ;; We used to have an early-clobber on the scratch register here.
3613 ;; However, there's a bug somewhere in reload which means that this
3614 ;; can be partially ignored during spill allocation if the memory
3615 ;; address also needs reloading; this causes us to die later on when
3616 ;; we try to verify the operands.  Fortunately, we don't really need
3617 ;; the early-clobber: we can always use operand 0 if operand 2
3618 ;; overlaps the address.
3619 (define_insn "*thumb_extendhisi2_insn_v6"
3620   [(set (match_operand:SI 0 "register_operand" "=l,l")
3621         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3622    (clobber (match_scratch:SI 2 "=X,l"))]
3623   "TARGET_THUMB && arm_arch6"
3624   "*
3625   {
3626     rtx ops[4];
3627     rtx mem;
3628
3629     if (which_alternative == 0)
3630       return \"sxth\\t%0, %1\";
3631
3632     mem = XEXP (operands[1], 0);
3633
3634     /* This code used to try to use 'V', and fix the address only if it was
3635        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3636        range of QImode offsets, and offsettable_address_p does a QImode
3637        address check.  */
3638        
3639     if (GET_CODE (mem) == CONST)
3640       mem = XEXP (mem, 0);
3641     
3642     if (GET_CODE (mem) == LABEL_REF)
3643       return \"ldr\\t%0, %1\";
3644     
3645     if (GET_CODE (mem) == PLUS)
3646       {
3647         rtx a = XEXP (mem, 0);
3648         rtx b = XEXP (mem, 1);
3649
3650         if (GET_CODE (a) == LABEL_REF
3651             && GET_CODE (b) == CONST_INT)
3652           return \"ldr\\t%0, %1\";
3653
3654         if (GET_CODE (b) == REG)
3655           return \"ldrsh\\t%0, %1\";
3656           
3657         ops[1] = a;
3658         ops[2] = b;
3659       }
3660     else
3661       {
3662         ops[1] = mem;
3663         ops[2] = const0_rtx;
3664       }
3665       
3666     gcc_assert (GET_CODE (ops[1]) == REG);
3667
3668     ops[0] = operands[0];
3669     if (reg_mentioned_p (operands[2], ops[1]))
3670       ops[3] = ops[0];
3671     else
3672       ops[3] = operands[2];
3673     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3674     return \"\";
3675   }"
3676   [(set_attr "length" "2,4")
3677    (set_attr "type" "alu_shift,load_byte")
3678    (set_attr "pool_range" "*,1020")]
3679 )
3680
3681 (define_expand "extendhisi2_mem"
3682   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3683    (set (match_dup 3)
3684         (zero_extend:SI (match_dup 7)))
3685    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3686    (set (match_operand:SI 0 "" "")
3687         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3688   "TARGET_ARM"
3689   "
3690   {
3691     rtx mem1, mem2;
3692     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3693
3694     mem1 = change_address (operands[1], QImode, addr);
3695     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
3696     operands[0] = gen_lowpart (SImode, operands[0]);
3697     operands[1] = mem1;
3698     operands[2] = gen_reg_rtx (SImode);
3699     operands[3] = gen_reg_rtx (SImode);
3700     operands[6] = gen_reg_rtx (SImode);
3701     operands[7] = mem2;
3702
3703     if (BYTES_BIG_ENDIAN)
3704       {
3705         operands[4] = operands[2];
3706         operands[5] = operands[3];
3707       }
3708     else
3709       {
3710         operands[4] = operands[3];
3711         operands[5] = operands[2];
3712       }
3713   }"
3714 )
3715
3716 (define_insn "*arm_extendhisi2"
3717   [(set (match_operand:SI 0 "s_register_operand" "=r")
3718         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3719   "TARGET_ARM && arm_arch4 && !arm_arch6"
3720   "ldr%?sh\\t%0, %1"
3721   [(set_attr "type" "load_byte")
3722    (set_attr "predicable" "yes")
3723    (set_attr "pool_range" "256")
3724    (set_attr "neg_pool_range" "244")]
3725 )
3726
3727 (define_insn "*arm_extendhisi2_v6"
3728   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3729         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3730   "TARGET_ARM && arm_arch6"
3731   "@
3732    sxth%?\\t%0, %1
3733    ldr%?sh\\t%0, %1"
3734   [(set_attr "type" "alu_shift,load_byte")
3735    (set_attr "predicable" "yes")
3736    (set_attr "pool_range" "*,256")
3737    (set_attr "neg_pool_range" "*,244")]
3738 )
3739
3740 (define_insn "*arm_extendhisi2addsi"
3741   [(set (match_operand:SI 0 "s_register_operand" "=r")
3742         (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3743                  (match_operand:SI 2 "s_register_operand" "r")))]
3744   "TARGET_ARM && arm_arch6"
3745   "sxtah%?\\t%0, %2, %1"
3746 )
3747
3748 (define_expand "extendqihi2"
3749   [(set (match_dup 2)
3750         (ashift:SI (match_operand:QI 1 "general_operand" "")
3751                    (const_int 24)))
3752    (set (match_operand:HI 0 "s_register_operand" "")
3753         (ashiftrt:SI (match_dup 2)
3754                      (const_int 24)))]
3755   "TARGET_ARM"
3756   "
3757   {
3758     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3759       {
3760         emit_insn (gen_rtx_SET (VOIDmode,
3761                                 operands[0],
3762                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3763         DONE;
3764       }
3765     if (!s_register_operand (operands[1], QImode))
3766       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3767     operands[0] = gen_lowpart (SImode, operands[0]);
3768     operands[1] = gen_lowpart (SImode, operands[1]);
3769     operands[2] = gen_reg_rtx (SImode);
3770   }"
3771 )
3772
3773 (define_insn "*extendqihi_insn"
3774   [(set (match_operand:HI 0 "s_register_operand" "=r")
3775         (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3776   "TARGET_ARM && arm_arch4"
3777   "ldr%?sb\\t%0, %1"
3778   [(set_attr "type" "load_byte")
3779    (set_attr "predicable" "yes")
3780    (set_attr "pool_range" "256")
3781    (set_attr "neg_pool_range" "244")]
3782 )
3783
3784 (define_expand "extendqisi2"
3785   [(set (match_dup 2)
3786         (ashift:SI (match_operand:QI 1 "general_operand" "")
3787                    (const_int 24)))
3788    (set (match_operand:SI 0 "s_register_operand" "")
3789         (ashiftrt:SI (match_dup 2)
3790                      (const_int 24)))]
3791   "TARGET_EITHER"
3792   "
3793   {
3794     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3795       {
3796         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3797                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3798         DONE;
3799       }
3800
3801     if (!s_register_operand (operands[1], QImode))
3802       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3803
3804     if (arm_arch6)
3805       {
3806         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3807                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3808         DONE;
3809       }
3810
3811     operands[1] = gen_lowpart (SImode, operands[1]);
3812     operands[2] = gen_reg_rtx (SImode);
3813   }"
3814 )
3815
3816 (define_insn "*arm_extendqisi"
3817   [(set (match_operand:SI 0 "s_register_operand" "=r")
3818         (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3819   "TARGET_ARM && arm_arch4 && !arm_arch6"
3820   "ldr%?sb\\t%0, %1"
3821   [(set_attr "type" "load_byte")
3822    (set_attr "predicable" "yes")
3823    (set_attr "pool_range" "256")
3824    (set_attr "neg_pool_range" "244")]
3825 )
3826
3827 (define_insn "*arm_extendqisi_v6"
3828   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3829         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3830   "TARGET_ARM && arm_arch6"
3831   "@
3832    sxtb%?\\t%0, %1
3833    ldr%?sb\\t%0, %1"
3834   [(set_attr "type" "alu_shift,load_byte")
3835    (set_attr "predicable" "yes")
3836    (set_attr "pool_range" "*,256")
3837    (set_attr "neg_pool_range" "*,244")]
3838 )
3839
3840 (define_insn "*arm_extendqisi2addsi"
3841   [(set (match_operand:SI 0 "s_register_operand" "=r")
3842         (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3843                  (match_operand:SI 2 "s_register_operand" "r")))]
3844   "TARGET_ARM && arm_arch6"
3845   "sxtab%?\\t%0, %2, %1"
3846   [(set_attr "type" "alu_shift")
3847    (set_attr "predicable" "yes")]
3848 )
3849
3850 (define_insn "*thumb_extendqisi2"
3851   [(set (match_operand:SI 0 "register_operand" "=l,l")
3852         (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3853   "TARGET_THUMB && !arm_arch6"
3854   "*
3855   {
3856     rtx ops[3];
3857     rtx mem = XEXP (operands[1], 0);
3858     
3859     if (GET_CODE (mem) == CONST)
3860       mem = XEXP (mem, 0);
3861     
3862     if (GET_CODE (mem) == LABEL_REF)
3863       return \"ldr\\t%0, %1\";
3864
3865     if (GET_CODE (mem) == PLUS
3866         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3867       return \"ldr\\t%0, %1\";
3868       
3869     if (which_alternative == 0)
3870       return \"ldrsb\\t%0, %1\";
3871       
3872     ops[0] = operands[0];
3873     
3874     if (GET_CODE (mem) == PLUS)
3875       {
3876         rtx a = XEXP (mem, 0);
3877         rtx b = XEXP (mem, 1);
3878         
3879         ops[1] = a;
3880         ops[2] = b;
3881
3882         if (GET_CODE (a) == REG)
3883           {
3884             if (GET_CODE (b) == REG)
3885               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3886             else if (REGNO (a) == REGNO (ops[0]))
3887               {
3888                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3889                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3890                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3891               }
3892             else
3893               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3894           }
3895         else
3896           {
3897             gcc_assert (GET_CODE (b) == REG);
3898             if (REGNO (b) == REGNO (ops[0]))
3899               {
3900                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3901                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3902                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3903               }
3904             else
3905               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3906           }
3907       }
3908     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3909       {
3910         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3911         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3912         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3913       }
3914     else
3915       {
3916         ops[1] = mem;
3917         ops[2] = const0_rtx;
3918         
3919         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3920       }
3921     return \"\";
3922   }"
3923   [(set_attr "length" "2,6")
3924    (set_attr "type" "load_byte,load_byte")
3925    (set_attr "pool_range" "32,32")]
3926 )
3927
3928 (define_insn "*thumb_extendqisi2_v6"
3929   [(set (match_operand:SI 0 "register_operand" "=l,l,l")
3930         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
3931   "TARGET_THUMB && arm_arch6"
3932   "*
3933   {
3934     rtx ops[3];
3935     rtx mem;
3936
3937     if (which_alternative == 0)
3938       return \"sxtb\\t%0, %1\";
3939
3940     mem = XEXP (operands[1], 0);
3941     
3942     if (GET_CODE (mem) == CONST)
3943       mem = XEXP (mem, 0);
3944     
3945     if (GET_CODE (mem) == LABEL_REF)
3946       return \"ldr\\t%0, %1\";
3947
3948     if (GET_CODE (mem) == PLUS
3949         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3950       return \"ldr\\t%0, %1\";
3951       
3952     if (which_alternative == 0)
3953       return \"ldrsb\\t%0, %1\";
3954       
3955     ops[0] = operands[0];
3956     
3957     if (GET_CODE (mem) == PLUS)
3958       {
3959         rtx a = XEXP (mem, 0);
3960         rtx b = XEXP (mem, 1);
3961         
3962         ops[1] = a;
3963         ops[2] = b;
3964
3965         if (GET_CODE (a) == REG)
3966           {
3967             if (GET_CODE (b) == REG)
3968               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3969             else if (REGNO (a) == REGNO (ops[0]))
3970               {
3971                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3972                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
3973               }
3974             else
3975               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3976           }
3977         else
3978           {
3979             gcc_assert (GET_CODE (b) == REG);
3980             if (REGNO (b) == REGNO (ops[0]))
3981               {
3982                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3983                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
3984               }
3985             else
3986               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3987           }
3988       }
3989     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3990       {
3991         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3992         output_asm_insn (\"sxtb\\t%0, %0\", ops);
3993       }
3994     else
3995       {
3996         ops[1] = mem;
3997         ops[2] = const0_rtx;
3998         
3999         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4000       }
4001     return \"\";
4002   }"
4003   [(set_attr "length" "2,2,4")
4004    (set_attr "type" "alu_shift,load_byte,load_byte")
4005    (set_attr "pool_range" "*,32,32")]
4006 )
4007
4008 (define_expand "extendsfdf2"
4009   [(set (match_operand:DF                  0 "s_register_operand" "")
4010         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
4011   "TARGET_ARM && TARGET_HARD_FLOAT"
4012   ""
4013 )
4014 \f
4015 ;; Move insns (including loads and stores)
4016
4017 ;; XXX Just some ideas about movti.
4018 ;; I don't think these are a good idea on the arm, there just aren't enough
4019 ;; registers
4020 ;;(define_expand "loadti"
4021 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
4022 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
4023 ;;  "" "")
4024
4025 ;;(define_expand "storeti"
4026 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4027 ;;      (match_operand:TI 1 "s_register_operand" ""))]
4028 ;;  "" "")
4029
4030 ;;(define_expand "movti"
4031 ;;  [(set (match_operand:TI 0 "general_operand" "")
4032 ;;      (match_operand:TI 1 "general_operand" ""))]
4033 ;;  ""
4034 ;;  "
4035 ;;{
4036 ;;  rtx insn;
4037 ;;
4038 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4039 ;;    operands[1] = copy_to_reg (operands[1]);
4040 ;;  if (GET_CODE (operands[0]) == MEM)
4041 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4042 ;;  else if (GET_CODE (operands[1]) == MEM)
4043 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4044 ;;  else
4045 ;;    FAIL;
4046 ;;
4047 ;;  emit_insn (insn);
4048 ;;  DONE;
4049 ;;}")
4050
4051 ;; Recognize garbage generated above.
4052
4053 ;;(define_insn ""
4054 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4055 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4056 ;;  ""
4057 ;;  "*
4058 ;;  {
4059 ;;    register mem = (which_alternative < 3);
4060 ;;    register const char *template;
4061 ;;
4062 ;;    operands[mem] = XEXP (operands[mem], 0);
4063 ;;    switch (which_alternative)
4064 ;;      {
4065 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4066 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
4067 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
4068 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
4069 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
4070 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
4071 ;;      }
4072 ;;    output_asm_insn (template, operands);
4073 ;;    return \"\";
4074 ;;  }")
4075
4076 (define_expand "movdi"
4077   [(set (match_operand:DI 0 "general_operand" "")
4078         (match_operand:DI 1 "general_operand" ""))]
4079   "TARGET_EITHER"
4080   "
4081   if (TARGET_THUMB)
4082     {
4083       if (!no_new_pseudos)
4084         {
4085           if (GET_CODE (operands[0]) != REG)
4086             operands[1] = force_reg (DImode, operands[1]);
4087         }
4088     }
4089   "
4090 )
4091
4092 (define_insn "*arm_movdi"
4093   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4094         (match_operand:DI 1 "di_operand"              "rDa,Db,Dc,mi,r"))]
4095   "TARGET_ARM
4096   && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4097   && !TARGET_IWMMXT"
4098   "*
4099   switch (which_alternative)
4100     {
4101     case 0:
4102     case 1:
4103     case 2:
4104       return \"#\";
4105     default:
4106       return output_move_double (operands);
4107     }
4108   "
4109   [(set_attr "length" "8,12,16,8,8")
4110    (set_attr "type" "*,*,*,load2,store2")
4111    (set_attr "pool_range" "*,*,*,1020,*")
4112    (set_attr "neg_pool_range" "*,*,*,1008,*")]
4113 )
4114
4115 (define_split
4116   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4117         (match_operand:ANY64 1 "const_double_operand" ""))]
4118   "TARGET_ARM
4119    && reload_completed
4120    && (arm_const_double_inline_cost (operands[1])
4121        <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4122   [(const_int 0)]
4123   "
4124   arm_split_constant (SET, SImode, curr_insn,
4125                       INTVAL (gen_lowpart (SImode, operands[1])),
4126                       gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4127   arm_split_constant (SET, SImode, curr_insn,
4128                       INTVAL (gen_highpart_mode (SImode,
4129                                                  GET_MODE (operands[0]),
4130                                                  operands[1])),
4131                       gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4132   DONE;
4133   "
4134 )
4135
4136 ; If optimizing for size, or if we have load delay slots, then 
4137 ; we want to split the constant into two separate operations. 
4138 ; In both cases this may split a trivial part into a single data op
4139 ; leaving a single complex constant to load.  We can also get longer
4140 ; offsets in a LDR which means we get better chances of sharing the pool
4141 ; entries.  Finally, we can normally do a better job of scheduling
4142 ; LDR instructions than we can with LDM.
4143 ; This pattern will only match if the one above did not.
4144 (define_split
4145   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4146         (match_operand:ANY64 1 "const_double_operand" ""))]
4147   "TARGET_ARM && reload_completed
4148    && arm_const_double_by_parts (operands[1])"
4149   [(set (match_dup 0) (match_dup 1))
4150    (set (match_dup 2) (match_dup 3))]
4151   "
4152   operands[2] = gen_highpart (SImode, operands[0]);
4153   operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4154                                    operands[1]);
4155   operands[0] = gen_lowpart (SImode, operands[0]);
4156   operands[1] = gen_lowpart (SImode, operands[1]);
4157   "
4158 )
4159
4160 (define_split
4161   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4162         (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4163   "TARGET_EITHER && reload_completed"
4164   [(set (match_dup 0) (match_dup 1))
4165    (set (match_dup 2) (match_dup 3))]
4166   "
4167   operands[2] = gen_highpart (SImode, operands[0]);
4168   operands[3] = gen_highpart (SImode, operands[1]);
4169   operands[0] = gen_lowpart (SImode, operands[0]);
4170   operands[1] = gen_lowpart (SImode, operands[1]);
4171
4172   /* Handle a partial overlap.  */
4173   if (rtx_equal_p (operands[0], operands[3]))
4174     {
4175       rtx tmp0 = operands[0];
4176       rtx tmp1 = operands[1];
4177
4178       operands[0] = operands[2];
4179       operands[1] = operands[3];
4180       operands[2] = tmp0;
4181       operands[3] = tmp1;
4182     }
4183   "
4184 )
4185
4186 ;; We can't actually do base+index doubleword loads if the index and
4187 ;; destination overlap.  Split here so that we at least have chance to
4188 ;; schedule.
4189 (define_split
4190   [(set (match_operand:DI 0 "s_register_operand" "")
4191         (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4192                          (match_operand:SI 2 "s_register_operand" ""))))]
4193   "TARGET_LDRD
4194   && reg_overlap_mentioned_p (operands[0], operands[1])
4195   && reg_overlap_mentioned_p (operands[0], operands[2])"
4196   [(set (match_dup 4)
4197         (plus:SI (match_dup 1)
4198                  (match_dup 2)))
4199    (set (match_dup 0)
4200         (mem:DI (match_dup 4)))]
4201   "
4202   operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4203   "
4204 )
4205
4206 ;;; ??? This should have alternatives for constants.
4207 ;;; ??? This was originally identical to the movdf_insn pattern.
4208 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4209 ;;; thumb_reorg with a memory reference.
4210 (define_insn "*thumb_movdi_insn"
4211   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4212         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
4213   "TARGET_THUMB
4214    && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4215    && (   register_operand (operands[0], DImode)
4216        || register_operand (operands[1], DImode))"
4217   "*
4218   {
4219   switch (which_alternative)
4220     {
4221     default:
4222     case 0:
4223       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4224         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
4225       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
4226     case 1:
4227       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4228     case 2:
4229       operands[1] = GEN_INT (- INTVAL (operands[1]));
4230       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4231     case 3:
4232       return \"ldmia\\t%1, {%0, %H0}\";
4233     case 4:
4234       return \"stmia\\t%0, {%1, %H1}\";
4235     case 5:
4236       return thumb_load_double_from_address (operands);
4237     case 6:
4238       operands[2] = gen_rtx_MEM (SImode,
4239                              plus_constant (XEXP (operands[0], 0), 4));
4240       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4241       return \"\";
4242     case 7:
4243       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4244         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4245       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4246     }
4247   }"
4248   [(set_attr "length" "4,4,6,2,2,6,4,4")
4249    (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4250    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4251 )
4252
4253 (define_expand "movsi"
4254   [(set (match_operand:SI 0 "general_operand" "")
4255         (match_operand:SI 1 "general_operand" ""))]
4256   "TARGET_EITHER"
4257   "
4258   if (TARGET_ARM)
4259     {
4260       /* Everything except mem = const or mem = mem can be done easily.  */
4261       if (GET_CODE (operands[0]) == MEM)
4262         operands[1] = force_reg (SImode, operands[1]);
4263       if (arm_general_register_operand (operands[0], SImode)
4264           && GET_CODE (operands[1]) == CONST_INT
4265           && !(const_ok_for_arm (INTVAL (operands[1]))
4266                || const_ok_for_arm (~INTVAL (operands[1]))))
4267         {
4268            arm_split_constant (SET, SImode, NULL_RTX,
4269                                INTVAL (operands[1]), operands[0], NULL_RTX,
4270                                optimize && !no_new_pseudos);
4271           DONE;
4272         }
4273     }
4274   else /* TARGET_THUMB....  */
4275     {
4276       if (!no_new_pseudos)
4277         {
4278           if (GET_CODE (operands[0]) != REG)
4279             operands[1] = force_reg (SImode, operands[1]);
4280         }
4281     }
4282     
4283   if (flag_pic
4284       && (CONSTANT_P (operands[1])
4285          || symbol_mentioned_p (operands[1])
4286          || label_mentioned_p (operands[1])))
4287     operands[1] = legitimize_pic_address (operands[1], SImode,
4288                                           (no_new_pseudos ? operands[0] : 0));
4289   "
4290 )
4291
4292 (define_insn "*arm_movsi_insn"
4293   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4294         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
4295   "TARGET_ARM && ! TARGET_IWMMXT
4296    && !(TARGET_HARD_FLOAT && TARGET_VFP)
4297    && (   register_operand (operands[0], SImode)
4298        || register_operand (operands[1], SImode))"
4299   "@
4300    mov%?\\t%0, %1
4301    mvn%?\\t%0, #%B1
4302    ldr%?\\t%0, %1
4303    str%?\\t%1, %0"
4304   [(set_attr "type" "*,*,load1,store1")
4305    (set_attr "predicable" "yes")
4306    (set_attr "pool_range" "*,*,4096,*")
4307    (set_attr "neg_pool_range" "*,*,4084,*")]
4308 )
4309
4310 (define_split
4311   [(set (match_operand:SI 0 "arm_general_register_operand" "")
4312         (match_operand:SI 1 "const_int_operand" ""))]
4313   "TARGET_ARM
4314   && (!(const_ok_for_arm (INTVAL (operands[1]))
4315         || const_ok_for_arm (~INTVAL (operands[1]))))"
4316   [(clobber (const_int 0))]
4317   "
4318   arm_split_constant (SET, SImode, NULL_RTX, 
4319                       INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4320   DONE;
4321   "
4322 )
4323
4324 (define_insn "*thumb_movsi_insn"
4325   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4326         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4327   "TARGET_THUMB
4328    && (   register_operand (operands[0], SImode) 
4329        || register_operand (operands[1], SImode))"
4330   "@
4331    mov  %0, %1
4332    mov  %0, %1
4333    #
4334    #
4335    ldmia\\t%1, {%0}
4336    stmia\\t%0, {%1}
4337    ldr\\t%0, %1
4338    str\\t%1, %0
4339    mov\\t%0, %1"
4340   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4341    (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4342    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4343 )
4344
4345 (define_split 
4346   [(set (match_operand:SI 0 "register_operand" "")
4347         (match_operand:SI 1 "const_int_operand" ""))]
4348   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4349   [(set (match_dup 0) (match_dup 1))
4350    (set (match_dup 0) (neg:SI (match_dup 0)))]
4351   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4352 )
4353
4354 (define_split 
4355   [(set (match_operand:SI 0 "register_operand" "")
4356         (match_operand:SI 1 "const_int_operand" ""))]
4357   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4358   [(set (match_dup 0) (match_dup 1))
4359    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4360   "
4361   {
4362     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4363     unsigned HOST_WIDE_INT mask = 0xff;
4364     int i;
4365     
4366     for (i = 0; i < 25; i++)
4367       if ((val & (mask << i)) == val)
4368         break;
4369
4370     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4371     if (i == 0)
4372       FAIL;
4373
4374     operands[1] = GEN_INT (val >> i);
4375     operands[2] = GEN_INT (i);
4376   }"
4377 )
4378
4379 ;; When generating pic, we need to load the symbol offset into a register.
4380 ;; So that the optimizer does not confuse this with a normal symbol load
4381 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
4382 ;; since that is the only type of relocation we can use.
4383
4384 ;; The rather odd constraints on the following are to force reload to leave
4385 ;; the insn alone, and to force the minipool generation pass to then move
4386 ;; the GOT symbol to memory.
4387
4388 (define_insn "pic_load_addr_arm"
4389   [(set (match_operand:SI 0 "s_register_operand" "=r")
4390         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4391   "TARGET_ARM && flag_pic"
4392   "ldr%?\\t%0, %1"
4393   [(set_attr "type" "load1")
4394    (set (attr "pool_range")     (const_int 4096))
4395    (set (attr "neg_pool_range") (const_int 4084))]
4396 )
4397
4398 (define_insn "pic_load_addr_thumb"
4399   [(set (match_operand:SI 0 "s_register_operand" "=l")
4400         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4401   "TARGET_THUMB && flag_pic"
4402   "ldr\\t%0, %1"
4403   [(set_attr "type" "load1")
4404    (set (attr "pool_range") (const_int 1024))]
4405 )
4406
4407 ;; This variant is used for AOF assembly, since it needs to mention the
4408 ;; pic register in the rtl.
4409 (define_expand "pic_load_addr_based"
4410   [(set (match_operand:SI 0 "s_register_operand" "")
4411         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4412   "TARGET_ARM && flag_pic"
4413   "operands[2] = pic_offset_table_rtx;"
4414 )
4415
4416 (define_insn "*pic_load_addr_based_insn"
4417   [(set (match_operand:SI 0 "s_register_operand" "=r")
4418         (unspec:SI [(match_operand 1 "" "")
4419                     (match_operand 2 "s_register_operand" "r")]
4420                    UNSPEC_PIC_SYM))]
4421   "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4422   "*
4423 #ifdef AOF_ASSEMBLER
4424   operands[1] = aof_pic_entry (operands[1]);
4425 #endif
4426   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4427   return \"\";
4428   "
4429   [(set_attr "type" "load1")
4430    (set (attr "pool_range")
4431         (if_then_else (eq_attr "is_thumb" "yes")
4432                       (const_int 1024)
4433                       (const_int 4096)))
4434    (set (attr "neg_pool_range")
4435         (if_then_else (eq_attr "is_thumb" "yes")
4436                       (const_int 0)
4437                       (const_int 4084)))]
4438 )
4439
4440 (define_insn "pic_add_dot_plus_four"
4441   [(set (match_operand:SI 0 "register_operand" "+r")
4442         (unspec:SI [(plus:SI (match_dup 0)
4443                              (const (plus:SI (pc) (const_int 4))))]
4444                    UNSPEC_PIC_BASE))
4445    (use (label_ref (match_operand 1 "" "")))]
4446   "TARGET_THUMB && flag_pic"
4447   "*
4448   (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4449                              CODE_LABEL_NUMBER (operands[1]));
4450   return \"add\\t%0, %|pc\";
4451   "
4452   [(set_attr "length" "2")]
4453 )
4454
4455 (define_insn "pic_add_dot_plus_eight"
4456   [(set (match_operand:SI 0 "register_operand" "+r")
4457         (unspec:SI [(plus:SI (match_dup 0)
4458                              (const (plus:SI (pc) (const_int 8))))]
4459                    UNSPEC_PIC_BASE))
4460    (use (label_ref (match_operand 1 "" "")))]
4461   "TARGET_ARM && flag_pic"
4462   "*
4463     (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4464                                CODE_LABEL_NUMBER (operands[1]));
4465     return \"add%?\\t%0, %|pc, %0\";
4466   "
4467   [(set_attr "predicable" "yes")]
4468 )
4469
4470 (define_expand "builtin_setjmp_receiver"
4471   [(label_ref (match_operand 0 "" ""))]
4472   "flag_pic"
4473   "
4474 {
4475   /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4476      register.  */
4477   arm_load_pic_register (3);
4478   DONE;
4479 }")
4480
4481 ;; If copying one reg to another we can set the condition codes according to
4482 ;; its value.  Such a move is common after a return from subroutine and the
4483 ;; result is being tested against zero.
4484
4485 (define_insn "*movsi_compare0"
4486   [(set (reg:CC CC_REGNUM)
4487         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4488                     (const_int 0)))
4489    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4490         (match_dup 1))]
4491   "TARGET_ARM"
4492   "@
4493    cmp%?\\t%0, #0
4494    sub%?s\\t%0, %1, #0"
4495   [(set_attr "conds" "set")]
4496 )
4497
4498 ;; Subroutine to store a half word from a register into memory.
4499 ;; Operand 0 is the source register (HImode)
4500 ;; Operand 1 is the destination address in a register (SImode)
4501
4502 ;; In both this routine and the next, we must be careful not to spill
4503 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4504 ;; can generate unrecognizable rtl.
4505
4506 (define_expand "storehi"
4507   [;; store the low byte
4508    (set (match_operand 1 "" "") (match_dup 3))
4509    ;; extract the high byte
4510    (set (match_dup 2)
4511         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4512    ;; store the high byte
4513    (set (match_dup 4) (match_dup 5))]
4514   "TARGET_ARM"
4515   "
4516   {
4517     rtx op1 = operands[1];
4518     rtx addr = XEXP (op1, 0);
4519     enum rtx_code code = GET_CODE (addr);
4520
4521     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4522         || code == MINUS)
4523       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4524
4525     operands[4] = adjust_address (op1, QImode, 1);
4526     operands[1] = adjust_address (operands[1], QImode, 0);
4527     operands[3] = gen_lowpart (QImode, operands[0]);
4528     operands[0] = gen_lowpart (SImode, operands[0]);
4529     operands[2] = gen_reg_rtx (SImode);
4530     operands[5] = gen_lowpart (QImode, operands[2]);
4531   }"
4532 )
4533
4534 (define_expand "storehi_bigend"
4535   [(set (match_dup 4) (match_dup 3))
4536    (set (match_dup 2)
4537         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4538    (set (match_operand 1 "" "") (match_dup 5))]
4539   "TARGET_ARM"
4540   "
4541   {
4542     rtx op1 = operands[1];
4543     rtx addr = XEXP (op1, 0);
4544     enum rtx_code code = GET_CODE (addr);
4545
4546     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4547         || code == MINUS)
4548       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4549
4550     operands[4] = adjust_address (op1, QImode, 1);
4551     operands[1] = adjust_address (operands[1], QImode, 0);
4552     operands[3] = gen_lowpart (QImode, operands[0]);
4553     operands[0] = gen_lowpart (SImode, operands[0]);
4554     operands[2] = gen_reg_rtx (SImode);
4555     operands[5] = gen_lowpart (QImode, operands[2]);
4556   }"
4557 )
4558
4559 ;; Subroutine to store a half word integer constant into memory.
4560 (define_expand "storeinthi"
4561   [(set (match_operand 0 "" "")
4562         (match_operand 1 "" ""))
4563    (set (match_dup 3) (match_dup 2))]
4564   "TARGET_ARM"
4565   "
4566   {
4567     HOST_WIDE_INT value = INTVAL (operands[1]);
4568     rtx addr = XEXP (operands[0], 0);
4569     rtx op0 = operands[0];
4570     enum rtx_code code = GET_CODE (addr);
4571
4572     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4573         || code == MINUS)
4574       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4575
4576     operands[1] = gen_reg_rtx (SImode);
4577     if (BYTES_BIG_ENDIAN)
4578       {
4579         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4580         if ((value & 255) == ((value >> 8) & 255))
4581           operands[2] = operands[1];
4582         else
4583           {
4584             operands[2] = gen_reg_rtx (SImode);
4585             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4586           }
4587       }
4588     else
4589       {
4590         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4591         if ((value & 255) == ((value >> 8) & 255))
4592           operands[2] = operands[1];
4593         else
4594           {
4595             operands[2] = gen_reg_rtx (SImode);
4596             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4597           }
4598       }
4599
4600     operands[3] = adjust_address (op0, QImode, 1);
4601     operands[0] = adjust_address (operands[0], QImode, 0);
4602     operands[2] = gen_lowpart (QImode, operands[2]);
4603     operands[1] = gen_lowpart (QImode, operands[1]);
4604   }"
4605 )
4606
4607 (define_expand "storehi_single_op"
4608   [(set (match_operand:HI 0 "memory_operand" "")
4609         (match_operand:HI 1 "general_operand" ""))]
4610   "TARGET_ARM && arm_arch4"
4611   "
4612   if (!s_register_operand (operands[1], HImode))
4613     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4614   "
4615 )
4616
4617 (define_expand "movhi"
4618   [(set (match_operand:HI 0 "general_operand" "")
4619         (match_operand:HI 1 "general_operand" ""))]
4620   "TARGET_EITHER"
4621   "
4622   if (TARGET_ARM)
4623     {
4624       if (!no_new_pseudos)
4625         {
4626           if (GET_CODE (operands[0]) == MEM)
4627             {
4628               if (arm_arch4)
4629                 {
4630                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4631                   DONE;
4632                 }
4633               if (GET_CODE (operands[1]) == CONST_INT)
4634                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4635               else
4636                 {
4637                   if (GET_CODE (operands[1]) == MEM)
4638                     operands[1] = force_reg (HImode, operands[1]);
4639                   if (BYTES_BIG_ENDIAN)
4640                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4641                   else
4642                    emit_insn (gen_storehi (operands[1], operands[0]));
4643                 }
4644               DONE;
4645             }
4646           /* Sign extend a constant, and keep it in an SImode reg.  */
4647           else if (GET_CODE (operands[1]) == CONST_INT)
4648             {
4649               rtx reg = gen_reg_rtx (SImode);
4650               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4651
4652               /* If the constant is already valid, leave it alone.  */
4653               if (!const_ok_for_arm (val))
4654                 {
4655                   /* If setting all the top bits will make the constant 
4656                      loadable in a single instruction, then set them.  
4657                      Otherwise, sign extend the number.  */
4658
4659                   if (const_ok_for_arm (~(val | ~0xffff)))
4660                     val |= ~0xffff;
4661                   else if (val & 0x8000)
4662                     val |= ~0xffff;
4663                 }
4664
4665               emit_insn (gen_movsi (reg, GEN_INT (val)));
4666               operands[1] = gen_lowpart (HImode, reg);
4667             }
4668           else if (arm_arch4 && optimize && !no_new_pseudos
4669                    && GET_CODE (operands[1]) == MEM)
4670             {
4671               rtx reg = gen_reg_rtx (SImode);
4672
4673               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4674               operands[1] = gen_lowpart (HImode, reg);
4675             }
4676           else if (!arm_arch4)
4677             {
4678               if (GET_CODE (operands[1]) == MEM)
4679                 {
4680                   rtx base;
4681                   rtx offset = const0_rtx;
4682                   rtx reg = gen_reg_rtx (SImode);
4683
4684                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4685                        || (GET_CODE (base) == PLUS
4686                            && (GET_CODE (offset = XEXP (base, 1))
4687                                == CONST_INT)
4688                            && ((INTVAL(offset) & 1) != 1)
4689                            && GET_CODE (base = XEXP (base, 0)) == REG))
4690                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4691                     {
4692                       rtx new;
4693
4694                       new = widen_memory_access (operands[1], SImode,
4695                                                  ((INTVAL (offset) & ~3)
4696                                                   - INTVAL (offset)));
4697                       emit_insn (gen_movsi (reg, new));
4698                       if (((INTVAL (offset) & 2) != 0)
4699                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4700                         {
4701                           rtx reg2 = gen_reg_rtx (SImode);
4702
4703                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4704                           reg = reg2;
4705                         }
4706                     }
4707                   else
4708                     emit_insn (gen_movhi_bytes (reg, operands[1]));
4709
4710                   operands[1] = gen_lowpart (HImode, reg);
4711                }
4712            }
4713         }
4714       /* Handle loading a large integer during reload.  */
4715       else if (GET_CODE (operands[1]) == CONST_INT
4716                && !const_ok_for_arm (INTVAL (operands[1]))
4717                && !const_ok_for_arm (~INTVAL (operands[1])))
4718         {
4719           /* Writing a constant to memory needs a scratch, which should
4720              be handled with SECONDARY_RELOADs.  */
4721           gcc_assert (GET_CODE (operands[0]) == REG);
4722
4723           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4724           emit_insn (gen_movsi (operands[0], operands[1]));
4725           DONE;
4726        }
4727     }
4728   else /* TARGET_THUMB */
4729     {
4730       if (!no_new_pseudos)
4731         {
4732           if (GET_CODE (operands[1]) == CONST_INT)
4733             {
4734               rtx reg = gen_reg_rtx (SImode);
4735
4736               emit_insn (gen_movsi (reg, operands[1]));
4737               operands[1] = gen_lowpart (HImode, reg);
4738             }
4739
4740           /* ??? We shouldn't really get invalid addresses here, but this can
4741              happen if we are passed a SP (never OK for HImode/QImode) or 
4742              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4743              HImode/QImode) relative address.  */
4744           /* ??? This should perhaps be fixed elsewhere, for instance, in
4745              fixup_stack_1, by checking for other kinds of invalid addresses,
4746              e.g. a bare reference to a virtual register.  This may confuse the
4747              alpha though, which must handle this case differently.  */
4748           if (GET_CODE (operands[0]) == MEM
4749               && !memory_address_p (GET_MODE (operands[0]),
4750                                     XEXP (operands[0], 0)))
4751             operands[0]
4752               = replace_equiv_address (operands[0],
4753                                        copy_to_reg (XEXP (operands[0], 0)));
4754    
4755           if (GET_CODE (operands[1]) == MEM
4756               && !memory_address_p (GET_MODE (operands[1]),
4757                                     XEXP (operands[1], 0)))
4758             operands[1]
4759               = replace_equiv_address (operands[1],
4760                                        copy_to_reg (XEXP (operands[1], 0)));
4761
4762           if (GET_CODE (operands[1]) == MEM && optimize > 0)
4763             {
4764               rtx reg = gen_reg_rtx (SImode);
4765
4766               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4767               operands[1] = gen_lowpart (HImode, reg);
4768             }
4769
4770           if (GET_CODE (operands[0]) == MEM)
4771             operands[1] = force_reg (HImode, operands[1]);
4772         }
4773       else if (GET_CODE (operands[1]) == CONST_INT
4774                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4775         {
4776           /* Handle loading a large integer during reload.  */
4777
4778           /* Writing a constant to memory needs a scratch, which should
4779              be handled with SECONDARY_RELOADs.  */
4780           gcc_assert (GET_CODE (operands[0]) == REG);
4781
4782           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4783           emit_insn (gen_movsi (operands[0], operands[1]));
4784           DONE;
4785         }
4786     }
4787   "
4788 )
4789
4790 (define_insn "*thumb_movhi_insn"
4791   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4792         (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
4793   "TARGET_THUMB
4794    && (   register_operand (operands[0], HImode)
4795        || register_operand (operands[1], HImode))"
4796   "*
4797   switch (which_alternative)
4798     {
4799     case 0: return \"add        %0, %1, #0\";
4800     case 2: return \"strh       %1, %0\";
4801     case 3: return \"mov        %0, %1\";
4802     case 4: return \"mov        %0, %1\";
4803     case 5: return \"mov        %0, %1\";
4804     default: gcc_unreachable ();
4805     case 1:
4806       /* The stack pointer can end up being taken as an index register.
4807           Catch this case here and deal with it.  */
4808       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4809           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4810           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4811         {
4812           rtx ops[2];
4813           ops[0] = operands[0];
4814           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4815       
4816           output_asm_insn (\"mov        %0, %1\", ops);
4817
4818           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4819     
4820         }
4821       return \"ldrh     %0, %1\";
4822     }"
4823   [(set_attr "length" "2,4,2,2,2,2")
4824    (set_attr "type" "*,load1,store1,*,*,*")]
4825 )
4826
4827
4828 (define_expand "movhi_bytes"
4829   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4830    (set (match_dup 3)
4831         (zero_extend:SI (match_dup 6)))
4832    (set (match_operand:SI 0 "" "")
4833          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4834   "TARGET_ARM"
4835   "
4836   {
4837     rtx mem1, mem2;
4838     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4839
4840     mem1 = change_address (operands[1], QImode, addr);
4841     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
4842     operands[0] = gen_lowpart (SImode, operands[0]);
4843     operands[1] = mem1;
4844     operands[2] = gen_reg_rtx (SImode);
4845     operands[3] = gen_reg_rtx (SImode);
4846     operands[6] = mem2;
4847
4848     if (BYTES_BIG_ENDIAN)
4849       {
4850         operands[4] = operands[2];
4851         operands[5] = operands[3];
4852       }
4853     else
4854       {
4855         operands[4] = operands[3];
4856         operands[5] = operands[2];
4857       }
4858   }"
4859 )
4860
4861 (define_expand "movhi_bigend"
4862   [(set (match_dup 2)
4863         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4864                    (const_int 16)))
4865    (set (match_dup 3)
4866         (ashiftrt:SI (match_dup 2) (const_int 16)))
4867    (set (match_operand:HI 0 "s_register_operand" "")
4868         (match_dup 4))]
4869   "TARGET_ARM"
4870   "
4871   operands[2] = gen_reg_rtx (SImode);
4872   operands[3] = gen_reg_rtx (SImode);
4873   operands[4] = gen_lowpart (HImode, operands[3]);
4874   "
4875 )
4876
4877 ;; Pattern to recognize insn generated default case above
4878 (define_insn "*movhi_insn_arch4"
4879   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4880         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4881   "TARGET_ARM
4882    && arm_arch4
4883    && (GET_CODE (operands[1]) != CONST_INT
4884        || const_ok_for_arm (INTVAL (operands[1]))
4885        || const_ok_for_arm (~INTVAL (operands[1])))"
4886   "@
4887    mov%?\\t%0, %1\\t%@ movhi
4888    mvn%?\\t%0, #%B1\\t%@ movhi
4889    str%?h\\t%1, %0\\t%@ movhi
4890    ldr%?h\\t%0, %1\\t%@ movhi"
4891   [(set_attr "type" "*,*,store1,load1")
4892    (set_attr "predicable" "yes")
4893    (set_attr "pool_range" "*,*,*,256")
4894    (set_attr "neg_pool_range" "*,*,*,244")]
4895 )
4896
4897 (define_insn "*movhi_bytes"
4898   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4899         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4900   "TARGET_ARM"
4901   "@
4902    mov%?\\t%0, %1\\t%@ movhi
4903    mvn%?\\t%0, #%B1\\t%@ movhi"
4904   [(set_attr "predicable" "yes")]
4905 )
4906
4907 (define_expand "thumb_movhi_clobber"
4908   [(set (match_operand:HI     0 "memory_operand"   "")
4909         (match_operand:HI     1 "register_operand" ""))
4910    (clobber (match_operand:DI 2 "register_operand" ""))]
4911   "TARGET_THUMB"
4912   "
4913   if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
4914       && REGNO (operands[1]) <= LAST_LO_REGNUM)
4915     {
4916       emit_insn (gen_movhi (operands[0], operands[1]));
4917       DONE;
4918     }
4919   /* XXX Fixme, need to handle other cases here as well.  */
4920   gcc_unreachable ();
4921   "
4922 )
4923         
4924 ;; We use a DImode scratch because we may occasionally need an additional
4925 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4926 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4927 (define_expand "reload_outhi"
4928   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4929               (match_operand:HI 1 "s_register_operand"        "r")
4930               (match_operand:DI 2 "s_register_operand"        "=&l")])]
4931   "TARGET_EITHER"
4932   "if (TARGET_ARM)
4933      arm_reload_out_hi (operands);
4934    else
4935      thumb_reload_out_hi (operands);
4936   DONE;
4937   "
4938 )
4939
4940 (define_expand "reload_inhi"
4941   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4942               (match_operand:HI 1 "arm_reload_memory_operand" "o")
4943               (match_operand:DI 2 "s_register_operand" "=&r")])]
4944   "TARGET_EITHER"
4945   "
4946   if (TARGET_ARM)
4947     arm_reload_in_hi (operands);
4948   else
4949     thumb_reload_out_hi (operands);
4950   DONE;
4951 ")
4952
4953 (define_expand "movqi"
4954   [(set (match_operand:QI 0 "general_operand" "")
4955         (match_operand:QI 1 "general_operand" ""))]
4956   "TARGET_EITHER"
4957   "
4958   /* Everything except mem = const or mem = mem can be done easily */
4959
4960   if (!no_new_pseudos)
4961     {
4962       if (GET_CODE (operands[1]) == CONST_INT)
4963         {
4964           rtx reg = gen_reg_rtx (SImode);
4965
4966           emit_insn (gen_movsi (reg, operands[1]));
4967           operands[1] = gen_lowpart (QImode, reg);
4968         }
4969
4970       if (TARGET_THUMB)
4971         {
4972           /* ??? We shouldn't really get invalid addresses here, but this can
4973              happen if we are passed a SP (never OK for HImode/QImode) or
4974              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4975              HImode/QImode) relative address.  */
4976           /* ??? This should perhaps be fixed elsewhere, for instance, in
4977              fixup_stack_1, by checking for other kinds of invalid addresses,
4978              e.g. a bare reference to a virtual register.  This may confuse the
4979              alpha though, which must handle this case differently.  */
4980           if (GET_CODE (operands[0]) == MEM
4981               && !memory_address_p (GET_MODE (operands[0]),
4982                                      XEXP (operands[0], 0)))
4983             operands[0]
4984               = replace_equiv_address (operands[0],
4985                                        copy_to_reg (XEXP (operands[0], 0)));
4986           if (GET_CODE (operands[1]) == MEM
4987               && !memory_address_p (GET_MODE (operands[1]),
4988                                     XEXP (operands[1], 0)))
4989              operands[1]
4990                = replace_equiv_address (operands[1],
4991                                         copy_to_reg (XEXP (operands[1], 0)));
4992         }
4993
4994       if (GET_CODE (operands[1]) == MEM && optimize > 0)
4995         {
4996           rtx reg = gen_reg_rtx (SImode);
4997
4998           emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4999           operands[1] = gen_lowpart (QImode, reg);
5000         }
5001
5002       if (GET_CODE (operands[0]) == MEM)
5003         operands[1] = force_reg (QImode, operands[1]);
5004     }
5005   else if (TARGET_THUMB
5006            && GET_CODE (operands[1]) == CONST_INT
5007            && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
5008     {
5009       /* Handle loading a large integer during reload.  */
5010
5011       /* Writing a constant to memory needs a scratch, which should
5012          be handled with SECONDARY_RELOADs.  */
5013       gcc_assert (GET_CODE (operands[0]) == REG);
5014
5015       operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5016       emit_insn (gen_movsi (operands[0], operands[1]));
5017       DONE;
5018     }
5019   "
5020 )
5021
5022
5023 (define_insn "*arm_movqi_insn"
5024   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5025         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5026   "TARGET_ARM
5027    && (   register_operand (operands[0], QImode)
5028        || register_operand (operands[1], QImode))"
5029   "@
5030    mov%?\\t%0, %1
5031    mvn%?\\t%0, #%B1
5032    ldr%?b\\t%0, %1
5033    str%?b\\t%1, %0"
5034   [(set_attr "type" "*,*,load1,store1")
5035    (set_attr "predicable" "yes")]
5036 )
5037
5038 (define_insn "*thumb_movqi_insn"
5039   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5040         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
5041   "TARGET_THUMB
5042    && (   register_operand (operands[0], QImode)
5043        || register_operand (operands[1], QImode))"
5044   "@
5045    add\\t%0, %1, #0
5046    ldrb\\t%0, %1
5047    strb\\t%1, %0
5048    mov\\t%0, %1
5049    mov\\t%0, %1
5050    mov\\t%0, %1"
5051   [(set_attr "length" "2")
5052    (set_attr "type" "*,load1,store1,*,*,*")
5053    (set_attr "pool_range" "*,32,*,*,*,*")]
5054 )
5055
5056 (define_expand "movsf"
5057   [(set (match_operand:SF 0 "general_operand" "")
5058         (match_operand:SF 1 "general_operand" ""))]
5059   "TARGET_EITHER"
5060   "
5061   if (TARGET_ARM)
5062     {
5063       if (GET_CODE (operands[0]) == MEM)
5064         operands[1] = force_reg (SFmode, operands[1]);
5065     }
5066   else /* TARGET_THUMB */
5067     {
5068       if (!no_new_pseudos)
5069         {
5070            if (GET_CODE (operands[0]) != REG)
5071              operands[1] = force_reg (SFmode, operands[1]);
5072         }
5073     }
5074   "
5075 )
5076
5077 (define_split
5078   [(set (match_operand:SF 0 "nonimmediate_operand" "")
5079         (match_operand:SF 1 "immediate_operand" ""))]
5080   "TARGET_ARM
5081    && !(TARGET_HARD_FLOAT && TARGET_FPA)
5082    && reload_completed
5083    && GET_CODE (operands[1]) == CONST_DOUBLE"
5084   [(set (match_dup 2) (match_dup 3))]
5085   "
5086   operands[2] = gen_lowpart (SImode, operands[0]);
5087   operands[3] = gen_lowpart (SImode, operands[1]);
5088   if (operands[2] == 0 || operands[3] == 0)
5089     FAIL;
5090   "
5091 )
5092
5093 (define_insn "*arm_movsf_soft_insn"
5094   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5095         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
5096   "TARGET_ARM
5097    && TARGET_SOFT_FLOAT
5098    && (GET_CODE (operands[0]) != MEM
5099        || register_operand (operands[1], SFmode))"
5100   "@
5101    mov%?\\t%0, %1
5102    ldr%?\\t%0, %1\\t%@ float
5103    str%?\\t%1, %0\\t%@ float"
5104   [(set_attr "length" "4,4,4")
5105    (set_attr "predicable" "yes")
5106    (set_attr "type" "*,load1,store1")
5107    (set_attr "pool_range" "*,4096,*")
5108    (set_attr "neg_pool_range" "*,4084,*")]
5109 )
5110
5111 ;;; ??? This should have alternatives for constants.
5112 (define_insn "*thumb_movsf_insn"
5113   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5114         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5115   "TARGET_THUMB
5116    && (   register_operand (operands[0], SFmode) 
5117        || register_operand (operands[1], SFmode))"
5118   "@
5119    add\\t%0, %1, #0
5120    ldmia\\t%1, {%0}
5121    stmia\\t%0, {%1}
5122    ldr\\t%0, %1
5123    str\\t%1, %0
5124    mov\\t%0, %1
5125    mov\\t%0, %1"
5126   [(set_attr "length" "2")
5127    (set_attr "type" "*,load1,store1,load1,store1,*,*")
5128    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5129 )
5130
5131 (define_expand "movdf"
5132   [(set (match_operand:DF 0 "general_operand" "")
5133         (match_operand:DF 1 "general_operand" ""))]
5134   "TARGET_EITHER"
5135   "
5136   if (TARGET_ARM)
5137     {
5138       if (GET_CODE (operands[0]) == MEM)
5139         operands[1] = force_reg (DFmode, operands[1]);
5140     }
5141   else /* TARGET_THUMB */
5142     {
5143       if (!no_new_pseudos)
5144         {
5145           if (GET_CODE (operands[0]) != REG)
5146             operands[1] = force_reg (DFmode, operands[1]);
5147         }
5148     }
5149   "
5150 )
5151
5152 ;; Reloading a df mode value stored in integer regs to memory can require a
5153 ;; scratch reg.
5154 (define_expand "reload_outdf"
5155   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5156    (match_operand:DF 1 "s_register_operand" "r")
5157    (match_operand:SI 2 "s_register_operand" "=&r")]
5158   "TARGET_ARM"
5159   "
5160   {
5161     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5162
5163     if (code == REG)
5164       operands[2] = XEXP (operands[0], 0);
5165     else if (code == POST_INC || code == PRE_DEC)
5166       {
5167         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5168         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5169         emit_insn (gen_movdi (operands[0], operands[1]));
5170         DONE;
5171       }
5172     else if (code == PRE_INC)
5173       {
5174         rtx reg = XEXP (XEXP (operands[0], 0), 0);
5175
5176         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5177         operands[2] = reg;
5178       }
5179     else if (code == POST_DEC)
5180       operands[2] = XEXP (XEXP (operands[0], 0), 0);
5181     else
5182       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5183                              XEXP (XEXP (operands[0], 0), 1)));
5184
5185     emit_insn (gen_rtx_SET (VOIDmode,
5186                             replace_equiv_address (operands[0], operands[2]),
5187                             operands[1]));
5188
5189     if (code == POST_DEC)
5190       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5191
5192     DONE;
5193   }"
5194 )
5195
5196 (define_insn "*movdf_soft_insn"
5197   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5198         (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
5199   "TARGET_ARM && TARGET_SOFT_FLOAT
5200   "
5201   "*
5202   switch (which_alternative)
5203     {
5204     case 0:
5205     case 1:
5206     case 2:
5207       return \"#\";
5208     default:
5209       return output_move_double (operands);
5210     }
5211   "
5212   [(set_attr "length" "8,12,16,8,8")
5213    (set_attr "type" "*,*,*,load2,store2")
5214    (set_attr "pool_range" "1020")
5215    (set_attr "neg_pool_range" "1008")]
5216 )
5217
5218 ;;; ??? This should have alternatives for constants.
5219 ;;; ??? This was originally identical to the movdi_insn pattern.
5220 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5221 ;;; thumb_reorg with a memory reference.
5222 (define_insn "*thumb_movdf_insn"
5223   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5224         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5225   "TARGET_THUMB
5226    && (   register_operand (operands[0], DFmode)
5227        || register_operand (operands[1], DFmode))"
5228   "*
5229   switch (which_alternative)
5230     {
5231     default:
5232     case 0:
5233       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5234         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5235       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5236     case 1:
5237       return \"ldmia\\t%1, {%0, %H0}\";
5238     case 2:
5239       return \"stmia\\t%0, {%1, %H1}\";
5240     case 3:
5241       return thumb_load_double_from_address (operands);
5242     case 4:
5243       operands[2] = gen_rtx_MEM (SImode,
5244                                  plus_constant (XEXP (operands[0], 0), 4));
5245       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5246       return \"\";
5247     case 5:
5248       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5249         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5250       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5251     }
5252   "
5253   [(set_attr "length" "4,2,2,6,4,4")
5254    (set_attr "type" "*,load2,store2,load2,store2,*")
5255    (set_attr "pool_range" "*,*,*,1020,*,*")]
5256 )
5257
5258 (define_expand "movxf"
5259   [(set (match_operand:XF 0 "general_operand" "")
5260         (match_operand:XF 1 "general_operand" ""))]
5261   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
5262   "
5263   if (GET_CODE (operands[0]) == MEM)
5264     operands[1] = force_reg (XFmode, operands[1]);
5265   "
5266 )
5267
5268 ;; Vector Moves
5269 (define_expand "movv2si"
5270   [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5271         (match_operand:V2SI 1 "general_operand" ""))]
5272   "TARGET_REALLY_IWMMXT"
5273 {
5274 })
5275
5276 (define_expand "movv4hi"
5277   [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5278         (match_operand:V4HI 1 "general_operand" ""))]
5279   "TARGET_REALLY_IWMMXT"
5280 {
5281 })
5282
5283 (define_expand "movv8qi"
5284   [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5285         (match_operand:V8QI 1 "general_operand" ""))]
5286   "TARGET_REALLY_IWMMXT"
5287 {
5288 })
5289 \f
5290
5291 ;; load- and store-multiple insns
5292 ;; The arm can load/store any set of registers, provided that they are in
5293 ;; ascending order; but that is beyond GCC so stick with what it knows.
5294
5295 (define_expand "load_multiple"
5296   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5297                           (match_operand:SI 1 "" ""))
5298                      (use (match_operand:SI 2 "" ""))])]
5299   "TARGET_ARM"
5300 {
5301   HOST_WIDE_INT offset = 0;
5302
5303   /* Support only fixed point registers.  */
5304   if (GET_CODE (operands[2]) != CONST_INT
5305       || INTVAL (operands[2]) > 14
5306       || INTVAL (operands[2]) < 2
5307       || GET_CODE (operands[1]) != MEM
5308       || GET_CODE (operands[0]) != REG
5309       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5310       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5311     FAIL;
5312
5313   operands[3]
5314     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5315                              force_reg (SImode, XEXP (operands[1], 0)),
5316                              TRUE, FALSE, operands[1], &offset);
5317 })
5318
5319 ;; Load multiple with write-back
5320
5321 (define_insn "*ldmsi_postinc4"
5322   [(match_parallel 0 "load_multiple_operation"
5323     [(set (match_operand:SI 1 "s_register_operand" "=r")
5324           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5325                    (const_int 16)))
5326      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5327           (mem:SI (match_dup 2)))
5328      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5329           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5330      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5331           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5332      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5333           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5334   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5335   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5336   [(set_attr "type" "load4")
5337    (set_attr "predicable" "yes")]
5338 )
5339
5340 (define_insn "*ldmsi_postinc4_thumb"
5341   [(match_parallel 0 "load_multiple_operation"
5342     [(set (match_operand:SI 1 "s_register_operand" "=l")
5343           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5344                    (const_int 16)))
5345      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5346           (mem:SI (match_dup 2)))
5347      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5348           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5349      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5350           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5351      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5352           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5353   "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5354   "ldmia\\t%1!, {%3, %4, %5, %6}"
5355   [(set_attr "type" "load4")]
5356 )
5357
5358 (define_insn "*ldmsi_postinc3"
5359   [(match_parallel 0 "load_multiple_operation"
5360     [(set (match_operand:SI 1 "s_register_operand" "=r")
5361           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5362                    (const_int 12)))
5363      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5364           (mem:SI (match_dup 2)))
5365      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5366           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5367      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5368           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5369   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5370   "ldm%?ia\\t%1!, {%3, %4, %5}"
5371   [(set_attr "type" "load3")
5372    (set_attr "predicable" "yes")]
5373 )
5374
5375 (define_insn "*ldmsi_postinc2"
5376   [(match_parallel 0 "load_multiple_operation"
5377     [(set (match_operand:SI 1 "s_register_operand" "=r")
5378           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5379                    (const_int 8)))
5380      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5381           (mem:SI (match_dup 2)))
5382      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5383           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5384   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5385   "ldm%?ia\\t%1!, {%3, %4}"
5386   [(set_attr "type" "load2")
5387    (set_attr "predicable" "yes")]
5388 )
5389
5390 ;; Ordinary load multiple
5391
5392 (define_insn "*ldmsi4"
5393   [(match_parallel 0 "load_multiple_operation"
5394     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5395           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5396      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5397           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5398      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5399           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5400      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5401           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5402   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5403   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5404   [(set_attr "type" "load4")
5405    (set_attr "predicable" "yes")]
5406 )
5407
5408 (define_insn "*ldmsi3"
5409   [(match_parallel 0 "load_multiple_operation"
5410     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5411           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5412      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5413           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5414      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5415           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5416   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5417   "ldm%?ia\\t%1, {%2, %3, %4}"
5418   [(set_attr "type" "load3")
5419    (set_attr "predicable" "yes")]
5420 )
5421
5422 (define_insn "*ldmsi2"
5423   [(match_parallel 0 "load_multiple_operation"
5424     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5425           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5426      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5427           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5428   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5429   "ldm%?ia\\t%1, {%2, %3}"
5430   [(set_attr "type" "load2")
5431    (set_attr "predicable" "yes")]
5432 )
5433
5434 (define_expand "store_multiple"
5435   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5436                           (match_operand:SI 1 "" ""))
5437                      (use (match_operand:SI 2 "" ""))])]
5438   "TARGET_ARM"
5439 {
5440   HOST_WIDE_INT offset = 0;
5441
5442   /* Support only fixed point registers.  */
5443   if (GET_CODE (operands[2]) != CONST_INT
5444       || INTVAL (operands[2]) > 14
5445       || INTVAL (operands[2]) < 2
5446       || GET_CODE (operands[1]) != REG
5447       || GET_CODE (operands[0]) != MEM
5448       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5449       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5450     FAIL;
5451
5452   operands[3]
5453     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5454                               force_reg (SImode, XEXP (operands[0], 0)),
5455                               TRUE, FALSE, operands[0], &offset);
5456 })
5457
5458 ;; Store multiple with write-back
5459
5460 (define_insn "*stmsi_postinc4"
5461   [(match_parallel 0 "store_multiple_operation"
5462     [(set (match_operand:SI 1 "s_register_operand" "=r")
5463           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5464                    (const_int 16)))
5465      (set (mem:SI (match_dup 2))
5466           (match_operand:SI 3 "arm_hard_register_operand" ""))
5467      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5468           (match_operand:SI 4 "arm_hard_register_operand" ""))
5469      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5470           (match_operand:SI 5 "arm_hard_register_operand" ""))
5471      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5472           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5473   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5474   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5475   [(set_attr "predicable" "yes")
5476    (set_attr "type" "store4")]
5477 )
5478
5479 (define_insn "*stmsi_postinc4_thumb"
5480   [(match_parallel 0 "store_multiple_operation"
5481     [(set (match_operand:SI 1 "s_register_operand" "=l")
5482           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5483                    (const_int 16)))
5484      (set (mem:SI (match_dup 2))
5485           (match_operand:SI 3 "arm_hard_register_operand" ""))
5486      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5487           (match_operand:SI 4 "arm_hard_register_operand" ""))
5488      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5489           (match_operand:SI 5 "arm_hard_register_operand" ""))
5490      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5491           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5492   "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5493   "stmia\\t%1!, {%3, %4, %5, %6}"
5494   [(set_attr "type" "store4")]
5495 )
5496
5497 (define_insn "*stmsi_postinc3"
5498   [(match_parallel 0 "store_multiple_operation"
5499     [(set (match_operand:SI 1 "s_register_operand" "=r")
5500           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5501                    (const_int 12)))
5502      (set (mem:SI (match_dup 2))
5503           (match_operand:SI 3 "arm_hard_register_operand" ""))
5504      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5505           (match_operand:SI 4 "arm_hard_register_operand" ""))
5506      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5507           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5508   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5509   "stm%?ia\\t%1!, {%3, %4, %5}"
5510   [(set_attr "predicable" "yes")
5511    (set_attr "type" "store3")]
5512 )
5513
5514 (define_insn "*stmsi_postinc2"
5515   [(match_parallel 0 "store_multiple_operation"
5516     [(set (match_operand:SI 1 "s_register_operand" "=r")
5517           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5518                    (const_int 8)))
5519      (set (mem:SI (match_dup 2))
5520           (match_operand:SI 3 "arm_hard_register_operand" ""))
5521      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5522           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5523   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5524   "stm%?ia\\t%1!, {%3, %4}"
5525   [(set_attr "predicable" "yes")
5526    (set_attr "type" "store2")]
5527 )
5528
5529 ;; Ordinary store multiple
5530
5531 (define_insn "*stmsi4"
5532   [(match_parallel 0 "store_multiple_operation"
5533     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5534           (match_operand:SI 2 "arm_hard_register_operand" ""))
5535      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5536           (match_operand:SI 3 "arm_hard_register_operand" ""))
5537      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5538           (match_operand:SI 4 "arm_hard_register_operand" ""))
5539      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5540           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5541   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5542   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5543   [(set_attr "predicable" "yes")
5544    (set_attr "type" "store4")]
5545 )
5546
5547 (define_insn "*stmsi3"
5548   [(match_parallel 0 "store_multiple_operation"
5549     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5550           (match_operand:SI 2 "arm_hard_register_operand" ""))
5551      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5552           (match_operand:SI 3 "arm_hard_register_operand" ""))
5553      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5554           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5555   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5556   "stm%?ia\\t%1, {%2, %3, %4}"
5557   [(set_attr "predicable" "yes")
5558    (set_attr "type" "store3")]
5559 )
5560
5561 (define_insn "*stmsi2"
5562   [(match_parallel 0 "store_multiple_operation"
5563     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5564           (match_operand:SI 2 "arm_hard_register_operand" ""))
5565      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5566           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5567   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5568   "stm%?ia\\t%1, {%2, %3}"
5569   [(set_attr "predicable" "yes")
5570    (set_attr "type" "store2")]
5571 )
5572
5573 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5574 ;; We could let this apply for blocks of less than this, but it clobbers so
5575 ;; many registers that there is then probably a better way.
5576
5577 (define_expand "movmemqi"
5578   [(match_operand:BLK 0 "general_operand" "")
5579    (match_operand:BLK 1 "general_operand" "")
5580    (match_operand:SI 2 "const_int_operand" "")
5581    (match_operand:SI 3 "const_int_operand" "")]
5582   "TARGET_EITHER"
5583   "
5584   if (TARGET_ARM)
5585     {
5586       if (arm_gen_movmemqi (operands))
5587         DONE;
5588       FAIL;
5589     }
5590   else /* TARGET_THUMB */
5591     {
5592       if (   INTVAL (operands[3]) != 4
5593           || INTVAL (operands[2]) > 48)
5594         FAIL;
5595
5596       thumb_expand_movmemqi (operands);
5597       DONE;
5598     }
5599   "
5600 )
5601
5602 ;; Thumb block-move insns
5603
5604 (define_insn "movmem12b"
5605   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5606         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5607    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5608         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5609    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5610         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5611    (set (match_operand:SI 0 "register_operand" "=l")
5612         (plus:SI (match_dup 2) (const_int 12)))
5613    (set (match_operand:SI 1 "register_operand" "=l")
5614         (plus:SI (match_dup 3) (const_int 12)))
5615    (clobber (match_scratch:SI 4 "=&l"))
5616    (clobber (match_scratch:SI 5 "=&l"))
5617    (clobber (match_scratch:SI 6 "=&l"))]
5618   "TARGET_THUMB"
5619   "* return thumb_output_move_mem_multiple (3, operands);"
5620   [(set_attr "length" "4")
5621    ; This isn't entirely accurate...  It loads as well, but in terms of
5622    ; scheduling the following insn it is better to consider it as a store
5623    (set_attr "type" "store3")]
5624 )
5625
5626 (define_insn "movmem8b"
5627   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5628         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5629    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5630         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5631    (set (match_operand:SI 0 "register_operand" "=l")
5632         (plus:SI (match_dup 2) (const_int 8)))
5633    (set (match_operand:SI 1 "register_operand" "=l")
5634         (plus:SI (match_dup 3) (const_int 8)))
5635    (clobber (match_scratch:SI 4 "=&l"))
5636    (clobber (match_scratch:SI 5 "=&l"))]
5637   "TARGET_THUMB"
5638   "* return thumb_output_move_mem_multiple (2, operands);"
5639   [(set_attr "length" "4")
5640    ; This isn't entirely accurate...  It loads as well, but in terms of
5641    ; scheduling the following insn it is better to consider it as a store
5642    (set_attr "type" "store2")]
5643 )
5644
5645 \f
5646
5647 ;; Compare & branch insns
5648 ;; The range calculations are based as follows:
5649 ;; For forward branches, the address calculation returns the address of
5650 ;; the next instruction.  This is 2 beyond the branch instruction.
5651 ;; For backward branches, the address calculation returns the address of
5652 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5653 ;; instruction for the shortest sequence, and 4 before the branch instruction
5654 ;; if we have to jump around an unconditional branch.
5655 ;; To the basic branch range the PC offset must be added (this is +4).
5656 ;; So for forward branches we have 
5657 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5658 ;; And for backward branches we have 
5659 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5660 ;;
5661 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5662 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5663
5664 (define_expand "cbranchsi4"
5665   [(set (pc) (if_then_else
5666               (match_operator 0 "arm_comparison_operator"
5667                [(match_operand:SI 1 "s_register_operand" "")
5668                 (match_operand:SI 2 "nonmemory_operand" "")])
5669               (label_ref (match_operand 3 "" ""))
5670               (pc)))]
5671   "TARGET_THUMB"
5672   "
5673   if (thumb_cmpneg_operand (operands[2], SImode))
5674     {
5675       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5676                                               operands[3], operands[0]));
5677       DONE;
5678     }
5679   if (!thumb_cmp_operand (operands[2], SImode))
5680     operands[2] = force_reg (SImode, operands[2]);
5681   ")
5682
5683 (define_insn "*cbranchsi4_insn"
5684   [(set (pc) (if_then_else
5685               (match_operator 0 "arm_comparison_operator"
5686                [(match_operand:SI 1 "s_register_operand" "l,*h")
5687                 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5688               (label_ref (match_operand 3 "" ""))
5689               (pc)))]
5690   "TARGET_THUMB"
5691   "*
5692   output_asm_insn (\"cmp\\t%1, %2\", operands);
5693
5694   switch (get_attr_length (insn))
5695     {
5696     case 4:  return \"b%d0\\t%l3\";
5697     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5698     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5699     }
5700   "
5701   [(set (attr "far_jump")
5702         (if_then_else
5703             (eq_attr "length" "8")
5704             (const_string "yes")
5705             (const_string "no")))
5706    (set (attr "length") 
5707         (if_then_else
5708             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5709                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5710             (const_int 4)
5711             (if_then_else
5712                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5713                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5714                 (const_int 6)
5715                 (const_int 8))))]
5716 )
5717
5718 (define_insn "cbranchsi4_scratch"
5719   [(set (pc) (if_then_else
5720               (match_operator 4 "arm_comparison_operator"
5721                [(match_operand:SI 1 "s_register_operand" "l,0")
5722                 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5723               (label_ref (match_operand 3 "" ""))
5724               (pc)))
5725    (clobber (match_scratch:SI 0 "=l,l"))]
5726   "TARGET_THUMB"
5727   "*
5728   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5729
5730   switch (get_attr_length (insn))
5731     {
5732     case 4:  return \"b%d4\\t%l3\";
5733     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5734     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5735     }
5736   "
5737   [(set (attr "far_jump")
5738         (if_then_else
5739             (eq_attr "length" "8")
5740             (const_string "yes")
5741             (const_string "no")))
5742    (set (attr "length") 
5743         (if_then_else
5744             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5745                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5746             (const_int 4)
5747             (if_then_else
5748                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5749                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5750                 (const_int 6)
5751                 (const_int 8))))]
5752 )
5753 (define_insn "*movsi_cbranchsi4"
5754   [(set (pc)
5755         (if_then_else
5756          (match_operator 3 "arm_comparison_operator"
5757           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5758            (const_int 0)])
5759          (label_ref (match_operand 2 "" ""))
5760          (pc)))
5761    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5762         (match_dup 1))]
5763   "TARGET_THUMB"
5764   "*{
5765   if (which_alternative == 0)
5766     output_asm_insn (\"cmp\t%0, #0\", operands);
5767   else if (which_alternative == 1)
5768     output_asm_insn (\"sub\t%0, %1, #0\", operands);
5769   else
5770     {
5771       output_asm_insn (\"cmp\t%1, #0\", operands);
5772       if (which_alternative == 2)
5773         output_asm_insn (\"mov\t%0, %1\", operands);
5774       else
5775         output_asm_insn (\"str\t%1, %0\", operands);
5776     }
5777   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5778     {
5779     case 4:  return \"b%d3\\t%l2\";
5780     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5781     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5782     }
5783   }"
5784   [(set (attr "far_jump")
5785         (if_then_else
5786             (ior (and (gt (symbol_ref ("which_alternative"))
5787                           (const_int 1))
5788                       (eq_attr "length" "8"))
5789                  (eq_attr "length" "10"))
5790             (const_string "yes")
5791             (const_string "no")))
5792    (set (attr "length")
5793      (if_then_else
5794        (le (symbol_ref ("which_alternative"))
5795                        (const_int 1))
5796        (if_then_else
5797          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5798               (le (minus (match_dup 2) (pc)) (const_int 256)))
5799          (const_int 4)
5800          (if_then_else
5801            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5802                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5803            (const_int 6)
5804            (const_int 8)))
5805        (if_then_else
5806          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5807               (le (minus (match_dup 2) (pc)) (const_int 256)))
5808          (const_int 6)
5809          (if_then_else
5810            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5811                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5812            (const_int 8)
5813            (const_int 10)))))]
5814 )
5815
5816 (define_insn "*negated_cbranchsi4"
5817   [(set (pc)
5818         (if_then_else
5819          (match_operator 0 "equality_operator"
5820           [(match_operand:SI 1 "s_register_operand" "l")
5821            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5822          (label_ref (match_operand 3 "" ""))
5823          (pc)))]
5824   "TARGET_THUMB"
5825   "*
5826   output_asm_insn (\"cmn\\t%1, %2\", operands);
5827   switch (get_attr_length (insn))
5828     {
5829     case 4:  return \"b%d0\\t%l3\";
5830     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5831     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5832     }
5833   "
5834   [(set (attr "far_jump")
5835         (if_then_else
5836             (eq_attr "length" "8")
5837             (const_string "yes")
5838             (const_string "no")))
5839    (set (attr "length") 
5840         (if_then_else
5841             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5842                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5843             (const_int 4)
5844             (if_then_else
5845                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5846                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5847                 (const_int 6)
5848                 (const_int 8))))]
5849 )
5850
5851 (define_insn "*tbit_cbranch"
5852   [(set (pc)
5853         (if_then_else
5854          (match_operator 0 "equality_operator"
5855           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5856                             (const_int 1)
5857                             (match_operand:SI 2 "const_int_operand" "i"))
5858            (const_int 0)])
5859          (label_ref (match_operand 3 "" ""))
5860          (pc)))
5861    (clobber (match_scratch:SI 4 "=l"))]
5862   "TARGET_THUMB"
5863   "*
5864   {
5865   rtx op[3];
5866   op[0] = operands[4];
5867   op[1] = operands[1];
5868   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5869
5870   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5871   switch (get_attr_length (insn))
5872     {
5873     case 4:  return \"b%d0\\t%l3\";
5874     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5875     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5876     }
5877   }"
5878   [(set (attr "far_jump")
5879         (if_then_else
5880             (eq_attr "length" "8")
5881             (const_string "yes")
5882             (const_string "no")))
5883    (set (attr "length") 
5884         (if_then_else
5885             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5886                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5887             (const_int 4)
5888             (if_then_else
5889                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5890                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5891                 (const_int 6)
5892                 (const_int 8))))]
5893 )
5894   
5895 (define_insn "*tstsi3_cbranch"
5896   [(set (pc)
5897         (if_then_else
5898          (match_operator 3 "equality_operator"
5899           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5900                    (match_operand:SI 1 "s_register_operand" "l"))
5901            (const_int 0)])
5902          (label_ref (match_operand 2 "" ""))
5903          (pc)))]
5904   "TARGET_THUMB"
5905   "*
5906   {
5907   output_asm_insn (\"tst\\t%0, %1\", operands);
5908   switch (get_attr_length (insn))
5909     {
5910     case 4:  return \"b%d3\\t%l2\";
5911     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5912     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5913     }
5914   }"
5915   [(set (attr "far_jump")
5916         (if_then_else
5917             (eq_attr "length" "8")
5918             (const_string "yes")
5919             (const_string "no")))
5920    (set (attr "length") 
5921         (if_then_else
5922             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5923                  (le (minus (match_dup 2) (pc)) (const_int 256)))
5924             (const_int 4)
5925             (if_then_else
5926                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5927                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
5928                 (const_int 6)
5929                 (const_int 8))))]
5930 )
5931   
5932 (define_insn "*andsi3_cbranch"
5933   [(set (pc)
5934         (if_then_else
5935          (match_operator 5 "equality_operator"
5936           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5937                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5938            (const_int 0)])
5939          (label_ref (match_operand 4 "" ""))
5940          (pc)))
5941    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5942         (and:SI (match_dup 2) (match_dup 3)))
5943    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5944   "TARGET_THUMB"
5945   "*
5946   {
5947   if (which_alternative == 0)
5948     output_asm_insn (\"and\\t%0, %3\", operands);
5949   else if (which_alternative == 1)
5950     {
5951       output_asm_insn (\"and\\t%1, %3\", operands);
5952       output_asm_insn (\"mov\\t%0, %1\", operands);
5953     }
5954   else
5955     {
5956       output_asm_insn (\"and\\t%1, %3\", operands);
5957       output_asm_insn (\"str\\t%1, %0\", operands);
5958     }
5959
5960   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5961     {
5962     case 4:  return \"b%d5\\t%l4\";
5963     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5964     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5965     }
5966   }"
5967   [(set (attr "far_jump")
5968         (if_then_else
5969             (ior (and (eq (symbol_ref ("which_alternative"))
5970                           (const_int 0))
5971                       (eq_attr "length" "8"))
5972                  (eq_attr "length" "10"))
5973             (const_string "yes")
5974             (const_string "no")))
5975    (set (attr "length")
5976      (if_then_else
5977        (eq (symbol_ref ("which_alternative"))
5978                        (const_int 0))
5979        (if_then_else
5980          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5981               (le (minus (match_dup 4) (pc)) (const_int 256)))
5982          (const_int 4)
5983          (if_then_else
5984            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5985                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5986            (const_int 6)
5987            (const_int 8)))
5988        (if_then_else
5989          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5990               (le (minus (match_dup 4) (pc)) (const_int 256)))
5991          (const_int 6)
5992          (if_then_else
5993            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5994                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5995            (const_int 8)
5996            (const_int 10)))))]
5997 )
5998
5999 (define_insn "*orrsi3_cbranch_scratch"
6000   [(set (pc)
6001         (if_then_else
6002          (match_operator 4 "equality_operator"
6003           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6004                    (match_operand:SI 2 "s_register_operand" "l"))
6005            (const_int 0)])
6006          (label_ref (match_operand 3 "" ""))
6007          (pc)))
6008    (clobber (match_scratch:SI 0 "=l"))]
6009   "TARGET_THUMB"
6010   "*
6011   {
6012   output_asm_insn (\"orr\\t%0, %2\", operands);
6013   switch (get_attr_length (insn))
6014     {
6015     case 4:  return \"b%d4\\t%l3\";
6016     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6017     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6018     }
6019   }"
6020   [(set (attr "far_jump")
6021         (if_then_else
6022             (eq_attr "length" "8")
6023             (const_string "yes")
6024             (const_string "no")))
6025    (set (attr "length") 
6026         (if_then_else
6027             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6028                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6029             (const_int 4)
6030             (if_then_else
6031                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6032                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6033                 (const_int 6)
6034                 (const_int 8))))]
6035 )
6036   
6037 (define_insn "*orrsi3_cbranch"
6038   [(set (pc)
6039         (if_then_else
6040          (match_operator 5 "equality_operator"
6041           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6042                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6043            (const_int 0)])
6044          (label_ref (match_operand 4 "" ""))
6045          (pc)))
6046    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6047         (ior:SI (match_dup 2) (match_dup 3)))
6048    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6049   "TARGET_THUMB"
6050   "*
6051   {
6052   if (which_alternative == 0)
6053     output_asm_insn (\"orr\\t%0, %3\", operands);
6054   else if (which_alternative == 1)
6055     {
6056       output_asm_insn (\"orr\\t%1, %3\", operands);
6057       output_asm_insn (\"mov\\t%0, %1\", operands);
6058     }
6059   else
6060     {
6061       output_asm_insn (\"orr\\t%1, %3\", operands);
6062       output_asm_insn (\"str\\t%1, %0\", operands);
6063     }
6064
6065   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6066     {
6067     case 4:  return \"b%d5\\t%l4\";
6068     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6069     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6070     }
6071   }"
6072   [(set (attr "far_jump")
6073         (if_then_else
6074             (ior (and (eq (symbol_ref ("which_alternative"))
6075                           (const_int 0))
6076                       (eq_attr "length" "8"))
6077                  (eq_attr "length" "10"))
6078             (const_string "yes")
6079             (const_string "no")))
6080    (set (attr "length")
6081      (if_then_else
6082        (eq (symbol_ref ("which_alternative"))
6083                        (const_int 0))
6084        (if_then_else
6085          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6086               (le (minus (match_dup 4) (pc)) (const_int 256)))
6087          (const_int 4)
6088          (if_then_else
6089            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6090                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6091            (const_int 6)
6092            (const_int 8)))
6093        (if_then_else
6094          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6095               (le (minus (match_dup 4) (pc)) (const_int 256)))
6096          (const_int 6)
6097          (if_then_else
6098            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6099                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6100            (const_int 8)
6101            (const_int 10)))))]
6102 )
6103
6104 (define_insn "*xorsi3_cbranch_scratch"
6105   [(set (pc)
6106         (if_then_else
6107          (match_operator 4 "equality_operator"
6108           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6109                    (match_operand:SI 2 "s_register_operand" "l"))
6110            (const_int 0)])
6111          (label_ref (match_operand 3 "" ""))
6112          (pc)))
6113    (clobber (match_scratch:SI 0 "=l"))]
6114   "TARGET_THUMB"
6115   "*
6116   {
6117   output_asm_insn (\"eor\\t%0, %2\", operands);
6118   switch (get_attr_length (insn))
6119     {
6120     case 4:  return \"b%d4\\t%l3\";
6121     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6122     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6123     }
6124   }"
6125   [(set (attr "far_jump")
6126         (if_then_else
6127             (eq_attr "length" "8")
6128             (const_string "yes")
6129             (const_string "no")))
6130    (set (attr "length") 
6131         (if_then_else
6132             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6133                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6134             (const_int 4)
6135             (if_then_else
6136                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6137                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6138                 (const_int 6)
6139                 (const_int 8))))]
6140 )
6141   
6142 (define_insn "*xorsi3_cbranch"
6143   [(set (pc)
6144         (if_then_else
6145          (match_operator 5 "equality_operator"
6146           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6147                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6148            (const_int 0)])
6149          (label_ref (match_operand 4 "" ""))
6150          (pc)))
6151    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6152         (xor:SI (match_dup 2) (match_dup 3)))
6153    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6154   "TARGET_THUMB"
6155   "*
6156   {
6157   if (which_alternative == 0)
6158     output_asm_insn (\"eor\\t%0, %3\", operands);
6159   else if (which_alternative == 1)
6160     {
6161       output_asm_insn (\"eor\\t%1, %3\", operands);
6162       output_asm_insn (\"mov\\t%0, %1\", operands);
6163     }
6164   else
6165     {
6166       output_asm_insn (\"eor\\t%1, %3\", operands);
6167       output_asm_insn (\"str\\t%1, %0\", operands);
6168     }
6169
6170   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6171     {
6172     case 4:  return \"b%d5\\t%l4\";
6173     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6174     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6175     }
6176   }"
6177   [(set (attr "far_jump")
6178         (if_then_else
6179             (ior (and (eq (symbol_ref ("which_alternative"))
6180                           (const_int 0))
6181                       (eq_attr "length" "8"))
6182                  (eq_attr "length" "10"))
6183             (const_string "yes")
6184             (const_string "no")))
6185    (set (attr "length")
6186      (if_then_else
6187        (eq (symbol_ref ("which_alternative"))
6188                        (const_int 0))
6189        (if_then_else
6190          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6191               (le (minus (match_dup 4) (pc)) (const_int 256)))
6192          (const_int 4)
6193          (if_then_else
6194            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6195                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6196            (const_int 6)
6197            (const_int 8)))
6198        (if_then_else
6199          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6200               (le (minus (match_dup 4) (pc)) (const_int 256)))
6201          (const_int 6)
6202          (if_then_else
6203            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6204                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6205            (const_int 8)
6206            (const_int 10)))))]
6207 )
6208
6209 (define_insn "*bicsi3_cbranch_scratch"
6210   [(set (pc)
6211         (if_then_else
6212          (match_operator 4 "equality_operator"
6213           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6214                    (match_operand:SI 1 "s_register_operand" "0"))
6215            (const_int 0)])
6216          (label_ref (match_operand 3 "" ""))
6217          (pc)))
6218    (clobber (match_scratch:SI 0 "=l"))]
6219   "TARGET_THUMB"
6220   "*
6221   {
6222   output_asm_insn (\"bic\\t%0, %2\", operands);
6223   switch (get_attr_length (insn))
6224     {
6225     case 4:  return \"b%d4\\t%l3\";
6226     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6227     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6228     }
6229   }"
6230   [(set (attr "far_jump")
6231         (if_then_else
6232             (eq_attr "length" "8")
6233             (const_string "yes")
6234             (const_string "no")))
6235    (set (attr "length") 
6236         (if_then_else
6237             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6238                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6239             (const_int 4)
6240             (if_then_else
6241                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6242                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6243                 (const_int 6)
6244                 (const_int 8))))]
6245 )
6246   
6247 (define_insn "*bicsi3_cbranch"
6248   [(set (pc)
6249         (if_then_else
6250          (match_operator 5 "equality_operator"
6251           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6252                    (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6253            (const_int 0)])
6254          (label_ref (match_operand 4 "" ""))
6255          (pc)))
6256    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6257         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6258    (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6259   "TARGET_THUMB"
6260   "*
6261   {
6262   if (which_alternative == 0)
6263     output_asm_insn (\"bic\\t%0, %3\", operands);
6264   else if (which_alternative <= 2)
6265     {
6266       output_asm_insn (\"bic\\t%1, %3\", operands);
6267       /* It's ok if OP0 is a lo-reg, even though the mov will set the
6268          conditions again, since we're only testing for equality.  */
6269       output_asm_insn (\"mov\\t%0, %1\", operands);
6270     }
6271   else
6272     {
6273       output_asm_insn (\"bic\\t%1, %3\", operands);
6274       output_asm_insn (\"str\\t%1, %0\", operands);
6275     }
6276
6277   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6278     {
6279     case 4:  return \"b%d5\\t%l4\";
6280     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6281     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6282     }
6283   }"
6284   [(set (attr "far_jump")
6285         (if_then_else
6286             (ior (and (eq (symbol_ref ("which_alternative"))
6287                           (const_int 0))
6288                       (eq_attr "length" "8"))
6289                  (eq_attr "length" "10"))
6290             (const_string "yes")
6291             (const_string "no")))
6292    (set (attr "length")
6293      (if_then_else
6294        (eq (symbol_ref ("which_alternative"))
6295                        (const_int 0))
6296        (if_then_else
6297          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6298               (le (minus (match_dup 4) (pc)) (const_int 256)))
6299          (const_int 4)
6300          (if_then_else
6301            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6302                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6303            (const_int 6)
6304            (const_int 8)))
6305        (if_then_else
6306          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6307               (le (minus (match_dup 4) (pc)) (const_int 256)))
6308          (const_int 6)
6309          (if_then_else
6310            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6311                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6312            (const_int 8)
6313            (const_int 10)))))]
6314 )
6315
6316 (define_insn "*cbranchne_decr1"
6317   [(set (pc)
6318         (if_then_else (match_operator 3 "equality_operator"
6319                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6320                         (const_int 0)])
6321                       (label_ref (match_operand 4 "" ""))
6322                       (pc)))
6323    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6324         (plus:SI (match_dup 2) (const_int -1)))
6325    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6326   "TARGET_THUMB"
6327   "*
6328    {
6329      rtx cond[2];
6330      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6331                                 ? GEU : LTU),
6332                                VOIDmode, operands[2], const1_rtx);
6333      cond[1] = operands[4];
6334
6335      if (which_alternative == 0)
6336        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6337      else if (which_alternative == 1)
6338        {
6339          /* We must provide an alternative for a hi reg because reload 
6340             cannot handle output reloads on a jump instruction, but we
6341             can't subtract into that.  Fortunately a mov from lo to hi
6342             does not clobber the condition codes.  */
6343          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6344          output_asm_insn (\"mov\\t%0, %1\", operands);
6345        }
6346      else
6347        {
6348          /* Similarly, but the target is memory.  */
6349          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6350          output_asm_insn (\"str\\t%1, %0\", operands);
6351        }
6352
6353      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6354        {
6355          case 4:
6356            output_asm_insn (\"b%d0\\t%l1\", cond);
6357            return \"\";
6358          case 6:
6359            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6360            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6361          default:
6362            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6363            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6364        }
6365    }
6366   "
6367   [(set (attr "far_jump")
6368         (if_then_else
6369             (ior (and (eq (symbol_ref ("which_alternative"))
6370                           (const_int 0))
6371                       (eq_attr "length" "8"))
6372                  (eq_attr "length" "10"))
6373             (const_string "yes")
6374             (const_string "no")))
6375    (set_attr_alternative "length"
6376       [
6377        ;; Alternative 0
6378        (if_then_else
6379          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6380               (le (minus (match_dup 4) (pc)) (const_int 256)))
6381          (const_int 4)
6382          (if_then_else
6383            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6384                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6385            (const_int 6)
6386            (const_int 8)))
6387        ;; Alternative 1
6388        (if_then_else
6389          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6390               (le (minus (match_dup 4) (pc)) (const_int 256)))
6391          (const_int 6)
6392          (if_then_else
6393            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6394                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6395            (const_int 8)
6396            (const_int 10)))
6397        ;; Alternative 2
6398        (if_then_else
6399          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6400               (le (minus (match_dup 4) (pc)) (const_int 256)))
6401          (const_int 6)
6402          (if_then_else
6403            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6404                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6405            (const_int 8)
6406            (const_int 10)))
6407        ;; Alternative 3
6408        (if_then_else
6409          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6410               (le (minus (match_dup 4) (pc)) (const_int 256)))
6411          (const_int 6)
6412          (if_then_else
6413            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6414                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6415            (const_int 8)
6416            (const_int 10)))])]
6417 )
6418
6419 (define_insn "*addsi3_cbranch"
6420   [(set (pc)
6421         (if_then_else
6422          (match_operator 4 "comparison_operator"
6423           [(plus:SI
6424             (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6425             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6426            (const_int 0)])
6427          (label_ref (match_operand 5 "" ""))
6428          (pc)))
6429    (set
6430     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6431     (plus:SI (match_dup 2) (match_dup 3)))
6432    (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6433   "TARGET_THUMB
6434    && (GET_CODE (operands[4]) == EQ
6435        || GET_CODE (operands[4]) == NE
6436        || GET_CODE (operands[4]) == GE
6437        || GET_CODE (operands[4]) == LT)"
6438   "*
6439    {
6440      rtx cond[3];
6441
6442      
6443      cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6444      cond[1] = operands[2];
6445      cond[2] = operands[3];
6446
6447      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6448        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6449      else
6450        output_asm_insn (\"add\\t%0, %1, %2\", cond);
6451
6452      if (which_alternative >= 3
6453          && which_alternative < 4)
6454        output_asm_insn (\"mov\\t%0, %1\", operands);
6455      else if (which_alternative >= 4)
6456        output_asm_insn (\"str\\t%1, %0\", operands);
6457
6458      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6459        {
6460          case 4:
6461            return \"b%d4\\t%l5\";
6462          case 6:
6463            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6464          default:
6465            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6466        }
6467    }
6468   "
6469   [(set (attr "far_jump")
6470         (if_then_else
6471             (ior (and (lt (symbol_ref ("which_alternative"))
6472                           (const_int 3))
6473                       (eq_attr "length" "8"))
6474                  (eq_attr "length" "10"))
6475             (const_string "yes")
6476             (const_string "no")))
6477    (set (attr "length")
6478      (if_then_else
6479        (lt (symbol_ref ("which_alternative"))
6480                        (const_int 3))
6481        (if_then_else
6482          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6483               (le (minus (match_dup 5) (pc)) (const_int 256)))
6484          (const_int 4)
6485          (if_then_else
6486            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6487                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6488            (const_int 6)
6489            (const_int 8)))
6490        (if_then_else
6491          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6492               (le (minus (match_dup 5) (pc)) (const_int 256)))
6493          (const_int 6)
6494          (if_then_else
6495            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6496                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6497            (const_int 8)
6498            (const_int 10)))))]
6499 )
6500
6501 (define_insn "*addsi3_cbranch_scratch"
6502   [(set (pc)
6503         (if_then_else
6504          (match_operator 3 "comparison_operator"
6505           [(plus:SI
6506             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6507             (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
6508            (const_int 0)])
6509          (label_ref (match_operand 4 "" ""))
6510          (pc)))
6511    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6512   "TARGET_THUMB
6513    && (GET_CODE (operands[3]) == EQ
6514        || GET_CODE (operands[3]) == NE
6515        || GET_CODE (operands[3]) == GE
6516        || GET_CODE (operands[3]) == LT)"
6517   "*
6518    {
6519      switch (which_alternative)
6520        {
6521        case 0:
6522          output_asm_insn (\"cmp\t%1, #%n2\", operands);
6523          break;
6524        case 1:
6525          output_asm_insn (\"cmn\t%1, %2\", operands);
6526          break;
6527        case 2:
6528          if (INTVAL (operands[2]) < 0)
6529            output_asm_insn (\"sub\t%0, %1, %2\", operands);
6530          else
6531            output_asm_insn (\"add\t%0, %1, %2\", operands);
6532          break;
6533        case 3:
6534          if (INTVAL (operands[2]) < 0)
6535            output_asm_insn (\"sub\t%0, %0, %2\", operands);
6536          else
6537            output_asm_insn (\"add\t%0, %0, %2\", operands);
6538          break;
6539        }
6540
6541      switch (get_attr_length (insn))
6542        {
6543          case 4:
6544            return \"b%d3\\t%l4\";
6545          case 6:
6546            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6547          default:
6548            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6549        }
6550    }
6551   "
6552   [(set (attr "far_jump")
6553         (if_then_else
6554             (eq_attr "length" "8")
6555             (const_string "yes")
6556             (const_string "no")))
6557    (set (attr "length")
6558        (if_then_else
6559          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6560               (le (minus (match_dup 4) (pc)) (const_int 256)))
6561          (const_int 4)
6562          (if_then_else
6563            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6564                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6565            (const_int 6)
6566            (const_int 8))))]
6567 )
6568
6569 (define_insn "*subsi3_cbranch"
6570   [(set (pc)
6571         (if_then_else
6572          (match_operator 4 "comparison_operator"
6573           [(minus:SI
6574             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6575             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6576            (const_int 0)])
6577          (label_ref (match_operand 5 "" ""))
6578          (pc)))
6579    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6580         (minus:SI (match_dup 2) (match_dup 3)))
6581    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6582   "TARGET_THUMB
6583    && (GET_CODE (operands[4]) == EQ
6584        || GET_CODE (operands[4]) == NE
6585        || GET_CODE (operands[4]) == GE
6586        || GET_CODE (operands[4]) == LT)"
6587   "*
6588    {
6589      if (which_alternative == 0)
6590        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6591      else if (which_alternative == 1)
6592        {
6593          /* We must provide an alternative for a hi reg because reload 
6594             cannot handle output reloads on a jump instruction, but we
6595             can't subtract into that.  Fortunately a mov from lo to hi
6596             does not clobber the condition codes.  */
6597          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6598          output_asm_insn (\"mov\\t%0, %1\", operands);
6599        }
6600      else
6601        {
6602          /* Similarly, but the target is memory.  */
6603          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6604          output_asm_insn (\"str\\t%1, %0\", operands);
6605        }
6606
6607      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6608        {
6609          case 4:
6610            return \"b%d4\\t%l5\";
6611          case 6:
6612            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6613          default:
6614            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6615        }
6616    }
6617   "
6618   [(set (attr "far_jump")
6619         (if_then_else
6620             (ior (and (eq (symbol_ref ("which_alternative"))
6621                           (const_int 0))
6622                       (eq_attr "length" "8"))
6623                  (eq_attr "length" "10"))
6624             (const_string "yes")
6625             (const_string "no")))
6626    (set (attr "length")
6627      (if_then_else
6628        (eq (symbol_ref ("which_alternative"))
6629                        (const_int 0))
6630        (if_then_else
6631          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6632               (le (minus (match_dup 5) (pc)) (const_int 256)))
6633          (const_int 4)
6634          (if_then_else
6635            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6636                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6637            (const_int 6)
6638            (const_int 8)))
6639        (if_then_else
6640          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6641               (le (minus (match_dup 5) (pc)) (const_int 256)))
6642          (const_int 6)
6643          (if_then_else
6644            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6645                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6646            (const_int 8)
6647            (const_int 10)))))]
6648 )
6649
6650 (define_insn "*subsi3_cbranch_scratch"
6651   [(set (pc)
6652         (if_then_else
6653          (match_operator 0 "arm_comparison_operator"
6654           [(minus:SI (match_operand:SI 1 "register_operand" "l")
6655                      (match_operand:SI 2 "nonmemory_operand" "l"))
6656            (const_int 0)])
6657          (label_ref (match_operand 3 "" ""))
6658          (pc)))]
6659   "TARGET_THUMB
6660    && (GET_CODE (operands[0]) == EQ
6661        || GET_CODE (operands[0]) == NE
6662        || GET_CODE (operands[0]) == GE
6663        || GET_CODE (operands[0]) == LT)"
6664   "*
6665   output_asm_insn (\"cmp\\t%1, %2\", operands);
6666   switch (get_attr_length (insn))
6667     {
6668     case 4:  return \"b%d0\\t%l3\";
6669     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6670     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6671     }
6672   "
6673   [(set (attr "far_jump")
6674         (if_then_else
6675             (eq_attr "length" "8")
6676             (const_string "yes")
6677             (const_string "no")))
6678    (set (attr "length") 
6679         (if_then_else
6680             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6681                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6682             (const_int 4)
6683             (if_then_else
6684                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6685                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6686                 (const_int 6)
6687                 (const_int 8))))]
6688 )
6689
6690 ;; Comparison and test insns
6691
6692 (define_expand "cmpsi"
6693   [(match_operand:SI 0 "s_register_operand" "")
6694    (match_operand:SI 1 "arm_add_operand" "")]
6695   "TARGET_ARM"
6696   "{
6697     arm_compare_op0 = operands[0];
6698     arm_compare_op1 = operands[1];
6699     DONE;
6700   }"
6701 )
6702
6703 (define_expand "cmpsf"
6704   [(match_operand:SF 0 "s_register_operand" "")
6705    (match_operand:SF 1 "arm_float_compare_operand" "")]
6706   "TARGET_ARM && TARGET_HARD_FLOAT"
6707   "
6708   arm_compare_op0 = operands[0];
6709   arm_compare_op1 = operands[1];
6710   DONE;
6711   "
6712 )
6713
6714 (define_expand "cmpdf"
6715   [(match_operand:DF 0 "s_register_operand" "")
6716    (match_operand:DF 1 "arm_float_compare_operand" "")]
6717   "TARGET_ARM && TARGET_HARD_FLOAT"
6718   "
6719   arm_compare_op0 = operands[0];
6720   arm_compare_op1 = operands[1];
6721   DONE;
6722   "
6723 )
6724
6725 (define_insn "*arm_cmpsi_insn"
6726   [(set (reg:CC CC_REGNUM)
6727         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6728                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
6729   "TARGET_ARM"
6730   "@
6731    cmp%?\\t%0, %1
6732    cmn%?\\t%0, #%n1"
6733   [(set_attr "conds" "set")]
6734 )
6735
6736 (define_insn "*cmpsi_shiftsi"
6737   [(set (reg:CC CC_REGNUM)
6738         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
6739                     (match_operator:SI  3 "shift_operator"
6740                      [(match_operand:SI 1 "s_register_operand" "r")
6741                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
6742   "TARGET_ARM"
6743   "cmp%?\\t%0, %1%S3"
6744   [(set_attr "conds" "set")
6745    (set_attr "shift" "1")
6746    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6747                       (const_string "alu_shift")
6748                       (const_string "alu_shift_reg")))]
6749 )
6750
6751 (define_insn "*cmpsi_shiftsi_swp"
6752   [(set (reg:CC_SWP CC_REGNUM)
6753         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6754                          [(match_operand:SI 1 "s_register_operand" "r")
6755                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
6756                         (match_operand:SI 0 "s_register_operand" "r")))]
6757   "TARGET_ARM"
6758   "cmp%?\\t%0, %1%S3"
6759   [(set_attr "conds" "set")
6760    (set_attr "shift" "1")
6761    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6762                       (const_string "alu_shift")
6763                       (const_string "alu_shift_reg")))]
6764 )
6765
6766 (define_insn "*cmpsi_negshiftsi_si"
6767   [(set (reg:CC_Z CC_REGNUM)
6768         (compare:CC_Z
6769          (neg:SI (match_operator:SI 1 "shift_operator"
6770                     [(match_operand:SI 2 "s_register_operand" "r")
6771                      (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6772          (match_operand:SI 0 "s_register_operand" "r")))]
6773   "TARGET_ARM"
6774   "cmn%?\\t%0, %2%S1"
6775   [(set_attr "conds" "set")
6776    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
6777                                     (const_string "alu_shift")
6778                                     (const_string "alu_shift_reg")))]
6779 )
6780
6781 ;; Cirrus SF compare instruction
6782 (define_insn "*cirrus_cmpsf"
6783   [(set (reg:CCFP CC_REGNUM)
6784         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6785                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
6786   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6787   "cfcmps%?\\tr15, %V0, %V1"
6788   [(set_attr "type"   "mav_farith")
6789    (set_attr "cirrus" "compare")]
6790 )
6791
6792 ;; Cirrus DF compare instruction
6793 (define_insn "*cirrus_cmpdf"
6794   [(set (reg:CCFP CC_REGNUM)
6795         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6796                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
6797   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6798   "cfcmpd%?\\tr15, %V0, %V1"
6799   [(set_attr "type"   "mav_farith")
6800    (set_attr "cirrus" "compare")]
6801 )
6802
6803 ;; Cirrus DI compare instruction
6804 (define_expand "cmpdi"
6805   [(match_operand:DI 0 "cirrus_fp_register" "")
6806    (match_operand:DI 1 "cirrus_fp_register" "")]
6807   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6808   "{
6809      arm_compare_op0 = operands[0];
6810      arm_compare_op1 = operands[1];
6811      DONE;
6812    }")
6813
6814 (define_insn "*cirrus_cmpdi"
6815   [(set (reg:CC CC_REGNUM)
6816         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6817                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
6818   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6819   "cfcmp64%?\\tr15, %V0, %V1"
6820   [(set_attr "type"   "mav_farith")
6821    (set_attr "cirrus" "compare")]
6822 )
6823
6824 ; This insn allows redundant compares to be removed by cse, nothing should
6825 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6826 ; is deleted later on. The match_dup will match the mode here, so that
6827 ; mode changes of the condition codes aren't lost by this even though we don't
6828 ; specify what they are.
6829
6830 (define_insn "*deleted_compare"
6831   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6832   "TARGET_ARM"
6833   "\\t%@ deleted compare"
6834   [(set_attr "conds" "set")
6835    (set_attr "length" "0")]
6836 )
6837
6838 \f
6839 ;; Conditional branch insns
6840
6841 (define_expand "beq"
6842   [(set (pc)
6843         (if_then_else (eq (match_dup 1) (const_int 0))
6844                       (label_ref (match_operand 0 "" ""))
6845                       (pc)))]
6846   "TARGET_ARM"
6847   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6848 )
6849
6850 (define_expand "bne"
6851   [(set (pc)
6852         (if_then_else (ne (match_dup 1) (const_int 0))
6853                       (label_ref (match_operand 0 "" ""))
6854                       (pc)))]
6855   "TARGET_ARM"
6856   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6857 )
6858
6859 (define_expand "bgt"
6860   [(set (pc)
6861         (if_then_else (gt (match_dup 1) (const_int 0))
6862                       (label_ref (match_operand 0 "" ""))
6863                       (pc)))]
6864   "TARGET_ARM"
6865   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6866 )
6867
6868 (define_expand "ble"
6869   [(set (pc)
6870         (if_then_else (le (match_dup 1) (const_int 0))
6871                       (label_ref (match_operand 0 "" ""))
6872                       (pc)))]
6873   "TARGET_ARM"
6874   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6875 )
6876
6877 (define_expand "bge"
6878   [(set (pc)
6879         (if_then_else (ge (match_dup 1) (const_int 0))
6880                       (label_ref (match_operand 0 "" ""))
6881                       (pc)))]
6882   "TARGET_ARM"
6883   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6884 )
6885
6886 (define_expand "blt"
6887   [(set (pc)
6888         (if_then_else (lt (match_dup 1) (const_int 0))
6889                       (label_ref (match_operand 0 "" ""))
6890                       (pc)))]
6891   "TARGET_ARM"
6892   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6893 )
6894
6895 (define_expand "bgtu"
6896   [(set (pc)
6897         (if_then_else (gtu (match_dup 1) (const_int 0))
6898                       (label_ref (match_operand 0 "" ""))
6899                       (pc)))]
6900   "TARGET_ARM"
6901   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6902 )
6903
6904 (define_expand "bleu"
6905   [(set (pc)
6906         (if_then_else (leu (match_dup 1) (const_int 0))
6907                       (label_ref (match_operand 0 "" ""))
6908                       (pc)))]
6909   "TARGET_ARM"
6910   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6911 )
6912
6913 (define_expand "bgeu"
6914   [(set (pc)
6915         (if_then_else (geu (match_dup 1) (const_int 0))
6916                       (label_ref (match_operand 0 "" ""))
6917                       (pc)))]
6918   "TARGET_ARM"
6919   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6920 )
6921
6922 (define_expand "bltu"
6923   [(set (pc)
6924         (if_then_else (ltu (match_dup 1) (const_int 0))
6925                       (label_ref (match_operand 0 "" ""))
6926                       (pc)))]
6927   "TARGET_ARM"
6928   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6929 )
6930
6931 (define_expand "bunordered"
6932   [(set (pc)
6933         (if_then_else (unordered (match_dup 1) (const_int 0))
6934                       (label_ref (match_operand 0 "" ""))
6935                       (pc)))]
6936   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
6937   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6938                                       arm_compare_op1);"
6939 )
6940
6941 (define_expand "bordered"
6942   [(set (pc)
6943         (if_then_else (ordered (match_dup 1) (const_int 0))
6944                       (label_ref (match_operand 0 "" ""))
6945                       (pc)))]
6946   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
6947   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6948                                       arm_compare_op1);"
6949 )
6950
6951 (define_expand "bungt"
6952   [(set (pc)
6953         (if_then_else (ungt (match_dup 1) (const_int 0))
6954                       (label_ref (match_operand 0 "" ""))
6955                       (pc)))]
6956   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
6957   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
6958 )
6959
6960 (define_expand "bunlt"
6961   [(set (pc)
6962         (if_then_else (unlt (match_dup 1) (const_int 0))
6963                       (label_ref (match_operand 0 "" ""))
6964                       (pc)))]
6965   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
6966   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
6967 )
6968
6969 (define_expand "bunge"
6970   [(set (pc)
6971         (if_then_else (unge (match_dup 1) (const_int 0))
6972                       (label_ref (match_operand 0 "" ""))
6973                       (pc)))]
6974   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
6975   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
6976 )
6977
6978 (define_expand "bunle"
6979   [(set (pc)
6980         (if_then_else (unle (match_dup 1) (const_int 0))
6981                       (label_ref (match_operand 0 "" ""))
6982                       (pc)))]
6983   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
6984   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
6985 )
6986
6987 ;; The following two patterns need two branch instructions, since there is
6988 ;; no single instruction that will handle all cases.
6989 (define_expand "buneq"
6990   [(set (pc)
6991         (if_then_else (uneq (match_dup 1) (const_int 0))
6992                       (label_ref (match_operand 0 "" ""))
6993                       (pc)))]
6994   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
6995   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6996 )
6997
6998 (define_expand "bltgt"
6999   [(set (pc)
7000         (if_then_else (ltgt (match_dup 1) (const_int 0))
7001                       (label_ref (match_operand 0 "" ""))
7002                       (pc)))]
7003   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7004   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
7005 )
7006
7007 ;;
7008 ;; Patterns to match conditional branch insns.
7009 ;;
7010
7011 ; Special pattern to match UNEQ.
7012 (define_insn "*arm_buneq"
7013   [(set (pc)
7014         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7015                       (label_ref (match_operand 0 "" ""))
7016                       (pc)))]
7017   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7018   "*
7019   gcc_assert (!arm_ccfsm_state);
7020
7021   return \"bvs\\t%l0\;beq\\t%l0\";
7022   "
7023   [(set_attr "conds" "jump_clob")
7024    (set_attr "length" "8")]
7025 )
7026
7027 ; Special pattern to match LTGT.
7028 (define_insn "*arm_bltgt"
7029   [(set (pc)
7030         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7031                       (label_ref (match_operand 0 "" ""))
7032                       (pc)))]
7033   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7034   "*
7035   gcc_assert (!arm_ccfsm_state);
7036
7037   return \"bmi\\t%l0\;bgt\\t%l0\";
7038   "
7039   [(set_attr "conds" "jump_clob")
7040    (set_attr "length" "8")]
7041 )
7042
7043 (define_insn "*arm_cond_branch"
7044   [(set (pc)
7045         (if_then_else (match_operator 1 "arm_comparison_operator"
7046                        [(match_operand 2 "cc_register" "") (const_int 0)])
7047                       (label_ref (match_operand 0 "" ""))
7048                       (pc)))]
7049   "TARGET_ARM"
7050   "*
7051   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7052     {
7053       arm_ccfsm_state += 2;
7054       return \"\";
7055     }
7056   return \"b%d1\\t%l0\";
7057   "
7058   [(set_attr "conds" "use")
7059    (set_attr "type" "branch")]
7060 )
7061
7062 ; Special pattern to match reversed UNEQ.
7063 (define_insn "*arm_buneq_reversed"
7064   [(set (pc)
7065         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7066                       (pc)
7067                       (label_ref (match_operand 0 "" ""))))]
7068   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7069   "*
7070   gcc_assert (!arm_ccfsm_state);
7071
7072   return \"bmi\\t%l0\;bgt\\t%l0\";
7073   "
7074   [(set_attr "conds" "jump_clob")
7075    (set_attr "length" "8")]
7076 )
7077
7078 ; Special pattern to match reversed LTGT.
7079 (define_insn "*arm_bltgt_reversed"
7080   [(set (pc)
7081         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7082                       (pc)
7083                       (label_ref (match_operand 0 "" ""))))]
7084   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7085   "*
7086   gcc_assert (!arm_ccfsm_state);
7087
7088   return \"bvs\\t%l0\;beq\\t%l0\";
7089   "
7090   [(set_attr "conds" "jump_clob")
7091    (set_attr "length" "8")]
7092 )
7093
7094 (define_insn "*arm_cond_branch_reversed"
7095   [(set (pc)
7096         (if_then_else (match_operator 1 "arm_comparison_operator"
7097                        [(match_operand 2 "cc_register" "") (const_int 0)])
7098                       (pc)
7099                       (label_ref (match_operand 0 "" ""))))]
7100   "TARGET_ARM"
7101   "*
7102   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7103     {
7104       arm_ccfsm_state += 2;
7105       return \"\";
7106     }
7107   return \"b%D1\\t%l0\";
7108   "
7109   [(set_attr "conds" "use")
7110    (set_attr "type" "branch")]
7111 )
7112
7113 \f
7114
7115 ; scc insns
7116
7117 (define_expand "seq"
7118   [(set (match_operand:SI 0 "s_register_operand" "")
7119         (eq:SI (match_dup 1) (const_int 0)))]
7120   "TARGET_ARM"
7121   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7122 )
7123
7124 (define_expand "sne"
7125   [(set (match_operand:SI 0 "s_register_operand" "")
7126         (ne:SI (match_dup 1) (const_int 0)))]
7127   "TARGET_ARM"
7128   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7129 )
7130
7131 (define_expand "sgt"
7132   [(set (match_operand:SI 0 "s_register_operand" "")
7133         (gt:SI (match_dup 1) (const_int 0)))]
7134   "TARGET_ARM"
7135   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7136 )
7137
7138 (define_expand "sle"
7139   [(set (match_operand:SI 0 "s_register_operand" "")
7140         (le:SI (match_dup 1) (const_int 0)))]
7141   "TARGET_ARM"
7142   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7143 )
7144
7145 (define_expand "sge"
7146   [(set (match_operand:SI 0 "s_register_operand" "")
7147         (ge:SI (match_dup 1) (const_int 0)))]
7148   "TARGET_ARM"
7149   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7150 )
7151
7152 (define_expand "slt"
7153   [(set (match_operand:SI 0 "s_register_operand" "")
7154         (lt:SI (match_dup 1) (const_int 0)))]
7155   "TARGET_ARM"
7156   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7157 )
7158
7159 (define_expand "sgtu"
7160   [(set (match_operand:SI 0 "s_register_operand" "")
7161         (gtu:SI (match_dup 1) (const_int 0)))]
7162   "TARGET_ARM"
7163   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7164 )
7165
7166 (define_expand "sleu"
7167   [(set (match_operand:SI 0 "s_register_operand" "")
7168         (leu:SI (match_dup 1) (const_int 0)))]
7169   "TARGET_ARM"
7170   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7171 )
7172
7173 (define_expand "sgeu"
7174   [(set (match_operand:SI 0 "s_register_operand" "")
7175         (geu:SI (match_dup 1) (const_int 0)))]
7176   "TARGET_ARM"
7177   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7178 )
7179
7180 (define_expand "sltu"
7181   [(set (match_operand:SI 0 "s_register_operand" "")
7182         (ltu:SI (match_dup 1) (const_int 0)))]
7183   "TARGET_ARM"
7184   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7185 )
7186
7187 (define_expand "sunordered"
7188   [(set (match_operand:SI 0 "s_register_operand" "")
7189         (unordered:SI (match_dup 1) (const_int 0)))]
7190   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7191   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7192                                       arm_compare_op1);"
7193 )
7194
7195 (define_expand "sordered"
7196   [(set (match_operand:SI 0 "s_register_operand" "")
7197         (ordered:SI (match_dup 1) (const_int 0)))]
7198   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7199   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7200                                       arm_compare_op1);"
7201 )
7202
7203 (define_expand "sungt"
7204   [(set (match_operand:SI 0 "s_register_operand" "")
7205         (ungt:SI (match_dup 1) (const_int 0)))]
7206   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7207   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7208                                       arm_compare_op1);"
7209 )
7210
7211 (define_expand "sunge"
7212   [(set (match_operand:SI 0 "s_register_operand" "")
7213         (unge:SI (match_dup 1) (const_int 0)))]
7214   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7215   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7216                                       arm_compare_op1);"
7217 )
7218
7219 (define_expand "sunlt"
7220   [(set (match_operand:SI 0 "s_register_operand" "")
7221         (unlt:SI (match_dup 1) (const_int 0)))]
7222   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7223   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7224                                       arm_compare_op1);"
7225 )
7226
7227 (define_expand "sunle"
7228   [(set (match_operand:SI 0 "s_register_operand" "")
7229         (unle:SI (match_dup 1) (const_int 0)))]
7230   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7231   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7232                                       arm_compare_op1);"
7233 )
7234
7235 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7236 ;;; simple ARM instructions. 
7237 ;
7238 ; (define_expand "suneq"
7239 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7240 ;       (uneq:SI (match_dup 1) (const_int 0)))]
7241 ;   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7242 ;   "gcc_unreachable ();"
7243 ; )
7244 ;
7245 ; (define_expand "sltgt"
7246 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7247 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
7248 ;   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7249 ;   "gcc_unreachable ();"
7250 ; )
7251
7252 (define_insn "*mov_scc"
7253   [(set (match_operand:SI 0 "s_register_operand" "=r")
7254         (match_operator:SI 1 "arm_comparison_operator"
7255          [(match_operand 2 "cc_register" "") (const_int 0)]))]
7256   "TARGET_ARM"
7257   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7258   [(set_attr "conds" "use")
7259    (set_attr "length" "8")]
7260 )
7261
7262 (define_insn "*mov_negscc"
7263   [(set (match_operand:SI 0 "s_register_operand" "=r")
7264         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7265                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7266   "TARGET_ARM"
7267   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7268   [(set_attr "conds" "use")
7269    (set_attr "length" "8")]
7270 )
7271
7272 (define_insn "*mov_notscc"
7273   [(set (match_operand:SI 0 "s_register_operand" "=r")
7274         (not:SI (match_operator:SI 1 "arm_comparison_operator"
7275                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7276   "TARGET_ARM"
7277   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7278   [(set_attr "conds" "use")
7279    (set_attr "length" "8")]
7280 )
7281
7282 \f
7283 ;; Conditional move insns
7284
7285 (define_expand "movsicc"
7286   [(set (match_operand:SI 0 "s_register_operand" "")
7287         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7288                          (match_operand:SI 2 "arm_not_operand" "")
7289                          (match_operand:SI 3 "arm_not_operand" "")))]
7290   "TARGET_ARM"
7291   "
7292   {
7293     enum rtx_code code = GET_CODE (operands[1]);
7294     rtx ccreg;
7295
7296     if (code == UNEQ || code == LTGT)
7297       FAIL;
7298
7299     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7300     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7301   }"
7302 )
7303
7304 (define_expand "movsfcc"
7305   [(set (match_operand:SF 0 "s_register_operand" "")
7306         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7307                          (match_operand:SF 2 "s_register_operand" "")
7308                          (match_operand:SF 3 "nonmemory_operand" "")))]
7309   "TARGET_ARM"
7310   "
7311   {
7312     enum rtx_code code = GET_CODE (operands[1]);
7313     rtx ccreg;
7314
7315     if (code == UNEQ || code == LTGT)
7316       FAIL;
7317
7318     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
7319        Otherwise, ensure it is a valid FP add operand */
7320     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7321         || (!arm_float_add_operand (operands[3], SFmode)))
7322       operands[3] = force_reg (SFmode, operands[3]);
7323
7324     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7325     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7326   }"
7327 )
7328
7329 (define_expand "movdfcc"
7330   [(set (match_operand:DF 0 "s_register_operand" "")
7331         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7332                          (match_operand:DF 2 "s_register_operand" "")
7333                          (match_operand:DF 3 "arm_float_add_operand" "")))]
7334   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7335   "
7336   {
7337     enum rtx_code code = GET_CODE (operands[1]);
7338     rtx ccreg;
7339
7340     if (code == UNEQ || code == LTGT)
7341       FAIL;
7342
7343     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7344     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7345   }"
7346 )
7347
7348 (define_insn "*movsicc_insn"
7349   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7350         (if_then_else:SI
7351          (match_operator 3 "arm_comparison_operator"
7352           [(match_operand 4 "cc_register" "") (const_int 0)])
7353          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7354          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7355   "TARGET_ARM"
7356   "@
7357    mov%D3\\t%0, %2
7358    mvn%D3\\t%0, #%B2
7359    mov%d3\\t%0, %1
7360    mvn%d3\\t%0, #%B1
7361    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7362    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7363    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7364    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7365   [(set_attr "length" "4,4,4,4,8,8,8,8")
7366    (set_attr "conds" "use")]
7367 )
7368
7369 (define_insn "*movsfcc_soft_insn"
7370   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7371         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7372                           [(match_operand 4 "cc_register" "") (const_int 0)])
7373                          (match_operand:SF 1 "s_register_operand" "0,r")
7374                          (match_operand:SF 2 "s_register_operand" "r,0")))]
7375   "TARGET_ARM && TARGET_SOFT_FLOAT"
7376   "@
7377    mov%D3\\t%0, %2
7378    mov%d3\\t%0, %1"
7379   [(set_attr "conds" "use")]
7380 )
7381
7382 \f
7383 ;; Jump and linkage insns
7384
7385 (define_expand "jump"
7386   [(set (pc)
7387         (label_ref (match_operand 0 "" "")))]
7388   "TARGET_EITHER"
7389   ""
7390 )
7391
7392 (define_insn "*arm_jump"
7393   [(set (pc)
7394         (label_ref (match_operand 0 "" "")))]
7395   "TARGET_ARM"
7396   "*
7397   {
7398     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7399       {
7400         arm_ccfsm_state += 2;
7401         return \"\";
7402       }
7403     return \"b%?\\t%l0\";
7404   }
7405   "
7406   [(set_attr "predicable" "yes")]
7407 )
7408
7409 (define_insn "*thumb_jump"
7410   [(set (pc)
7411         (label_ref (match_operand 0 "" "")))]
7412   "TARGET_THUMB"
7413   "*
7414   if (get_attr_length (insn) == 2)
7415     return \"b\\t%l0\";
7416   return \"bl\\t%l0\\t%@ far jump\";
7417   "
7418   [(set (attr "far_jump")
7419         (if_then_else
7420             (eq_attr "length" "4")
7421             (const_string "yes")
7422             (const_string "no")))
7423    (set (attr "length") 
7424         (if_then_else
7425             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7426                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
7427             (const_int 2)
7428             (const_int 4)))]
7429 )
7430
7431 (define_expand "call"
7432   [(parallel [(call (match_operand 0 "memory_operand" "")
7433                     (match_operand 1 "general_operand" ""))
7434               (use (match_operand 2 "" ""))
7435               (clobber (reg:SI LR_REGNUM))])]
7436   "TARGET_EITHER"
7437   "
7438   {
7439     rtx callee;
7440     
7441     /* In an untyped call, we can get NULL for operand 2.  */
7442     if (operands[2] == NULL_RTX)
7443       operands[2] = const0_rtx;
7444       
7445     /* This is to decide if we should generate indirect calls by loading the
7446        32 bit address of the callee into a register before performing the
7447        branch and link.  operand[2] encodes the long_call/short_call
7448        attribute of the function being called.  This attribute is set whenever
7449        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7450        is used, and the short_call attribute can also be set if function is
7451        declared as static or if it has already been defined in the current
7452        compilation unit.  See arm.c and arm.h for info about this.  The third
7453        parameter to arm_is_longcall_p is used to tell it which pattern
7454        invoked it.  */
7455     callee  = XEXP (operands[0], 0);
7456     
7457     if (GET_CODE (callee) != REG
7458        && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7459       XEXP (operands[0], 0) = force_reg (Pmode, callee);
7460   }"
7461 )
7462
7463 (define_insn "*call_reg_armv5"
7464   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7465          (match_operand 1 "" ""))
7466    (use (match_operand 2 "" ""))
7467    (clobber (reg:SI LR_REGNUM))]
7468   "TARGET_ARM && arm_arch5"
7469   "blx%?\\t%0"
7470   [(set_attr "type" "call")]
7471 )
7472
7473 (define_insn "*call_reg_arm"
7474   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7475          (match_operand 1 "" ""))
7476    (use (match_operand 2 "" ""))
7477    (clobber (reg:SI LR_REGNUM))]
7478   "TARGET_ARM && !arm_arch5"
7479   "*
7480   return output_call (operands);
7481   "
7482   ;; length is worst case, normally it is only two
7483   [(set_attr "length" "12")
7484    (set_attr "type" "call")]
7485 )
7486
7487 (define_insn "*call_mem"
7488   [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7489          (match_operand 1 "" ""))
7490    (use (match_operand 2 "" ""))
7491    (clobber (reg:SI LR_REGNUM))]
7492   "TARGET_ARM"
7493   "*
7494   return output_call_mem (operands);
7495   "
7496   [(set_attr "length" "12")
7497    (set_attr "type" "call")]
7498 )
7499
7500 (define_insn "*call_reg_thumb_v5"
7501   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7502          (match_operand 1 "" ""))
7503    (use (match_operand 2 "" ""))
7504    (clobber (reg:SI LR_REGNUM))]
7505   "TARGET_THUMB && arm_arch5"
7506   "blx\\t%0"
7507   [(set_attr "length" "2")
7508    (set_attr "type" "call")]
7509 )
7510
7511 (define_insn "*call_reg_thumb"
7512   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7513          (match_operand 1 "" ""))
7514    (use (match_operand 2 "" ""))
7515    (clobber (reg:SI LR_REGNUM))]
7516   "TARGET_THUMB && !arm_arch5"
7517   "*
7518   {
7519     if (!TARGET_CALLER_INTERWORKING)
7520       return thumb_call_via_reg (operands[0]);
7521     else if (operands[1] == const0_rtx)
7522       return \"bl\\t%__interwork_call_via_%0\";
7523     else if (frame_pointer_needed)
7524       return \"bl\\t%__interwork_r7_call_via_%0\";
7525     else
7526       return \"bl\\t%__interwork_r11_call_via_%0\";
7527   }"
7528   [(set_attr "type" "call")]
7529 )
7530
7531 (define_expand "call_value"
7532   [(parallel [(set (match_operand       0 "" "")
7533                    (call (match_operand 1 "memory_operand" "")
7534                          (match_operand 2 "general_operand" "")))
7535               (use (match_operand 3 "" ""))
7536               (clobber (reg:SI LR_REGNUM))])]
7537   "TARGET_EITHER"
7538   "
7539   {
7540     rtx callee = XEXP (operands[1], 0);
7541     
7542     /* In an untyped call, we can get NULL for operand 2.  */
7543     if (operands[3] == 0)
7544       operands[3] = const0_rtx;
7545       
7546     /* See the comment in define_expand \"call\".  */
7547     if (GET_CODE (callee) != REG
7548         && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7549       XEXP (operands[1], 0) = force_reg (Pmode, callee);
7550   }"
7551 )
7552
7553 (define_insn "*call_value_reg_armv5"
7554   [(set (match_operand 0 "" "")
7555         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7556               (match_operand 2 "" "")))
7557    (use (match_operand 3 "" ""))
7558    (clobber (reg:SI LR_REGNUM))]
7559   "TARGET_ARM && arm_arch5"
7560   "blx%?\\t%1"
7561   [(set_attr "type" "call")]
7562 )
7563
7564 (define_insn "*call_value_reg_arm"
7565   [(set (match_operand 0 "" "")
7566         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7567               (match_operand 2 "" "")))
7568    (use (match_operand 3 "" ""))
7569    (clobber (reg:SI LR_REGNUM))]
7570   "TARGET_ARM && !arm_arch5"
7571   "*
7572   return output_call (&operands[1]);
7573   "
7574   [(set_attr "length" "12")
7575    (set_attr "type" "call")]
7576 )
7577
7578 (define_insn "*call_value_mem"
7579   [(set (match_operand 0 "" "")
7580         (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7581               (match_operand 2 "" "")))
7582    (use (match_operand 3 "" ""))
7583    (clobber (reg:SI LR_REGNUM))]
7584   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7585   "*
7586   return output_call_mem (&operands[1]);
7587   "
7588   [(set_attr "length" "12")
7589    (set_attr "type" "call")]
7590 )
7591
7592 (define_insn "*call_value_reg_thumb_v5"
7593   [(set (match_operand 0 "" "")
7594         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7595               (match_operand 2 "" "")))
7596    (use (match_operand 3 "" ""))
7597    (clobber (reg:SI LR_REGNUM))]
7598   "TARGET_THUMB && arm_arch5"
7599   "blx\\t%1"
7600   [(set_attr "length" "2")
7601    (set_attr "type" "call")]
7602 )
7603
7604 (define_insn "*call_value_reg_thumb"
7605   [(set (match_operand 0 "" "")
7606         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7607               (match_operand 2 "" "")))
7608    (use (match_operand 3 "" ""))
7609    (clobber (reg:SI LR_REGNUM))]
7610   "TARGET_THUMB && !arm_arch5"
7611   "*
7612   {
7613     if (!TARGET_CALLER_INTERWORKING)
7614       return thumb_call_via_reg (operands[1]);
7615     else if (operands[2] == const0_rtx)
7616       return \"bl\\t%__interwork_call_via_%1\";
7617     else if (frame_pointer_needed)
7618       return \"bl\\t%__interwork_r7_call_via_%1\";
7619     else
7620       return \"bl\\t%__interwork_r11_call_via_%1\";
7621   }"
7622   [(set_attr "type" "call")]
7623 )
7624
7625 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7626 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7627
7628 (define_insn "*call_symbol"
7629   [(call (mem:SI (match_operand:SI 0 "" ""))
7630          (match_operand 1 "" ""))
7631    (use (match_operand 2 "" ""))
7632    (clobber (reg:SI LR_REGNUM))]
7633   "TARGET_ARM
7634    && (GET_CODE (operands[0]) == SYMBOL_REF)
7635    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7636   "*
7637   {
7638     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7639   }"
7640   [(set_attr "type" "call")]
7641 )
7642
7643 (define_insn "*call_value_symbol"
7644   [(set (match_operand 0 "" "")
7645         (call (mem:SI (match_operand:SI 1 "" ""))
7646         (match_operand:SI 2 "" "")))
7647    (use (match_operand 3 "" ""))
7648    (clobber (reg:SI LR_REGNUM))]
7649   "TARGET_ARM
7650    && (GET_CODE (operands[1]) == SYMBOL_REF)
7651    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7652   "*
7653   {
7654     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7655   }"
7656   [(set_attr "type" "call")]
7657 )
7658
7659 (define_insn "*call_insn"
7660   [(call (mem:SI (match_operand:SI 0 "" ""))
7661          (match_operand:SI 1 "" ""))
7662    (use (match_operand 2 "" ""))
7663    (clobber (reg:SI LR_REGNUM))]
7664   "TARGET_THUMB
7665    && GET_CODE (operands[0]) == SYMBOL_REF
7666    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7667   "bl\\t%a0"
7668   [(set_attr "length" "4")
7669    (set_attr "type" "call")]
7670 )
7671
7672 (define_insn "*call_value_insn"
7673   [(set (match_operand 0 "" "")
7674         (call (mem:SI (match_operand 1 "" ""))
7675               (match_operand 2 "" "")))
7676    (use (match_operand 3 "" ""))
7677    (clobber (reg:SI LR_REGNUM))]
7678   "TARGET_THUMB
7679    && GET_CODE (operands[1]) == SYMBOL_REF
7680    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7681   "bl\\t%a1"
7682   [(set_attr "length" "4")
7683    (set_attr "type" "call")]
7684 )
7685
7686 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7687 (define_expand "sibcall"
7688   [(parallel [(call (match_operand 0 "memory_operand" "")
7689                     (match_operand 1 "general_operand" ""))
7690               (return)
7691               (use (match_operand 2 "" ""))])]
7692   "TARGET_ARM"
7693   "
7694   {
7695     if (operands[2] == NULL_RTX)
7696       operands[2] = const0_rtx;
7697   }"
7698 )
7699
7700 (define_expand "sibcall_value"
7701   [(parallel [(set (match_operand 0 "" "")
7702                    (call (match_operand 1 "memory_operand" "")
7703                          (match_operand 2 "general_operand" "")))
7704               (return)
7705               (use (match_operand 3 "" ""))])]
7706   "TARGET_ARM"
7707   "
7708   {
7709     if (operands[3] == NULL_RTX)
7710       operands[3] = const0_rtx;
7711   }"
7712 )
7713
7714 (define_insn "*sibcall_insn"
7715  [(call (mem:SI (match_operand:SI 0 "" "X"))
7716         (match_operand 1 "" ""))
7717   (return)
7718   (use (match_operand 2 "" ""))]
7719   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7720   "*
7721   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7722   "
7723   [(set_attr "type" "call")]
7724 )
7725
7726 (define_insn "*sibcall_value_insn"
7727  [(set (match_operand 0 "" "")
7728        (call (mem:SI (match_operand:SI 1 "" "X"))
7729              (match_operand 2 "" "")))
7730   (return)
7731   (use (match_operand 3 "" ""))]
7732   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7733   "*
7734   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7735   "
7736   [(set_attr "type" "call")]
7737 )
7738
7739 ;; Often the return insn will be the same as loading from memory, so set attr
7740 (define_insn "return"
7741   [(return)]
7742   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7743   "*
7744   {
7745     if (arm_ccfsm_state == 2)
7746       {
7747         arm_ccfsm_state += 2;
7748         return \"\";
7749       }
7750     return output_return_instruction (const_true_rtx, TRUE, FALSE);
7751   }"
7752   [(set_attr "type" "load1")
7753    (set_attr "length" "12")
7754    (set_attr "predicable" "yes")]
7755 )
7756
7757 (define_insn "*cond_return"
7758   [(set (pc)
7759         (if_then_else (match_operator 0 "arm_comparison_operator"
7760                        [(match_operand 1 "cc_register" "") (const_int 0)])
7761                       (return)
7762                       (pc)))]
7763   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7764   "*
7765   {
7766     if (arm_ccfsm_state == 2)
7767       {
7768         arm_ccfsm_state += 2;
7769         return \"\";
7770       }
7771     return output_return_instruction (operands[0], TRUE, FALSE);
7772   }"
7773   [(set_attr "conds" "use")
7774    (set_attr "length" "12")
7775    (set_attr "type" "load1")]
7776 )
7777
7778 (define_insn "*cond_return_inverted"
7779   [(set (pc)
7780         (if_then_else (match_operator 0 "arm_comparison_operator"
7781                        [(match_operand 1 "cc_register" "") (const_int 0)])
7782                       (pc)
7783                       (return)))]
7784   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7785   "*
7786   {
7787     if (arm_ccfsm_state == 2)
7788       {
7789         arm_ccfsm_state += 2;
7790         return \"\";
7791       }
7792     return output_return_instruction (operands[0], TRUE, TRUE);
7793   }"
7794   [(set_attr "conds" "use")
7795    (set_attr "length" "12")
7796    (set_attr "type" "load1")]
7797 )
7798
7799 ;; Generate a sequence of instructions to determine if the processor is
7800 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7801 ;; mask.
7802
7803 (define_expand "return_addr_mask"
7804   [(set (match_dup 1)
7805       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7806                        (const_int 0)))
7807    (set (match_operand:SI 0 "s_register_operand" "")
7808       (if_then_else:SI (eq (match_dup 1) (const_int 0))
7809                        (const_int -1)
7810                        (const_int 67108860)))] ; 0x03fffffc
7811   "TARGET_ARM"
7812   "
7813   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7814   ")
7815
7816 (define_insn "*check_arch2"
7817   [(set (match_operand:CC_NOOV 0 "cc_register" "")
7818       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7819                        (const_int 0)))]
7820   "TARGET_ARM"
7821   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7822   [(set_attr "length" "8")
7823    (set_attr "conds" "set")]
7824 )
7825
7826 ;; Call subroutine returning any type.
7827
7828 (define_expand "untyped_call"
7829   [(parallel [(call (match_operand 0 "" "")
7830                     (const_int 0))
7831               (match_operand 1 "" "")
7832               (match_operand 2 "" "")])]
7833   "TARGET_EITHER"
7834   "
7835   {
7836     int i;
7837     rtx par = gen_rtx_PARALLEL (VOIDmode,
7838                                 rtvec_alloc (XVECLEN (operands[2], 0)));
7839     rtx addr = gen_reg_rtx (Pmode);
7840     rtx mem;
7841     int size = 0;
7842
7843     emit_move_insn (addr, XEXP (operands[1], 0));
7844     mem = change_address (operands[1], BLKmode, addr);
7845
7846     for (i = 0; i < XVECLEN (operands[2], 0); i++)
7847       {
7848         rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
7849
7850         /* Default code only uses r0 as a return value, but we could
7851            be using anything up to 4 registers.  */
7852         if (REGNO (src) == R0_REGNUM)
7853           src = gen_rtx_REG (TImode, R0_REGNUM);
7854
7855         XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
7856                                                  GEN_INT (size));
7857         size += GET_MODE_SIZE (GET_MODE (src));
7858       }
7859
7860     emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
7861                                     const0_rtx));
7862
7863     size = 0;
7864
7865     for (i = 0; i < XVECLEN (par, 0); i++)
7866       {
7867         HOST_WIDE_INT offset = 0;
7868         rtx reg = XEXP (XVECEXP (par, 0, i), 0);
7869
7870         if (size != 0)
7871           emit_move_insn (addr, plus_constant (addr, size));
7872
7873         mem = change_address (mem, GET_MODE (reg), NULL);
7874         if (REGNO (reg) == R0_REGNUM)
7875           {
7876             /* On thumb we have to use a write-back instruction.  */
7877             emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
7878                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7879             size = TARGET_ARM ? 16 : 0;
7880           }
7881         else
7882           {
7883             emit_move_insn (mem, reg);
7884             size = GET_MODE_SIZE (GET_MODE (reg));
7885           }
7886       }
7887
7888     /* The optimizer does not know that the call sets the function value
7889        registers we stored in the result block.  We avoid problems by
7890        claiming that all hard registers are used and clobbered at this
7891        point.  */
7892     emit_insn (gen_blockage ());
7893
7894     DONE;
7895   }"
7896 )
7897
7898 (define_expand "untyped_return"
7899   [(match_operand:BLK 0 "memory_operand" "")
7900    (match_operand 1 "" "")]
7901   "TARGET_EITHER"
7902   "
7903   {
7904     int i;
7905     rtx addr = gen_reg_rtx (Pmode);
7906     rtx mem;
7907     int size = 0;
7908
7909     emit_move_insn (addr, XEXP (operands[0], 0));
7910     mem = change_address (operands[0], BLKmode, addr);
7911
7912     for (i = 0; i < XVECLEN (operands[1], 0); i++)
7913       {
7914         HOST_WIDE_INT offset = 0;
7915         rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
7916
7917         if (size != 0)
7918           emit_move_insn (addr, plus_constant (addr, size));
7919
7920         mem = change_address (mem, GET_MODE (reg), NULL);
7921         if (REGNO (reg) == R0_REGNUM)
7922           {
7923             /* On thumb we have to use a write-back instruction.  */
7924             emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
7925                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7926             size = TARGET_ARM ? 16 : 0;
7927           }
7928         else
7929           {
7930             emit_move_insn (reg, mem);
7931             size = GET_MODE_SIZE (GET_MODE (reg));
7932           }
7933       }
7934
7935     /* Emit USE insns before the return.  */
7936     for (i = 0; i < XVECLEN (operands[1], 0); i++)
7937       emit_insn (gen_rtx_USE (VOIDmode,
7938                               SET_DEST (XVECEXP (operands[1], 0, i))));
7939
7940     /* Construct the return.  */
7941     expand_naked_return ();
7942
7943     DONE;
7944   }"
7945 )
7946
7947 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7948 ;; all of memory.  This blocks insns from being moved across this point.
7949
7950 (define_insn "blockage"
7951   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
7952   "TARGET_EITHER"
7953   ""
7954   [(set_attr "length" "0")
7955    (set_attr "type" "block")]
7956 )
7957
7958 (define_expand "casesi"
7959   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
7960    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
7961    (match_operand:SI 2 "const_int_operand" "")  ; total range
7962    (match_operand:SI 3 "" "")                   ; table label
7963    (match_operand:SI 4 "" "")]                  ; Out of range label
7964   "TARGET_ARM"
7965   "
7966   {
7967     rtx reg;
7968     if (operands[1] != const0_rtx)
7969       {
7970         reg = gen_reg_rtx (SImode);
7971
7972         emit_insn (gen_addsi3 (reg, operands[0],
7973                                GEN_INT (-INTVAL (operands[1]))));
7974         operands[0] = reg;
7975       }
7976
7977     if (!const_ok_for_arm (INTVAL (operands[2])))
7978       operands[2] = force_reg (SImode, operands[2]);
7979
7980     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
7981                                          operands[4]));
7982     DONE;
7983   }"
7984 )
7985
7986 ;; The USE in this pattern is needed to tell flow analysis that this is
7987 ;; a CASESI insn.  It has no other purpose.
7988 (define_insn "casesi_internal"
7989   [(parallel [(set (pc)
7990                (if_then_else
7991                 (leu (match_operand:SI 0 "s_register_operand" "r")
7992                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
7993                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
7994                                  (label_ref (match_operand 2 "" ""))))
7995                 (label_ref (match_operand 3 "" ""))))
7996               (clobber (reg:CC CC_REGNUM))
7997               (use (label_ref (match_dup 2)))])]
7998   "TARGET_ARM"
7999   "*
8000     if (flag_pic)
8001       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8002     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8003   "
8004   [(set_attr "conds" "clob")
8005    (set_attr "length" "12")]
8006 )
8007
8008 (define_expand "indirect_jump"
8009   [(set (pc)
8010         (match_operand:SI 0 "s_register_operand" ""))]
8011   "TARGET_EITHER"
8012   ""
8013 )
8014
8015 ;; NB Never uses BX.
8016 (define_insn "*arm_indirect_jump"
8017   [(set (pc)
8018         (match_operand:SI 0 "s_register_operand" "r"))]
8019   "TARGET_ARM"
8020   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
8021   [(set_attr "predicable" "yes")]
8022 )
8023
8024 (define_insn "*load_indirect_jump"
8025   [(set (pc)
8026         (match_operand:SI 0 "memory_operand" "m"))]
8027   "TARGET_ARM"
8028   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
8029   [(set_attr "type" "load1")
8030    (set_attr "pool_range" "4096")
8031    (set_attr "neg_pool_range" "4084")
8032    (set_attr "predicable" "yes")]
8033 )
8034
8035 ;; NB Never uses BX.
8036 (define_insn "*thumb_indirect_jump"
8037   [(set (pc)
8038         (match_operand:SI 0 "register_operand" "l*r"))]
8039   "TARGET_THUMB"
8040   "mov\\tpc, %0"
8041   [(set_attr "conds" "clob")
8042    (set_attr "length" "2")]
8043 )
8044
8045 \f
8046 ;; Misc insns
8047
8048 (define_insn "nop"
8049   [(const_int 0)]
8050   "TARGET_EITHER"
8051   "*
8052   if (TARGET_ARM)
8053     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8054   return  \"mov\\tr8, r8\";
8055   "
8056   [(set (attr "length")
8057         (if_then_else (eq_attr "is_thumb" "yes")
8058                       (const_int 2)
8059                       (const_int 4)))]
8060 )
8061
8062 \f
8063 ;; Patterns to allow combination of arithmetic, cond code and shifts
8064
8065 (define_insn "*arith_shiftsi"
8066   [(set (match_operand:SI 0 "s_register_operand" "=r")
8067         (match_operator:SI 1 "shiftable_operator"
8068           [(match_operator:SI 3 "shift_operator"
8069              [(match_operand:SI 4 "s_register_operand" "r")
8070               (match_operand:SI 5 "reg_or_int_operand" "rI")])
8071            (match_operand:SI 2 "s_register_operand" "r")]))]
8072   "TARGET_ARM"
8073   "%i1%?\\t%0, %2, %4%S3"
8074   [(set_attr "predicable" "yes")
8075    (set_attr "shift" "4")
8076    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8077                       (const_string "alu_shift")
8078                       (const_string "alu_shift_reg")))]
8079 )
8080
8081 (define_split
8082   [(set (match_operand:SI 0 "s_register_operand" "")
8083         (match_operator:SI 1 "shiftable_operator"
8084          [(match_operator:SI 2 "shiftable_operator"
8085            [(match_operator:SI 3 "shift_operator"
8086              [(match_operand:SI 4 "s_register_operand" "")
8087               (match_operand:SI 5 "reg_or_int_operand" "")])
8088             (match_operand:SI 6 "s_register_operand" "")])
8089           (match_operand:SI 7 "arm_rhs_operand" "")]))
8090    (clobber (match_operand:SI 8 "s_register_operand" ""))]
8091   "TARGET_ARM"
8092   [(set (match_dup 8)
8093         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8094                          (match_dup 6)]))
8095    (set (match_dup 0)
8096         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8097   "")
8098
8099 (define_insn "*arith_shiftsi_compare0"
8100   [(set (reg:CC_NOOV CC_REGNUM)
8101         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8102                           [(match_operator:SI 3 "shift_operator"
8103                             [(match_operand:SI 4 "s_register_operand" "r")
8104                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8105                            (match_operand:SI 2 "s_register_operand" "r")])
8106                          (const_int 0)))
8107    (set (match_operand:SI 0 "s_register_operand" "=r")
8108         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8109                          (match_dup 2)]))]
8110   "TARGET_ARM"
8111   "%i1%?s\\t%0, %2, %4%S3"
8112   [(set_attr "conds" "set")
8113    (set_attr "shift" "4")
8114    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8115                       (const_string "alu_shift")
8116                       (const_string "alu_shift_reg")))]
8117 )
8118
8119 (define_insn "*arith_shiftsi_compare0_scratch"
8120   [(set (reg:CC_NOOV CC_REGNUM)
8121         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8122                           [(match_operator:SI 3 "shift_operator"
8123                             [(match_operand:SI 4 "s_register_operand" "r")
8124                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8125                            (match_operand:SI 2 "s_register_operand" "r")])
8126                          (const_int 0)))
8127    (clobber (match_scratch:SI 0 "=r"))]
8128   "TARGET_ARM"
8129   "%i1%?s\\t%0, %2, %4%S3"
8130   [(set_attr "conds" "set")
8131    (set_attr "shift" "4")
8132    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8133                       (const_string "alu_shift")
8134                       (const_string "alu_shift_reg")))]
8135 )
8136
8137 (define_insn "*sub_shiftsi"
8138   [(set (match_operand:SI 0 "s_register_operand" "=r")
8139         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8140                   (match_operator:SI 2 "shift_operator"
8141                    [(match_operand:SI 3 "s_register_operand" "r")
8142                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
8143   "TARGET_ARM"
8144   "sub%?\\t%0, %1, %3%S2"
8145   [(set_attr "predicable" "yes")
8146    (set_attr "shift" "3")
8147    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8148                       (const_string "alu_shift")
8149                       (const_string "alu_shift_reg")))]
8150 )
8151
8152 (define_insn "*sub_shiftsi_compare0"
8153   [(set (reg:CC_NOOV CC_REGNUM)
8154         (compare:CC_NOOV
8155          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8156                    (match_operator:SI 2 "shift_operator"
8157                     [(match_operand:SI 3 "s_register_operand" "r")
8158                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8159          (const_int 0)))
8160    (set (match_operand:SI 0 "s_register_operand" "=r")
8161         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8162                                                  (match_dup 4)])))]
8163   "TARGET_ARM"
8164   "sub%?s\\t%0, %1, %3%S2"
8165   [(set_attr "conds" "set")
8166    (set_attr "shift" "3")
8167    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8168                       (const_string "alu_shift")
8169                       (const_string "alu_shift_reg")))]
8170 )
8171
8172 (define_insn "*sub_shiftsi_compare0_scratch"
8173   [(set (reg:CC_NOOV CC_REGNUM)
8174         (compare:CC_NOOV
8175          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8176                    (match_operator:SI 2 "shift_operator"
8177                     [(match_operand:SI 3 "s_register_operand" "r")
8178                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8179          (const_int 0)))
8180    (clobber (match_scratch:SI 0 "=r"))]
8181   "TARGET_ARM"
8182   "sub%?s\\t%0, %1, %3%S2"
8183   [(set_attr "conds" "set")
8184    (set_attr "shift" "3")
8185    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8186                       (const_string "alu_shift")
8187                       (const_string "alu_shift_reg")))]
8188 )
8189
8190 \f
8191
8192 (define_insn "*and_scc"
8193   [(set (match_operand:SI 0 "s_register_operand" "=r")
8194         (and:SI (match_operator:SI 1 "arm_comparison_operator"
8195                  [(match_operand 3 "cc_register" "") (const_int 0)])
8196                 (match_operand:SI 2 "s_register_operand" "r")))]
8197   "TARGET_ARM"
8198   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8199   [(set_attr "conds" "use")
8200    (set_attr "length" "8")]
8201 )
8202
8203 (define_insn "*ior_scc"
8204   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8205         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8206                  [(match_operand 3 "cc_register" "") (const_int 0)])
8207                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8208   "TARGET_ARM"
8209   "@
8210    orr%d2\\t%0, %1, #1
8211    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8212   [(set_attr "conds" "use")
8213    (set_attr "length" "4,8")]
8214 )
8215
8216 (define_insn "*compare_scc"
8217   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8218         (match_operator:SI 1 "arm_comparison_operator"
8219          [(match_operand:SI 2 "s_register_operand" "r,r")
8220           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8221    (clobber (reg:CC CC_REGNUM))]
8222   "TARGET_ARM"
8223   "*
8224     if (operands[3] == const0_rtx)
8225       {
8226         if (GET_CODE (operands[1]) == LT)
8227           return \"mov\\t%0, %2, lsr #31\";
8228
8229         if (GET_CODE (operands[1]) == GE)
8230           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8231
8232         if (GET_CODE (operands[1]) == EQ)
8233           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8234       }
8235
8236     if (GET_CODE (operands[1]) == NE)
8237       {
8238         if (which_alternative == 1)
8239           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8240         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8241       }
8242     if (which_alternative == 1)
8243       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8244     else
8245       output_asm_insn (\"cmp\\t%2, %3\", operands);
8246     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8247   "
8248   [(set_attr "conds" "clob")
8249    (set_attr "length" "12")]
8250 )
8251
8252 (define_insn "*cond_move"
8253   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8254         (if_then_else:SI (match_operator 3 "equality_operator"
8255                           [(match_operator 4 "arm_comparison_operator"
8256                             [(match_operand 5 "cc_register" "") (const_int 0)])
8257                            (const_int 0)])
8258                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8259                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8260   "TARGET_ARM"
8261   "*
8262     if (GET_CODE (operands[3]) == NE)
8263       {
8264         if (which_alternative != 1)
8265           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8266         if (which_alternative != 0)
8267           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8268         return \"\";
8269       }
8270     if (which_alternative != 0)
8271       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8272     if (which_alternative != 1)
8273       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8274     return \"\";
8275   "
8276   [(set_attr "conds" "use")
8277    (set_attr "length" "4,4,8")]
8278 )
8279
8280 (define_insn "*cond_arith"
8281   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8282         (match_operator:SI 5 "shiftable_operator" 
8283          [(match_operator:SI 4 "arm_comparison_operator"
8284            [(match_operand:SI 2 "s_register_operand" "r,r")
8285             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8286           (match_operand:SI 1 "s_register_operand" "0,?r")]))
8287    (clobber (reg:CC CC_REGNUM))]
8288   "TARGET_ARM"
8289   "*
8290     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8291       return \"%i5\\t%0, %1, %2, lsr #31\";
8292
8293     output_asm_insn (\"cmp\\t%2, %3\", operands);
8294     if (GET_CODE (operands[5]) == AND)
8295       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8296     else if (GET_CODE (operands[5]) == MINUS)
8297       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8298     else if (which_alternative != 0)
8299       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8300     return \"%i5%d4\\t%0, %1, #1\";
8301   "
8302   [(set_attr "conds" "clob")
8303    (set_attr "length" "12")]
8304 )
8305
8306 (define_insn "*cond_sub"
8307   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8308         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8309                   (match_operator:SI 4 "arm_comparison_operator"
8310                    [(match_operand:SI 2 "s_register_operand" "r,r")
8311                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8312    (clobber (reg:CC CC_REGNUM))]
8313   "TARGET_ARM"
8314   "*
8315     output_asm_insn (\"cmp\\t%2, %3\", operands);
8316     if (which_alternative != 0)
8317       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8318     return \"sub%d4\\t%0, %1, #1\";
8319   "
8320   [(set_attr "conds" "clob")
8321    (set_attr "length" "8,12")]
8322 )
8323
8324 (define_insn "*cmp_ite0"
8325   [(set (match_operand 6 "dominant_cc_register" "")
8326         (compare
8327          (if_then_else:SI
8328           (match_operator 4 "arm_comparison_operator"
8329            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8330             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8331           (match_operator:SI 5 "arm_comparison_operator"
8332            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8333             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8334           (const_int 0))
8335          (const_int 0)))]
8336   "TARGET_ARM"
8337   "*
8338   {
8339     static const char * const opcodes[4][2] =
8340     {
8341       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8342        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8343       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8344        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8345       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8346        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8347       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8348        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8349     };
8350     int swap =
8351       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8352
8353     return opcodes[which_alternative][swap];
8354   }"
8355   [(set_attr "conds" "set")
8356    (set_attr "length" "8")]
8357 )
8358
8359 (define_insn "*cmp_ite1"
8360   [(set (match_operand 6 "dominant_cc_register" "")
8361         (compare
8362          (if_then_else:SI
8363           (match_operator 4 "arm_comparison_operator"
8364            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8365             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8366           (match_operator:SI 5 "arm_comparison_operator"
8367            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8368             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8369           (const_int 1))
8370          (const_int 0)))]
8371   "TARGET_ARM"
8372   "*
8373   {
8374     static const char * const opcodes[4][2] =
8375     {
8376       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8377        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8378       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8379        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8380       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8381        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8382       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8383        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8384     };
8385     int swap =
8386       comparison_dominates_p (GET_CODE (operands[5]),
8387                               reverse_condition (GET_CODE (operands[4])));
8388
8389     return opcodes[which_alternative][swap];
8390   }"
8391   [(set_attr "conds" "set")
8392    (set_attr "length" "8")]
8393 )
8394
8395 (define_insn "*cmp_and"
8396   [(set (match_operand 6 "dominant_cc_register" "")
8397         (compare
8398          (and:SI
8399           (match_operator 4 "arm_comparison_operator"
8400            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8401             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8402           (match_operator:SI 5 "arm_comparison_operator"
8403            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8404             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8405          (const_int 0)))]
8406   "TARGET_ARM"
8407   "*
8408   {
8409     static const char *const opcodes[4][2] =
8410     {
8411       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8412        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8413       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8414        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8415       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8416        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8417       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8418        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8419     };
8420     int swap =
8421       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8422
8423     return opcodes[which_alternative][swap];
8424   }"
8425   [(set_attr "conds" "set")
8426    (set_attr "predicable" "no")
8427    (set_attr "length" "8")]
8428 )
8429
8430 (define_insn "*cmp_ior"
8431   [(set (match_operand 6 "dominant_cc_register" "")
8432         (compare
8433          (ior:SI
8434           (match_operator 4 "arm_comparison_operator"
8435            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8436             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8437           (match_operator:SI 5 "arm_comparison_operator"
8438            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8439             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8440          (const_int 0)))]
8441   "TARGET_ARM"
8442   "*
8443 {
8444   static const char *const opcodes[4][2] =
8445   {
8446     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8447      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8448     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8449      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8450     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8451      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8452     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8453      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8454   };
8455   int swap =
8456     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8457
8458   return opcodes[which_alternative][swap];
8459 }
8460 "
8461   [(set_attr "conds" "set")
8462    (set_attr "length" "8")]
8463 )
8464
8465 (define_insn_and_split "*ior_scc_scc"
8466   [(set (match_operand:SI 0 "s_register_operand" "=r")
8467         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8468                  [(match_operand:SI 1 "s_register_operand" "r")
8469                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8470                 (match_operator:SI 6 "arm_comparison_operator"
8471                  [(match_operand:SI 4 "s_register_operand" "r")
8472                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8473    (clobber (reg:CC CC_REGNUM))]
8474   "TARGET_ARM
8475    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8476        != CCmode)"
8477   "#"
8478   "TARGET_ARM && reload_completed"
8479   [(set (match_dup 7)
8480         (compare
8481          (ior:SI
8482           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8483           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8484          (const_int 0)))
8485    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8486   "operands[7]
8487      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8488                                                   DOM_CC_X_OR_Y),
8489                     CC_REGNUM);"
8490   [(set_attr "conds" "clob")
8491    (set_attr "length" "16")])
8492
8493 ; If the above pattern is followed by a CMP insn, then the compare is 
8494 ; redundant, since we can rework the conditional instruction that follows.
8495 (define_insn_and_split "*ior_scc_scc_cmp"
8496   [(set (match_operand 0 "dominant_cc_register" "")
8497         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8498                           [(match_operand:SI 1 "s_register_operand" "r")
8499                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8500                          (match_operator:SI 6 "arm_comparison_operator"
8501                           [(match_operand:SI 4 "s_register_operand" "r")
8502                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8503                  (const_int 0)))
8504    (set (match_operand:SI 7 "s_register_operand" "=r")
8505         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8506                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8507   "TARGET_ARM"
8508   "#"
8509   "TARGET_ARM && reload_completed"
8510   [(set (match_dup 0)
8511         (compare
8512          (ior:SI
8513           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8514           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8515          (const_int 0)))
8516    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8517   ""
8518   [(set_attr "conds" "set")
8519    (set_attr "length" "16")])
8520
8521 (define_insn_and_split "*and_scc_scc"
8522   [(set (match_operand:SI 0 "s_register_operand" "=r")
8523         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8524                  [(match_operand:SI 1 "s_register_operand" "r")
8525                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8526                 (match_operator:SI 6 "arm_comparison_operator"
8527                  [(match_operand:SI 4 "s_register_operand" "r")
8528                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8529    (clobber (reg:CC CC_REGNUM))]
8530   "TARGET_ARM
8531    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8532        != CCmode)"
8533   "#"
8534   "TARGET_ARM && reload_completed
8535    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8536        != CCmode)"
8537   [(set (match_dup 7)
8538         (compare
8539          (and:SI
8540           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8541           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8542          (const_int 0)))
8543    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8544   "operands[7]
8545      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8546                                                   DOM_CC_X_AND_Y),
8547                     CC_REGNUM);"
8548   [(set_attr "conds" "clob")
8549    (set_attr "length" "16")])
8550
8551 ; If the above pattern is followed by a CMP insn, then the compare is 
8552 ; redundant, since we can rework the conditional instruction that follows.
8553 (define_insn_and_split "*and_scc_scc_cmp"
8554   [(set (match_operand 0 "dominant_cc_register" "")
8555         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8556                           [(match_operand:SI 1 "s_register_operand" "r")
8557                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8558                          (match_operator:SI 6 "arm_comparison_operator"
8559                           [(match_operand:SI 4 "s_register_operand" "r")
8560                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8561                  (const_int 0)))
8562    (set (match_operand:SI 7 "s_register_operand" "=r")
8563         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8564                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8565   "TARGET_ARM"
8566   "#"
8567   "TARGET_ARM && reload_completed"
8568   [(set (match_dup 0)
8569         (compare
8570          (and:SI
8571           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8572           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8573          (const_int 0)))
8574    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8575   ""
8576   [(set_attr "conds" "set")
8577    (set_attr "length" "16")])
8578
8579 ;; If there is no dominance in the comparison, then we can still save an
8580 ;; instruction in the AND case, since we can know that the second compare
8581 ;; need only zero the value if false (if true, then the value is already
8582 ;; correct).
8583 (define_insn_and_split "*and_scc_scc_nodom"
8584   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8585         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8586                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
8587                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8588                 (match_operator:SI 6 "arm_comparison_operator"
8589                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
8590                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8591    (clobber (reg:CC CC_REGNUM))]
8592   "TARGET_ARM
8593    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8594        == CCmode)"
8595   "#"
8596   "TARGET_ARM && reload_completed"
8597   [(parallel [(set (match_dup 0)
8598                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8599               (clobber (reg:CC CC_REGNUM))])
8600    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8601    (set (match_dup 0)
8602         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8603                          (match_dup 0)
8604                          (const_int 0)))]
8605   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8606                                               operands[4], operands[5]),
8607                               CC_REGNUM);
8608    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8609                                   operands[5]);"
8610   [(set_attr "conds" "clob")
8611    (set_attr "length" "20")])
8612
8613 (define_split
8614   [(set (reg:CC_NOOV CC_REGNUM)
8615         (compare:CC_NOOV (ior:SI
8616                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8617                                   (const_int 1))
8618                           (match_operator:SI 1 "comparison_operator"
8619                            [(match_operand:SI 2 "s_register_operand" "")
8620                             (match_operand:SI 3 "arm_add_operand" "")]))
8621                          (const_int 0)))
8622    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8623   "TARGET_ARM"
8624   [(set (match_dup 4)
8625         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8626                 (match_dup 0)))
8627    (set (reg:CC_NOOV CC_REGNUM)
8628         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8629                          (const_int 0)))]
8630   "")
8631
8632 (define_split
8633   [(set (reg:CC_NOOV CC_REGNUM)
8634         (compare:CC_NOOV (ior:SI
8635                           (match_operator:SI 1 "comparison_operator"
8636                            [(match_operand:SI 2 "s_register_operand" "")
8637                             (match_operand:SI 3 "arm_add_operand" "")])
8638                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8639                                   (const_int 1)))
8640                          (const_int 0)))
8641    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8642   "TARGET_ARM"
8643   [(set (match_dup 4)
8644         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8645                 (match_dup 0)))
8646    (set (reg:CC_NOOV CC_REGNUM)
8647         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8648                          (const_int 0)))]
8649   "")
8650
8651 (define_insn "*negscc"
8652   [(set (match_operand:SI 0 "s_register_operand" "=r")
8653         (neg:SI (match_operator 3 "arm_comparison_operator"
8654                  [(match_operand:SI 1 "s_register_operand" "r")
8655                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8656    (clobber (reg:CC CC_REGNUM))]
8657   "TARGET_ARM"
8658   "*
8659   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8660     return \"mov\\t%0, %1, asr #31\";
8661
8662   if (GET_CODE (operands[3]) == NE)
8663     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8664
8665   if (GET_CODE (operands[3]) == GT)
8666     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8667
8668   output_asm_insn (\"cmp\\t%1, %2\", operands);
8669   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8670   return \"mvn%d3\\t%0, #0\";
8671   "
8672   [(set_attr "conds" "clob")
8673    (set_attr "length" "12")]
8674 )
8675
8676 (define_insn "movcond"
8677   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8678         (if_then_else:SI
8679          (match_operator 5 "arm_comparison_operator"
8680           [(match_operand:SI 3 "s_register_operand" "r,r,r")
8681            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8682          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8683          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8684    (clobber (reg:CC CC_REGNUM))]
8685   "TARGET_ARM"
8686   "*
8687   if (GET_CODE (operands[5]) == LT
8688       && (operands[4] == const0_rtx))
8689     {
8690       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8691         {
8692           if (operands[2] == const0_rtx)
8693             return \"and\\t%0, %1, %3, asr #31\";
8694           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8695         }
8696       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8697         {
8698           if (operands[1] == const0_rtx)
8699             return \"bic\\t%0, %2, %3, asr #31\";
8700           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8701         }
8702       /* The only case that falls through to here is when both ops 1 & 2
8703          are constants.  */
8704     }
8705
8706   if (GET_CODE (operands[5]) == GE
8707       && (operands[4] == const0_rtx))
8708     {
8709       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8710         {
8711           if (operands[2] == const0_rtx)
8712             return \"bic\\t%0, %1, %3, asr #31\";
8713           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8714         }
8715       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8716         {
8717           if (operands[1] == const0_rtx)
8718             return \"and\\t%0, %2, %3, asr #31\";
8719           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8720         }
8721       /* The only case that falls through to here is when both ops 1 & 2
8722          are constants.  */
8723     }
8724   if (GET_CODE (operands[4]) == CONST_INT
8725       && !const_ok_for_arm (INTVAL (operands[4])))
8726     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8727   else
8728     output_asm_insn (\"cmp\\t%3, %4\", operands);
8729   if (which_alternative != 0)
8730     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8731   if (which_alternative != 1)
8732     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8733   return \"\";
8734   "
8735   [(set_attr "conds" "clob")
8736    (set_attr "length" "8,8,12")]
8737 )
8738
8739 (define_insn "*ifcompare_plus_move"
8740   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8741         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8742                           [(match_operand:SI 4 "s_register_operand" "r,r")
8743                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8744                          (plus:SI
8745                           (match_operand:SI 2 "s_register_operand" "r,r")
8746                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8747                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8748    (clobber (reg:CC CC_REGNUM))]
8749   "TARGET_ARM"
8750   "#"
8751   [(set_attr "conds" "clob")
8752    (set_attr "length" "8,12")]
8753 )
8754
8755 (define_insn "*if_plus_move"
8756   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8757         (if_then_else:SI
8758          (match_operator 4 "arm_comparison_operator"
8759           [(match_operand 5 "cc_register" "") (const_int 0)])
8760          (plus:SI
8761           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8762           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8763          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8764   "TARGET_ARM"
8765   "@
8766    add%d4\\t%0, %2, %3
8767    sub%d4\\t%0, %2, #%n3
8768    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8769    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8770   [(set_attr "conds" "use")
8771    (set_attr "length" "4,4,8,8")
8772    (set_attr "type" "*,*,*,*")]
8773 )
8774
8775 (define_insn "*ifcompare_move_plus"
8776   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8777         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8778                           [(match_operand:SI 4 "s_register_operand" "r,r")
8779                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8780                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8781                          (plus:SI
8782                           (match_operand:SI 2 "s_register_operand" "r,r")
8783                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8784    (clobber (reg:CC CC_REGNUM))]
8785   "TARGET_ARM"
8786   "#"
8787   [(set_attr "conds" "clob")
8788    (set_attr "length" "8,12")]
8789 )
8790
8791 (define_insn "*if_move_plus"
8792   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8793         (if_then_else:SI
8794          (match_operator 4 "arm_comparison_operator"
8795           [(match_operand 5 "cc_register" "") (const_int 0)])
8796          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8797          (plus:SI
8798           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8799           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8800   "TARGET_ARM"
8801   "@
8802    add%D4\\t%0, %2, %3
8803    sub%D4\\t%0, %2, #%n3
8804    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8805    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8806   [(set_attr "conds" "use")
8807    (set_attr "length" "4,4,8,8")
8808    (set_attr "type" "*,*,*,*")]
8809 )
8810
8811 (define_insn "*ifcompare_arith_arith"
8812   [(set (match_operand:SI 0 "s_register_operand" "=r")
8813         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8814                           [(match_operand:SI 5 "s_register_operand" "r")
8815                            (match_operand:SI 6 "arm_add_operand" "rIL")])
8816                          (match_operator:SI 8 "shiftable_operator"
8817                           [(match_operand:SI 1 "s_register_operand" "r")
8818                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8819                          (match_operator:SI 7 "shiftable_operator"
8820                           [(match_operand:SI 3 "s_register_operand" "r")
8821                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8822    (clobber (reg:CC CC_REGNUM))]
8823   "TARGET_ARM"
8824   "#"
8825   [(set_attr "conds" "clob")
8826    (set_attr "length" "12")]
8827 )
8828
8829 (define_insn "*if_arith_arith"
8830   [(set (match_operand:SI 0 "s_register_operand" "=r")
8831         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8832                           [(match_operand 8 "cc_register" "") (const_int 0)])
8833                          (match_operator:SI 6 "shiftable_operator"
8834                           [(match_operand:SI 1 "s_register_operand" "r")
8835                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8836                          (match_operator:SI 7 "shiftable_operator"
8837                           [(match_operand:SI 3 "s_register_operand" "r")
8838                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8839   "TARGET_ARM"
8840   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8841   [(set_attr "conds" "use")
8842    (set_attr "length" "8")]
8843 )
8844
8845 (define_insn "*ifcompare_arith_move"
8846   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8847         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8848                           [(match_operand:SI 2 "s_register_operand" "r,r")
8849                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8850                          (match_operator:SI 7 "shiftable_operator"
8851                           [(match_operand:SI 4 "s_register_operand" "r,r")
8852                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8853                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8854    (clobber (reg:CC CC_REGNUM))]
8855   "TARGET_ARM"
8856   "*
8857   /* If we have an operation where (op x 0) is the identity operation and
8858      the conditional operator is LT or GE and we are comparing against zero and
8859      everything is in registers then we can do this in two instructions.  */
8860   if (operands[3] == const0_rtx
8861       && GET_CODE (operands[7]) != AND
8862       && GET_CODE (operands[5]) == REG
8863       && GET_CODE (operands[1]) == REG 
8864       && REGNO (operands[1]) == REGNO (operands[4])
8865       && REGNO (operands[4]) != REGNO (operands[0]))
8866     {
8867       if (GET_CODE (operands[6]) == LT)
8868         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8869       else if (GET_CODE (operands[6]) == GE)
8870         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8871     }
8872   if (GET_CODE (operands[3]) == CONST_INT
8873       && !const_ok_for_arm (INTVAL (operands[3])))
8874     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8875   else
8876     output_asm_insn (\"cmp\\t%2, %3\", operands);
8877   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8878   if (which_alternative != 0)
8879     return \"mov%D6\\t%0, %1\";
8880   return \"\";
8881   "
8882   [(set_attr "conds" "clob")
8883    (set_attr "length" "8,12")]
8884 )
8885
8886 (define_insn "*if_arith_move"
8887   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8888         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8889                           [(match_operand 6 "cc_register" "") (const_int 0)])
8890                          (match_operator:SI 5 "shiftable_operator"
8891                           [(match_operand:SI 2 "s_register_operand" "r,r")
8892                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8893                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8894   "TARGET_ARM"
8895   "@
8896    %I5%d4\\t%0, %2, %3
8897    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8898   [(set_attr "conds" "use")
8899    (set_attr "length" "4,8")
8900    (set_attr "type" "*,*")]
8901 )
8902
8903 (define_insn "*ifcompare_move_arith"
8904   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8905         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8906                           [(match_operand:SI 4 "s_register_operand" "r,r")
8907                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8908                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8909                          (match_operator:SI 7 "shiftable_operator"
8910                           [(match_operand:SI 2 "s_register_operand" "r,r")
8911                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8912    (clobber (reg:CC CC_REGNUM))]
8913   "TARGET_ARM"
8914   "*
8915   /* If we have an operation where (op x 0) is the identity operation and
8916      the conditional operator is LT or GE and we are comparing against zero and
8917      everything is in registers then we can do this in two instructions */
8918   if (operands[5] == const0_rtx
8919       && GET_CODE (operands[7]) != AND
8920       && GET_CODE (operands[3]) == REG
8921       && GET_CODE (operands[1]) == REG 
8922       && REGNO (operands[1]) == REGNO (operands[2])
8923       && REGNO (operands[2]) != REGNO (operands[0]))
8924     {
8925       if (GET_CODE (operands[6]) == GE)
8926         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8927       else if (GET_CODE (operands[6]) == LT)
8928         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8929     }
8930
8931   if (GET_CODE (operands[5]) == CONST_INT
8932       && !const_ok_for_arm (INTVAL (operands[5])))
8933     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
8934   else
8935     output_asm_insn (\"cmp\\t%4, %5\", operands);
8936
8937   if (which_alternative != 0)
8938     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
8939   return \"%I7%D6\\t%0, %2, %3\";
8940   "
8941   [(set_attr "conds" "clob")
8942    (set_attr "length" "8,12")]
8943 )
8944
8945 (define_insn "*if_move_arith"
8946   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8947         (if_then_else:SI
8948          (match_operator 4 "arm_comparison_operator"
8949           [(match_operand 6 "cc_register" "") (const_int 0)])
8950          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8951          (match_operator:SI 5 "shiftable_operator"
8952           [(match_operand:SI 2 "s_register_operand" "r,r")
8953            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
8954   "TARGET_ARM"
8955   "@
8956    %I5%D4\\t%0, %2, %3
8957    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8958   [(set_attr "conds" "use")
8959    (set_attr "length" "4,8")
8960    (set_attr "type" "*,*")]
8961 )
8962
8963 (define_insn "*ifcompare_move_not"
8964   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8965         (if_then_else:SI
8966          (match_operator 5 "arm_comparison_operator"
8967           [(match_operand:SI 3 "s_register_operand" "r,r")
8968            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8969          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8970          (not:SI
8971           (match_operand:SI 2 "s_register_operand" "r,r"))))
8972    (clobber (reg:CC CC_REGNUM))]
8973   "TARGET_ARM"
8974   "#"
8975   [(set_attr "conds" "clob")
8976    (set_attr "length" "8,12")]
8977 )
8978
8979 (define_insn "*if_move_not"
8980   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8981         (if_then_else:SI
8982          (match_operator 4 "arm_comparison_operator"
8983           [(match_operand 3 "cc_register" "") (const_int 0)])
8984          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8985          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8986   "TARGET_ARM"
8987   "@
8988    mvn%D4\\t%0, %2
8989    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
8990    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8991   [(set_attr "conds" "use")
8992    (set_attr "length" "4,8,8")]
8993 )
8994
8995 (define_insn "*ifcompare_not_move"
8996   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8997         (if_then_else:SI 
8998          (match_operator 5 "arm_comparison_operator"
8999           [(match_operand:SI 3 "s_register_operand" "r,r")
9000            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9001          (not:SI
9002           (match_operand:SI 2 "s_register_operand" "r,r"))
9003          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9004    (clobber (reg:CC CC_REGNUM))]
9005   "TARGET_ARM"
9006   "#"
9007   [(set_attr "conds" "clob")
9008    (set_attr "length" "8,12")]
9009 )
9010
9011 (define_insn "*if_not_move"
9012   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9013         (if_then_else:SI
9014          (match_operator 4 "arm_comparison_operator"
9015           [(match_operand 3 "cc_register" "") (const_int 0)])
9016          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9017          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9018   "TARGET_ARM"
9019   "@
9020    mvn%d4\\t%0, %2
9021    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9022    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
9023   [(set_attr "conds" "use")
9024    (set_attr "length" "4,8,8")]
9025 )
9026
9027 (define_insn "*ifcompare_shift_move"
9028   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9029         (if_then_else:SI
9030          (match_operator 6 "arm_comparison_operator"
9031           [(match_operand:SI 4 "s_register_operand" "r,r")
9032            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9033          (match_operator:SI 7 "shift_operator"
9034           [(match_operand:SI 2 "s_register_operand" "r,r")
9035            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9036          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9037    (clobber (reg:CC CC_REGNUM))]
9038   "TARGET_ARM"
9039   "#"
9040   [(set_attr "conds" "clob")
9041    (set_attr "length" "8,12")]
9042 )
9043
9044 (define_insn "*if_shift_move"
9045   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9046         (if_then_else:SI
9047          (match_operator 5 "arm_comparison_operator"
9048           [(match_operand 6 "cc_register" "") (const_int 0)])
9049          (match_operator:SI 4 "shift_operator"
9050           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9051            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9052          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9053   "TARGET_ARM"
9054   "@
9055    mov%d5\\t%0, %2%S4
9056    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9057    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
9058   [(set_attr "conds" "use")
9059    (set_attr "shift" "2")
9060    (set_attr "length" "4,8,8")
9061    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9062                       (const_string "alu_shift")
9063                       (const_string "alu_shift_reg")))]
9064 )
9065
9066 (define_insn "*ifcompare_move_shift"
9067   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9068         (if_then_else:SI
9069          (match_operator 6 "arm_comparison_operator"
9070           [(match_operand:SI 4 "s_register_operand" "r,r")
9071            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9072          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9073          (match_operator:SI 7 "shift_operator"
9074           [(match_operand:SI 2 "s_register_operand" "r,r")
9075            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
9076    (clobber (reg:CC CC_REGNUM))]
9077   "TARGET_ARM"
9078   "#"
9079   [(set_attr "conds" "clob")
9080    (set_attr "length" "8,12")]
9081 )
9082
9083 (define_insn "*if_move_shift"
9084   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9085         (if_then_else:SI
9086          (match_operator 5 "arm_comparison_operator"
9087           [(match_operand 6 "cc_register" "") (const_int 0)])
9088          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9089          (match_operator:SI 4 "shift_operator"
9090           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9091            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
9092   "TARGET_ARM"
9093   "@
9094    mov%D5\\t%0, %2%S4
9095    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9096    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
9097   [(set_attr "conds" "use")
9098    (set_attr "shift" "2")
9099    (set_attr "length" "4,8,8")
9100    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9101                       (const_string "alu_shift")
9102                       (const_string "alu_shift_reg")))]
9103 )
9104
9105 (define_insn "*ifcompare_shift_shift"
9106   [(set (match_operand:SI 0 "s_register_operand" "=r")
9107         (if_then_else:SI
9108          (match_operator 7 "arm_comparison_operator"
9109           [(match_operand:SI 5 "s_register_operand" "r")
9110            (match_operand:SI 6 "arm_add_operand" "rIL")])
9111          (match_operator:SI 8 "shift_operator"
9112           [(match_operand:SI 1 "s_register_operand" "r")
9113            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9114          (match_operator:SI 9 "shift_operator"
9115           [(match_operand:SI 3 "s_register_operand" "r")
9116            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
9117    (clobber (reg:CC CC_REGNUM))]
9118   "TARGET_ARM"
9119   "#"
9120   [(set_attr "conds" "clob")
9121    (set_attr "length" "12")]
9122 )
9123
9124 (define_insn "*if_shift_shift"
9125   [(set (match_operand:SI 0 "s_register_operand" "=r")
9126         (if_then_else:SI
9127          (match_operator 5 "arm_comparison_operator"
9128           [(match_operand 8 "cc_register" "") (const_int 0)])
9129          (match_operator:SI 6 "shift_operator"
9130           [(match_operand:SI 1 "s_register_operand" "r")
9131            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9132          (match_operator:SI 7 "shift_operator"
9133           [(match_operand:SI 3 "s_register_operand" "r")
9134            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
9135   "TARGET_ARM"
9136   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
9137   [(set_attr "conds" "use")
9138    (set_attr "shift" "1")
9139    (set_attr "length" "8")
9140    (set (attr "type") (if_then_else
9141                         (and (match_operand 2 "const_int_operand" "")
9142                              (match_operand 4 "const_int_operand" ""))
9143                       (const_string "alu_shift")
9144                       (const_string "alu_shift_reg")))]
9145 )
9146
9147 (define_insn "*ifcompare_not_arith"
9148   [(set (match_operand:SI 0 "s_register_operand" "=r")
9149         (if_then_else:SI
9150          (match_operator 6 "arm_comparison_operator"
9151           [(match_operand:SI 4 "s_register_operand" "r")
9152            (match_operand:SI 5 "arm_add_operand" "rIL")])
9153          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9154          (match_operator:SI 7 "shiftable_operator"
9155           [(match_operand:SI 2 "s_register_operand" "r")
9156            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
9157    (clobber (reg:CC CC_REGNUM))]
9158   "TARGET_ARM"
9159   "#"
9160   [(set_attr "conds" "clob")
9161    (set_attr "length" "12")]
9162 )
9163
9164 (define_insn "*if_not_arith"
9165   [(set (match_operand:SI 0 "s_register_operand" "=r")
9166         (if_then_else:SI
9167          (match_operator 5 "arm_comparison_operator"
9168           [(match_operand 4 "cc_register" "") (const_int 0)])
9169          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9170          (match_operator:SI 6 "shiftable_operator"
9171           [(match_operand:SI 2 "s_register_operand" "r")
9172            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
9173   "TARGET_ARM"
9174   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
9175   [(set_attr "conds" "use")
9176    (set_attr "length" "8")]
9177 )
9178
9179 (define_insn "*ifcompare_arith_not"
9180   [(set (match_operand:SI 0 "s_register_operand" "=r")
9181         (if_then_else:SI
9182          (match_operator 6 "arm_comparison_operator"
9183           [(match_operand:SI 4 "s_register_operand" "r")
9184            (match_operand:SI 5 "arm_add_operand" "rIL")])
9185          (match_operator:SI 7 "shiftable_operator"
9186           [(match_operand:SI 2 "s_register_operand" "r")
9187            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9188          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9189    (clobber (reg:CC CC_REGNUM))]
9190   "TARGET_ARM"
9191   "#"
9192   [(set_attr "conds" "clob")
9193    (set_attr "length" "12")]
9194 )
9195
9196 (define_insn "*if_arith_not"
9197   [(set (match_operand:SI 0 "s_register_operand" "=r")
9198         (if_then_else:SI
9199          (match_operator 5 "arm_comparison_operator"
9200           [(match_operand 4 "cc_register" "") (const_int 0)])
9201          (match_operator:SI 6 "shiftable_operator"
9202           [(match_operand:SI 2 "s_register_operand" "r")
9203            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9204          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9205   "TARGET_ARM"
9206   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9207   [(set_attr "conds" "use")
9208    (set_attr "length" "8")]
9209 )
9210
9211 (define_insn "*ifcompare_neg_move"
9212   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9213         (if_then_else:SI
9214          (match_operator 5 "arm_comparison_operator"
9215           [(match_operand:SI 3 "s_register_operand" "r,r")
9216            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9217          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9218          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9219    (clobber (reg:CC CC_REGNUM))]
9220   "TARGET_ARM"
9221   "#"
9222   [(set_attr "conds" "clob")
9223    (set_attr "length" "8,12")]
9224 )
9225
9226 (define_insn "*if_neg_move"
9227   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9228         (if_then_else:SI
9229          (match_operator 4 "arm_comparison_operator"
9230           [(match_operand 3 "cc_register" "") (const_int 0)])
9231          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9232          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9233   "TARGET_ARM"
9234   "@
9235    rsb%d4\\t%0, %2, #0
9236    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9237    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9238   [(set_attr "conds" "use")
9239    (set_attr "length" "4,8,8")]
9240 )
9241
9242 (define_insn "*ifcompare_move_neg"
9243   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9244         (if_then_else:SI
9245          (match_operator 5 "arm_comparison_operator"
9246           [(match_operand:SI 3 "s_register_operand" "r,r")
9247            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9248          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9249          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9250    (clobber (reg:CC CC_REGNUM))]
9251   "TARGET_ARM"
9252   "#"
9253   [(set_attr "conds" "clob")
9254    (set_attr "length" "8,12")]
9255 )
9256
9257 (define_insn "*if_move_neg"
9258   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9259         (if_then_else:SI
9260          (match_operator 4 "arm_comparison_operator"
9261           [(match_operand 3 "cc_register" "") (const_int 0)])
9262          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9263          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9264   "TARGET_ARM"
9265   "@
9266    rsb%D4\\t%0, %2, #0
9267    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9268    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9269   [(set_attr "conds" "use")
9270    (set_attr "length" "4,8,8")]
9271 )
9272
9273 (define_insn "*arith_adjacentmem"
9274   [(set (match_operand:SI 0 "s_register_operand" "=r")
9275         (match_operator:SI 1 "shiftable_operator"
9276          [(match_operand:SI 2 "memory_operand" "m")
9277           (match_operand:SI 3 "memory_operand" "m")]))
9278    (clobber (match_scratch:SI 4 "=r"))]
9279   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9280   "*
9281   {
9282     rtx ldm[3];
9283     rtx arith[4];
9284     rtx base_reg;
9285     HOST_WIDE_INT val1 = 0, val2 = 0;
9286
9287     if (REGNO (operands[0]) > REGNO (operands[4]))
9288       {
9289         ldm[1] = operands[4];
9290         ldm[2] = operands[0];
9291       }
9292     else
9293       {
9294         ldm[1] = operands[0];
9295         ldm[2] = operands[4];
9296       }
9297
9298     base_reg = XEXP (operands[2], 0);
9299
9300     if (!REG_P (base_reg))
9301       {
9302         val1 = INTVAL (XEXP (base_reg, 1));
9303         base_reg = XEXP (base_reg, 0);
9304       }
9305
9306     if (!REG_P (XEXP (operands[3], 0)))
9307       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9308
9309     arith[0] = operands[0];
9310     arith[3] = operands[1];
9311
9312     if (val1 < val2)
9313       {
9314         arith[1] = ldm[1];
9315         arith[2] = ldm[2];
9316       }
9317     else
9318       {
9319         arith[1] = ldm[2];
9320         arith[2] = ldm[1];
9321       }
9322
9323     ldm[0] = base_reg;
9324     if (val1 !=0 && val2 != 0)
9325       {
9326         if (val1 == 4 || val2 == 4)
9327           /* Other val must be 8, since we know they are adjacent and neither
9328              is zero.  */
9329           output_asm_insn (\"ldm%?ib\\t%0, {%1, %2}\", ldm);
9330         else
9331           {
9332             rtx ops[3];
9333
9334             ldm[0] = ops[0] = operands[4];
9335             ops[1] = base_reg;
9336             ops[2] = GEN_INT (val1);
9337             output_add_immediate (ops);
9338             if (val1 < val2)
9339               output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9340             else
9341               output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9342           }
9343       }
9344     else if (val1 != 0)
9345       {
9346         if (val1 < val2)
9347           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9348         else
9349           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9350       }
9351     else
9352       {
9353         if (val1 < val2)
9354           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9355         else
9356           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9357       }
9358     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9359     return \"\";
9360   }"
9361   [(set_attr "length" "12")
9362    (set_attr "predicable" "yes")
9363    (set_attr "type" "load1")]
9364 )
9365
9366 ; This pattern is never tried by combine, so do it as a peephole
9367
9368 (define_peephole2
9369   [(set (match_operand:SI 0 "arm_general_register_operand" "")
9370         (match_operand:SI 1 "arm_general_register_operand" ""))
9371    (set (reg:CC CC_REGNUM)
9372         (compare:CC (match_dup 1) (const_int 0)))]
9373   "TARGET_ARM"
9374   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9375               (set (match_dup 0) (match_dup 1))])]
9376   ""
9377 )
9378
9379 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9380 ; reversed, check that the memory references aren't volatile.
9381
9382 (define_peephole
9383   [(set (match_operand:SI 0 "s_register_operand" "=r")
9384         (match_operand:SI 4 "memory_operand" "m"))
9385    (set (match_operand:SI 1 "s_register_operand" "=r")
9386         (match_operand:SI 5 "memory_operand" "m"))
9387    (set (match_operand:SI 2 "s_register_operand" "=r")
9388         (match_operand:SI 6 "memory_operand" "m"))
9389    (set (match_operand:SI 3 "s_register_operand" "=r")
9390         (match_operand:SI 7 "memory_operand" "m"))]
9391   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9392   "*
9393   return emit_ldm_seq (operands, 4);
9394   "
9395 )
9396
9397 (define_peephole
9398   [(set (match_operand:SI 0 "s_register_operand" "=r")
9399         (match_operand:SI 3 "memory_operand" "m"))
9400    (set (match_operand:SI 1 "s_register_operand" "=r")
9401         (match_operand:SI 4 "memory_operand" "m"))
9402    (set (match_operand:SI 2 "s_register_operand" "=r")
9403         (match_operand:SI 5 "memory_operand" "m"))]
9404   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9405   "*
9406   return emit_ldm_seq (operands, 3);
9407   "
9408 )
9409
9410 (define_peephole
9411   [(set (match_operand:SI 0 "s_register_operand" "=r")
9412         (match_operand:SI 2 "memory_operand" "m"))
9413    (set (match_operand:SI 1 "s_register_operand" "=r")
9414         (match_operand:SI 3 "memory_operand" "m"))]
9415   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9416   "*
9417   return emit_ldm_seq (operands, 2);
9418   "
9419 )
9420
9421 (define_peephole
9422   [(set (match_operand:SI 4 "memory_operand" "=m")
9423         (match_operand:SI 0 "s_register_operand" "r"))
9424    (set (match_operand:SI 5 "memory_operand" "=m")
9425         (match_operand:SI 1 "s_register_operand" "r"))
9426    (set (match_operand:SI 6 "memory_operand" "=m")
9427         (match_operand:SI 2 "s_register_operand" "r"))
9428    (set (match_operand:SI 7 "memory_operand" "=m")
9429         (match_operand:SI 3 "s_register_operand" "r"))]
9430   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9431   "*
9432   return emit_stm_seq (operands, 4);
9433   "
9434 )
9435
9436 (define_peephole
9437   [(set (match_operand:SI 3 "memory_operand" "=m")
9438         (match_operand:SI 0 "s_register_operand" "r"))
9439    (set (match_operand:SI 4 "memory_operand" "=m")
9440         (match_operand:SI 1 "s_register_operand" "r"))
9441    (set (match_operand:SI 5 "memory_operand" "=m")
9442         (match_operand:SI 2 "s_register_operand" "r"))]
9443   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9444   "*
9445   return emit_stm_seq (operands, 3);
9446   "
9447 )
9448
9449 (define_peephole
9450   [(set (match_operand:SI 2 "memory_operand" "=m")
9451         (match_operand:SI 0 "s_register_operand" "r"))
9452    (set (match_operand:SI 3 "memory_operand" "=m")
9453         (match_operand:SI 1 "s_register_operand" "r"))]
9454   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9455   "*
9456   return emit_stm_seq (operands, 2);
9457   "
9458 )
9459
9460 (define_split
9461   [(set (match_operand:SI 0 "s_register_operand" "")
9462         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9463                        (const_int 0))
9464                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9465                          [(match_operand:SI 3 "s_register_operand" "")
9466                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
9467    (clobber (match_operand:SI 5 "s_register_operand" ""))]
9468   "TARGET_ARM"
9469   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9470    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9471                               (match_dup 5)))]
9472   ""
9473 )
9474
9475 ;; This split can be used because CC_Z mode implies that the following
9476 ;; branch will be an equality, or an unsigned inequality, so the sign
9477 ;; extension is not needed.
9478
9479 (define_split
9480   [(set (reg:CC_Z CC_REGNUM)
9481         (compare:CC_Z
9482          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9483                     (const_int 24))
9484          (match_operand 1 "const_int_operand" "")))
9485    (clobber (match_scratch:SI 2 ""))]
9486   "TARGET_ARM
9487    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9488        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9489   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9490    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9491   "
9492   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9493   "
9494 )
9495
9496 (define_expand "prologue"
9497   [(clobber (const_int 0))]
9498   "TARGET_EITHER"
9499   "if (TARGET_ARM)
9500      arm_expand_prologue ();
9501    else
9502      thumb_expand_prologue ();
9503   DONE;
9504   "
9505 )
9506
9507 (define_expand "epilogue"
9508   [(clobber (const_int 0))]
9509   "TARGET_EITHER"
9510   "
9511   if (current_function_calls_eh_return)
9512     emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
9513   if (TARGET_THUMB)
9514     thumb_expand_epilogue ();
9515   else if (USE_RETURN_INSN (FALSE))
9516     {
9517       emit_jump_insn (gen_return ());
9518       DONE;
9519     }
9520   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9521         gen_rtvec (1,
9522                 gen_rtx_RETURN (VOIDmode)),
9523         VUNSPEC_EPILOGUE));
9524   DONE;
9525   "
9526 )
9527
9528 ;; Note - although unspec_volatile's USE all hard registers,
9529 ;; USEs are ignored after relaod has completed.  Thus we need
9530 ;; to add an unspec of the link register to ensure that flow
9531 ;; does not think that it is unused by the sibcall branch that
9532 ;; will replace the standard function epilogue.
9533 (define_insn "sibcall_epilogue"
9534   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9535               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9536   "TARGET_ARM"
9537   "*
9538   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9539     return output_return_instruction (const_true_rtx, FALSE, FALSE);
9540   return arm_output_epilogue (next_nonnote_insn (insn));
9541   "
9542 ;; Length is absolute worst case
9543   [(set_attr "length" "44")
9544    (set_attr "type" "block")
9545    ;; We don't clobber the conditions, but the potential length of this
9546    ;; operation is sufficient to make conditionalizing the sequence 
9547    ;; unlikely to be profitable.
9548    (set_attr "conds" "clob")]
9549 )
9550
9551 (define_insn "*epilogue_insns"
9552   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9553   "TARGET_EITHER"
9554   "*
9555   if (TARGET_ARM)
9556     return arm_output_epilogue (NULL);
9557   else /* TARGET_THUMB */
9558     return thumb_unexpanded_epilogue ();
9559   "
9560   ; Length is absolute worst case
9561   [(set_attr "length" "44")
9562    (set_attr "type" "block")
9563    ;; We don't clobber the conditions, but the potential length of this
9564    ;; operation is sufficient to make conditionalizing the sequence 
9565    ;; unlikely to be profitable.
9566    (set_attr "conds" "clob")]
9567 )
9568
9569 (define_expand "eh_epilogue"
9570   [(use (match_operand:SI 0 "register_operand" ""))
9571    (use (match_operand:SI 1 "register_operand" ""))
9572    (use (match_operand:SI 2 "register_operand" ""))]
9573   "TARGET_EITHER"
9574   "
9575   {
9576     cfun->machine->eh_epilogue_sp_ofs = operands[1];
9577     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9578       {
9579         rtx ra = gen_rtx_REG (Pmode, 2);
9580
9581         emit_move_insn (ra, operands[2]);
9582         operands[2] = ra;
9583       }
9584     /* This is a hack -- we may have crystalized the function type too
9585        early.  */
9586     cfun->machine->func_type = 0;
9587   }"
9588 )
9589
9590 ;; This split is only used during output to reduce the number of patterns
9591 ;; that need assembler instructions adding to them.  We allowed the setting
9592 ;; of the conditions to be implicit during rtl generation so that
9593 ;; the conditional compare patterns would work.  However this conflicts to
9594 ;; some extent with the conditional data operations, so we have to split them
9595 ;; up again here.
9596
9597 (define_split
9598   [(set (match_operand:SI 0 "s_register_operand" "")
9599         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9600                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9601                          (match_dup 0)
9602                          (match_operand 4 "" "")))
9603    (clobber (reg:CC CC_REGNUM))]
9604   "TARGET_ARM && reload_completed"
9605   [(set (match_dup 5) (match_dup 6))
9606    (cond_exec (match_dup 7)
9607               (set (match_dup 0) (match_dup 4)))]
9608   "
9609   {
9610     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9611                                              operands[2], operands[3]);
9612     enum rtx_code rc = GET_CODE (operands[1]);
9613
9614     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9615     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9616     if (mode == CCFPmode || mode == CCFPEmode)
9617       rc = reverse_condition_maybe_unordered (rc);
9618     else
9619       rc = reverse_condition (rc);
9620
9621     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9622   }"
9623 )
9624
9625 (define_split
9626   [(set (match_operand:SI 0 "s_register_operand" "")
9627         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9628                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9629                          (match_operand 4 "" "")
9630                          (match_dup 0)))
9631    (clobber (reg:CC CC_REGNUM))]
9632   "TARGET_ARM && reload_completed"
9633   [(set (match_dup 5) (match_dup 6))
9634    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9635               (set (match_dup 0) (match_dup 4)))]
9636   "
9637   {
9638     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9639                                              operands[2], operands[3]);
9640
9641     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9642     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9643   }"
9644 )
9645
9646 (define_split
9647   [(set (match_operand:SI 0 "s_register_operand" "")
9648         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9649                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9650                          (match_operand 4 "" "")
9651                          (match_operand 5 "" "")))
9652    (clobber (reg:CC CC_REGNUM))]
9653   "TARGET_ARM && reload_completed"
9654   [(set (match_dup 6) (match_dup 7))
9655    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9656               (set (match_dup 0) (match_dup 4)))
9657    (cond_exec (match_dup 8)
9658               (set (match_dup 0) (match_dup 5)))]
9659   "
9660   {
9661     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9662                                              operands[2], operands[3]);
9663     enum rtx_code rc = GET_CODE (operands[1]);
9664
9665     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9666     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9667     if (mode == CCFPmode || mode == CCFPEmode)
9668       rc = reverse_condition_maybe_unordered (rc);
9669     else
9670       rc = reverse_condition (rc);
9671
9672     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9673   }"
9674 )
9675
9676 (define_split
9677   [(set (match_operand:SI 0 "s_register_operand" "")
9678         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9679                           [(match_operand:SI 2 "s_register_operand" "")
9680                            (match_operand:SI 3 "arm_add_operand" "")])
9681                          (match_operand:SI 4 "arm_rhs_operand" "")
9682                          (not:SI
9683                           (match_operand:SI 5 "s_register_operand" ""))))
9684    (clobber (reg:CC CC_REGNUM))]
9685   "TARGET_ARM && reload_completed"
9686   [(set (match_dup 6) (match_dup 7))
9687    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9688               (set (match_dup 0) (match_dup 4)))
9689    (cond_exec (match_dup 8)
9690               (set (match_dup 0) (not:SI (match_dup 5))))]
9691   "
9692   {
9693     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9694                                              operands[2], operands[3]);
9695     enum rtx_code rc = GET_CODE (operands[1]);
9696
9697     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9698     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9699     if (mode == CCFPmode || mode == CCFPEmode)
9700       rc = reverse_condition_maybe_unordered (rc);
9701     else
9702       rc = reverse_condition (rc);
9703
9704     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9705   }"
9706 )
9707
9708 (define_insn "*cond_move_not"
9709   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9710         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9711                           [(match_operand 3 "cc_register" "") (const_int 0)])
9712                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9713                          (not:SI
9714                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
9715   "TARGET_ARM"
9716   "@
9717    mvn%D4\\t%0, %2
9718    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
9719   [(set_attr "conds" "use")
9720    (set_attr "length" "4,8")]
9721 )
9722
9723 ;; The next two patterns occur when an AND operation is followed by a
9724 ;; scc insn sequence 
9725
9726 (define_insn "*sign_extract_onebit"
9727   [(set (match_operand:SI 0 "s_register_operand" "=r")
9728         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9729                          (const_int 1)
9730                          (match_operand:SI 2 "const_int_operand" "n")))
9731     (clobber (reg:CC CC_REGNUM))]
9732   "TARGET_ARM"
9733   "*
9734     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9735     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
9736     return \"mvnne\\t%0, #0\";
9737   "
9738   [(set_attr "conds" "clob")
9739    (set_attr "length" "8")]
9740 )
9741
9742 (define_insn "*not_signextract_onebit"
9743   [(set (match_operand:SI 0 "s_register_operand" "=r")
9744         (not:SI
9745          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9746                           (const_int 1)
9747                           (match_operand:SI 2 "const_int_operand" "n"))))
9748    (clobber (reg:CC CC_REGNUM))]
9749   "TARGET_ARM"
9750   "*
9751     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9752     output_asm_insn (\"tst\\t%1, %2\", operands);
9753     output_asm_insn (\"mvneq\\t%0, #0\", operands);
9754     return \"movne\\t%0, #0\";
9755   "
9756   [(set_attr "conds" "clob")
9757    (set_attr "length" "12")]
9758 )
9759
9760 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
9761 ;; expressions.  For simplicity, the first register is also in the unspec
9762 ;; part.
9763 (define_insn "*push_multi"
9764   [(match_parallel 2 "multi_register_push"
9765     [(set (match_operand:BLK 0 "memory_operand" "=m")
9766           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
9767                       UNSPEC_PUSH_MULT))])]
9768   "TARGET_ARM"
9769   "*
9770   {
9771     int num_saves = XVECLEN (operands[2], 0);
9772      
9773     /* For the StrongARM at least it is faster to
9774        use STR to store only a single register.  */
9775     if (num_saves == 1)
9776       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9777     else
9778       {
9779         int i;
9780         char pattern[100];
9781
9782         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9783
9784         for (i = 1; i < num_saves; i++)
9785           {
9786             strcat (pattern, \", %|\");
9787             strcat (pattern,
9788                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9789           }
9790
9791         strcat (pattern, \"}\");
9792         output_asm_insn (pattern, operands);
9793       }
9794
9795     return \"\";
9796   }"
9797   [(set_attr "type" "store4")]
9798 )
9799
9800 (define_insn "stack_tie"
9801   [(set (mem:BLK (scratch))
9802         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
9803                      (match_operand:SI 1 "s_register_operand" "r")]
9804                     UNSPEC_PRLG_STK))]
9805   ""
9806   ""
9807   [(set_attr "length" "0")]
9808 )
9809
9810 ;; Similarly for the floating point registers
9811 (define_insn "*push_fp_multi"
9812   [(match_parallel 2 "multi_register_push"
9813     [(set (match_operand:BLK 0 "memory_operand" "=m")
9814           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9815                       UNSPEC_PUSH_MULT))])]
9816   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
9817   "*
9818   {
9819     char pattern[100];
9820
9821     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
9822     output_asm_insn (pattern, operands);
9823     return \"\";
9824   }"
9825   [(set_attr "type" "f_store")]
9826 )
9827
9828 ;; Special patterns for dealing with the constant pool
9829
9830 (define_insn "align_4"
9831   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
9832   "TARGET_EITHER"
9833   "*
9834   assemble_align (32);
9835   return \"\";
9836   "
9837 )
9838
9839 (define_insn "align_8"
9840   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
9841   "TARGET_EITHER"
9842   "*
9843   assemble_align (64);
9844   return \"\";
9845   "
9846 )
9847
9848 (define_insn "consttable_end"
9849   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
9850   "TARGET_EITHER"
9851   "*
9852   making_const_table = FALSE;
9853   return \"\";
9854   "
9855 )
9856
9857 (define_insn "consttable_1"
9858   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
9859   "TARGET_THUMB"
9860   "*
9861   making_const_table = TRUE;
9862   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
9863   assemble_zeros (3);
9864   return \"\";
9865   "
9866   [(set_attr "length" "4")]
9867 )
9868
9869 (define_insn "consttable_2"
9870   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
9871   "TARGET_THUMB"
9872   "*
9873   making_const_table = TRUE;
9874   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
9875   assemble_zeros (2);
9876   return \"\";
9877   "
9878   [(set_attr "length" "4")]
9879 )
9880
9881 (define_insn "consttable_4"
9882   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
9883   "TARGET_EITHER"
9884   "*
9885   {
9886     making_const_table = TRUE;
9887     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9888       {
9889       case MODE_FLOAT:
9890       {
9891         REAL_VALUE_TYPE r;
9892         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9893         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9894         break;
9895       }
9896       default:
9897         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
9898         break;
9899       }
9900     return \"\";
9901   }"
9902   [(set_attr "length" "4")]
9903 )
9904
9905 (define_insn "consttable_8"
9906   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9907   "TARGET_EITHER"
9908   "*
9909   {
9910     making_const_table = TRUE;
9911     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9912       {
9913        case MODE_FLOAT:
9914         {
9915           REAL_VALUE_TYPE r;
9916           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9917           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9918           break;
9919         }
9920       default:
9921         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
9922         break;
9923       }
9924     return \"\";
9925   }"
9926   [(set_attr "length" "8")]
9927 )
9928
9929 ;; Miscellaneous Thumb patterns
9930
9931 (define_expand "tablejump"
9932   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
9933               (use (label_ref (match_operand 1 "" "")))])]
9934   "TARGET_THUMB"
9935   "
9936   if (flag_pic)
9937     {
9938       /* Hopefully, CSE will eliminate this copy.  */
9939       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
9940       rtx reg2 = gen_reg_rtx (SImode);
9941
9942       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
9943       operands[0] = reg2;
9944     }
9945   "
9946 )
9947
9948 ;; NB never uses BX.
9949 (define_insn "*thumb_tablejump"
9950   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9951    (use (label_ref (match_operand 1 "" "")))]
9952   "TARGET_THUMB"
9953   "mov\\t%|pc, %0"
9954   [(set_attr "length" "2")]
9955 )
9956
9957 ;; V5 Instructions,
9958
9959 (define_insn "clzsi2"
9960   [(set (match_operand:SI 0 "s_register_operand" "=r")
9961         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
9962   "TARGET_ARM && arm_arch5"
9963   "clz%?\\t%0, %1"
9964   [(set_attr "predicable" "yes")])
9965
9966 (define_expand "ffssi2"
9967   [(set (match_operand:SI 0 "s_register_operand" "")
9968         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
9969   "TARGET_ARM && arm_arch5"
9970   "
9971   {
9972     rtx t1, t2, t3;
9973
9974     t1 = gen_reg_rtx (SImode);
9975     t2 = gen_reg_rtx (SImode);
9976     t3 = gen_reg_rtx (SImode);
9977
9978     emit_insn (gen_negsi2 (t1, operands[1]));
9979     emit_insn (gen_andsi3 (t2, operands[1], t1));
9980     emit_insn (gen_clzsi2 (t3, t2));
9981     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
9982     DONE;
9983   }"
9984 )
9985
9986 (define_expand "ctzsi2"
9987   [(set (match_operand:SI 0 "s_register_operand" "")
9988         (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
9989   "TARGET_ARM && arm_arch5"
9990   "
9991   {
9992     rtx t1, t2, t3;
9993
9994     t1 = gen_reg_rtx (SImode);
9995     t2 = gen_reg_rtx (SImode);
9996     t3 = gen_reg_rtx (SImode);
9997
9998     emit_insn (gen_negsi2 (t1, operands[1]));
9999     emit_insn (gen_andsi3 (t2, operands[1], t1));
10000     emit_insn (gen_clzsi2 (t3, t2));
10001     emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10002     DONE;
10003   }"
10004 )
10005
10006 ;; V5E instructions.
10007
10008 (define_insn "prefetch"
10009   [(prefetch (match_operand:SI 0 "address_operand" "p")
10010              (match_operand:SI 1 "" "")
10011              (match_operand:SI 2 "" ""))]
10012   "TARGET_ARM && arm_arch5e"
10013   "pld\\t%a0")
10014
10015 ;; General predication pattern
10016
10017 (define_cond_exec
10018   [(match_operator 0 "arm_comparison_operator"
10019     [(match_operand 1 "cc_register" "")
10020      (const_int 0)])]
10021   "TARGET_ARM"
10022   ""
10023 )
10024
10025 (define_insn "prologue_use"
10026   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10027   ""
10028   "%@ %0 needed for prologue"
10029 )
10030
10031
10032 ;; Patterns for exception handling
10033
10034 (define_expand "eh_return"
10035   [(use (match_operand 0 "general_operand" ""))]
10036   "TARGET_EITHER"
10037   "
10038   {
10039     if (TARGET_ARM)
10040       emit_insn (gen_arm_eh_return (operands[0]));
10041     else
10042       emit_insn (gen_thumb_eh_return (operands[0]));
10043     DONE;
10044   }"
10045 )
10046                                    
10047 ;; We can't expand this before we know where the link register is stored.
10048 (define_insn_and_split "arm_eh_return"
10049   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10050                     VUNSPEC_EH_RETURN)
10051    (clobber (match_scratch:SI 1 "=&r"))]
10052   "TARGET_ARM"
10053   "#"
10054   "&& reload_completed"
10055   [(const_int 0)]
10056   "
10057   {
10058     arm_set_return_address (operands[0], operands[1]);
10059     DONE;
10060   }"
10061 )
10062
10063 (define_insn_and_split "thumb_eh_return"
10064   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10065                     VUNSPEC_EH_RETURN)
10066    (clobber (match_scratch:SI 1 "=&l"))]
10067   "TARGET_THUMB"
10068   "#"
10069   "&& reload_completed"
10070   [(const_int 0)]
10071   "
10072   {
10073     thumb_set_return_address (operands[0], operands[1]);
10074     DONE;
10075   }"
10076 )
10077
10078 ;; Load the FPA co-processor patterns
10079 (include "fpa.md")
10080 ;; Load the Maverick co-processor patterns
10081 (include "cirrus.md")
10082 ;; Load the Intel Wireless Multimedia Extension patterns
10083 (include "iwmmxt.md")
10084 ;; Load the VFP co-processor patterns
10085 (include "vfp.md")
10086