OSDN Git Service

e94ceb81461c2f0a17cfb8dab4fb3788d0331fd3
[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, 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, 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_is_strong")))
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_mem_r       a transfer of a floating point register to a real reg via mem
206 ; r_mem_f       the reverse of f_mem_r
207 ; f_2_r         fast transfer float to arm (no memory needed)
208 ; r_2_f         fast transfer arm to float
209 ; branch        a branch
210 ; call          a subroutine call
211 ; load_byte     load byte(s) from memory to arm registers
212 ; load1         load 1 word from memory to arm registers
213 ; load2         load 2 words from memory to arm registers
214 ; load3         load 3 words from memory to arm registers
215 ; load4         load 4 words from memory to arm registers
216 ; store         store 1 word to memory from arm registers
217 ; store2        store 2 words
218 ; store3        store 3 words
219 ; store4        store 4 (or more) words
220 ;  Additions for Cirrus Maverick co-processor:
221 ; mav_farith    Floating point arithmetic (4 cycle)
222 ; mav_dmult     Double multiplies (7 cycle)
223 ;
224 (define_attr "type"
225         "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,float_em,f_load,f_store,f_mem_r,r_mem_f,f_2_r,r_2_f,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult" 
226         (if_then_else 
227          (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
228          (const_string "mult")
229          (const_string "alu")))
230
231 ; Load scheduling, set from the arm_ld_sched variable
232 ; initialized by arm_override_options() 
233 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
234
235 ; condition codes: this one is used by final_prescan_insn to speed up
236 ; conditionalizing instructions.  It saves having to scan the rtl to see if
237 ; it uses or alters the condition codes.
238
239 ; USE means that the condition codes are used by the insn in the process of
240 ;   outputting code, this means (at present) that we can't use the insn in
241 ;   inlined branches
242 ;
243 ; SET means that the purpose of the insn is to set the condition codes in a
244 ;   well defined manner.
245 ;
246 ; CLOB means that the condition codes are altered in an undefined manner, if
247 ;   they are altered at all
248 ;
249 ; JUMP_CLOB is used when the condition cannot be represented by a single
250 ;   instruction (UNEQ and LTGT).  These cannot be predicated.
251 ;
252 ; NOCOND means that the condition codes are neither altered nor affect the
253 ;   output of this insn
254
255 (define_attr "conds" "use,set,clob,jump_clob,nocond"
256         (if_then_else (eq_attr "type" "call")
257          (const_string "clob")
258          (const_string "nocond")))
259
260 ; Predicable means that the insn can be conditionally executed based on
261 ; an automatically added predicate (additional patterns are generated by 
262 ; gen...).  We default to 'no' because no Thumb patterns match this rule
263 ; and not all ARM patterns do.
264 (define_attr "predicable" "no,yes" (const_string "no"))
265
266 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
267 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
268 ; suffer blockages enough to warrant modelling this (and it can adversely
269 ; affect the schedule).
270 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
271
272 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
273 ; to stall the processor.  Used with model_wbuf above.
274 (define_attr "write_conflict" "no,yes"
275   (if_then_else (eq_attr "type"
276                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
277                 (const_string "yes")
278                 (const_string "no")))
279
280 ; Classify the insns into those that take one cycle and those that take more
281 ; than one on the main cpu execution unit.
282 (define_attr "core_cycles" "single,multi"
283   (if_then_else (eq_attr "type"
284                  "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
285                 (const_string "single")
286                 (const_string "multi")))
287
288 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
289 ;; distant label.  Only applicable to Thumb code.
290 (define_attr "far_jump" "yes,no" (const_string "no"))
291
292
293 ;;---------------------------------------------------------------------------
294 ;; Mode macros
295
296 ; A list of modes that are exactly 64 bits in size.  We use this to expand
297 ; some splits that are the same for all modes when operating on ARM 
298 ; registers.
299 (define_mode_macro ANY64 [DI DF V8QI V4HI V2SI V2SF])
300
301 ;;---------------------------------------------------------------------------
302 ;; Predicates
303
304 (include "predicates.md")
305
306 ;;---------------------------------------------------------------------------
307 ;; Pipeline descriptions
308
309 ;; Processor type.  This is created automatically from arm-cores.def.
310 (include "arm-tune.md")
311
312 ;; True if the generic scheduling description should be used.
313
314 (define_attr "generic_sched" "yes,no"
315   (const (if_then_else 
316           (eq_attr "tune" "arm926ejs,arm1026ejs,arm1136js,arm1136jfs") 
317           (const_string "no")
318           (const_string "yes"))))
319
320 (include "arm-generic.md")
321 (include "arm926ejs.md")
322 (include "arm1026ejs.md")
323 (include "arm1136jfs.md")
324
325 \f
326 ;;---------------------------------------------------------------------------
327 ;; Insn patterns
328 ;;
329 ;; Addition insns.
330
331 ;; Note: For DImode insns, there is normally no reason why operands should
332 ;; not be in the same register, what we don't want is for something being
333 ;; written to partially overlap something that is an input.
334 ;; Cirrus 64bit additions should not be split because we have a native
335 ;; 64bit addition instructions.
336
337 (define_expand "adddi3"
338  [(parallel
339    [(set (match_operand:DI           0 "s_register_operand" "")
340           (plus:DI (match_operand:DI 1 "s_register_operand" "")
341                    (match_operand:DI 2 "s_register_operand" "")))
342     (clobber (reg:CC CC_REGNUM))])]
343   "TARGET_EITHER"
344   "
345   if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
346     {
347       if (!cirrus_fp_register (operands[0], DImode))
348         operands[0] = force_reg (DImode, operands[0]);
349       if (!cirrus_fp_register (operands[1], DImode))
350         operands[1] = force_reg (DImode, operands[1]);
351       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
352       DONE;
353     }
354
355   if (TARGET_THUMB)
356     {
357       if (GET_CODE (operands[1]) != REG)
358         operands[1] = force_reg (SImode, operands[1]);
359       if (GET_CODE (operands[2]) != REG)
360         operands[2] = force_reg (SImode, operands[2]);
361      }
362   "
363 )
364
365 (define_insn "*thumb_adddi3"
366   [(set (match_operand:DI          0 "register_operand" "=l")
367         (plus:DI (match_operand:DI 1 "register_operand" "%0")
368                  (match_operand:DI 2 "register_operand" "l")))
369    (clobber (reg:CC CC_REGNUM))
370   ]
371   "TARGET_THUMB"
372   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
373   [(set_attr "length" "4")]
374 )
375
376 (define_insn_and_split "*arm_adddi3"
377   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
378         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
379                  (match_operand:DI 2 "s_register_operand" "r,  0")))
380    (clobber (reg:CC CC_REGNUM))]
381   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
382   "#"
383   "TARGET_ARM && reload_completed"
384   [(parallel [(set (reg:CC_C CC_REGNUM)
385                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
386                                  (match_dup 1)))
387               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
388    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
389                                (plus:SI (match_dup 4) (match_dup 5))))]
390   "
391   {
392     operands[3] = gen_highpart (SImode, operands[0]);
393     operands[0] = gen_lowpart (SImode, operands[0]);
394     operands[4] = gen_highpart (SImode, operands[1]);
395     operands[1] = gen_lowpart (SImode, operands[1]);
396     operands[5] = gen_highpart (SImode, operands[2]);
397     operands[2] = gen_lowpart (SImode, operands[2]);
398   }"
399   [(set_attr "conds" "clob")
400    (set_attr "length" "8")]
401 )
402
403 (define_insn_and_split "*adddi_sesidi_di"
404   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
405         (plus:DI (sign_extend:DI
406                   (match_operand:SI 2 "s_register_operand" "r,r"))
407                  (match_operand:DI 1 "s_register_operand" "r,0")))
408    (clobber (reg:CC CC_REGNUM))]
409   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
410   "#"
411   "TARGET_ARM && reload_completed"
412   [(parallel [(set (reg:CC_C CC_REGNUM)
413                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
414                                  (match_dup 1)))
415               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
416    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
417                                (plus:SI (ashiftrt:SI (match_dup 2)
418                                                      (const_int 31))
419                                         (match_dup 4))))]
420   "
421   {
422     operands[3] = gen_highpart (SImode, operands[0]);
423     operands[0] = gen_lowpart (SImode, operands[0]);
424     operands[4] = gen_highpart (SImode, operands[1]);
425     operands[1] = gen_lowpart (SImode, operands[1]);
426     operands[2] = gen_lowpart (SImode, operands[2]);
427   }"
428   [(set_attr "conds" "clob")
429    (set_attr "length" "8")]
430 )
431
432 (define_insn_and_split "*adddi_zesidi_di"
433   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
434         (plus:DI (zero_extend:DI
435                   (match_operand:SI 2 "s_register_operand" "r,r"))
436                  (match_operand:DI 1 "s_register_operand" "r,0")))
437    (clobber (reg:CC CC_REGNUM))]
438   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
439   "#"
440   "TARGET_ARM && reload_completed"
441   [(parallel [(set (reg:CC_C CC_REGNUM)
442                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
443                                  (match_dup 1)))
444               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
445    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
446                                (plus:SI (match_dup 4) (const_int 0))))]
447   "
448   {
449     operands[3] = gen_highpart (SImode, operands[0]);
450     operands[0] = gen_lowpart (SImode, operands[0]);
451     operands[4] = gen_highpart (SImode, operands[1]);
452     operands[1] = gen_lowpart (SImode, operands[1]);
453     operands[2] = gen_lowpart (SImode, operands[2]);
454   }"
455   [(set_attr "conds" "clob")
456    (set_attr "length" "8")]
457 )
458
459 (define_expand "addsi3"
460   [(set (match_operand:SI          0 "s_register_operand" "")
461         (plus:SI (match_operand:SI 1 "s_register_operand" "")
462                  (match_operand:SI 2 "reg_or_int_operand" "")))]
463   "TARGET_EITHER"
464   "
465   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
466     {
467       arm_split_constant (PLUS, SImode, NULL_RTX,
468                           INTVAL (operands[2]), operands[0], operands[1],
469                           optimize && !no_new_pseudos);
470       DONE;
471     }
472   "
473 )
474
475 ; If there is a scratch available, this will be faster than synthesizing the
476 ; addition.
477 (define_peephole2
478   [(match_scratch:SI 3 "r")
479    (set (match_operand:SI          0 "arm_general_register_operand" "")
480         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
481                  (match_operand:SI 2 "const_int_operand"  "")))]
482   "TARGET_ARM &&
483    !(const_ok_for_arm (INTVAL (operands[2]))
484      || const_ok_for_arm (-INTVAL (operands[2])))
485     && const_ok_for_arm (~INTVAL (operands[2]))"
486   [(set (match_dup 3) (match_dup 2))
487    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
488   ""
489 )
490
491 (define_insn_and_split "*arm_addsi3"
492   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
493         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
494                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
495   "TARGET_ARM"
496   "@
497    add%?\\t%0, %1, %2
498    sub%?\\t%0, %1, #%n2
499    #"
500   "TARGET_ARM &&
501    GET_CODE (operands[2]) == CONST_INT
502    && !(const_ok_for_arm (INTVAL (operands[2]))
503         || const_ok_for_arm (-INTVAL (operands[2])))"
504   [(clobber (const_int 0))]
505   "
506   arm_split_constant (PLUS, SImode, curr_insn,
507                       INTVAL (operands[2]), operands[0],
508                       operands[1], 0);
509   DONE;
510   "
511   [(set_attr "length" "4,4,16")
512    (set_attr "predicable" "yes")]
513 )
514
515 ;; Register group 'k' is a single register group containing only the stack
516 ;; register.  Trying to reload it will always fail catastrophically,
517 ;; so never allow those alternatives to match if reloading is needed.
518
519 (define_insn "*thumb_addsi3"
520   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
521         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
522                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
523   "TARGET_THUMB"
524   "*
525    static const char * const asms[] = 
526    {
527      \"add\\t%0, %0, %2\",
528      \"sub\\t%0, %0, #%n2\",
529      \"add\\t%0, %1, %2\",
530      \"add\\t%0, %0, %2\",
531      \"add\\t%0, %0, %2\",
532      \"add\\t%0, %1, %2\",
533      \"add\\t%0, %1, %2\"
534    };
535    if ((which_alternative == 2 || which_alternative == 6)
536        && GET_CODE (operands[2]) == CONST_INT
537        && INTVAL (operands[2]) < 0)
538      return \"sub\\t%0, %1, #%n2\";
539    return asms[which_alternative];
540   "
541   [(set_attr "length" "2")]
542 )
543
544 ;; Reloading and elimination of the frame pointer can
545 ;; sometimes cause this optimization to be missed.
546 (define_peephole2
547   [(set (match_operand:SI 0 "arm_general_register_operand" "")
548         (match_operand:SI 1 "const_int_operand" ""))
549    (set (match_dup 0)
550         (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
551   "TARGET_THUMB
552    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
553    && (INTVAL (operands[1]) & 3) == 0"
554   [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
555   ""
556 )
557
558 (define_insn "*addsi3_compare0"
559   [(set (reg:CC_NOOV CC_REGNUM)
560         (compare:CC_NOOV
561          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
562                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
563          (const_int 0)))
564    (set (match_operand:SI 0 "s_register_operand" "=r,r")
565         (plus:SI (match_dup 1) (match_dup 2)))]
566   "TARGET_ARM"
567   "@
568    add%?s\\t%0, %1, %2
569    sub%?s\\t%0, %1, #%n2"
570   [(set_attr "conds" "set")]
571 )
572
573 (define_insn "*addsi3_compare0_scratch"
574   [(set (reg:CC_NOOV CC_REGNUM)
575         (compare:CC_NOOV
576          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
577                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
578          (const_int 0)))]
579   "TARGET_ARM"
580   "@
581    cmn%?\\t%0, %1
582    cmp%?\\t%0, #%n1"
583   [(set_attr "conds" "set")]
584 )
585
586 (define_insn "*compare_negsi_si"
587   [(set (reg:CC_Z CC_REGNUM)
588         (compare:CC_Z
589          (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
590          (match_operand:SI 1 "s_register_operand" "r")))]
591   "TARGET_ARM"
592   "cmn%?\\t%1, %0"
593   [(set_attr "conds" "set")]
594 )
595
596 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
597 ;; addend is a constant.
598 (define_insn "*cmpsi2_addneg"
599   [(set (reg:CC CC_REGNUM)
600         (compare:CC
601          (match_operand:SI 1 "s_register_operand" "r,r")
602          (match_operand:SI 2 "arm_addimm_operand" "I,L")))
603    (set (match_operand:SI 0 "s_register_operand" "=r,r")
604         (plus:SI (match_dup 1)
605                  (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
606   "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
607   "@
608    sub%?s\\t%0, %1, %2
609    add%?s\\t%0, %1, #%n2"
610   [(set_attr "conds" "set")]
611 )
612
613 ;; Convert the sequence
614 ;;  sub  rd, rn, #1
615 ;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
616 ;;  bne  dest
617 ;; into
618 ;;  subs rd, rn, #1
619 ;;  bcs  dest   ((unsigned)rn >= 1)
620 ;; similarly for the beq variant using bcc.
621 ;; This is a common looping idiom (while (n--))
622 (define_peephole2
623   [(set (match_operand:SI 0 "arm_general_register_operand" "")
624         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
625                  (const_int -1)))
626    (set (match_operand 2 "cc_register" "")
627         (compare (match_dup 0) (const_int -1)))
628    (set (pc)
629         (if_then_else (match_operator 3 "equality_operator"
630                        [(match_dup 2) (const_int 0)])
631                       (match_operand 4 "" "")
632                       (match_operand 5 "" "")))]
633   "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
634   [(parallel[
635     (set (match_dup 2)
636          (compare:CC
637           (match_dup 1) (const_int 1)))
638     (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
639    (set (pc)
640         (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
641                       (match_dup 4)
642                       (match_dup 5)))]
643   "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
644    operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
645                                   ? GEU : LTU),
646                                  VOIDmode, 
647                                  operands[2], const0_rtx);"
648 )
649
650 ;; The next four insns work because they compare the result with one of
651 ;; the operands, and we know that the use of the condition code is
652 ;; either GEU or LTU, so we can use the carry flag from the addition
653 ;; instead of doing the compare a second time.
654 (define_insn "*addsi3_compare_op1"
655   [(set (reg:CC_C CC_REGNUM)
656         (compare:CC_C
657          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
658                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
659          (match_dup 1)))
660    (set (match_operand:SI 0 "s_register_operand" "=r,r")
661         (plus:SI (match_dup 1) (match_dup 2)))]
662   "TARGET_ARM"
663   "@
664    add%?s\\t%0, %1, %2
665    sub%?s\\t%0, %1, #%n2"
666   [(set_attr "conds" "set")]
667 )
668
669 (define_insn "*addsi3_compare_op2"
670   [(set (reg:CC_C CC_REGNUM)
671         (compare:CC_C
672          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
673                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
674          (match_dup 2)))
675    (set (match_operand:SI 0 "s_register_operand" "=r,r")
676         (plus:SI (match_dup 1) (match_dup 2)))]
677   "TARGET_ARM"
678   "@
679    add%?s\\t%0, %1, %2
680    sub%?s\\t%0, %1, #%n2"
681   [(set_attr "conds" "set")]
682 )
683
684 (define_insn "*compare_addsi2_op0"
685   [(set (reg:CC_C CC_REGNUM)
686         (compare:CC_C
687          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
688                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
689          (match_dup 0)))]
690   "TARGET_ARM"
691   "@
692    cmn%?\\t%0, %1
693    cmp%?\\t%0, #%n1"
694   [(set_attr "conds" "set")]
695 )
696
697 (define_insn "*compare_addsi2_op1"
698   [(set (reg:CC_C CC_REGNUM)
699         (compare:CC_C
700          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
701                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
702          (match_dup 1)))]
703   "TARGET_ARM"
704   "@
705    cmn%?\\t%0, %1
706    cmp%?\\t%0, #%n1"
707   [(set_attr "conds" "set")]
708 )
709
710 (define_insn "*addsi3_carryin"
711   [(set (match_operand:SI 0 "s_register_operand" "=r")
712         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
713                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
714                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
715   "TARGET_ARM"
716   "adc%?\\t%0, %1, %2"
717   [(set_attr "conds" "use")]
718 )
719
720 (define_insn "*addsi3_carryin_shift"
721   [(set (match_operand:SI 0 "s_register_operand" "=r")
722         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
723                  (plus:SI
724                    (match_operator:SI 2 "shift_operator"
725                       [(match_operand:SI 3 "s_register_operand" "r")
726                        (match_operand:SI 4 "reg_or_int_operand" "rM")])
727                     (match_operand:SI 1 "s_register_operand" "r"))))]
728   "TARGET_ARM"
729   "adc%?\\t%0, %1, %3%S2"
730   [(set_attr "conds" "use")
731    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
732                       (const_string "alu_shift")
733                       (const_string "alu_shift_reg")))]
734 )
735
736 (define_insn "*addsi3_carryin_alt1"
737   [(set (match_operand:SI 0 "s_register_operand" "=r")
738         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
739                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
740                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
741   "TARGET_ARM"
742   "adc%?\\t%0, %1, %2"
743   [(set_attr "conds" "use")]
744 )
745
746 (define_insn "*addsi3_carryin_alt2"
747   [(set (match_operand:SI 0 "s_register_operand" "=r")
748         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
749                           (match_operand:SI 1 "s_register_operand" "r"))
750                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
751   "TARGET_ARM"
752   "adc%?\\t%0, %1, %2"
753   [(set_attr "conds" "use")]
754 )
755
756 (define_insn "*addsi3_carryin_alt3"
757   [(set (match_operand:SI 0 "s_register_operand" "=r")
758         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
759                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
760                  (match_operand:SI 1 "s_register_operand" "r")))]
761   "TARGET_ARM"
762   "adc%?\\t%0, %1, %2"
763   [(set_attr "conds" "use")]
764 )
765
766 (define_insn "incscc"
767   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
768         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
769                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
770                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
771   "TARGET_ARM"
772   "@
773   add%d2\\t%0, %1, #1
774   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
775   [(set_attr "conds" "use")
776    (set_attr "length" "4,8")]
777 )
778
779 ; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
780 (define_split
781   [(set (match_operand:SI 0 "s_register_operand" "")
782         (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
783                             (match_operand:SI 2 "s_register_operand" ""))
784                  (const_int -1)))
785    (clobber (match_operand:SI 3 "s_register_operand" ""))]
786   "TARGET_ARM"
787   [(set (match_dup 3) (match_dup 1))
788    (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
789   "
790   operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
791 ")
792
793 (define_expand "addsf3"
794   [(set (match_operand:SF          0 "s_register_operand" "")
795         (plus:SF (match_operand:SF 1 "s_register_operand" "")
796                  (match_operand:SF 2 "arm_float_add_operand" "")))]
797   "TARGET_ARM && TARGET_HARD_FLOAT"
798   "
799   if (TARGET_MAVERICK
800       && !cirrus_fp_register (operands[2], SFmode))
801     operands[2] = force_reg (SFmode, operands[2]);
802 ")
803
804 (define_expand "adddf3"
805   [(set (match_operand:DF          0 "s_register_operand" "")
806         (plus:DF (match_operand:DF 1 "s_register_operand" "")
807                  (match_operand:DF 2 "arm_float_add_operand" "")))]
808   "TARGET_ARM && TARGET_HARD_FLOAT"
809   "
810   if (TARGET_MAVERICK
811       && !cirrus_fp_register (operands[2], DFmode))
812     operands[2] = force_reg (DFmode, operands[2]);
813 ")
814
815 (define_expand "subdi3"
816  [(parallel
817    [(set (match_operand:DI            0 "s_register_operand" "")
818           (minus:DI (match_operand:DI 1 "s_register_operand" "")
819                     (match_operand:DI 2 "s_register_operand" "")))
820     (clobber (reg:CC CC_REGNUM))])]
821   "TARGET_EITHER"
822   "
823   if (TARGET_HARD_FLOAT && TARGET_MAVERICK
824       && TARGET_ARM
825       && cirrus_fp_register (operands[0], DImode)
826       && cirrus_fp_register (operands[1], DImode))
827     {
828       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
829       DONE;
830     }
831
832   if (TARGET_THUMB)
833     {
834       if (GET_CODE (operands[1]) != REG)
835         operands[1] = force_reg (SImode, operands[1]);
836       if (GET_CODE (operands[2]) != REG)
837         operands[2] = force_reg (SImode, operands[2]);
838      }  
839   "
840 )
841
842 (define_insn "*arm_subdi3"
843   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
844         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
845                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
846    (clobber (reg:CC CC_REGNUM))]
847   "TARGET_ARM"
848   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
849   [(set_attr "conds" "clob")
850    (set_attr "length" "8")]
851 )
852
853 (define_insn "*thumb_subdi3"
854   [(set (match_operand:DI           0 "register_operand" "=l")
855         (minus:DI (match_operand:DI 1 "register_operand"  "0")
856                   (match_operand:DI 2 "register_operand"  "l")))
857    (clobber (reg:CC CC_REGNUM))]
858   "TARGET_THUMB"
859   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
860   [(set_attr "length" "4")]
861 )
862
863 (define_insn "*subdi_di_zesidi"
864   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
865         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
866                   (zero_extend:DI
867                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
868    (clobber (reg:CC CC_REGNUM))]
869   "TARGET_ARM"
870   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
871   [(set_attr "conds" "clob")
872    (set_attr "length" "8")]
873 )
874
875 (define_insn "*subdi_di_sesidi"
876   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
877         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
878                   (sign_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, %2, asr #31"
883   [(set_attr "conds" "clob")
884    (set_attr "length" "8")]
885 )
886
887 (define_insn "*subdi_zesidi_di"
888   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
889         (minus:DI (zero_extend:DI
890                    (match_operand:SI 2 "s_register_operand"  "r,r"))
891                   (match_operand:DI  1 "s_register_operand" "?r,0")))
892    (clobber (reg:CC CC_REGNUM))]
893   "TARGET_ARM"
894   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
895   [(set_attr "conds" "clob")
896    (set_attr "length" "8")]
897 )
898
899 (define_insn "*subdi_sesidi_di"
900   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
901         (minus:DI (sign_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, %2, asr #31"
907   [(set_attr "conds" "clob")
908    (set_attr "length" "8")]
909 )
910
911 (define_insn "*subdi_zesidi_zesidi"
912   [(set (match_operand:DI            0 "s_register_operand" "=r")
913         (minus:DI (zero_extend:DI
914                    (match_operand:SI 1 "s_register_operand"  "r"))
915                   (zero_extend:DI
916                    (match_operand:SI 2 "s_register_operand"  "r"))))
917    (clobber (reg:CC CC_REGNUM))]
918   "TARGET_ARM"
919   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
920   [(set_attr "conds" "clob")
921    (set_attr "length" "8")]
922 )
923
924 (define_expand "subsi3"
925   [(set (match_operand:SI           0 "s_register_operand" "")
926         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
927                   (match_operand:SI 2 "s_register_operand" "")))]
928   "TARGET_EITHER"
929   "
930   if (GET_CODE (operands[1]) == CONST_INT)
931     {
932       if (TARGET_ARM)
933         {
934           arm_split_constant (MINUS, SImode, NULL_RTX,
935                               INTVAL (operands[1]), operands[0],
936                               operands[2], optimize && !no_new_pseudos);
937           DONE;
938         }
939       else /* TARGET_THUMB */
940         operands[1] = force_reg (SImode, operands[1]);
941     }
942   "
943 )
944
945 (define_insn "*thumb_subsi3_insn"
946   [(set (match_operand:SI           0 "register_operand" "=l")
947         (minus:SI (match_operand:SI 1 "register_operand" "l")
948                   (match_operand:SI 2 "register_operand" "l")))]
949   "TARGET_THUMB"
950   "sub\\t%0, %1, %2"
951   [(set_attr "length" "2")]
952 )
953
954 (define_insn_and_split "*arm_subsi3_insn"
955   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
956         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
957                   (match_operand:SI 2 "s_register_operand" "r,r")))]
958   "TARGET_ARM"
959   "@
960    rsb%?\\t%0, %2, %1
961    #"
962   "TARGET_ARM
963    && GET_CODE (operands[1]) == CONST_INT
964    && !const_ok_for_arm (INTVAL (operands[1]))"
965   [(clobber (const_int 0))]
966   "
967   arm_split_constant (MINUS, SImode, curr_insn,
968                       INTVAL (operands[1]), operands[0], operands[2], 0);
969   DONE;
970   "
971   [(set_attr "length" "4,16")
972    (set_attr "predicable" "yes")]
973 )
974
975 (define_peephole2
976   [(match_scratch:SI 3 "r")
977    (set (match_operand:SI 0 "arm_general_register_operand" "")
978         (minus:SI (match_operand:SI 1 "const_int_operand" "")
979                   (match_operand:SI 2 "arm_general_register_operand" "")))]
980   "TARGET_ARM
981    && !const_ok_for_arm (INTVAL (operands[1]))
982    && const_ok_for_arm (~INTVAL (operands[1]))"
983   [(set (match_dup 3) (match_dup 1))
984    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
985   ""
986 )
987
988 (define_insn "*subsi3_compare0"
989   [(set (reg:CC_NOOV CC_REGNUM)
990         (compare:CC_NOOV
991          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
992                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
993          (const_int 0)))
994    (set (match_operand:SI 0 "s_register_operand" "=r,r")
995         (minus:SI (match_dup 1) (match_dup 2)))]
996   "TARGET_ARM"
997   "@
998    sub%?s\\t%0, %1, %2
999    rsb%?s\\t%0, %2, %1"
1000   [(set_attr "conds" "set")]
1001 )
1002
1003 (define_insn "decscc"
1004   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1005         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1006                   (match_operator:SI 2 "arm_comparison_operator"
1007                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1008   "TARGET_ARM"
1009   "@
1010    sub%d2\\t%0, %1, #1
1011    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1012   [(set_attr "conds" "use")
1013    (set_attr "length" "*,8")]
1014 )
1015
1016 (define_expand "subsf3"
1017   [(set (match_operand:SF           0 "s_register_operand" "")
1018         (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1019                   (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1020   "TARGET_ARM && TARGET_HARD_FLOAT"
1021   "
1022   if (TARGET_MAVERICK)
1023     {
1024       if (!cirrus_fp_register (operands[1], SFmode))
1025         operands[1] = force_reg (SFmode, operands[1]);
1026       if (!cirrus_fp_register (operands[2], SFmode))
1027         operands[2] = force_reg (SFmode, operands[2]);
1028     }
1029 ")
1030
1031 (define_expand "subdf3"
1032   [(set (match_operand:DF           0 "s_register_operand" "")
1033         (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1034                   (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1035   "TARGET_ARM && TARGET_HARD_FLOAT"
1036   "
1037   if (TARGET_MAVERICK)
1038     {
1039        if (!cirrus_fp_register (operands[1], DFmode))
1040          operands[1] = force_reg (DFmode, operands[1]);
1041        if (!cirrus_fp_register (operands[2], DFmode))
1042          operands[2] = force_reg (DFmode, operands[2]);
1043     }
1044 ")
1045
1046 \f
1047 ;; Multiplication insns
1048
1049 (define_expand "mulsi3"
1050   [(set (match_operand:SI          0 "s_register_operand" "")
1051         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1052                  (match_operand:SI 1 "s_register_operand" "")))]
1053   "TARGET_EITHER"
1054   ""
1055 )
1056
1057 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1058 (define_insn "*arm_mulsi3"
1059   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1060         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1061                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1062   "TARGET_ARM"
1063   "mul%?\\t%0, %2, %1"
1064   [(set_attr "insn" "mul")
1065    (set_attr "predicable" "yes")]
1066 )
1067
1068 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1069 ; 1 and 2; are the same, because reload will make operand 0 match 
1070 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1071 ; this by adding another alternative to match this case, and then `reload' 
1072 ; it ourselves.  This alternative must come first.
1073 (define_insn "*thumb_mulsi3"
1074   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1075         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1076                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1077   "TARGET_THUMB"
1078   "*
1079   if (which_alternative < 2)
1080     return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1081   else
1082     return \"mul\\t%0, %0, %2\";
1083   "
1084   [(set_attr "length" "4,4,2")
1085    (set_attr "insn" "mul")]
1086 )
1087
1088 (define_insn "*mulsi3_compare0"
1089   [(set (reg:CC_NOOV CC_REGNUM)
1090         (compare:CC_NOOV (mult:SI
1091                           (match_operand:SI 2 "s_register_operand" "r,r")
1092                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1093                          (const_int 0)))
1094    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1095         (mult:SI (match_dup 2) (match_dup 1)))]
1096   "TARGET_ARM"
1097   "mul%?s\\t%0, %2, %1"
1098   [(set_attr "conds" "set")
1099    (set_attr "insn" "muls")]
1100 )
1101
1102 (define_insn "*mulsi_compare0_scratch"
1103   [(set (reg:CC_NOOV CC_REGNUM)
1104         (compare:CC_NOOV (mult:SI
1105                           (match_operand:SI 2 "s_register_operand" "r,r")
1106                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1107                          (const_int 0)))
1108    (clobber (match_scratch:SI 0 "=&r,&r"))]
1109   "TARGET_ARM"
1110   "mul%?s\\t%0, %2, %1"
1111   [(set_attr "conds" "set")
1112    (set_attr "insn" "muls")]
1113 )
1114
1115 ;; Unnamed templates to match MLA instruction.
1116
1117 (define_insn "*mulsi3addsi"
1118   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1119         (plus:SI
1120           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1121                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1122           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1123   "TARGET_ARM"
1124   "mla%?\\t%0, %2, %1, %3"
1125   [(set_attr "insn" "mla")
1126    (set_attr "predicable" "yes")]
1127 )
1128
1129 (define_insn "*mulsi3addsi_compare0"
1130   [(set (reg:CC_NOOV CC_REGNUM)
1131         (compare:CC_NOOV
1132          (plus:SI (mult:SI
1133                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1134                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1135                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1136          (const_int 0)))
1137    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1138         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1139                  (match_dup 3)))]
1140   "TARGET_ARM"
1141   "mla%?s\\t%0, %2, %1, %3"
1142   [(set_attr "conds" "set")
1143    (set_attr "insn" "mlas")]
1144 )
1145
1146 (define_insn "*mulsi3addsi_compare0_scratch"
1147   [(set (reg:CC_NOOV CC_REGNUM)
1148         (compare:CC_NOOV
1149          (plus:SI (mult:SI
1150                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1151                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1152                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1153          (const_int 0)))
1154    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1155   "TARGET_ARM"
1156   "mla%?s\\t%0, %2, %1, %3"
1157   [(set_attr "conds" "set")
1158    (set_attr "insn" "mlas")]
1159 )
1160
1161 ;; Unnamed template to match long long multiply-accumulate (smlal)
1162
1163 (define_insn "*mulsidi3adddi"
1164   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1165         (plus:DI
1166          (mult:DI
1167           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1168           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1169          (match_operand:DI 1 "s_register_operand" "0")))]
1170   "TARGET_ARM && arm_arch3m"
1171   "smlal%?\\t%Q0, %R0, %3, %2"
1172   [(set_attr "insn" "smlal")
1173    (set_attr "predicable" "yes")]
1174 )
1175
1176 (define_insn "mulsidi3"
1177   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1178         (mult:DI
1179          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1180          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1181   "TARGET_ARM && arm_arch3m"
1182   "smull%?\\t%Q0, %R0, %1, %2"
1183   [(set_attr "insn" "smull")
1184    (set_attr "predicable" "yes")]
1185 )
1186
1187 (define_insn "umulsidi3"
1188   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1189         (mult:DI
1190          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1191          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1192   "TARGET_ARM && arm_arch3m"
1193   "umull%?\\t%Q0, %R0, %1, %2"
1194   [(set_attr "insn" "umull")
1195    (set_attr "predicable" "yes")]
1196 )
1197
1198 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1199
1200 (define_insn "*umulsidi3adddi"
1201   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1202         (plus:DI
1203          (mult:DI
1204           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1205           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1206          (match_operand:DI 1 "s_register_operand" "0")))]
1207   "TARGET_ARM && arm_arch3m"
1208   "umlal%?\\t%Q0, %R0, %3, %2"
1209   [(set_attr "insn" "umlal")
1210    (set_attr "predicable" "yes")]
1211 )
1212
1213 (define_insn "smulsi3_highpart"
1214   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1215         (truncate:SI
1216          (lshiftrt:DI
1217           (mult:DI
1218            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1219            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1220           (const_int 32))))
1221    (clobber (match_scratch:SI 3 "=&r,&r"))]
1222   "TARGET_ARM && arm_arch3m"
1223   "smull%?\\t%3, %0, %2, %1"
1224   [(set_attr "insn" "smull")
1225    (set_attr "predicable" "yes")]
1226 )
1227
1228 (define_insn "umulsi3_highpart"
1229   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1230         (truncate:SI
1231          (lshiftrt:DI
1232           (mult:DI
1233            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1234            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1235           (const_int 32))))
1236    (clobber (match_scratch:SI 3 "=&r,&r"))]
1237   "TARGET_ARM && arm_arch3m"
1238   "umull%?\\t%3, %0, %2, %1"
1239   [(set_attr "insn" "umull")
1240    (set_attr "predicable" "yes")]
1241 )
1242
1243 (define_insn "mulhisi3"
1244   [(set (match_operand:SI 0 "s_register_operand" "=r")
1245         (mult:SI (sign_extend:SI
1246                   (match_operand:HI 1 "s_register_operand" "%r"))
1247                  (sign_extend:SI
1248                   (match_operand:HI 2 "s_register_operand" "r"))))]
1249   "TARGET_ARM && arm_arch5e"
1250   "smulbb%?\\t%0, %1, %2"
1251   [(set_attr "insn" "smulxy")
1252    (set_attr "predicable" "yes")]
1253 )
1254
1255 (define_insn "*mulhisi3tb"
1256   [(set (match_operand:SI 0 "s_register_operand" "=r")
1257         (mult:SI (ashiftrt:SI
1258                   (match_operand:SI 1 "s_register_operand" "r")
1259                   (const_int 16))
1260                  (sign_extend:SI
1261                   (match_operand:HI 2 "s_register_operand" "r"))))]
1262   "TARGET_ARM && arm_arch5e"
1263   "smultb%?\\t%0, %1, %2"
1264   [(set_attr "insn" "smulxy")
1265    (set_attr "predicable" "yes")]
1266 )
1267
1268 (define_insn "*mulhisi3bt"
1269   [(set (match_operand:SI 0 "s_register_operand" "=r")
1270         (mult:SI (sign_extend:SI
1271                   (match_operand:HI 1 "s_register_operand" "r"))
1272                  (ashiftrt:SI
1273                   (match_operand:SI 2 "s_register_operand" "r")
1274                   (const_int 16))))]
1275   "TARGET_ARM && arm_arch5e"
1276   "smulbt%?\\t%0, %1, %2"
1277   [(set_attr "insn" "smulxy")
1278    (set_attr "predicable" "yes")]
1279 )
1280
1281 (define_insn "*mulhisi3tt"
1282   [(set (match_operand:SI 0 "s_register_operand" "=r")
1283         (mult:SI (ashiftrt:SI
1284                   (match_operand:SI 1 "s_register_operand" "r")
1285                   (const_int 16))
1286                  (ashiftrt:SI
1287                   (match_operand:SI 2 "s_register_operand" "r")
1288                   (const_int 16))))]
1289   "TARGET_ARM && arm_arch5e"
1290   "smultt%?\\t%0, %1, %2"
1291   [(set_attr "insn" "smulxy")
1292    (set_attr "predicable" "yes")]
1293 )
1294
1295 (define_insn "*mulhisi3addsi"
1296   [(set (match_operand:SI 0 "s_register_operand" "=r")
1297         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1298                  (mult:SI (sign_extend:SI
1299                            (match_operand:HI 2 "s_register_operand" "%r"))
1300                           (sign_extend:SI
1301                            (match_operand:HI 3 "s_register_operand" "r")))))]
1302   "TARGET_ARM && arm_arch5e"
1303   "smlabb%?\\t%0, %2, %3, %1"
1304   [(set_attr "insn" "smlaxy")
1305    (set_attr "predicable" "yes")]
1306 )
1307
1308 (define_insn "*mulhidi3adddi"
1309   [(set (match_operand:DI 0 "s_register_operand" "=r")
1310         (plus:DI
1311           (match_operand:DI 1 "s_register_operand" "0")
1312           (mult:DI (sign_extend:DI
1313                     (match_operand:HI 2 "s_register_operand" "%r"))
1314                    (sign_extend:DI
1315                     (match_operand:HI 3 "s_register_operand" "r")))))]
1316   "TARGET_ARM && arm_arch5e"
1317   "smlalbb%?\\t%Q0, %R0, %2, %3"
1318   [(set_attr "insn" "smlalxy")
1319    (set_attr "predicable" "yes")])
1320
1321 (define_expand "mulsf3"
1322   [(set (match_operand:SF          0 "s_register_operand" "")
1323         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1324                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1325   "TARGET_ARM && TARGET_HARD_FLOAT"
1326   "
1327   if (TARGET_MAVERICK
1328       && !cirrus_fp_register (operands[2], SFmode))
1329     operands[2] = force_reg (SFmode, operands[2]);
1330 ")
1331
1332 (define_expand "muldf3"
1333   [(set (match_operand:DF          0 "s_register_operand" "")
1334         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1335                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1336   "TARGET_ARM && TARGET_HARD_FLOAT"
1337   "
1338   if (TARGET_MAVERICK
1339       && !cirrus_fp_register (operands[2], DFmode))
1340     operands[2] = force_reg (DFmode, operands[2]);
1341 ")
1342 \f
1343 ;; Division insns
1344
1345 (define_expand "divsf3"
1346   [(set (match_operand:SF 0 "s_register_operand" "")
1347         (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1348                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1349   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1350   "")
1351
1352 (define_expand "divdf3"
1353   [(set (match_operand:DF 0 "s_register_operand" "")
1354         (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1355                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1356   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1357   "")
1358 \f
1359 ;; Modulo insns
1360
1361 (define_expand "modsf3"
1362   [(set (match_operand:SF 0 "s_register_operand" "")
1363         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1364                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1365   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1366   "")
1367
1368 (define_expand "moddf3"
1369   [(set (match_operand:DF 0 "s_register_operand" "")
1370         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1371                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1372   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1373   "")
1374 \f
1375 ;; Boolean and,ior,xor insns
1376
1377 ;; Split up double word logical operations
1378
1379 ;; Split up simple DImode logical operations.  Simply perform the logical
1380 ;; operation on the upper and lower halves of the registers.
1381 (define_split
1382   [(set (match_operand:DI 0 "s_register_operand" "")
1383         (match_operator:DI 6 "logical_binary_operator"
1384           [(match_operand:DI 1 "s_register_operand" "")
1385            (match_operand:DI 2 "s_register_operand" "")]))]
1386   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1387   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1388    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1389   "
1390   {
1391     operands[3] = gen_highpart (SImode, operands[0]);
1392     operands[0] = gen_lowpart (SImode, operands[0]);
1393     operands[4] = gen_highpart (SImode, operands[1]);
1394     operands[1] = gen_lowpart (SImode, operands[1]);
1395     operands[5] = gen_highpart (SImode, operands[2]);
1396     operands[2] = gen_lowpart (SImode, operands[2]);
1397   }"
1398 )
1399
1400 (define_split
1401   [(set (match_operand:DI 0 "s_register_operand" "")
1402         (match_operator:DI 6 "logical_binary_operator"
1403           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1404            (match_operand:DI 1 "s_register_operand" "")]))]
1405   "TARGET_ARM && reload_completed"
1406   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1407    (set (match_dup 3) (match_op_dup:SI 6
1408                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1409                          (match_dup 4)]))]
1410   "
1411   {
1412     operands[3] = gen_highpart (SImode, operands[0]);
1413     operands[0] = gen_lowpart (SImode, operands[0]);
1414     operands[4] = gen_highpart (SImode, operands[1]);
1415     operands[1] = gen_lowpart (SImode, operands[1]);
1416     operands[5] = gen_highpart (SImode, operands[2]);
1417     operands[2] = gen_lowpart (SImode, operands[2]);
1418   }"
1419 )
1420
1421 ;; The zero extend of operand 2 means we can just copy the high part of
1422 ;; operand1 into operand0.
1423 (define_split
1424   [(set (match_operand:DI 0 "s_register_operand" "")
1425         (ior:DI
1426           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1427           (match_operand:DI 1 "s_register_operand" "")))]
1428   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1429   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1430    (set (match_dup 3) (match_dup 4))]
1431   "
1432   {
1433     operands[4] = gen_highpart (SImode, operands[1]);
1434     operands[3] = gen_highpart (SImode, operands[0]);
1435     operands[0] = gen_lowpart (SImode, operands[0]);
1436     operands[1] = gen_lowpart (SImode, operands[1]);
1437   }"
1438 )
1439
1440 ;; The zero extend of operand 2 means we can just copy the high part of
1441 ;; operand1 into operand0.
1442 (define_split
1443   [(set (match_operand:DI 0 "s_register_operand" "")
1444         (xor:DI
1445           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1446           (match_operand:DI 1 "s_register_operand" "")))]
1447   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1448   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1449    (set (match_dup 3) (match_dup 4))]
1450   "
1451   {
1452     operands[4] = gen_highpart (SImode, operands[1]);
1453     operands[3] = gen_highpart (SImode, operands[0]);
1454     operands[0] = gen_lowpart (SImode, operands[0]);
1455     operands[1] = gen_lowpart (SImode, operands[1]);
1456   }"
1457 )
1458
1459 (define_insn "anddi3"
1460   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1461         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1462                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1463   "TARGET_ARM && ! TARGET_IWMMXT"
1464   "#"
1465   [(set_attr "length" "8")]
1466 )
1467
1468 (define_insn_and_split "*anddi_zesidi_di"
1469   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1470         (and:DI (zero_extend:DI
1471                  (match_operand:SI 2 "s_register_operand" "r,r"))
1472                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1473   "TARGET_ARM"
1474   "#"
1475   "TARGET_ARM && reload_completed"
1476   ; The zero extend of operand 2 clears the high word of the output
1477   ; operand.
1478   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1479    (set (match_dup 3) (const_int 0))]
1480   "
1481   {
1482     operands[3] = gen_highpart (SImode, operands[0]);
1483     operands[0] = gen_lowpart (SImode, operands[0]);
1484     operands[1] = gen_lowpart (SImode, operands[1]);
1485   }"
1486   [(set_attr "length" "8")]
1487 )
1488
1489 (define_insn "*anddi_sesdi_di"
1490   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1491         (and:DI (sign_extend:DI
1492                  (match_operand:SI 2 "s_register_operand" "r,r"))
1493                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1494   "TARGET_ARM"
1495   "#"
1496   [(set_attr "length" "8")]
1497 )
1498
1499 (define_expand "andsi3"
1500   [(set (match_operand:SI         0 "s_register_operand" "")
1501         (and:SI (match_operand:SI 1 "s_register_operand" "")
1502                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1503   "TARGET_EITHER"
1504   "
1505   if (TARGET_ARM)
1506     {
1507       if (GET_CODE (operands[2]) == CONST_INT)
1508         {
1509           arm_split_constant (AND, SImode, NULL_RTX,
1510                               INTVAL (operands[2]), operands[0],
1511                               operands[1], optimize && !no_new_pseudos);
1512
1513           DONE;
1514         }
1515     }
1516   else /* TARGET_THUMB */
1517     {
1518       if (GET_CODE (operands[2]) != CONST_INT)
1519         operands[2] = force_reg (SImode, operands[2]);
1520       else
1521         {
1522           int i;
1523           
1524           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1525             {
1526               operands[2] = force_reg (SImode,
1527                                        GEN_INT (~INTVAL (operands[2])));
1528               
1529               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1530               
1531               DONE;
1532             }
1533
1534           for (i = 9; i <= 31; i++)
1535             {
1536               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1537                 {
1538                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1539                                         const0_rtx));
1540                   DONE;
1541                 }
1542               else if ((((HOST_WIDE_INT) 1) << i) - 1
1543                        == ~INTVAL (operands[2]))
1544                 {
1545                   rtx shift = GEN_INT (i);
1546                   rtx reg = gen_reg_rtx (SImode);
1547                 
1548                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1549                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1550                   
1551                   DONE;
1552                 }
1553             }
1554
1555           operands[2] = force_reg (SImode, operands[2]);
1556         }
1557     }
1558   "
1559 )
1560
1561 (define_insn_and_split "*arm_andsi3_insn"
1562   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1563         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1564                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1565   "TARGET_ARM"
1566   "@
1567    and%?\\t%0, %1, %2
1568    bic%?\\t%0, %1, #%B2
1569    #"
1570   "TARGET_ARM
1571    && GET_CODE (operands[2]) == CONST_INT
1572    && !(const_ok_for_arm (INTVAL (operands[2]))
1573         || const_ok_for_arm (~INTVAL (operands[2])))"
1574   [(clobber (const_int 0))]
1575   "
1576   arm_split_constant  (AND, SImode, curr_insn, 
1577                        INTVAL (operands[2]), operands[0], operands[1], 0);
1578   DONE;
1579   "
1580   [(set_attr "length" "4,4,16")
1581    (set_attr "predicable" "yes")]
1582 )
1583
1584 (define_insn "*thumb_andsi3_insn"
1585   [(set (match_operand:SI         0 "register_operand" "=l")
1586         (and:SI (match_operand:SI 1 "register_operand" "%0")
1587                 (match_operand:SI 2 "register_operand" "l")))]
1588   "TARGET_THUMB"
1589   "and\\t%0, %0, %2"
1590   [(set_attr "length" "2")]
1591 )
1592
1593 (define_insn "*andsi3_compare0"
1594   [(set (reg:CC_NOOV CC_REGNUM)
1595         (compare:CC_NOOV
1596          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1597                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1598          (const_int 0)))
1599    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1600         (and:SI (match_dup 1) (match_dup 2)))]
1601   "TARGET_ARM"
1602   "@
1603    and%?s\\t%0, %1, %2
1604    bic%?s\\t%0, %1, #%B2"
1605   [(set_attr "conds" "set")]
1606 )
1607
1608 (define_insn "*andsi3_compare0_scratch"
1609   [(set (reg:CC_NOOV CC_REGNUM)
1610         (compare:CC_NOOV
1611          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1612                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1613          (const_int 0)))
1614    (clobber (match_scratch:SI 2 "=X,r"))]
1615   "TARGET_ARM"
1616   "@
1617    tst%?\\t%0, %1
1618    bic%?s\\t%2, %0, #%B1"
1619   [(set_attr "conds" "set")]
1620 )
1621
1622 (define_insn "*zeroextractsi_compare0_scratch"
1623   [(set (reg:CC_NOOV CC_REGNUM)
1624         (compare:CC_NOOV (zero_extract:SI
1625                           (match_operand:SI 0 "s_register_operand" "r")
1626                           (match_operand 1 "const_int_operand" "n")
1627                           (match_operand 2 "const_int_operand" "n"))
1628                          (const_int 0)))]
1629   "TARGET_ARM
1630   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1631       && INTVAL (operands[1]) > 0 
1632       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1633       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1634   "*
1635   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1636                          << INTVAL (operands[2]));
1637   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1638   return \"\";
1639   "
1640   [(set_attr "conds" "set")]
1641 )
1642
1643 (define_insn_and_split "*ne_zeroextractsi"
1644   [(set (match_operand:SI 0 "s_register_operand" "=r")
1645         (ne:SI (zero_extract:SI
1646                 (match_operand:SI 1 "s_register_operand" "r")
1647                 (match_operand:SI 2 "const_int_operand" "n")
1648                 (match_operand:SI 3 "const_int_operand" "n"))
1649                (const_int 0)))
1650    (clobber (reg:CC CC_REGNUM))]
1651   "TARGET_ARM
1652    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1653        && INTVAL (operands[2]) > 0 
1654        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1655        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1656   "#"
1657   "TARGET_ARM
1658    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1659        && INTVAL (operands[2]) > 0 
1660        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1661        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1662   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1663                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1664                                     (const_int 0)))
1665               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1666    (set (match_dup 0)
1667         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1668                          (match_dup 0) (const_int 1)))]
1669   "
1670   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1671                          << INTVAL (operands[3])); 
1672   "
1673   [(set_attr "conds" "clob")
1674    (set_attr "length" "8")]
1675 )
1676
1677 (define_insn_and_split "*ne_zeroextractsi_shifted"
1678   [(set (match_operand:SI 0 "s_register_operand" "=r")
1679         (ne:SI (zero_extract:SI
1680                 (match_operand:SI 1 "s_register_operand" "r")
1681                 (match_operand:SI 2 "const_int_operand" "n")
1682                 (const_int 0))
1683                (const_int 0)))
1684    (clobber (reg:CC CC_REGNUM))]
1685   "TARGET_ARM"
1686   "#"
1687   "TARGET_ARM"
1688   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1689                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1690                                     (const_int 0)))
1691               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1692    (set (match_dup 0)
1693         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1694                          (match_dup 0) (const_int 1)))]
1695   "
1696   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1697   "
1698   [(set_attr "conds" "clob")
1699    (set_attr "length" "8")]
1700 )
1701
1702 (define_insn_and_split "*ite_ne_zeroextractsi"
1703   [(set (match_operand:SI 0 "s_register_operand" "=r")
1704         (if_then_else:SI (ne (zero_extract:SI
1705                               (match_operand:SI 1 "s_register_operand" "r")
1706                               (match_operand:SI 2 "const_int_operand" "n")
1707                               (match_operand:SI 3 "const_int_operand" "n"))
1708                              (const_int 0))
1709                          (match_operand:SI 4 "arm_not_operand" "rIK")
1710                          (const_int 0)))
1711    (clobber (reg:CC CC_REGNUM))]
1712   "TARGET_ARM
1713    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1714        && INTVAL (operands[2]) > 0 
1715        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1716        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1717    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1718   "#"
1719   "TARGET_ARM
1720    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1721        && INTVAL (operands[2]) > 0 
1722        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1723        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1724    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1725   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1726                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1727                                     (const_int 0)))
1728               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1729    (set (match_dup 0)
1730         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1731                          (match_dup 0) (match_dup 4)))]
1732   "
1733   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1734                          << INTVAL (operands[3])); 
1735   "
1736   [(set_attr "conds" "clob")
1737    (set_attr "length" "8")]
1738 )
1739
1740 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1741   [(set (match_operand:SI 0 "s_register_operand" "=r")
1742         (if_then_else:SI (ne (zero_extract:SI
1743                               (match_operand:SI 1 "s_register_operand" "r")
1744                               (match_operand:SI 2 "const_int_operand" "n")
1745                               (const_int 0))
1746                              (const_int 0))
1747                          (match_operand:SI 3 "arm_not_operand" "rIK")
1748                          (const_int 0)))
1749    (clobber (reg:CC CC_REGNUM))]
1750   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1751   "#"
1752   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1753   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1754                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1755                                     (const_int 0)))
1756               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1757    (set (match_dup 0)
1758         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1759                          (match_dup 0) (match_dup 3)))]
1760   "
1761   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1762   "
1763   [(set_attr "conds" "clob")
1764    (set_attr "length" "8")]
1765 )
1766
1767 (define_split
1768   [(set (match_operand:SI 0 "s_register_operand" "")
1769         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1770                          (match_operand:SI 2 "const_int_operand" "")
1771                          (match_operand:SI 3 "const_int_operand" "")))
1772    (clobber (match_operand:SI 4 "s_register_operand" ""))]
1773   "TARGET_THUMB"
1774   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1775    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1776   "{
1777      HOST_WIDE_INT temp = INTVAL (operands[2]);
1778
1779      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1780      operands[3] = GEN_INT (32 - temp);
1781    }"
1782 )
1783
1784 (define_split
1785   [(set (match_operand:SI 0 "s_register_operand" "")
1786         (match_operator:SI 1 "shiftable_operator"
1787          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1788                            (match_operand:SI 3 "const_int_operand" "")
1789                            (match_operand:SI 4 "const_int_operand" ""))
1790           (match_operand:SI 5 "s_register_operand" "")]))
1791    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1792   "TARGET_ARM"
1793   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1794    (set (match_dup 0)
1795         (match_op_dup 1
1796          [(lshiftrt:SI (match_dup 6) (match_dup 4))
1797           (match_dup 5)]))]
1798   "{
1799      HOST_WIDE_INT temp = INTVAL (operands[3]);
1800
1801      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1802      operands[4] = GEN_INT (32 - temp);
1803    }"
1804 )
1805   
1806 (define_split
1807   [(set (match_operand:SI 0 "s_register_operand" "")
1808         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1809                          (match_operand:SI 2 "const_int_operand" "")
1810                          (match_operand:SI 3 "const_int_operand" "")))]
1811   "TARGET_THUMB"
1812   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1813    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1814   "{
1815      HOST_WIDE_INT temp = INTVAL (operands[2]);
1816
1817      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1818      operands[3] = GEN_INT (32 - temp);
1819    }"
1820 )
1821
1822 (define_split
1823   [(set (match_operand:SI 0 "s_register_operand" "")
1824         (match_operator:SI 1 "shiftable_operator"
1825          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1826                            (match_operand:SI 3 "const_int_operand" "")
1827                            (match_operand:SI 4 "const_int_operand" ""))
1828           (match_operand:SI 5 "s_register_operand" "")]))
1829    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1830   "TARGET_ARM"
1831   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1832    (set (match_dup 0)
1833         (match_op_dup 1
1834          [(ashiftrt:SI (match_dup 6) (match_dup 4))
1835           (match_dup 5)]))]
1836   "{
1837      HOST_WIDE_INT temp = INTVAL (operands[3]);
1838
1839      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1840      operands[4] = GEN_INT (32 - temp);
1841    }"
1842 )
1843   
1844 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1845 ;;; represented by the bitfield, then this will produce incorrect results.
1846 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1847 ;;; which have a real bit-field insert instruction, the truncation happens
1848 ;;; in the bit-field insert instruction itself.  Since arm does not have a
1849 ;;; bit-field insert instruction, we would have to emit code here to truncate
1850 ;;; the value before we insert.  This loses some of the advantage of having
1851 ;;; this insv pattern, so this pattern needs to be reevalutated.
1852
1853 (define_expand "insv"
1854   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1855                          (match_operand:SI 1 "general_operand" "")
1856                          (match_operand:SI 2 "general_operand" ""))
1857         (match_operand:SI 3 "reg_or_int_operand" ""))]
1858   "TARGET_ARM"
1859   "
1860   {
1861     int start_bit = INTVAL (operands[2]);
1862     int width = INTVAL (operands[1]);
1863     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1864     rtx target, subtarget;
1865
1866     target = operands[0];
1867     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1868        subreg as the final target.  */
1869     if (GET_CODE (target) == SUBREG)
1870       {
1871         subtarget = gen_reg_rtx (SImode);
1872         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1873             < GET_MODE_SIZE (SImode))
1874           target = SUBREG_REG (target);
1875       }
1876     else
1877       subtarget = target;    
1878
1879     if (GET_CODE (operands[3]) == CONST_INT)
1880       {
1881         /* Since we are inserting a known constant, we may be able to
1882            reduce the number of bits that we have to clear so that
1883            the mask becomes simple.  */
1884         /* ??? This code does not check to see if the new mask is actually
1885            simpler.  It may not be.  */
1886         rtx op1 = gen_reg_rtx (SImode);
1887         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1888            start of this pattern.  */
1889         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1890         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1891
1892         emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1893         emit_insn (gen_iorsi3 (subtarget, op1,
1894                                gen_int_mode (op3_value << start_bit, SImode)));
1895       }
1896     else if (start_bit == 0
1897              && !(const_ok_for_arm (mask)
1898                   || const_ok_for_arm (~mask)))
1899       {
1900         /* A Trick, since we are setting the bottom bits in the word,
1901            we can shift operand[3] up, operand[0] down, OR them together
1902            and rotate the result back again.  This takes 3 insns, and
1903            the third might be mergeable into another op.  */
1904         /* The shift up copes with the possibility that operand[3] is
1905            wider than the bitfield.  */
1906         rtx op0 = gen_reg_rtx (SImode);
1907         rtx op1 = gen_reg_rtx (SImode);
1908
1909         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1910         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1911         emit_insn (gen_iorsi3  (op1, op1, op0));
1912         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1913       }
1914     else if ((width + start_bit == 32)
1915              && !(const_ok_for_arm (mask)
1916                   || const_ok_for_arm (~mask)))
1917       {
1918         /* Similar trick, but slightly less efficient.  */
1919
1920         rtx op0 = gen_reg_rtx (SImode);
1921         rtx op1 = gen_reg_rtx (SImode);
1922
1923         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1924         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1925         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1926         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1927       }
1928     else
1929       {
1930         rtx op0 = GEN_INT (mask);
1931         rtx op1 = gen_reg_rtx (SImode);
1932         rtx op2 = gen_reg_rtx (SImode);
1933
1934         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1935           {
1936             rtx tmp = gen_reg_rtx (SImode);
1937
1938             emit_insn (gen_movsi (tmp, op0));
1939             op0 = tmp;
1940           }
1941
1942         /* Mask out any bits in operand[3] that are not needed.  */
1943            emit_insn (gen_andsi3 (op1, operands[3], op0));
1944
1945         if (GET_CODE (op0) == CONST_INT
1946             && (const_ok_for_arm (mask << start_bit)
1947                 || const_ok_for_arm (~(mask << start_bit))))
1948           {
1949             op0 = GEN_INT (~(mask << start_bit));
1950             emit_insn (gen_andsi3 (op2, operands[0], op0));
1951           }
1952         else
1953           {
1954             if (GET_CODE (op0) == CONST_INT)
1955               {
1956                 rtx tmp = gen_reg_rtx (SImode);
1957
1958                 emit_insn (gen_movsi (tmp, op0));
1959                 op0 = tmp;
1960               }
1961
1962             if (start_bit != 0)
1963               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1964             
1965             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1966           }
1967
1968         if (start_bit != 0)
1969           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1970
1971         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1972       }
1973
1974     if (subtarget != target)
1975       {
1976         /* If TARGET is still a SUBREG, then it must be wider than a word,
1977            so we must be careful only to set the subword we were asked to.  */
1978         if (GET_CODE (target) == SUBREG)
1979           emit_move_insn (target, subtarget);
1980         else
1981           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1982       }
1983
1984     DONE;
1985   }"
1986 )
1987
1988 ; constants for op 2 will never be given to these patterns.
1989 (define_insn_and_split "*anddi_notdi_di"
1990   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1991         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1992                 (match_operand:DI 2 "s_register_operand" "0,r")))]
1993   "TARGET_ARM"
1994   "#"
1995   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1996   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1997    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
1998   "
1999   {
2000     operands[3] = gen_highpart (SImode, operands[0]);
2001     operands[0] = gen_lowpart (SImode, operands[0]);
2002     operands[4] = gen_highpart (SImode, operands[1]);
2003     operands[1] = gen_lowpart (SImode, operands[1]);
2004     operands[5] = gen_highpart (SImode, operands[2]);
2005     operands[2] = gen_lowpart (SImode, operands[2]);
2006   }"
2007   [(set_attr "length" "8")
2008    (set_attr "predicable" "yes")]
2009 )
2010   
2011 (define_insn_and_split "*anddi_notzesidi_di"
2012   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2013         (and:DI (not:DI (zero_extend:DI
2014                          (match_operand:SI 2 "s_register_operand" "r,r")))
2015                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2016   "TARGET_ARM"
2017   "@
2018    bic%?\\t%Q0, %Q1, %2
2019    #"
2020   ; (not (zero_extend ...)) allows us to just copy the high word from
2021   ; operand1 to operand0.
2022   "TARGET_ARM
2023    && reload_completed
2024    && operands[0] != operands[1]"
2025   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2026    (set (match_dup 3) (match_dup 4))]
2027   "
2028   {
2029     operands[3] = gen_highpart (SImode, operands[0]);
2030     operands[0] = gen_lowpart (SImode, operands[0]);
2031     operands[4] = gen_highpart (SImode, operands[1]);
2032     operands[1] = gen_lowpart (SImode, operands[1]);
2033   }"
2034   [(set_attr "length" "4,8")
2035    (set_attr "predicable" "yes")]
2036 )
2037   
2038 (define_insn_and_split "*anddi_notsesidi_di"
2039   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2040         (and:DI (not:DI (sign_extend:DI
2041                          (match_operand:SI 2 "s_register_operand" "r,r")))
2042                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2043   "TARGET_ARM"
2044   "#"
2045   "TARGET_ARM && reload_completed"
2046   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2047    (set (match_dup 3) (and:SI (not:SI
2048                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2049                                (match_dup 4)))]
2050   "
2051   {
2052     operands[3] = gen_highpart (SImode, operands[0]);
2053     operands[0] = gen_lowpart (SImode, operands[0]);
2054     operands[4] = gen_highpart (SImode, operands[1]);
2055     operands[1] = gen_lowpart (SImode, operands[1]);
2056   }"
2057   [(set_attr "length" "8")
2058    (set_attr "predicable" "yes")]
2059 )
2060   
2061 (define_insn "andsi_notsi_si"
2062   [(set (match_operand:SI 0 "s_register_operand" "=r")
2063         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2064                 (match_operand:SI 1 "s_register_operand" "r")))]
2065   "TARGET_ARM"
2066   "bic%?\\t%0, %1, %2"
2067   [(set_attr "predicable" "yes")]
2068 )
2069
2070 (define_insn "bicsi3"
2071   [(set (match_operand:SI                 0 "register_operand" "=l")
2072         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2073                 (match_operand:SI         2 "register_operand" "0")))]
2074   "TARGET_THUMB"
2075   "bic\\t%0, %0, %1"
2076   [(set_attr "length" "2")]
2077 )
2078
2079 (define_insn "andsi_not_shiftsi_si"
2080   [(set (match_operand:SI 0 "s_register_operand" "=r")
2081         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2082                          [(match_operand:SI 2 "s_register_operand" "r")
2083                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2084                 (match_operand:SI 1 "s_register_operand" "r")))]
2085   "TARGET_ARM"
2086   "bic%?\\t%0, %1, %2%S4"
2087   [(set_attr "predicable" "yes")
2088    (set_attr "shift" "2")
2089    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2090                       (const_string "alu_shift")
2091                       (const_string "alu_shift_reg")))]
2092 )
2093
2094 (define_insn "*andsi_notsi_si_compare0"
2095   [(set (reg:CC_NOOV CC_REGNUM)
2096         (compare:CC_NOOV
2097          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2098                  (match_operand:SI 1 "s_register_operand" "r"))
2099          (const_int 0)))
2100    (set (match_operand:SI 0 "s_register_operand" "=r")
2101         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2102   "TARGET_ARM"
2103   "bic%?s\\t%0, %1, %2"
2104   [(set_attr "conds" "set")]
2105 )
2106
2107 (define_insn "*andsi_notsi_si_compare0_scratch"
2108   [(set (reg:CC_NOOV CC_REGNUM)
2109         (compare:CC_NOOV
2110          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2111                  (match_operand:SI 1 "s_register_operand" "r"))
2112          (const_int 0)))
2113    (clobber (match_scratch:SI 0 "=r"))]
2114   "TARGET_ARM"
2115   "bic%?s\\t%0, %1, %2"
2116   [(set_attr "conds" "set")]
2117 )
2118
2119 (define_insn "iordi3"
2120   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2121         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2122                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2123   "TARGET_ARM && ! TARGET_IWMMXT"
2124   "#"
2125   [(set_attr "length" "8")
2126    (set_attr "predicable" "yes")]
2127 )
2128
2129 (define_insn "*iordi_zesidi_di"
2130   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2131         (ior:DI (zero_extend:DI
2132                  (match_operand:SI 2 "s_register_operand" "r,r"))
2133                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2134   "TARGET_ARM"
2135   "@
2136    orr%?\\t%Q0, %Q1, %2
2137    #"
2138   [(set_attr "length" "4,8")
2139    (set_attr "predicable" "yes")]
2140 )
2141
2142 (define_insn "*iordi_sesidi_di"
2143   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2144         (ior:DI (sign_extend:DI
2145                  (match_operand:SI 2 "s_register_operand" "r,r"))
2146                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2147   "TARGET_ARM"
2148   "#"
2149   [(set_attr "length" "8")
2150    (set_attr "predicable" "yes")]
2151 )
2152
2153 (define_expand "iorsi3"
2154   [(set (match_operand:SI         0 "s_register_operand" "")
2155         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2156                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2157   "TARGET_EITHER"
2158   "
2159   if (GET_CODE (operands[2]) == CONST_INT)
2160     {
2161       if (TARGET_ARM)
2162         {
2163           arm_split_constant (IOR, SImode, NULL_RTX,
2164                               INTVAL (operands[2]), operands[0], operands[1],
2165                               optimize && !no_new_pseudos);
2166           DONE;
2167         }
2168       else /* TARGET_THUMB */
2169         operands [2] = force_reg (SImode, operands [2]);
2170     }
2171   "
2172 )
2173
2174 (define_insn_and_split "*arm_iorsi3"
2175   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2176         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2177                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2178   "TARGET_ARM"
2179   "@
2180    orr%?\\t%0, %1, %2
2181    #"
2182   "TARGET_ARM
2183    && GET_CODE (operands[2]) == CONST_INT
2184    && !const_ok_for_arm (INTVAL (operands[2]))"
2185   [(clobber (const_int 0))]
2186   "
2187   arm_split_constant (IOR, SImode, curr_insn, 
2188                       INTVAL (operands[2]), operands[0], operands[1], 0);
2189   DONE;
2190   "
2191   [(set_attr "length" "4,16")
2192    (set_attr "predicable" "yes")]
2193 )
2194
2195 (define_insn "*thumb_iorsi3"
2196   [(set (match_operand:SI         0 "register_operand" "=l")
2197         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2198                 (match_operand:SI 2 "register_operand" "l")))]
2199   "TARGET_THUMB"
2200   "orr\\t%0, %0, %2"
2201   [(set_attr "length" "2")]
2202 )
2203
2204 (define_peephole2
2205   [(match_scratch:SI 3 "r")
2206    (set (match_operand:SI 0 "arm_general_register_operand" "")
2207         (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2208                 (match_operand:SI 2 "const_int_operand" "")))]
2209   "TARGET_ARM
2210    && !const_ok_for_arm (INTVAL (operands[2]))
2211    && const_ok_for_arm (~INTVAL (operands[2]))"
2212   [(set (match_dup 3) (match_dup 2))
2213    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2214   ""
2215 )
2216
2217 (define_insn "*iorsi3_compare0"
2218   [(set (reg:CC_NOOV CC_REGNUM)
2219         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2220                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2221                          (const_int 0)))
2222    (set (match_operand:SI 0 "s_register_operand" "=r")
2223         (ior:SI (match_dup 1) (match_dup 2)))]
2224   "TARGET_ARM"
2225   "orr%?s\\t%0, %1, %2"
2226   [(set_attr "conds" "set")]
2227 )
2228
2229 (define_insn "*iorsi3_compare0_scratch"
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    (clobber (match_scratch:SI 0 "=r"))]
2235   "TARGET_ARM"
2236   "orr%?s\\t%0, %1, %2"
2237   [(set_attr "conds" "set")]
2238 )
2239
2240 (define_insn "xordi3"
2241   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2242         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2243                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2244   "TARGET_ARM && !TARGET_IWMMXT"
2245   "#"
2246   [(set_attr "length" "8")
2247    (set_attr "predicable" "yes")]
2248 )
2249
2250 (define_insn "*xordi_zesidi_di"
2251   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2252         (xor:DI (zero_extend:DI
2253                  (match_operand:SI 2 "s_register_operand" "r,r"))
2254                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2255   "TARGET_ARM"
2256   "@
2257    eor%?\\t%Q0, %Q1, %2
2258    #"
2259   [(set_attr "length" "4,8")
2260    (set_attr "predicable" "yes")]
2261 )
2262
2263 (define_insn "*xordi_sesidi_di"
2264   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2265         (xor:DI (sign_extend:DI
2266                  (match_operand:SI 2 "s_register_operand" "r,r"))
2267                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2268   "TARGET_ARM"
2269   "#"
2270   [(set_attr "length" "8")
2271    (set_attr "predicable" "yes")]
2272 )
2273
2274 (define_expand "xorsi3"
2275   [(set (match_operand:SI         0 "s_register_operand" "")
2276         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2277                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2278   "TARGET_EITHER"
2279   "if (TARGET_THUMB)
2280      if (GET_CODE (operands[2]) == CONST_INT)
2281        operands[2] = force_reg (SImode, operands[2]);
2282   "
2283 )
2284
2285 (define_insn "*arm_xorsi3"
2286   [(set (match_operand:SI         0 "s_register_operand" "=r")
2287         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2288                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2289   "TARGET_ARM"
2290   "eor%?\\t%0, %1, %2"
2291   [(set_attr "predicable" "yes")]
2292 )
2293
2294 (define_insn "*thumb_xorsi3"
2295   [(set (match_operand:SI         0 "register_operand" "=l")
2296         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2297                 (match_operand:SI 2 "register_operand" "l")))]
2298   "TARGET_THUMB"
2299   "eor\\t%0, %0, %2"
2300   [(set_attr "length" "2")]
2301 )
2302
2303 (define_insn "*xorsi3_compare0"
2304   [(set (reg:CC_NOOV CC_REGNUM)
2305         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2306                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2307                          (const_int 0)))
2308    (set (match_operand:SI 0 "s_register_operand" "=r")
2309         (xor:SI (match_dup 1) (match_dup 2)))]
2310   "TARGET_ARM"
2311   "eor%?s\\t%0, %1, %2"
2312   [(set_attr "conds" "set")]
2313 )
2314
2315 (define_insn "*xorsi3_compare0_scratch"
2316   [(set (reg:CC_NOOV CC_REGNUM)
2317         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2318                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2319                          (const_int 0)))]
2320   "TARGET_ARM"
2321   "teq%?\\t%0, %1"
2322   [(set_attr "conds" "set")]
2323 )
2324
2325 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2326 ; (NOT D) we can sometimes merge the final NOT into one of the following
2327 ; insns.
2328
2329 (define_split
2330   [(set (match_operand:SI 0 "s_register_operand" "")
2331         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2332                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2333                 (match_operand:SI 3 "arm_rhs_operand" "")))
2334    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2335   "TARGET_ARM"
2336   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2337                               (not:SI (match_dup 3))))
2338    (set (match_dup 0) (not:SI (match_dup 4)))]
2339   ""
2340 )
2341
2342 (define_insn "*andsi_iorsi3_notsi"
2343   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2344         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2345                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2346                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2347   "TARGET_ARM"
2348   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2349   [(set_attr "length" "8")
2350    (set_attr "predicable" "yes")]
2351 )
2352
2353 (define_split
2354   [(set (match_operand:SI 0 "s_register_operand" "")
2355         (match_operator:SI 1 "logical_binary_operator"
2356          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2357                            (match_operand:SI 3 "const_int_operand" "")
2358                            (match_operand:SI 4 "const_int_operand" ""))
2359           (match_operator:SI 9 "logical_binary_operator"
2360            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2361                          (match_operand:SI 6 "const_int_operand" ""))
2362             (match_operand:SI 7 "s_register_operand" "")])]))
2363    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2364   "TARGET_ARM
2365    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2366    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2367   [(set (match_dup 8)
2368         (match_op_dup 1
2369          [(ashift:SI (match_dup 2) (match_dup 4))
2370           (match_dup 5)]))
2371    (set (match_dup 0)
2372         (match_op_dup 1
2373          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2374           (match_dup 7)]))]
2375   "
2376   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2377 ")
2378
2379 (define_split
2380   [(set (match_operand:SI 0 "s_register_operand" "")
2381         (match_operator:SI 1 "logical_binary_operator"
2382          [(match_operator:SI 9 "logical_binary_operator"
2383            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2384                          (match_operand:SI 6 "const_int_operand" ""))
2385             (match_operand:SI 7 "s_register_operand" "")])
2386           (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2387                            (match_operand:SI 3 "const_int_operand" "")
2388                            (match_operand:SI 4 "const_int_operand" ""))]))
2389    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2390   "TARGET_ARM
2391    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2392    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2393   [(set (match_dup 8)
2394         (match_op_dup 1
2395          [(ashift:SI (match_dup 2) (match_dup 4))
2396           (match_dup 5)]))
2397    (set (match_dup 0)
2398         (match_op_dup 1
2399          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2400           (match_dup 7)]))]
2401   "
2402   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2403 ")
2404
2405 (define_split
2406   [(set (match_operand:SI 0 "s_register_operand" "")
2407         (match_operator:SI 1 "logical_binary_operator"
2408          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2409                            (match_operand:SI 3 "const_int_operand" "")
2410                            (match_operand:SI 4 "const_int_operand" ""))
2411           (match_operator:SI 9 "logical_binary_operator"
2412            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2413                          (match_operand:SI 6 "const_int_operand" ""))
2414             (match_operand:SI 7 "s_register_operand" "")])]))
2415    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2416   "TARGET_ARM
2417    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2418    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2419   [(set (match_dup 8)
2420         (match_op_dup 1
2421          [(ashift:SI (match_dup 2) (match_dup 4))
2422           (match_dup 5)]))
2423    (set (match_dup 0)
2424         (match_op_dup 1
2425          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2426           (match_dup 7)]))]
2427   "
2428   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2429 ")
2430
2431 (define_split
2432   [(set (match_operand:SI 0 "s_register_operand" "")
2433         (match_operator:SI 1 "logical_binary_operator"
2434          [(match_operator:SI 9 "logical_binary_operator"
2435            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2436                          (match_operand:SI 6 "const_int_operand" ""))
2437             (match_operand:SI 7 "s_register_operand" "")])
2438           (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2439                            (match_operand:SI 3 "const_int_operand" "")
2440                            (match_operand:SI 4 "const_int_operand" ""))]))
2441    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2442   "TARGET_ARM
2443    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2444    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2445   [(set (match_dup 8)
2446         (match_op_dup 1
2447          [(ashift:SI (match_dup 2) (match_dup 4))
2448           (match_dup 5)]))
2449    (set (match_dup 0)
2450         (match_op_dup 1
2451          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2452           (match_dup 7)]))]
2453   "
2454   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2455 ")
2456 \f
2457
2458 ;; Minimum and maximum insns
2459
2460 (define_insn "smaxsi3"
2461   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2462         (smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2463                  (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2464    (clobber (reg:CC CC_REGNUM))]
2465   "TARGET_ARM"
2466   "@
2467    cmp\\t%1, %2\;movlt\\t%0, %2
2468    cmp\\t%1, %2\;movge\\t%0, %1
2469    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2470   [(set_attr "conds" "clob")
2471    (set_attr "length" "8,8,12")]
2472 )
2473
2474 (define_insn "sminsi3"
2475   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2476         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2477                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2478    (clobber (reg:CC CC_REGNUM))]
2479   "TARGET_ARM"
2480   "@
2481    cmp\\t%1, %2\;movge\\t%0, %2
2482    cmp\\t%1, %2\;movlt\\t%0, %1
2483    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2484   [(set_attr "conds" "clob")
2485    (set_attr "length" "8,8,12")]
2486 )
2487
2488 (define_insn "umaxsi3"
2489   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2490         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2491                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2492    (clobber (reg:CC CC_REGNUM))]
2493   "TARGET_ARM"
2494   "@
2495    cmp\\t%1, %2\;movcc\\t%0, %2
2496    cmp\\t%1, %2\;movcs\\t%0, %1
2497    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2498   [(set_attr "conds" "clob")
2499    (set_attr "length" "8,8,12")]
2500 )
2501
2502 (define_insn "uminsi3"
2503   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2504         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2505                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2506    (clobber (reg:CC CC_REGNUM))]
2507   "TARGET_ARM"
2508   "@
2509    cmp\\t%1, %2\;movcs\\t%0, %2
2510    cmp\\t%1, %2\;movcc\\t%0, %1
2511    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2512   [(set_attr "conds" "clob")
2513    (set_attr "length" "8,8,12")]
2514 )
2515
2516 (define_insn "*store_minmaxsi"
2517   [(set (match_operand:SI 0 "memory_operand" "=m")
2518         (match_operator:SI 3 "minmax_operator"
2519          [(match_operand:SI 1 "s_register_operand" "r")
2520           (match_operand:SI 2 "s_register_operand" "r")]))
2521    (clobber (reg:CC CC_REGNUM))]
2522   "TARGET_ARM"
2523   "*
2524   operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2525                                 operands[1], operands[2]);
2526   output_asm_insn (\"cmp\\t%1, %2\", operands);
2527   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2528   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2529   return \"\";
2530   "
2531   [(set_attr "conds" "clob")
2532    (set_attr "length" "12")
2533    (set_attr "type" "store1")]
2534 )
2535
2536 ; Reject the frame pointer in operand[1], since reloading this after
2537 ; it has been eliminated can cause carnage.
2538 (define_insn "*minmax_arithsi"
2539   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2540         (match_operator:SI 4 "shiftable_operator"
2541          [(match_operator:SI 5 "minmax_operator"
2542            [(match_operand:SI 2 "s_register_operand" "r,r")
2543             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2544           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2545    (clobber (reg:CC CC_REGNUM))]
2546   "TARGET_ARM && !arm_eliminable_register (operands[1])"
2547   "*
2548   {
2549     enum rtx_code code = GET_CODE (operands[4]);
2550
2551     operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2552                                   operands[2], operands[3]);
2553     output_asm_insn (\"cmp\\t%2, %3\", operands);
2554     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2555     if (which_alternative != 0 || operands[3] != const0_rtx
2556         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2557       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2558     return \"\";
2559   }"
2560   [(set_attr "conds" "clob")
2561    (set_attr "length" "12")]
2562 )
2563
2564 \f
2565 ;; Shift and rotation insns
2566
2567 (define_expand "ashldi3"
2568   [(set (match_operand:DI            0 "s_register_operand" "")
2569         (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2570                    (match_operand:SI 2 "reg_or_int_operand" "")))]
2571   "TARGET_ARM"
2572   "
2573   if (GET_CODE (operands[2]) == CONST_INT)
2574     {
2575       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2576         {
2577           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2578           DONE;
2579         }
2580         /* Ideally we shouldn't fail here if we could know that operands[1] 
2581            ends up already living in an iwmmxt register. Otherwise it's
2582            cheaper to have the alternate code being generated than moving
2583            values to iwmmxt regs and back.  */
2584         FAIL;
2585     }
2586   else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2587     FAIL;
2588   "
2589 )
2590
2591 (define_insn "arm_ashldi3_1bit"
2592   [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
2593         (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2594                    (const_int 1)))
2595    (clobber (reg:CC CC_REGNUM))]
2596   "TARGET_ARM"
2597   "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2598   [(set_attr "conds" "clob")
2599    (set_attr "length" "8")]
2600 )
2601
2602 (define_expand "ashlsi3"
2603   [(set (match_operand:SI            0 "s_register_operand" "")
2604         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2605                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2606   "TARGET_EITHER"
2607   "
2608   if (GET_CODE (operands[2]) == CONST_INT
2609       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2610     {
2611       emit_insn (gen_movsi (operands[0], const0_rtx));
2612       DONE;
2613     }
2614   "
2615 )
2616
2617 (define_insn "*thumb_ashlsi3"
2618   [(set (match_operand:SI            0 "register_operand" "=l,l")
2619         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2620                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2621   "TARGET_THUMB"
2622   "lsl\\t%0, %1, %2"
2623   [(set_attr "length" "2")]
2624 )
2625
2626 (define_expand "ashrdi3"
2627   [(set (match_operand:DI              0 "s_register_operand" "")
2628         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2629                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2630   "TARGET_ARM"
2631   "
2632   if (GET_CODE (operands[2]) == CONST_INT)
2633     {
2634       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2635         {
2636           emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2637           DONE;
2638         }
2639         /* Ideally we shouldn't fail here if we could know that operands[1] 
2640            ends up already living in an iwmmxt register. Otherwise it's
2641            cheaper to have the alternate code being generated than moving
2642            values to iwmmxt regs and back.  */
2643         FAIL;
2644     }
2645   else if (!TARGET_REALLY_IWMMXT)
2646     FAIL;
2647   "
2648 )
2649
2650 (define_insn "arm_ashrdi3_1bit"
2651   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2652         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2653                      (const_int 1)))
2654    (clobber (reg:CC CC_REGNUM))]
2655   "TARGET_ARM"
2656   "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2657   [(set_attr "conds" "clob")
2658    (set_attr "length" "8")]
2659 )
2660
2661 (define_expand "ashrsi3"
2662   [(set (match_operand:SI              0 "s_register_operand" "")
2663         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2664                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2665   "TARGET_EITHER"
2666   "
2667   if (GET_CODE (operands[2]) == CONST_INT
2668       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2669     operands[2] = GEN_INT (31);
2670   "
2671 )
2672
2673 (define_insn "*thumb_ashrsi3"
2674   [(set (match_operand:SI              0 "register_operand" "=l,l")
2675         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2676                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2677   "TARGET_THUMB"
2678   "asr\\t%0, %1, %2"
2679   [(set_attr "length" "2")]
2680 )
2681
2682 (define_expand "lshrdi3"
2683   [(set (match_operand:DI              0 "s_register_operand" "")
2684         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2685                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2686   "TARGET_ARM"
2687   "
2688   if (GET_CODE (operands[2]) == CONST_INT)
2689     {
2690       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2691         {
2692           emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2693           DONE;
2694         }
2695         /* Ideally we shouldn't fail here if we could know that operands[1] 
2696            ends up already living in an iwmmxt register. Otherwise it's
2697            cheaper to have the alternate code being generated than moving
2698            values to iwmmxt regs and back.  */
2699         FAIL;
2700     }
2701   else if (!TARGET_REALLY_IWMMXT)
2702     FAIL;
2703   "
2704 )
2705
2706 (define_insn "arm_lshrdi3_1bit"
2707   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2708         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2709                      (const_int 1)))
2710    (clobber (reg:CC CC_REGNUM))]
2711   "TARGET_ARM"
2712   "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2713   [(set_attr "conds" "clob")
2714    (set_attr "length" "8")]
2715 )
2716
2717 (define_expand "lshrsi3"
2718   [(set (match_operand:SI              0 "s_register_operand" "")
2719         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2720                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2721   "TARGET_EITHER"
2722   "
2723   if (GET_CODE (operands[2]) == CONST_INT
2724       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2725     {
2726       emit_insn (gen_movsi (operands[0], const0_rtx));
2727       DONE;
2728     }
2729   "
2730 )
2731
2732 (define_insn "*thumb_lshrsi3"
2733   [(set (match_operand:SI              0 "register_operand" "=l,l")
2734         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2735                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2736   "TARGET_THUMB"
2737   "lsr\\t%0, %1, %2"
2738   [(set_attr "length" "2")]
2739 )
2740
2741 (define_expand "rotlsi3"
2742   [(set (match_operand:SI              0 "s_register_operand" "")
2743         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2744                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2745   "TARGET_ARM"
2746   "
2747   if (GET_CODE (operands[2]) == CONST_INT)
2748     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2749   else
2750     {
2751       rtx reg = gen_reg_rtx (SImode);
2752       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2753       operands[2] = reg;
2754     }
2755   "
2756 )
2757
2758 (define_expand "rotrsi3"
2759   [(set (match_operand:SI              0 "s_register_operand" "")
2760         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2761                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2762   "TARGET_EITHER"
2763   "
2764   if (TARGET_ARM)
2765     {
2766       if (GET_CODE (operands[2]) == CONST_INT
2767           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2768         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2769     }
2770   else /* TARGET_THUMB */
2771     {
2772       if (GET_CODE (operands [2]) == CONST_INT)
2773         operands [2] = force_reg (SImode, operands[2]);
2774     }
2775   "
2776 )
2777
2778 (define_insn "*thumb_rotrsi3"
2779   [(set (match_operand:SI              0 "register_operand" "=l")
2780         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2781                      (match_operand:SI 2 "register_operand" "l")))]
2782   "TARGET_THUMB"
2783   "ror\\t%0, %0, %2"
2784   [(set_attr "length" "2")]
2785 )
2786
2787 (define_insn "*arm_shiftsi3"
2788   [(set (match_operand:SI   0 "s_register_operand" "=r")
2789         (match_operator:SI  3 "shift_operator"
2790          [(match_operand:SI 1 "s_register_operand"  "r")
2791           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2792   "TARGET_ARM"
2793   "mov%?\\t%0, %1%S3"
2794   [(set_attr "predicable" "yes")
2795    (set_attr "shift" "1")
2796    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2797                       (const_string "alu_shift")
2798                       (const_string "alu_shift_reg")))]
2799 )
2800
2801 (define_insn "*shiftsi3_compare0"
2802   [(set (reg:CC_NOOV CC_REGNUM)
2803         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2804                           [(match_operand:SI 1 "s_register_operand" "r")
2805                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2806                          (const_int 0)))
2807    (set (match_operand:SI 0 "s_register_operand" "=r")
2808         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2809   "TARGET_ARM"
2810   "mov%?s\\t%0, %1%S3"
2811   [(set_attr "conds" "set")
2812    (set_attr "shift" "1")
2813    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2814                       (const_string "alu_shift")
2815                       (const_string "alu_shift_reg")))]
2816 )
2817
2818 (define_insn "*shiftsi3_compare0_scratch"
2819   [(set (reg:CC_NOOV CC_REGNUM)
2820         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2821                           [(match_operand:SI 1 "s_register_operand" "r")
2822                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2823                          (const_int 0)))
2824    (clobber (match_scratch:SI 0 "=r"))]
2825   "TARGET_ARM"
2826   "mov%?s\\t%0, %1%S3"
2827   [(set_attr "conds" "set")
2828    (set_attr "shift" "1")]
2829 )
2830
2831 (define_insn "*notsi_shiftsi"
2832   [(set (match_operand:SI 0 "s_register_operand" "=r")
2833         (not:SI (match_operator:SI 3 "shift_operator"
2834                  [(match_operand:SI 1 "s_register_operand" "r")
2835                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2836   "TARGET_ARM"
2837   "mvn%?\\t%0, %1%S3"
2838   [(set_attr "predicable" "yes")
2839    (set_attr "shift" "1")
2840    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2841                       (const_string "alu_shift")
2842                       (const_string "alu_shift_reg")))]
2843 )
2844
2845 (define_insn "*notsi_shiftsi_compare0"
2846   [(set (reg:CC_NOOV CC_REGNUM)
2847         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2848                           [(match_operand:SI 1 "s_register_operand" "r")
2849                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2850                          (const_int 0)))
2851    (set (match_operand:SI 0 "s_register_operand" "=r")
2852         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2853   "TARGET_ARM"
2854   "mvn%?s\\t%0, %1%S3"
2855   [(set_attr "conds" "set")
2856    (set_attr "shift" "1")
2857    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2858                       (const_string "alu_shift")
2859                       (const_string "alu_shift_reg")))]
2860 )
2861
2862 (define_insn "*not_shiftsi_compare0_scratch"
2863   [(set (reg:CC_NOOV CC_REGNUM)
2864         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2865                           [(match_operand:SI 1 "s_register_operand" "r")
2866                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2867                          (const_int 0)))
2868    (clobber (match_scratch:SI 0 "=r"))]
2869   "TARGET_ARM"
2870   "mvn%?s\\t%0, %1%S3"
2871   [(set_attr "conds" "set")
2872    (set_attr "shift" "1")
2873    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2874                       (const_string "alu_shift")
2875                       (const_string "alu_shift_reg")))]
2876 )
2877
2878 ;; We don't really have extzv, but defining this using shifts helps
2879 ;; to reduce register pressure later on.
2880
2881 (define_expand "extzv"
2882   [(set (match_dup 4)
2883         (ashift:SI (match_operand:SI   1 "register_operand" "")
2884                    (match_operand:SI   2 "const_int_operand" "")))
2885    (set (match_operand:SI              0 "register_operand" "")
2886         (lshiftrt:SI (match_dup 4)
2887                      (match_operand:SI 3 "const_int_operand" "")))]
2888   "TARGET_THUMB"
2889   "
2890   {
2891     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2892     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2893     
2894     operands[3] = GEN_INT (rshift);
2895     
2896     if (lshift == 0)
2897       {
2898         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2899         DONE;
2900       }
2901       
2902     operands[2] = GEN_INT (lshift);
2903     operands[4] = gen_reg_rtx (SImode);
2904   }"
2905 )
2906
2907 \f
2908 ;; Unary arithmetic insns
2909
2910 (define_expand "negdi2"
2911  [(parallel
2912    [(set (match_operand:DI          0 "s_register_operand" "")
2913           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2914     (clobber (reg:CC CC_REGNUM))])]
2915   "TARGET_EITHER"
2916   "
2917   if (TARGET_THUMB)
2918     {
2919       if (GET_CODE (operands[1]) != REG)
2920         operands[1] = force_reg (SImode, operands[1]);
2921      }
2922   "
2923 )
2924
2925 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2926 ;; The second alternative is to allow the common case of a *full* overlap.
2927 (define_insn "*arm_negdi2"
2928   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2929         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2930    (clobber (reg:CC CC_REGNUM))]
2931   "TARGET_ARM"
2932   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2933   [(set_attr "conds" "clob")
2934    (set_attr "length" "8")]
2935 )
2936
2937 (define_insn "*thumb_negdi2"
2938   [(set (match_operand:DI         0 "register_operand" "=&l")
2939         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
2940    (clobber (reg:CC CC_REGNUM))]
2941   "TARGET_THUMB"
2942   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2943   [(set_attr "length" "6")]
2944 )
2945
2946 (define_expand "negsi2"
2947   [(set (match_operand:SI         0 "s_register_operand" "")
2948         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2949   "TARGET_EITHER"
2950   ""
2951 )
2952
2953 (define_insn "*arm_negsi2"
2954   [(set (match_operand:SI         0 "s_register_operand" "=r")
2955         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2956   "TARGET_ARM"
2957   "rsb%?\\t%0, %1, #0"
2958   [(set_attr "predicable" "yes")]
2959 )
2960
2961 (define_insn "*thumb_negsi2"
2962   [(set (match_operand:SI         0 "register_operand" "=l")
2963         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2964   "TARGET_THUMB"
2965   "neg\\t%0, %1"
2966   [(set_attr "length" "2")]
2967 )
2968
2969 (define_expand "negsf2"
2970   [(set (match_operand:SF         0 "s_register_operand" "")
2971         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2972   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2973   ""
2974 )
2975
2976 (define_expand "negdf2"
2977   [(set (match_operand:DF         0 "s_register_operand" "")
2978         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2979   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2980   "")
2981
2982 ;; abssi2 doesn't really clobber the condition codes if a different register
2983 ;; is being set.  To keep things simple, assume during rtl manipulations that
2984 ;; it does, but tell the final scan operator the truth.  Similarly for
2985 ;; (neg (abs...))
2986
2987 (define_expand "abssi2"
2988   [(parallel
2989     [(set (match_operand:SI         0 "s_register_operand" "")
2990           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
2991      (clobber (reg:CC CC_REGNUM))])]
2992   "TARGET_ARM"
2993   "")
2994
2995 (define_insn "*arm_abssi2"
2996   [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
2997         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2998    (clobber (reg:CC CC_REGNUM))]
2999   "TARGET_ARM"
3000   "@
3001    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3002    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3003   [(set_attr "conds" "clob,*")
3004    (set_attr "shift" "1")
3005    ;; predicable can't be set based on the variant, so left as no
3006    (set_attr "length" "8")]
3007 )
3008
3009 (define_insn "*neg_abssi2"
3010   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3011         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3012    (clobber (reg:CC CC_REGNUM))]
3013   "TARGET_ARM"
3014   "@
3015    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3016    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3017   [(set_attr "conds" "clob,*")
3018    (set_attr "shift" "1")
3019    ;; predicable can't be set based on the variant, so left as no
3020    (set_attr "length" "8")]
3021 )
3022
3023 (define_expand "abssf2"
3024   [(set (match_operand:SF         0 "s_register_operand" "")
3025         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3026   "TARGET_ARM && TARGET_HARD_FLOAT"
3027   "")
3028
3029 (define_expand "absdf2"
3030   [(set (match_operand:DF         0 "s_register_operand" "")
3031         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3032   "TARGET_ARM && TARGET_HARD_FLOAT"
3033   "")
3034
3035 (define_expand "sqrtsf2"
3036   [(set (match_operand:SF 0 "s_register_operand" "")
3037         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3038   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3039   "")
3040
3041 (define_expand "sqrtdf2"
3042   [(set (match_operand:DF 0 "s_register_operand" "")
3043         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3044   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3045   "")
3046
3047 (define_insn_and_split "one_cmpldi2"
3048   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3049         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3050   "TARGET_ARM"
3051   "#"
3052   "TARGET_ARM && reload_completed"
3053   [(set (match_dup 0) (not:SI (match_dup 1)))
3054    (set (match_dup 2) (not:SI (match_dup 3)))]
3055   "
3056   {
3057     operands[2] = gen_highpart (SImode, operands[0]);
3058     operands[0] = gen_lowpart (SImode, operands[0]);
3059     operands[3] = gen_highpart (SImode, operands[1]);
3060     operands[1] = gen_lowpart (SImode, operands[1]);
3061   }"
3062   [(set_attr "length" "8")
3063    (set_attr "predicable" "yes")]
3064 )
3065
3066 (define_expand "one_cmplsi2"
3067   [(set (match_operand:SI         0 "s_register_operand" "")
3068         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3069   "TARGET_EITHER"
3070   ""
3071 )
3072
3073 (define_insn "*arm_one_cmplsi2"
3074   [(set (match_operand:SI         0 "s_register_operand" "=r")
3075         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3076   "TARGET_ARM"
3077   "mvn%?\\t%0, %1"
3078   [(set_attr "predicable" "yes")]
3079 )
3080
3081 (define_insn "*thumb_one_cmplsi2"
3082   [(set (match_operand:SI         0 "register_operand" "=l")
3083         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3084   "TARGET_THUMB"
3085   "mvn\\t%0, %1"
3086   [(set_attr "length" "2")]
3087 )
3088
3089 (define_insn "*notsi_compare0"
3090   [(set (reg:CC_NOOV CC_REGNUM)
3091         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3092                          (const_int 0)))
3093    (set (match_operand:SI 0 "s_register_operand" "=r")
3094         (not:SI (match_dup 1)))]
3095   "TARGET_ARM"
3096   "mvn%?s\\t%0, %1"
3097   [(set_attr "conds" "set")]
3098 )
3099
3100 (define_insn "*notsi_compare0_scratch"
3101   [(set (reg:CC_NOOV CC_REGNUM)
3102         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3103                          (const_int 0)))
3104    (clobber (match_scratch:SI 0 "=r"))]
3105   "TARGET_ARM"
3106   "mvn%?s\\t%0, %1"
3107   [(set_attr "conds" "set")]
3108 )
3109 \f
3110 ;; Fixed <--> Floating conversion insns
3111
3112 (define_expand "floatsisf2"
3113   [(set (match_operand:SF           0 "s_register_operand" "")
3114         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3115   "TARGET_ARM && TARGET_HARD_FLOAT"
3116   "
3117   if (TARGET_MAVERICK)
3118     {
3119       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3120       DONE;
3121     }
3122 ")
3123
3124 (define_expand "floatsidf2"
3125   [(set (match_operand:DF           0 "s_register_operand" "")
3126         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3127   "TARGET_ARM && TARGET_HARD_FLOAT"
3128   "
3129   if (TARGET_MAVERICK)
3130     {
3131       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3132       DONE;
3133     }
3134 ")
3135
3136 (define_expand "fix_truncsfsi2"
3137   [(set (match_operand:SI         0 "s_register_operand" "")
3138         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3139   "TARGET_ARM && TARGET_HARD_FLOAT"
3140   "
3141   if (TARGET_MAVERICK)
3142     {
3143       if (!cirrus_fp_register (operands[0], SImode))
3144         operands[0] = force_reg (SImode, operands[0]);
3145       if (!cirrus_fp_register (operands[1], SFmode))
3146         operands[1] = force_reg (SFmode, operands[0]);
3147       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3148       DONE;
3149     }
3150 ")
3151
3152 (define_expand "fix_truncdfsi2"
3153   [(set (match_operand:SI         0 "s_register_operand" "")
3154         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3155   "TARGET_ARM && TARGET_HARD_FLOAT"
3156   "
3157   if (TARGET_MAVERICK)
3158     {
3159       if (!cirrus_fp_register (operands[1], DFmode))
3160         operands[1] = force_reg (DFmode, operands[0]);
3161       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3162       DONE;
3163     }
3164 ")
3165
3166 ;; Truncation insns
3167
3168 (define_expand "truncdfsf2"
3169   [(set (match_operand:SF  0 "s_register_operand" "")
3170         (float_truncate:SF
3171          (match_operand:DF 1 "s_register_operand" "")))]
3172   "TARGET_ARM && TARGET_HARD_FLOAT"
3173   ""
3174 )
3175 \f
3176 ;; Zero and sign extension instructions.
3177
3178 (define_insn "zero_extendsidi2"
3179   [(set (match_operand:DI 0 "s_register_operand" "=r")
3180         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3181   "TARGET_ARM"
3182   "*
3183     if (REGNO (operands[1])
3184         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3185       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3186     return \"mov%?\\t%R0, #0\";
3187   "
3188   [(set_attr "length" "8")
3189    (set_attr "predicable" "yes")]
3190 )
3191
3192 (define_insn "zero_extendqidi2"
3193   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3194         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3195   "TARGET_ARM"
3196   "@
3197    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3198    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3199   [(set_attr "length" "8")
3200    (set_attr "predicable" "yes")
3201    (set_attr "type" "*,load_byte")
3202    (set_attr "pool_range" "*,4092")
3203    (set_attr "neg_pool_range" "*,4084")]
3204 )
3205
3206 (define_insn "extendsidi2"
3207   [(set (match_operand:DI 0 "s_register_operand" "=r")
3208         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3209   "TARGET_ARM"
3210   "*
3211     if (REGNO (operands[1])
3212         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3213       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3214     return \"mov%?\\t%R0, %Q0, asr #31\";
3215   "
3216   [(set_attr "length" "8")
3217    (set_attr "shift" "1")
3218    (set_attr "predicable" "yes")]
3219 )
3220
3221 (define_expand "zero_extendhisi2"
3222   [(set (match_dup 2)
3223         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3224                    (const_int 16)))
3225    (set (match_operand:SI 0 "s_register_operand" "")
3226         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3227   "TARGET_EITHER"
3228   "
3229   {
3230     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3231       {
3232         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3233                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3234         DONE;
3235       }
3236
3237     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3238       {
3239         emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3240         DONE;
3241       }
3242
3243     if (!s_register_operand (operands[1], HImode))
3244       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3245
3246     if (arm_arch6)
3247       {
3248         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3249                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3250         DONE;
3251       }
3252
3253     operands[1] = gen_lowpart (SImode, operands[1]);
3254     operands[2] = gen_reg_rtx (SImode);
3255   }"
3256 )
3257
3258 (define_insn "*thumb_zero_extendhisi2"
3259   [(set (match_operand:SI 0 "register_operand" "=l")
3260         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3261   "TARGET_THUMB && !arm_arch6"
3262   "*
3263   rtx mem = XEXP (operands[1], 0);
3264
3265   if (GET_CODE (mem) == CONST)
3266     mem = XEXP (mem, 0);
3267     
3268   if (GET_CODE (mem) == LABEL_REF)
3269     return \"ldr\\t%0, %1\";
3270     
3271   if (GET_CODE (mem) == PLUS)
3272     {
3273       rtx a = XEXP (mem, 0);
3274       rtx b = XEXP (mem, 1);
3275
3276       /* This can happen due to bugs in reload.  */
3277       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3278         {
3279           rtx ops[2];
3280           ops[0] = operands[0];
3281           ops[1] = a;
3282       
3283           output_asm_insn (\"mov        %0, %1\", ops);
3284
3285           XEXP (mem, 0) = operands[0];
3286        }
3287
3288       else if (   GET_CODE (a) == LABEL_REF
3289                && GET_CODE (b) == CONST_INT)
3290         return \"ldr\\t%0, %1\";
3291     }
3292     
3293   return \"ldrh\\t%0, %1\";
3294   "
3295   [(set_attr "length" "4")
3296    (set_attr "type" "load_byte")
3297    (set_attr "pool_range" "60")]
3298 )
3299
3300 (define_insn "*thumb_zero_extendhisi2_v6"
3301   [(set (match_operand:SI 0 "register_operand" "=l,l")
3302         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3303   "TARGET_THUMB && arm_arch6"
3304   "*
3305   rtx mem;
3306
3307   if (which_alternative == 0)
3308     return \"uxth\\t%0, %1\";
3309
3310   mem = XEXP (operands[1], 0);
3311
3312   if (GET_CODE (mem) == CONST)
3313     mem = XEXP (mem, 0);
3314     
3315   if (GET_CODE (mem) == LABEL_REF)
3316     return \"ldr\\t%0, %1\";
3317     
3318   if (GET_CODE (mem) == PLUS)
3319     {
3320       rtx a = XEXP (mem, 0);
3321       rtx b = XEXP (mem, 1);
3322
3323       /* This can happen due to bugs in reload.  */
3324       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3325         {
3326           rtx ops[2];
3327           ops[0] = operands[0];
3328           ops[1] = a;
3329       
3330           output_asm_insn (\"mov        %0, %1\", ops);
3331
3332           XEXP (mem, 0) = operands[0];
3333        }
3334
3335       else if (   GET_CODE (a) == LABEL_REF
3336                && GET_CODE (b) == CONST_INT)
3337         return \"ldr\\t%0, %1\";
3338     }
3339     
3340   return \"ldrh\\t%0, %1\";
3341   "
3342   [(set_attr "length" "2,4")
3343    (set_attr "type" "alu_shift,load_byte")
3344    (set_attr "pool_range" "*,60")]
3345 )
3346
3347 (define_insn "*arm_zero_extendhisi2"
3348   [(set (match_operand:SI 0 "s_register_operand" "=r")
3349         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3350   "TARGET_ARM && arm_arch4 && !arm_arch6"
3351   "ldr%?h\\t%0, %1"
3352   [(set_attr "type" "load_byte")
3353    (set_attr "predicable" "yes")
3354    (set_attr "pool_range" "256")
3355    (set_attr "neg_pool_range" "244")]
3356 )
3357
3358 (define_insn "*arm_zero_extendhisi2_v6"
3359   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3360         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3361   "TARGET_ARM && arm_arch6"
3362   "@
3363    uxth%?\\t%0, %1
3364    ldr%?h\\t%0, %1"
3365   [(set_attr "type" "alu_shift,load_byte")
3366    (set_attr "predicable" "yes")
3367    (set_attr "pool_range" "*,256")
3368    (set_attr "neg_pool_range" "*,244")]
3369 )
3370
3371 (define_insn "*arm_zero_extendhisi2addsi"
3372   [(set (match_operand:SI 0 "s_register_operand" "=r")
3373         (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3374                  (match_operand:SI 2 "s_register_operand" "r")))]
3375   "TARGET_ARM && arm_arch6"
3376   "uxtah%?\\t%0, %2, %1"
3377   [(set_attr "type" "alu_shift")
3378    (set_attr "predicable" "yes")]
3379 )
3380
3381 (define_split
3382   [(set (match_operand:SI 0 "s_register_operand" "")
3383         (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3384    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3385   "TARGET_ARM && (!arm_arch4)"
3386   [(set (match_dup 2) (match_dup 1))
3387    (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3388   "
3389   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3390     FAIL;
3391   "
3392 )
3393
3394 (define_split
3395   [(set (match_operand:SI 0 "s_register_operand" "")
3396         (match_operator:SI 3 "shiftable_operator"
3397          [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3398           (match_operand:SI 4 "s_register_operand" "")]))
3399    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3400   "TARGET_ARM && (!arm_arch4)"
3401   [(set (match_dup 2) (match_dup 1))
3402    (set (match_dup 0)
3403         (match_op_dup 3
3404          [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3405   "
3406   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3407     FAIL;
3408   "
3409 )
3410
3411 (define_expand "zero_extendqisi2"
3412   [(set (match_operand:SI 0 "s_register_operand" "")
3413         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3414   "TARGET_EITHER"
3415   "
3416   if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3417     {
3418       if (TARGET_ARM)
3419         {
3420           emit_insn (gen_andsi3 (operands[0],
3421                                  gen_lowpart (SImode, operands[1]),
3422                                  GEN_INT (255)));
3423         }
3424       else /* TARGET_THUMB */
3425         {
3426           rtx temp = gen_reg_rtx (SImode);
3427           rtx ops[3];
3428           
3429           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3430           operands[1] = gen_lowpart (SImode, operands[1]);
3431
3432           ops[0] = temp;
3433           ops[1] = operands[1];
3434           ops[2] = GEN_INT (24);
3435
3436           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3437                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3438           
3439           ops[0] = operands[0];
3440           ops[1] = temp;
3441           ops[2] = GEN_INT (24);
3442
3443           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3444                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3445         }
3446       DONE;
3447     }
3448   "
3449 )
3450
3451 (define_insn "*thumb_zero_extendqisi2"
3452   [(set (match_operand:SI 0 "register_operand" "=l")
3453         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3454   "TARGET_THUMB && !arm_arch6"
3455   "ldrb\\t%0, %1"
3456   [(set_attr "length" "2")
3457    (set_attr "type" "load_byte")
3458    (set_attr "pool_range" "32")]
3459 )
3460
3461 (define_insn "*thumb_zero_extendqisi2_v6"
3462   [(set (match_operand:SI 0 "register_operand" "=l,l")
3463         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3464   "TARGET_THUMB && arm_arch6"
3465   "@
3466    uxtb\\t%0, %1
3467    ldrb\\t%0, %1"
3468   [(set_attr "length" "2,2")
3469    (set_attr "type" "alu_shift,load_byte")
3470    (set_attr "pool_range" "*,32")]
3471 )
3472
3473 (define_insn "*arm_zero_extendqisi2"
3474   [(set (match_operand:SI 0 "s_register_operand" "=r")
3475         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3476   "TARGET_ARM && !arm_arch6"
3477   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3478   [(set_attr "type" "load_byte")
3479    (set_attr "predicable" "yes")
3480    (set_attr "pool_range" "4096")
3481    (set_attr "neg_pool_range" "4084")]
3482 )
3483
3484 (define_insn "*arm_zero_extendqisi2_v6"
3485   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3486         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3487   "TARGET_ARM && arm_arch6"
3488   "@
3489    uxtb%?\\t%0, %1
3490    ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3491   [(set_attr "type" "alu_shift,load_byte")
3492    (set_attr "predicable" "yes")
3493    (set_attr "pool_range" "*,4096")
3494    (set_attr "neg_pool_range" "*,4084")]
3495 )
3496
3497 (define_insn "*arm_zero_extendqisi2addsi"
3498   [(set (match_operand:SI 0 "s_register_operand" "=r")
3499         (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3500                  (match_operand:SI 2 "s_register_operand" "r")))]
3501   "TARGET_ARM && arm_arch6"
3502   "uxtab%?\\t%0, %2, %1"
3503   [(set_attr "predicable" "yes")
3504    (set_attr "type" "alu_shift")]
3505 )
3506
3507 (define_split
3508   [(set (match_operand:SI 0 "s_register_operand" "")
3509         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3510    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3511   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3512   [(set (match_dup 2) (match_dup 1))
3513    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3514   ""
3515 )
3516
3517 (define_insn "*compareqi_eq0"
3518   [(set (reg:CC_Z CC_REGNUM)
3519         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3520                          (const_int 0)))]
3521   "TARGET_ARM"
3522   "tst\\t%0, #255"
3523   [(set_attr "conds" "set")]
3524 )
3525
3526 (define_expand "extendhisi2"
3527   [(set (match_dup 2)
3528         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3529                    (const_int 16)))
3530    (set (match_operand:SI 0 "s_register_operand" "")
3531         (ashiftrt:SI (match_dup 2)
3532                      (const_int 16)))]
3533   "TARGET_EITHER"
3534   "
3535   {
3536     if (GET_CODE (operands[1]) == MEM)
3537       {
3538         if (TARGET_THUMB)
3539           {
3540             emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3541             DONE;
3542           }
3543         else if (arm_arch4)
3544           {
3545             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3546                        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3547             DONE;
3548           }
3549       }
3550
3551     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3552       {
3553         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3554         DONE;
3555       }
3556
3557     if (!s_register_operand (operands[1], HImode))
3558       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3559
3560     if (arm_arch6)
3561       {
3562         if (TARGET_THUMB)
3563           emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3564         else
3565           emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3566                      gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3567
3568         DONE;
3569       }
3570
3571     operands[1] = gen_lowpart (SImode, operands[1]);
3572     operands[2] = gen_reg_rtx (SImode);
3573   }"
3574 )
3575
3576 (define_insn "thumb_extendhisi2"
3577   [(set (match_operand:SI 0 "register_operand" "=l")
3578         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3579    (clobber (match_scratch:SI 2 "=&l"))]
3580   "TARGET_THUMB && !arm_arch6"
3581   "*
3582   {
3583     rtx ops[4];
3584     rtx mem = XEXP (operands[1], 0);
3585
3586     /* This code used to try to use 'V', and fix the address only if it was
3587        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3588        range of QImode offsets, and offsettable_address_p does a QImode
3589        address check.  */
3590        
3591     if (GET_CODE (mem) == CONST)
3592       mem = XEXP (mem, 0);
3593     
3594     if (GET_CODE (mem) == LABEL_REF)
3595       return \"ldr\\t%0, %1\";
3596     
3597     if (GET_CODE (mem) == PLUS)
3598       {
3599         rtx a = XEXP (mem, 0);
3600         rtx b = XEXP (mem, 1);
3601
3602         if (GET_CODE (a) == LABEL_REF
3603             && GET_CODE (b) == CONST_INT)
3604           return \"ldr\\t%0, %1\";
3605
3606         if (GET_CODE (b) == REG)
3607           return \"ldrsh\\t%0, %1\";
3608           
3609         ops[1] = a;
3610         ops[2] = b;
3611       }
3612     else
3613       {
3614         ops[1] = mem;
3615         ops[2] = const0_rtx;
3616       }
3617       
3618     if (GET_CODE (ops[1]) != REG)
3619       {
3620         debug_rtx (ops[1]);
3621         abort ();
3622       }
3623
3624     ops[0] = operands[0];
3625     ops[3] = operands[2];
3626     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3627     return \"\";
3628   }"
3629   [(set_attr "length" "4")
3630    (set_attr "type" "load_byte")
3631    (set_attr "pool_range" "1020")]
3632 )
3633
3634 ;; We used to have an early-clobber on the scratch register here.
3635 ;; However, there's a bug somewhere in reload which means that this
3636 ;; can be partially ignored during spill allocation if the memory
3637 ;; address also needs reloading; this causes an abort later on when
3638 ;; we try to verify the operands.  Fortunately, we don't really need
3639 ;; the early-clobber: we can always use operand 0 if operand 2
3640 ;; overlaps the address.
3641 (define_insn "*thumb_extendhisi2_insn_v6"
3642   [(set (match_operand:SI 0 "register_operand" "=l,l")
3643         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3644    (clobber (match_scratch:SI 2 "=X,l"))]
3645   "TARGET_THUMB && arm_arch6"
3646   "*
3647   {
3648     rtx ops[4];
3649     rtx mem;
3650
3651     if (which_alternative == 0)
3652       return \"sxth\\t%0, %1\";
3653
3654     mem = XEXP (operands[1], 0);
3655
3656     /* This code used to try to use 'V', and fix the address only if it was
3657        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3658        range of QImode offsets, and offsettable_address_p does a QImode
3659        address check.  */
3660        
3661     if (GET_CODE (mem) == CONST)
3662       mem = XEXP (mem, 0);
3663     
3664     if (GET_CODE (mem) == LABEL_REF)
3665       return \"ldr\\t%0, %1\";
3666     
3667     if (GET_CODE (mem) == PLUS)
3668       {
3669         rtx a = XEXP (mem, 0);
3670         rtx b = XEXP (mem, 1);
3671
3672         if (GET_CODE (a) == LABEL_REF
3673             && GET_CODE (b) == CONST_INT)
3674           return \"ldr\\t%0, %1\";
3675
3676         if (GET_CODE (b) == REG)
3677           return \"ldrsh\\t%0, %1\";
3678           
3679         ops[1] = a;
3680         ops[2] = b;
3681       }
3682     else
3683       {
3684         ops[1] = mem;
3685         ops[2] = const0_rtx;
3686       }
3687       
3688     if (GET_CODE (ops[1]) != REG)
3689       {
3690         debug_rtx (ops[1]);
3691         abort ();
3692       }
3693
3694     ops[0] = operands[0];
3695     if (reg_mentioned_p (operands[2], ops[1]))
3696       ops[3] = ops[0];
3697     else
3698       ops[3] = operands[2];
3699     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3700     return \"\";
3701   }"
3702   [(set_attr "length" "2,4")
3703    (set_attr "type" "alu_shift,load_byte")
3704    (set_attr "pool_range" "*,1020")]
3705 )
3706
3707 (define_expand "extendhisi2_mem"
3708   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3709    (set (match_dup 3)
3710         (zero_extend:SI (match_dup 7)))
3711    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3712    (set (match_operand:SI 0 "" "")
3713         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3714   "TARGET_ARM"
3715   "
3716   {
3717     rtx mem1, mem2;
3718     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3719
3720     mem1 = gen_rtx_MEM (QImode, addr);
3721     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3722     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3723     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3724     operands[0] = gen_lowpart (SImode, operands[0]);
3725     operands[1] = mem1;
3726     operands[2] = gen_reg_rtx (SImode);
3727     operands[3] = gen_reg_rtx (SImode);
3728     operands[6] = gen_reg_rtx (SImode);
3729     operands[7] = mem2;
3730
3731     if (BYTES_BIG_ENDIAN)
3732       {
3733         operands[4] = operands[2];
3734         operands[5] = operands[3];
3735       }
3736     else
3737       {
3738         operands[4] = operands[3];
3739         operands[5] = operands[2];
3740       }
3741   }"
3742 )
3743
3744 (define_insn "*arm_extendhisi2"
3745   [(set (match_operand:SI 0 "s_register_operand" "=r")
3746         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3747   "TARGET_ARM && arm_arch4 && !arm_arch6"
3748   "ldr%?sh\\t%0, %1"
3749   [(set_attr "type" "load_byte")
3750    (set_attr "predicable" "yes")
3751    (set_attr "pool_range" "256")
3752    (set_attr "neg_pool_range" "244")]
3753 )
3754
3755 (define_insn "*arm_extendhisi2_v6"
3756   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3757         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3758   "TARGET_ARM && arm_arch6"
3759   "@
3760    sxth%?\\t%0, %1
3761    ldr%?sh\\t%0, %1"
3762   [(set_attr "type" "alu_shift,load_byte")
3763    (set_attr "predicable" "yes")
3764    (set_attr "pool_range" "*,256")
3765    (set_attr "neg_pool_range" "*,244")]
3766 )
3767
3768 (define_insn "*arm_extendhisi2addsi"
3769   [(set (match_operand:SI 0 "s_register_operand" "=r")
3770         (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3771                  (match_operand:SI 2 "s_register_operand" "r")))]
3772   "TARGET_ARM && arm_arch6"
3773   "sxtah%?\\t%0, %2, %1"
3774 )
3775
3776 (define_split
3777   [(set (match_operand:SI                 0 "s_register_operand" "")
3778         (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3779    (clobber (match_operand:SI             2 "s_register_operand" ""))]
3780   "TARGET_ARM && (!arm_arch4)"
3781   [(set (match_dup 2) (match_dup 1))
3782    (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3783   "
3784   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3785     FAIL;
3786   "
3787 )
3788
3789 (define_split
3790   [(set (match_operand:SI                   0 "s_register_operand" "")
3791         (match_operator:SI                  3 "shiftable_operator"
3792          [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3793           (match_operand:SI                 4 "s_register_operand" "")]))
3794    (clobber (match_operand:SI               2 "s_register_operand" ""))]
3795   "TARGET_ARM && (!arm_arch4)"
3796   [(set (match_dup 2) (match_dup 1))
3797    (set (match_dup 0)
3798         (match_op_dup 3
3799          [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3800   "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3801      FAIL;
3802   "
3803 )
3804
3805 (define_expand "extendqihi2"
3806   [(set (match_dup 2)
3807         (ashift:SI (match_operand:QI 1 "general_operand" "")
3808                    (const_int 24)))
3809    (set (match_operand:HI 0 "s_register_operand" "")
3810         (ashiftrt:SI (match_dup 2)
3811                      (const_int 24)))]
3812   "TARGET_ARM"
3813   "
3814   {
3815     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3816       {
3817         emit_insn (gen_rtx_SET (VOIDmode,
3818                                 operands[0],
3819                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3820         DONE;
3821       }
3822     if (!s_register_operand (operands[1], QImode))
3823       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3824     operands[0] = gen_lowpart (SImode, operands[0]);
3825     operands[1] = gen_lowpart (SImode, operands[1]);
3826     operands[2] = gen_reg_rtx (SImode);
3827   }"
3828 )
3829
3830 (define_insn "*extendqihi_insn"
3831   [(set (match_operand:HI 0 "s_register_operand" "=r")
3832         (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3833   "TARGET_ARM && arm_arch4"
3834   "ldr%?sb\\t%0, %1"
3835   [(set_attr "type" "load_byte")
3836    (set_attr "predicable" "yes")
3837    (set_attr "pool_range" "256")
3838    (set_attr "neg_pool_range" "244")]
3839 )
3840
3841 (define_expand "extendqisi2"
3842   [(set (match_dup 2)
3843         (ashift:SI (match_operand:QI 1 "general_operand" "")
3844                    (const_int 24)))
3845    (set (match_operand:SI 0 "s_register_operand" "")
3846         (ashiftrt:SI (match_dup 2)
3847                      (const_int 24)))]
3848   "TARGET_EITHER"
3849   "
3850   {
3851     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3852       {
3853         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3854                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3855         DONE;
3856       }
3857
3858     if (!s_register_operand (operands[1], QImode))
3859       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3860
3861     if (arm_arch6)
3862       {
3863         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3864                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3865         DONE;
3866       }
3867
3868     operands[1] = gen_lowpart (SImode, operands[1]);
3869     operands[2] = gen_reg_rtx (SImode);
3870   }"
3871 )
3872
3873 (define_insn "*arm_extendqisi"
3874   [(set (match_operand:SI 0 "s_register_operand" "=r")
3875         (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3876   "TARGET_ARM && arm_arch4 && !arm_arch6"
3877   "ldr%?sb\\t%0, %1"
3878   [(set_attr "type" "load_byte")
3879    (set_attr "predicable" "yes")
3880    (set_attr "pool_range" "256")
3881    (set_attr "neg_pool_range" "244")]
3882 )
3883
3884 (define_insn "*arm_extendqisi_v6"
3885   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3886         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3887   "TARGET_ARM && arm_arch6"
3888   "@
3889    sxtb%?\\t%0, %1
3890    ldr%?sb\\t%0, %1"
3891   [(set_attr "type" "alu_shift,load_byte")
3892    (set_attr "predicable" "yes")
3893    (set_attr "pool_range" "*,256")
3894    (set_attr "neg_pool_range" "*,244")]
3895 )
3896
3897 (define_insn "*arm_extendqisi2addsi"
3898   [(set (match_operand:SI 0 "s_register_operand" "=r")
3899         (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3900                  (match_operand:SI 2 "s_register_operand" "r")))]
3901   "TARGET_ARM && arm_arch6"
3902   "sxtab%?\\t%0, %2, %1"
3903   [(set_attr "type" "alu_shift")
3904    (set_attr "predicable" "yes")]
3905 )
3906
3907 (define_insn "*thumb_extendqisi2"
3908   [(set (match_operand:SI 0 "register_operand" "=l,l")
3909         (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3910   "TARGET_THUMB && !arm_arch6"
3911   "*
3912   {
3913     rtx ops[3];
3914     rtx mem = XEXP (operands[1], 0);
3915     
3916     if (GET_CODE (mem) == CONST)
3917       mem = XEXP (mem, 0);
3918     
3919     if (GET_CODE (mem) == LABEL_REF)
3920       return \"ldr\\t%0, %1\";
3921
3922     if (GET_CODE (mem) == PLUS
3923         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3924       return \"ldr\\t%0, %1\";
3925       
3926     if (which_alternative == 0)
3927       return \"ldrsb\\t%0, %1\";
3928       
3929     ops[0] = operands[0];
3930     
3931     if (GET_CODE (mem) == PLUS)
3932       {
3933         rtx a = XEXP (mem, 0);
3934         rtx b = XEXP (mem, 1);
3935         
3936         ops[1] = a;
3937         ops[2] = b;
3938
3939         if (GET_CODE (a) == REG)
3940           {
3941             if (GET_CODE (b) == REG)
3942               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3943             else if (REGNO (a) == REGNO (ops[0]))
3944               {
3945                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3946                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3947                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3948               }
3949             else
3950               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3951           }
3952         else if (GET_CODE (b) != REG)
3953           abort ();
3954         else
3955           {
3956             if (REGNO (b) == REGNO (ops[0]))
3957               {
3958                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3959                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3960                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3961               }
3962             else
3963               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3964           }
3965       }
3966     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3967       {
3968         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3969         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3970         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3971       }
3972     else
3973       {
3974         ops[1] = mem;
3975         ops[2] = const0_rtx;
3976         
3977         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3978       }
3979     return \"\";
3980   }"
3981   [(set_attr "length" "2,6")
3982    (set_attr "type" "load_byte,load_byte")
3983    (set_attr "pool_range" "32,32")]
3984 )
3985
3986 (define_insn "*thumb_extendqisi2_v6"
3987   [(set (match_operand:SI 0 "register_operand" "=l,l,l")
3988         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
3989   "TARGET_THUMB && arm_arch6"
3990   "*
3991   {
3992     rtx ops[3];
3993     rtx mem;
3994
3995     if (which_alternative == 0)
3996       return \"sxtb\\t%0, %1\";
3997
3998     mem = XEXP (operands[1], 0);
3999     
4000     if (GET_CODE (mem) == CONST)
4001       mem = XEXP (mem, 0);
4002     
4003     if (GET_CODE (mem) == LABEL_REF)
4004       return \"ldr\\t%0, %1\";
4005
4006     if (GET_CODE (mem) == PLUS
4007         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4008       return \"ldr\\t%0, %1\";
4009       
4010     if (which_alternative == 0)
4011       return \"ldrsb\\t%0, %1\";
4012       
4013     ops[0] = operands[0];
4014     
4015     if (GET_CODE (mem) == PLUS)
4016       {
4017         rtx a = XEXP (mem, 0);
4018         rtx b = XEXP (mem, 1);
4019         
4020         ops[1] = a;
4021         ops[2] = b;
4022
4023         if (GET_CODE (a) == REG)
4024           {
4025             if (GET_CODE (b) == REG)
4026               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4027             else if (REGNO (a) == REGNO (ops[0]))
4028               {
4029                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4030                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4031               }
4032             else
4033               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4034           }
4035         else if (GET_CODE (b) != REG)
4036           abort ();
4037         else
4038           {
4039             if (REGNO (b) == REGNO (ops[0]))
4040               {
4041                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4042                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4043               }
4044             else
4045               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4046           }
4047       }
4048     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4049       {
4050         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4051         output_asm_insn (\"sxtb\\t%0, %0\", ops);
4052       }
4053     else
4054       {
4055         ops[1] = mem;
4056         ops[2] = const0_rtx;
4057         
4058         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4059       }
4060     return \"\";
4061   }"
4062   [(set_attr "length" "2,2,4")
4063    (set_attr "type" "alu_shift,load_byte,load_byte")
4064    (set_attr "pool_range" "*,32,32")]
4065 )
4066
4067 (define_expand "extendsfdf2"
4068   [(set (match_operand:DF                  0 "s_register_operand" "")
4069         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
4070   "TARGET_ARM && TARGET_HARD_FLOAT"
4071   ""
4072 )
4073 \f
4074 ;; Move insns (including loads and stores)
4075
4076 ;; XXX Just some ideas about movti.
4077 ;; I don't think these are a good idea on the arm, there just aren't enough
4078 ;; registers
4079 ;;(define_expand "loadti"
4080 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
4081 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
4082 ;;  "" "")
4083
4084 ;;(define_expand "storeti"
4085 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4086 ;;      (match_operand:TI 1 "s_register_operand" ""))]
4087 ;;  "" "")
4088
4089 ;;(define_expand "movti"
4090 ;;  [(set (match_operand:TI 0 "general_operand" "")
4091 ;;      (match_operand:TI 1 "general_operand" ""))]
4092 ;;  ""
4093 ;;  "
4094 ;;{
4095 ;;  rtx insn;
4096 ;;
4097 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4098 ;;    operands[1] = copy_to_reg (operands[1]);
4099 ;;  if (GET_CODE (operands[0]) == MEM)
4100 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4101 ;;  else if (GET_CODE (operands[1]) == MEM)
4102 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4103 ;;  else
4104 ;;    FAIL;
4105 ;;
4106 ;;  emit_insn (insn);
4107 ;;  DONE;
4108 ;;}")
4109
4110 ;; Recognize garbage generated above.
4111
4112 ;;(define_insn ""
4113 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4114 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4115 ;;  ""
4116 ;;  "*
4117 ;;  {
4118 ;;    register mem = (which_alternative < 3);
4119 ;;    register const char *template;
4120 ;;
4121 ;;    operands[mem] = XEXP (operands[mem], 0);
4122 ;;    switch (which_alternative)
4123 ;;      {
4124 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4125 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
4126 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
4127 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
4128 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
4129 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
4130 ;;      }
4131 ;;    output_asm_insn (template, operands);
4132 ;;    return \"\";
4133 ;;  }")
4134
4135 (define_expand "movdi"
4136   [(set (match_operand:DI 0 "general_operand" "")
4137         (match_operand:DI 1 "general_operand" ""))]
4138   "TARGET_EITHER"
4139   "
4140   if (TARGET_THUMB)
4141     {
4142       if (!no_new_pseudos)
4143         {
4144           if (GET_CODE (operands[0]) != REG)
4145             operands[1] = force_reg (DImode, operands[1]);
4146         }
4147     }
4148   "
4149 )
4150
4151 (define_insn "*arm_movdi"
4152   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4153         (match_operand:DI 1 "di_operand"              "rDa,Db,Dc,mi,r"))]
4154   "TARGET_ARM
4155   && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4156   && !TARGET_IWMMXT"
4157   "*
4158   switch (which_alternative)
4159     {
4160     case 0:
4161     case 1:
4162     case 2:
4163       return \"#\";
4164     default:
4165       return output_move_double (operands);
4166     }
4167   "
4168   [(set_attr "length" "8,12,16,8,8")
4169    (set_attr "type" "*,*,*,load2,store2")
4170    (set_attr "pool_range" "*,*,*,1020,*")
4171    (set_attr "neg_pool_range" "*,*,*,1008,*")]
4172 )
4173
4174 (define_split
4175   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4176         (match_operand:ANY64 1 "const_double_operand" ""))]
4177   "TARGET_ARM
4178    && reload_completed
4179    && (arm_const_double_inline_cost (operands[1])
4180        <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4181   [(const_int 0)]
4182   "
4183   arm_split_constant (SET, SImode, curr_insn,
4184                       INTVAL (gen_lowpart (SImode, operands[1])),
4185                       gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4186   arm_split_constant (SET, SImode, curr_insn,
4187                       INTVAL (gen_highpart_mode (SImode,
4188                                                  GET_MODE (operands[0]),
4189                                                  operands[1])),
4190                       gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4191   DONE;
4192   "
4193 )
4194
4195 ; If optimizing for size, or if we have load delay slots, then 
4196 ; we want to split the constant into two separate operations. 
4197 ; In both cases this may split a trivial part into a single data op
4198 ; leaving a single complex constant to load.  We can also get longer
4199 ; offsets in a LDR which means we get better chances of sharing the pool
4200 ; entries.  Finally, we can normally do a better job of scheduling
4201 ; LDR instructions than we can with LDM.
4202 ; This pattern will only match if the one above did not.
4203 (define_split
4204   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4205         (match_operand:ANY64 1 "const_double_operand" ""))]
4206   "TARGET_ARM && reload_completed
4207    && arm_const_double_by_parts (operands[1])"
4208   [(set (match_dup 0) (match_dup 1))
4209    (set (match_dup 2) (match_dup 3))]
4210   "
4211   operands[2] = gen_highpart (SImode, operands[0]);
4212   operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4213                                    operands[1]);
4214   operands[0] = gen_lowpart (SImode, operands[0]);
4215   operands[1] = gen_lowpart (SImode, operands[1]);
4216   "
4217 )
4218
4219 (define_split
4220   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4221         (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4222   "TARGET_EITHER && reload_completed"
4223   [(set (match_dup 0) (match_dup 1))
4224    (set (match_dup 2) (match_dup 3))]
4225   "
4226   operands[2] = gen_highpart (SImode, operands[0]);
4227   operands[3] = gen_highpart (SImode, operands[1]);
4228   operands[0] = gen_lowpart (SImode, operands[0]);
4229   operands[1] = gen_lowpart (SImode, operands[1]);
4230
4231   /* Handle a partial overlap.  */
4232   if (rtx_equal_p (operands[0], operands[3]))
4233     {
4234       rtx tmp0 = operands[0];
4235       rtx tmp1 = operands[1];
4236
4237       operands[0] = operands[2];
4238       operands[1] = operands[3];
4239       operands[2] = tmp0;
4240       operands[3] = tmp1;
4241     }
4242   "
4243 )
4244
4245 ;; We can't actually do base+index doubleword loads if the index and
4246 ;; destination overlap.  Split here so that we at least have chance to
4247 ;; schedule.
4248 (define_split
4249   [(set (match_operand:DI 0 "s_register_operand" "")
4250         (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4251                          (match_operand:SI 2 "s_register_operand" ""))))]
4252   "TARGET_LDRD
4253   && reg_overlap_mentioned_p (operands[0], operands[1])
4254   && reg_overlap_mentioned_p (operands[0], operands[2])"
4255   [(set (match_dup 4)
4256         (plus:SI (match_dup 1)
4257                  (match_dup 2)))
4258    (set (match_dup 0)
4259         (mem:DI (match_dup 4)))]
4260   "
4261   operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4262   "
4263 )
4264
4265 ;;; ??? This should have alternatives for constants.
4266 ;;; ??? This was originally identical to the movdf_insn pattern.
4267 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4268 ;;; thumb_reorg with a memory reference.
4269 (define_insn "*thumb_movdi_insn"
4270   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4271         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
4272   "TARGET_THUMB
4273    && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4274    && (   register_operand (operands[0], DImode)
4275        || register_operand (operands[1], DImode))"
4276   "*
4277   {
4278   switch (which_alternative)
4279     {
4280     default:
4281     case 0:
4282       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4283         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
4284       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
4285     case 1:
4286       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4287     case 2:
4288       operands[1] = GEN_INT (- INTVAL (operands[1]));
4289       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4290     case 3:
4291       return \"ldmia\\t%1, {%0, %H0}\";
4292     case 4:
4293       return \"stmia\\t%0, {%1, %H1}\";
4294     case 5:
4295       return thumb_load_double_from_address (operands);
4296     case 6:
4297       operands[2] = gen_rtx_MEM (SImode,
4298                              plus_constant (XEXP (operands[0], 0), 4));
4299       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4300       return \"\";
4301     case 7:
4302       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4303         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4304       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4305     }
4306   }"
4307   [(set_attr "length" "4,4,6,2,2,6,4,4")
4308    (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4309    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4310 )
4311
4312 (define_expand "movsi"
4313   [(set (match_operand:SI 0 "general_operand" "")
4314         (match_operand:SI 1 "general_operand" ""))]
4315   "TARGET_EITHER"
4316   "
4317   if (TARGET_ARM)
4318     {
4319       /* Everything except mem = const or mem = mem can be done easily.  */
4320       if (GET_CODE (operands[0]) == MEM)
4321         operands[1] = force_reg (SImode, operands[1]);
4322       if (arm_general_register_operand (operands[0], SImode)
4323           && GET_CODE (operands[1]) == CONST_INT
4324           && !(const_ok_for_arm (INTVAL (operands[1]))
4325                || const_ok_for_arm (~INTVAL (operands[1]))))
4326         {
4327            arm_split_constant (SET, SImode, NULL_RTX,
4328                                INTVAL (operands[1]), operands[0], NULL_RTX,
4329                                optimize && !no_new_pseudos);
4330           DONE;
4331         }
4332     }
4333   else /* TARGET_THUMB....  */
4334     {
4335       if (!no_new_pseudos)
4336         {
4337           if (GET_CODE (operands[0]) != REG)
4338             operands[1] = force_reg (SImode, operands[1]);
4339         }
4340     }
4341     
4342   if (flag_pic
4343       && (CONSTANT_P (operands[1])
4344          || symbol_mentioned_p (operands[1])
4345          || label_mentioned_p (operands[1])))
4346     operands[1] = legitimize_pic_address (operands[1], SImode,
4347                                           (no_new_pseudos ? operands[0] : 0));
4348   "
4349 )
4350
4351 (define_insn "*arm_movsi_insn"
4352   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4353         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
4354   "TARGET_ARM && ! TARGET_IWMMXT
4355    && !(TARGET_HARD_FLOAT && TARGET_VFP)
4356    && (   register_operand (operands[0], SImode)
4357        || register_operand (operands[1], SImode))"
4358   "@
4359    mov%?\\t%0, %1
4360    mvn%?\\t%0, #%B1
4361    ldr%?\\t%0, %1
4362    str%?\\t%1, %0"
4363   [(set_attr "type" "*,*,load1,store1")
4364    (set_attr "predicable" "yes")
4365    (set_attr "pool_range" "*,*,4096,*")
4366    (set_attr "neg_pool_range" "*,*,4084,*")]
4367 )
4368
4369 (define_split
4370   [(set (match_operand:SI 0 "arm_general_register_operand" "")
4371         (match_operand:SI 1 "const_int_operand" ""))]
4372   "TARGET_ARM
4373   && (!(const_ok_for_arm (INTVAL (operands[1]))
4374         || const_ok_for_arm (~INTVAL (operands[1]))))"
4375   [(clobber (const_int 0))]
4376   "
4377   arm_split_constant (SET, SImode, NULL_RTX, 
4378                       INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4379   DONE;
4380   "
4381 )
4382
4383 (define_insn "*thumb_movsi_insn"
4384   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4385         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4386   "TARGET_THUMB
4387    && (   register_operand (operands[0], SImode) 
4388        || register_operand (operands[1], SImode))"
4389   "@
4390    mov  %0, %1
4391    mov  %0, %1
4392    #
4393    #
4394    ldmia\\t%1, {%0}
4395    stmia\\t%0, {%1}
4396    ldr\\t%0, %1
4397    str\\t%1, %0
4398    mov\\t%0, %1"
4399   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4400    (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4401    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4402 )
4403
4404 (define_split 
4405   [(set (match_operand:SI 0 "register_operand" "")
4406         (match_operand:SI 1 "const_int_operand" ""))]
4407   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4408   [(set (match_dup 0) (match_dup 1))
4409    (set (match_dup 0) (neg:SI (match_dup 0)))]
4410   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4411 )
4412
4413 (define_split 
4414   [(set (match_operand:SI 0 "register_operand" "")
4415         (match_operand:SI 1 "const_int_operand" ""))]
4416   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4417   [(set (match_dup 0) (match_dup 1))
4418    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4419   "
4420   {
4421     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4422     unsigned HOST_WIDE_INT mask = 0xff;
4423     int i;
4424     
4425     for (i = 0; i < 25; i++)
4426       if ((val & (mask << i)) == val)
4427         break;
4428
4429     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4430     if (i == 0)
4431       FAIL;
4432
4433     operands[1] = GEN_INT (val >> i);
4434     operands[2] = GEN_INT (i);
4435   }"
4436 )
4437
4438 ;; When generating pic, we need to load the symbol offset into a register.
4439 ;; So that the optimizer does not confuse this with a normal symbol load
4440 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
4441 ;; since that is the only type of relocation we can use.
4442
4443 ;; The rather odd constraints on the following are to force reload to leave
4444 ;; the insn alone, and to force the minipool generation pass to then move
4445 ;; the GOT symbol to memory.
4446
4447 (define_insn "pic_load_addr_arm"
4448   [(set (match_operand:SI 0 "s_register_operand" "=r")
4449         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4450   "TARGET_ARM && flag_pic"
4451   "ldr%?\\t%0, %1"
4452   [(set_attr "type" "load1")
4453    (set (attr "pool_range")     (const_int 4096))
4454    (set (attr "neg_pool_range") (const_int 4084))]
4455 )
4456
4457 (define_insn "pic_load_addr_thumb"
4458   [(set (match_operand:SI 0 "s_register_operand" "=l")
4459         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4460   "TARGET_THUMB && flag_pic"
4461   "ldr\\t%0, %1"
4462   [(set_attr "type" "load1")
4463    (set (attr "pool_range") (const_int 1024))]
4464 )
4465
4466 ;; This variant is used for AOF assembly, since it needs to mention the
4467 ;; pic register in the rtl.
4468 (define_expand "pic_load_addr_based"
4469   [(set (match_operand:SI 0 "s_register_operand" "")
4470         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4471   "TARGET_ARM && flag_pic"
4472   "operands[2] = pic_offset_table_rtx;"
4473 )
4474
4475 (define_insn "*pic_load_addr_based_insn"
4476   [(set (match_operand:SI 0 "s_register_operand" "=r")
4477         (unspec:SI [(match_operand 1 "" "")
4478                     (match_operand 2 "s_register_operand" "r")]
4479                    UNSPEC_PIC_SYM))]
4480   "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4481   "*
4482 #ifdef AOF_ASSEMBLER
4483   operands[1] = aof_pic_entry (operands[1]);
4484 #endif
4485   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4486   return \"\";
4487   "
4488   [(set_attr "type" "load1")
4489    (set (attr "pool_range")
4490         (if_then_else (eq_attr "is_thumb" "yes")
4491                       (const_int 1024)
4492                       (const_int 4096)))
4493    (set (attr "neg_pool_range")
4494         (if_then_else (eq_attr "is_thumb" "yes")
4495                       (const_int 0)
4496                       (const_int 4084)))]
4497 )
4498
4499 (define_insn "pic_add_dot_plus_four"
4500   [(set (match_operand:SI 0 "register_operand" "+r")
4501         (unspec:SI [(plus:SI (match_dup 0)
4502                              (const (plus:SI (pc) (const_int 4))))]
4503                    UNSPEC_PIC_BASE))
4504    (use (label_ref (match_operand 1 "" "")))]
4505   "TARGET_THUMB && flag_pic"
4506   "*
4507   (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4508                              CODE_LABEL_NUMBER (operands[1]));
4509   return \"add\\t%0, %|pc\";
4510   "
4511   [(set_attr "length" "2")]
4512 )
4513
4514 (define_insn "pic_add_dot_plus_eight"
4515   [(set (match_operand:SI 0 "register_operand" "+r")
4516         (unspec:SI [(plus:SI (match_dup 0)
4517                              (const (plus:SI (pc) (const_int 8))))]
4518                    UNSPEC_PIC_BASE))
4519    (use (label_ref (match_operand 1 "" "")))]
4520   "TARGET_ARM && flag_pic"
4521   "*
4522     (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4523                                CODE_LABEL_NUMBER (operands[1]));
4524     return \"add%?\\t%0, %|pc, %0\";
4525   "
4526   [(set_attr "predicable" "yes")]
4527 )
4528
4529 (define_expand "builtin_setjmp_receiver"
4530   [(label_ref (match_operand 0 "" ""))]
4531   "flag_pic"
4532   "
4533 {
4534   /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4535      register.  */
4536   arm_load_pic_register (3);
4537   DONE;
4538 }")
4539
4540 ;; If copying one reg to another we can set the condition codes according to
4541 ;; its value.  Such a move is common after a return from subroutine and the
4542 ;; result is being tested against zero.
4543
4544 (define_insn "*movsi_compare0"
4545   [(set (reg:CC CC_REGNUM)
4546         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4547                     (const_int 0)))
4548    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4549         (match_dup 1))]
4550   "TARGET_ARM"
4551   "@
4552    cmp%?\\t%0, #0
4553    sub%?s\\t%0, %1, #0"
4554   [(set_attr "conds" "set")]
4555 )
4556
4557 ;; Subroutine to store a half word from a register into memory.
4558 ;; Operand 0 is the source register (HImode)
4559 ;; Operand 1 is the destination address in a register (SImode)
4560
4561 ;; In both this routine and the next, we must be careful not to spill
4562 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4563 ;; can generate unrecognizable rtl.
4564
4565 (define_expand "storehi"
4566   [;; store the low byte
4567    (set (match_operand 1 "" "") (match_dup 3))
4568    ;; extract the high byte
4569    (set (match_dup 2)
4570         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4571    ;; store the high byte
4572    (set (match_dup 4) (match_dup 5))]
4573   "TARGET_ARM"
4574   "
4575   {
4576     rtx op1 = operands[1];
4577     rtx addr = XEXP (op1, 0);
4578     enum rtx_code code = GET_CODE (addr);
4579
4580     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4581         || code == MINUS)
4582       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4583
4584     operands[4] = adjust_address (op1, QImode, 1);
4585     operands[1] = adjust_address (operands[1], QImode, 0);
4586     operands[3] = gen_lowpart (QImode, operands[0]);
4587     operands[0] = gen_lowpart (SImode, operands[0]);
4588     operands[2] = gen_reg_rtx (SImode);
4589     operands[5] = gen_lowpart (QImode, operands[2]);
4590   }"
4591 )
4592
4593 (define_expand "storehi_bigend"
4594   [(set (match_dup 4) (match_dup 3))
4595    (set (match_dup 2)
4596         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4597    (set (match_operand 1 "" "") (match_dup 5))]
4598   "TARGET_ARM"
4599   "
4600   {
4601     rtx op1 = operands[1];
4602     rtx addr = XEXP (op1, 0);
4603     enum rtx_code code = GET_CODE (addr);
4604
4605     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4606         || code == MINUS)
4607       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4608
4609     operands[4] = adjust_address (op1, QImode, 1);
4610     operands[1] = adjust_address (operands[1], QImode, 0);
4611     operands[3] = gen_lowpart (QImode, operands[0]);
4612     operands[0] = gen_lowpart (SImode, operands[0]);
4613     operands[2] = gen_reg_rtx (SImode);
4614     operands[5] = gen_lowpart (QImode, operands[2]);
4615   }"
4616 )
4617
4618 ;; Subroutine to store a half word integer constant into memory.
4619 (define_expand "storeinthi"
4620   [(set (match_operand 0 "" "")
4621         (match_operand 1 "" ""))
4622    (set (match_dup 3) (match_dup 2))]
4623   "TARGET_ARM"
4624   "
4625   {
4626     HOST_WIDE_INT value = INTVAL (operands[1]);
4627     rtx addr = XEXP (operands[0], 0);
4628     rtx op0 = operands[0];
4629     enum rtx_code code = GET_CODE (addr);
4630
4631     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4632         || code == MINUS)
4633       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4634
4635     operands[1] = gen_reg_rtx (SImode);
4636     if (BYTES_BIG_ENDIAN)
4637       {
4638         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4639         if ((value & 255) == ((value >> 8) & 255))
4640           operands[2] = operands[1];
4641         else
4642           {
4643             operands[2] = gen_reg_rtx (SImode);
4644             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4645           }
4646       }
4647     else
4648       {
4649         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4650         if ((value & 255) == ((value >> 8) & 255))
4651           operands[2] = operands[1];
4652         else
4653           {
4654             operands[2] = gen_reg_rtx (SImode);
4655             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4656           }
4657       }
4658
4659     operands[3] = adjust_address (op0, QImode, 1);
4660     operands[0] = adjust_address (operands[0], QImode, 0);
4661     operands[2] = gen_lowpart (QImode, operands[2]);
4662     operands[1] = gen_lowpart (QImode, operands[1]);
4663   }"
4664 )
4665
4666 (define_expand "storehi_single_op"
4667   [(set (match_operand:HI 0 "memory_operand" "")
4668         (match_operand:HI 1 "general_operand" ""))]
4669   "TARGET_ARM && arm_arch4"
4670   "
4671   if (!s_register_operand (operands[1], HImode))
4672     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4673   "
4674 )
4675
4676 (define_expand "movhi"
4677   [(set (match_operand:HI 0 "general_operand" "")
4678         (match_operand:HI 1 "general_operand" ""))]
4679   "TARGET_EITHER"
4680   "
4681   if (TARGET_ARM)
4682     {
4683       if (!no_new_pseudos)
4684         {
4685           if (GET_CODE (operands[0]) == MEM)
4686             {
4687               if (arm_arch4)
4688                 {
4689                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4690                   DONE;
4691                 }
4692               if (GET_CODE (operands[1]) == CONST_INT)
4693                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4694               else
4695                 {
4696                   if (GET_CODE (operands[1]) == MEM)
4697                     operands[1] = force_reg (HImode, operands[1]);
4698                   if (BYTES_BIG_ENDIAN)
4699                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4700                   else
4701                    emit_insn (gen_storehi (operands[1], operands[0]));
4702                 }
4703               DONE;
4704             }
4705           /* Sign extend a constant, and keep it in an SImode reg.  */
4706           else if (GET_CODE (operands[1]) == CONST_INT)
4707             {
4708               rtx reg = gen_reg_rtx (SImode);
4709               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4710
4711               /* If the constant is already valid, leave it alone.  */
4712               if (!const_ok_for_arm (val))
4713                 {
4714                   /* If setting all the top bits will make the constant 
4715                      loadable in a single instruction, then set them.  
4716                      Otherwise, sign extend the number.  */
4717
4718                   if (const_ok_for_arm (~(val | ~0xffff)))
4719                     val |= ~0xffff;
4720                   else if (val & 0x8000)
4721                     val |= ~0xffff;
4722                 }
4723
4724               emit_insn (gen_movsi (reg, GEN_INT (val)));
4725               operands[1] = gen_lowpart (HImode, reg);
4726             }
4727           else if (arm_arch4 && optimize && !no_new_pseudos
4728                    && GET_CODE (operands[1]) == MEM)
4729             {
4730               rtx reg = gen_reg_rtx (SImode);
4731
4732               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4733               operands[1] = gen_lowpart (HImode, reg);
4734             }
4735           else if (!arm_arch4)
4736             {
4737               if (GET_CODE (operands[1]) == MEM)
4738                 {
4739                   rtx base;
4740                   rtx offset = const0_rtx;
4741                   rtx reg = gen_reg_rtx (SImode);
4742
4743                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4744                        || (GET_CODE (base) == PLUS
4745                            && (GET_CODE (offset = XEXP (base, 1))
4746                                == CONST_INT)
4747                            && ((INTVAL(offset) & 1) != 1)
4748                            && GET_CODE (base = XEXP (base, 0)) == REG))
4749                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4750                     {
4751                       HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4752                       rtx new;
4753
4754                       new = gen_rtx_MEM (SImode,
4755                                          plus_constant (base, new_offset));
4756                       MEM_COPY_ATTRIBUTES (new, operands[1]);
4757                       emit_insn (gen_movsi (reg, new));
4758                       if (((INTVAL (offset) & 2) != 0)
4759                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4760                         {
4761                           rtx reg2 = gen_reg_rtx (SImode);
4762
4763                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4764                           reg = reg2;
4765                         }
4766                     }
4767                   else
4768                     emit_insn (gen_movhi_bytes (reg, operands[1]));
4769
4770                   operands[1] = gen_lowpart (HImode, reg);
4771                }
4772            }
4773         }
4774       /* Handle loading a large integer during reload.  */
4775       else if (GET_CODE (operands[1]) == CONST_INT
4776                && !const_ok_for_arm (INTVAL (operands[1]))
4777                && !const_ok_for_arm (~INTVAL (operands[1])))
4778         {
4779           /* Writing a constant to memory needs a scratch, which should
4780              be handled with SECONDARY_RELOADs.  */
4781           if (GET_CODE (operands[0]) != REG)
4782             abort ();
4783
4784           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4785           emit_insn (gen_movsi (operands[0], operands[1]));
4786           DONE;
4787        }
4788     }
4789   else /* TARGET_THUMB */
4790     {
4791       if (!no_new_pseudos)
4792         {
4793           if (GET_CODE (operands[0]) != REG)
4794             operands[1] = force_reg (HImode, operands[1]);
4795
4796           /* ??? We shouldn't really get invalid addresses here, but this can
4797              happen if we are passed a SP (never OK for HImode/QImode) or 
4798              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4799              HImode/QImode) relative address.  */
4800           /* ??? This should perhaps be fixed elsewhere, for instance, in
4801              fixup_stack_1, by checking for other kinds of invalid addresses,
4802              e.g. a bare reference to a virtual register.  This may confuse the
4803              alpha though, which must handle this case differently.  */
4804           if (GET_CODE (operands[0]) == MEM
4805               && !memory_address_p (GET_MODE (operands[0]),
4806                                     XEXP (operands[0], 0)))
4807             operands[0]
4808               = replace_equiv_address (operands[0],
4809                                        copy_to_reg (XEXP (operands[0], 0)));
4810    
4811           if (GET_CODE (operands[1]) == MEM
4812               && !memory_address_p (GET_MODE (operands[1]),
4813                                     XEXP (operands[1], 0)))
4814             operands[1]
4815               = replace_equiv_address (operands[1],
4816                                        copy_to_reg (XEXP (operands[1], 0)));
4817         }
4818       /* Handle loading a large integer during reload.  */
4819       else if (GET_CODE (operands[1]) == CONST_INT
4820                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4821         {
4822           /* Writing a constant to memory needs a scratch, which should
4823              be handled with SECONDARY_RELOADs.  */
4824           if (GET_CODE (operands[0]) != REG)
4825             abort ();
4826
4827           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4828           emit_insn (gen_movsi (operands[0], operands[1]));
4829           DONE;
4830         }
4831     }
4832   "
4833 )
4834
4835 (define_insn "*thumb_movhi_insn"
4836   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4837         (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
4838   "TARGET_THUMB
4839    && (   register_operand (operands[0], HImode)
4840        || register_operand (operands[1], HImode))"
4841   "*
4842   switch (which_alternative)
4843     {
4844     case 0: return \"add        %0, %1, #0\";
4845     case 2: return \"strh       %1, %0\";
4846     case 3: return \"mov        %0, %1\";
4847     case 4: return \"mov        %0, %1\";
4848     case 5: return \"mov        %0, %1\";
4849     default: abort ();
4850     case 1:
4851       /* The stack pointer can end up being taken as an index register.
4852           Catch this case here and deal with it.  */
4853       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4854           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4855           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4856         {
4857           rtx ops[2];
4858           ops[0] = operands[0];
4859           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4860       
4861           output_asm_insn (\"mov        %0, %1\", ops);
4862
4863           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4864     
4865         }
4866       return \"ldrh     %0, %1\";
4867     }"
4868   [(set_attr "length" "2,4,2,2,2,2")
4869    (set_attr "type" "*,load1,store1,*,*,*")]
4870 )
4871
4872
4873 (define_expand "movhi_bytes"
4874   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4875    (set (match_dup 3)
4876         (zero_extend:SI (match_dup 6)))
4877    (set (match_operand:SI 0 "" "")
4878          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4879   "TARGET_ARM"
4880   "
4881   {
4882     rtx mem1, mem2;
4883     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4884
4885     mem1 = gen_rtx_MEM (QImode, addr);
4886     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4887     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4888     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4889     operands[0] = gen_lowpart (SImode, operands[0]);
4890     operands[1] = mem1;
4891     operands[2] = gen_reg_rtx (SImode);
4892     operands[3] = gen_reg_rtx (SImode);
4893     operands[6] = mem2;
4894
4895     if (BYTES_BIG_ENDIAN)
4896       {
4897         operands[4] = operands[2];
4898         operands[5] = operands[3];
4899       }
4900     else
4901       {
4902         operands[4] = operands[3];
4903         operands[5] = operands[2];
4904       }
4905   }"
4906 )
4907
4908 (define_expand "movhi_bigend"
4909   [(set (match_dup 2)
4910         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4911                    (const_int 16)))
4912    (set (match_dup 3)
4913         (ashiftrt:SI (match_dup 2) (const_int 16)))
4914    (set (match_operand:HI 0 "s_register_operand" "")
4915         (match_dup 4))]
4916   "TARGET_ARM"
4917   "
4918   operands[2] = gen_reg_rtx (SImode);
4919   operands[3] = gen_reg_rtx (SImode);
4920   operands[4] = gen_lowpart (HImode, operands[3]);
4921   "
4922 )
4923
4924 ;; Pattern to recognize insn generated default case above
4925 (define_insn "*movhi_insn_arch4"
4926   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4927         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4928   "TARGET_ARM
4929    && arm_arch4
4930    && (GET_CODE (operands[1]) != CONST_INT
4931        || const_ok_for_arm (INTVAL (operands[1]))
4932        || const_ok_for_arm (~INTVAL (operands[1])))"
4933   "@
4934    mov%?\\t%0, %1\\t%@ movhi
4935    mvn%?\\t%0, #%B1\\t%@ movhi
4936    str%?h\\t%1, %0\\t%@ movhi
4937    ldr%?h\\t%0, %1\\t%@ movhi"
4938   [(set_attr "type" "*,*,store1,load1")
4939    (set_attr "predicable" "yes")
4940    (set_attr "pool_range" "*,*,*,256")
4941    (set_attr "neg_pool_range" "*,*,*,244")]
4942 )
4943
4944 (define_insn "*movhi_bytes"
4945   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4946         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4947   "TARGET_ARM"
4948   "@
4949    mov%?\\t%0, %1\\t%@ movhi
4950    mvn%?\\t%0, #%B1\\t%@ movhi"
4951   [(set_attr "predicable" "yes")]
4952 )
4953
4954 (define_insn "thumb_movhi_clobber"
4955   [(set (match_operand:HI     0 "memory_operand"   "=m")
4956         (match_operand:HI     1 "register_operand" "l"))
4957    (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4958   "TARGET_THUMB"
4959   "*
4960   abort ();"
4961 )
4962         
4963 ;; We use a DImode scratch because we may occasionally need an additional
4964 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4965 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4966 (define_expand "reload_outhi"
4967   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4968               (match_operand:HI 1 "s_register_operand"        "r")
4969               (match_operand:DI 2 "s_register_operand"        "=&l")])]
4970   "TARGET_EITHER"
4971   "if (TARGET_ARM)
4972      arm_reload_out_hi (operands);
4973    else
4974      thumb_reload_out_hi (operands);
4975   DONE;
4976   "
4977 )
4978
4979 (define_expand "reload_inhi"
4980   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4981               (match_operand:HI 1 "arm_reload_memory_operand" "o")
4982               (match_operand:DI 2 "s_register_operand" "=&r")])]
4983   "TARGET_EITHER"
4984   "
4985   if (TARGET_ARM)
4986     arm_reload_in_hi (operands);
4987   else
4988     thumb_reload_out_hi (operands);
4989   DONE;
4990 ")
4991
4992 (define_expand "movqi"
4993   [(set (match_operand:QI 0 "general_operand" "")
4994         (match_operand:QI 1 "general_operand" ""))]
4995   "TARGET_EITHER"
4996   "
4997   if (TARGET_ARM)
4998     {
4999       /* Everything except mem = const or mem = mem can be done easily */
5000
5001       if (!no_new_pseudos)
5002         {
5003           if (GET_CODE (operands[1]) == CONST_INT)
5004             {
5005               rtx reg = gen_reg_rtx (SImode);
5006
5007               emit_insn (gen_movsi (reg, operands[1]));
5008               operands[1] = gen_lowpart (QImode, reg);
5009             }
5010           if (GET_CODE (operands[1]) == MEM && optimize > 0)
5011             {
5012               rtx reg = gen_reg_rtx (SImode);
5013
5014               emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5015               operands[1] = gen_lowpart (QImode, reg);
5016             }
5017           if (GET_CODE (operands[0]) == MEM)
5018             operands[1] = force_reg (QImode, operands[1]);
5019         }
5020     }
5021   else /* TARGET_THUMB */
5022     {
5023       if (!no_new_pseudos)
5024         {
5025           if (GET_CODE (operands[0]) != REG)
5026             operands[1] = force_reg (QImode, operands[1]);
5027
5028           /* ??? We shouldn't really get invalid addresses here, but this can
5029              happen if we are passed a SP (never OK for HImode/QImode) or
5030              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
5031              HImode/QImode) relative address.  */
5032           /* ??? This should perhaps be fixed elsewhere, for instance, in
5033              fixup_stack_1, by checking for other kinds of invalid addresses,
5034              e.g. a bare reference to a virtual register.  This may confuse the
5035              alpha though, which must handle this case differently.  */
5036           if (GET_CODE (operands[0]) == MEM
5037               && !memory_address_p (GET_MODE (operands[0]),
5038                                      XEXP (operands[0], 0)))
5039             operands[0]
5040               = replace_equiv_address (operands[0],
5041                                        copy_to_reg (XEXP (operands[0], 0)));
5042           if (GET_CODE (operands[1]) == MEM
5043               && !memory_address_p (GET_MODE (operands[1]),
5044                                     XEXP (operands[1], 0)))
5045              operands[1]
5046                = replace_equiv_address (operands[1],
5047                                         copy_to_reg (XEXP (operands[1], 0)));
5048         }
5049       /* Handle loading a large integer during reload.  */
5050       else if (GET_CODE (operands[1]) == CONST_INT
5051                && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
5052         {
5053           /* Writing a constant to memory needs a scratch, which should
5054              be handled with SECONDARY_RELOADs.  */
5055           if (GET_CODE (operands[0]) != REG)
5056             abort ();
5057
5058           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5059           emit_insn (gen_movsi (operands[0], operands[1]));
5060           DONE;
5061        }
5062     }
5063   "
5064 )
5065
5066
5067 (define_insn "*arm_movqi_insn"
5068   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5069         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5070   "TARGET_ARM
5071    && (   register_operand (operands[0], QImode)
5072        || register_operand (operands[1], QImode))"
5073   "@
5074    mov%?\\t%0, %1
5075    mvn%?\\t%0, #%B1
5076    ldr%?b\\t%0, %1
5077    str%?b\\t%1, %0"
5078   [(set_attr "type" "*,*,load1,store1")
5079    (set_attr "predicable" "yes")]
5080 )
5081
5082 (define_insn "*thumb_movqi_insn"
5083   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5084         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
5085   "TARGET_THUMB
5086    && (   register_operand (operands[0], QImode)
5087        || register_operand (operands[1], QImode))"
5088   "@
5089    add\\t%0, %1, #0
5090    ldrb\\t%0, %1
5091    strb\\t%1, %0
5092    mov\\t%0, %1
5093    mov\\t%0, %1
5094    mov\\t%0, %1"
5095   [(set_attr "length" "2")
5096    (set_attr "type" "*,load1,store1,*,*,*")
5097    (set_attr "pool_range" "*,32,*,*,*,*")]
5098 )
5099
5100 (define_expand "movsf"
5101   [(set (match_operand:SF 0 "general_operand" "")
5102         (match_operand:SF 1 "general_operand" ""))]
5103   "TARGET_EITHER"
5104   "
5105   if (TARGET_ARM)
5106     {
5107       if (GET_CODE (operands[0]) == MEM)
5108         operands[1] = force_reg (SFmode, operands[1]);
5109     }
5110   else /* TARGET_THUMB */
5111     {
5112       if (!no_new_pseudos)
5113         {
5114            if (GET_CODE (operands[0]) != REG)
5115              operands[1] = force_reg (SFmode, operands[1]);
5116         }
5117     }
5118   "
5119 )
5120
5121 (define_split
5122   [(set (match_operand:SF 0 "nonimmediate_operand" "")
5123         (match_operand:SF 1 "immediate_operand" ""))]
5124   "TARGET_ARM
5125    && !(TARGET_HARD_FLOAT && TARGET_FPA)
5126    && reload_completed
5127    && GET_CODE (operands[1]) == CONST_DOUBLE"
5128   [(set (match_dup 2) (match_dup 3))]
5129   "
5130   operands[2] = gen_lowpart (SImode, operands[0]);
5131   operands[3] = gen_lowpart (SImode, operands[1]);
5132   if (operands[2] == 0 || operands[3] == 0)
5133     FAIL;
5134   "
5135 )
5136
5137 (define_insn "*arm_movsf_soft_insn"
5138   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5139         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
5140   "TARGET_ARM
5141    && TARGET_SOFT_FLOAT
5142    && (GET_CODE (operands[0]) != MEM
5143        || register_operand (operands[1], SFmode))"
5144   "@
5145    mov%?\\t%0, %1
5146    ldr%?\\t%0, %1\\t%@ float
5147    str%?\\t%1, %0\\t%@ float"
5148   [(set_attr "length" "4,4,4")
5149    (set_attr "predicable" "yes")
5150    (set_attr "type" "*,load1,store1")
5151    (set_attr "pool_range" "*,4096,*")
5152    (set_attr "neg_pool_range" "*,4084,*")]
5153 )
5154
5155 ;;; ??? This should have alternatives for constants.
5156 (define_insn "*thumb_movsf_insn"
5157   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5158         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5159   "TARGET_THUMB
5160    && (   register_operand (operands[0], SFmode) 
5161        || register_operand (operands[1], SFmode))"
5162   "@
5163    add\\t%0, %1, #0
5164    ldmia\\t%1, {%0}
5165    stmia\\t%0, {%1}
5166    ldr\\t%0, %1
5167    str\\t%1, %0
5168    mov\\t%0, %1
5169    mov\\t%0, %1"
5170   [(set_attr "length" "2")
5171    (set_attr "type" "*,load1,store1,load1,store1,*,*")
5172    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5173 )
5174
5175 (define_expand "movdf"
5176   [(set (match_operand:DF 0 "general_operand" "")
5177         (match_operand:DF 1 "general_operand" ""))]
5178   "TARGET_EITHER"
5179   "
5180   if (TARGET_ARM)
5181     {
5182       if (GET_CODE (operands[0]) == MEM)
5183         operands[1] = force_reg (DFmode, operands[1]);
5184     }
5185   else /* TARGET_THUMB */
5186     {
5187       if (!no_new_pseudos)
5188         {
5189           if (GET_CODE (operands[0]) != REG)
5190             operands[1] = force_reg (DFmode, operands[1]);
5191         }
5192     }
5193   "
5194 )
5195
5196 ;; Reloading a df mode value stored in integer regs to memory can require a
5197 ;; scratch reg.
5198 (define_expand "reload_outdf"
5199   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5200    (match_operand:DF 1 "s_register_operand" "r")
5201    (match_operand:SI 2 "s_register_operand" "=&r")]
5202   "TARGET_ARM"
5203   "
5204   {
5205     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5206
5207     if (code == REG)
5208       operands[2] = XEXP (operands[0], 0);
5209     else if (code == POST_INC || code == PRE_DEC)
5210       {
5211         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5212         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5213         emit_insn (gen_movdi (operands[0], operands[1]));
5214         DONE;
5215       }
5216     else if (code == PRE_INC)
5217       {
5218         rtx reg = XEXP (XEXP (operands[0], 0), 0);
5219
5220         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5221         operands[2] = reg;
5222       }
5223     else if (code == POST_DEC)
5224       operands[2] = XEXP (XEXP (operands[0], 0), 0);
5225     else
5226       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5227                              XEXP (XEXP (operands[0], 0), 1)));
5228
5229     emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5230                             operands[1]));
5231
5232     if (code == POST_DEC)
5233       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5234
5235     DONE;
5236   }"
5237 )
5238
5239 (define_insn "*movdf_soft_insn"
5240   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5241         (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
5242   "TARGET_ARM && TARGET_SOFT_FLOAT
5243   "
5244   "*
5245   switch (which_alternative)
5246     {
5247     case 0:
5248     case 1:
5249     case 2:
5250       return \"#\";
5251     default:
5252       return output_move_double (operands);
5253     }
5254   "
5255   [(set_attr "length" "8,12,16,8,8")
5256    (set_attr "type" "*,*,*,load2,store2")
5257    (set_attr "pool_range" "1020")
5258    (set_attr "neg_pool_range" "1008")]
5259 )
5260
5261 ;;; ??? This should have alternatives for constants.
5262 ;;; ??? This was originally identical to the movdi_insn pattern.
5263 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5264 ;;; thumb_reorg with a memory reference.
5265 (define_insn "*thumb_movdf_insn"
5266   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5267         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5268   "TARGET_THUMB
5269    && (   register_operand (operands[0], DFmode)
5270        || register_operand (operands[1], DFmode))"
5271   "*
5272   switch (which_alternative)
5273     {
5274     default:
5275     case 0:
5276       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5277         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5278       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5279     case 1:
5280       return \"ldmia\\t%1, {%0, %H0}\";
5281     case 2:
5282       return \"stmia\\t%0, {%1, %H1}\";
5283     case 3:
5284       return thumb_load_double_from_address (operands);
5285     case 4:
5286       operands[2] = gen_rtx_MEM (SImode,
5287                                  plus_constant (XEXP (operands[0], 0), 4));
5288       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5289       return \"\";
5290     case 5:
5291       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5292         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5293       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5294     }
5295   "
5296   [(set_attr "length" "4,2,2,6,4,4")
5297    (set_attr "type" "*,load2,store2,load2,store2,*")
5298    (set_attr "pool_range" "*,*,*,1020,*,*")]
5299 )
5300
5301 (define_expand "movxf"
5302   [(set (match_operand:XF 0 "general_operand" "")
5303         (match_operand:XF 1 "general_operand" ""))]
5304   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
5305   "
5306   if (GET_CODE (operands[0]) == MEM)
5307     operands[1] = force_reg (XFmode, operands[1]);
5308   "
5309 )
5310
5311 ;; Vector Moves
5312 (define_expand "movv2si"
5313   [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5314         (match_operand:V2SI 1 "general_operand" ""))]
5315   "TARGET_REALLY_IWMMXT"
5316 {
5317 })
5318
5319 (define_expand "movv4hi"
5320   [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5321         (match_operand:V4HI 1 "general_operand" ""))]
5322   "TARGET_REALLY_IWMMXT"
5323 {
5324 })
5325
5326 (define_expand "movv8qi"
5327   [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5328         (match_operand:V8QI 1 "general_operand" ""))]
5329   "TARGET_REALLY_IWMMXT"
5330 {
5331 })
5332 \f
5333
5334 ;; load- and store-multiple insns
5335 ;; The arm can load/store any set of registers, provided that they are in
5336 ;; ascending order; but that is beyond GCC so stick with what it knows.
5337
5338 (define_expand "load_multiple"
5339   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5340                           (match_operand:SI 1 "" ""))
5341                      (use (match_operand:SI 2 "" ""))])]
5342   "TARGET_ARM"
5343 {
5344   HOST_WIDE_INT offset = 0;
5345
5346   /* Support only fixed point registers.  */
5347   if (GET_CODE (operands[2]) != CONST_INT
5348       || INTVAL (operands[2]) > 14
5349       || INTVAL (operands[2]) < 2
5350       || GET_CODE (operands[1]) != MEM
5351       || GET_CODE (operands[0]) != REG
5352       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5353       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5354     FAIL;
5355
5356   operands[3]
5357     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5358                              force_reg (SImode, XEXP (operands[1], 0)),
5359                              TRUE, FALSE, operands[1], &offset);
5360 })
5361
5362 ;; Load multiple with write-back
5363
5364 (define_insn "*ldmsi_postinc4"
5365   [(match_parallel 0 "load_multiple_operation"
5366     [(set (match_operand:SI 1 "s_register_operand" "=r")
5367           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5368                    (const_int 16)))
5369      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5370           (mem:SI (match_dup 2)))
5371      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5372           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5373      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5374           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5375      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5376           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5377   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5378   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5379   [(set_attr "type" "load4")
5380    (set_attr "predicable" "yes")]
5381 )
5382
5383 (define_insn "*ldmsi_postinc4_thumb"
5384   [(match_parallel 0 "load_multiple_operation"
5385     [(set (match_operand:SI 1 "s_register_operand" "=l")
5386           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5387                    (const_int 16)))
5388      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5389           (mem:SI (match_dup 2)))
5390      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5391           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5392      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5393           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5394      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5395           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5396   "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5397   "ldmia\\t%1!, {%3, %4, %5, %6}"
5398   [(set_attr "type" "load4")]
5399 )
5400
5401 (define_insn "*ldmsi_postinc3"
5402   [(match_parallel 0 "load_multiple_operation"
5403     [(set (match_operand:SI 1 "s_register_operand" "=r")
5404           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5405                    (const_int 12)))
5406      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5407           (mem:SI (match_dup 2)))
5408      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5409           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5410      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5411           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5412   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5413   "ldm%?ia\\t%1!, {%3, %4, %5}"
5414   [(set_attr "type" "load3")
5415    (set_attr "predicable" "yes")]
5416 )
5417
5418 (define_insn "*ldmsi_postinc2"
5419   [(match_parallel 0 "load_multiple_operation"
5420     [(set (match_operand:SI 1 "s_register_operand" "=r")
5421           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5422                    (const_int 8)))
5423      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5424           (mem:SI (match_dup 2)))
5425      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5426           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5427   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5428   "ldm%?ia\\t%1!, {%3, %4}"
5429   [(set_attr "type" "load2")
5430    (set_attr "predicable" "yes")]
5431 )
5432
5433 ;; Ordinary load multiple
5434
5435 (define_insn "*ldmsi4"
5436   [(match_parallel 0 "load_multiple_operation"
5437     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5438           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5439      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5440           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5441      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5442           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5443      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5444           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5445   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5446   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5447   [(set_attr "type" "load4")
5448    (set_attr "predicable" "yes")]
5449 )
5450
5451 (define_insn "*ldmsi3"
5452   [(match_parallel 0 "load_multiple_operation"
5453     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5454           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5455      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5456           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5457      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5458           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5459   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5460   "ldm%?ia\\t%1, {%2, %3, %4}"
5461   [(set_attr "type" "load3")
5462    (set_attr "predicable" "yes")]
5463 )
5464
5465 (define_insn "*ldmsi2"
5466   [(match_parallel 0 "load_multiple_operation"
5467     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5468           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5469      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5470           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5471   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5472   "ldm%?ia\\t%1, {%2, %3}"
5473   [(set_attr "type" "load2")
5474    (set_attr "predicable" "yes")]
5475 )
5476
5477 (define_expand "store_multiple"
5478   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5479                           (match_operand:SI 1 "" ""))
5480                      (use (match_operand:SI 2 "" ""))])]
5481   "TARGET_ARM"
5482 {
5483   HOST_WIDE_INT offset = 0;
5484
5485   /* Support only fixed point registers.  */
5486   if (GET_CODE (operands[2]) != CONST_INT
5487       || INTVAL (operands[2]) > 14
5488       || INTVAL (operands[2]) < 2
5489       || GET_CODE (operands[1]) != REG
5490       || GET_CODE (operands[0]) != MEM
5491       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5492       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5493     FAIL;
5494
5495   operands[3]
5496     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5497                               force_reg (SImode, XEXP (operands[0], 0)),
5498                               TRUE, FALSE, operands[0], &offset);
5499 })
5500
5501 ;; Store multiple with write-back
5502
5503 (define_insn "*stmsi_postinc4"
5504   [(match_parallel 0 "store_multiple_operation"
5505     [(set (match_operand:SI 1 "s_register_operand" "=r")
5506           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5507                    (const_int 16)))
5508      (set (mem:SI (match_dup 2))
5509           (match_operand:SI 3 "arm_hard_register_operand" ""))
5510      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5511           (match_operand:SI 4 "arm_hard_register_operand" ""))
5512      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5513           (match_operand:SI 5 "arm_hard_register_operand" ""))
5514      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5515           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5516   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5517   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5518   [(set_attr "predicable" "yes")
5519    (set_attr "type" "store4")]
5520 )
5521
5522 (define_insn "*stmsi_postinc4_thumb"
5523   [(match_parallel 0 "store_multiple_operation"
5524     [(set (match_operand:SI 1 "s_register_operand" "=l")
5525           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5526                    (const_int 16)))
5527      (set (mem:SI (match_dup 2))
5528           (match_operand:SI 3 "arm_hard_register_operand" ""))
5529      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5530           (match_operand:SI 4 "arm_hard_register_operand" ""))
5531      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5532           (match_operand:SI 5 "arm_hard_register_operand" ""))
5533      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5534           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5535   "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5536   "stmia\\t%1!, {%3, %4, %5, %6}"
5537   [(set_attr "type" "store4")]
5538 )
5539
5540 (define_insn "*stmsi_postinc3"
5541   [(match_parallel 0 "store_multiple_operation"
5542     [(set (match_operand:SI 1 "s_register_operand" "=r")
5543           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5544                    (const_int 12)))
5545      (set (mem:SI (match_dup 2))
5546           (match_operand:SI 3 "arm_hard_register_operand" ""))
5547      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5548           (match_operand:SI 4 "arm_hard_register_operand" ""))
5549      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5550           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5551   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5552   "stm%?ia\\t%1!, {%3, %4, %5}"
5553   [(set_attr "predicable" "yes")
5554    (set_attr "type" "store3")]
5555 )
5556
5557 (define_insn "*stmsi_postinc2"
5558   [(match_parallel 0 "store_multiple_operation"
5559     [(set (match_operand:SI 1 "s_register_operand" "=r")
5560           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5561                    (const_int 8)))
5562      (set (mem:SI (match_dup 2))
5563           (match_operand:SI 3 "arm_hard_register_operand" ""))
5564      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5565           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5566   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5567   "stm%?ia\\t%1!, {%3, %4}"
5568   [(set_attr "predicable" "yes")
5569    (set_attr "type" "store2")]
5570 )
5571
5572 ;; Ordinary store multiple
5573
5574 (define_insn "*stmsi4"
5575   [(match_parallel 0 "store_multiple_operation"
5576     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5577           (match_operand:SI 2 "arm_hard_register_operand" ""))
5578      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5579           (match_operand:SI 3 "arm_hard_register_operand" ""))
5580      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5581           (match_operand:SI 4 "arm_hard_register_operand" ""))
5582      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5583           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5584   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5585   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5586   [(set_attr "predicable" "yes")
5587    (set_attr "type" "store4")]
5588 )
5589
5590 (define_insn "*stmsi3"
5591   [(match_parallel 0 "store_multiple_operation"
5592     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5593           (match_operand:SI 2 "arm_hard_register_operand" ""))
5594      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5595           (match_operand:SI 3 "arm_hard_register_operand" ""))
5596      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5597           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5598   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5599   "stm%?ia\\t%1, {%2, %3, %4}"
5600   [(set_attr "predicable" "yes")
5601    (set_attr "type" "store3")]
5602 )
5603
5604 (define_insn "*stmsi2"
5605   [(match_parallel 0 "store_multiple_operation"
5606     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5607           (match_operand:SI 2 "arm_hard_register_operand" ""))
5608      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5609           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5610   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5611   "stm%?ia\\t%1, {%2, %3}"
5612   [(set_attr "predicable" "yes")
5613    (set_attr "type" "store2")]
5614 )
5615
5616 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5617 ;; We could let this apply for blocks of less than this, but it clobbers so
5618 ;; many registers that there is then probably a better way.
5619
5620 (define_expand "movmemqi"
5621   [(match_operand:BLK 0 "general_operand" "")
5622    (match_operand:BLK 1 "general_operand" "")
5623    (match_operand:SI 2 "const_int_operand" "")
5624    (match_operand:SI 3 "const_int_operand" "")]
5625   "TARGET_EITHER"
5626   "
5627   if (TARGET_ARM)
5628     {
5629       if (arm_gen_movmemqi (operands))
5630         DONE;
5631       FAIL;
5632     }
5633   else /* TARGET_THUMB */
5634     {
5635       if (   INTVAL (operands[3]) != 4
5636           || INTVAL (operands[2]) > 48)
5637         FAIL;
5638
5639       thumb_expand_movmemqi (operands);
5640       DONE;
5641     }
5642   "
5643 )
5644
5645 ;; Thumb block-move insns
5646
5647 (define_insn "movmem12b"
5648   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5649         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5650    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5651         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5652    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5653         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5654    (set (match_operand:SI 0 "register_operand" "=l")
5655         (plus:SI (match_dup 2) (const_int 12)))
5656    (set (match_operand:SI 1 "register_operand" "=l")
5657         (plus:SI (match_dup 3) (const_int 12)))
5658    (clobber (match_scratch:SI 4 "=&l"))
5659    (clobber (match_scratch:SI 5 "=&l"))
5660    (clobber (match_scratch:SI 6 "=&l"))]
5661   "TARGET_THUMB"
5662   "* return thumb_output_move_mem_multiple (3, operands);"
5663   [(set_attr "length" "4")
5664    ; This isn't entirely accurate...  It loads as well, but in terms of
5665    ; scheduling the following insn it is better to consider it as a store
5666    (set_attr "type" "store3")]
5667 )
5668
5669 (define_insn "movmem8b"
5670   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5671         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5672    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5673         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5674    (set (match_operand:SI 0 "register_operand" "=l")
5675         (plus:SI (match_dup 2) (const_int 8)))
5676    (set (match_operand:SI 1 "register_operand" "=l")
5677         (plus:SI (match_dup 3) (const_int 8)))
5678    (clobber (match_scratch:SI 4 "=&l"))
5679    (clobber (match_scratch:SI 5 "=&l"))]
5680   "TARGET_THUMB"
5681   "* return thumb_output_move_mem_multiple (2, operands);"
5682   [(set_attr "length" "4")
5683    ; This isn't entirely accurate...  It loads as well, but in terms of
5684    ; scheduling the following insn it is better to consider it as a store
5685    (set_attr "type" "store2")]
5686 )
5687
5688 \f
5689
5690 ;; Compare & branch insns
5691 ;; The range calculations are based as follows:
5692 ;; For forward branches, the address calculation returns the address of
5693 ;; the next instruction.  This is 2 beyond the branch instruction.
5694 ;; For backward branches, the address calculation returns the address of
5695 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5696 ;; instruction for the shortest sequence, and 4 before the branch instruction
5697 ;; if we have to jump around an unconditional branch.
5698 ;; To the basic branch range the PC offset must be added (this is +4).
5699 ;; So for forward branches we have 
5700 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5701 ;; And for backward branches we have 
5702 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5703 ;;
5704 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5705 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5706
5707 (define_expand "cbranchsi4"
5708   [(set (pc) (if_then_else
5709               (match_operator 0 "arm_comparison_operator"
5710                [(match_operand:SI 1 "s_register_operand" "")
5711                 (match_operand:SI 2 "nonmemory_operand" "")])
5712               (label_ref (match_operand 3 "" ""))
5713               (pc)))]
5714   "TARGET_THUMB"
5715   "
5716   if (thumb_cmpneg_operand (operands[2], SImode))
5717     {
5718       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5719                                               operands[3], operands[0]));
5720       DONE;
5721     }
5722   if (!thumb_cmp_operand (operands[2], SImode))
5723     operands[2] = force_reg (SImode, operands[2]);
5724   ")
5725
5726 (define_insn "*cbranchsi4_insn"
5727   [(set (pc) (if_then_else
5728               (match_operator 0 "arm_comparison_operator"
5729                [(match_operand:SI 1 "s_register_operand" "l,*h")
5730                 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5731               (label_ref (match_operand 3 "" ""))
5732               (pc)))]
5733   "TARGET_THUMB"
5734   "*
5735   output_asm_insn (\"cmp\\t%1, %2\", operands);
5736
5737   switch (get_attr_length (insn))
5738     {
5739     case 4:  return \"b%d0\\t%l3\";
5740     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5741     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5742     }
5743   "
5744   [(set (attr "far_jump")
5745         (if_then_else
5746             (eq_attr "length" "8")
5747             (const_string "yes")
5748             (const_string "no")))
5749    (set (attr "length") 
5750         (if_then_else
5751             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5752                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5753             (const_int 4)
5754             (if_then_else
5755                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5756                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5757                 (const_int 6)
5758                 (const_int 8))))]
5759 )
5760
5761 (define_insn "cbranchsi4_scratch"
5762   [(set (pc) (if_then_else
5763               (match_operator 4 "arm_comparison_operator"
5764                [(match_operand:SI 1 "s_register_operand" "l,0")
5765                 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5766               (label_ref (match_operand 3 "" ""))
5767               (pc)))
5768    (clobber (match_scratch:SI 0 "=l,l"))]
5769   "TARGET_THUMB"
5770   "*
5771   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5772
5773   switch (get_attr_length (insn))
5774     {
5775     case 4:  return \"b%d4\\t%l3\";
5776     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5777     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5778     }
5779   "
5780   [(set (attr "far_jump")
5781         (if_then_else
5782             (eq_attr "length" "8")
5783             (const_string "yes")
5784             (const_string "no")))
5785    (set (attr "length") 
5786         (if_then_else
5787             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5788                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5789             (const_int 4)
5790             (if_then_else
5791                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5792                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5793                 (const_int 6)
5794                 (const_int 8))))]
5795 )
5796 (define_insn "*movsi_cbranchsi4"
5797   [(set (pc)
5798         (if_then_else
5799          (match_operator 3 "arm_comparison_operator"
5800           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5801            (const_int 0)])
5802          (label_ref (match_operand 2 "" ""))
5803          (pc)))
5804    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5805         (match_dup 1))]
5806   "TARGET_THUMB"
5807   "*{
5808   if (which_alternative == 0)
5809     output_asm_insn (\"cmp\t%0, #0\", operands);
5810   else if (which_alternative == 1)
5811     output_asm_insn (\"sub\t%0, %1, #0\", operands);
5812   else
5813     {
5814       output_asm_insn (\"cmp\t%1, #0\", operands);
5815       if (which_alternative == 2)
5816         output_asm_insn (\"mov\t%0, %1\", operands);
5817       else
5818         output_asm_insn (\"str\t%1, %0\", operands);
5819     }
5820   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5821     {
5822     case 4:  return \"b%d3\\t%l2\";
5823     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5824     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5825     }
5826   }"
5827   [(set (attr "far_jump")
5828         (if_then_else
5829             (ior (and (gt (symbol_ref ("which_alternative"))
5830                           (const_int 1))
5831                       (eq_attr "length" "8"))
5832                  (eq_attr "length" "10"))
5833             (const_string "yes")
5834             (const_string "no")))
5835    (set (attr "length")
5836      (if_then_else
5837        (le (symbol_ref ("which_alternative"))
5838                        (const_int 1))
5839        (if_then_else
5840          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5841               (le (minus (match_dup 2) (pc)) (const_int 256)))
5842          (const_int 4)
5843          (if_then_else
5844            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5845                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5846            (const_int 6)
5847            (const_int 8)))
5848        (if_then_else
5849          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5850               (le (minus (match_dup 2) (pc)) (const_int 256)))
5851          (const_int 6)
5852          (if_then_else
5853            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5854                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5855            (const_int 8)
5856            (const_int 10)))))]
5857 )
5858
5859 (define_insn "*negated_cbranchsi4"
5860   [(set (pc)
5861         (if_then_else
5862          (match_operator 0 "equality_operator"
5863           [(match_operand:SI 1 "s_register_operand" "l")
5864            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5865          (label_ref (match_operand 3 "" ""))
5866          (pc)))]
5867   "TARGET_THUMB"
5868   "*
5869   output_asm_insn (\"cmn\\t%1, %2\", operands);
5870   switch (get_attr_length (insn))
5871     {
5872     case 4:  return \"b%d0\\t%l3\";
5873     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5874     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5875     }
5876   "
5877   [(set (attr "far_jump")
5878         (if_then_else
5879             (eq_attr "length" "8")
5880             (const_string "yes")
5881             (const_string "no")))
5882    (set (attr "length") 
5883         (if_then_else
5884             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5885                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5886             (const_int 4)
5887             (if_then_else
5888                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5889                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5890                 (const_int 6)
5891                 (const_int 8))))]
5892 )
5893
5894 (define_insn "*tbit_cbranch"
5895   [(set (pc)
5896         (if_then_else
5897          (match_operator 0 "equality_operator"
5898           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5899                             (const_int 1)
5900                             (match_operand:SI 2 "const_int_operand" "i"))
5901            (const_int 0)])
5902          (label_ref (match_operand 3 "" ""))
5903          (pc)))
5904    (clobber (match_scratch:SI 4 "=l"))]
5905   "TARGET_THUMB"
5906   "*
5907   {
5908   rtx op[3];
5909   op[0] = operands[4];
5910   op[1] = operands[1];
5911   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5912
5913   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5914   switch (get_attr_length (insn))
5915     {
5916     case 4:  return \"b%d0\\t%l3\";
5917     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5918     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5919     }
5920   }"
5921   [(set (attr "far_jump")
5922         (if_then_else
5923             (eq_attr "length" "8")
5924             (const_string "yes")
5925             (const_string "no")))
5926    (set (attr "length") 
5927         (if_then_else
5928             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5929                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5930             (const_int 4)
5931             (if_then_else
5932                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5933                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5934                 (const_int 6)
5935                 (const_int 8))))]
5936 )
5937   
5938 (define_insn "*tstsi3_cbranch"
5939   [(set (pc)
5940         (if_then_else
5941          (match_operator 3 "equality_operator"
5942           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5943                    (match_operand:SI 1 "s_register_operand" "l"))
5944            (const_int 0)])
5945          (label_ref (match_operand 2 "" ""))
5946          (pc)))]
5947   "TARGET_THUMB"
5948   "*
5949   {
5950   output_asm_insn (\"tst\\t%0, %1\", operands);
5951   switch (get_attr_length (insn))
5952     {
5953     case 4:  return \"b%d3\\t%l2\";
5954     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5955     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5956     }
5957   }"
5958   [(set (attr "far_jump")
5959         (if_then_else
5960             (eq_attr "length" "8")
5961             (const_string "yes")
5962             (const_string "no")))
5963    (set (attr "length") 
5964         (if_then_else
5965             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5966                  (le (minus (match_dup 2) (pc)) (const_int 256)))
5967             (const_int 4)
5968             (if_then_else
5969                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5970                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
5971                 (const_int 6)
5972                 (const_int 8))))]
5973 )
5974   
5975 (define_insn "*andsi3_cbranch"
5976   [(set (pc)
5977         (if_then_else
5978          (match_operator 5 "equality_operator"
5979           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5980                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5981            (const_int 0)])
5982          (label_ref (match_operand 4 "" ""))
5983          (pc)))
5984    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5985         (and:SI (match_dup 2) (match_dup 3)))
5986    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5987   "TARGET_THUMB"
5988   "*
5989   {
5990   if (which_alternative == 0)
5991     output_asm_insn (\"and\\t%0, %3\", operands);
5992   else if (which_alternative == 1)
5993     {
5994       output_asm_insn (\"and\\t%1, %3\", operands);
5995       output_asm_insn (\"mov\\t%0, %1\", operands);
5996     }
5997   else
5998     {
5999       output_asm_insn (\"and\\t%1, %3\", operands);
6000       output_asm_insn (\"str\\t%1, %0\", operands);
6001     }
6002
6003   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6004     {
6005     case 4:  return \"b%d5\\t%l4\";
6006     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6007     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6008     }
6009   }"
6010   [(set (attr "far_jump")
6011         (if_then_else
6012             (ior (and (eq (symbol_ref ("which_alternative"))
6013                           (const_int 0))
6014                       (eq_attr "length" "8"))
6015                  (eq_attr "length" "10"))
6016             (const_string "yes")
6017             (const_string "no")))
6018    (set (attr "length")
6019      (if_then_else
6020        (eq (symbol_ref ("which_alternative"))
6021                        (const_int 0))
6022        (if_then_else
6023          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6024               (le (minus (match_dup 4) (pc)) (const_int 256)))
6025          (const_int 4)
6026          (if_then_else
6027            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6028                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6029            (const_int 6)
6030            (const_int 8)))
6031        (if_then_else
6032          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6033               (le (minus (match_dup 4) (pc)) (const_int 256)))
6034          (const_int 6)
6035          (if_then_else
6036            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6037                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6038            (const_int 8)
6039            (const_int 10)))))]
6040 )
6041
6042 (define_insn "*orrsi3_cbranch_scratch"
6043   [(set (pc)
6044         (if_then_else
6045          (match_operator 4 "equality_operator"
6046           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6047                    (match_operand:SI 2 "s_register_operand" "l"))
6048            (const_int 0)])
6049          (label_ref (match_operand 3 "" ""))
6050          (pc)))
6051    (clobber (match_scratch:SI 0 "=l"))]
6052   "TARGET_THUMB"
6053   "*
6054   {
6055   output_asm_insn (\"orr\\t%0, %2\", operands);
6056   switch (get_attr_length (insn))
6057     {
6058     case 4:  return \"b%d4\\t%l3\";
6059     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6060     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6061     }
6062   }"
6063   [(set (attr "far_jump")
6064         (if_then_else
6065             (eq_attr "length" "8")
6066             (const_string "yes")
6067             (const_string "no")))
6068    (set (attr "length") 
6069         (if_then_else
6070             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6071                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6072             (const_int 4)
6073             (if_then_else
6074                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6075                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6076                 (const_int 6)
6077                 (const_int 8))))]
6078 )
6079   
6080 (define_insn "*orrsi3_cbranch"
6081   [(set (pc)
6082         (if_then_else
6083          (match_operator 5 "equality_operator"
6084           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6085                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6086            (const_int 0)])
6087          (label_ref (match_operand 4 "" ""))
6088          (pc)))
6089    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6090         (ior:SI (match_dup 2) (match_dup 3)))
6091    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6092   "TARGET_THUMB"
6093   "*
6094   {
6095   if (which_alternative == 0)
6096     output_asm_insn (\"orr\\t%0, %3\", operands);
6097   else if (which_alternative == 1)
6098     {
6099       output_asm_insn (\"orr\\t%1, %3\", operands);
6100       output_asm_insn (\"mov\\t%0, %1\", operands);
6101     }
6102   else
6103     {
6104       output_asm_insn (\"orr\\t%1, %3\", operands);
6105       output_asm_insn (\"str\\t%1, %0\", operands);
6106     }
6107
6108   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6109     {
6110     case 4:  return \"b%d5\\t%l4\";
6111     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6112     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6113     }
6114   }"
6115   [(set (attr "far_jump")
6116         (if_then_else
6117             (ior (and (eq (symbol_ref ("which_alternative"))
6118                           (const_int 0))
6119                       (eq_attr "length" "8"))
6120                  (eq_attr "length" "10"))
6121             (const_string "yes")
6122             (const_string "no")))
6123    (set (attr "length")
6124      (if_then_else
6125        (eq (symbol_ref ("which_alternative"))
6126                        (const_int 0))
6127        (if_then_else
6128          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6129               (le (minus (match_dup 4) (pc)) (const_int 256)))
6130          (const_int 4)
6131          (if_then_else
6132            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6133                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6134            (const_int 6)
6135            (const_int 8)))
6136        (if_then_else
6137          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6138               (le (minus (match_dup 4) (pc)) (const_int 256)))
6139          (const_int 6)
6140          (if_then_else
6141            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6142                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6143            (const_int 8)
6144            (const_int 10)))))]
6145 )
6146
6147 (define_insn "*xorsi3_cbranch_scratch"
6148   [(set (pc)
6149         (if_then_else
6150          (match_operator 4 "equality_operator"
6151           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6152                    (match_operand:SI 2 "s_register_operand" "l"))
6153            (const_int 0)])
6154          (label_ref (match_operand 3 "" ""))
6155          (pc)))
6156    (clobber (match_scratch:SI 0 "=l"))]
6157   "TARGET_THUMB"
6158   "*
6159   {
6160   output_asm_insn (\"eor\\t%0, %2\", operands);
6161   switch (get_attr_length (insn))
6162     {
6163     case 4:  return \"b%d4\\t%l3\";
6164     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6165     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6166     }
6167   }"
6168   [(set (attr "far_jump")
6169         (if_then_else
6170             (eq_attr "length" "8")
6171             (const_string "yes")
6172             (const_string "no")))
6173    (set (attr "length") 
6174         (if_then_else
6175             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6176                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6177             (const_int 4)
6178             (if_then_else
6179                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6180                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6181                 (const_int 6)
6182                 (const_int 8))))]
6183 )
6184   
6185 (define_insn "*xorsi3_cbranch"
6186   [(set (pc)
6187         (if_then_else
6188          (match_operator 5 "equality_operator"
6189           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6190                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6191            (const_int 0)])
6192          (label_ref (match_operand 4 "" ""))
6193          (pc)))
6194    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6195         (xor:SI (match_dup 2) (match_dup 3)))
6196    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6197   "TARGET_THUMB"
6198   "*
6199   {
6200   if (which_alternative == 0)
6201     output_asm_insn (\"eor\\t%0, %3\", operands);
6202   else if (which_alternative == 1)
6203     {
6204       output_asm_insn (\"eor\\t%1, %3\", operands);
6205       output_asm_insn (\"mov\\t%0, %1\", operands);
6206     }
6207   else
6208     {
6209       output_asm_insn (\"eor\\t%1, %3\", operands);
6210       output_asm_insn (\"str\\t%1, %0\", operands);
6211     }
6212
6213   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6214     {
6215     case 4:  return \"b%d5\\t%l4\";
6216     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6217     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6218     }
6219   }"
6220   [(set (attr "far_jump")
6221         (if_then_else
6222             (ior (and (eq (symbol_ref ("which_alternative"))
6223                           (const_int 0))
6224                       (eq_attr "length" "8"))
6225                  (eq_attr "length" "10"))
6226             (const_string "yes")
6227             (const_string "no")))
6228    (set (attr "length")
6229      (if_then_else
6230        (eq (symbol_ref ("which_alternative"))
6231                        (const_int 0))
6232        (if_then_else
6233          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6234               (le (minus (match_dup 4) (pc)) (const_int 256)))
6235          (const_int 4)
6236          (if_then_else
6237            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6238                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6239            (const_int 6)
6240            (const_int 8)))
6241        (if_then_else
6242          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6243               (le (minus (match_dup 4) (pc)) (const_int 256)))
6244          (const_int 6)
6245          (if_then_else
6246            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6247                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6248            (const_int 8)
6249            (const_int 10)))))]
6250 )
6251
6252 (define_insn "*bicsi3_cbranch_scratch"
6253   [(set (pc)
6254         (if_then_else
6255          (match_operator 4 "equality_operator"
6256           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6257                    (match_operand:SI 1 "s_register_operand" "0"))
6258            (const_int 0)])
6259          (label_ref (match_operand 3 "" ""))
6260          (pc)))
6261    (clobber (match_scratch:SI 0 "=l"))]
6262   "TARGET_THUMB"
6263   "*
6264   {
6265   output_asm_insn (\"bic\\t%0, %2\", operands);
6266   switch (get_attr_length (insn))
6267     {
6268     case 4:  return \"b%d4\\t%l3\";
6269     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6270     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6271     }
6272   }"
6273   [(set (attr "far_jump")
6274         (if_then_else
6275             (eq_attr "length" "8")
6276             (const_string "yes")
6277             (const_string "no")))
6278    (set (attr "length") 
6279         (if_then_else
6280             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6281                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6282             (const_int 4)
6283             (if_then_else
6284                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6285                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6286                 (const_int 6)
6287                 (const_int 8))))]
6288 )
6289   
6290 (define_insn "*bicsi3_cbranch"
6291   [(set (pc)
6292         (if_then_else
6293          (match_operator 5 "equality_operator"
6294           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6295                    (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6296            (const_int 0)])
6297          (label_ref (match_operand 4 "" ""))
6298          (pc)))
6299    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6300         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6301    (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6302   "TARGET_THUMB"
6303   "*
6304   {
6305   if (which_alternative == 0)
6306     output_asm_insn (\"bic\\t%0, %3\", operands);
6307   else if (which_alternative <= 2)
6308     {
6309       output_asm_insn (\"bic\\t%1, %3\", operands);
6310       /* It's ok if OP0 is a lo-reg, even though the mov will set the
6311          conditions again, since we're only testing for equality.  */
6312       output_asm_insn (\"mov\\t%0, %1\", operands);
6313     }
6314   else
6315     {
6316       output_asm_insn (\"bic\\t%1, %3\", operands);
6317       output_asm_insn (\"str\\t%1, %0\", operands);
6318     }
6319
6320   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6321     {
6322     case 4:  return \"b%d5\\t%l4\";
6323     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6324     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6325     }
6326   }"
6327   [(set (attr "far_jump")
6328         (if_then_else
6329             (ior (and (eq (symbol_ref ("which_alternative"))
6330                           (const_int 0))
6331                       (eq_attr "length" "8"))
6332                  (eq_attr "length" "10"))
6333             (const_string "yes")
6334             (const_string "no")))
6335    (set (attr "length")
6336      (if_then_else
6337        (eq (symbol_ref ("which_alternative"))
6338                        (const_int 0))
6339        (if_then_else
6340          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6341               (le (minus (match_dup 4) (pc)) (const_int 256)))
6342          (const_int 4)
6343          (if_then_else
6344            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6345                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6346            (const_int 6)
6347            (const_int 8)))
6348        (if_then_else
6349          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6350               (le (minus (match_dup 4) (pc)) (const_int 256)))
6351          (const_int 6)
6352          (if_then_else
6353            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6354                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6355            (const_int 8)
6356            (const_int 10)))))]
6357 )
6358
6359 (define_insn "*cbranchne_decr1"
6360   [(set (pc)
6361         (if_then_else (match_operator 3 "equality_operator"
6362                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6363                         (const_int 0)])
6364                       (label_ref (match_operand 4 "" ""))
6365                       (pc)))
6366    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6367         (plus:SI (match_dup 2) (const_int -1)))
6368    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6369   "TARGET_THUMB"
6370   "*
6371    {
6372      rtx cond[2];
6373      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6374                                 ? GEU : LTU),
6375                                VOIDmode, operands[2], const1_rtx);
6376      cond[1] = operands[4];
6377
6378      if (which_alternative == 0)
6379        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6380      else if (which_alternative == 1)
6381        {
6382          /* We must provide an alternative for a hi reg because reload 
6383             cannot handle output reloads on a jump instruction, but we
6384             can't subtract into that.  Fortunately a mov from lo to hi
6385             does not clobber the condition codes.  */
6386          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6387          output_asm_insn (\"mov\\t%0, %1\", operands);
6388        }
6389      else
6390        {
6391          /* Similarly, but the target is memory.  */
6392          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6393          output_asm_insn (\"str\\t%1, %0\", operands);
6394        }
6395
6396      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6397        {
6398          case 4:
6399            output_asm_insn (\"b%d0\\t%l1\", cond);
6400            return \"\";
6401          case 6:
6402            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6403            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6404          default:
6405            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6406            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6407        }
6408    }
6409   "
6410   [(set (attr "far_jump")
6411         (if_then_else
6412             (ior (and (eq (symbol_ref ("which_alternative"))
6413                           (const_int 0))
6414                       (eq_attr "length" "8"))
6415                  (eq_attr "length" "10"))
6416             (const_string "yes")
6417             (const_string "no")))
6418    (set_attr_alternative "length"
6419       [
6420        ;; Alternative 0
6421        (if_then_else
6422          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6423               (le (minus (match_dup 4) (pc)) (const_int 256)))
6424          (const_int 4)
6425          (if_then_else
6426            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6427                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6428            (const_int 6)
6429            (const_int 8)))
6430        ;; Alternative 1
6431        (if_then_else
6432          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6433               (le (minus (match_dup 4) (pc)) (const_int 256)))
6434          (const_int 6)
6435          (if_then_else
6436            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6437                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6438            (const_int 8)
6439            (const_int 10)))
6440        ;; Alternative 2
6441        (if_then_else
6442          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6443               (le (minus (match_dup 4) (pc)) (const_int 256)))
6444          (const_int 6)
6445          (if_then_else
6446            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6447                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6448            (const_int 8)
6449            (const_int 10)))
6450        ;; Alternative 3
6451        (if_then_else
6452          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6453               (le (minus (match_dup 4) (pc)) (const_int 256)))
6454          (const_int 6)
6455          (if_then_else
6456            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6457                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6458            (const_int 8)
6459            (const_int 10)))])]
6460 )
6461
6462 (define_insn "*addsi3_cbranch"
6463   [(set (pc)
6464         (if_then_else
6465          (match_operator 4 "comparison_operator"
6466           [(plus:SI
6467             (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6468             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6469            (const_int 0)])
6470          (label_ref (match_operand 5 "" ""))
6471          (pc)))
6472    (set
6473     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6474     (plus:SI (match_dup 2) (match_dup 3)))
6475    (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6476   "TARGET_THUMB
6477    && (GET_CODE (operands[4]) == EQ
6478        || GET_CODE (operands[4]) == NE
6479        || GET_CODE (operands[4]) == GE
6480        || GET_CODE (operands[4]) == LT)"
6481   "*
6482    {
6483      rtx cond[3];
6484
6485      
6486      cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6487      cond[1] = operands[2];
6488      cond[2] = operands[3];
6489
6490      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6491        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6492      else
6493        output_asm_insn (\"add\\t%0, %1, %2\", cond);
6494
6495      if (which_alternative >= 3
6496          && which_alternative < 4)
6497        output_asm_insn (\"mov\\t%0, %1\", operands);
6498      else if (which_alternative >= 4)
6499        output_asm_insn (\"str\\t%1, %0\", operands);
6500
6501      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6502        {
6503          case 4:
6504            return \"b%d4\\t%l5\";
6505          case 6:
6506            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6507          default:
6508            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6509        }
6510    }
6511   "
6512   [(set (attr "far_jump")
6513         (if_then_else
6514             (ior (and (lt (symbol_ref ("which_alternative"))
6515                           (const_int 3))
6516                       (eq_attr "length" "8"))
6517                  (eq_attr "length" "10"))
6518             (const_string "yes")
6519             (const_string "no")))
6520    (set (attr "length")
6521      (if_then_else
6522        (lt (symbol_ref ("which_alternative"))
6523                        (const_int 3))
6524        (if_then_else
6525          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6526               (le (minus (match_dup 5) (pc)) (const_int 256)))
6527          (const_int 4)
6528          (if_then_else
6529            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6530                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6531            (const_int 6)
6532            (const_int 8)))
6533        (if_then_else
6534          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6535               (le (minus (match_dup 5) (pc)) (const_int 256)))
6536          (const_int 6)
6537          (if_then_else
6538            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6539                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6540            (const_int 8)
6541            (const_int 10)))))]
6542 )
6543
6544 (define_insn "*addsi3_cbranch_scratch"
6545   [(set (pc)
6546         (if_then_else
6547          (match_operator 3 "comparison_operator"
6548           [(plus:SI
6549             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6550             (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
6551            (const_int 0)])
6552          (label_ref (match_operand 4 "" ""))
6553          (pc)))
6554    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6555   "TARGET_THUMB
6556    && (GET_CODE (operands[3]) == EQ
6557        || GET_CODE (operands[3]) == NE
6558        || GET_CODE (operands[3]) == GE
6559        || GET_CODE (operands[3]) == LT)"
6560   "*
6561    {
6562      switch (which_alternative)
6563        {
6564        case 0:
6565          output_asm_insn (\"cmp\t%1, #%n2\", operands);
6566          break;
6567        case 1:
6568          output_asm_insn (\"cmn\t%1, %2\", operands);
6569          break;
6570        case 2:
6571          if (INTVAL (operands[2]) < 0)
6572            output_asm_insn (\"sub\t%0, %1, %2\", operands);
6573          else
6574            output_asm_insn (\"add\t%0, %1, %2\", operands);
6575          break;
6576        case 3:
6577          if (INTVAL (operands[2]) < 0)
6578            output_asm_insn (\"sub\t%0, %0, %2\", operands);
6579          else
6580            output_asm_insn (\"add\t%0, %0, %2\", operands);
6581          break;
6582        }
6583
6584      switch (get_attr_length (insn))
6585        {
6586          case 4:
6587            return \"b%d3\\t%l4\";
6588          case 6:
6589            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6590          default:
6591            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6592        }
6593    }
6594   "
6595   [(set (attr "far_jump")
6596         (if_then_else
6597             (eq_attr "length" "8")
6598             (const_string "yes")
6599             (const_string "no")))
6600    (set (attr "length")
6601        (if_then_else
6602          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6603               (le (minus (match_dup 4) (pc)) (const_int 256)))
6604          (const_int 4)
6605          (if_then_else
6606            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6607                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6608            (const_int 6)
6609            (const_int 8))))]
6610 )
6611
6612 (define_insn "*subsi3_cbranch"
6613   [(set (pc)
6614         (if_then_else
6615          (match_operator 4 "comparison_operator"
6616           [(minus:SI
6617             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6618             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6619            (const_int 0)])
6620          (label_ref (match_operand 5 "" ""))
6621          (pc)))
6622    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6623         (minus:SI (match_dup 2) (match_dup 3)))
6624    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6625   "TARGET_THUMB
6626    && (GET_CODE (operands[4]) == EQ
6627        || GET_CODE (operands[4]) == NE
6628        || GET_CODE (operands[4]) == GE
6629        || GET_CODE (operands[4]) == LT)"
6630   "*
6631    {
6632      if (which_alternative == 0)
6633        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6634      else if (which_alternative == 1)
6635        {
6636          /* We must provide an alternative for a hi reg because reload 
6637             cannot handle output reloads on a jump instruction, but we
6638             can't subtract into that.  Fortunately a mov from lo to hi
6639             does not clobber the condition codes.  */
6640          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6641          output_asm_insn (\"mov\\t%0, %1\", operands);
6642        }
6643      else
6644        {
6645          /* Similarly, but the target is memory.  */
6646          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6647          output_asm_insn (\"str\\t%1, %0\", operands);
6648        }
6649
6650      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6651        {
6652          case 4:
6653            return \"b%d4\\t%l5\";
6654          case 6:
6655            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6656          default:
6657            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6658        }
6659    }
6660   "
6661   [(set (attr "far_jump")
6662         (if_then_else
6663             (ior (and (eq (symbol_ref ("which_alternative"))
6664                           (const_int 0))
6665                       (eq_attr "length" "8"))
6666                  (eq_attr "length" "10"))
6667             (const_string "yes")
6668             (const_string "no")))
6669    (set (attr "length")
6670      (if_then_else
6671        (eq (symbol_ref ("which_alternative"))
6672                        (const_int 0))
6673        (if_then_else
6674          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6675               (le (minus (match_dup 5) (pc)) (const_int 256)))
6676          (const_int 4)
6677          (if_then_else
6678            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6679                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6680            (const_int 6)
6681            (const_int 8)))
6682        (if_then_else
6683          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6684               (le (minus (match_dup 5) (pc)) (const_int 256)))
6685          (const_int 6)
6686          (if_then_else
6687            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6688                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6689            (const_int 8)
6690            (const_int 10)))))]
6691 )
6692
6693 (define_insn "*subsi3_cbranch_scratch"
6694   [(set (pc)
6695         (if_then_else
6696          (match_operator 0 "arm_comparison_operator"
6697           [(minus:SI (match_operand:SI 1 "register_operand" "l")
6698                      (match_operand:SI 2 "nonmemory_operand" "l"))
6699            (const_int 0)])
6700          (label_ref (match_operand 3 "" ""))
6701          (pc)))]
6702   "TARGET_THUMB
6703    && (GET_CODE (operands[0]) == EQ
6704        || GET_CODE (operands[0]) == NE
6705        || GET_CODE (operands[0]) == GE
6706        || GET_CODE (operands[0]) == LT)"
6707   "*
6708   output_asm_insn (\"cmp\\t%1, %2\", operands);
6709   switch (get_attr_length (insn))
6710     {
6711     case 4:  return \"b%d0\\t%l3\";
6712     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6713     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6714     }
6715   "
6716   [(set (attr "far_jump")
6717         (if_then_else
6718             (eq_attr "length" "8")
6719             (const_string "yes")
6720             (const_string "no")))
6721    (set (attr "length") 
6722         (if_then_else
6723             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6724                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6725             (const_int 4)
6726             (if_then_else
6727                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6728                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6729                 (const_int 6)
6730                 (const_int 8))))]
6731 )
6732
6733 ;; Comparison and test insns
6734
6735 (define_expand "cmpsi"
6736   [(match_operand:SI 0 "s_register_operand" "")
6737    (match_operand:SI 1 "arm_add_operand" "")]
6738   "TARGET_ARM"
6739   "{
6740     arm_compare_op0 = operands[0];
6741     arm_compare_op1 = operands[1];
6742     DONE;
6743   }"
6744 )
6745
6746 (define_expand "cmpsf"
6747   [(match_operand:SF 0 "s_register_operand" "")
6748    (match_operand:SF 1 "arm_float_compare_operand" "")]
6749   "TARGET_ARM && TARGET_HARD_FLOAT"
6750   "
6751   arm_compare_op0 = operands[0];
6752   arm_compare_op1 = operands[1];
6753   DONE;
6754   "
6755 )
6756
6757 (define_expand "cmpdf"
6758   [(match_operand:DF 0 "s_register_operand" "")
6759    (match_operand:DF 1 "arm_float_compare_operand" "")]
6760   "TARGET_ARM && TARGET_HARD_FLOAT"
6761   "
6762   arm_compare_op0 = operands[0];
6763   arm_compare_op1 = operands[1];
6764   DONE;
6765   "
6766 )
6767
6768 (define_insn "*arm_cmpsi_insn"
6769   [(set (reg:CC CC_REGNUM)
6770         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6771                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
6772   "TARGET_ARM"
6773   "@
6774    cmp%?\\t%0, %1
6775    cmn%?\\t%0, #%n1"
6776   [(set_attr "conds" "set")]
6777 )
6778
6779 (define_insn "*cmpsi_shiftsi"
6780   [(set (reg:CC CC_REGNUM)
6781         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
6782                     (match_operator:SI  3 "shift_operator"
6783                      [(match_operand:SI 1 "s_register_operand" "r")
6784                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
6785   "TARGET_ARM"
6786   "cmp%?\\t%0, %1%S3"
6787   [(set_attr "conds" "set")
6788    (set_attr "shift" "1")
6789    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6790                       (const_string "alu_shift")
6791                       (const_string "alu_shift_reg")))]
6792 )
6793
6794 (define_insn "*cmpsi_shiftsi_swp"
6795   [(set (reg:CC_SWP CC_REGNUM)
6796         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6797                          [(match_operand:SI 1 "s_register_operand" "r")
6798                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
6799                         (match_operand:SI 0 "s_register_operand" "r")))]
6800   "TARGET_ARM"
6801   "cmp%?\\t%0, %1%S3"
6802   [(set_attr "conds" "set")
6803    (set_attr "shift" "1")
6804    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6805                       (const_string "alu_shift")
6806                       (const_string "alu_shift_reg")))]
6807 )
6808
6809 (define_insn "*cmpsi_negshiftsi_si"
6810   [(set (reg:CC_Z CC_REGNUM)
6811         (compare:CC_Z
6812          (neg:SI (match_operator:SI 1 "shift_operator"
6813                     [(match_operand:SI 2 "s_register_operand" "r")
6814                      (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6815          (match_operand:SI 0 "s_register_operand" "r")))]
6816   "TARGET_ARM"
6817   "cmn%?\\t%0, %2%S1"
6818   [(set_attr "conds" "set")
6819    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
6820                                     (const_string "alu_shift")
6821                                     (const_string "alu_shift_reg")))]
6822 )
6823
6824 ;; Cirrus SF compare instruction
6825 (define_insn "*cirrus_cmpsf"
6826   [(set (reg:CCFP CC_REGNUM)
6827         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6828                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
6829   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6830   "cfcmps%?\\tr15, %V0, %V1"
6831   [(set_attr "type"   "mav_farith")
6832    (set_attr "cirrus" "compare")]
6833 )
6834
6835 ;; Cirrus DF compare instruction
6836 (define_insn "*cirrus_cmpdf"
6837   [(set (reg:CCFP CC_REGNUM)
6838         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6839                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
6840   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6841   "cfcmpd%?\\tr15, %V0, %V1"
6842   [(set_attr "type"   "mav_farith")
6843    (set_attr "cirrus" "compare")]
6844 )
6845
6846 ;; Cirrus DI compare instruction
6847 (define_expand "cmpdi"
6848   [(match_operand:DI 0 "cirrus_fp_register" "")
6849    (match_operand:DI 1 "cirrus_fp_register" "")]
6850   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6851   "{
6852      arm_compare_op0 = operands[0];
6853      arm_compare_op1 = operands[1];
6854      DONE;
6855    }")
6856
6857 (define_insn "*cirrus_cmpdi"
6858   [(set (reg:CC CC_REGNUM)
6859         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6860                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
6861   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6862   "cfcmp64%?\\tr15, %V0, %V1"
6863   [(set_attr "type"   "mav_farith")
6864    (set_attr "cirrus" "compare")]
6865 )
6866
6867 ; This insn allows redundant compares to be removed by cse, nothing should
6868 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6869 ; is deleted later on. The match_dup will match the mode here, so that
6870 ; mode changes of the condition codes aren't lost by this even though we don't
6871 ; specify what they are.
6872
6873 (define_insn "*deleted_compare"
6874   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6875   "TARGET_ARM"
6876   "\\t%@ deleted compare"
6877   [(set_attr "conds" "set")
6878    (set_attr "length" "0")]
6879 )
6880
6881 \f
6882 ;; Conditional branch insns
6883
6884 (define_expand "beq"
6885   [(set (pc)
6886         (if_then_else (eq (match_dup 1) (const_int 0))
6887                       (label_ref (match_operand 0 "" ""))
6888                       (pc)))]
6889   "TARGET_ARM"
6890   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6891 )
6892
6893 (define_expand "bne"
6894   [(set (pc)
6895         (if_then_else (ne (match_dup 1) (const_int 0))
6896                       (label_ref (match_operand 0 "" ""))
6897                       (pc)))]
6898   "TARGET_ARM"
6899   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6900 )
6901
6902 (define_expand "bgt"
6903   [(set (pc)
6904         (if_then_else (gt (match_dup 1) (const_int 0))
6905                       (label_ref (match_operand 0 "" ""))
6906                       (pc)))]
6907   "TARGET_ARM"
6908   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6909 )
6910
6911 (define_expand "ble"
6912   [(set (pc)
6913         (if_then_else (le (match_dup 1) (const_int 0))
6914                       (label_ref (match_operand 0 "" ""))
6915                       (pc)))]
6916   "TARGET_ARM"
6917   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6918 )
6919
6920 (define_expand "bge"
6921   [(set (pc)
6922         (if_then_else (ge (match_dup 1) (const_int 0))
6923                       (label_ref (match_operand 0 "" ""))
6924                       (pc)))]
6925   "TARGET_ARM"
6926   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6927 )
6928
6929 (define_expand "blt"
6930   [(set (pc)
6931         (if_then_else (lt (match_dup 1) (const_int 0))
6932                       (label_ref (match_operand 0 "" ""))
6933                       (pc)))]
6934   "TARGET_ARM"
6935   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6936 )
6937
6938 (define_expand "bgtu"
6939   [(set (pc)
6940         (if_then_else (gtu (match_dup 1) (const_int 0))
6941                       (label_ref (match_operand 0 "" ""))
6942                       (pc)))]
6943   "TARGET_ARM"
6944   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6945 )
6946
6947 (define_expand "bleu"
6948   [(set (pc)
6949         (if_then_else (leu (match_dup 1) (const_int 0))
6950                       (label_ref (match_operand 0 "" ""))
6951                       (pc)))]
6952   "TARGET_ARM"
6953   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6954 )
6955
6956 (define_expand "bgeu"
6957   [(set (pc)
6958         (if_then_else (geu (match_dup 1) (const_int 0))
6959                       (label_ref (match_operand 0 "" ""))
6960                       (pc)))]
6961   "TARGET_ARM"
6962   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6963 )
6964
6965 (define_expand "bltu"
6966   [(set (pc)
6967         (if_then_else (ltu (match_dup 1) (const_int 0))
6968                       (label_ref (match_operand 0 "" ""))
6969                       (pc)))]
6970   "TARGET_ARM"
6971   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6972 )
6973
6974 (define_expand "bunordered"
6975   [(set (pc)
6976         (if_then_else (unordered (match_dup 1) (const_int 0))
6977                       (label_ref (match_operand 0 "" ""))
6978                       (pc)))]
6979   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6980   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6981                                       arm_compare_op1);"
6982 )
6983
6984 (define_expand "bordered"
6985   [(set (pc)
6986         (if_then_else (ordered (match_dup 1) (const_int 0))
6987                       (label_ref (match_operand 0 "" ""))
6988                       (pc)))]
6989   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6990   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6991                                       arm_compare_op1);"
6992 )
6993
6994 (define_expand "bungt"
6995   [(set (pc)
6996         (if_then_else (ungt (match_dup 1) (const_int 0))
6997                       (label_ref (match_operand 0 "" ""))
6998                       (pc)))]
6999   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7000   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
7001 )
7002
7003 (define_expand "bunlt"
7004   [(set (pc)
7005         (if_then_else (unlt (match_dup 1) (const_int 0))
7006                       (label_ref (match_operand 0 "" ""))
7007                       (pc)))]
7008   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7009   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
7010 )
7011
7012 (define_expand "bunge"
7013   [(set (pc)
7014         (if_then_else (unge (match_dup 1) (const_int 0))
7015                       (label_ref (match_operand 0 "" ""))
7016                       (pc)))]
7017   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7018   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
7019 )
7020
7021 (define_expand "bunle"
7022   [(set (pc)
7023         (if_then_else (unle (match_dup 1) (const_int 0))
7024                       (label_ref (match_operand 0 "" ""))
7025                       (pc)))]
7026   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7027   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
7028 )
7029
7030 ;; The following two patterns need two branch instructions, since there is
7031 ;; no single instruction that will handle all cases.
7032 (define_expand "buneq"
7033   [(set (pc)
7034         (if_then_else (uneq (match_dup 1) (const_int 0))
7035                       (label_ref (match_operand 0 "" ""))
7036                       (pc)))]
7037   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7038   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
7039 )
7040
7041 (define_expand "bltgt"
7042   [(set (pc)
7043         (if_then_else (ltgt (match_dup 1) (const_int 0))
7044                       (label_ref (match_operand 0 "" ""))
7045                       (pc)))]
7046   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7047   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
7048 )
7049
7050 ;;
7051 ;; Patterns to match conditional branch insns.
7052 ;;
7053
7054 ; Special pattern to match UNEQ.
7055 (define_insn "*arm_buneq"
7056   [(set (pc)
7057         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7058                       (label_ref (match_operand 0 "" ""))
7059                       (pc)))]
7060   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7061   "*
7062   if (arm_ccfsm_state != 0)
7063     abort ();
7064
7065   return \"bvs\\t%l0\;beq\\t%l0\";
7066   "
7067   [(set_attr "conds" "jump_clob")
7068    (set_attr "length" "8")]
7069 )
7070
7071 ; Special pattern to match LTGT.
7072 (define_insn "*arm_bltgt"
7073   [(set (pc)
7074         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7075                       (label_ref (match_operand 0 "" ""))
7076                       (pc)))]
7077   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7078   "*
7079   if (arm_ccfsm_state != 0)
7080     abort ();
7081
7082   return \"bmi\\t%l0\;bgt\\t%l0\";
7083   "
7084   [(set_attr "conds" "jump_clob")
7085    (set_attr "length" "8")]
7086 )
7087
7088 (define_insn "*arm_cond_branch"
7089   [(set (pc)
7090         (if_then_else (match_operator 1 "arm_comparison_operator"
7091                        [(match_operand 2 "cc_register" "") (const_int 0)])
7092                       (label_ref (match_operand 0 "" ""))
7093                       (pc)))]
7094   "TARGET_ARM"
7095   "*
7096   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7097     {
7098       arm_ccfsm_state += 2;
7099       return \"\";
7100     }
7101   return \"b%d1\\t%l0\";
7102   "
7103   [(set_attr "conds" "use")
7104    (set_attr "type" "branch")]
7105 )
7106
7107 ; Special pattern to match reversed UNEQ.
7108 (define_insn "*arm_buneq_reversed"
7109   [(set (pc)
7110         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7111                       (pc)
7112                       (label_ref (match_operand 0 "" ""))))]
7113   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7114   "*
7115   if (arm_ccfsm_state != 0)
7116     abort ();
7117
7118   return \"bmi\\t%l0\;bgt\\t%l0\";
7119   "
7120   [(set_attr "conds" "jump_clob")
7121    (set_attr "length" "8")]
7122 )
7123
7124 ; Special pattern to match reversed LTGT.
7125 (define_insn "*arm_bltgt_reversed"
7126   [(set (pc)
7127         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7128                       (pc)
7129                       (label_ref (match_operand 0 "" ""))))]
7130   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7131   "*
7132   if (arm_ccfsm_state != 0)
7133     abort ();
7134
7135   return \"bvs\\t%l0\;beq\\t%l0\";
7136   "
7137   [(set_attr "conds" "jump_clob")
7138    (set_attr "length" "8")]
7139 )
7140
7141 (define_insn "*arm_cond_branch_reversed"
7142   [(set (pc)
7143         (if_then_else (match_operator 1 "arm_comparison_operator"
7144                        [(match_operand 2 "cc_register" "") (const_int 0)])
7145                       (pc)
7146                       (label_ref (match_operand 0 "" ""))))]
7147   "TARGET_ARM"
7148   "*
7149   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7150     {
7151       arm_ccfsm_state += 2;
7152       return \"\";
7153     }
7154   return \"b%D1\\t%l0\";
7155   "
7156   [(set_attr "conds" "use")
7157    (set_attr "type" "branch")]
7158 )
7159
7160 \f
7161
7162 ; scc insns
7163
7164 (define_expand "seq"
7165   [(set (match_operand:SI 0 "s_register_operand" "")
7166         (eq:SI (match_dup 1) (const_int 0)))]
7167   "TARGET_ARM"
7168   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7169 )
7170
7171 (define_expand "sne"
7172   [(set (match_operand:SI 0 "s_register_operand" "")
7173         (ne:SI (match_dup 1) (const_int 0)))]
7174   "TARGET_ARM"
7175   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7176 )
7177
7178 (define_expand "sgt"
7179   [(set (match_operand:SI 0 "s_register_operand" "")
7180         (gt:SI (match_dup 1) (const_int 0)))]
7181   "TARGET_ARM"
7182   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7183 )
7184
7185 (define_expand "sle"
7186   [(set (match_operand:SI 0 "s_register_operand" "")
7187         (le:SI (match_dup 1) (const_int 0)))]
7188   "TARGET_ARM"
7189   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7190 )
7191
7192 (define_expand "sge"
7193   [(set (match_operand:SI 0 "s_register_operand" "")
7194         (ge:SI (match_dup 1) (const_int 0)))]
7195   "TARGET_ARM"
7196   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7197 )
7198
7199 (define_expand "slt"
7200   [(set (match_operand:SI 0 "s_register_operand" "")
7201         (lt:SI (match_dup 1) (const_int 0)))]
7202   "TARGET_ARM"
7203   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7204 )
7205
7206 (define_expand "sgtu"
7207   [(set (match_operand:SI 0 "s_register_operand" "")
7208         (gtu:SI (match_dup 1) (const_int 0)))]
7209   "TARGET_ARM"
7210   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7211 )
7212
7213 (define_expand "sleu"
7214   [(set (match_operand:SI 0 "s_register_operand" "")
7215         (leu:SI (match_dup 1) (const_int 0)))]
7216   "TARGET_ARM"
7217   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7218 )
7219
7220 (define_expand "sgeu"
7221   [(set (match_operand:SI 0 "s_register_operand" "")
7222         (geu:SI (match_dup 1) (const_int 0)))]
7223   "TARGET_ARM"
7224   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7225 )
7226
7227 (define_expand "sltu"
7228   [(set (match_operand:SI 0 "s_register_operand" "")
7229         (ltu:SI (match_dup 1) (const_int 0)))]
7230   "TARGET_ARM"
7231   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7232 )
7233
7234 (define_expand "sunordered"
7235   [(set (match_operand:SI 0 "s_register_operand" "")
7236         (unordered:SI (match_dup 1) (const_int 0)))]
7237   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7238   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7239                                       arm_compare_op1);"
7240 )
7241
7242 (define_expand "sordered"
7243   [(set (match_operand:SI 0 "s_register_operand" "")
7244         (ordered:SI (match_dup 1) (const_int 0)))]
7245   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7246   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7247                                       arm_compare_op1);"
7248 )
7249
7250 (define_expand "sungt"
7251   [(set (match_operand:SI 0 "s_register_operand" "")
7252         (ungt:SI (match_dup 1) (const_int 0)))]
7253   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7254   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7255                                       arm_compare_op1);"
7256 )
7257
7258 (define_expand "sunge"
7259   [(set (match_operand:SI 0 "s_register_operand" "")
7260         (unge:SI (match_dup 1) (const_int 0)))]
7261   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7262   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7263                                       arm_compare_op1);"
7264 )
7265
7266 (define_expand "sunlt"
7267   [(set (match_operand:SI 0 "s_register_operand" "")
7268         (unlt:SI (match_dup 1) (const_int 0)))]
7269   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7270   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7271                                       arm_compare_op1);"
7272 )
7273
7274 (define_expand "sunle"
7275   [(set (match_operand:SI 0 "s_register_operand" "")
7276         (unle:SI (match_dup 1) (const_int 0)))]
7277   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7278   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7279                                       arm_compare_op1);"
7280 )
7281
7282 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7283 ;;; simple ARM instructions. 
7284 ;
7285 ; (define_expand "suneq"
7286 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7287 ;       (uneq:SI (match_dup 1) (const_int 0)))]
7288 ;   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7289 ;   "abort ();"
7290 ; )
7291 ;
7292 ; (define_expand "sltgt"
7293 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7294 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
7295 ;   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7296 ;   "abort ();"
7297 ; )
7298
7299 (define_insn "*mov_scc"
7300   [(set (match_operand:SI 0 "s_register_operand" "=r")
7301         (match_operator:SI 1 "arm_comparison_operator"
7302          [(match_operand 2 "cc_register" "") (const_int 0)]))]
7303   "TARGET_ARM"
7304   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7305   [(set_attr "conds" "use")
7306    (set_attr "length" "8")]
7307 )
7308
7309 (define_insn "*mov_negscc"
7310   [(set (match_operand:SI 0 "s_register_operand" "=r")
7311         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7312                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7313   "TARGET_ARM"
7314   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7315   [(set_attr "conds" "use")
7316    (set_attr "length" "8")]
7317 )
7318
7319 (define_insn "*mov_notscc"
7320   [(set (match_operand:SI 0 "s_register_operand" "=r")
7321         (not:SI (match_operator:SI 1 "arm_comparison_operator"
7322                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7323   "TARGET_ARM"
7324   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7325   [(set_attr "conds" "use")
7326    (set_attr "length" "8")]
7327 )
7328
7329 \f
7330 ;; Conditional move insns
7331
7332 (define_expand "movsicc"
7333   [(set (match_operand:SI 0 "s_register_operand" "")
7334         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7335                          (match_operand:SI 2 "arm_not_operand" "")
7336                          (match_operand:SI 3 "arm_not_operand" "")))]
7337   "TARGET_ARM"
7338   "
7339   {
7340     enum rtx_code code = GET_CODE (operands[1]);
7341     rtx ccreg;
7342
7343     if (code == UNEQ || code == LTGT)
7344       FAIL;
7345
7346     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7347     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7348   }"
7349 )
7350
7351 (define_expand "movsfcc"
7352   [(set (match_operand:SF 0 "s_register_operand" "")
7353         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7354                          (match_operand:SF 2 "s_register_operand" "")
7355                          (match_operand:SF 3 "nonmemory_operand" "")))]
7356   "TARGET_ARM"
7357   "
7358   {
7359     enum rtx_code code = GET_CODE (operands[1]);
7360     rtx ccreg;
7361
7362     if (code == UNEQ || code == LTGT)
7363       FAIL;
7364
7365     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
7366        Otherwise, ensure it is a valid FP add operand */
7367     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7368         || (!arm_float_add_operand (operands[3], SFmode)))
7369       operands[3] = force_reg (SFmode, operands[3]);
7370
7371     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7372     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7373   }"
7374 )
7375
7376 (define_expand "movdfcc"
7377   [(set (match_operand:DF 0 "s_register_operand" "")
7378         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7379                          (match_operand:DF 2 "s_register_operand" "")
7380                          (match_operand:DF 3 "arm_float_add_operand" "")))]
7381   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7382   "
7383   {
7384     enum rtx_code code = GET_CODE (operands[1]);
7385     rtx ccreg;
7386
7387     if (code == UNEQ || code == LTGT)
7388       FAIL;
7389
7390     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7391     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7392   }"
7393 )
7394
7395 (define_insn "*movsicc_insn"
7396   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7397         (if_then_else:SI
7398          (match_operator 3 "arm_comparison_operator"
7399           [(match_operand 4 "cc_register" "") (const_int 0)])
7400          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7401          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7402   "TARGET_ARM"
7403   "@
7404    mov%D3\\t%0, %2
7405    mvn%D3\\t%0, #%B2
7406    mov%d3\\t%0, %1
7407    mvn%d3\\t%0, #%B1
7408    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7409    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7410    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7411    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7412   [(set_attr "length" "4,4,4,4,8,8,8,8")
7413    (set_attr "conds" "use")]
7414 )
7415
7416 (define_insn "*movsfcc_soft_insn"
7417   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7418         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7419                           [(match_operand 4 "cc_register" "") (const_int 0)])
7420                          (match_operand:SF 1 "s_register_operand" "0,r")
7421                          (match_operand:SF 2 "s_register_operand" "r,0")))]
7422   "TARGET_ARM && TARGET_SOFT_FLOAT"
7423   "@
7424    mov%D3\\t%0, %2
7425    mov%d3\\t%0, %1"
7426   [(set_attr "conds" "use")]
7427 )
7428
7429 \f
7430 ;; Jump and linkage insns
7431
7432 (define_expand "jump"
7433   [(set (pc)
7434         (label_ref (match_operand 0 "" "")))]
7435   "TARGET_EITHER"
7436   ""
7437 )
7438
7439 (define_insn "*arm_jump"
7440   [(set (pc)
7441         (label_ref (match_operand 0 "" "")))]
7442   "TARGET_ARM"
7443   "*
7444   {
7445     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7446       {
7447         arm_ccfsm_state += 2;
7448         return \"\";
7449       }
7450     return \"b%?\\t%l0\";
7451   }
7452   "
7453   [(set_attr "predicable" "yes")]
7454 )
7455
7456 (define_insn "*thumb_jump"
7457   [(set (pc)
7458         (label_ref (match_operand 0 "" "")))]
7459   "TARGET_THUMB"
7460   "*
7461   if (get_attr_length (insn) == 2)
7462     return \"b\\t%l0\";
7463   return \"bl\\t%l0\\t%@ far jump\";
7464   "
7465   [(set (attr "far_jump")
7466         (if_then_else
7467             (eq_attr "length" "4")
7468             (const_string "yes")
7469             (const_string "no")))
7470    (set (attr "length") 
7471         (if_then_else
7472             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7473                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
7474             (const_int 2)
7475             (const_int 4)))]
7476 )
7477
7478 (define_expand "call"
7479   [(parallel [(call (match_operand 0 "memory_operand" "")
7480                     (match_operand 1 "general_operand" ""))
7481               (use (match_operand 2 "" ""))
7482               (clobber (reg:SI LR_REGNUM))])]
7483   "TARGET_EITHER"
7484   "
7485   {
7486     rtx callee;
7487     
7488     /* In an untyped call, we can get NULL for operand 2.  */
7489     if (operands[2] == NULL_RTX)
7490       operands[2] = const0_rtx;
7491       
7492     /* This is to decide if we should generate indirect calls by loading the
7493        32 bit address of the callee into a register before performing the
7494        branch and link.  operand[2] encodes the long_call/short_call
7495        attribute of the function being called.  This attribute is set whenever
7496        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7497        is used, and the short_call attribute can also be set if function is
7498        declared as static or if it has already been defined in the current
7499        compilation unit.  See arm.c and arm.h for info about this.  The third
7500        parameter to arm_is_longcall_p is used to tell it which pattern
7501        invoked it.  */
7502     callee  = XEXP (operands[0], 0);
7503     
7504     if (GET_CODE (callee) != REG
7505        && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7506       XEXP (operands[0], 0) = force_reg (Pmode, callee);
7507   }"
7508 )
7509
7510 (define_insn "*call_reg_armv5"
7511   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7512          (match_operand 1 "" ""))
7513    (use (match_operand 2 "" ""))
7514    (clobber (reg:SI LR_REGNUM))]
7515   "TARGET_ARM && arm_arch5"
7516   "blx%?\\t%0"
7517   [(set_attr "type" "call")]
7518 )
7519
7520 (define_insn "*call_reg_arm"
7521   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7522          (match_operand 1 "" ""))
7523    (use (match_operand 2 "" ""))
7524    (clobber (reg:SI LR_REGNUM))]
7525   "TARGET_ARM && !arm_arch5"
7526   "*
7527   return output_call (operands);
7528   "
7529   ;; length is worst case, normally it is only two
7530   [(set_attr "length" "12")
7531    (set_attr "type" "call")]
7532 )
7533
7534 (define_insn "*call_mem"
7535   [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7536          (match_operand 1 "" ""))
7537    (use (match_operand 2 "" ""))
7538    (clobber (reg:SI LR_REGNUM))]
7539   "TARGET_ARM"
7540   "*
7541   return output_call_mem (operands);
7542   "
7543   [(set_attr "length" "12")
7544    (set_attr "type" "call")]
7545 )
7546
7547 (define_insn "*call_reg_thumb_v5"
7548   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7549          (match_operand 1 "" ""))
7550    (use (match_operand 2 "" ""))
7551    (clobber (reg:SI LR_REGNUM))]
7552   "TARGET_THUMB && arm_arch5"
7553   "blx\\t%0"
7554   [(set_attr "length" "2")
7555    (set_attr "type" "call")]
7556 )
7557
7558 (define_insn "*call_reg_thumb"
7559   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7560          (match_operand 1 "" ""))
7561    (use (match_operand 2 "" ""))
7562    (clobber (reg:SI LR_REGNUM))]
7563   "TARGET_THUMB && !arm_arch5"
7564   "*
7565   {
7566     if (!TARGET_CALLER_INTERWORKING)
7567       return thumb_call_via_reg (operands[0]);
7568     else if (operands[1] == const0_rtx)
7569       return \"bl\\t%__interwork_call_via_%0\";
7570     else if (frame_pointer_needed)
7571       return \"bl\\t%__interwork_r7_call_via_%0\";
7572     else
7573       return \"bl\\t%__interwork_r11_call_via_%0\";
7574   }"
7575   [(set_attr "type" "call")]
7576 )
7577
7578 (define_expand "call_value"
7579   [(parallel [(set (match_operand       0 "" "")
7580                    (call (match_operand 1 "memory_operand" "")
7581                          (match_operand 2 "general_operand" "")))
7582               (use (match_operand 3 "" ""))
7583               (clobber (reg:SI LR_REGNUM))])]
7584   "TARGET_EITHER"
7585   "
7586   {
7587     rtx callee = XEXP (operands[1], 0);
7588     
7589     /* In an untyped call, we can get NULL for operand 2.  */
7590     if (operands[3] == 0)
7591       operands[3] = const0_rtx;
7592       
7593     /* See the comment in define_expand \"call\".  */
7594     if (GET_CODE (callee) != REG
7595         && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7596       XEXP (operands[1], 0) = force_reg (Pmode, callee);
7597   }"
7598 )
7599
7600 (define_insn "*call_value_reg_armv5"
7601   [(set (match_operand 0 "" "")
7602         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7603               (match_operand 2 "" "")))
7604    (use (match_operand 3 "" ""))
7605    (clobber (reg:SI LR_REGNUM))]
7606   "TARGET_ARM && arm_arch5"
7607   "blx%?\\t%1"
7608   [(set_attr "type" "call")]
7609 )
7610
7611 (define_insn "*call_value_reg_arm"
7612   [(set (match_operand 0 "" "")
7613         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7614               (match_operand 2 "" "")))
7615    (use (match_operand 3 "" ""))
7616    (clobber (reg:SI LR_REGNUM))]
7617   "TARGET_ARM && !arm_arch5"
7618   "*
7619   return output_call (&operands[1]);
7620   "
7621   [(set_attr "length" "12")
7622    (set_attr "type" "call")]
7623 )
7624
7625 (define_insn "*call_value_mem"
7626   [(set (match_operand 0 "" "")
7627         (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7628               (match_operand 2 "" "")))
7629    (use (match_operand 3 "" ""))
7630    (clobber (reg:SI LR_REGNUM))]
7631   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7632   "*
7633   return output_call_mem (&operands[1]);
7634   "
7635   [(set_attr "length" "12")
7636    (set_attr "type" "call")]
7637 )
7638
7639 (define_insn "*call_value_reg_thumb_v5"
7640   [(set (match_operand 0 "" "")
7641         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7642               (match_operand 2 "" "")))
7643    (use (match_operand 3 "" ""))
7644    (clobber (reg:SI LR_REGNUM))]
7645   "TARGET_THUMB && arm_arch5"
7646   "blx\\t%1"
7647   [(set_attr "length" "2")
7648    (set_attr "type" "call")]
7649 )
7650
7651 (define_insn "*call_value_reg_thumb"
7652   [(set (match_operand 0 "" "")
7653         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7654               (match_operand 2 "" "")))
7655    (use (match_operand 3 "" ""))
7656    (clobber (reg:SI LR_REGNUM))]
7657   "TARGET_THUMB && !arm_arch5"
7658   "*
7659   {
7660     if (!TARGET_CALLER_INTERWORKING)
7661       return thumb_call_via_reg (operands[1]);
7662     else if (operands[2] == const0_rtx)
7663       return \"bl\\t%__interwork_call_via_%1\";
7664     else if (frame_pointer_needed)
7665       return \"bl\\t%__interwork_r7_call_via_%1\";
7666     else
7667       return \"bl\\t%__interwork_r11_call_via_%1\";
7668   }"
7669   [(set_attr "type" "call")]
7670 )
7671
7672 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7673 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7674
7675 (define_insn "*call_symbol"
7676   [(call (mem:SI (match_operand:SI 0 "" ""))
7677          (match_operand 1 "" ""))
7678    (use (match_operand 2 "" ""))
7679    (clobber (reg:SI LR_REGNUM))]
7680   "TARGET_ARM
7681    && (GET_CODE (operands[0]) == SYMBOL_REF)
7682    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7683   "*
7684   {
7685     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7686   }"
7687   [(set_attr "type" "call")]
7688 )
7689
7690 (define_insn "*call_value_symbol"
7691   [(set (match_operand 0 "" "")
7692         (call (mem:SI (match_operand:SI 1 "" ""))
7693         (match_operand:SI 2 "" "")))
7694    (use (match_operand 3 "" ""))
7695    (clobber (reg:SI LR_REGNUM))]
7696   "TARGET_ARM
7697    && (GET_CODE (operands[1]) == SYMBOL_REF)
7698    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7699   "*
7700   {
7701     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7702   }"
7703   [(set_attr "type" "call")]
7704 )
7705
7706 (define_insn "*call_insn"
7707   [(call (mem:SI (match_operand:SI 0 "" ""))
7708          (match_operand:SI 1 "" ""))
7709    (use (match_operand 2 "" ""))
7710    (clobber (reg:SI LR_REGNUM))]
7711   "TARGET_THUMB
7712    && GET_CODE (operands[0]) == SYMBOL_REF
7713    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7714   "bl\\t%a0"
7715   [(set_attr "length" "4")
7716    (set_attr "type" "call")]
7717 )
7718
7719 (define_insn "*call_value_insn"
7720   [(set (match_operand 0 "" "")
7721         (call (mem:SI (match_operand 1 "" ""))
7722               (match_operand 2 "" "")))
7723    (use (match_operand 3 "" ""))
7724    (clobber (reg:SI LR_REGNUM))]
7725   "TARGET_THUMB
7726    && GET_CODE (operands[1]) == SYMBOL_REF
7727    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7728   "bl\\t%a1"
7729   [(set_attr "length" "4")
7730    (set_attr "type" "call")]
7731 )
7732
7733 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7734 (define_expand "sibcall"
7735   [(parallel [(call (match_operand 0 "memory_operand" "")
7736                     (match_operand 1 "general_operand" ""))
7737               (return)
7738               (use (match_operand 2 "" ""))])]
7739   "TARGET_ARM"
7740   "
7741   {
7742     if (operands[2] == NULL_RTX)
7743       operands[2] = const0_rtx;
7744   }"
7745 )
7746
7747 (define_expand "sibcall_value"
7748   [(parallel [(set (match_operand 0 "" "")
7749                    (call (match_operand 1 "memory_operand" "")
7750                          (match_operand 2 "general_operand" "")))
7751               (return)
7752               (use (match_operand 3 "" ""))])]
7753   "TARGET_ARM"
7754   "
7755   {
7756     if (operands[3] == NULL_RTX)
7757       operands[3] = const0_rtx;
7758   }"
7759 )
7760
7761 (define_insn "*sibcall_insn"
7762  [(call (mem:SI (match_operand:SI 0 "" "X"))
7763         (match_operand 1 "" ""))
7764   (return)
7765   (use (match_operand 2 "" ""))]
7766   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7767   "*
7768   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7769   "
7770   [(set_attr "type" "call")]
7771 )
7772
7773 (define_insn "*sibcall_value_insn"
7774  [(set (match_operand 0 "" "")
7775        (call (mem:SI (match_operand:SI 1 "" "X"))
7776              (match_operand 2 "" "")))
7777   (return)
7778   (use (match_operand 3 "" ""))]
7779   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7780   "*
7781   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7782   "
7783   [(set_attr "type" "call")]
7784 )
7785
7786 ;; Often the return insn will be the same as loading from memory, so set attr
7787 (define_insn "return"
7788   [(return)]
7789   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7790   "*
7791   {
7792     if (arm_ccfsm_state == 2)
7793       {
7794         arm_ccfsm_state += 2;
7795         return \"\";
7796       }
7797     return output_return_instruction (const_true_rtx, TRUE, FALSE);
7798   }"
7799   [(set_attr "type" "load1")
7800    (set_attr "length" "12")
7801    (set_attr "predicable" "yes")]
7802 )
7803
7804 (define_insn "*cond_return"
7805   [(set (pc)
7806         (if_then_else (match_operator 0 "arm_comparison_operator"
7807                        [(match_operand 1 "cc_register" "") (const_int 0)])
7808                       (return)
7809                       (pc)))]
7810   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7811   "*
7812   {
7813     if (arm_ccfsm_state == 2)
7814       {
7815         arm_ccfsm_state += 2;
7816         return \"\";
7817       }
7818     return output_return_instruction (operands[0], TRUE, FALSE);
7819   }"
7820   [(set_attr "conds" "use")
7821    (set_attr "length" "12")
7822    (set_attr "type" "load1")]
7823 )
7824
7825 (define_insn "*cond_return_inverted"
7826   [(set (pc)
7827         (if_then_else (match_operator 0 "arm_comparison_operator"
7828                        [(match_operand 1 "cc_register" "") (const_int 0)])
7829                       (pc)
7830                       (return)))]
7831   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7832   "*
7833   {
7834     if (arm_ccfsm_state == 2)
7835       {
7836         arm_ccfsm_state += 2;
7837         return \"\";
7838       }
7839     return output_return_instruction (operands[0], TRUE, TRUE);
7840   }"
7841   [(set_attr "conds" "use")
7842    (set_attr "length" "12")
7843    (set_attr "type" "load1")]
7844 )
7845
7846 ;; Generate a sequence of instructions to determine if the processor is
7847 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7848 ;; mask.
7849
7850 (define_expand "return_addr_mask"
7851   [(set (match_dup 1)
7852       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7853                        (const_int 0)))
7854    (set (match_operand:SI 0 "s_register_operand" "")
7855       (if_then_else:SI (eq (match_dup 1) (const_int 0))
7856                        (const_int -1)
7857                        (const_int 67108860)))] ; 0x03fffffc
7858   "TARGET_ARM"
7859   "
7860   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7861   ")
7862
7863 (define_insn "*check_arch2"
7864   [(set (match_operand:CC_NOOV 0 "cc_register" "")
7865       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7866                        (const_int 0)))]
7867   "TARGET_ARM"
7868   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7869   [(set_attr "length" "8")
7870    (set_attr "conds" "set")]
7871 )
7872
7873 ;; Call subroutine returning any type.
7874
7875 (define_expand "untyped_call"
7876   [(parallel [(call (match_operand 0 "" "")
7877                     (const_int 0))
7878               (match_operand 1 "" "")
7879               (match_operand 2 "" "")])]
7880   "TARGET_EITHER"
7881   "
7882   {
7883     int i;
7884     rtx par = gen_rtx_PARALLEL (VOIDmode,
7885                                 rtvec_alloc (XVECLEN (operands[2], 0)));
7886     rtx addr = gen_reg_rtx (Pmode);
7887     rtx mem;
7888     int size = 0;
7889
7890     emit_move_insn (addr, XEXP (operands[1], 0));
7891     mem = change_address (operands[1], BLKmode, addr);
7892
7893     for (i = 0; i < XVECLEN (operands[2], 0); i++)
7894       {
7895         rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
7896
7897         /* Default code only uses r0 as a return value, but we could
7898            be using anything up to 4 registers.  */
7899         if (REGNO (src) == R0_REGNUM)
7900           src = gen_rtx_REG (TImode, R0_REGNUM);
7901
7902         XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
7903                                                  GEN_INT (size));
7904         size += GET_MODE_SIZE (GET_MODE (src));
7905       }
7906
7907     emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
7908                                     const0_rtx));
7909
7910     size = 0;
7911
7912     for (i = 0; i < XVECLEN (par, 0); i++)
7913       {
7914         HOST_WIDE_INT offset = 0;
7915         rtx reg = XEXP (XVECEXP (par, 0, i), 0);
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_store_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 (mem, reg);
7931             size = GET_MODE_SIZE (GET_MODE (reg));
7932           }
7933       }
7934
7935     /* The optimizer does not know that the call sets the function value
7936        registers we stored in the result block.  We avoid problems by
7937        claiming that all hard registers are used and clobbered at this
7938        point.  */
7939     emit_insn (gen_blockage ());
7940
7941     DONE;
7942   }"
7943 )
7944
7945 (define_expand "untyped_return"
7946   [(match_operand:BLK 0 "memory_operand" "")
7947    (match_operand 1 "" "")]
7948   "TARGET_EITHER"
7949   "
7950   {
7951     int i;
7952     rtx addr = gen_reg_rtx (Pmode);
7953     rtx mem;
7954     int size = 0;
7955
7956     emit_move_insn (addr, XEXP (operands[0], 0));
7957     mem = change_address (operands[0], BLKmode, addr);
7958
7959     for (i = 0; i < XVECLEN (operands[1], 0); i++)
7960       {
7961         HOST_WIDE_INT offset = 0;
7962         rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
7963
7964         if (size != 0)
7965           emit_move_insn (addr, plus_constant (addr, size));
7966
7967         mem = change_address (mem, GET_MODE (reg), NULL);
7968         if (REGNO (reg) == R0_REGNUM)
7969           {
7970             /* On thumb we have to use a write-back instruction.  */
7971             emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
7972                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7973             size = TARGET_ARM ? 16 : 0;
7974           }
7975         else
7976           {
7977             emit_move_insn (reg, mem);
7978             size = GET_MODE_SIZE (GET_MODE (reg));
7979           }
7980       }
7981
7982     /* Emit USE insns before the return.  */
7983     for (i = 0; i < XVECLEN (operands[1], 0); i++)
7984       emit_insn (gen_rtx_USE (VOIDmode,
7985                               SET_DEST (XVECEXP (operands[1], 0, i))));
7986
7987     /* Construct the return.  */
7988     expand_naked_return ();
7989
7990     DONE;
7991   }"
7992 )
7993
7994 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7995 ;; all of memory.  This blocks insns from being moved across this point.
7996
7997 (define_insn "blockage"
7998   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
7999   "TARGET_EITHER"
8000   ""
8001   [(set_attr "length" "0")
8002    (set_attr "type" "block")]
8003 )
8004
8005 (define_expand "casesi"
8006   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
8007    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
8008    (match_operand:SI 2 "const_int_operand" "")  ; total range
8009    (match_operand:SI 3 "" "")                   ; table label
8010    (match_operand:SI 4 "" "")]                  ; Out of range label
8011   "TARGET_ARM"
8012   "
8013   {
8014     rtx reg;
8015     if (operands[1] != const0_rtx)
8016       {
8017         reg = gen_reg_rtx (SImode);
8018
8019         emit_insn (gen_addsi3 (reg, operands[0],
8020                                GEN_INT (-INTVAL (operands[1]))));
8021         operands[0] = reg;
8022       }
8023
8024     if (!const_ok_for_arm (INTVAL (operands[2])))
8025       operands[2] = force_reg (SImode, operands[2]);
8026
8027     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
8028                                          operands[4]));
8029     DONE;
8030   }"
8031 )
8032
8033 ;; The USE in this pattern is needed to tell flow analysis that this is
8034 ;; a CASESI insn.  It has no other purpose.
8035 (define_insn "casesi_internal"
8036   [(parallel [(set (pc)
8037                (if_then_else
8038                 (leu (match_operand:SI 0 "s_register_operand" "r")
8039                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
8040                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8041                                  (label_ref (match_operand 2 "" ""))))
8042                 (label_ref (match_operand 3 "" ""))))
8043               (clobber (reg:CC CC_REGNUM))
8044               (use (label_ref (match_dup 2)))])]
8045   "TARGET_ARM"
8046   "*
8047     if (flag_pic)
8048       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8049     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8050   "
8051   [(set_attr "conds" "clob")
8052    (set_attr "length" "12")]
8053 )
8054
8055 (define_expand "indirect_jump"
8056   [(set (pc)
8057         (match_operand:SI 0 "s_register_operand" ""))]
8058   "TARGET_EITHER"
8059   ""
8060 )
8061
8062 ;; NB Never uses BX.
8063 (define_insn "*arm_indirect_jump"
8064   [(set (pc)
8065         (match_operand:SI 0 "s_register_operand" "r"))]
8066   "TARGET_ARM"
8067   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
8068   [(set_attr "predicable" "yes")]
8069 )
8070
8071 (define_insn "*load_indirect_jump"
8072   [(set (pc)
8073         (match_operand:SI 0 "memory_operand" "m"))]
8074   "TARGET_ARM"
8075   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
8076   [(set_attr "type" "load1")
8077    (set_attr "pool_range" "4096")
8078    (set_attr "neg_pool_range" "4084")
8079    (set_attr "predicable" "yes")]
8080 )
8081
8082 ;; NB Never uses BX.
8083 (define_insn "*thumb_indirect_jump"
8084   [(set (pc)
8085         (match_operand:SI 0 "register_operand" "l*r"))]
8086   "TARGET_THUMB"
8087   "mov\\tpc, %0"
8088   [(set_attr "conds" "clob")
8089    (set_attr "length" "2")]
8090 )
8091
8092 \f
8093 ;; Misc insns
8094
8095 (define_insn "nop"
8096   [(const_int 0)]
8097   "TARGET_EITHER"
8098   "*
8099   if (TARGET_ARM)
8100     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8101   return  \"mov\\tr8, r8\";
8102   "
8103   [(set (attr "length")
8104         (if_then_else (eq_attr "is_thumb" "yes")
8105                       (const_int 2)
8106                       (const_int 4)))]
8107 )
8108
8109 \f
8110 ;; Patterns to allow combination of arithmetic, cond code and shifts
8111
8112 (define_insn "*arith_shiftsi"
8113   [(set (match_operand:SI 0 "s_register_operand" "=r")
8114         (match_operator:SI 1 "shiftable_operator"
8115           [(match_operator:SI 3 "shift_operator"
8116              [(match_operand:SI 4 "s_register_operand" "r")
8117               (match_operand:SI 5 "reg_or_int_operand" "rI")])
8118            (match_operand:SI 2 "s_register_operand" "r")]))]
8119   "TARGET_ARM"
8120   "%i1%?\\t%0, %2, %4%S3"
8121   [(set_attr "predicable" "yes")
8122    (set_attr "shift" "4")
8123    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8124                       (const_string "alu_shift")
8125                       (const_string "alu_shift_reg")))]
8126 )
8127
8128 (define_split
8129   [(set (match_operand:SI 0 "s_register_operand" "")
8130         (match_operator:SI 1 "shiftable_operator"
8131          [(match_operator:SI 2 "shiftable_operator"
8132            [(match_operator:SI 3 "shift_operator"
8133              [(match_operand:SI 4 "s_register_operand" "")
8134               (match_operand:SI 5 "reg_or_int_operand" "")])
8135             (match_operand:SI 6 "s_register_operand" "")])
8136           (match_operand:SI 7 "arm_rhs_operand" "")]))
8137    (clobber (match_operand:SI 8 "s_register_operand" ""))]
8138   "TARGET_ARM"
8139   [(set (match_dup 8)
8140         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8141                          (match_dup 6)]))
8142    (set (match_dup 0)
8143         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8144   "")
8145
8146 (define_insn "*arith_shiftsi_compare0"
8147   [(set (reg:CC_NOOV CC_REGNUM)
8148         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8149                           [(match_operator:SI 3 "shift_operator"
8150                             [(match_operand:SI 4 "s_register_operand" "r")
8151                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8152                            (match_operand:SI 2 "s_register_operand" "r")])
8153                          (const_int 0)))
8154    (set (match_operand:SI 0 "s_register_operand" "=r")
8155         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8156                          (match_dup 2)]))]
8157   "TARGET_ARM"
8158   "%i1%?s\\t%0, %2, %4%S3"
8159   [(set_attr "conds" "set")
8160    (set_attr "shift" "4")
8161    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8162                       (const_string "alu_shift")
8163                       (const_string "alu_shift_reg")))]
8164 )
8165
8166 (define_insn "*arith_shiftsi_compare0_scratch"
8167   [(set (reg:CC_NOOV CC_REGNUM)
8168         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8169                           [(match_operator:SI 3 "shift_operator"
8170                             [(match_operand:SI 4 "s_register_operand" "r")
8171                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8172                            (match_operand:SI 2 "s_register_operand" "r")])
8173                          (const_int 0)))
8174    (clobber (match_scratch:SI 0 "=r"))]
8175   "TARGET_ARM"
8176   "%i1%?s\\t%0, %2, %4%S3"
8177   [(set_attr "conds" "set")
8178    (set_attr "shift" "4")
8179    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8180                       (const_string "alu_shift")
8181                       (const_string "alu_shift_reg")))]
8182 )
8183
8184 (define_insn "*sub_shiftsi"
8185   [(set (match_operand:SI 0 "s_register_operand" "=r")
8186         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8187                   (match_operator:SI 2 "shift_operator"
8188                    [(match_operand:SI 3 "s_register_operand" "r")
8189                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
8190   "TARGET_ARM"
8191   "sub%?\\t%0, %1, %3%S2"
8192   [(set_attr "predicable" "yes")
8193    (set_attr "shift" "3")
8194    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8195                       (const_string "alu_shift")
8196                       (const_string "alu_shift_reg")))]
8197 )
8198
8199 (define_insn "*sub_shiftsi_compare0"
8200   [(set (reg:CC_NOOV CC_REGNUM)
8201         (compare:CC_NOOV
8202          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8203                    (match_operator:SI 2 "shift_operator"
8204                     [(match_operand:SI 3 "s_register_operand" "r")
8205                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8206          (const_int 0)))
8207    (set (match_operand:SI 0 "s_register_operand" "=r")
8208         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8209                                                  (match_dup 4)])))]
8210   "TARGET_ARM"
8211   "sub%?s\\t%0, %1, %3%S2"
8212   [(set_attr "conds" "set")
8213    (set_attr "shift" "3")
8214    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8215                       (const_string "alu_shift")
8216                       (const_string "alu_shift_reg")))]
8217 )
8218
8219 (define_insn "*sub_shiftsi_compare0_scratch"
8220   [(set (reg:CC_NOOV CC_REGNUM)
8221         (compare:CC_NOOV
8222          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8223                    (match_operator:SI 2 "shift_operator"
8224                     [(match_operand:SI 3 "s_register_operand" "r")
8225                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8226          (const_int 0)))
8227    (clobber (match_scratch:SI 0 "=r"))]
8228   "TARGET_ARM"
8229   "sub%?s\\t%0, %1, %3%S2"
8230   [(set_attr "conds" "set")
8231    (set_attr "shift" "3")
8232    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8233                       (const_string "alu_shift")
8234                       (const_string "alu_shift_reg")))]
8235 )
8236
8237 \f
8238
8239 (define_insn "*and_scc"
8240   [(set (match_operand:SI 0 "s_register_operand" "=r")
8241         (and:SI (match_operator:SI 1 "arm_comparison_operator"
8242                  [(match_operand 3 "cc_register" "") (const_int 0)])
8243                 (match_operand:SI 2 "s_register_operand" "r")))]
8244   "TARGET_ARM"
8245   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8246   [(set_attr "conds" "use")
8247    (set_attr "length" "8")]
8248 )
8249
8250 (define_insn "*ior_scc"
8251   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8252         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8253                  [(match_operand 3 "cc_register" "") (const_int 0)])
8254                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8255   "TARGET_ARM"
8256   "@
8257    orr%d2\\t%0, %1, #1
8258    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8259   [(set_attr "conds" "use")
8260    (set_attr "length" "4,8")]
8261 )
8262
8263 (define_insn "*compare_scc"
8264   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8265         (match_operator:SI 1 "arm_comparison_operator"
8266          [(match_operand:SI 2 "s_register_operand" "r,r")
8267           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8268    (clobber (reg:CC CC_REGNUM))]
8269   "TARGET_ARM"
8270   "*
8271     if (operands[3] == const0_rtx)
8272       {
8273         if (GET_CODE (operands[1]) == LT)
8274           return \"mov\\t%0, %2, lsr #31\";
8275
8276         if (GET_CODE (operands[1]) == GE)
8277           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8278
8279         if (GET_CODE (operands[1]) == EQ)
8280           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8281       }
8282
8283     if (GET_CODE (operands[1]) == NE)
8284       {
8285         if (which_alternative == 1)
8286           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8287         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8288       }
8289     if (which_alternative == 1)
8290       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8291     else
8292       output_asm_insn (\"cmp\\t%2, %3\", operands);
8293     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8294   "
8295   [(set_attr "conds" "clob")
8296    (set_attr "length" "12")]
8297 )
8298
8299 (define_insn "*cond_move"
8300   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8301         (if_then_else:SI (match_operator 3 "equality_operator"
8302                           [(match_operator 4 "arm_comparison_operator"
8303                             [(match_operand 5 "cc_register" "") (const_int 0)])
8304                            (const_int 0)])
8305                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8306                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8307   "TARGET_ARM"
8308   "*
8309     if (GET_CODE (operands[3]) == NE)
8310       {
8311         if (which_alternative != 1)
8312           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8313         if (which_alternative != 0)
8314           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8315         return \"\";
8316       }
8317     if (which_alternative != 0)
8318       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8319     if (which_alternative != 1)
8320       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8321     return \"\";
8322   "
8323   [(set_attr "conds" "use")
8324    (set_attr "length" "4,4,8")]
8325 )
8326
8327 (define_insn "*cond_arith"
8328   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8329         (match_operator:SI 5 "shiftable_operator" 
8330          [(match_operator:SI 4 "arm_comparison_operator"
8331            [(match_operand:SI 2 "s_register_operand" "r,r")
8332             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8333           (match_operand:SI 1 "s_register_operand" "0,?r")]))
8334    (clobber (reg:CC CC_REGNUM))]
8335   "TARGET_ARM"
8336   "*
8337     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8338       return \"%i5\\t%0, %1, %2, lsr #31\";
8339
8340     output_asm_insn (\"cmp\\t%2, %3\", operands);
8341     if (GET_CODE (operands[5]) == AND)
8342       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8343     else if (GET_CODE (operands[5]) == MINUS)
8344       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8345     else if (which_alternative != 0)
8346       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8347     return \"%i5%d4\\t%0, %1, #1\";
8348   "
8349   [(set_attr "conds" "clob")
8350    (set_attr "length" "12")]
8351 )
8352
8353 (define_insn "*cond_sub"
8354   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8355         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8356                   (match_operator:SI 4 "arm_comparison_operator"
8357                    [(match_operand:SI 2 "s_register_operand" "r,r")
8358                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8359    (clobber (reg:CC CC_REGNUM))]
8360   "TARGET_ARM"
8361   "*
8362     output_asm_insn (\"cmp\\t%2, %3\", operands);
8363     if (which_alternative != 0)
8364       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8365     return \"sub%d4\\t%0, %1, #1\";
8366   "
8367   [(set_attr "conds" "clob")
8368    (set_attr "length" "8,12")]
8369 )
8370
8371 (define_insn "*cmp_ite0"
8372   [(set (match_operand 6 "dominant_cc_register" "")
8373         (compare
8374          (if_then_else:SI
8375           (match_operator 4 "arm_comparison_operator"
8376            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8377             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8378           (match_operator:SI 5 "arm_comparison_operator"
8379            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8380             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8381           (const_int 0))
8382          (const_int 0)))]
8383   "TARGET_ARM"
8384   "*
8385   {
8386     static const char * const opcodes[4][2] =
8387     {
8388       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8389        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8390       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8391        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8392       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8393        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8394       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8395        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8396     };
8397     int swap =
8398       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8399
8400     return opcodes[which_alternative][swap];
8401   }"
8402   [(set_attr "conds" "set")
8403    (set_attr "length" "8")]
8404 )
8405
8406 (define_insn "*cmp_ite1"
8407   [(set (match_operand 6 "dominant_cc_register" "")
8408         (compare
8409          (if_then_else:SI
8410           (match_operator 4 "arm_comparison_operator"
8411            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8412             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8413           (match_operator:SI 5 "arm_comparison_operator"
8414            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8415             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8416           (const_int 1))
8417          (const_int 0)))]
8418   "TARGET_ARM"
8419   "*
8420   {
8421     static const char * const opcodes[4][2] =
8422     {
8423       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8424        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8425       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8426        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8427       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8428        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8429       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8430        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8431     };
8432     int swap =
8433       comparison_dominates_p (GET_CODE (operands[5]),
8434                               reverse_condition (GET_CODE (operands[4])));
8435
8436     return opcodes[which_alternative][swap];
8437   }"
8438   [(set_attr "conds" "set")
8439    (set_attr "length" "8")]
8440 )
8441
8442 (define_insn "*cmp_and"
8443   [(set (match_operand 6 "dominant_cc_register" "")
8444         (compare
8445          (and:SI
8446           (match_operator 4 "arm_comparison_operator"
8447            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8448             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8449           (match_operator:SI 5 "arm_comparison_operator"
8450            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8451             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8452          (const_int 0)))]
8453   "TARGET_ARM"
8454   "*
8455   {
8456     static const char *const opcodes[4][2] =
8457     {
8458       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8459        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8460       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8461        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8462       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8463        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8464       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8465        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8466     };
8467     int swap =
8468       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8469
8470     return opcodes[which_alternative][swap];
8471   }"
8472   [(set_attr "conds" "set")
8473    (set_attr "predicable" "no")
8474    (set_attr "length" "8")]
8475 )
8476
8477 (define_insn "*cmp_ior"
8478   [(set (match_operand 6 "dominant_cc_register" "")
8479         (compare
8480          (ior:SI
8481           (match_operator 4 "arm_comparison_operator"
8482            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8483             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8484           (match_operator:SI 5 "arm_comparison_operator"
8485            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8486             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8487          (const_int 0)))]
8488   "TARGET_ARM"
8489   "*
8490 {
8491   static const char *const opcodes[4][2] =
8492   {
8493     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8494      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8495     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8496      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8497     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8498      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8499     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8500      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8501   };
8502   int swap =
8503     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8504
8505   return opcodes[which_alternative][swap];
8506 }
8507 "
8508   [(set_attr "conds" "set")
8509    (set_attr "length" "8")]
8510 )
8511
8512 (define_insn_and_split "*ior_scc_scc"
8513   [(set (match_operand:SI 0 "s_register_operand" "=r")
8514         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8515                  [(match_operand:SI 1 "s_register_operand" "r")
8516                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8517                 (match_operator:SI 6 "arm_comparison_operator"
8518                  [(match_operand:SI 4 "s_register_operand" "r")
8519                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8520    (clobber (reg:CC CC_REGNUM))]
8521   "TARGET_ARM
8522    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8523        != CCmode)"
8524   "#"
8525   "TARGET_ARM && reload_completed"
8526   [(set (match_dup 7)
8527         (compare
8528          (ior:SI
8529           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8530           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8531          (const_int 0)))
8532    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8533   "operands[7]
8534      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8535                                                   DOM_CC_X_OR_Y),
8536                     CC_REGNUM);"
8537   [(set_attr "conds" "clob")
8538    (set_attr "length" "16")])
8539
8540 ; If the above pattern is followed by a CMP insn, then the compare is 
8541 ; redundant, since we can rework the conditional instruction that follows.
8542 (define_insn_and_split "*ior_scc_scc_cmp"
8543   [(set (match_operand 0 "dominant_cc_register" "")
8544         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8545                           [(match_operand:SI 1 "s_register_operand" "r")
8546                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8547                          (match_operator:SI 6 "arm_comparison_operator"
8548                           [(match_operand:SI 4 "s_register_operand" "r")
8549                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8550                  (const_int 0)))
8551    (set (match_operand:SI 7 "s_register_operand" "=r")
8552         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8553                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8554   "TARGET_ARM"
8555   "#"
8556   "TARGET_ARM && reload_completed"
8557   [(set (match_dup 0)
8558         (compare
8559          (ior:SI
8560           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8561           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8562          (const_int 0)))
8563    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8564   ""
8565   [(set_attr "conds" "set")
8566    (set_attr "length" "16")])
8567
8568 (define_insn_and_split "*and_scc_scc"
8569   [(set (match_operand:SI 0 "s_register_operand" "=r")
8570         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8571                  [(match_operand:SI 1 "s_register_operand" "r")
8572                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8573                 (match_operator:SI 6 "arm_comparison_operator"
8574                  [(match_operand:SI 4 "s_register_operand" "r")
8575                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8576    (clobber (reg:CC CC_REGNUM))]
8577   "TARGET_ARM
8578    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8579        != CCmode)"
8580   "#"
8581   "TARGET_ARM && reload_completed
8582    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8583        != CCmode)"
8584   [(set (match_dup 7)
8585         (compare
8586          (and:SI
8587           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8588           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8589          (const_int 0)))
8590    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8591   "operands[7]
8592      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8593                                                   DOM_CC_X_AND_Y),
8594                     CC_REGNUM);"
8595   [(set_attr "conds" "clob")
8596    (set_attr "length" "16")])
8597
8598 ; If the above pattern is followed by a CMP insn, then the compare is 
8599 ; redundant, since we can rework the conditional instruction that follows.
8600 (define_insn_and_split "*and_scc_scc_cmp"
8601   [(set (match_operand 0 "dominant_cc_register" "")
8602         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8603                           [(match_operand:SI 1 "s_register_operand" "r")
8604                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8605                          (match_operator:SI 6 "arm_comparison_operator"
8606                           [(match_operand:SI 4 "s_register_operand" "r")
8607                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8608                  (const_int 0)))
8609    (set (match_operand:SI 7 "s_register_operand" "=r")
8610         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8611                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8612   "TARGET_ARM"
8613   "#"
8614   "TARGET_ARM && reload_completed"
8615   [(set (match_dup 0)
8616         (compare
8617          (and:SI
8618           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8619           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8620          (const_int 0)))
8621    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8622   ""
8623   [(set_attr "conds" "set")
8624    (set_attr "length" "16")])
8625
8626 ;; If there is no dominance in the comparison, then we can still save an
8627 ;; instruction in the AND case, since we can know that the second compare
8628 ;; need only zero the value if false (if true, then the value is already
8629 ;; correct).
8630 (define_insn_and_split "*and_scc_scc_nodom"
8631   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8632         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8633                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
8634                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8635                 (match_operator:SI 6 "arm_comparison_operator"
8636                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
8637                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8638    (clobber (reg:CC CC_REGNUM))]
8639   "TARGET_ARM
8640    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8641        == CCmode)"
8642   "#"
8643   "TARGET_ARM && reload_completed"
8644   [(parallel [(set (match_dup 0)
8645                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8646               (clobber (reg:CC CC_REGNUM))])
8647    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8648    (set (match_dup 0)
8649         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8650                          (match_dup 0)
8651                          (const_int 0)))]
8652   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8653                                               operands[4], operands[5]),
8654                               CC_REGNUM);
8655    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8656                                   operands[5]);"
8657   [(set_attr "conds" "clob")
8658    (set_attr "length" "20")])
8659
8660 (define_split
8661   [(set (reg:CC_NOOV CC_REGNUM)
8662         (compare:CC_NOOV (ior:SI
8663                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8664                                   (const_int 1))
8665                           (match_operator:SI 1 "comparison_operator"
8666                            [(match_operand:SI 2 "s_register_operand" "")
8667                             (match_operand:SI 3 "arm_add_operand" "")]))
8668                          (const_int 0)))
8669    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8670   "TARGET_ARM"
8671   [(set (match_dup 4)
8672         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8673                 (match_dup 0)))
8674    (set (reg:CC_NOOV CC_REGNUM)
8675         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8676                          (const_int 0)))]
8677   "")
8678
8679 (define_split
8680   [(set (reg:CC_NOOV CC_REGNUM)
8681         (compare:CC_NOOV (ior:SI
8682                           (match_operator:SI 1 "comparison_operator"
8683                            [(match_operand:SI 2 "s_register_operand" "")
8684                             (match_operand:SI 3 "arm_add_operand" "")])
8685                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8686                                   (const_int 1)))
8687                          (const_int 0)))
8688    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8689   "TARGET_ARM"
8690   [(set (match_dup 4)
8691         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8692                 (match_dup 0)))
8693    (set (reg:CC_NOOV CC_REGNUM)
8694         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8695                          (const_int 0)))]
8696   "")
8697
8698 (define_insn "*negscc"
8699   [(set (match_operand:SI 0 "s_register_operand" "=r")
8700         (neg:SI (match_operator 3 "arm_comparison_operator"
8701                  [(match_operand:SI 1 "s_register_operand" "r")
8702                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8703    (clobber (reg:CC CC_REGNUM))]
8704   "TARGET_ARM"
8705   "*
8706   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8707     return \"mov\\t%0, %1, asr #31\";
8708
8709   if (GET_CODE (operands[3]) == NE)
8710     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8711
8712   if (GET_CODE (operands[3]) == GT)
8713     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8714
8715   output_asm_insn (\"cmp\\t%1, %2\", operands);
8716   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8717   return \"mvn%d3\\t%0, #0\";
8718   "
8719   [(set_attr "conds" "clob")
8720    (set_attr "length" "12")]
8721 )
8722
8723 (define_insn "movcond"
8724   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8725         (if_then_else:SI
8726          (match_operator 5 "arm_comparison_operator"
8727           [(match_operand:SI 3 "s_register_operand" "r,r,r")
8728            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8729          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8730          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8731    (clobber (reg:CC CC_REGNUM))]
8732   "TARGET_ARM"
8733   "*
8734   if (GET_CODE (operands[5]) == LT
8735       && (operands[4] == const0_rtx))
8736     {
8737       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8738         {
8739           if (operands[2] == const0_rtx)
8740             return \"and\\t%0, %1, %3, asr #31\";
8741           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8742         }
8743       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8744         {
8745           if (operands[1] == const0_rtx)
8746             return \"bic\\t%0, %2, %3, asr #31\";
8747           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8748         }
8749       /* The only case that falls through to here is when both ops 1 & 2
8750          are constants.  */
8751     }
8752
8753   if (GET_CODE (operands[5]) == GE
8754       && (operands[4] == const0_rtx))
8755     {
8756       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8757         {
8758           if (operands[2] == const0_rtx)
8759             return \"bic\\t%0, %1, %3, asr #31\";
8760           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8761         }
8762       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8763         {
8764           if (operands[1] == const0_rtx)
8765             return \"and\\t%0, %2, %3, asr #31\";
8766           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8767         }
8768       /* The only case that falls through to here is when both ops 1 & 2
8769          are constants.  */
8770     }
8771   if (GET_CODE (operands[4]) == CONST_INT
8772       && !const_ok_for_arm (INTVAL (operands[4])))
8773     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8774   else
8775     output_asm_insn (\"cmp\\t%3, %4\", operands);
8776   if (which_alternative != 0)
8777     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8778   if (which_alternative != 1)
8779     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8780   return \"\";
8781   "
8782   [(set_attr "conds" "clob")
8783    (set_attr "length" "8,8,12")]
8784 )
8785
8786 (define_insn "*ifcompare_plus_move"
8787   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8788         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8789                           [(match_operand:SI 4 "s_register_operand" "r,r")
8790                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8791                          (plus:SI
8792                           (match_operand:SI 2 "s_register_operand" "r,r")
8793                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8794                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8795    (clobber (reg:CC CC_REGNUM))]
8796   "TARGET_ARM"
8797   "#"
8798   [(set_attr "conds" "clob")
8799    (set_attr "length" "8,12")]
8800 )
8801
8802 (define_insn "*if_plus_move"
8803   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8804         (if_then_else:SI
8805          (match_operator 4 "arm_comparison_operator"
8806           [(match_operand 5 "cc_register" "") (const_int 0)])
8807          (plus:SI
8808           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8809           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8810          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8811   "TARGET_ARM"
8812   "@
8813    add%d4\\t%0, %2, %3
8814    sub%d4\\t%0, %2, #%n3
8815    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8816    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8817   [(set_attr "conds" "use")
8818    (set_attr "length" "4,4,8,8")
8819    (set_attr "type" "*,*,*,*")]
8820 )
8821
8822 (define_insn "*ifcompare_move_plus"
8823   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8824         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8825                           [(match_operand:SI 4 "s_register_operand" "r,r")
8826                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8827                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8828                          (plus:SI
8829                           (match_operand:SI 2 "s_register_operand" "r,r")
8830                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8831    (clobber (reg:CC CC_REGNUM))]
8832   "TARGET_ARM"
8833   "#"
8834   [(set_attr "conds" "clob")
8835    (set_attr "length" "8,12")]
8836 )
8837
8838 (define_insn "*if_move_plus"
8839   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8840         (if_then_else:SI
8841          (match_operator 4 "arm_comparison_operator"
8842           [(match_operand 5 "cc_register" "") (const_int 0)])
8843          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8844          (plus:SI
8845           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8846           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8847   "TARGET_ARM"
8848   "@
8849    add%D4\\t%0, %2, %3
8850    sub%D4\\t%0, %2, #%n3
8851    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8852    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8853   [(set_attr "conds" "use")
8854    (set_attr "length" "4,4,8,8")
8855    (set_attr "type" "*,*,*,*")]
8856 )
8857
8858 (define_insn "*ifcompare_arith_arith"
8859   [(set (match_operand:SI 0 "s_register_operand" "=r")
8860         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8861                           [(match_operand:SI 5 "s_register_operand" "r")
8862                            (match_operand:SI 6 "arm_add_operand" "rIL")])
8863                          (match_operator:SI 8 "shiftable_operator"
8864                           [(match_operand:SI 1 "s_register_operand" "r")
8865                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8866                          (match_operator:SI 7 "shiftable_operator"
8867                           [(match_operand:SI 3 "s_register_operand" "r")
8868                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8869    (clobber (reg:CC CC_REGNUM))]
8870   "TARGET_ARM"
8871   "#"
8872   [(set_attr "conds" "clob")
8873    (set_attr "length" "12")]
8874 )
8875
8876 (define_insn "*if_arith_arith"
8877   [(set (match_operand:SI 0 "s_register_operand" "=r")
8878         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8879                           [(match_operand 8 "cc_register" "") (const_int 0)])
8880                          (match_operator:SI 6 "shiftable_operator"
8881                           [(match_operand:SI 1 "s_register_operand" "r")
8882                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8883                          (match_operator:SI 7 "shiftable_operator"
8884                           [(match_operand:SI 3 "s_register_operand" "r")
8885                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8886   "TARGET_ARM"
8887   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8888   [(set_attr "conds" "use")
8889    (set_attr "length" "8")]
8890 )
8891
8892 (define_insn "*ifcompare_arith_move"
8893   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8894         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8895                           [(match_operand:SI 2 "s_register_operand" "r,r")
8896                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8897                          (match_operator:SI 7 "shiftable_operator"
8898                           [(match_operand:SI 4 "s_register_operand" "r,r")
8899                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8900                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8901    (clobber (reg:CC CC_REGNUM))]
8902   "TARGET_ARM"
8903   "*
8904   /* If we have an operation where (op x 0) is the identity operation and
8905      the conditional operator is LT or GE and we are comparing against zero and
8906      everything is in registers then we can do this in two instructions.  */
8907   if (operands[3] == const0_rtx
8908       && GET_CODE (operands[7]) != AND
8909       && GET_CODE (operands[5]) == REG
8910       && GET_CODE (operands[1]) == REG 
8911       && REGNO (operands[1]) == REGNO (operands[4])
8912       && REGNO (operands[4]) != REGNO (operands[0]))
8913     {
8914       if (GET_CODE (operands[6]) == LT)
8915         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8916       else if (GET_CODE (operands[6]) == GE)
8917         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8918     }
8919   if (GET_CODE (operands[3]) == CONST_INT
8920       && !const_ok_for_arm (INTVAL (operands[3])))
8921     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8922   else
8923     output_asm_insn (\"cmp\\t%2, %3\", operands);
8924   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8925   if (which_alternative != 0)
8926     return \"mov%D6\\t%0, %1\";
8927   return \"\";
8928   "
8929   [(set_attr "conds" "clob")
8930    (set_attr "length" "8,12")]
8931 )
8932
8933 (define_insn "*if_arith_move"
8934   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8935         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8936                           [(match_operand 6 "cc_register" "") (const_int 0)])
8937                          (match_operator:SI 5 "shiftable_operator"
8938                           [(match_operand:SI 2 "s_register_operand" "r,r")
8939                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8940                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8941   "TARGET_ARM"
8942   "@
8943    %I5%d4\\t%0, %2, %3
8944    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8945   [(set_attr "conds" "use")
8946    (set_attr "length" "4,8")
8947    (set_attr "type" "*,*")]
8948 )
8949
8950 (define_insn "*ifcompare_move_arith"
8951   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8952         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8953                           [(match_operand:SI 4 "s_register_operand" "r,r")
8954                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8955                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8956                          (match_operator:SI 7 "shiftable_operator"
8957                           [(match_operand:SI 2 "s_register_operand" "r,r")
8958                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8959    (clobber (reg:CC CC_REGNUM))]
8960   "TARGET_ARM"
8961   "*
8962   /* If we have an operation where (op x 0) is the identity operation and
8963      the conditional operator is LT or GE and we are comparing against zero and
8964      everything is in registers then we can do this in two instructions */
8965   if (operands[5] == const0_rtx
8966       && GET_CODE (operands[7]) != AND
8967       && GET_CODE (operands[3]) == REG
8968       && GET_CODE (operands[1]) == REG 
8969       && REGNO (operands[1]) == REGNO (operands[2])
8970       && REGNO (operands[2]) != REGNO (operands[0]))
8971     {
8972       if (GET_CODE (operands[6]) == GE)
8973         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8974       else if (GET_CODE (operands[6]) == LT)
8975         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8976     }
8977
8978   if (GET_CODE (operands[5]) == CONST_INT
8979       && !const_ok_for_arm (INTVAL (operands[5])))
8980     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
8981   else
8982     output_asm_insn (\"cmp\\t%4, %5\", operands);
8983
8984   if (which_alternative != 0)
8985     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
8986   return \"%I7%D6\\t%0, %2, %3\";
8987   "
8988   [(set_attr "conds" "clob")
8989    (set_attr "length" "8,12")]
8990 )
8991
8992 (define_insn "*if_move_arith"
8993   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8994         (if_then_else:SI
8995          (match_operator 4 "arm_comparison_operator"
8996           [(match_operand 6 "cc_register" "") (const_int 0)])
8997          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8998          (match_operator:SI 5 "shiftable_operator"
8999           [(match_operand:SI 2 "s_register_operand" "r,r")
9000            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
9001   "TARGET_ARM"
9002   "@
9003    %I5%D4\\t%0, %2, %3
9004    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
9005   [(set_attr "conds" "use")
9006    (set_attr "length" "4,8")
9007    (set_attr "type" "*,*")]
9008 )
9009
9010 (define_insn "*ifcompare_move_not"
9011   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9012         (if_then_else:SI
9013          (match_operator 5 "arm_comparison_operator"
9014           [(match_operand:SI 3 "s_register_operand" "r,r")
9015            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9016          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9017          (not:SI
9018           (match_operand:SI 2 "s_register_operand" "r,r"))))
9019    (clobber (reg:CC CC_REGNUM))]
9020   "TARGET_ARM"
9021   "#"
9022   [(set_attr "conds" "clob")
9023    (set_attr "length" "8,12")]
9024 )
9025
9026 (define_insn "*if_move_not"
9027   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9028         (if_then_else:SI
9029          (match_operator 4 "arm_comparison_operator"
9030           [(match_operand 3 "cc_register" "") (const_int 0)])
9031          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9032          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9033   "TARGET_ARM"
9034   "@
9035    mvn%D4\\t%0, %2
9036    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9037    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
9038   [(set_attr "conds" "use")
9039    (set_attr "length" "4,8,8")]
9040 )
9041
9042 (define_insn "*ifcompare_not_move"
9043   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9044         (if_then_else:SI 
9045          (match_operator 5 "arm_comparison_operator"
9046           [(match_operand:SI 3 "s_register_operand" "r,r")
9047            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9048          (not:SI
9049           (match_operand:SI 2 "s_register_operand" "r,r"))
9050          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9051    (clobber (reg:CC CC_REGNUM))]
9052   "TARGET_ARM"
9053   "#"
9054   [(set_attr "conds" "clob")
9055    (set_attr "length" "8,12")]
9056 )
9057
9058 (define_insn "*if_not_move"
9059   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9060         (if_then_else:SI
9061          (match_operator 4 "arm_comparison_operator"
9062           [(match_operand 3 "cc_register" "") (const_int 0)])
9063          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9064          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9065   "TARGET_ARM"
9066   "@
9067    mvn%d4\\t%0, %2
9068    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9069    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
9070   [(set_attr "conds" "use")
9071    (set_attr "length" "4,8,8")]
9072 )
9073
9074 (define_insn "*ifcompare_shift_move"
9075   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9076         (if_then_else:SI
9077          (match_operator 6 "arm_comparison_operator"
9078           [(match_operand:SI 4 "s_register_operand" "r,r")
9079            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9080          (match_operator:SI 7 "shift_operator"
9081           [(match_operand:SI 2 "s_register_operand" "r,r")
9082            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9083          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9084    (clobber (reg:CC CC_REGNUM))]
9085   "TARGET_ARM"
9086   "#"
9087   [(set_attr "conds" "clob")
9088    (set_attr "length" "8,12")]
9089 )
9090
9091 (define_insn "*if_shift_move"
9092   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9093         (if_then_else:SI
9094          (match_operator 5 "arm_comparison_operator"
9095           [(match_operand 6 "cc_register" "") (const_int 0)])
9096          (match_operator:SI 4 "shift_operator"
9097           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9098            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9099          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9100   "TARGET_ARM"
9101   "@
9102    mov%d5\\t%0, %2%S4
9103    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9104    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
9105   [(set_attr "conds" "use")
9106    (set_attr "shift" "2")
9107    (set_attr "length" "4,8,8")
9108    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9109                       (const_string "alu_shift")
9110                       (const_string "alu_shift_reg")))]
9111 )
9112
9113 (define_insn "*ifcompare_move_shift"
9114   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9115         (if_then_else:SI
9116          (match_operator 6 "arm_comparison_operator"
9117           [(match_operand:SI 4 "s_register_operand" "r,r")
9118            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9119          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9120          (match_operator:SI 7 "shift_operator"
9121           [(match_operand:SI 2 "s_register_operand" "r,r")
9122            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
9123    (clobber (reg:CC CC_REGNUM))]
9124   "TARGET_ARM"
9125   "#"
9126   [(set_attr "conds" "clob")
9127    (set_attr "length" "8,12")]
9128 )
9129
9130 (define_insn "*if_move_shift"
9131   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9132         (if_then_else:SI
9133          (match_operator 5 "arm_comparison_operator"
9134           [(match_operand 6 "cc_register" "") (const_int 0)])
9135          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9136          (match_operator:SI 4 "shift_operator"
9137           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9138            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
9139   "TARGET_ARM"
9140   "@
9141    mov%D5\\t%0, %2%S4
9142    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9143    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
9144   [(set_attr "conds" "use")
9145    (set_attr "shift" "2")
9146    (set_attr "length" "4,8,8")
9147    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9148                       (const_string "alu_shift")
9149                       (const_string "alu_shift_reg")))]
9150 )
9151
9152 (define_insn "*ifcompare_shift_shift"
9153   [(set (match_operand:SI 0 "s_register_operand" "=r")
9154         (if_then_else:SI
9155          (match_operator 7 "arm_comparison_operator"
9156           [(match_operand:SI 5 "s_register_operand" "r")
9157            (match_operand:SI 6 "arm_add_operand" "rIL")])
9158          (match_operator:SI 8 "shift_operator"
9159           [(match_operand:SI 1 "s_register_operand" "r")
9160            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9161          (match_operator:SI 9 "shift_operator"
9162           [(match_operand:SI 3 "s_register_operand" "r")
9163            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
9164    (clobber (reg:CC CC_REGNUM))]
9165   "TARGET_ARM"
9166   "#"
9167   [(set_attr "conds" "clob")
9168    (set_attr "length" "12")]
9169 )
9170
9171 (define_insn "*if_shift_shift"
9172   [(set (match_operand:SI 0 "s_register_operand" "=r")
9173         (if_then_else:SI
9174          (match_operator 5 "arm_comparison_operator"
9175           [(match_operand 8 "cc_register" "") (const_int 0)])
9176          (match_operator:SI 6 "shift_operator"
9177           [(match_operand:SI 1 "s_register_operand" "r")
9178            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9179          (match_operator:SI 7 "shift_operator"
9180           [(match_operand:SI 3 "s_register_operand" "r")
9181            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
9182   "TARGET_ARM"
9183   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
9184   [(set_attr "conds" "use")
9185    (set_attr "shift" "1")
9186    (set_attr "length" "8")
9187    (set (attr "type") (if_then_else
9188                         (and (match_operand 2 "const_int_operand" "")
9189                              (match_operand 4 "const_int_operand" ""))
9190                       (const_string "alu_shift")
9191                       (const_string "alu_shift_reg")))]
9192 )
9193
9194 (define_insn "*ifcompare_not_arith"
9195   [(set (match_operand:SI 0 "s_register_operand" "=r")
9196         (if_then_else:SI
9197          (match_operator 6 "arm_comparison_operator"
9198           [(match_operand:SI 4 "s_register_operand" "r")
9199            (match_operand:SI 5 "arm_add_operand" "rIL")])
9200          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9201          (match_operator:SI 7 "shiftable_operator"
9202           [(match_operand:SI 2 "s_register_operand" "r")
9203            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
9204    (clobber (reg:CC CC_REGNUM))]
9205   "TARGET_ARM"
9206   "#"
9207   [(set_attr "conds" "clob")
9208    (set_attr "length" "12")]
9209 )
9210
9211 (define_insn "*if_not_arith"
9212   [(set (match_operand:SI 0 "s_register_operand" "=r")
9213         (if_then_else:SI
9214          (match_operator 5 "arm_comparison_operator"
9215           [(match_operand 4 "cc_register" "") (const_int 0)])
9216          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9217          (match_operator:SI 6 "shiftable_operator"
9218           [(match_operand:SI 2 "s_register_operand" "r")
9219            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
9220   "TARGET_ARM"
9221   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
9222   [(set_attr "conds" "use")
9223    (set_attr "length" "8")]
9224 )
9225
9226 (define_insn "*ifcompare_arith_not"
9227   [(set (match_operand:SI 0 "s_register_operand" "=r")
9228         (if_then_else:SI
9229          (match_operator 6 "arm_comparison_operator"
9230           [(match_operand:SI 4 "s_register_operand" "r")
9231            (match_operand:SI 5 "arm_add_operand" "rIL")])
9232          (match_operator:SI 7 "shiftable_operator"
9233           [(match_operand:SI 2 "s_register_operand" "r")
9234            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9235          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9236    (clobber (reg:CC CC_REGNUM))]
9237   "TARGET_ARM"
9238   "#"
9239   [(set_attr "conds" "clob")
9240    (set_attr "length" "12")]
9241 )
9242
9243 (define_insn "*if_arith_not"
9244   [(set (match_operand:SI 0 "s_register_operand" "=r")
9245         (if_then_else:SI
9246          (match_operator 5 "arm_comparison_operator"
9247           [(match_operand 4 "cc_register" "") (const_int 0)])
9248          (match_operator:SI 6 "shiftable_operator"
9249           [(match_operand:SI 2 "s_register_operand" "r")
9250            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9251          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9252   "TARGET_ARM"
9253   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9254   [(set_attr "conds" "use")
9255    (set_attr "length" "8")]
9256 )
9257
9258 (define_insn "*ifcompare_neg_move"
9259   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9260         (if_then_else:SI
9261          (match_operator 5 "arm_comparison_operator"
9262           [(match_operand:SI 3 "s_register_operand" "r,r")
9263            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9264          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9265          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9266    (clobber (reg:CC CC_REGNUM))]
9267   "TARGET_ARM"
9268   "#"
9269   [(set_attr "conds" "clob")
9270    (set_attr "length" "8,12")]
9271 )
9272
9273 (define_insn "*if_neg_move"
9274   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9275         (if_then_else:SI
9276          (match_operator 4 "arm_comparison_operator"
9277           [(match_operand 3 "cc_register" "") (const_int 0)])
9278          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9279          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9280   "TARGET_ARM"
9281   "@
9282    rsb%d4\\t%0, %2, #0
9283    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9284    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9285   [(set_attr "conds" "use")
9286    (set_attr "length" "4,8,8")]
9287 )
9288
9289 (define_insn "*ifcompare_move_neg"
9290   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9291         (if_then_else:SI
9292          (match_operator 5 "arm_comparison_operator"
9293           [(match_operand:SI 3 "s_register_operand" "r,r")
9294            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9295          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9296          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9297    (clobber (reg:CC CC_REGNUM))]
9298   "TARGET_ARM"
9299   "#"
9300   [(set_attr "conds" "clob")
9301    (set_attr "length" "8,12")]
9302 )
9303
9304 (define_insn "*if_move_neg"
9305   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9306         (if_then_else:SI
9307          (match_operator 4 "arm_comparison_operator"
9308           [(match_operand 3 "cc_register" "") (const_int 0)])
9309          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9310          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9311   "TARGET_ARM"
9312   "@
9313    rsb%D4\\t%0, %2, #0
9314    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9315    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9316   [(set_attr "conds" "use")
9317    (set_attr "length" "4,8,8")]
9318 )
9319
9320 (define_insn "*arith_adjacentmem"
9321   [(set (match_operand:SI 0 "s_register_operand" "=r")
9322         (match_operator:SI 1 "shiftable_operator"
9323          [(match_operand:SI 2 "memory_operand" "m")
9324           (match_operand:SI 3 "memory_operand" "m")]))
9325    (clobber (match_scratch:SI 4 "=r"))]
9326   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9327   "*
9328   {
9329     rtx ldm[3];
9330     rtx arith[4];
9331     rtx base_reg;
9332     HOST_WIDE_INT val1 = 0, val2 = 0;
9333
9334     if (REGNO (operands[0]) > REGNO (operands[4]))
9335       {
9336         ldm[1] = operands[4];
9337         ldm[2] = operands[0];
9338       }
9339     else
9340       {
9341         ldm[1] = operands[0];
9342         ldm[2] = operands[4];
9343       }
9344
9345     base_reg = XEXP (operands[2], 0);
9346
9347     if (!REG_P (base_reg))
9348       {
9349         val1 = INTVAL (XEXP (base_reg, 1));
9350         base_reg = XEXP (base_reg, 0);
9351       }
9352
9353     if (!REG_P (XEXP (operands[3], 0)))
9354       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9355
9356     arith[0] = operands[0];
9357     arith[3] = operands[1];
9358
9359     if (val1 < val2)
9360       {
9361         arith[1] = ldm[1];
9362         arith[2] = ldm[2];
9363       }
9364     else
9365       {
9366         arith[1] = ldm[2];
9367         arith[2] = ldm[1];
9368       }
9369
9370     ldm[0] = base_reg;
9371     if (val1 !=0 && val2 != 0)
9372       {
9373         if (val1 == 4 || val2 == 4)
9374           /* Other val must be 8, since we know they are adjacent and neither
9375              is zero.  */
9376           output_asm_insn (\"ldm%?ib\\t%0, {%1, %2}\", ldm);
9377         else
9378           {
9379             rtx ops[3];
9380
9381             ldm[0] = ops[0] = operands[4];
9382             ops[1] = base_reg;
9383             ops[2] = GEN_INT (val1);
9384             output_add_immediate (ops);
9385             if (val1 < val2)
9386               output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9387             else
9388               output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9389           }
9390       }
9391     else if (val1 != 0)
9392       {
9393         if (val1 < val2)
9394           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9395         else
9396           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9397       }
9398     else
9399       {
9400         if (val1 < val2)
9401           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9402         else
9403           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9404       }
9405     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9406     return \"\";
9407   }"
9408   [(set_attr "length" "12")
9409    (set_attr "predicable" "yes")
9410    (set_attr "type" "load1")]
9411 )
9412
9413 ;; the arm can support extended pre-inc instructions
9414
9415 ;; In all these cases, we use operands 0 and 1 for the register being
9416 ;; incremented because those are the operands that local-alloc will
9417 ;; tie and these are the pair most likely to be tieable (and the ones
9418 ;; that will benefit the most).
9419
9420 ;; We reject the frame pointer if it occurs anywhere in these patterns since
9421 ;; elimination will cause too many headaches.
9422
9423 (define_insn "*strqi_preinc"
9424   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9425                          (match_operand:SI 2 "index_operand" "rJ")))
9426         (match_operand:QI 3 "s_register_operand" "r"))
9427    (set (match_operand:SI 0 "s_register_operand" "=r")
9428         (plus:SI (match_dup 1) (match_dup 2)))]
9429   "TARGET_ARM
9430    && !arm_eliminable_register (operands[0])
9431    && !arm_eliminable_register (operands[1])
9432    && !arm_eliminable_register (operands[2])"
9433   "str%?b\\t%3, [%0, %2]!"
9434   [(set_attr "type" "store1")
9435    (set_attr "predicable" "yes")]
9436 )
9437
9438 (define_insn "*strqi_predec"
9439   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9440                           (match_operand:SI 2 "s_register_operand" "r")))
9441         (match_operand:QI 3 "s_register_operand" "r"))
9442    (set (match_operand:SI 0 "s_register_operand" "=r")
9443         (minus:SI (match_dup 1) (match_dup 2)))]
9444   "TARGET_ARM
9445    && !arm_eliminable_register (operands[0])
9446    && !arm_eliminable_register (operands[1])
9447    && !arm_eliminable_register (operands[2])"
9448   "str%?b\\t%3, [%0, -%2]!"
9449   [(set_attr "type" "store1")
9450    (set_attr "predicable" "yes")]
9451 )
9452
9453 (define_insn "*loadqi_preinc"
9454   [(set (match_operand:QI 3 "s_register_operand" "=r")
9455         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9456                          (match_operand:SI 2 "index_operand" "rJ"))))
9457    (set (match_operand:SI 0 "s_register_operand" "=r")
9458         (plus:SI (match_dup 1) (match_dup 2)))]
9459   "TARGET_ARM
9460    && !arm_eliminable_register (operands[0])
9461    && !arm_eliminable_register (operands[1])
9462    && !arm_eliminable_register (operands[2])"
9463   "ldr%?b\\t%3, [%0, %2]!"
9464   [(set_attr "type" "load_byte")
9465    (set_attr "predicable" "yes")]
9466 )
9467
9468 (define_insn "*loadqi_predec"
9469   [(set (match_operand:QI 3 "s_register_operand" "=r")
9470         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9471                           (match_operand:SI 2 "s_register_operand" "r"))))
9472    (set (match_operand:SI 0 "s_register_operand" "=r")
9473         (minus:SI (match_dup 1) (match_dup 2)))]
9474   "TARGET_ARM
9475    && !arm_eliminable_register (operands[0])
9476    && !arm_eliminable_register (operands[1])
9477    && !arm_eliminable_register (operands[2])"
9478   "ldr%?b\\t%3, [%0, -%2]!"
9479   [(set_attr "type" "load_byte")
9480    (set_attr "predicable" "yes")]
9481 )
9482
9483 (define_insn "*loadqisi_preinc"
9484   [(set (match_operand:SI 3 "s_register_operand" "=r")
9485         (zero_extend:SI
9486          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9487                           (match_operand:SI 2 "index_operand" "rJ")))))
9488    (set (match_operand:SI 0 "s_register_operand" "=r")
9489         (plus:SI (match_dup 1) (match_dup 2)))]
9490   "TARGET_ARM
9491    && !arm_eliminable_register (operands[0])
9492    && !arm_eliminable_register (operands[1])
9493    && !arm_eliminable_register (operands[2])"
9494   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
9495   [(set_attr "type" "load_byte")
9496    (set_attr "predicable" "yes")]
9497 )
9498
9499 (define_insn "*loadqisi_predec"
9500   [(set (match_operand:SI 3 "s_register_operand" "=r")
9501         (zero_extend:SI
9502          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9503                            (match_operand:SI 2 "s_register_operand" "r")))))
9504    (set (match_operand:SI 0 "s_register_operand" "=r")
9505         (minus:SI (match_dup 1) (match_dup 2)))]
9506   "TARGET_ARM
9507    && !arm_eliminable_register (operands[0])
9508    && !arm_eliminable_register (operands[1])
9509    && !arm_eliminable_register (operands[2])"
9510   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
9511   [(set_attr "type" "load_byte")
9512    (set_attr "predicable" "yes")]
9513 )
9514
9515 (define_insn "*strsi_preinc"
9516   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9517                          (match_operand:SI 2 "index_operand" "rJ")))
9518         (match_operand:SI 3 "s_register_operand" "r"))
9519    (set (match_operand:SI 0 "s_register_operand" "=r")
9520         (plus:SI (match_dup 1) (match_dup 2)))]
9521   "TARGET_ARM
9522    && !arm_eliminable_register (operands[0])
9523    && !arm_eliminable_register (operands[1])
9524    && !arm_eliminable_register (operands[2])"
9525   "str%?\\t%3, [%0, %2]!"
9526   [(set_attr "type" "store1")
9527    (set_attr "predicable" "yes")]
9528 )
9529
9530 (define_insn "*strsi_predec"
9531   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9532                           (match_operand:SI 2 "s_register_operand" "r")))
9533         (match_operand:SI 3 "s_register_operand" "r"))
9534    (set (match_operand:SI 0 "s_register_operand" "=r")
9535         (minus:SI (match_dup 1) (match_dup 2)))]
9536   "TARGET_ARM
9537    && !arm_eliminable_register (operands[0])
9538    && !arm_eliminable_register (operands[1])
9539    && !arm_eliminable_register (operands[2])"
9540   "str%?\\t%3, [%0, -%2]!"
9541   [(set_attr "type" "store1")
9542    (set_attr "predicable" "yes")]
9543 )
9544
9545 (define_insn "*loadsi_preinc"
9546   [(set (match_operand:SI 3 "s_register_operand" "=r")
9547         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9548                          (match_operand:SI 2 "index_operand" "rJ"))))
9549    (set (match_operand:SI 0 "s_register_operand" "=r")
9550         (plus:SI (match_dup 1) (match_dup 2)))]
9551   "TARGET_ARM
9552    && !arm_eliminable_register (operands[0])
9553    && !arm_eliminable_register (operands[1])
9554    && !arm_eliminable_register (operands[2])"
9555   "ldr%?\\t%3, [%0, %2]!"
9556   [(set_attr "type" "load1")
9557    (set_attr "predicable" "yes")]
9558 )
9559
9560 (define_insn "*loadsi_predec"
9561   [(set (match_operand:SI 3 "s_register_operand" "=r")
9562         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9563                           (match_operand:SI 2 "s_register_operand" "r"))))
9564    (set (match_operand:SI 0 "s_register_operand" "=r")
9565         (minus:SI (match_dup 1) (match_dup 2)))]
9566   "TARGET_ARM
9567    && !arm_eliminable_register (operands[0])
9568    && !arm_eliminable_register (operands[1])
9569    && !arm_eliminable_register (operands[2])"
9570   "ldr%?\\t%3, [%0, -%2]!"
9571   [(set_attr "type" "load1")
9572    (set_attr "predicable" "yes")]
9573 )
9574
9575 (define_insn "*strqi_shiftpreinc"
9576   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9577                           [(match_operand:SI 3 "s_register_operand" "r")
9578                            (match_operand:SI 4 "const_shift_operand" "n")])
9579                          (match_operand:SI 1 "s_register_operand" "0")))
9580         (match_operand:QI 5 "s_register_operand" "r"))
9581    (set (match_operand:SI 0 "s_register_operand" "=r")
9582         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9583                  (match_dup 1)))]
9584   "TARGET_ARM
9585    && !arm_eliminable_register (operands[0])
9586    && !arm_eliminable_register (operands[1])
9587    && !arm_eliminable_register (operands[3])"
9588   "str%?b\\t%5, [%0, %3%S2]!"
9589   [(set_attr "type" "store1")
9590    (set_attr "predicable" "yes")]
9591 )
9592
9593 (define_insn "*strqi_shiftpredec"
9594   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9595                           (match_operator:SI 2 "shift_operator"
9596                            [(match_operand:SI 3 "s_register_operand" "r")
9597                             (match_operand:SI 4 "const_shift_operand" "n")])))
9598         (match_operand:QI 5 "s_register_operand" "r"))
9599    (set (match_operand:SI 0 "s_register_operand" "=r")
9600         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9601                                                  (match_dup 4)])))]
9602   "TARGET_ARM
9603    && !arm_eliminable_register (operands[0])
9604    && !arm_eliminable_register (operands[1])
9605    && !arm_eliminable_register (operands[3])"
9606   "str%?b\\t%5, [%0, -%3%S2]!"
9607   [(set_attr "type" "store1")
9608    (set_attr "predicable" "yes")]
9609 )
9610
9611 (define_insn "*loadqi_shiftpreinc"
9612   [(set (match_operand:QI 5 "s_register_operand" "=r")
9613         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9614                           [(match_operand:SI 3 "s_register_operand" "r")
9615                            (match_operand:SI 4 "const_shift_operand" "n")])
9616                          (match_operand:SI 1 "s_register_operand" "0"))))
9617    (set (match_operand:SI 0 "s_register_operand" "=r")
9618         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9619                  (match_dup 1)))]
9620   "TARGET_ARM
9621    && !arm_eliminable_register (operands[0])
9622    && !arm_eliminable_register (operands[1])
9623    && !arm_eliminable_register (operands[3])"
9624   "ldr%?b\\t%5, [%0, %3%S2]!"
9625   [(set_attr "type" "load_byte")
9626    (set_attr "predicable" "yes")]
9627 )
9628
9629 (define_insn "*loadqi_shiftpredec"
9630   [(set (match_operand:QI 5 "s_register_operand" "=r")
9631         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9632                           (match_operator:SI 2 "shift_operator"
9633                            [(match_operand:SI 3 "s_register_operand" "r")
9634                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9635    (set (match_operand:SI 0 "s_register_operand" "=r")
9636         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9637                                                  (match_dup 4)])))]
9638   "TARGET_ARM
9639    && !arm_eliminable_register (operands[0])
9640    && !arm_eliminable_register (operands[1])
9641    && !arm_eliminable_register (operands[3])"
9642   "ldr%?b\\t%5, [%0, -%3%S2]!"
9643   [(set_attr "type" "load_byte")
9644    (set_attr "predicable" "yes")]
9645 )
9646
9647 (define_insn "*strsi_shiftpreinc"
9648   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9649                           [(match_operand:SI 3 "s_register_operand" "r")
9650                            (match_operand:SI 4 "const_shift_operand" "n")])
9651                          (match_operand:SI 1 "s_register_operand" "0")))
9652         (match_operand:SI 5 "s_register_operand" "r"))
9653    (set (match_operand:SI 0 "s_register_operand" "=r")
9654         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9655                  (match_dup 1)))]
9656   "TARGET_ARM
9657    && !arm_eliminable_register (operands[0])
9658    && !arm_eliminable_register (operands[1])
9659    && !arm_eliminable_register (operands[3])"
9660   "str%?\\t%5, [%0, %3%S2]!"
9661   [(set_attr "type" "store1")
9662    (set_attr "predicable" "yes")]
9663 )
9664
9665 (define_insn "*strsi_shiftpredec"
9666   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9667                           (match_operator:SI 2 "shift_operator"
9668                            [(match_operand:SI 3 "s_register_operand" "r")
9669                             (match_operand:SI 4 "const_shift_operand" "n")])))
9670         (match_operand:SI 5 "s_register_operand" "r"))
9671    (set (match_operand:SI 0 "s_register_operand" "=r")
9672         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9673                                                  (match_dup 4)])))]
9674   "TARGET_ARM
9675    && !arm_eliminable_register (operands[0])
9676    && !arm_eliminable_register (operands[1])
9677    && !arm_eliminable_register (operands[3])"
9678   "str%?\\t%5, [%0, -%3%S2]!"
9679   [(set_attr "type" "store1")
9680    (set_attr "predicable" "yes")]
9681 )
9682
9683 (define_insn "*loadsi_shiftpreinc"
9684   [(set (match_operand:SI 5 "s_register_operand" "=r")
9685         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9686                           [(match_operand:SI 3 "s_register_operand" "r")
9687                            (match_operand:SI 4 "const_shift_operand" "n")])
9688                          (match_operand:SI 1 "s_register_operand" "0"))))
9689    (set (match_operand:SI 0 "s_register_operand" "=r")
9690         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9691                  (match_dup 1)))]
9692   "TARGET_ARM
9693    && !arm_eliminable_register (operands[0])
9694    && !arm_eliminable_register (operands[1])
9695    && !arm_eliminable_register (operands[3])"
9696   "ldr%?\\t%5, [%0, %3%S2]!"
9697   [(set_attr "type" "load1")
9698    (set_attr "predicable" "yes")]
9699 )
9700
9701 (define_insn "*loadsi_shiftpredec"
9702   [(set (match_operand:SI 5 "s_register_operand" "=r")
9703         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9704                           (match_operator:SI 2 "shift_operator"
9705                            [(match_operand:SI 3 "s_register_operand" "r")
9706                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9707    (set (match_operand:SI 0 "s_register_operand" "=r")
9708         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9709                                                  (match_dup 4)])))]
9710   "TARGET_ARM
9711    && !arm_eliminable_register (operands[0])
9712    && !arm_eliminable_register (operands[1])
9713    && !arm_eliminable_register (operands[3])"
9714   "ldr%?\\t%5, [%0, -%3%S2]!"
9715   [(set_attr "type" "load1")
9716    (set_attr "predicable" "yes")])
9717
9718 ; It can also support extended post-inc expressions, but combine doesn't
9719 ; try these....
9720 ; It doesn't seem worth adding peepholes for anything but the most common
9721 ; cases since, unlike combine, the increment must immediately follow the load
9722 ; for this pattern to match.
9723 ; We must watch to see that the source/destination register isn't also the
9724 ; same as the base address register, and that if the index is a register,
9725 ; that it is not the same as the base address register.  In such cases the
9726 ; instruction that we would generate would have UNPREDICTABLE behavior so 
9727 ; we cannot use it.
9728
9729 (define_peephole
9730   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9731         (match_operand:QI 2 "s_register_operand" "r"))
9732    (set (match_dup 0)
9733         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9734   "TARGET_ARM
9735    && (REGNO (operands[2]) != REGNO (operands[0]))
9736    && (GET_CODE (operands[1]) != REG
9737        || (REGNO (operands[1]) != REGNO (operands[0])))"
9738   "str%?b\\t%2, [%0], %1"
9739 )
9740
9741 (define_peephole
9742   [(set (match_operand:QI 0 "s_register_operand" "=r")
9743         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9744    (set (match_dup 1)
9745         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9746   "TARGET_ARM
9747    && REGNO (operands[0]) != REGNO(operands[1])
9748    && (GET_CODE (operands[2]) != REG
9749        || REGNO(operands[0]) != REGNO (operands[2]))"
9750   "ldr%?b\\t%0, [%1], %2"
9751 )
9752
9753 (define_peephole
9754   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9755         (match_operand:SI 2 "s_register_operand" "r"))
9756    (set (match_dup 0)
9757         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9758   "TARGET_ARM
9759    && (REGNO (operands[2]) != REGNO (operands[0]))
9760    && (GET_CODE (operands[1]) != REG
9761        || (REGNO (operands[1]) != REGNO (operands[0])))"
9762   "str%?\\t%2, [%0], %1"
9763 )
9764
9765 (define_peephole
9766   [(set (match_operand:SI 0 "s_register_operand" "=r")
9767         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9768    (set (match_dup 1)
9769         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9770   "TARGET_ARM
9771    && REGNO (operands[0]) != REGNO(operands[1])
9772    && (GET_CODE (operands[2]) != REG
9773        || REGNO(operands[0]) != REGNO (operands[2]))"
9774   "ldr%?\\t%0, [%1], %2"
9775 )
9776
9777 (define_peephole
9778   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9779                          (match_operand:SI 1 "index_operand" "rJ")))
9780         (match_operand:QI 2 "s_register_operand" "r"))
9781    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
9782   "TARGET_ARM
9783    && (REGNO (operands[2]) != REGNO (operands[0]))
9784    && (GET_CODE (operands[1]) != REG
9785        || (REGNO (operands[1]) != REGNO (operands[0])))"
9786   "str%?b\\t%2, [%0, %1]!"
9787 )
9788
9789 (define_peephole
9790   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9791                           [(match_operand:SI 0 "s_register_operand" "r")
9792                            (match_operand:SI 1 "const_int_operand" "n")])
9793                          (match_operand:SI 2 "s_register_operand" "+r")))
9794         (match_operand:QI 3 "s_register_operand" "r"))
9795    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9796                                (match_dup 2)))]
9797   "TARGET_ARM
9798    && (REGNO (operands[3]) != REGNO (operands[2]))
9799    && (REGNO (operands[0]) != REGNO (operands[2]))"
9800   "str%?b\\t%3, [%2, %0%S4]!"
9801 )
9802
9803 ; This pattern is never tried by combine, so do it as a peephole
9804
9805 (define_peephole2
9806   [(set (match_operand:SI 0 "arm_general_register_operand" "")
9807         (match_operand:SI 1 "arm_general_register_operand" ""))
9808    (set (reg:CC CC_REGNUM)
9809         (compare:CC (match_dup 1) (const_int 0)))]
9810   "TARGET_ARM"
9811   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9812               (set (match_dup 0) (match_dup 1))])]
9813   ""
9814 )
9815
9816 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9817 ; reversed, check that the memory references aren't volatile.
9818
9819 (define_peephole
9820   [(set (match_operand:SI 0 "s_register_operand" "=r")
9821         (match_operand:SI 4 "memory_operand" "m"))
9822    (set (match_operand:SI 1 "s_register_operand" "=r")
9823         (match_operand:SI 5 "memory_operand" "m"))
9824    (set (match_operand:SI 2 "s_register_operand" "=r")
9825         (match_operand:SI 6 "memory_operand" "m"))
9826    (set (match_operand:SI 3 "s_register_operand" "=r")
9827         (match_operand:SI 7 "memory_operand" "m"))]
9828   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9829   "*
9830   return emit_ldm_seq (operands, 4);
9831   "
9832 )
9833
9834 (define_peephole
9835   [(set (match_operand:SI 0 "s_register_operand" "=r")
9836         (match_operand:SI 3 "memory_operand" "m"))
9837    (set (match_operand:SI 1 "s_register_operand" "=r")
9838         (match_operand:SI 4 "memory_operand" "m"))
9839    (set (match_operand:SI 2 "s_register_operand" "=r")
9840         (match_operand:SI 5 "memory_operand" "m"))]
9841   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9842   "*
9843   return emit_ldm_seq (operands, 3);
9844   "
9845 )
9846
9847 (define_peephole
9848   [(set (match_operand:SI 0 "s_register_operand" "=r")
9849         (match_operand:SI 2 "memory_operand" "m"))
9850    (set (match_operand:SI 1 "s_register_operand" "=r")
9851         (match_operand:SI 3 "memory_operand" "m"))]
9852   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9853   "*
9854   return emit_ldm_seq (operands, 2);
9855   "
9856 )
9857
9858 (define_peephole
9859   [(set (match_operand:SI 4 "memory_operand" "=m")
9860         (match_operand:SI 0 "s_register_operand" "r"))
9861    (set (match_operand:SI 5 "memory_operand" "=m")
9862         (match_operand:SI 1 "s_register_operand" "r"))
9863    (set (match_operand:SI 6 "memory_operand" "=m")
9864         (match_operand:SI 2 "s_register_operand" "r"))
9865    (set (match_operand:SI 7 "memory_operand" "=m")
9866         (match_operand:SI 3 "s_register_operand" "r"))]
9867   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9868   "*
9869   return emit_stm_seq (operands, 4);
9870   "
9871 )
9872
9873 (define_peephole
9874   [(set (match_operand:SI 3 "memory_operand" "=m")
9875         (match_operand:SI 0 "s_register_operand" "r"))
9876    (set (match_operand:SI 4 "memory_operand" "=m")
9877         (match_operand:SI 1 "s_register_operand" "r"))
9878    (set (match_operand:SI 5 "memory_operand" "=m")
9879         (match_operand:SI 2 "s_register_operand" "r"))]
9880   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9881   "*
9882   return emit_stm_seq (operands, 3);
9883   "
9884 )
9885
9886 (define_peephole
9887   [(set (match_operand:SI 2 "memory_operand" "=m")
9888         (match_operand:SI 0 "s_register_operand" "r"))
9889    (set (match_operand:SI 3 "memory_operand" "=m")
9890         (match_operand:SI 1 "s_register_operand" "r"))]
9891   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9892   "*
9893   return emit_stm_seq (operands, 2);
9894   "
9895 )
9896
9897 (define_split
9898   [(set (match_operand:SI 0 "s_register_operand" "")
9899         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9900                        (const_int 0))
9901                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9902                          [(match_operand:SI 3 "s_register_operand" "")
9903                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
9904    (clobber (match_operand:SI 5 "s_register_operand" ""))]
9905   "TARGET_ARM"
9906   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9907    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9908                               (match_dup 5)))]
9909   ""
9910 )
9911
9912 ;; This split can be used because CC_Z mode implies that the following
9913 ;; branch will be an equality, or an unsigned inequality, so the sign
9914 ;; extension is not needed.
9915
9916 (define_split
9917   [(set (reg:CC_Z CC_REGNUM)
9918         (compare:CC_Z
9919          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9920                     (const_int 24))
9921          (match_operand 1 "const_int_operand" "")))
9922    (clobber (match_scratch:SI 2 ""))]
9923   "TARGET_ARM
9924    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9925        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9926   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9927    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9928   "
9929   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9930   "
9931 )
9932
9933 (define_expand "prologue"
9934   [(clobber (const_int 0))]
9935   "TARGET_EITHER"
9936   "if (TARGET_ARM)
9937      arm_expand_prologue ();
9938    else
9939      thumb_expand_prologue ();
9940   DONE;
9941   "
9942 )
9943
9944 (define_expand "epilogue"
9945   [(clobber (const_int 0))]
9946   "TARGET_EITHER"
9947   "
9948   if (current_function_calls_eh_return)
9949     emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
9950   if (TARGET_THUMB)
9951     thumb_expand_epilogue ();
9952   else if (USE_RETURN_INSN (FALSE))
9953     {
9954       emit_jump_insn (gen_return ());
9955       DONE;
9956     }
9957   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9958         gen_rtvec (1,
9959                 gen_rtx_RETURN (VOIDmode)),
9960         VUNSPEC_EPILOGUE));
9961   DONE;
9962   "
9963 )
9964
9965 ;; Note - although unspec_volatile's USE all hard registers,
9966 ;; USEs are ignored after relaod has completed.  Thus we need
9967 ;; to add an unspec of the link register to ensure that flow
9968 ;; does not think that it is unused by the sibcall branch that
9969 ;; will replace the standard function epilogue.
9970 (define_insn "sibcall_epilogue"
9971   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9972               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9973   "TARGET_ARM"
9974   "*
9975   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9976     return output_return_instruction (const_true_rtx, FALSE, FALSE);
9977   return arm_output_epilogue (next_nonnote_insn (insn));
9978   "
9979 ;; Length is absolute worst case
9980   [(set_attr "length" "44")
9981    (set_attr "type" "block")
9982    ;; We don't clobber the conditions, but the potential length of this
9983    ;; operation is sufficient to make conditionalizing the sequence 
9984    ;; unlikely to be profitable.
9985    (set_attr "conds" "clob")]
9986 )
9987
9988 (define_insn "*epilogue_insns"
9989   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9990   "TARGET_EITHER"
9991   "*
9992   if (TARGET_ARM)
9993     return arm_output_epilogue (NULL);
9994   else /* TARGET_THUMB */
9995     return thumb_unexpanded_epilogue ();
9996   "
9997   ; Length is absolute worst case
9998   [(set_attr "length" "44")
9999    (set_attr "type" "block")
10000    ;; We don't clobber the conditions, but the potential length of this
10001    ;; operation is sufficient to make conditionalizing the sequence 
10002    ;; unlikely to be profitable.
10003    (set_attr "conds" "clob")]
10004 )
10005
10006 (define_expand "eh_epilogue"
10007   [(use (match_operand:SI 0 "register_operand" ""))
10008    (use (match_operand:SI 1 "register_operand" ""))
10009    (use (match_operand:SI 2 "register_operand" ""))]
10010   "TARGET_EITHER"
10011   "
10012   {
10013     cfun->machine->eh_epilogue_sp_ofs = operands[1];
10014     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10015       {
10016         rtx ra = gen_rtx_REG (Pmode, 2);
10017
10018         emit_move_insn (ra, operands[2]);
10019         operands[2] = ra;
10020       }
10021     /* This is a hack -- we may have crystalized the function type too
10022        early.  */
10023     cfun->machine->func_type = 0;
10024   }"
10025 )
10026
10027 ;; This split is only used during output to reduce the number of patterns
10028 ;; that need assembler instructions adding to them.  We allowed the setting
10029 ;; of the conditions to be implicit during rtl generation so that
10030 ;; the conditional compare patterns would work.  However this conflicts to
10031 ;; some extent with the conditional data operations, so we have to split them
10032 ;; up again here.
10033
10034 (define_split
10035   [(set (match_operand:SI 0 "s_register_operand" "")
10036         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10037                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10038                          (match_dup 0)
10039                          (match_operand 4 "" "")))
10040    (clobber (reg:CC CC_REGNUM))]
10041   "TARGET_ARM && reload_completed"
10042   [(set (match_dup 5) (match_dup 6))
10043    (cond_exec (match_dup 7)
10044               (set (match_dup 0) (match_dup 4)))]
10045   "
10046   {
10047     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10048                                              operands[2], operands[3]);
10049     enum rtx_code rc = GET_CODE (operands[1]);
10050
10051     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10052     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10053     if (mode == CCFPmode || mode == CCFPEmode)
10054       rc = reverse_condition_maybe_unordered (rc);
10055     else
10056       rc = reverse_condition (rc);
10057
10058     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10059   }"
10060 )
10061
10062 (define_split
10063   [(set (match_operand:SI 0 "s_register_operand" "")
10064         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10065                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10066                          (match_operand 4 "" "")
10067                          (match_dup 0)))
10068    (clobber (reg:CC CC_REGNUM))]
10069   "TARGET_ARM && reload_completed"
10070   [(set (match_dup 5) (match_dup 6))
10071    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10072               (set (match_dup 0) (match_dup 4)))]
10073   "
10074   {
10075     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10076                                              operands[2], operands[3]);
10077
10078     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10079     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10080   }"
10081 )
10082
10083 (define_split
10084   [(set (match_operand:SI 0 "s_register_operand" "")
10085         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10086                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10087                          (match_operand 4 "" "")
10088                          (match_operand 5 "" "")))
10089    (clobber (reg:CC CC_REGNUM))]
10090   "TARGET_ARM && reload_completed"
10091   [(set (match_dup 6) (match_dup 7))
10092    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10093               (set (match_dup 0) (match_dup 4)))
10094    (cond_exec (match_dup 8)
10095               (set (match_dup 0) (match_dup 5)))]
10096   "
10097   {
10098     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10099                                              operands[2], operands[3]);
10100     enum rtx_code rc = GET_CODE (operands[1]);
10101
10102     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10103     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10104     if (mode == CCFPmode || mode == CCFPEmode)
10105       rc = reverse_condition_maybe_unordered (rc);
10106     else
10107       rc = reverse_condition (rc);
10108
10109     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10110   }"
10111 )
10112
10113 (define_split
10114   [(set (match_operand:SI 0 "s_register_operand" "")
10115         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10116                           [(match_operand:SI 2 "s_register_operand" "")
10117                            (match_operand:SI 3 "arm_add_operand" "")])
10118                          (match_operand:SI 4 "arm_rhs_operand" "")
10119                          (not:SI
10120                           (match_operand:SI 5 "s_register_operand" ""))))
10121    (clobber (reg:CC CC_REGNUM))]
10122   "TARGET_ARM && reload_completed"
10123   [(set (match_dup 6) (match_dup 7))
10124    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10125               (set (match_dup 0) (match_dup 4)))
10126    (cond_exec (match_dup 8)
10127               (set (match_dup 0) (not:SI (match_dup 5))))]
10128   "
10129   {
10130     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10131                                              operands[2], operands[3]);
10132     enum rtx_code rc = GET_CODE (operands[1]);
10133
10134     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10135     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10136     if (mode == CCFPmode || mode == CCFPEmode)
10137       rc = reverse_condition_maybe_unordered (rc);
10138     else
10139       rc = reverse_condition (rc);
10140
10141     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10142   }"
10143 )
10144
10145 (define_insn "*cond_move_not"
10146   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10147         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10148                           [(match_operand 3 "cc_register" "") (const_int 0)])
10149                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10150                          (not:SI
10151                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
10152   "TARGET_ARM"
10153   "@
10154    mvn%D4\\t%0, %2
10155    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
10156   [(set_attr "conds" "use")
10157    (set_attr "length" "4,8")]
10158 )
10159
10160 ;; The next two patterns occur when an AND operation is followed by a
10161 ;; scc insn sequence 
10162
10163 (define_insn "*sign_extract_onebit"
10164   [(set (match_operand:SI 0 "s_register_operand" "=r")
10165         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10166                          (const_int 1)
10167                          (match_operand:SI 2 "const_int_operand" "n")))
10168     (clobber (reg:CC CC_REGNUM))]
10169   "TARGET_ARM"
10170   "*
10171     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10172     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10173     return \"mvnne\\t%0, #0\";
10174   "
10175   [(set_attr "conds" "clob")
10176    (set_attr "length" "8")]
10177 )
10178
10179 (define_insn "*not_signextract_onebit"
10180   [(set (match_operand:SI 0 "s_register_operand" "=r")
10181         (not:SI
10182          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10183                           (const_int 1)
10184                           (match_operand:SI 2 "const_int_operand" "n"))))
10185    (clobber (reg:CC CC_REGNUM))]
10186   "TARGET_ARM"
10187   "*
10188     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10189     output_asm_insn (\"tst\\t%1, %2\", operands);
10190     output_asm_insn (\"mvneq\\t%0, #0\", operands);
10191     return \"movne\\t%0, #0\";
10192   "
10193   [(set_attr "conds" "clob")
10194    (set_attr "length" "12")]
10195 )
10196
10197 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
10198 ;; expressions.  For simplicity, the first register is also in the unspec
10199 ;; part.
10200 (define_insn "*push_multi"
10201   [(match_parallel 2 "multi_register_push"
10202     [(set (match_operand:BLK 0 "memory_operand" "=m")
10203           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
10204                       UNSPEC_PUSH_MULT))])]
10205   "TARGET_ARM"
10206   "*
10207   {
10208     int num_saves = XVECLEN (operands[2], 0);
10209      
10210     /* For the StrongARM at least it is faster to
10211        use STR to store only a single register.  */
10212     if (num_saves == 1)
10213       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10214     else
10215       {
10216         int i;
10217         char pattern[100];
10218
10219         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10220
10221         for (i = 1; i < num_saves; i++)
10222           {
10223             strcat (pattern, \", %|\");
10224             strcat (pattern,
10225                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10226           }
10227
10228         strcat (pattern, \"}\");
10229         output_asm_insn (pattern, operands);
10230       }
10231
10232     return \"\";
10233   }"
10234   [(set_attr "type" "store4")]
10235 )
10236
10237 (define_insn "stack_tie"
10238   [(set (mem:BLK (scratch))
10239         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
10240                      (match_operand:SI 1 "s_register_operand" "r")]
10241                     UNSPEC_PRLG_STK))]
10242   ""
10243   ""
10244   [(set_attr "length" "0")]
10245 )
10246
10247 ;; Similarly for the floating point registers
10248 (define_insn "*push_fp_multi"
10249   [(match_parallel 2 "multi_register_push"
10250     [(set (match_operand:BLK 0 "memory_operand" "=m")
10251           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10252                       UNSPEC_PUSH_MULT))])]
10253   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
10254   "*
10255   {
10256     char pattern[100];
10257
10258     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10259     output_asm_insn (pattern, operands);
10260     return \"\";
10261   }"
10262   [(set_attr "type" "f_store")]
10263 )
10264
10265 ;; Special patterns for dealing with the constant pool
10266
10267 (define_insn "align_4"
10268   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10269   "TARGET_EITHER"
10270   "*
10271   assemble_align (32);
10272   return \"\";
10273   "
10274 )
10275
10276 (define_insn "align_8"
10277   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10278   "TARGET_EITHER"
10279   "*
10280   assemble_align (64);
10281   return \"\";
10282   "
10283 )
10284
10285 (define_insn "consttable_end"
10286   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10287   "TARGET_EITHER"
10288   "*
10289   making_const_table = FALSE;
10290   return \"\";
10291   "
10292 )
10293
10294 (define_insn "consttable_1"
10295   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10296   "TARGET_THUMB"
10297   "*
10298   making_const_table = TRUE;
10299   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10300   assemble_zeros (3);
10301   return \"\";
10302   "
10303   [(set_attr "length" "4")]
10304 )
10305
10306 (define_insn "consttable_2"
10307   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10308   "TARGET_THUMB"
10309   "*
10310   making_const_table = TRUE;
10311   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10312   assemble_zeros (2);
10313   return \"\";
10314   "
10315   [(set_attr "length" "4")]
10316 )
10317
10318 (define_insn "consttable_4"
10319   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10320   "TARGET_EITHER"
10321   "*
10322   {
10323     making_const_table = TRUE;
10324     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10325       {
10326       case MODE_FLOAT:
10327       {
10328         REAL_VALUE_TYPE r;
10329         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10330         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10331         break;
10332       }
10333       default:
10334         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
10335         break;
10336       }
10337     return \"\";
10338   }"
10339   [(set_attr "length" "4")]
10340 )
10341
10342 (define_insn "consttable_8"
10343   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10344   "TARGET_EITHER"
10345   "*
10346   {
10347     making_const_table = TRUE;
10348     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10349       {
10350        case MODE_FLOAT:
10351         {
10352           REAL_VALUE_TYPE r;
10353           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10354           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10355           break;
10356         }
10357       default:
10358         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10359         break;
10360       }
10361     return \"\";
10362   }"
10363   [(set_attr "length" "8")]
10364 )
10365
10366 ;; Miscellaneous Thumb patterns
10367
10368 (define_expand "tablejump"
10369   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10370               (use (label_ref (match_operand 1 "" "")))])]
10371   "TARGET_THUMB"
10372   "
10373   if (flag_pic)
10374     {
10375       /* Hopefully, CSE will eliminate this copy.  */
10376       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10377       rtx reg2 = gen_reg_rtx (SImode);
10378
10379       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10380       operands[0] = reg2;
10381     }
10382   "
10383 )
10384
10385 ;; NB never uses BX.
10386 (define_insn "*thumb_tablejump"
10387   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10388    (use (label_ref (match_operand 1 "" "")))]
10389   "TARGET_THUMB"
10390   "mov\\t%|pc, %0"
10391   [(set_attr "length" "2")]
10392 )
10393
10394 ;; V5 Instructions,
10395
10396 (define_insn "clzsi2"
10397   [(set (match_operand:SI 0 "s_register_operand" "=r")
10398         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10399   "TARGET_ARM && arm_arch5"
10400   "clz%?\\t%0, %1"
10401   [(set_attr "predicable" "yes")])
10402
10403 (define_expand "ffssi2"
10404   [(set (match_operand:SI 0 "s_register_operand" "")
10405         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10406   "TARGET_ARM && arm_arch5"
10407   "
10408   {
10409     rtx t1, t2, t3;
10410
10411     t1 = gen_reg_rtx (SImode);
10412     t2 = gen_reg_rtx (SImode);
10413     t3 = gen_reg_rtx (SImode);
10414
10415     emit_insn (gen_negsi2 (t1, operands[1]));
10416     emit_insn (gen_andsi3 (t2, operands[1], t1));
10417     emit_insn (gen_clzsi2 (t3, t2));
10418     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10419     DONE;
10420   }"
10421 )
10422
10423 (define_expand "ctzsi2"
10424   [(set (match_operand:SI 0 "s_register_operand" "")
10425         (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10426   "TARGET_ARM && arm_arch5"
10427   "
10428   {
10429     rtx t1, t2, t3;
10430
10431     t1 = gen_reg_rtx (SImode);
10432     t2 = gen_reg_rtx (SImode);
10433     t3 = gen_reg_rtx (SImode);
10434
10435     emit_insn (gen_negsi2 (t1, operands[1]));
10436     emit_insn (gen_andsi3 (t2, operands[1], t1));
10437     emit_insn (gen_clzsi2 (t3, t2));
10438     emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10439     DONE;
10440   }"
10441 )
10442
10443 ;; V5E instructions.
10444
10445 (define_insn "prefetch"
10446   [(prefetch (match_operand:SI 0 "address_operand" "p")
10447              (match_operand:SI 1 "" "")
10448              (match_operand:SI 2 "" ""))]
10449   "TARGET_ARM && arm_arch5e"
10450   "pld\\t%a0")
10451
10452 ;; General predication pattern
10453
10454 (define_cond_exec
10455   [(match_operator 0 "arm_comparison_operator"
10456     [(match_operand 1 "cc_register" "")
10457      (const_int 0)])]
10458   "TARGET_ARM"
10459   ""
10460 )
10461
10462 (define_insn "prologue_use"
10463   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10464   ""
10465   "%@ %0 needed for prologue"
10466 )
10467
10468
10469 ;; Patterns for exception handling
10470
10471 (define_expand "eh_return"
10472   [(use (match_operand 0 "general_operand" ""))]
10473   "TARGET_EITHER"
10474   "
10475   {
10476     if (TARGET_ARM)
10477       emit_insn (gen_arm_eh_return (operands[0]));
10478     else
10479       emit_insn (gen_thumb_eh_return (operands[0]));
10480     DONE;
10481   }"
10482 )
10483                                    
10484 ;; We can't expand this before we know where the link register is stored.
10485 (define_insn_and_split "arm_eh_return"
10486   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10487                     VUNSPEC_EH_RETURN)
10488    (clobber (match_scratch:SI 1 "=&r"))]
10489   "TARGET_ARM"
10490   "#"
10491   "&& reload_completed"
10492   [(const_int 0)]
10493   "
10494   {
10495     arm_set_return_address (operands[0], operands[1]);
10496     DONE;
10497   }"
10498 )
10499
10500 (define_insn_and_split "thumb_eh_return"
10501   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10502                     VUNSPEC_EH_RETURN)
10503    (clobber (match_scratch:SI 1 "=&l"))]
10504   "TARGET_THUMB"
10505   "#"
10506   "&& reload_completed"
10507   [(const_int 0)]
10508   "
10509   {
10510     thumb_set_return_address (operands[0], operands[1]);
10511     DONE;
10512   }"
10513 )
10514
10515 ;; Load the FPA co-processor patterns
10516 (include "fpa.md")
10517 ;; Load the Maverick co-processor patterns
10518 (include "cirrus.md")
10519 ;; Load the Intel Wireless Multimedia Extension patterns
10520 (include "iwmmxt.md")
10521 ;; Load the VFP co-processor patterns
10522 (include "vfp.md")
10523