* config/arm/arm.md (addsi3_cbranch_scratch): Correct constraints.
[official-gcc.git] / gcc / config / arm / arm.md
blob86113e7135e91f88cfa1c18ffc33110b7cffc2e2
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  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).
8 ;; This file is part of GCC.
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.
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.
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.
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
28 ;;---------------------------------------------------------------------------
29 ;; Constants
31 ;; Register numbers
32 (define_constants
33   [(IP_REGNUM       12)         ; Scratch register
34    (SP_REGNUM       13)         ; Stack pointer
35    (LR_REGNUM       14)         ; Return address register
36    (PC_REGNUM       15)         ; Program counter
37    (CC_REGNUM       24)         ; Condition code pseudo register
38    (LAST_ARM_REGNUM 15)
39   ]
41 ;; 3rd operand to select_dominance_cc_mode
42 (define_constants
43   [(DOM_CC_X_AND_Y  0)
44    (DOM_CC_NX_OR_Y  1)
45    (DOM_CC_X_OR_Y   2)
46   ]
49 ;; UNSPEC Usage:
50 ;; Note: sin and cos are no-longer used.
52 (define_constants
53   [(UNSPEC_SIN       0) ; `sin' operation (MODE_FLOAT):
54                         ;   operand 0 is the result,
55                         ;   operand 1 the parameter.
56    (UNPSEC_COS       1) ; `cos' operation (MODE_FLOAT):
57                         ;   operand 0 is the result,
58                         ;   operand 1 the parameter.
59    (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
60                         ;   operand 0 is the first register,
61                         ;   subsequent registers are in parallel (use ...)
62                         ;   expressions.
63    (UNSPEC_PIC_SYM   3) ; A symbol that has been treated properly for pic
64                         ;   usage, that is, we will add the pic_register
65                         ;   value to it before trying to dereference it.
66    (UNSPEC_PIC_BASE  4) ; Adding the PC value to the offset to the
67                         ;   GLOBAL_OFFSET_TABLE.  The operation is fully
68                         ;   described by the RTL but must be wrapped to
69                         ;   prevent combine from trying to rip it apart.
70    (UNSPEC_PRLG_STK  5) ; A special barrier that prevents frame accesses 
71                         ;   being scheduled before the stack adjustment insn.
72    (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
73                         ; this unspec is used to prevent the deletion of
74                         ; instructions setting registers for EH handling
75                         ; and stack frame generation.  Operand 0 is the
76                         ; register to "use".
77    (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
78    (UNSPEC_WSHUFH    8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
79    (UNSPEC_WACC      9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
80    (UNSPEC_TMOVMSK  10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
81    (UNSPEC_WSAD     11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
82    (UNSPEC_WSADZ    12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
83    (UNSPEC_WMACS    13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
84    (UNSPEC_WMACU    14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
85    (UNSPEC_WMACSZ   15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
86    (UNSPEC_WMACUZ   16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
87    (UNSPEC_CLRDI    17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
88    (UNSPEC_WMADDS   18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
89    (UNSPEC_WMADDU   19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
90   ]
93 ;; UNSPEC_VOLATILE Usage:
95 (define_constants
96   [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
97                         ;   insn in the code.
98    (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
99                         ;   instruction epilogue sequence that isn't expanded
100                         ;   into normal RTL.  Used for both normal and sibcall
101                         ;   epilogues.
102    (VUNSPEC_ALIGN    2) ; `align' insn.  Used at the head of a minipool table 
103                         ;   for inlined constants.
104    (VUNSPEC_POOL_END 3) ; `end-of-table'.  Used to mark the end of a minipool
105                         ;   table.
106    (VUNSPEC_POOL_1   4) ; `pool-entry(1)'.  An entry in the constant pool for
107                         ;   an 8-bit object.
108    (VUNSPEC_POOL_2   5) ; `pool-entry(2)'.  An entry in the constant pool for
109                         ;   a 16-bit object.
110    (VUNSPEC_POOL_4   6) ; `pool-entry(4)'.  An entry in the constant pool for
111                         ;   a 32-bit object.
112    (VUNSPEC_POOL_8   7) ; `pool-entry(8)'.  An entry in the constant pool for
113                         ;   a 64-bit object.
114    (VUNSPEC_TMRC     8) ; Used by the iWMMXt TMRC instruction.
115    (VUNSPEC_TMCR     9) ; Used by the iWMMXt TMCR instruction.
116    (VUNSPEC_ALIGN8   10) ; 8-byte alignment version of VUNSPEC_ALIGN
117    (VUNSPEC_WCMP_EQ  11) ; Used by the iWMMXt WCMPEQ instructions
118    (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
119    (VUNSPEC_WCMP_GT  13) ; Used by the iwMMXT WCMPGT instructions
120    (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
121                          ; handling.
122   ]
125 ;;---------------------------------------------------------------------------
126 ;; Attributes
128 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
129 ; generating ARM code.  This is used to control the length of some insn
130 ; patterns that share the same RTL in both ARM and Thumb code.
131 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
133 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
134 ; scheduling decisions for the load unit and the multiplier.
135 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
137 ; IS_XSCALE is set to 'yes' when compiling for XScale.
138 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
140 ;; Operand number of an input operand that is shifted.  Zero if the
141 ;; given instruction does not shift one of its input operands.
142 (define_attr "shift" "" (const_int 0))
144 ; Floating Point Unit.  If we only have floating point emulation, then there
145 ; is no point in scheduling the floating point insns.  (Well, for best
146 ; performance we should try and group them together).
147 (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
148   (const (symbol_ref "arm_fpu_attr")))
150 ; LENGTH of an instruction (in bytes)
151 (define_attr "length" "" (const_int 4))
153 ; POOL_RANGE is how far away from a constant pool entry that this insn
154 ; can be placed.  If the distance is zero, then this insn will never
155 ; reference the pool.
156 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
157 ; before its address.
158 (define_attr "pool_range" "" (const_int 0))
159 (define_attr "neg_pool_range" "" (const_int 0))
161 ; An assembler sequence may clobber the condition codes without us knowing.
162 ; If such an insn references the pool, then we have no way of knowing how,
163 ; so use the most conservative value for pool_range.
164 (define_asm_attributes
165  [(set_attr "conds" "clob")
166   (set_attr "length" "4")
167   (set_attr "pool_range" "250")])
169 ;; The instruction used to implement a particular pattern.  This
170 ;; information is used by pipeline descriptions to provide accurate
171 ;; scheduling information.
173 (define_attr "insn"
174         "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"
175         (const_string "other"))
177 ; TYPE attribute is used to detect floating point instructions which, if
178 ; running on a co-processor can run in parallel with other, basic instructions
179 ; If write-buffer scheduling is enabled then it can also be used in the
180 ; scheduling of writes.
182 ; Classification of each insn
183 ; alu           any alu  instruction that doesn't hit memory or fp
184 ;               regs or have a shifted source operand
185 ; alu_shift     any data instruction that doesn't hit memory or fp
186 ;               regs, but has a source operand shifted by a constant
187 ; alu_shift_reg any data instruction that doesn't hit memory or fp
188 ;               regs, but has a source operand shifted by a register value
189 ; mult          a multiply instruction
190 ; block         blockage insn, this blocks all functional units
191 ; float         a floating point arithmetic operation (subject to expansion)
192 ; fdivd         DFmode floating point division
193 ; fdivs         SFmode floating point division
194 ; fmul          Floating point multiply
195 ; ffmul         Fast floating point multiply
196 ; farith        Floating point arithmetic (4 cycle)
197 ; ffarith       Fast floating point arithmetic (2 cycle)
198 ; float_em      a floating point arithmetic operation that is normally emulated
199 ;               even on a machine with an fpa.
200 ; f_load        a floating point load from memory
201 ; f_store       a floating point store to memory
202 ; f_mem_r       a transfer of a floating point register to a real reg via mem
203 ; r_mem_f       the reverse of f_mem_r
204 ; f_2_r         fast transfer float to arm (no memory needed)
205 ; r_2_f         fast transfer arm to float
206 ; branch        a branch
207 ; call          a subroutine call
208 ; load_byte     load byte(s) from memory to arm registers
209 ; load1         load 1 word from memory to arm registers
210 ; load2         load 2 words from memory to arm registers
211 ; load3         load 3 words from memory to arm registers
212 ; load4         load 4 words from memory to arm registers
213 ; store         store 1 word to memory from arm registers
214 ; store2        store 2 words
215 ; store3        store 3 words
216 ; store4        store 4 (or more) words
217 ;  Additions for Cirrus Maverick co-processor:
218 ; mav_farith    Floating point arithmetic (4 cycle)
219 ; mav_dmult     Double multiplies (7 cycle)
221 (define_attr "type"
222         "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" 
223         (if_then_else 
224          (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
225          (const_string "mult")
226          (const_string "alu")))
228 ; Load scheduling, set from the arm_ld_sched variable
229 ; initialized by arm_override_options() 
230 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
232 ; condition codes: this one is used by final_prescan_insn to speed up
233 ; conditionalizing instructions.  It saves having to scan the rtl to see if
234 ; it uses or alters the condition codes.
236 ; USE means that the condition codes are used by the insn in the process of
237 ;   outputting code, this means (at present) that we can't use the insn in
238 ;   inlined branches
240 ; SET means that the purpose of the insn is to set the condition codes in a
241 ;   well defined manner.
243 ; CLOB means that the condition codes are altered in an undefined manner, if
244 ;   they are altered at all
246 ; JUMP_CLOB is used when the condition cannot be represented by a single
247 ;   instruction (UNEQ and LTGT).  These cannot be predicated.
249 ; NOCOND means that the condition codes are neither altered nor affect the
250 ;   output of this insn
252 (define_attr "conds" "use,set,clob,jump_clob,nocond"
253         (if_then_else (eq_attr "type" "call")
254          (const_string "clob")
255          (const_string "nocond")))
257 ; Predicable means that the insn can be conditionally executed based on
258 ; an automatically added predicate (additional patterns are generated by 
259 ; gen...).  We default to 'no' because no Thumb patterns match this rule
260 ; and not all ARM patterns do.
261 (define_attr "predicable" "no,yes" (const_string "no"))
263 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
264 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
265 ; suffer blockages enough to warrant modelling this (and it can adversely
266 ; affect the schedule).
267 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
269 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
270 ; to stall the processor.  Used with model_wbuf above.
271 (define_attr "write_conflict" "no,yes"
272   (if_then_else (eq_attr "type"
273                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
274                 (const_string "yes")
275                 (const_string "no")))
277 ; Classify the insns into those that take one cycle and those that take more
278 ; than one on the main cpu execution unit.
279 (define_attr "core_cycles" "single,multi"
280   (if_then_else (eq_attr "type"
281                  "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
282                 (const_string "single")
283                 (const_string "multi")))
285 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
286 ;; distant label.  Only applicable to Thumb code.
287 (define_attr "far_jump" "yes,no" (const_string "no"))
289 (include "predicates.md")
291 ;;---------------------------------------------------------------------------
292 ;; Pipeline descriptions
294 ;; Processor type.  This is created automatically from arm-cores.def.
295 (include "arm-tune.md")
297 ;; True if the generic scheduling description should be used.
299 (define_attr "generic_sched" "yes,no"
300         (if_then_else 
301          (eq_attr "tune" "arm926ejs,arm1026ejs,arm1136js,arm1136jfs") 
302          (const_string "no")
303          (const_string "yes")))
304         
305 (include "arm-generic.md")
306 (include "arm926ejs.md")
307 (include "arm1026ejs.md")
308 (include "arm1136jfs.md")
311 ;;---------------------------------------------------------------------------
312 ;; Insn patterns
314 ;; Addition insns.
316 ;; Note: For DImode insns, there is normally no reason why operands should
317 ;; not be in the same register, what we don't want is for something being
318 ;; written to partially overlap something that is an input.
319 ;; Cirrus 64bit additions should not be split because we have a native
320 ;; 64bit addition instructions.
322 (define_expand "adddi3"
323  [(parallel
324    [(set (match_operand:DI           0 "s_register_operand" "")
325           (plus:DI (match_operand:DI 1 "s_register_operand" "")
326                    (match_operand:DI 2 "s_register_operand" "")))
327     (clobber (reg:CC CC_REGNUM))])]
328   "TARGET_EITHER"
329   "
330   if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
331     {
332       if (!cirrus_fp_register (operands[0], DImode))
333         operands[0] = force_reg (DImode, operands[0]);
334       if (!cirrus_fp_register (operands[1], DImode))
335         operands[1] = force_reg (DImode, operands[1]);
336       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
337       DONE;
338     }
340   if (TARGET_THUMB)
341     {
342       if (GET_CODE (operands[1]) != REG)
343         operands[1] = force_reg (SImode, operands[1]);
344       if (GET_CODE (operands[2]) != REG)
345         operands[2] = force_reg (SImode, operands[2]);
346      }
347   "
350 (define_insn "*thumb_adddi3"
351   [(set (match_operand:DI          0 "register_operand" "=l")
352         (plus:DI (match_operand:DI 1 "register_operand" "%0")
353                  (match_operand:DI 2 "register_operand" "l")))
354    (clobber (reg:CC CC_REGNUM))
355   ]
356   "TARGET_THUMB"
357   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
358   [(set_attr "length" "4")]
361 (define_insn_and_split "*arm_adddi3"
362   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
363         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
364                  (match_operand:DI 2 "s_register_operand" "r,  0")))
365    (clobber (reg:CC CC_REGNUM))]
366   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
367   "#"
368   "TARGET_ARM && reload_completed"
369   [(parallel [(set (reg:CC_C CC_REGNUM)
370                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
371                                  (match_dup 1)))
372               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
373    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
374                                (plus:SI (match_dup 4) (match_dup 5))))]
375   "
376   {
377     operands[3] = gen_highpart (SImode, operands[0]);
378     operands[0] = gen_lowpart (SImode, operands[0]);
379     operands[4] = gen_highpart (SImode, operands[1]);
380     operands[1] = gen_lowpart (SImode, operands[1]);
381     operands[5] = gen_highpart (SImode, operands[2]);
382     operands[2] = gen_lowpart (SImode, operands[2]);
383   }"
384   [(set_attr "conds" "clob")
385    (set_attr "length" "8")]
388 (define_insn_and_split "*adddi_sesidi_di"
389   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
390         (plus:DI (sign_extend:DI
391                   (match_operand:SI 2 "s_register_operand" "r,r"))
392                  (match_operand:DI 1 "s_register_operand" "r,0")))
393    (clobber (reg:CC CC_REGNUM))]
394   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
395   "#"
396   "TARGET_ARM && reload_completed"
397   [(parallel [(set (reg:CC_C CC_REGNUM)
398                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
399                                  (match_dup 1)))
400               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
401    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
402                                (plus:SI (ashiftrt:SI (match_dup 2)
403                                                      (const_int 31))
404                                         (match_dup 4))))]
405   "
406   {
407     operands[3] = gen_highpart (SImode, operands[0]);
408     operands[0] = gen_lowpart (SImode, operands[0]);
409     operands[4] = gen_highpart (SImode, operands[1]);
410     operands[1] = gen_lowpart (SImode, operands[1]);
411     operands[2] = gen_lowpart (SImode, operands[2]);
412   }"
413   [(set_attr "conds" "clob")
414    (set_attr "length" "8")]
417 (define_insn_and_split "*adddi_zesidi_di"
418   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
419         (plus:DI (zero_extend:DI
420                   (match_operand:SI 2 "s_register_operand" "r,r"))
421                  (match_operand:DI 1 "s_register_operand" "r,0")))
422    (clobber (reg:CC CC_REGNUM))]
423   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
424   "#"
425   "TARGET_ARM && reload_completed"
426   [(parallel [(set (reg:CC_C CC_REGNUM)
427                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
428                                  (match_dup 1)))
429               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
430    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
431                                (plus:SI (match_dup 4) (const_int 0))))]
432   "
433   {
434     operands[3] = gen_highpart (SImode, operands[0]);
435     operands[0] = gen_lowpart (SImode, operands[0]);
436     operands[4] = gen_highpart (SImode, operands[1]);
437     operands[1] = gen_lowpart (SImode, operands[1]);
438     operands[2] = gen_lowpart (SImode, operands[2]);
439   }"
440   [(set_attr "conds" "clob")
441    (set_attr "length" "8")]
444 (define_expand "addsi3"
445   [(set (match_operand:SI          0 "s_register_operand" "")
446         (plus:SI (match_operand:SI 1 "s_register_operand" "")
447                  (match_operand:SI 2 "reg_or_int_operand" "")))]
448   "TARGET_EITHER"
449   "
450   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
451     {
452       arm_split_constant (PLUS, SImode, NULL_RTX,
453                           INTVAL (operands[2]), operands[0], operands[1],
454                           optimize && !no_new_pseudos);
455       DONE;
456     }
457   "
460 ; If there is a scratch available, this will be faster than synthesizing the
461 ; addition.
462 (define_peephole2
463   [(match_scratch:SI 3 "r")
464    (set (match_operand:SI          0 "arm_general_register_operand" "")
465         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
466                  (match_operand:SI 2 "const_int_operand"  "")))]
467   "TARGET_ARM &&
468    !(const_ok_for_arm (INTVAL (operands[2]))
469      || const_ok_for_arm (-INTVAL (operands[2])))
470     && const_ok_for_arm (~INTVAL (operands[2]))"
471   [(set (match_dup 3) (match_dup 2))
472    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
473   ""
476 (define_insn_and_split "*arm_addsi3"
477   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
478         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
479                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
480   "TARGET_ARM"
481   "@
482    add%?\\t%0, %1, %2
483    sub%?\\t%0, %1, #%n2
484    #"
485   "TARGET_ARM &&
486    GET_CODE (operands[2]) == CONST_INT
487    && !(const_ok_for_arm (INTVAL (operands[2]))
488         || const_ok_for_arm (-INTVAL (operands[2])))"
489   [(clobber (const_int 0))]
490   "
491   arm_split_constant (PLUS, SImode, curr_insn,
492                       INTVAL (operands[2]), operands[0],
493                       operands[1], 0);
494   DONE;
495   "
496   [(set_attr "length" "4,4,16")
497    (set_attr "predicable" "yes")]
500 ;; Register group 'k' is a single register group containing only the stack
501 ;; register.  Trying to reload it will always fail catastrophically,
502 ;; so never allow those alternatives to match if reloading is needed.
504 (define_insn "*thumb_addsi3"
505   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
506         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
507                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
508   "TARGET_THUMB"
509   "*
510    static const char * const asms[] = 
511    {
512      \"add\\t%0, %0, %2\",
513      \"sub\\t%0, %0, #%n2\",
514      \"add\\t%0, %1, %2\",
515      \"add\\t%0, %0, %2\",
516      \"add\\t%0, %0, %2\",
517      \"add\\t%0, %1, %2\",
518      \"add\\t%0, %1, %2\"
519    };
520    if ((which_alternative == 2 || which_alternative == 6)
521        && GET_CODE (operands[2]) == CONST_INT
522        && INTVAL (operands[2]) < 0)
523      return \"sub\\t%0, %1, #%n2\";
524    return asms[which_alternative];
525   "
526   [(set_attr "length" "2")]
529 ;; Reloading and elimination of the frame pointer can
530 ;; sometimes cause this optimization to be missed.
531 (define_peephole2
532   [(set (match_operand:SI 0 "arm_general_register_operand" "")
533         (match_operand:SI 1 "const_int_operand" ""))
534    (set (match_dup 0)
535         (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
536   "TARGET_THUMB
537    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
538    && (INTVAL (operands[1]) & 3) == 0"
539   [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
540   ""
543 (define_insn "*addsi3_compare0"
544   [(set (reg:CC_NOOV CC_REGNUM)
545         (compare:CC_NOOV
546          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
547                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
548          (const_int 0)))
549    (set (match_operand:SI 0 "s_register_operand" "=r,r")
550         (plus:SI (match_dup 1) (match_dup 2)))]
551   "TARGET_ARM"
552   "@
553    add%?s\\t%0, %1, %2
554    sub%?s\\t%0, %1, #%n2"
555   [(set_attr "conds" "set")]
558 (define_insn "*addsi3_compare0_scratch"
559   [(set (reg:CC_NOOV CC_REGNUM)
560         (compare:CC_NOOV
561          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
562                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
563          (const_int 0)))]
564   "TARGET_ARM"
565   "@
566    cmn%?\\t%0, %1
567    cmp%?\\t%0, #%n1"
568   [(set_attr "conds" "set")]
571 ;; These patterns are the same ones as the two regular addsi3_compare0
572 ;; patterns, except we write them slightly different - the combiner
573 ;; tends to generate them this way.
574 (define_insn "*addsi3_compare0_for_combiner"
575   [(set (reg:CC CC_REGNUM)
576         (compare:CC
577          (match_operand:SI 1 "s_register_operand" "r,r")
578          (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
579    (set (match_operand:SI 0 "s_register_operand" "=r,r")
580         (plus:SI (match_dup 1) (match_dup 2)))]
581   "TARGET_ARM"
582   "@
583    add%?s\\t%0, %1, %2
584    sub%?s\\t%0, %1, #%n2"
585   [(set_attr "conds" "set")]
588 (define_insn "*addsi3_compare0_scratch_for_combiner"
589   [(set (reg:CC CC_REGNUM)
590         (compare:CC
591          (match_operand:SI 0 "s_register_operand" "r,r")
592          (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
593   "TARGET_ARM"
594   "@
595    cmn%?\\t%0, %1
596    cmp%?\\t%0, #%n1"
597   [(set_attr "conds" "set")]
600 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
601 ;; addend is a constant.
602 (define_insn "*cmpsi2_addneg"
603   [(set (reg:CC CC_REGNUM)
604         (compare:CC
605          (match_operand:SI 1 "s_register_operand" "r,r")
606          (match_operand:SI 2 "arm_addimm_operand" "I,L")))
607    (set (match_operand:SI 0 "s_register_operand" "=r,r")
608         (plus:SI (match_dup 1)
609                  (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
610   "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
611   "@
612    sub%?s\\t%0, %1, %2
613    add%?s\\t%0, %1, #%n2"
614   [(set_attr "conds" "set")]
617 ;; Convert the sequence
618 ;;  sub  rd, rn, #1
619 ;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
620 ;;  bne  dest
621 ;; into
622 ;;  subs rd, rn, #1
623 ;;  bcs  dest   ((unsigned)rn >= 1)
624 ;; similarly for the beq variant using bcc.
625 ;; This is a common looping idiom (while (n--))
626 (define_peephole2
627   [(set (match_operand:SI 0 "arm_general_register_operand" "")
628         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
629                  (const_int -1)))
630    (set (match_operand 2 "cc_register" "")
631         (compare (match_dup 0) (const_int -1)))
632    (set (pc)
633         (if_then_else (match_operator 3 "equality_operator"
634                        [(match_dup 2) (const_int 0)])
635                       (match_operand 4 "" "")
636                       (match_operand 5 "" "")))]
637   "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
638   [(parallel[
639     (set (match_dup 2)
640          (compare:CC
641           (match_dup 1) (const_int 1)))
642     (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
643    (set (pc)
644         (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
645                       (match_dup 4)
646                       (match_dup 5)))]
647   "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
648    operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
649                                   ? GEU : LTU),
650                                  VOIDmode, 
651                                  operands[2], const0_rtx);"
654 ;; The next four insns work because they compare the result with one of
655 ;; the operands, and we know that the use of the condition code is
656 ;; either GEU or LTU, so we can use the carry flag from the addition
657 ;; instead of doing the compare a second time.
658 (define_insn "*addsi3_compare_op1"
659   [(set (reg:CC_C CC_REGNUM)
660         (compare:CC_C
661          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
662                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
663          (match_dup 1)))
664    (set (match_operand:SI 0 "s_register_operand" "=r,r")
665         (plus:SI (match_dup 1) (match_dup 2)))]
666   "TARGET_ARM"
667   "@
668    add%?s\\t%0, %1, %2
669    sub%?s\\t%0, %1, #%n2"
670   [(set_attr "conds" "set")]
673 (define_insn "*addsi3_compare_op2"
674   [(set (reg:CC_C CC_REGNUM)
675         (compare:CC_C
676          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
677                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
678          (match_dup 2)))
679    (set (match_operand:SI 0 "s_register_operand" "=r,r")
680         (plus:SI (match_dup 1) (match_dup 2)))]
681   "TARGET_ARM"
682   "@
683    add%?s\\t%0, %1, %2
684    sub%?s\\t%0, %1, #%n2"
685   [(set_attr "conds" "set")]
688 (define_insn "*compare_addsi2_op0"
689   [(set (reg:CC_C CC_REGNUM)
690         (compare:CC_C
691          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
692                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
693          (match_dup 0)))]
694   "TARGET_ARM"
695   "@
696    cmn%?\\t%0, %1
697    cmp%?\\t%0, #%n1"
698   [(set_attr "conds" "set")]
701 (define_insn "*compare_addsi2_op1"
702   [(set (reg:CC_C CC_REGNUM)
703         (compare:CC_C
704          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
705                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
706          (match_dup 1)))]
707   "TARGET_ARM"
708   "@
709    cmn%?\\t%0, %1
710    cmp%?\\t%0, #%n1"
711   [(set_attr "conds" "set")]
714 (define_insn "*addsi3_carryin"
715   [(set (match_operand:SI 0 "s_register_operand" "=r")
716         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
717                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
718                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
719   "TARGET_ARM"
720   "adc%?\\t%0, %1, %2"
721   [(set_attr "conds" "use")]
724 (define_insn "*addsi3_carryin_shift"
725   [(set (match_operand:SI 0 "s_register_operand" "=r")
726         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
727                  (plus:SI
728                    (match_operator:SI 2 "shift_operator"
729                       [(match_operand:SI 3 "s_register_operand" "r")
730                        (match_operand:SI 4 "reg_or_int_operand" "rM")])
731                     (match_operand:SI 1 "s_register_operand" "r"))))]
732   "TARGET_ARM"
733   "adc%?\\t%0, %1, %3%S2"
734   [(set_attr "conds" "use")
735    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
736                       (const_string "alu_shift")
737                       (const_string "alu_shift_reg")))]
740 (define_insn "*addsi3_carryin_alt1"
741   [(set (match_operand:SI 0 "s_register_operand" "=r")
742         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
743                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
744                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
745   "TARGET_ARM"
746   "adc%?\\t%0, %1, %2"
747   [(set_attr "conds" "use")]
750 (define_insn "*addsi3_carryin_alt2"
751   [(set (match_operand:SI 0 "s_register_operand" "=r")
752         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
753                           (match_operand:SI 1 "s_register_operand" "r"))
754                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
755   "TARGET_ARM"
756   "adc%?\\t%0, %1, %2"
757   [(set_attr "conds" "use")]
760 (define_insn "*addsi3_carryin_alt3"
761   [(set (match_operand:SI 0 "s_register_operand" "=r")
762         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
763                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
764                  (match_operand:SI 1 "s_register_operand" "r")))]
765   "TARGET_ARM"
766   "adc%?\\t%0, %1, %2"
767   [(set_attr "conds" "use")]
770 (define_insn "incscc"
771   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
772         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
773                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
774                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
775   "TARGET_ARM"
776   "@
777   add%d2\\t%0, %1, #1
778   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
779   [(set_attr "conds" "use")
780    (set_attr "length" "4,8")]
783 ; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
784 (define_split
785   [(set (match_operand:SI 0 "s_register_operand" "")
786         (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
787                             (match_operand:SI 2 "s_register_operand" ""))
788                  (const_int -1)))
789    (clobber (match_operand:SI 3 "s_register_operand" ""))]
790   "TARGET_ARM"
791   [(set (match_dup 3) (match_dup 1))
792    (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
793   "
794   operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
797 (define_expand "addsf3"
798   [(set (match_operand:SF          0 "s_register_operand" "")
799         (plus:SF (match_operand:SF 1 "s_register_operand" "")
800                  (match_operand:SF 2 "arm_float_add_operand" "")))]
801   "TARGET_ARM && TARGET_HARD_FLOAT"
802   "
803   if (TARGET_MAVERICK
804       && !cirrus_fp_register (operands[2], SFmode))
805     operands[2] = force_reg (SFmode, operands[2]);
808 (define_expand "adddf3"
809   [(set (match_operand:DF          0 "s_register_operand" "")
810         (plus:DF (match_operand:DF 1 "s_register_operand" "")
811                  (match_operand:DF 2 "arm_float_add_operand" "")))]
812   "TARGET_ARM && TARGET_HARD_FLOAT"
813   "
814   if (TARGET_MAVERICK
815       && !cirrus_fp_register (operands[2], DFmode))
816     operands[2] = force_reg (DFmode, operands[2]);
819 (define_expand "subdi3"
820  [(parallel
821    [(set (match_operand:DI            0 "s_register_operand" "")
822           (minus:DI (match_operand:DI 1 "s_register_operand" "")
823                     (match_operand:DI 2 "s_register_operand" "")))
824     (clobber (reg:CC CC_REGNUM))])]
825   "TARGET_EITHER"
826   "
827   if (TARGET_HARD_FLOAT && TARGET_MAVERICK
828       && TARGET_ARM
829       && cirrus_fp_register (operands[0], DImode)
830       && cirrus_fp_register (operands[1], DImode))
831     {
832       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
833       DONE;
834     }
836   if (TARGET_THUMB)
837     {
838       if (GET_CODE (operands[1]) != REG)
839         operands[1] = force_reg (SImode, operands[1]);
840       if (GET_CODE (operands[2]) != REG)
841         operands[2] = force_reg (SImode, operands[2]);
842      }  
843   "
846 (define_insn "*arm_subdi3"
847   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
848         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
849                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
850    (clobber (reg:CC CC_REGNUM))]
851   "TARGET_ARM"
852   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
853   [(set_attr "conds" "clob")
854    (set_attr "length" "8")]
857 (define_insn "*thumb_subdi3"
858   [(set (match_operand:DI           0 "register_operand" "=l")
859         (minus:DI (match_operand:DI 1 "register_operand"  "0")
860                   (match_operand:DI 2 "register_operand"  "l")))
861    (clobber (reg:CC CC_REGNUM))]
862   "TARGET_THUMB"
863   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
864   [(set_attr "length" "4")]
867 (define_insn "*subdi_di_zesidi"
868   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
869         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
870                   (zero_extend:DI
871                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
872    (clobber (reg:CC CC_REGNUM))]
873   "TARGET_ARM"
874   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
875   [(set_attr "conds" "clob")
876    (set_attr "length" "8")]
879 (define_insn "*subdi_di_sesidi"
880   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
881         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
882                   (sign_extend:DI
883                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
884    (clobber (reg:CC CC_REGNUM))]
885   "TARGET_ARM"
886   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
887   [(set_attr "conds" "clob")
888    (set_attr "length" "8")]
891 (define_insn "*subdi_zesidi_di"
892   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
893         (minus:DI (zero_extend:DI
894                    (match_operand:SI 2 "s_register_operand"  "r,r"))
895                   (match_operand:DI  1 "s_register_operand" "?r,0")))
896    (clobber (reg:CC CC_REGNUM))]
897   "TARGET_ARM"
898   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
899   [(set_attr "conds" "clob")
900    (set_attr "length" "8")]
903 (define_insn "*subdi_sesidi_di"
904   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
905         (minus:DI (sign_extend:DI
906                    (match_operand:SI 2 "s_register_operand"   "r,r"))
907                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
908    (clobber (reg:CC CC_REGNUM))]
909   "TARGET_ARM"
910   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
911   [(set_attr "conds" "clob")
912    (set_attr "length" "8")]
915 (define_insn "*subdi_zesidi_zesidi"
916   [(set (match_operand:DI            0 "s_register_operand" "=r")
917         (minus:DI (zero_extend:DI
918                    (match_operand:SI 1 "s_register_operand"  "r"))
919                   (zero_extend:DI
920                    (match_operand:SI 2 "s_register_operand"  "r"))))
921    (clobber (reg:CC CC_REGNUM))]
922   "TARGET_ARM"
923   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
924   [(set_attr "conds" "clob")
925    (set_attr "length" "8")]
928 (define_expand "subsi3"
929   [(set (match_operand:SI           0 "s_register_operand" "")
930         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
931                   (match_operand:SI 2 "s_register_operand" "")))]
932   "TARGET_EITHER"
933   "
934   if (GET_CODE (operands[1]) == CONST_INT)
935     {
936       if (TARGET_ARM)
937         {
938           arm_split_constant (MINUS, SImode, NULL_RTX,
939                               INTVAL (operands[1]), operands[0],
940                               operands[2], optimize && !no_new_pseudos);
941           DONE;
942         }
943       else /* TARGET_THUMB */
944         operands[1] = force_reg (SImode, operands[1]);
945     }
946   "
949 (define_insn "*thumb_subsi3_insn"
950   [(set (match_operand:SI           0 "register_operand" "=l")
951         (minus:SI (match_operand:SI 1 "register_operand" "l")
952                   (match_operand:SI 2 "register_operand" "l")))]
953   "TARGET_THUMB"
954   "sub\\t%0, %1, %2"
955   [(set_attr "length" "2")]
958 (define_insn_and_split "*arm_subsi3_insn"
959   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
960         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
961                   (match_operand:SI 2 "s_register_operand" "r,r")))]
962   "TARGET_ARM"
963   "@
964    rsb%?\\t%0, %2, %1
965    #"
966   "TARGET_ARM
967    && GET_CODE (operands[1]) == CONST_INT
968    && !const_ok_for_arm (INTVAL (operands[1]))"
969   [(clobber (const_int 0))]
970   "
971   arm_split_constant (MINUS, SImode, curr_insn,
972                       INTVAL (operands[1]), operands[0], operands[2], 0);
973   DONE;
974   "
975   [(set_attr "length" "4,16")
976    (set_attr "predicable" "yes")]
979 (define_peephole2
980   [(match_scratch:SI 3 "r")
981    (set (match_operand:SI 0 "arm_general_register_operand" "")
982         (minus:SI (match_operand:SI 1 "const_int_operand" "")
983                   (match_operand:SI 2 "arm_general_register_operand" "")))]
984   "TARGET_ARM
985    && !const_ok_for_arm (INTVAL (operands[1]))
986    && const_ok_for_arm (~INTVAL (operands[1]))"
987   [(set (match_dup 3) (match_dup 1))
988    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
989   ""
992 (define_insn "*subsi3_compare0"
993   [(set (reg:CC_NOOV CC_REGNUM)
994         (compare:CC_NOOV
995          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
996                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
997          (const_int 0)))
998    (set (match_operand:SI 0 "s_register_operand" "=r,r")
999         (minus:SI (match_dup 1) (match_dup 2)))]
1000   "TARGET_ARM"
1001   "@
1002    sub%?s\\t%0, %1, %2
1003    rsb%?s\\t%0, %2, %1"
1004   [(set_attr "conds" "set")]
1007 (define_insn "decscc"
1008   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1009         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1010                   (match_operator:SI 2 "arm_comparison_operator"
1011                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1012   "TARGET_ARM"
1013   "@
1014    sub%d2\\t%0, %1, #1
1015    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1016   [(set_attr "conds" "use")
1017    (set_attr "length" "*,8")]
1020 (define_expand "subsf3"
1021   [(set (match_operand:SF           0 "s_register_operand" "")
1022         (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1023                   (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1024   "TARGET_ARM && TARGET_HARD_FLOAT"
1025   "
1026   if (TARGET_MAVERICK)
1027     {
1028       if (!cirrus_fp_register (operands[1], SFmode))
1029         operands[1] = force_reg (SFmode, operands[1]);
1030       if (!cirrus_fp_register (operands[2], SFmode))
1031         operands[2] = force_reg (SFmode, operands[2]);
1032     }
1035 (define_expand "subdf3"
1036   [(set (match_operand:DF           0 "s_register_operand" "")
1037         (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1038                   (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1039   "TARGET_ARM && TARGET_HARD_FLOAT"
1040   "
1041   if (TARGET_MAVERICK)
1042     {
1043        if (!cirrus_fp_register (operands[1], DFmode))
1044          operands[1] = force_reg (DFmode, operands[1]);
1045        if (!cirrus_fp_register (operands[2], DFmode))
1046          operands[2] = force_reg (DFmode, operands[2]);
1047     }
1051 ;; Multiplication insns
1053 (define_expand "mulsi3"
1054   [(set (match_operand:SI          0 "s_register_operand" "")
1055         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1056                  (match_operand:SI 1 "s_register_operand" "")))]
1057   "TARGET_EITHER"
1058   ""
1061 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1062 (define_insn "*arm_mulsi3"
1063   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1064         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1065                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1066   "TARGET_ARM"
1067   "mul%?\\t%0, %2, %1"
1068   [(set_attr "insn" "mul")
1069    (set_attr "predicable" "yes")]
1072 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1073 ; 1 and 2; are the same, because reload will make operand 0 match 
1074 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1075 ; this by adding another alternative to match this case, and then `reload' 
1076 ; it ourselves.  This alternative must come first.
1077 (define_insn "*thumb_mulsi3"
1078   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1079         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1080                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1081   "TARGET_THUMB"
1082   "*
1083   if (which_alternative < 2)
1084     return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1085   else
1086     return \"mul\\t%0, %0, %2\";
1087   "
1088   [(set_attr "length" "4,4,2")
1089    (set_attr "insn" "mul")]
1092 (define_insn "*mulsi3_compare0"
1093   [(set (reg:CC_NOOV CC_REGNUM)
1094         (compare:CC_NOOV (mult:SI
1095                           (match_operand:SI 2 "s_register_operand" "r,r")
1096                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1097                          (const_int 0)))
1098    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1099         (mult:SI (match_dup 2) (match_dup 1)))]
1100   "TARGET_ARM && !arm_arch_xscale"
1101   "mul%?s\\t%0, %2, %1"
1102   [(set_attr "conds" "set")
1103    (set_attr "insn" "muls")]
1106 (define_insn "*mulsi_compare0_scratch"
1107   [(set (reg:CC_NOOV CC_REGNUM)
1108         (compare:CC_NOOV (mult:SI
1109                           (match_operand:SI 2 "s_register_operand" "r,r")
1110                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1111                          (const_int 0)))
1112    (clobber (match_scratch:SI 0 "=&r,&r"))]
1113   "TARGET_ARM && !arm_arch_xscale"
1114   "mul%?s\\t%0, %2, %1"
1115   [(set_attr "conds" "set")
1116    (set_attr "insn" "muls")]
1119 ;; Unnamed templates to match MLA instruction.
1121 (define_insn "*mulsi3addsi"
1122   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1123         (plus:SI
1124           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1125                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1126           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1127   "TARGET_ARM"
1128   "mla%?\\t%0, %2, %1, %3"
1129   [(set_attr "insn" "mla")
1130    (set_attr "predicable" "yes")]
1133 (define_insn "*mulsi3addsi_compare0"
1134   [(set (reg:CC_NOOV CC_REGNUM)
1135         (compare:CC_NOOV
1136          (plus:SI (mult:SI
1137                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1138                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1139                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1140          (const_int 0)))
1141    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1142         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1143                  (match_dup 3)))]
1144   "TARGET_ARM && !arm_arch_xscale"
1145   "mla%?s\\t%0, %2, %1, %3"
1146   [(set_attr "conds" "set")
1147    (set_attr "insn" "mlas")]
1150 (define_insn "*mulsi3addsi_compare0_scratch"
1151   [(set (reg:CC_NOOV CC_REGNUM)
1152         (compare:CC_NOOV
1153          (plus:SI (mult:SI
1154                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1155                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1156                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1157          (const_int 0)))
1158    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1159   "TARGET_ARM && !arm_arch_xscale"
1160   "mla%?s\\t%0, %2, %1, %3"
1161   [(set_attr "conds" "set")
1162    (set_attr "insn" "mlas")]
1165 ;; Unnamed template to match long long multiply-accumulate (smlal)
1167 (define_insn "*mulsidi3adddi"
1168   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1169         (plus:DI
1170          (mult:DI
1171           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1172           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1173          (match_operand:DI 1 "s_register_operand" "0")))]
1174   "TARGET_ARM && arm_arch3m"
1175   "smlal%?\\t%Q0, %R0, %3, %2"
1176   [(set_attr "insn" "smlal")
1177    (set_attr "predicable" "yes")]
1180 (define_insn "mulsidi3"
1181   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1182         (mult:DI
1183          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1184          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1185   "TARGET_ARM && arm_arch3m"
1186   "smull%?\\t%Q0, %R0, %1, %2"
1187   [(set_attr "insn" "smull")
1188    (set_attr "predicable" "yes")]
1191 (define_insn "umulsidi3"
1192   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1193         (mult:DI
1194          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1195          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1196   "TARGET_ARM && arm_arch3m"
1197   "umull%?\\t%Q0, %R0, %1, %2"
1198   [(set_attr "insn" "umull")
1199    (set_attr "predicable" "yes")]
1202 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1204 (define_insn "*umulsidi3adddi"
1205   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1206         (plus:DI
1207          (mult:DI
1208           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1209           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1210          (match_operand:DI 1 "s_register_operand" "0")))]
1211   "TARGET_ARM && arm_arch3m"
1212   "umlal%?\\t%Q0, %R0, %3, %2"
1213   [(set_attr "insn" "umlal")
1214    (set_attr "predicable" "yes")]
1217 (define_insn "smulsi3_highpart"
1218   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1219         (truncate:SI
1220          (lshiftrt:DI
1221           (mult:DI
1222            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1223            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1224           (const_int 32))))
1225    (clobber (match_scratch:SI 3 "=&r,&r"))]
1226   "TARGET_ARM && arm_arch3m"
1227   "smull%?\\t%3, %0, %2, %1"
1228   [(set_attr "insn" "smull")
1229    (set_attr "predicable" "yes")]
1232 (define_insn "umulsi3_highpart"
1233   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1234         (truncate:SI
1235          (lshiftrt:DI
1236           (mult:DI
1237            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1238            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1239           (const_int 32))))
1240    (clobber (match_scratch:SI 3 "=&r,&r"))]
1241   "TARGET_ARM && arm_arch3m"
1242   "umull%?\\t%3, %0, %2, %1"
1243   [(set_attr "insn" "umull")
1244    (set_attr "predicable" "yes")]
1247 (define_insn "mulhisi3"
1248   [(set (match_operand:SI 0 "s_register_operand" "=r")
1249         (mult:SI (sign_extend:SI
1250                   (match_operand:HI 1 "s_register_operand" "%r"))
1251                  (sign_extend:SI
1252                   (match_operand:HI 2 "s_register_operand" "r"))))]
1253   "TARGET_ARM && arm_arch5e"
1254   "smulbb%?\\t%0, %1, %2"
1255   [(set_attr "insn" "smulxy")
1256    (set_attr "predicable" "yes")]
1259 (define_insn "*mulhisi3tb"
1260   [(set (match_operand:SI 0 "s_register_operand" "=r")
1261         (mult:SI (ashiftrt:SI
1262                   (match_operand:SI 1 "s_register_operand" "r")
1263                   (const_int 16))
1264                  (sign_extend:SI
1265                   (match_operand:HI 2 "s_register_operand" "r"))))]
1266   "TARGET_ARM && arm_arch5e"
1267   "smultb%?\\t%0, %1, %2"
1268   [(set_attr "insn" "smulxy")
1269    (set_attr "predicable" "yes")]
1272 (define_insn "*mulhisi3bt"
1273   [(set (match_operand:SI 0 "s_register_operand" "=r")
1274         (mult:SI (sign_extend:SI
1275                   (match_operand:HI 1 "s_register_operand" "r"))
1276                  (ashiftrt:SI
1277                   (match_operand:SI 2 "s_register_operand" "r")
1278                   (const_int 16))))]
1279   "TARGET_ARM && arm_arch5e"
1280   "smulbt%?\\t%0, %1, %2"
1281   [(set_attr "insn" "smulxy")
1282    (set_attr "predicable" "yes")]
1285 (define_insn "*mulhisi3tt"
1286   [(set (match_operand:SI 0 "s_register_operand" "=r")
1287         (mult:SI (ashiftrt:SI
1288                   (match_operand:SI 1 "s_register_operand" "r")
1289                   (const_int 16))
1290                  (ashiftrt:SI
1291                   (match_operand:SI 2 "s_register_operand" "r")
1292                   (const_int 16))))]
1293   "TARGET_ARM && arm_arch5e"
1294   "smultt%?\\t%0, %1, %2"
1295   [(set_attr "insn" "smulxy")
1296    (set_attr "predicable" "yes")]
1299 (define_insn "*mulhisi3addsi"
1300   [(set (match_operand:SI 0 "s_register_operand" "=r")
1301         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1302                  (mult:SI (sign_extend:SI
1303                            (match_operand:HI 2 "s_register_operand" "%r"))
1304                           (sign_extend:SI
1305                            (match_operand:HI 3 "s_register_operand" "r")))))]
1306   "TARGET_ARM && arm_arch5e"
1307   "smlabb%?\\t%0, %2, %3, %1"
1308   [(set_attr "insn" "smlaxy")
1309    (set_attr "predicable" "yes")]
1312 (define_insn "*mulhidi3adddi"
1313   [(set (match_operand:DI 0 "s_register_operand" "=r")
1314         (plus:DI
1315           (match_operand:DI 1 "s_register_operand" "0")
1316           (mult:DI (sign_extend:DI
1317                     (match_operand:HI 2 "s_register_operand" "%r"))
1318                    (sign_extend:DI
1319                     (match_operand:HI 3 "s_register_operand" "r")))))]
1320   "TARGET_ARM && arm_arch5e"
1321   "smlalbb%?\\t%Q0, %R0, %2, %3"
1322   [(set_attr "insn" "smlalxy")
1323    (set_attr "predicable" "yes")])
1325 (define_expand "mulsf3"
1326   [(set (match_operand:SF          0 "s_register_operand" "")
1327         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1328                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1329   "TARGET_ARM && TARGET_HARD_FLOAT"
1330   "
1331   if (TARGET_MAVERICK
1332       && !cirrus_fp_register (operands[2], SFmode))
1333     operands[2] = force_reg (SFmode, operands[2]);
1336 (define_expand "muldf3"
1337   [(set (match_operand:DF          0 "s_register_operand" "")
1338         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1339                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1340   "TARGET_ARM && TARGET_HARD_FLOAT"
1341   "
1342   if (TARGET_MAVERICK
1343       && !cirrus_fp_register (operands[2], DFmode))
1344     operands[2] = force_reg (DFmode, operands[2]);
1347 ;; Division insns
1349 (define_expand "divsf3"
1350   [(set (match_operand:SF 0 "s_register_operand" "")
1351         (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1352                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1353   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1354   "")
1356 (define_expand "divdf3"
1357   [(set (match_operand:DF 0 "s_register_operand" "")
1358         (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1359                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1360   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1361   "")
1363 ;; Modulo insns
1365 (define_expand "modsf3"
1366   [(set (match_operand:SF 0 "s_register_operand" "")
1367         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1368                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1369   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1370   "")
1372 (define_expand "moddf3"
1373   [(set (match_operand:DF 0 "s_register_operand" "")
1374         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1375                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1376   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1377   "")
1379 ;; Boolean and,ior,xor insns
1381 ;; Split up double word logical operations
1383 ;; Split up simple DImode logical operations.  Simply perform the logical
1384 ;; operation on the upper and lower halves of the registers.
1385 (define_split
1386   [(set (match_operand:DI 0 "s_register_operand" "")
1387         (match_operator:DI 6 "logical_binary_operator"
1388           [(match_operand:DI 1 "s_register_operand" "")
1389            (match_operand:DI 2 "s_register_operand" "")]))]
1390   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1391   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1392    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1393   "
1394   {
1395     operands[3] = gen_highpart (SImode, operands[0]);
1396     operands[0] = gen_lowpart (SImode, operands[0]);
1397     operands[4] = gen_highpart (SImode, operands[1]);
1398     operands[1] = gen_lowpart (SImode, operands[1]);
1399     operands[5] = gen_highpart (SImode, operands[2]);
1400     operands[2] = gen_lowpart (SImode, operands[2]);
1401   }"
1404 (define_split
1405   [(set (match_operand:DI 0 "s_register_operand" "")
1406         (match_operator:DI 6 "logical_binary_operator"
1407           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1408            (match_operand:DI 1 "s_register_operand" "")]))]
1409   "TARGET_ARM && reload_completed"
1410   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1411    (set (match_dup 3) (match_op_dup:SI 6
1412                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1413                          (match_dup 4)]))]
1414   "
1415   {
1416     operands[3] = gen_highpart (SImode, operands[0]);
1417     operands[0] = gen_lowpart (SImode, operands[0]);
1418     operands[4] = gen_highpart (SImode, operands[1]);
1419     operands[1] = gen_lowpart (SImode, operands[1]);
1420     operands[5] = gen_highpart (SImode, operands[2]);
1421     operands[2] = gen_lowpart (SImode, operands[2]);
1422   }"
1425 ;; The zero extend of operand 2 means we can just copy the high part of
1426 ;; operand1 into operand0.
1427 (define_split
1428   [(set (match_operand:DI 0 "s_register_operand" "")
1429         (ior:DI
1430           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1431           (match_operand:DI 1 "s_register_operand" "")))]
1432   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1433   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1434    (set (match_dup 3) (match_dup 4))]
1435   "
1436   {
1437     operands[4] = gen_highpart (SImode, operands[1]);
1438     operands[3] = gen_highpart (SImode, operands[0]);
1439     operands[0] = gen_lowpart (SImode, operands[0]);
1440     operands[1] = gen_lowpart (SImode, operands[1]);
1441   }"
1444 ;; The zero extend of operand 2 means we can just copy the high part of
1445 ;; operand1 into operand0.
1446 (define_split
1447   [(set (match_operand:DI 0 "s_register_operand" "")
1448         (xor:DI
1449           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1450           (match_operand:DI 1 "s_register_operand" "")))]
1451   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1452   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1453    (set (match_dup 3) (match_dup 4))]
1454   "
1455   {
1456     operands[4] = gen_highpart (SImode, operands[1]);
1457     operands[3] = gen_highpart (SImode, operands[0]);
1458     operands[0] = gen_lowpart (SImode, operands[0]);
1459     operands[1] = gen_lowpart (SImode, operands[1]);
1460   }"
1463 (define_insn "anddi3"
1464   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1465         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1466                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1467   "TARGET_ARM && ! TARGET_IWMMXT"
1468   "#"
1469   [(set_attr "length" "8")]
1472 (define_insn_and_split "*anddi_zesidi_di"
1473   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1474         (and:DI (zero_extend:DI
1475                  (match_operand:SI 2 "s_register_operand" "r,r"))
1476                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1477   "TARGET_ARM"
1478   "#"
1479   "TARGET_ARM && reload_completed"
1480   ; The zero extend of operand 2 clears the high word of the output
1481   ; operand.
1482   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1483    (set (match_dup 3) (const_int 0))]
1484   "
1485   {
1486     operands[3] = gen_highpart (SImode, operands[0]);
1487     operands[0] = gen_lowpart (SImode, operands[0]);
1488     operands[1] = gen_lowpart (SImode, operands[1]);
1489   }"
1490   [(set_attr "length" "8")]
1493 (define_insn "*anddi_sesdi_di"
1494   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1495         (and:DI (sign_extend:DI
1496                  (match_operand:SI 2 "s_register_operand" "r,r"))
1497                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1498   "TARGET_ARM"
1499   "#"
1500   [(set_attr "length" "8")]
1503 (define_expand "andsi3"
1504   [(set (match_operand:SI         0 "s_register_operand" "")
1505         (and:SI (match_operand:SI 1 "s_register_operand" "")
1506                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1507   "TARGET_EITHER"
1508   "
1509   if (TARGET_ARM)
1510     {
1511       if (GET_CODE (operands[2]) == CONST_INT)
1512         {
1513           arm_split_constant (AND, SImode, NULL_RTX,
1514                               INTVAL (operands[2]), operands[0],
1515                               operands[1], optimize && !no_new_pseudos);
1517           DONE;
1518         }
1519     }
1520   else /* TARGET_THUMB */
1521     {
1522       if (GET_CODE (operands[2]) != CONST_INT)
1523         operands[2] = force_reg (SImode, operands[2]);
1524       else
1525         {
1526           int i;
1527           
1528           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1529             {
1530               operands[2] = force_reg (SImode,
1531                                        GEN_INT (~INTVAL (operands[2])));
1532               
1533               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1534               
1535               DONE;
1536             }
1538           for (i = 9; i <= 31; i++)
1539             {
1540               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1541                 {
1542                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1543                                         const0_rtx));
1544                   DONE;
1545                 }
1546               else if ((((HOST_WIDE_INT) 1) << i) - 1
1547                        == ~INTVAL (operands[2]))
1548                 {
1549                   rtx shift = GEN_INT (i);
1550                   rtx reg = gen_reg_rtx (SImode);
1551                 
1552                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1553                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1554                   
1555                   DONE;
1556                 }
1557             }
1559           operands[2] = force_reg (SImode, operands[2]);
1560         }
1561     }
1562   "
1565 (define_insn_and_split "*arm_andsi3_insn"
1566   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1567         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1568                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1569   "TARGET_ARM"
1570   "@
1571    and%?\\t%0, %1, %2
1572    bic%?\\t%0, %1, #%B2
1573    #"
1574   "TARGET_ARM
1575    && GET_CODE (operands[2]) == CONST_INT
1576    && !(const_ok_for_arm (INTVAL (operands[2]))
1577         || const_ok_for_arm (~INTVAL (operands[2])))"
1578   [(clobber (const_int 0))]
1579   "
1580   arm_split_constant  (AND, SImode, curr_insn, 
1581                        INTVAL (operands[2]), operands[0], operands[1], 0);
1582   DONE;
1583   "
1584   [(set_attr "length" "4,4,16")
1585    (set_attr "predicable" "yes")]
1588 (define_insn "*thumb_andsi3_insn"
1589   [(set (match_operand:SI         0 "register_operand" "=l")
1590         (and:SI (match_operand:SI 1 "register_operand" "%0")
1591                 (match_operand:SI 2 "register_operand" "l")))]
1592   "TARGET_THUMB"
1593   "and\\t%0, %0, %2"
1594   [(set_attr "length" "2")]
1597 (define_insn "*andsi3_compare0"
1598   [(set (reg:CC_NOOV CC_REGNUM)
1599         (compare:CC_NOOV
1600          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1601                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1602          (const_int 0)))
1603    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1604         (and:SI (match_dup 1) (match_dup 2)))]
1605   "TARGET_ARM"
1606   "@
1607    and%?s\\t%0, %1, %2
1608    bic%?s\\t%0, %1, #%B2"
1609   [(set_attr "conds" "set")]
1612 (define_insn "*andsi3_compare0_scratch"
1613   [(set (reg:CC_NOOV CC_REGNUM)
1614         (compare:CC_NOOV
1615          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1616                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1617          (const_int 0)))
1618    (clobber (match_scratch:SI 2 "=X,r"))]
1619   "TARGET_ARM"
1620   "@
1621    tst%?\\t%0, %1
1622    bic%?s\\t%2, %0, #%B1"
1623   [(set_attr "conds" "set")]
1626 (define_insn "*zeroextractsi_compare0_scratch"
1627   [(set (reg:CC_NOOV CC_REGNUM)
1628         (compare:CC_NOOV (zero_extract:SI
1629                           (match_operand:SI 0 "s_register_operand" "r")
1630                           (match_operand 1 "const_int_operand" "n")
1631                           (match_operand 2 "const_int_operand" "n"))
1632                          (const_int 0)))]
1633   "TARGET_ARM
1634   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1635       && INTVAL (operands[1]) > 0 
1636       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1637       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1638   "*
1639   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1640                          << INTVAL (operands[2]));
1641   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1642   return \"\";
1643   "
1644   [(set_attr "conds" "set")]
1647 (define_insn_and_split "*ne_zeroextractsi"
1648   [(set (match_operand:SI 0 "s_register_operand" "=r")
1649         (ne:SI (zero_extract:SI
1650                 (match_operand:SI 1 "s_register_operand" "r")
1651                 (match_operand:SI 2 "const_int_operand" "n")
1652                 (match_operand:SI 3 "const_int_operand" "n"))
1653                (const_int 0)))
1654    (clobber (reg:CC CC_REGNUM))]
1655   "TARGET_ARM
1656    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1657        && INTVAL (operands[2]) > 0 
1658        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1659        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1660   "#"
1661   "TARGET_ARM
1662    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1663        && INTVAL (operands[2]) > 0 
1664        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1665        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1666   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1667                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1668                                     (const_int 0)))
1669               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1670    (set (match_dup 0)
1671         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1672                          (match_dup 0) (const_int 1)))]
1673   "
1674   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1675                          << INTVAL (operands[3])); 
1676   "
1677   [(set_attr "conds" "clob")
1678    (set_attr "length" "8")]
1681 (define_insn_and_split "*ne_zeroextractsi_shifted"
1682   [(set (match_operand:SI 0 "s_register_operand" "=r")
1683         (ne:SI (zero_extract:SI
1684                 (match_operand:SI 1 "s_register_operand" "r")
1685                 (match_operand:SI 2 "const_int_operand" "n")
1686                 (const_int 0))
1687                (const_int 0)))
1688    (clobber (reg:CC CC_REGNUM))]
1689   "TARGET_ARM"
1690   "#"
1691   "TARGET_ARM"
1692   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1693                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1694                                     (const_int 0)))
1695               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1696    (set (match_dup 0)
1697         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1698                          (match_dup 0) (const_int 1)))]
1699   "
1700   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1701   "
1702   [(set_attr "conds" "clob")
1703    (set_attr "length" "8")]
1706 (define_insn_and_split "*ite_ne_zeroextractsi"
1707   [(set (match_operand:SI 0 "s_register_operand" "=r")
1708         (if_then_else:SI (ne (zero_extract:SI
1709                               (match_operand:SI 1 "s_register_operand" "r")
1710                               (match_operand:SI 2 "const_int_operand" "n")
1711                               (match_operand:SI 3 "const_int_operand" "n"))
1712                              (const_int 0))
1713                          (match_operand:SI 4 "arm_not_operand" "rIK")
1714                          (const_int 0)))
1715    (clobber (reg:CC CC_REGNUM))]
1716   "TARGET_ARM
1717    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1718        && INTVAL (operands[2]) > 0 
1719        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1720        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1721    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1722   "#"
1723   "TARGET_ARM
1724    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1725        && INTVAL (operands[2]) > 0 
1726        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1727        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1728    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1729   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1730                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1731                                     (const_int 0)))
1732               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1733    (set (match_dup 0)
1734         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1735                          (match_dup 0) (match_dup 4)))]
1736   "
1737   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1738                          << INTVAL (operands[3])); 
1739   "
1740   [(set_attr "conds" "clob")
1741    (set_attr "length" "8")]
1744 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1745   [(set (match_operand:SI 0 "s_register_operand" "=r")
1746         (if_then_else:SI (ne (zero_extract:SI
1747                               (match_operand:SI 1 "s_register_operand" "r")
1748                               (match_operand:SI 2 "const_int_operand" "n")
1749                               (const_int 0))
1750                              (const_int 0))
1751                          (match_operand:SI 3 "arm_not_operand" "rIK")
1752                          (const_int 0)))
1753    (clobber (reg:CC CC_REGNUM))]
1754   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1755   "#"
1756   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1757   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1758                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1759                                     (const_int 0)))
1760               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1761    (set (match_dup 0)
1762         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1763                          (match_dup 0) (match_dup 3)))]
1764   "
1765   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1766   "
1767   [(set_attr "conds" "clob")
1768    (set_attr "length" "8")]
1771 (define_split
1772   [(set (match_operand:SI 0 "s_register_operand" "")
1773         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1774                          (match_operand:SI 2 "const_int_operand" "")
1775                          (match_operand:SI 3 "const_int_operand" "")))
1776    (clobber (match_operand:SI 4 "s_register_operand" ""))]
1777   "TARGET_THUMB"
1778   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1779    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1780   "{
1781      HOST_WIDE_INT temp = INTVAL (operands[2]);
1783      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1784      operands[3] = GEN_INT (32 - temp);
1785    }"
1788 (define_split
1789   [(set (match_operand:SI 0 "s_register_operand" "")
1790         (match_operator:SI 1 "shiftable_operator"
1791          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1792                            (match_operand:SI 3 "const_int_operand" "")
1793                            (match_operand:SI 4 "const_int_operand" ""))
1794           (match_operand:SI 5 "s_register_operand" "")]))
1795    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1796   "TARGET_ARM"
1797   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1798    (set (match_dup 0)
1799         (match_op_dup 1
1800          [(lshiftrt:SI (match_dup 6) (match_dup 4))
1801           (match_dup 5)]))]
1802   "{
1803      HOST_WIDE_INT temp = INTVAL (operands[3]);
1805      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1806      operands[4] = GEN_INT (32 - temp);
1807    }"
1809   
1810 (define_split
1811   [(set (match_operand:SI 0 "s_register_operand" "")
1812         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1813                          (match_operand:SI 2 "const_int_operand" "")
1814                          (match_operand:SI 3 "const_int_operand" "")))]
1815   "TARGET_THUMB"
1816   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1817    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1818   "{
1819      HOST_WIDE_INT temp = INTVAL (operands[2]);
1821      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1822      operands[3] = GEN_INT (32 - temp);
1823    }"
1826 (define_split
1827   [(set (match_operand:SI 0 "s_register_operand" "")
1828         (match_operator:SI 1 "shiftable_operator"
1829          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1830                            (match_operand:SI 3 "const_int_operand" "")
1831                            (match_operand:SI 4 "const_int_operand" ""))
1832           (match_operand:SI 5 "s_register_operand" "")]))
1833    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1834   "TARGET_ARM"
1835   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1836    (set (match_dup 0)
1837         (match_op_dup 1
1838          [(ashiftrt:SI (match_dup 6) (match_dup 4))
1839           (match_dup 5)]))]
1840   "{
1841      HOST_WIDE_INT temp = INTVAL (operands[3]);
1843      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1844      operands[4] = GEN_INT (32 - temp);
1845    }"
1847   
1848 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1849 ;;; represented by the bitfield, then this will produce incorrect results.
1850 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1851 ;;; which have a real bit-field insert instruction, the truncation happens
1852 ;;; in the bit-field insert instruction itself.  Since arm does not have a
1853 ;;; bit-field insert instruction, we would have to emit code here to truncate
1854 ;;; the value before we insert.  This loses some of the advantage of having
1855 ;;; this insv pattern, so this pattern needs to be reevalutated.
1857 (define_expand "insv"
1858   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1859                          (match_operand:SI 1 "general_operand" "")
1860                          (match_operand:SI 2 "general_operand" ""))
1861         (match_operand:SI 3 "reg_or_int_operand" ""))]
1862   "TARGET_ARM"
1863   "
1864   {
1865     int start_bit = INTVAL (operands[2]);
1866     int width = INTVAL (operands[1]);
1867     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1868     rtx target, subtarget;
1870     target = operands[0];
1871     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1872        subreg as the final target.  */
1873     if (GET_CODE (target) == SUBREG)
1874       {
1875         subtarget = gen_reg_rtx (SImode);
1876         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1877             < GET_MODE_SIZE (SImode))
1878           target = SUBREG_REG (target);
1879       }
1880     else
1881       subtarget = target;    
1883     if (GET_CODE (operands[3]) == CONST_INT)
1884       {
1885         /* Since we are inserting a known constant, we may be able to
1886            reduce the number of bits that we have to clear so that
1887            the mask becomes simple.  */
1888         /* ??? This code does not check to see if the new mask is actually
1889            simpler.  It may not be.  */
1890         rtx op1 = gen_reg_rtx (SImode);
1891         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1892            start of this pattern.  */
1893         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1894         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1896         emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1897         emit_insn (gen_iorsi3 (subtarget, op1,
1898                                GEN_INT (op3_value << start_bit)));
1899       }
1900     else if (start_bit == 0
1901              && !(const_ok_for_arm (mask)
1902                   || const_ok_for_arm (~mask)))
1903       {
1904         /* A Trick, since we are setting the bottom bits in the word,
1905            we can shift operand[3] up, operand[0] down, OR them together
1906            and rotate the result back again.  This takes 3 insns, and
1907            the third might be mergeable into another op.  */
1908         /* The shift up copes with the possibility that operand[3] is
1909            wider than the bitfield.  */
1910         rtx op0 = gen_reg_rtx (SImode);
1911         rtx op1 = gen_reg_rtx (SImode);
1913         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1914         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1915         emit_insn (gen_iorsi3  (op1, op1, op0));
1916         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1917       }
1918     else if ((width + start_bit == 32)
1919              && !(const_ok_for_arm (mask)
1920                   || const_ok_for_arm (~mask)))
1921       {
1922         /* Similar trick, but slightly less efficient.  */
1924         rtx op0 = gen_reg_rtx (SImode);
1925         rtx op1 = gen_reg_rtx (SImode);
1927         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1928         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1929         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1930         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1931       }
1932     else
1933       {
1934         rtx op0 = GEN_INT (mask);
1935         rtx op1 = gen_reg_rtx (SImode);
1936         rtx op2 = gen_reg_rtx (SImode);
1938         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1939           {
1940             rtx tmp = gen_reg_rtx (SImode);
1942             emit_insn (gen_movsi (tmp, op0));
1943             op0 = tmp;
1944           }
1946         /* Mask out any bits in operand[3] that are not needed.  */
1947            emit_insn (gen_andsi3 (op1, operands[3], op0));
1949         if (GET_CODE (op0) == CONST_INT
1950             && (const_ok_for_arm (mask << start_bit)
1951                 || const_ok_for_arm (~(mask << start_bit))))
1952           {
1953             op0 = GEN_INT (~(mask << start_bit));
1954             emit_insn (gen_andsi3 (op2, operands[0], op0));
1955           }
1956         else
1957           {
1958             if (GET_CODE (op0) == CONST_INT)
1959               {
1960                 rtx tmp = gen_reg_rtx (SImode);
1962                 emit_insn (gen_movsi (tmp, op0));
1963                 op0 = tmp;
1964               }
1966             if (start_bit != 0)
1967               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1968             
1969             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1970           }
1972         if (start_bit != 0)
1973           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1975         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1976       }
1978     if (subtarget != target)
1979       {
1980         /* If TARGET is still a SUBREG, then it must be wider than a word,
1981            so we must be careful only to set the subword we were asked to.  */
1982         if (GET_CODE (target) == SUBREG)
1983           emit_move_insn (target, subtarget);
1984         else
1985           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1986       }
1988     DONE;
1989   }"
1992 ; constants for op 2 will never be given to these patterns.
1993 (define_insn_and_split "*anddi_notdi_di"
1994   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1995         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1996                 (match_operand:DI 2 "s_register_operand" "0,r")))]
1997   "TARGET_ARM"
1998   "#"
1999   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2000   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2001    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2002   "
2003   {
2004     operands[3] = gen_highpart (SImode, operands[0]);
2005     operands[0] = gen_lowpart (SImode, operands[0]);
2006     operands[4] = gen_highpart (SImode, operands[1]);
2007     operands[1] = gen_lowpart (SImode, operands[1]);
2008     operands[5] = gen_highpart (SImode, operands[2]);
2009     operands[2] = gen_lowpart (SImode, operands[2]);
2010   }"
2011   [(set_attr "length" "8")
2012    (set_attr "predicable" "yes")]
2014   
2015 (define_insn_and_split "*anddi_notzesidi_di"
2016   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2017         (and:DI (not:DI (zero_extend:DI
2018                          (match_operand:SI 2 "s_register_operand" "r,r")))
2019                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2020   "TARGET_ARM"
2021   "@
2022    bic%?\\t%Q0, %Q1, %2
2023    #"
2024   ; (not (zero_extend ...)) allows us to just copy the high word from
2025   ; operand1 to operand0.
2026   "TARGET_ARM
2027    && reload_completed
2028    && operands[0] != operands[1]"
2029   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2030    (set (match_dup 3) (match_dup 4))]
2031   "
2032   {
2033     operands[3] = gen_highpart (SImode, operands[0]);
2034     operands[0] = gen_lowpart (SImode, operands[0]);
2035     operands[4] = gen_highpart (SImode, operands[1]);
2036     operands[1] = gen_lowpart (SImode, operands[1]);
2037   }"
2038   [(set_attr "length" "4,8")
2039    (set_attr "predicable" "yes")]
2041   
2042 (define_insn_and_split "*anddi_notsesidi_di"
2043   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2044         (and:DI (not:DI (sign_extend:DI
2045                          (match_operand:SI 2 "s_register_operand" "r,r")))
2046                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2047   "TARGET_ARM"
2048   "#"
2049   "TARGET_ARM && reload_completed"
2050   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2051    (set (match_dup 3) (and:SI (not:SI
2052                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2053                                (match_dup 4)))]
2054   "
2055   {
2056     operands[3] = gen_highpart (SImode, operands[0]);
2057     operands[0] = gen_lowpart (SImode, operands[0]);
2058     operands[4] = gen_highpart (SImode, operands[1]);
2059     operands[1] = gen_lowpart (SImode, operands[1]);
2060   }"
2061   [(set_attr "length" "8")
2062    (set_attr "predicable" "yes")]
2064   
2065 (define_insn "andsi_notsi_si"
2066   [(set (match_operand:SI 0 "s_register_operand" "=r")
2067         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2068                 (match_operand:SI 1 "s_register_operand" "r")))]
2069   "TARGET_ARM"
2070   "bic%?\\t%0, %1, %2"
2071   [(set_attr "predicable" "yes")]
2074 (define_insn "bicsi3"
2075   [(set (match_operand:SI                 0 "register_operand" "=l")
2076         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2077                 (match_operand:SI         2 "register_operand" "0")))]
2078   "TARGET_THUMB"
2079   "bic\\t%0, %0, %1"
2080   [(set_attr "length" "2")]
2083 (define_insn "andsi_not_shiftsi_si"
2084   [(set (match_operand:SI 0 "s_register_operand" "=r")
2085         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2086                          [(match_operand:SI 2 "s_register_operand" "r")
2087                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2088                 (match_operand:SI 1 "s_register_operand" "r")))]
2089   "TARGET_ARM"
2090   "bic%?\\t%0, %1, %2%S4"
2091   [(set_attr "predicable" "yes")
2092    (set_attr "shift" "2")
2093    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2094                       (const_string "alu_shift")
2095                       (const_string "alu_shift_reg")))]
2098 (define_insn "*andsi_notsi_si_compare0"
2099   [(set (reg:CC_NOOV CC_REGNUM)
2100         (compare:CC_NOOV
2101          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2102                  (match_operand:SI 1 "s_register_operand" "r"))
2103          (const_int 0)))
2104    (set (match_operand:SI 0 "s_register_operand" "=r")
2105         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2106   "TARGET_ARM"
2107   "bic%?s\\t%0, %1, %2"
2108   [(set_attr "conds" "set")]
2111 (define_insn "*andsi_notsi_si_compare0_scratch"
2112   [(set (reg:CC_NOOV CC_REGNUM)
2113         (compare:CC_NOOV
2114          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2115                  (match_operand:SI 1 "s_register_operand" "r"))
2116          (const_int 0)))
2117    (clobber (match_scratch:SI 0 "=r"))]
2118   "TARGET_ARM"
2119   "bic%?s\\t%0, %1, %2"
2120   [(set_attr "conds" "set")]
2123 (define_insn "iordi3"
2124   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2125         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2126                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2127   "TARGET_ARM && ! TARGET_IWMMXT"
2128   "#"
2129   [(set_attr "length" "8")
2130    (set_attr "predicable" "yes")]
2133 (define_insn "*iordi_zesidi_di"
2134   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2135         (ior:DI (zero_extend:DI
2136                  (match_operand:SI 2 "s_register_operand" "r,r"))
2137                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2138   "TARGET_ARM"
2139   "@
2140    orr%?\\t%Q0, %Q1, %2
2141    #"
2142   [(set_attr "length" "4,8")
2143    (set_attr "predicable" "yes")]
2146 (define_insn "*iordi_sesidi_di"
2147   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2148         (ior:DI (sign_extend:DI
2149                  (match_operand:SI 2 "s_register_operand" "r,r"))
2150                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2151   "TARGET_ARM"
2152   "#"
2153   [(set_attr "length" "8")
2154    (set_attr "predicable" "yes")]
2157 (define_expand "iorsi3"
2158   [(set (match_operand:SI         0 "s_register_operand" "")
2159         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2160                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2161   "TARGET_EITHER"
2162   "
2163   if (GET_CODE (operands[2]) == CONST_INT)
2164     {
2165       if (TARGET_ARM)
2166         {
2167           arm_split_constant (IOR, SImode, NULL_RTX,
2168                               INTVAL (operands[2]), operands[0], operands[1],
2169                               optimize && !no_new_pseudos);
2170           DONE;
2171         }
2172       else /* TARGET_THUMB */
2173         operands [2] = force_reg (SImode, operands [2]);
2174     }
2175   "
2178 (define_insn_and_split "*arm_iorsi3"
2179   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2180         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2181                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2182   "TARGET_ARM"
2183   "@
2184    orr%?\\t%0, %1, %2
2185    #"
2186   "TARGET_ARM
2187    && GET_CODE (operands[2]) == CONST_INT
2188    && !const_ok_for_arm (INTVAL (operands[2]))"
2189   [(clobber (const_int 0))]
2190   "
2191   arm_split_constant (IOR, SImode, curr_insn, 
2192                       INTVAL (operands[2]), operands[0], operands[1], 0);
2193   DONE;
2194   "
2195   [(set_attr "length" "4,16")
2196    (set_attr "predicable" "yes")]
2199 (define_insn "*thumb_iorsi3"
2200   [(set (match_operand:SI         0 "register_operand" "=l")
2201         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2202                 (match_operand:SI 2 "register_operand" "l")))]
2203   "TARGET_THUMB"
2204   "orr\\t%0, %0, %2"
2205   [(set_attr "length" "2")]
2208 (define_peephole2
2209   [(match_scratch:SI 3 "r")
2210    (set (match_operand:SI 0 "arm_general_register_operand" "")
2211         (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2212                 (match_operand:SI 2 "const_int_operand" "")))]
2213   "TARGET_ARM
2214    && !const_ok_for_arm (INTVAL (operands[2]))
2215    && const_ok_for_arm (~INTVAL (operands[2]))"
2216   [(set (match_dup 3) (match_dup 2))
2217    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2218   ""
2221 (define_insn "*iorsi3_compare0"
2222   [(set (reg:CC_NOOV CC_REGNUM)
2223         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2224                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2225                          (const_int 0)))
2226    (set (match_operand:SI 0 "s_register_operand" "=r")
2227         (ior:SI (match_dup 1) (match_dup 2)))]
2228   "TARGET_ARM"
2229   "orr%?s\\t%0, %1, %2"
2230   [(set_attr "conds" "set")]
2233 (define_insn "*iorsi3_compare0_scratch"
2234   [(set (reg:CC_NOOV CC_REGNUM)
2235         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2236                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2237                          (const_int 0)))
2238    (clobber (match_scratch:SI 0 "=r"))]
2239   "TARGET_ARM"
2240   "orr%?s\\t%0, %1, %2"
2241   [(set_attr "conds" "set")]
2244 (define_insn "xordi3"
2245   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2246         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2247                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2248   "TARGET_ARM && !TARGET_IWMMXT"
2249   "#"
2250   [(set_attr "length" "8")
2251    (set_attr "predicable" "yes")]
2254 (define_insn "*xordi_zesidi_di"
2255   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2256         (xor:DI (zero_extend:DI
2257                  (match_operand:SI 2 "s_register_operand" "r,r"))
2258                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2259   "TARGET_ARM"
2260   "@
2261    eor%?\\t%Q0, %Q1, %2
2262    #"
2263   [(set_attr "length" "4,8")
2264    (set_attr "predicable" "yes")]
2267 (define_insn "*xordi_sesidi_di"
2268   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2269         (xor:DI (sign_extend:DI
2270                  (match_operand:SI 2 "s_register_operand" "r,r"))
2271                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2272   "TARGET_ARM"
2273   "#"
2274   [(set_attr "length" "8")
2275    (set_attr "predicable" "yes")]
2278 (define_expand "xorsi3"
2279   [(set (match_operand:SI         0 "s_register_operand" "")
2280         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2281                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2282   "TARGET_EITHER"
2283   "if (TARGET_THUMB)
2284      if (GET_CODE (operands[2]) == CONST_INT)
2285        operands[2] = force_reg (SImode, operands[2]);
2286   "
2289 (define_insn "*arm_xorsi3"
2290   [(set (match_operand:SI         0 "s_register_operand" "=r")
2291         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2292                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2293   "TARGET_ARM"
2294   "eor%?\\t%0, %1, %2"
2295   [(set_attr "predicable" "yes")]
2298 (define_insn "*thumb_xorsi3"
2299   [(set (match_operand:SI         0 "register_operand" "=l")
2300         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2301                 (match_operand:SI 2 "register_operand" "l")))]
2302   "TARGET_THUMB"
2303   "eor\\t%0, %0, %2"
2304   [(set_attr "length" "2")]
2307 (define_insn "*xorsi3_compare0"
2308   [(set (reg:CC_NOOV CC_REGNUM)
2309         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2310                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2311                          (const_int 0)))
2312    (set (match_operand:SI 0 "s_register_operand" "=r")
2313         (xor:SI (match_dup 1) (match_dup 2)))]
2314   "TARGET_ARM"
2315   "eor%?s\\t%0, %1, %2"
2316   [(set_attr "conds" "set")]
2319 (define_insn "*xorsi3_compare0_scratch"
2320   [(set (reg:CC_NOOV CC_REGNUM)
2321         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2322                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2323                          (const_int 0)))]
2324   "TARGET_ARM"
2325   "teq%?\\t%0, %1"
2326   [(set_attr "conds" "set")]
2329 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2330 ; (NOT D) we can sometimes merge the final NOT into one of the following
2331 ; insns.
2333 (define_split
2334   [(set (match_operand:SI 0 "s_register_operand" "")
2335         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2336                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2337                 (match_operand:SI 3 "arm_rhs_operand" "")))
2338    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2339   "TARGET_ARM"
2340   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2341                               (not:SI (match_dup 3))))
2342    (set (match_dup 0) (not:SI (match_dup 4)))]
2343   ""
2346 (define_insn "*andsi_iorsi3_notsi"
2347   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2348         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2349                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2350                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2351   "TARGET_ARM"
2352   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2353   [(set_attr "length" "8")
2354    (set_attr "predicable" "yes")]
2357 (define_split
2358   [(set (match_operand:SI 0 "s_register_operand" "")
2359         (match_operator:SI 1 "logical_binary_operator"
2360          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2361                            (match_operand:SI 3 "const_int_operand" "")
2362                            (match_operand:SI 4 "const_int_operand" ""))
2363           (match_operator:SI 9 "logical_binary_operator"
2364            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2365                          (match_operand:SI 6 "const_int_operand" ""))
2366             (match_operand:SI 7 "s_register_operand" "")])]))
2367    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2368   "TARGET_ARM
2369    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2370    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2371   [(set (match_dup 8)
2372         (match_op_dup 1
2373          [(ashift:SI (match_dup 2) (match_dup 4))
2374           (match_dup 5)]))
2375    (set (match_dup 0)
2376         (match_op_dup 1
2377          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2378           (match_dup 7)]))]
2379   "
2380   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2383 (define_split
2384   [(set (match_operand:SI 0 "s_register_operand" "")
2385         (match_operator:SI 1 "logical_binary_operator"
2386          [(match_operator:SI 9 "logical_binary_operator"
2387            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2388                          (match_operand:SI 6 "const_int_operand" ""))
2389             (match_operand:SI 7 "s_register_operand" "")])
2390           (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2391                            (match_operand:SI 3 "const_int_operand" "")
2392                            (match_operand:SI 4 "const_int_operand" ""))]))
2393    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2394   "TARGET_ARM
2395    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2396    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2397   [(set (match_dup 8)
2398         (match_op_dup 1
2399          [(ashift:SI (match_dup 2) (match_dup 4))
2400           (match_dup 5)]))
2401    (set (match_dup 0)
2402         (match_op_dup 1
2403          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2404           (match_dup 7)]))]
2405   "
2406   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2409 (define_split
2410   [(set (match_operand:SI 0 "s_register_operand" "")
2411         (match_operator:SI 1 "logical_binary_operator"
2412          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2413                            (match_operand:SI 3 "const_int_operand" "")
2414                            (match_operand:SI 4 "const_int_operand" ""))
2415           (match_operator:SI 9 "logical_binary_operator"
2416            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2417                          (match_operand:SI 6 "const_int_operand" ""))
2418             (match_operand:SI 7 "s_register_operand" "")])]))
2419    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2420   "TARGET_ARM
2421    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2422    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2423   [(set (match_dup 8)
2424         (match_op_dup 1
2425          [(ashift:SI (match_dup 2) (match_dup 4))
2426           (match_dup 5)]))
2427    (set (match_dup 0)
2428         (match_op_dup 1
2429          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2430           (match_dup 7)]))]
2431   "
2432   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2435 (define_split
2436   [(set (match_operand:SI 0 "s_register_operand" "")
2437         (match_operator:SI 1 "logical_binary_operator"
2438          [(match_operator:SI 9 "logical_binary_operator"
2439            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2440                          (match_operand:SI 6 "const_int_operand" ""))
2441             (match_operand:SI 7 "s_register_operand" "")])
2442           (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2443                            (match_operand:SI 3 "const_int_operand" "")
2444                            (match_operand:SI 4 "const_int_operand" ""))]))
2445    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2446   "TARGET_ARM
2447    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2448    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2449   [(set (match_dup 8)
2450         (match_op_dup 1
2451          [(ashift:SI (match_dup 2) (match_dup 4))
2452           (match_dup 5)]))
2453    (set (match_dup 0)
2454         (match_op_dup 1
2455          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2456           (match_dup 7)]))]
2457   "
2458   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2462 ;; Minimum and maximum insns
2464 (define_insn "smaxsi3"
2465   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2466         (smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2467                  (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2468    (clobber (reg:CC CC_REGNUM))]
2469   "TARGET_ARM"
2470   "@
2471    cmp\\t%1, %2\;movlt\\t%0, %2
2472    cmp\\t%1, %2\;movge\\t%0, %1
2473    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2474   [(set_attr "conds" "clob")
2475    (set_attr "length" "8,8,12")]
2478 (define_insn "sminsi3"
2479   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2480         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2481                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2482    (clobber (reg:CC CC_REGNUM))]
2483   "TARGET_ARM"
2484   "@
2485    cmp\\t%1, %2\;movge\\t%0, %2
2486    cmp\\t%1, %2\;movlt\\t%0, %1
2487    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2488   [(set_attr "conds" "clob")
2489    (set_attr "length" "8,8,12")]
2492 (define_insn "umaxsi3"
2493   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2494         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2495                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2496    (clobber (reg:CC CC_REGNUM))]
2497   "TARGET_ARM"
2498   "@
2499    cmp\\t%1, %2\;movcc\\t%0, %2
2500    cmp\\t%1, %2\;movcs\\t%0, %1
2501    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2502   [(set_attr "conds" "clob")
2503    (set_attr "length" "8,8,12")]
2506 (define_insn "uminsi3"
2507   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2508         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2509                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2510    (clobber (reg:CC CC_REGNUM))]
2511   "TARGET_ARM"
2512   "@
2513    cmp\\t%1, %2\;movcs\\t%0, %2
2514    cmp\\t%1, %2\;movcc\\t%0, %1
2515    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2516   [(set_attr "conds" "clob")
2517    (set_attr "length" "8,8,12")]
2520 (define_insn "*store_minmaxsi"
2521   [(set (match_operand:SI 0 "memory_operand" "=m")
2522         (match_operator:SI 3 "minmax_operator"
2523          [(match_operand:SI 1 "s_register_operand" "r")
2524           (match_operand:SI 2 "s_register_operand" "r")]))
2525    (clobber (reg:CC CC_REGNUM))]
2526   "TARGET_ARM"
2527   "*
2528   operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2529                                 operands[1], operands[2]);
2530   output_asm_insn (\"cmp\\t%1, %2\", operands);
2531   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2532   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2533   return \"\";
2534   "
2535   [(set_attr "conds" "clob")
2536    (set_attr "length" "12")
2537    (set_attr "type" "store1")]
2540 ; Reject the frame pointer in operand[1], since reloading this after
2541 ; it has been eliminated can cause carnage.
2542 (define_insn "*minmax_arithsi"
2543   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2544         (match_operator:SI 4 "shiftable_operator"
2545          [(match_operator:SI 5 "minmax_operator"
2546            [(match_operand:SI 2 "s_register_operand" "r,r")
2547             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2548           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2549    (clobber (reg:CC CC_REGNUM))]
2550   "TARGET_ARM
2551    && (GET_CODE (operands[1]) != REG
2552        || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2553            && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2554   "*
2555   {
2556     enum rtx_code code = GET_CODE (operands[4]);
2558     operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2559                                   operands[2], operands[3]);
2560     output_asm_insn (\"cmp\\t%2, %3\", operands);
2561     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2562     if (which_alternative != 0 || operands[3] != const0_rtx
2563         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2564       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2565     return \"\";
2566   }"
2567   [(set_attr "conds" "clob")
2568    (set_attr "length" "12")]
2572 ;; Shift and rotation insns
2574 (define_expand "ashldi3"
2575   [(set (match_operand:DI            0 "s_register_operand" "")
2576         (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2577                    (match_operand:SI 2 "reg_or_int_operand" "")))]
2578   "TARGET_ARM"
2579   "
2580   if (GET_CODE (operands[2]) == CONST_INT)
2581     {
2582       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2583         {
2584           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2585           DONE;
2586         }
2587         /* Ideally we shouldn't fail here if we could know that operands[1] 
2588            ends up already living in an iwmmxt register. Otherwise it's
2589            cheaper to have the alternate code being generated than moving
2590            values to iwmmxt regs and back.  */
2591         FAIL;
2592     }
2593   else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2594     FAIL;
2595   "
2598 (define_insn "arm_ashldi3_1bit"
2599   [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
2600         (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2601                    (const_int 1)))
2602    (clobber (reg:CC CC_REGNUM))]
2603   "TARGET_ARM"
2604   "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2605   [(set_attr "conds" "clob")
2606    (set_attr "length" "8")]
2609 (define_expand "ashlsi3"
2610   [(set (match_operand:SI            0 "s_register_operand" "")
2611         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2612                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2613   "TARGET_EITHER"
2614   "
2615   if (GET_CODE (operands[2]) == CONST_INT
2616       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2617     {
2618       emit_insn (gen_movsi (operands[0], const0_rtx));
2619       DONE;
2620     }
2621   "
2624 (define_insn "*thumb_ashlsi3"
2625   [(set (match_operand:SI            0 "register_operand" "=l,l")
2626         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2627                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2628   "TARGET_THUMB"
2629   "lsl\\t%0, %1, %2"
2630   [(set_attr "length" "2")]
2633 (define_expand "ashrdi3"
2634   [(set (match_operand:DI              0 "s_register_operand" "")
2635         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2636                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2637   "TARGET_ARM"
2638   "
2639   if (GET_CODE (operands[2]) == CONST_INT)
2640     {
2641       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2642         {
2643           emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2644           DONE;
2645         }
2646         /* Ideally we shouldn't fail here if we could know that operands[1] 
2647            ends up already living in an iwmmxt register. Otherwise it's
2648            cheaper to have the alternate code being generated than moving
2649            values to iwmmxt regs and back.  */
2650         FAIL;
2651     }
2652   else if (!TARGET_REALLY_IWMMXT)
2653     FAIL;
2654   "
2657 (define_insn "arm_ashrdi3_1bit"
2658   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2659         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2660                      (const_int 1)))
2661    (clobber (reg:CC CC_REGNUM))]
2662   "TARGET_ARM"
2663   "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2664   [(set_attr "conds" "clob")
2665    (set_attr "length" "8")]
2668 (define_expand "ashrsi3"
2669   [(set (match_operand:SI              0 "s_register_operand" "")
2670         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2671                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2672   "TARGET_EITHER"
2673   "
2674   if (GET_CODE (operands[2]) == CONST_INT
2675       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2676     operands[2] = GEN_INT (31);
2677   "
2680 (define_insn "*thumb_ashrsi3"
2681   [(set (match_operand:SI              0 "register_operand" "=l,l")
2682         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2683                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2684   "TARGET_THUMB"
2685   "asr\\t%0, %1, %2"
2686   [(set_attr "length" "2")]
2689 (define_expand "lshrdi3"
2690   [(set (match_operand:DI              0 "s_register_operand" "")
2691         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2692                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2693   "TARGET_ARM"
2694   "
2695   if (GET_CODE (operands[2]) == CONST_INT)
2696     {
2697       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2698         {
2699           emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2700           DONE;
2701         }
2702         /* Ideally we shouldn't fail here if we could know that operands[1] 
2703            ends up already living in an iwmmxt register. Otherwise it's
2704            cheaper to have the alternate code being generated than moving
2705            values to iwmmxt regs and back.  */
2706         FAIL;
2707     }
2708   else if (!TARGET_REALLY_IWMMXT)
2709     FAIL;
2710   "
2713 (define_insn "arm_lshrdi3_1bit"
2714   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2715         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2716                      (const_int 1)))
2717    (clobber (reg:CC CC_REGNUM))]
2718   "TARGET_ARM"
2719   "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2720   [(set_attr "conds" "clob")
2721    (set_attr "length" "8")]
2724 (define_expand "lshrsi3"
2725   [(set (match_operand:SI              0 "s_register_operand" "")
2726         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2727                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2728   "TARGET_EITHER"
2729   "
2730   if (GET_CODE (operands[2]) == CONST_INT
2731       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2732     {
2733       emit_insn (gen_movsi (operands[0], const0_rtx));
2734       DONE;
2735     }
2736   "
2739 (define_insn "*thumb_lshrsi3"
2740   [(set (match_operand:SI              0 "register_operand" "=l,l")
2741         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2742                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2743   "TARGET_THUMB"
2744   "lsr\\t%0, %1, %2"
2745   [(set_attr "length" "2")]
2748 (define_expand "rotlsi3"
2749   [(set (match_operand:SI              0 "s_register_operand" "")
2750         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2751                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2752   "TARGET_ARM"
2753   "
2754   if (GET_CODE (operands[2]) == CONST_INT)
2755     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2756   else
2757     {
2758       rtx reg = gen_reg_rtx (SImode);
2759       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2760       operands[2] = reg;
2761     }
2762   "
2765 (define_expand "rotrsi3"
2766   [(set (match_operand:SI              0 "s_register_operand" "")
2767         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2768                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2769   "TARGET_EITHER"
2770   "
2771   if (TARGET_ARM)
2772     {
2773       if (GET_CODE (operands[2]) == CONST_INT
2774           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2775         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2776     }
2777   else /* TARGET_THUMB */
2778     {
2779       if (GET_CODE (operands [2]) == CONST_INT)
2780         operands [2] = force_reg (SImode, operands[2]);
2781     }
2782   "
2785 (define_insn "*thumb_rotrsi3"
2786   [(set (match_operand:SI              0 "register_operand" "=l")
2787         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2788                      (match_operand:SI 2 "register_operand" "l")))]
2789   "TARGET_THUMB"
2790   "ror\\t%0, %0, %2"
2791   [(set_attr "length" "2")]
2794 (define_insn "*arm_shiftsi3"
2795   [(set (match_operand:SI   0 "s_register_operand" "=r")
2796         (match_operator:SI  3 "shift_operator"
2797          [(match_operand:SI 1 "s_register_operand"  "r")
2798           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2799   "TARGET_ARM"
2800   "mov%?\\t%0, %1%S3"
2801   [(set_attr "predicable" "yes")
2802    (set_attr "shift" "1")
2803    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2804                       (const_string "alu_shift")
2805                       (const_string "alu_shift_reg")))]
2808 (define_insn "*shiftsi3_compare0"
2809   [(set (reg:CC_NOOV CC_REGNUM)
2810         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2811                           [(match_operand:SI 1 "s_register_operand" "r")
2812                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2813                          (const_int 0)))
2814    (set (match_operand:SI 0 "s_register_operand" "=r")
2815         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2816   "TARGET_ARM"
2817   "mov%?s\\t%0, %1%S3"
2818   [(set_attr "conds" "set")
2819    (set_attr "shift" "1")
2820    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2821                       (const_string "alu_shift")
2822                       (const_string "alu_shift_reg")))]
2825 (define_insn "*shiftsi3_compare0_scratch"
2826   [(set (reg:CC_NOOV CC_REGNUM)
2827         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2828                           [(match_operand:SI 1 "s_register_operand" "r")
2829                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2830                          (const_int 0)))
2831    (clobber (match_scratch:SI 0 "=r"))]
2832   "TARGET_ARM"
2833   "mov%?s\\t%0, %1%S3"
2834   [(set_attr "conds" "set")
2835    (set_attr "shift" "1")]
2838 (define_insn "*notsi_shiftsi"
2839   [(set (match_operand:SI 0 "s_register_operand" "=r")
2840         (not:SI (match_operator:SI 3 "shift_operator"
2841                  [(match_operand:SI 1 "s_register_operand" "r")
2842                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2843   "TARGET_ARM"
2844   "mvn%?\\t%0, %1%S3"
2845   [(set_attr "predicable" "yes")
2846    (set_attr "shift" "1")
2847    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2848                       (const_string "alu_shift")
2849                       (const_string "alu_shift_reg")))]
2852 (define_insn "*notsi_shiftsi_compare0"
2853   [(set (reg:CC_NOOV CC_REGNUM)
2854         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2855                           [(match_operand:SI 1 "s_register_operand" "r")
2856                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2857                          (const_int 0)))
2858    (set (match_operand:SI 0 "s_register_operand" "=r")
2859         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2860   "TARGET_ARM"
2861   "mvn%?s\\t%0, %1%S3"
2862   [(set_attr "conds" "set")
2863    (set_attr "shift" "1")
2864    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2865                       (const_string "alu_shift")
2866                       (const_string "alu_shift_reg")))]
2869 (define_insn "*not_shiftsi_compare0_scratch"
2870   [(set (reg:CC_NOOV CC_REGNUM)
2871         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2872                           [(match_operand:SI 1 "s_register_operand" "r")
2873                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2874                          (const_int 0)))
2875    (clobber (match_scratch:SI 0 "=r"))]
2876   "TARGET_ARM"
2877   "mvn%?s\\t%0, %1%S3"
2878   [(set_attr "conds" "set")
2879    (set_attr "shift" "1")
2880    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2881                       (const_string "alu_shift")
2882                       (const_string "alu_shift_reg")))]
2885 ;; We don't really have extzv, but defining this using shifts helps
2886 ;; to reduce register pressure later on.
2888 (define_expand "extzv"
2889   [(set (match_dup 4)
2890         (ashift:SI (match_operand:SI   1 "register_operand" "")
2891                    (match_operand:SI   2 "const_int_operand" "")))
2892    (set (match_operand:SI              0 "register_operand" "")
2893         (lshiftrt:SI (match_dup 4)
2894                      (match_operand:SI 3 "const_int_operand" "")))]
2895   "TARGET_THUMB"
2896   "
2897   {
2898     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2899     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2900     
2901     operands[3] = GEN_INT (rshift);
2902     
2903     if (lshift == 0)
2904       {
2905         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2906         DONE;
2907       }
2908       
2909     operands[2] = GEN_INT (lshift);
2910     operands[4] = gen_reg_rtx (SImode);
2911   }"
2915 ;; Unary arithmetic insns
2917 (define_expand "negdi2"
2918  [(parallel
2919    [(set (match_operand:DI          0 "s_register_operand" "")
2920           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2921     (clobber (reg:CC CC_REGNUM))])]
2922   "TARGET_EITHER"
2923   "
2924   if (TARGET_THUMB)
2925     {
2926       if (GET_CODE (operands[1]) != REG)
2927         operands[1] = force_reg (SImode, operands[1]);
2928      }
2929   "
2932 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2933 ;; The second alternative is to allow the common case of a *full* overlap.
2934 (define_insn "*arm_negdi2"
2935   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2936         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2937    (clobber (reg:CC CC_REGNUM))]
2938   "TARGET_ARM"
2939   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2940   [(set_attr "conds" "clob")
2941    (set_attr "length" "8")]
2944 (define_insn "*thumb_negdi2"
2945   [(set (match_operand:DI         0 "register_operand" "=&l")
2946         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
2947    (clobber (reg:CC CC_REGNUM))]
2948   "TARGET_THUMB"
2949   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2950   [(set_attr "length" "6")]
2953 (define_expand "negsi2"
2954   [(set (match_operand:SI         0 "s_register_operand" "")
2955         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2956   "TARGET_EITHER"
2957   ""
2960 (define_insn "*arm_negsi2"
2961   [(set (match_operand:SI         0 "s_register_operand" "=r")
2962         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2963   "TARGET_ARM"
2964   "rsb%?\\t%0, %1, #0"
2965   [(set_attr "predicable" "yes")]
2968 (define_insn "*thumb_negsi2"
2969   [(set (match_operand:SI         0 "register_operand" "=l")
2970         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2971   "TARGET_THUMB"
2972   "neg\\t%0, %1"
2973   [(set_attr "length" "2")]
2976 (define_expand "negsf2"
2977   [(set (match_operand:SF         0 "s_register_operand" "")
2978         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2979   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2980   ""
2983 (define_expand "negdf2"
2984   [(set (match_operand:DF         0 "s_register_operand" "")
2985         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2986   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2987   "")
2989 ;; abssi2 doesn't really clobber the condition codes if a different register
2990 ;; is being set.  To keep things simple, assume during rtl manipulations that
2991 ;; it does, but tell the final scan operator the truth.  Similarly for
2992 ;; (neg (abs...))
2994 (define_expand "abssi2"
2995   [(parallel
2996     [(set (match_operand:SI         0 "s_register_operand" "")
2997           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
2998      (clobber (reg:CC CC_REGNUM))])]
2999   "TARGET_ARM"
3000   "")
3002 (define_insn "*arm_abssi2"
3003   [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
3004         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3005    (clobber (reg:CC CC_REGNUM))]
3006   "TARGET_ARM"
3007   "@
3008    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3009    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3010   [(set_attr "conds" "clob,*")
3011    (set_attr "shift" "1")
3012    ;; predicable can't be set based on the variant, so left as no
3013    (set_attr "length" "8")]
3016 (define_insn "*neg_abssi2"
3017   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3018         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3019    (clobber (reg:CC CC_REGNUM))]
3020   "TARGET_ARM"
3021   "@
3022    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3023    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3024   [(set_attr "conds" "clob,*")
3025    (set_attr "shift" "1")
3026    ;; predicable can't be set based on the variant, so left as no
3027    (set_attr "length" "8")]
3030 (define_expand "abssf2"
3031   [(set (match_operand:SF         0 "s_register_operand" "")
3032         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3033   "TARGET_ARM && TARGET_HARD_FLOAT"
3034   "")
3036 (define_expand "absdf2"
3037   [(set (match_operand:DF         0 "s_register_operand" "")
3038         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3039   "TARGET_ARM && TARGET_HARD_FLOAT"
3040   "")
3042 (define_expand "sqrtsf2"
3043   [(set (match_operand:SF 0 "s_register_operand" "")
3044         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3045   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3046   "")
3048 (define_expand "sqrtdf2"
3049   [(set (match_operand:DF 0 "s_register_operand" "")
3050         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3051   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3052   "")
3054 (define_insn_and_split "one_cmpldi2"
3055   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3056         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3057   "TARGET_ARM"
3058   "#"
3059   "TARGET_ARM && reload_completed"
3060   [(set (match_dup 0) (not:SI (match_dup 1)))
3061    (set (match_dup 2) (not:SI (match_dup 3)))]
3062   "
3063   {
3064     operands[2] = gen_highpart (SImode, operands[0]);
3065     operands[0] = gen_lowpart (SImode, operands[0]);
3066     operands[3] = gen_highpart (SImode, operands[1]);
3067     operands[1] = gen_lowpart (SImode, operands[1]);
3068   }"
3069   [(set_attr "length" "8")
3070    (set_attr "predicable" "yes")]
3073 (define_expand "one_cmplsi2"
3074   [(set (match_operand:SI         0 "s_register_operand" "")
3075         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3076   "TARGET_EITHER"
3077   ""
3080 (define_insn "*arm_one_cmplsi2"
3081   [(set (match_operand:SI         0 "s_register_operand" "=r")
3082         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3083   "TARGET_ARM"
3084   "mvn%?\\t%0, %1"
3085   [(set_attr "predicable" "yes")]
3088 (define_insn "*thumb_one_cmplsi2"
3089   [(set (match_operand:SI         0 "register_operand" "=l")
3090         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3091   "TARGET_THUMB"
3092   "mvn\\t%0, %1"
3093   [(set_attr "length" "2")]
3096 (define_insn "*notsi_compare0"
3097   [(set (reg:CC_NOOV CC_REGNUM)
3098         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3099                          (const_int 0)))
3100    (set (match_operand:SI 0 "s_register_operand" "=r")
3101         (not:SI (match_dup 1)))]
3102   "TARGET_ARM"
3103   "mvn%?s\\t%0, %1"
3104   [(set_attr "conds" "set")]
3107 (define_insn "*notsi_compare0_scratch"
3108   [(set (reg:CC_NOOV CC_REGNUM)
3109         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3110                          (const_int 0)))
3111    (clobber (match_scratch:SI 0 "=r"))]
3112   "TARGET_ARM"
3113   "mvn%?s\\t%0, %1"
3114   [(set_attr "conds" "set")]
3117 ;; Fixed <--> Floating conversion insns
3119 (define_expand "floatsisf2"
3120   [(set (match_operand:SF           0 "s_register_operand" "")
3121         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3122   "TARGET_ARM && TARGET_HARD_FLOAT"
3123   "
3124   if (TARGET_MAVERICK)
3125     {
3126       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3127       DONE;
3128     }
3131 (define_expand "floatsidf2"
3132   [(set (match_operand:DF           0 "s_register_operand" "")
3133         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3134   "TARGET_ARM && TARGET_HARD_FLOAT"
3135   "
3136   if (TARGET_MAVERICK)
3137     {
3138       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3139       DONE;
3140     }
3143 (define_expand "fix_truncsfsi2"
3144   [(set (match_operand:SI         0 "s_register_operand" "")
3145         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3146   "TARGET_ARM && TARGET_HARD_FLOAT"
3147   "
3148   if (TARGET_MAVERICK)
3149     {
3150       if (!cirrus_fp_register (operands[0], SImode))
3151         operands[0] = force_reg (SImode, operands[0]);
3152       if (!cirrus_fp_register (operands[1], SFmode))
3153         operands[1] = force_reg (SFmode, operands[0]);
3154       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3155       DONE;
3156     }
3159 (define_expand "fix_truncdfsi2"
3160   [(set (match_operand:SI         0 "s_register_operand" "")
3161         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3162   "TARGET_ARM && TARGET_HARD_FLOAT"
3163   "
3164   if (TARGET_MAVERICK)
3165     {
3166       if (!cirrus_fp_register (operands[1], DFmode))
3167         operands[1] = force_reg (DFmode, operands[0]);
3168       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3169       DONE;
3170     }
3173 ;; Truncation insns
3175 (define_expand "truncdfsf2"
3176   [(set (match_operand:SF  0 "s_register_operand" "")
3177         (float_truncate:SF
3178          (match_operand:DF 1 "s_register_operand" "")))]
3179   "TARGET_ARM && TARGET_HARD_FLOAT"
3180   ""
3183 ;; Zero and sign extension instructions.
3185 (define_insn "zero_extendsidi2"
3186   [(set (match_operand:DI 0 "s_register_operand" "=r")
3187         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3188   "TARGET_ARM"
3189   "*
3190     if (REGNO (operands[1])
3191         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3192       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3193     return \"mov%?\\t%R0, #0\";
3194   "
3195   [(set_attr "length" "8")
3196    (set_attr "predicable" "yes")]
3199 (define_insn "zero_extendqidi2"
3200   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3201         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3202   "TARGET_ARM"
3203   "@
3204    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3205    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3206   [(set_attr "length" "8")
3207    (set_attr "predicable" "yes")
3208    (set_attr "type" "*,load_byte")
3209    (set_attr "pool_range" "*,4092")
3210    (set_attr "neg_pool_range" "*,4084")]
3213 (define_insn "extendsidi2"
3214   [(set (match_operand:DI 0 "s_register_operand" "=r")
3215         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3216   "TARGET_ARM"
3217   "*
3218     if (REGNO (operands[1])
3219         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3220       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3221     return \"mov%?\\t%R0, %Q0, asr #31\";
3222   "
3223   [(set_attr "length" "8")
3224    (set_attr "shift" "1")
3225    (set_attr "predicable" "yes")]
3228 (define_expand "zero_extendhisi2"
3229   [(set (match_dup 2)
3230         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3231                    (const_int 16)))
3232    (set (match_operand:SI 0 "s_register_operand" "")
3233         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3234   "TARGET_EITHER"
3235   "
3236   {
3237     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3238       {
3239         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3240                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3241         DONE;
3242       }
3244     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3245       {
3246         emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3247         DONE;
3248       }
3250     if (!s_register_operand (operands[1], HImode))
3251       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3253     if (arm_arch6)
3254       {
3255         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3256                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3257         DONE;
3258       }
3260     operands[1] = gen_lowpart (SImode, operands[1]);
3261     operands[2] = gen_reg_rtx (SImode);
3262   }"
3265 (define_insn "*thumb_zero_extendhisi2"
3266   [(set (match_operand:SI 0 "register_operand" "=l")
3267         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3268   "TARGET_THUMB && !arm_arch6"
3269   "*
3270   rtx mem = XEXP (operands[1], 0);
3272   if (GET_CODE (mem) == CONST)
3273     mem = XEXP (mem, 0);
3274     
3275   if (GET_CODE (mem) == LABEL_REF)
3276     return \"ldr\\t%0, %1\";
3277     
3278   if (GET_CODE (mem) == PLUS)
3279     {
3280       rtx a = XEXP (mem, 0);
3281       rtx b = XEXP (mem, 1);
3283       /* This can happen due to bugs in reload.  */
3284       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3285         {
3286           rtx ops[2];
3287           ops[0] = operands[0];
3288           ops[1] = a;
3289       
3290           output_asm_insn (\"mov        %0, %1\", ops);
3292           XEXP (mem, 0) = operands[0];
3293        }
3295       else if (   GET_CODE (a) == LABEL_REF
3296                && GET_CODE (b) == CONST_INT)
3297         return \"ldr\\t%0, %1\";
3298     }
3299     
3300   return \"ldrh\\t%0, %1\";
3301   "
3302   [(set_attr "length" "4")
3303    (set_attr "type" "load_byte")
3304    (set_attr "pool_range" "60")]
3307 (define_insn "*thumb_zero_extendhisi2_v6"
3308   [(set (match_operand:SI 0 "register_operand" "=l,l")
3309         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3310   "TARGET_THUMB && arm_arch6"
3311   "*
3312   rtx mem;
3314   if (which_alternative == 0)
3315     return \"uxth\\t%0, %1\";
3317   mem = XEXP (operands[1], 0);
3319   if (GET_CODE (mem) == CONST)
3320     mem = XEXP (mem, 0);
3321     
3322   if (GET_CODE (mem) == LABEL_REF)
3323     return \"ldr\\t%0, %1\";
3324     
3325   if (GET_CODE (mem) == PLUS)
3326     {
3327       rtx a = XEXP (mem, 0);
3328       rtx b = XEXP (mem, 1);
3330       /* This can happen due to bugs in reload.  */
3331       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3332         {
3333           rtx ops[2];
3334           ops[0] = operands[0];
3335           ops[1] = a;
3336       
3337           output_asm_insn (\"mov        %0, %1\", ops);
3339           XEXP (mem, 0) = operands[0];
3340        }
3342       else if (   GET_CODE (a) == LABEL_REF
3343                && GET_CODE (b) == CONST_INT)
3344         return \"ldr\\t%0, %1\";
3345     }
3346     
3347   return \"ldrh\\t%0, %1\";
3348   "
3349   [(set_attr "length" "2,4")
3350    (set_attr "type" "alu_shift,load_byte")
3351    (set_attr "pool_range" "*,60")]
3354 (define_insn "*arm_zero_extendhisi2"
3355   [(set (match_operand:SI 0 "s_register_operand" "=r")
3356         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3357   "TARGET_ARM && arm_arch4 && !arm_arch6"
3358   "ldr%?h\\t%0, %1"
3359   [(set_attr "type" "load_byte")
3360    (set_attr "predicable" "yes")
3361    (set_attr "pool_range" "256")
3362    (set_attr "neg_pool_range" "244")]
3365 (define_insn "*arm_zero_extendhisi2_v6"
3366   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3367         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3368   "TARGET_ARM && arm_arch6"
3369   "@
3370    uxth%?\\t%0, %1
3371    ldr%?h\\t%0, %1"
3372   [(set_attr "type" "alu_shift,load_byte")
3373    (set_attr "predicable" "yes")
3374    (set_attr "pool_range" "*,256")
3375    (set_attr "neg_pool_range" "*,244")]
3378 (define_insn "*arm_zero_extendhisi2addsi"
3379   [(set (match_operand:SI 0 "s_register_operand" "=r")
3380         (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3381                  (match_operand:SI 2 "s_register_operand" "r")))]
3382   "TARGET_ARM && arm_arch6"
3383   "uxtah%?\\t%0, %2, %1"
3384   [(set_attr "type" "alu_shift")
3385    (set_attr "predicable" "yes")]
3388 (define_split
3389   [(set (match_operand:SI 0 "s_register_operand" "")
3390         (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3391    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3392   "TARGET_ARM && (!arm_arch4)"
3393   [(set (match_dup 2) (match_dup 1))
3394    (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3395   "
3396   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3397     FAIL;
3398   "
3401 (define_split
3402   [(set (match_operand:SI 0 "s_register_operand" "")
3403         (match_operator:SI 3 "shiftable_operator"
3404          [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3405           (match_operand:SI 4 "s_register_operand" "")]))
3406    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3407   "TARGET_ARM && (!arm_arch4)"
3408   [(set (match_dup 2) (match_dup 1))
3409    (set (match_dup 0)
3410         (match_op_dup 3
3411          [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3412   "
3413   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3414     FAIL;
3415   "
3418 (define_expand "zero_extendqisi2"
3419   [(set (match_operand:SI 0 "s_register_operand" "")
3420         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3421   "TARGET_EITHER"
3422   "
3423   if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3424     {
3425       if (TARGET_ARM)
3426         {
3427           emit_insn (gen_andsi3 (operands[0],
3428                                  gen_lowpart (SImode, operands[1]),
3429                                  GEN_INT (255)));
3430         }
3431       else /* TARGET_THUMB */
3432         {
3433           rtx temp = gen_reg_rtx (SImode);
3434           rtx ops[3];
3435           
3436           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3437           operands[1] = gen_lowpart (SImode, operands[1]);
3439           ops[0] = temp;
3440           ops[1] = operands[1];
3441           ops[2] = GEN_INT (24);
3443           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3444                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3445           
3446           ops[0] = operands[0];
3447           ops[1] = temp;
3448           ops[2] = GEN_INT (24);
3450           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3451                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3452         }
3453       DONE;
3454     }
3455   "
3458 (define_insn "*thumb_zero_extendqisi2"
3459   [(set (match_operand:SI 0 "register_operand" "=l")
3460         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3461   "TARGET_THUMB && !arm_arch6"
3462   "ldrb\\t%0, %1"
3463   [(set_attr "length" "2")
3464    (set_attr "type" "load_byte")
3465    (set_attr "pool_range" "32")]
3468 (define_insn "*thumb_zero_extendqisi2_v6"
3469   [(set (match_operand:SI 0 "register_operand" "=l,l")
3470         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3471   "TARGET_THUMB && arm_arch6"
3472   "@
3473    uxtb\\t%0, %1
3474    ldrb\\t%0, %1"
3475   [(set_attr "length" "2,2")
3476    (set_attr "type" "alu_shift,load_byte")
3477    (set_attr "pool_range" "*,32")]
3480 (define_insn "*arm_zero_extendqisi2"
3481   [(set (match_operand:SI 0 "s_register_operand" "=r")
3482         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3483   "TARGET_ARM && !arm_arch6"
3484   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3485   [(set_attr "type" "load_byte")
3486    (set_attr "predicable" "yes")
3487    (set_attr "pool_range" "4096")
3488    (set_attr "neg_pool_range" "4084")]
3491 (define_insn "*arm_zero_extendqisi2_v6"
3492   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3493         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3494   "TARGET_ARM && arm_arch6"
3495   "@
3496    uxtb%?\\t%0, %1
3497    ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3498   [(set_attr "type" "alu_shift,load_byte")
3499    (set_attr "predicable" "yes")
3500    (set_attr "pool_range" "*,4096")
3501    (set_attr "neg_pool_range" "*,4084")]
3504 (define_insn "*arm_zero_extendqisi2addsi"
3505   [(set (match_operand:SI 0 "s_register_operand" "=r")
3506         (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3507                  (match_operand:SI 2 "s_register_operand" "r")))]
3508   "TARGET_ARM && arm_arch6"
3509   "uxtab%?\\t%0, %2, %1"
3510   [(set_attr "predicable" "yes")
3511    (set_attr "type" "alu_shift")]
3514 (define_split
3515   [(set (match_operand:SI 0 "s_register_operand" "")
3516         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3517    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3518   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3519   [(set (match_dup 2) (match_dup 1))
3520    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3521   ""
3524 (define_insn "*compareqi_eq0"
3525   [(set (reg:CC_Z CC_REGNUM)
3526         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3527                          (const_int 0)))]
3528   "TARGET_ARM"
3529   "tst\\t%0, #255"
3530   [(set_attr "conds" "set")]
3533 (define_expand "extendhisi2"
3534   [(set (match_dup 2)
3535         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3536                    (const_int 16)))
3537    (set (match_operand:SI 0 "s_register_operand" "")
3538         (ashiftrt:SI (match_dup 2)
3539                      (const_int 16)))]
3540   "TARGET_EITHER"
3541   "
3542   {
3543     if (GET_CODE (operands[1]) == MEM)
3544       {
3545         if (TARGET_THUMB)
3546           {
3547             emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3548             DONE;
3549           }
3550         else if (arm_arch4)
3551           {
3552             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3553                        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3554             DONE;
3555           }
3556       }
3558     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3559       {
3560         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3561         DONE;
3562       }
3564     if (!s_register_operand (operands[1], HImode))
3565       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3567     if (arm_arch6)
3568       {
3569         if (TARGET_THUMB)
3570           emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3571         else
3572           emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3573                      gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3575         DONE;
3576       }
3578     operands[1] = gen_lowpart (SImode, operands[1]);
3579     operands[2] = gen_reg_rtx (SImode);
3580   }"
3583 (define_insn "thumb_extendhisi2"
3584   [(set (match_operand:SI 0 "register_operand" "=l")
3585         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3586    (clobber (match_scratch:SI 2 "=&l"))]
3587   "TARGET_THUMB && !arm_arch6"
3588   "*
3589   {
3590     rtx ops[4];
3591     rtx mem = XEXP (operands[1], 0);
3593     /* This code used to try to use 'V', and fix the address only if it was
3594        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3595        range of QImode offsets, and offsettable_address_p does a QImode
3596        address check.  */
3597        
3598     if (GET_CODE (mem) == CONST)
3599       mem = XEXP (mem, 0);
3600     
3601     if (GET_CODE (mem) == LABEL_REF)
3602       return \"ldr\\t%0, %1\";
3603     
3604     if (GET_CODE (mem) == PLUS)
3605       {
3606         rtx a = XEXP (mem, 0);
3607         rtx b = XEXP (mem, 1);
3609         if (GET_CODE (a) == LABEL_REF
3610             && GET_CODE (b) == CONST_INT)
3611           return \"ldr\\t%0, %1\";
3613         if (GET_CODE (b) == REG)
3614           return \"ldrsh\\t%0, %1\";
3615           
3616         ops[1] = a;
3617         ops[2] = b;
3618       }
3619     else
3620       {
3621         ops[1] = mem;
3622         ops[2] = const0_rtx;
3623       }
3624       
3625     if (GET_CODE (ops[1]) != REG)
3626       {
3627         debug_rtx (ops[1]);
3628         abort ();
3629       }
3631     ops[0] = operands[0];
3632     ops[3] = operands[2];
3633     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3634     return \"\";
3635   }"
3636   [(set_attr "length" "4")
3637    (set_attr "type" "load_byte")
3638    (set_attr "pool_range" "1020")]
3641 ;; We used to have an early-clobber on the scratch register here.
3642 ;; However, there's a bug somewhere in reload which means that this
3643 ;; can be partially ignored during spill allocation if the memory
3644 ;; address also needs reloading; this causes an abort later on when
3645 ;; we try to verify the operands.  Fortunately, we don't really need
3646 ;; the early-clobber: we can always use operand 0 if operand 2
3647 ;; overlaps the address.
3648 (define_insn "*thumb_extendhisi2_insn_v6"
3649   [(set (match_operand:SI 0 "register_operand" "=l,l")
3650         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3651    (clobber (match_scratch:SI 2 "=X,l"))]
3652   "TARGET_THUMB && arm_arch6"
3653   "*
3654   {
3655     rtx ops[4];
3656     rtx mem;
3658     if (which_alternative == 0)
3659       return \"sxth\\t%0, %1\";
3661     mem = XEXP (operands[1], 0);
3663     /* This code used to try to use 'V', and fix the address only if it was
3664        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3665        range of QImode offsets, and offsettable_address_p does a QImode
3666        address check.  */
3667        
3668     if (GET_CODE (mem) == CONST)
3669       mem = XEXP (mem, 0);
3670     
3671     if (GET_CODE (mem) == LABEL_REF)
3672       return \"ldr\\t%0, %1\";
3673     
3674     if (GET_CODE (mem) == PLUS)
3675       {
3676         rtx a = XEXP (mem, 0);
3677         rtx b = XEXP (mem, 1);
3679         if (GET_CODE (a) == LABEL_REF
3680             && GET_CODE (b) == CONST_INT)
3681           return \"ldr\\t%0, %1\";
3683         if (GET_CODE (b) == REG)
3684           return \"ldrsh\\t%0, %1\";
3685           
3686         ops[1] = a;
3687         ops[2] = b;
3688       }
3689     else
3690       {
3691         ops[1] = mem;
3692         ops[2] = const0_rtx;
3693       }
3694       
3695     if (GET_CODE (ops[1]) != REG)
3696       {
3697         debug_rtx (ops[1]);
3698         abort ();
3699       }
3701     ops[0] = operands[0];
3702     if (reg_mentioned_p (operands[2], ops[1]))
3703       ops[3] = ops[0];
3704     else
3705       ops[3] = operands[2];
3706     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3707     return \"\";
3708   }"
3709   [(set_attr "length" "2,4")
3710    (set_attr "type" "alu_shift,load_byte")
3711    (set_attr "pool_range" "*,1020")]
3714 (define_expand "extendhisi2_mem"
3715   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3716    (set (match_dup 3)
3717         (zero_extend:SI (match_dup 7)))
3718    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3719    (set (match_operand:SI 0 "" "")
3720         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3721   "TARGET_ARM"
3722   "
3723   {
3724     rtx mem1, mem2;
3725     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3727     mem1 = gen_rtx_MEM (QImode, addr);
3728     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3729     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3730     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3731     operands[0] = gen_lowpart (SImode, operands[0]);
3732     operands[1] = mem1;
3733     operands[2] = gen_reg_rtx (SImode);
3734     operands[3] = gen_reg_rtx (SImode);
3735     operands[6] = gen_reg_rtx (SImode);
3736     operands[7] = mem2;
3738     if (BYTES_BIG_ENDIAN)
3739       {
3740         operands[4] = operands[2];
3741         operands[5] = operands[3];
3742       }
3743     else
3744       {
3745         operands[4] = operands[3];
3746         operands[5] = operands[2];
3747       }
3748   }"
3751 (define_insn "*arm_extendhisi2"
3752   [(set (match_operand:SI 0 "s_register_operand" "=r")
3753         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3754   "TARGET_ARM && arm_arch4 && !arm_arch6"
3755   "ldr%?sh\\t%0, %1"
3756   [(set_attr "type" "load_byte")
3757    (set_attr "predicable" "yes")
3758    (set_attr "pool_range" "256")
3759    (set_attr "neg_pool_range" "244")]
3762 (define_insn "*arm_extendhisi2_v6"
3763   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3764         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3765   "TARGET_ARM && arm_arch6"
3766   "@
3767    sxth%?\\t%0, %1
3768    ldr%?sh\\t%0, %1"
3769   [(set_attr "type" "alu_shift,load_byte")
3770    (set_attr "predicable" "yes")
3771    (set_attr "pool_range" "*,256")
3772    (set_attr "neg_pool_range" "*,244")]
3775 (define_insn "*arm_extendhisi2addsi"
3776   [(set (match_operand:SI 0 "s_register_operand" "=r")
3777         (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3778                  (match_operand:SI 2 "s_register_operand" "r")))]
3779   "TARGET_ARM && arm_arch6"
3780   "sxtah%?\\t%0, %2, %1"
3783 (define_split
3784   [(set (match_operand:SI                 0 "s_register_operand" "")
3785         (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3786    (clobber (match_operand:SI             2 "s_register_operand" ""))]
3787   "TARGET_ARM && (!arm_arch4)"
3788   [(set (match_dup 2) (match_dup 1))
3789    (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3790   "
3791   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3792     FAIL;
3793   "
3796 (define_split
3797   [(set (match_operand:SI                   0 "s_register_operand" "")
3798         (match_operator:SI                  3 "shiftable_operator"
3799          [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3800           (match_operand:SI                 4 "s_register_operand" "")]))
3801    (clobber (match_operand:SI               2 "s_register_operand" ""))]
3802   "TARGET_ARM && (!arm_arch4)"
3803   [(set (match_dup 2) (match_dup 1))
3804    (set (match_dup 0)
3805         (match_op_dup 3
3806          [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3807   "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3808      FAIL;
3809   "
3812 (define_expand "extendqihi2"
3813   [(set (match_dup 2)
3814         (ashift:SI (match_operand:QI 1 "general_operand" "")
3815                    (const_int 24)))
3816    (set (match_operand:HI 0 "s_register_operand" "")
3817         (ashiftrt:SI (match_dup 2)
3818                      (const_int 24)))]
3819   "TARGET_ARM"
3820   "
3821   {
3822     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3823       {
3824         emit_insn (gen_rtx_SET (VOIDmode,
3825                                 operands[0],
3826                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3827         DONE;
3828       }
3829     if (!s_register_operand (operands[1], QImode))
3830       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3831     operands[0] = gen_lowpart (SImode, operands[0]);
3832     operands[1] = gen_lowpart (SImode, operands[1]);
3833     operands[2] = gen_reg_rtx (SImode);
3834   }"
3837 (define_insn "*extendqihi_insn"
3838   [(set (match_operand:HI 0 "s_register_operand" "=r")
3839         (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3840   "TARGET_ARM && arm_arch4"
3841   "ldr%?sb\\t%0, %1"
3842   [(set_attr "type" "load_byte")
3843    (set_attr "predicable" "yes")
3844    (set_attr "pool_range" "256")
3845    (set_attr "neg_pool_range" "244")]
3848 (define_expand "extendqisi2"
3849   [(set (match_dup 2)
3850         (ashift:SI (match_operand:QI 1 "general_operand" "")
3851                    (const_int 24)))
3852    (set (match_operand:SI 0 "s_register_operand" "")
3853         (ashiftrt:SI (match_dup 2)
3854                      (const_int 24)))]
3855   "TARGET_EITHER"
3856   "
3857   {
3858     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3859       {
3860         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3861                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3862         DONE;
3863       }
3865     if (!s_register_operand (operands[1], QImode))
3866       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3868     if (arm_arch6)
3869       {
3870         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3871                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3872         DONE;
3873       }
3875     operands[1] = gen_lowpart (SImode, operands[1]);
3876     operands[2] = gen_reg_rtx (SImode);
3877   }"
3880 (define_insn "*arm_extendqisi"
3881   [(set (match_operand:SI 0 "s_register_operand" "=r")
3882         (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3883   "TARGET_ARM && arm_arch4 && !arm_arch6"
3884   "ldr%?sb\\t%0, %1"
3885   [(set_attr "type" "load_byte")
3886    (set_attr "predicable" "yes")
3887    (set_attr "pool_range" "256")
3888    (set_attr "neg_pool_range" "244")]
3891 (define_insn "*arm_extendqisi_v6"
3892   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3893         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3894   "TARGET_ARM && arm_arch6"
3895   "@
3896    sxtb%?\\t%0, %1
3897    ldr%?sb\\t%0, %1"
3898   [(set_attr "type" "alu_shift,load_byte")
3899    (set_attr "predicable" "yes")
3900    (set_attr "pool_range" "*,256")
3901    (set_attr "neg_pool_range" "*,244")]
3904 (define_insn "*arm_extendqisi2addsi"
3905   [(set (match_operand:SI 0 "s_register_operand" "=r")
3906         (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3907                  (match_operand:SI 2 "s_register_operand" "r")))]
3908   "TARGET_ARM && arm_arch6"
3909   "sxtab%?\\t%0, %2, %1"
3910   [(set_attr "type" "alu_shift")
3911    (set_attr "predicable" "yes")]
3914 (define_insn "*thumb_extendqisi2"
3915   [(set (match_operand:SI 0 "register_operand" "=l,l")
3916         (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3917   "TARGET_THUMB && !arm_arch6"
3918   "*
3919   {
3920     rtx ops[3];
3921     rtx mem = XEXP (operands[1], 0);
3922     
3923     if (GET_CODE (mem) == CONST)
3924       mem = XEXP (mem, 0);
3925     
3926     if (GET_CODE (mem) == LABEL_REF)
3927       return \"ldr\\t%0, %1\";
3929     if (GET_CODE (mem) == PLUS
3930         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3931       return \"ldr\\t%0, %1\";
3932       
3933     if (which_alternative == 0)
3934       return \"ldrsb\\t%0, %1\";
3935       
3936     ops[0] = operands[0];
3937     
3938     if (GET_CODE (mem) == PLUS)
3939       {
3940         rtx a = XEXP (mem, 0);
3941         rtx b = XEXP (mem, 1);
3942         
3943         ops[1] = a;
3944         ops[2] = b;
3946         if (GET_CODE (a) == REG)
3947           {
3948             if (GET_CODE (b) == REG)
3949               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3950             else if (REGNO (a) == REGNO (ops[0]))
3951               {
3952                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3953                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3954                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3955               }
3956             else
3957               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3958           }
3959         else if (GET_CODE (b) != REG)
3960           abort ();
3961         else
3962           {
3963             if (REGNO (b) == REGNO (ops[0]))
3964               {
3965                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3966                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3967                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3968               }
3969             else
3970               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3971           }
3972       }
3973     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3974       {
3975         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3976         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3977         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3978       }
3979     else
3980       {
3981         ops[1] = mem;
3982         ops[2] = const0_rtx;
3983         
3984         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3985       }
3986     return \"\";
3987   }"
3988   [(set_attr "length" "2,6")
3989    (set_attr "type" "load_byte,load_byte")
3990    (set_attr "pool_range" "32,32")]
3993 (define_insn "*thumb_extendqisi2_v6"
3994   [(set (match_operand:SI 0 "register_operand" "=l,l,l")
3995         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
3996   "TARGET_THUMB && arm_arch6"
3997   "*
3998   {
3999     rtx ops[3];
4000     rtx mem;
4002     if (which_alternative == 0)
4003       return \"sxtb\\t%0, %1\";
4005     mem = XEXP (operands[1], 0);
4006     
4007     if (GET_CODE (mem) == CONST)
4008       mem = XEXP (mem, 0);
4009     
4010     if (GET_CODE (mem) == LABEL_REF)
4011       return \"ldr\\t%0, %1\";
4013     if (GET_CODE (mem) == PLUS
4014         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4015       return \"ldr\\t%0, %1\";
4016       
4017     if (which_alternative == 0)
4018       return \"ldrsb\\t%0, %1\";
4019       
4020     ops[0] = operands[0];
4021     
4022     if (GET_CODE (mem) == PLUS)
4023       {
4024         rtx a = XEXP (mem, 0);
4025         rtx b = XEXP (mem, 1);
4026         
4027         ops[1] = a;
4028         ops[2] = b;
4030         if (GET_CODE (a) == REG)
4031           {
4032             if (GET_CODE (b) == REG)
4033               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4034             else if (REGNO (a) == REGNO (ops[0]))
4035               {
4036                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4037                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4038               }
4039             else
4040               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4041           }
4042         else if (GET_CODE (b) != REG)
4043           abort ();
4044         else
4045           {
4046             if (REGNO (b) == REGNO (ops[0]))
4047               {
4048                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4049                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4050               }
4051             else
4052               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4053           }
4054       }
4055     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4056       {
4057         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4058         output_asm_insn (\"sxtb\\t%0, %0\", ops);
4059       }
4060     else
4061       {
4062         ops[1] = mem;
4063         ops[2] = const0_rtx;
4064         
4065         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4066       }
4067     return \"\";
4068   }"
4069   [(set_attr "length" "2,2,4")
4070    (set_attr "type" "alu_shift,load_byte,load_byte")
4071    (set_attr "pool_range" "*,32,32")]
4074 (define_expand "extendsfdf2"
4075   [(set (match_operand:DF                  0 "s_register_operand" "")
4076         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
4077   "TARGET_ARM && TARGET_HARD_FLOAT"
4078   ""
4081 ;; Move insns (including loads and stores)
4083 ;; XXX Just some ideas about movti.
4084 ;; I don't think these are a good idea on the arm, there just aren't enough
4085 ;; registers
4086 ;;(define_expand "loadti"
4087 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
4088 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
4089 ;;  "" "")
4091 ;;(define_expand "storeti"
4092 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4093 ;;      (match_operand:TI 1 "s_register_operand" ""))]
4094 ;;  "" "")
4096 ;;(define_expand "movti"
4097 ;;  [(set (match_operand:TI 0 "general_operand" "")
4098 ;;      (match_operand:TI 1 "general_operand" ""))]
4099 ;;  ""
4100 ;;  "
4102 ;;  rtx insn;
4104 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4105 ;;    operands[1] = copy_to_reg (operands[1]);
4106 ;;  if (GET_CODE (operands[0]) == MEM)
4107 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4108 ;;  else if (GET_CODE (operands[1]) == MEM)
4109 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4110 ;;  else
4111 ;;    FAIL;
4113 ;;  emit_insn (insn);
4114 ;;  DONE;
4115 ;;}")
4117 ;; Recognize garbage generated above.
4119 ;;(define_insn ""
4120 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4121 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4122 ;;  ""
4123 ;;  "*
4124 ;;  {
4125 ;;    register mem = (which_alternative < 3);
4126 ;;    register const char *template;
4128 ;;    operands[mem] = XEXP (operands[mem], 0);
4129 ;;    switch (which_alternative)
4130 ;;      {
4131 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4132 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
4133 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
4134 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
4135 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
4136 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
4137 ;;      }
4138 ;;    output_asm_insn (template, operands);
4139 ;;    return \"\";
4140 ;;  }")
4142 (define_expand "movdi"
4143   [(set (match_operand:DI 0 "general_operand" "")
4144         (match_operand:DI 1 "general_operand" ""))]
4145   "TARGET_EITHER"
4146   "
4147   if (TARGET_THUMB)
4148     {
4149       if (!no_new_pseudos)
4150         {
4151           if (GET_CODE (operands[0]) != REG)
4152             operands[1] = force_reg (DImode, operands[1]);
4153         }
4154     }
4155   "
4158 (define_insn "*arm_movdi"
4159   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r ,m")
4160         (match_operand:DI 1 "di_operand"              "rIK,mi,r"))]
4161   "TARGET_ARM
4162   && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4163   && !TARGET_IWMMXT"
4164   "*
4165   return (output_move_double (operands));
4166   "
4167   [(set_attr "length" "8")
4168    (set_attr "type" "*,load2,store2")
4169    (set_attr "pool_range" "*,1020,*")
4170    (set_attr "neg_pool_range" "*,1008,*")]
4173 ;; We can't actually do base+index doubleword loads if the index and
4174 ;; destination overlap.  Split here so that we at least have chance to
4175 ;; schedule.
4176 (define_split
4177   [(set (match_operand:DI 0 "s_register_operand" "")
4178         (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4179                          (match_operand:SI 2 "s_register_operand" ""))))]
4180   "TARGET_LDRD
4181   && reg_overlap_mentioned_p (operands[0], operands[1])
4182   && reg_overlap_mentioned_p (operands[0], operands[2])"
4183   [(set (match_dup 4)
4184         (plus:SI (match_dup 1)
4185                  (match_dup 2)))
4186    (set (match_dup 0)
4187         (mem:DI (match_dup 4)))]
4188   "
4189   operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4190   "
4193 ;;; ??? This should have alternatives for constants.
4194 ;;; ??? This was originally identical to the movdf_insn pattern.
4195 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4196 ;;; thumb_reorg with a memory reference.
4197 (define_insn "*thumb_movdi_insn"
4198   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4199         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
4200   "TARGET_THUMB
4201    && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4202    && (   register_operand (operands[0], DImode)
4203        || register_operand (operands[1], DImode))"
4204   "*
4205   {
4206   switch (which_alternative)
4207     {
4208     default:
4209     case 0:
4210       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4211         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
4212       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
4213     case 1:
4214       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4215     case 2:
4216       operands[1] = GEN_INT (- INTVAL (operands[1]));
4217       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4218     case 3:
4219       return \"ldmia\\t%1, {%0, %H0}\";
4220     case 4:
4221       return \"stmia\\t%0, {%1, %H1}\";
4222     case 5:
4223       return thumb_load_double_from_address (operands);
4224     case 6:
4225       operands[2] = gen_rtx_MEM (SImode,
4226                              plus_constant (XEXP (operands[0], 0), 4));
4227       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4228       return \"\";
4229     case 7:
4230       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4231         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4232       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4233     }
4234   }"
4235   [(set_attr "length" "4,4,6,2,2,6,4,4")
4236    (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4237    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4240 (define_expand "movsi"
4241   [(set (match_operand:SI 0 "general_operand" "")
4242         (match_operand:SI 1 "general_operand" ""))]
4243   "TARGET_EITHER"
4244   "
4245   if (TARGET_ARM)
4246     {
4247       /* Everything except mem = const or mem = mem can be done easily.  */
4248       if (GET_CODE (operands[0]) == MEM)
4249         operands[1] = force_reg (SImode, operands[1]);
4250       if (arm_general_register_operand (operands[0], SImode)
4251           && GET_CODE (operands[1]) == CONST_INT
4252           && !(const_ok_for_arm (INTVAL (operands[1]))
4253                || const_ok_for_arm (~INTVAL (operands[1]))))
4254         {
4255            arm_split_constant (SET, SImode, NULL_RTX,
4256                                INTVAL (operands[1]), operands[0], NULL_RTX,
4257                                optimize && !no_new_pseudos);
4258           DONE;
4259         }
4260     }
4261   else /* TARGET_THUMB....  */
4262     {
4263       if (!no_new_pseudos)
4264         {
4265           if (GET_CODE (operands[0]) != REG)
4266             operands[1] = force_reg (SImode, operands[1]);
4267         }
4268     }
4269     
4270   if (flag_pic
4271       && (CONSTANT_P (operands[1])
4272          || symbol_mentioned_p (operands[1])
4273          || label_mentioned_p (operands[1])))
4274     operands[1] = legitimize_pic_address (operands[1], SImode,
4275                                           (no_new_pseudos ? operands[0] : 0));
4276   "
4279 (define_insn "*arm_movsi_insn"
4280   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4281         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
4282   "TARGET_ARM && ! TARGET_IWMMXT
4283    && !(TARGET_HARD_FLOAT && TARGET_VFP)
4284    && (   register_operand (operands[0], SImode)
4285        || register_operand (operands[1], SImode))"
4286   "@
4287    mov%?\\t%0, %1
4288    mvn%?\\t%0, #%B1
4289    ldr%?\\t%0, %1
4290    str%?\\t%1, %0"
4291   [(set_attr "type" "*,*,load1,store1")
4292    (set_attr "predicable" "yes")
4293    (set_attr "pool_range" "*,*,4096,*")
4294    (set_attr "neg_pool_range" "*,*,4084,*")]
4297 (define_split
4298   [(set (match_operand:SI 0 "arm_general_register_operand" "")
4299         (match_operand:SI 1 "const_int_operand" ""))]
4300   "TARGET_ARM
4301   && (!(const_ok_for_arm (INTVAL (operands[1]))
4302         || const_ok_for_arm (~INTVAL (operands[1]))))"
4303   [(clobber (const_int 0))]
4304   "
4305   arm_split_constant (SET, SImode, NULL_RTX, 
4306                       INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4307   DONE;
4308   "
4311 (define_insn "*thumb_movsi_insn"
4312   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4313         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4314   "TARGET_THUMB
4315    && (   register_operand (operands[0], SImode) 
4316        || register_operand (operands[1], SImode))"
4317   "@
4318    mov  %0, %1
4319    mov  %0, %1
4320    #
4321    #
4322    ldmia\\t%1, {%0}
4323    stmia\\t%0, {%1}
4324    ldr\\t%0, %1
4325    str\\t%1, %0
4326    mov\\t%0, %1"
4327   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4328    (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4329    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4332 (define_split 
4333   [(set (match_operand:SI 0 "register_operand" "")
4334         (match_operand:SI 1 "const_int_operand" ""))]
4335   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4336   [(set (match_dup 0) (match_dup 1))
4337    (set (match_dup 0) (neg:SI (match_dup 0)))]
4338   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4341 (define_split 
4342   [(set (match_operand:SI 0 "register_operand" "")
4343         (match_operand:SI 1 "const_int_operand" ""))]
4344   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4345   [(set (match_dup 0) (match_dup 1))
4346    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4347   "
4348   {
4349     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4350     unsigned HOST_WIDE_INT mask = 0xff;
4351     int i;
4352     
4353     for (i = 0; i < 25; i++)
4354       if ((val & (mask << i)) == val)
4355         break;
4357     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4358     if (i == 0)
4359       FAIL;
4361     operands[1] = GEN_INT (val >> i);
4362     operands[2] = GEN_INT (i);
4363   }"
4366 ;; When generating pic, we need to load the symbol offset into a register.
4367 ;; So that the optimizer does not confuse this with a normal symbol load
4368 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
4369 ;; since that is the only type of relocation we can use.
4371 ;; The rather odd constraints on the following are to force reload to leave
4372 ;; the insn alone, and to force the minipool generation pass to then move
4373 ;; the GOT symbol to memory.
4375 (define_insn "pic_load_addr_arm"
4376   [(set (match_operand:SI 0 "s_register_operand" "=r")
4377         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4378   "TARGET_ARM && flag_pic"
4379   "ldr%?\\t%0, %1"
4380   [(set_attr "type" "load1")
4381    (set (attr "pool_range")     (const_int 4096))
4382    (set (attr "neg_pool_range") (const_int 4084))]
4385 (define_insn "pic_load_addr_thumb"
4386   [(set (match_operand:SI 0 "s_register_operand" "=l")
4387         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4388   "TARGET_THUMB && flag_pic"
4389   "ldr\\t%0, %1"
4390   [(set_attr "type" "load1")
4391    (set (attr "pool_range") (const_int 1024))]
4394 ;; This variant is used for AOF assembly, since it needs to mention the
4395 ;; pic register in the rtl.
4396 (define_expand "pic_load_addr_based"
4397   [(set (match_operand:SI 0 "s_register_operand" "")
4398         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4399   "TARGET_ARM && flag_pic"
4400   "operands[2] = pic_offset_table_rtx;"
4403 (define_insn "*pic_load_addr_based_insn"
4404   [(set (match_operand:SI 0 "s_register_operand" "=r")
4405         (unspec:SI [(match_operand 1 "" "")
4406                     (match_operand 2 "s_register_operand" "r")]
4407                    UNSPEC_PIC_SYM))]
4408   "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4409   "*
4410 #ifdef AOF_ASSEMBLER
4411   operands[1] = aof_pic_entry (operands[1]);
4412 #endif
4413   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4414   return \"\";
4415   "
4416   [(set_attr "type" "load1")
4417    (set (attr "pool_range")
4418         (if_then_else (eq_attr "is_thumb" "yes")
4419                       (const_int 1024)
4420                       (const_int 4096)))
4421    (set (attr "neg_pool_range")
4422         (if_then_else (eq_attr "is_thumb" "yes")
4423                       (const_int 0)
4424                       (const_int 4084)))]
4427 (define_insn "pic_add_dot_plus_four"
4428   [(set (match_operand:SI 0 "register_operand" "+r")
4429         (unspec:SI [(plus:SI (match_dup 0)
4430                              (const (plus:SI (pc) (const_int 4))))]
4431                    UNSPEC_PIC_BASE))
4432    (use (label_ref (match_operand 1 "" "")))]
4433   "TARGET_THUMB && flag_pic"
4434   "*
4435   (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4436                              CODE_LABEL_NUMBER (operands[1]));
4437   return \"add\\t%0, %|pc\";
4438   "
4439   [(set_attr "length" "2")]
4442 (define_insn "pic_add_dot_plus_eight"
4443   [(set (match_operand:SI 0 "register_operand" "+r")
4444         (unspec:SI [(plus:SI (match_dup 0)
4445                              (const (plus:SI (pc) (const_int 8))))]
4446                    UNSPEC_PIC_BASE))
4447    (use (label_ref (match_operand 1 "" "")))]
4448   "TARGET_ARM && flag_pic"
4449   "*
4450     (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4451                                CODE_LABEL_NUMBER (operands[1]));
4452     return \"add%?\\t%0, %|pc, %0\";
4453   "
4454   [(set_attr "predicable" "yes")]
4457 (define_expand "builtin_setjmp_receiver"
4458   [(label_ref (match_operand 0 "" ""))]
4459   "flag_pic"
4460   "
4462   arm_load_pic_register ();
4463   DONE;
4466 ;; If copying one reg to another we can set the condition codes according to
4467 ;; its value.  Such a move is common after a return from subroutine and the
4468 ;; result is being tested against zero.
4470 (define_insn "*movsi_compare0"
4471   [(set (reg:CC CC_REGNUM)
4472         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4473                     (const_int 0)))
4474    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4475         (match_dup 1))]
4476   "TARGET_ARM"
4477   "@
4478    cmp%?\\t%0, #0
4479    sub%?s\\t%0, %1, #0"
4480   [(set_attr "conds" "set")]
4483 ;; Subroutine to store a half word from a register into memory.
4484 ;; Operand 0 is the source register (HImode)
4485 ;; Operand 1 is the destination address in a register (SImode)
4487 ;; In both this routine and the next, we must be careful not to spill
4488 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4489 ;; can generate unrecognizable rtl.
4491 (define_expand "storehi"
4492   [;; store the low byte
4493    (set (match_operand 1 "" "") (match_dup 3))
4494    ;; extract the high byte
4495    (set (match_dup 2)
4496         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4497    ;; store the high byte
4498    (set (match_dup 4) (match_dup 5))]
4499   "TARGET_ARM"
4500   "
4501   {
4502     rtx op1 = operands[1];
4503     rtx addr = XEXP (op1, 0);
4504     enum rtx_code code = GET_CODE (addr);
4506     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4507         || code == MINUS)
4508       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4510     operands[4] = adjust_address (op1, QImode, 1);
4511     operands[1] = adjust_address (operands[1], QImode, 0);
4512     operands[3] = gen_lowpart (QImode, operands[0]);
4513     operands[0] = gen_lowpart (SImode, operands[0]);
4514     operands[2] = gen_reg_rtx (SImode);
4515     operands[5] = gen_lowpart (QImode, operands[2]);
4516   }"
4519 (define_expand "storehi_bigend"
4520   [(set (match_dup 4) (match_dup 3))
4521    (set (match_dup 2)
4522         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4523    (set (match_operand 1 "" "") (match_dup 5))]
4524   "TARGET_ARM"
4525   "
4526   {
4527     rtx op1 = operands[1];
4528     rtx addr = XEXP (op1, 0);
4529     enum rtx_code code = GET_CODE (addr);
4531     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4532         || code == MINUS)
4533       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4535     operands[4] = adjust_address (op1, QImode, 1);
4536     operands[1] = adjust_address (operands[1], QImode, 0);
4537     operands[3] = gen_lowpart (QImode, operands[0]);
4538     operands[0] = gen_lowpart (SImode, operands[0]);
4539     operands[2] = gen_reg_rtx (SImode);
4540     operands[5] = gen_lowpart (QImode, operands[2]);
4541   }"
4544 ;; Subroutine to store a half word integer constant into memory.
4545 (define_expand "storeinthi"
4546   [(set (match_operand 0 "" "")
4547         (match_operand 1 "" ""))
4548    (set (match_dup 3) (match_dup 2))]
4549   "TARGET_ARM"
4550   "
4551   {
4552     HOST_WIDE_INT value = INTVAL (operands[1]);
4553     rtx addr = XEXP (operands[0], 0);
4554     rtx op0 = operands[0];
4555     enum rtx_code code = GET_CODE (addr);
4557     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4558         || code == MINUS)
4559       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4561     operands[1] = gen_reg_rtx (SImode);
4562     if (BYTES_BIG_ENDIAN)
4563       {
4564         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4565         if ((value & 255) == ((value >> 8) & 255))
4566           operands[2] = operands[1];
4567         else
4568           {
4569             operands[2] = gen_reg_rtx (SImode);
4570             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4571           }
4572       }
4573     else
4574       {
4575         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4576         if ((value & 255) == ((value >> 8) & 255))
4577           operands[2] = operands[1];
4578         else
4579           {
4580             operands[2] = gen_reg_rtx (SImode);
4581             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4582           }
4583       }
4585     operands[3] = adjust_address (op0, QImode, 1);
4586     operands[0] = adjust_address (operands[0], QImode, 0);
4587     operands[2] = gen_lowpart (QImode, operands[2]);
4588     operands[1] = gen_lowpart (QImode, operands[1]);
4589   }"
4592 (define_expand "storehi_single_op"
4593   [(set (match_operand:HI 0 "memory_operand" "")
4594         (match_operand:HI 1 "general_operand" ""))]
4595   "TARGET_ARM && arm_arch4"
4596   "
4597   if (!s_register_operand (operands[1], HImode))
4598     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4599   "
4602 (define_expand "movhi"
4603   [(set (match_operand:HI 0 "general_operand" "")
4604         (match_operand:HI 1 "general_operand" ""))]
4605   "TARGET_EITHER"
4606   "
4607   if (TARGET_ARM)
4608     {
4609       if (!no_new_pseudos)
4610         {
4611           if (GET_CODE (operands[0]) == MEM)
4612             {
4613               if (arm_arch4)
4614                 {
4615                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4616                   DONE;
4617                 }
4618               if (GET_CODE (operands[1]) == CONST_INT)
4619                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4620               else
4621                 {
4622                   if (GET_CODE (operands[1]) == MEM)
4623                     operands[1] = force_reg (HImode, operands[1]);
4624                   if (BYTES_BIG_ENDIAN)
4625                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4626                   else
4627                    emit_insn (gen_storehi (operands[1], operands[0]));
4628                 }
4629               DONE;
4630             }
4631           /* Sign extend a constant, and keep it in an SImode reg.  */
4632           else if (GET_CODE (operands[1]) == CONST_INT)
4633             {
4634               rtx reg = gen_reg_rtx (SImode);
4635               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4637               /* If the constant is already valid, leave it alone.  */
4638               if (!const_ok_for_arm (val))
4639                 {
4640                   /* If setting all the top bits will make the constant 
4641                      loadable in a single instruction, then set them.  
4642                      Otherwise, sign extend the number.  */
4644                   if (const_ok_for_arm (~(val | ~0xffff)))
4645                     val |= ~0xffff;
4646                   else if (val & 0x8000)
4647                     val |= ~0xffff;
4648                 }
4650               emit_insn (gen_movsi (reg, GEN_INT (val)));
4651               operands[1] = gen_lowpart (HImode, reg);
4652             }
4653           else if (arm_arch4 && optimize && !no_new_pseudos
4654                    && GET_CODE (operands[1]) == MEM)
4655             {
4656               rtx reg = gen_reg_rtx (SImode);
4658               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4659               operands[1] = gen_lowpart (HImode, reg);
4660             }
4661           else if (!arm_arch4)
4662             {
4663               if (GET_CODE (operands[1]) == MEM)
4664                 {
4665                   rtx base;
4666                   rtx offset = const0_rtx;
4667                   rtx reg = gen_reg_rtx (SImode);
4669                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4670                        || (GET_CODE (base) == PLUS
4671                            && (GET_CODE (offset = XEXP (base, 1))
4672                                == CONST_INT)
4673                            && ((INTVAL(offset) & 1) != 1)
4674                            && GET_CODE (base = XEXP (base, 0)) == REG))
4675                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4676                     {
4677                       HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4678                       rtx new;
4680                       new = gen_rtx_MEM (SImode,
4681                                          plus_constant (base, new_offset));
4682                       MEM_COPY_ATTRIBUTES (new, operands[1]);
4683                       emit_insn (gen_movsi (reg, new));
4684                       if (((INTVAL (offset) & 2) != 0)
4685                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4686                         {
4687                           rtx reg2 = gen_reg_rtx (SImode);
4689                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4690                           reg = reg2;
4691                         }
4692                     }
4693                   else
4694                     emit_insn (gen_movhi_bytes (reg, operands[1]));
4696                   operands[1] = gen_lowpart (HImode, reg);
4697                }
4698            }
4699         }
4700       /* Handle loading a large integer during reload.  */
4701       else if (GET_CODE (operands[1]) == CONST_INT
4702                && !const_ok_for_arm (INTVAL (operands[1]))
4703                && !const_ok_for_arm (~INTVAL (operands[1])))
4704         {
4705           /* Writing a constant to memory needs a scratch, which should
4706              be handled with SECONDARY_RELOADs.  */
4707           if (GET_CODE (operands[0]) != REG)
4708             abort ();
4710           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4711           emit_insn (gen_movsi (operands[0], operands[1]));
4712           DONE;
4713        }
4714     }
4715   else /* TARGET_THUMB */
4716     {
4717       if (!no_new_pseudos)
4718         {
4719           if (GET_CODE (operands[0]) != REG)
4720             operands[1] = force_reg (HImode, operands[1]);
4722           /* ??? We shouldn't really get invalid addresses here, but this can
4723              happen if we are passed a SP (never OK for HImode/QImode) or 
4724              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4725              HImode/QImode) relative address.  */
4726           /* ??? This should perhaps be fixed elsewhere, for instance, in
4727              fixup_stack_1, by checking for other kinds of invalid addresses,
4728              e.g. a bare reference to a virtual register.  This may confuse the
4729              alpha though, which must handle this case differently.  */
4730           if (GET_CODE (operands[0]) == MEM
4731               && !memory_address_p (GET_MODE (operands[0]),
4732                                     XEXP (operands[0], 0)))
4733             operands[0]
4734               = replace_equiv_address (operands[0],
4735                                        copy_to_reg (XEXP (operands[0], 0)));
4736    
4737           if (GET_CODE (operands[1]) == MEM
4738               && !memory_address_p (GET_MODE (operands[1]),
4739                                     XEXP (operands[1], 0)))
4740             operands[1]
4741               = replace_equiv_address (operands[1],
4742                                        copy_to_reg (XEXP (operands[1], 0)));
4743         }
4744       /* Handle loading a large integer during reload.  */
4745       else if (GET_CODE (operands[1]) == CONST_INT
4746                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4747         {
4748           /* Writing a constant to memory needs a scratch, which should
4749              be handled with SECONDARY_RELOADs.  */
4750           if (GET_CODE (operands[0]) != REG)
4751             abort ();
4753           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4754           emit_insn (gen_movsi (operands[0], operands[1]));
4755           DONE;
4756         }
4757     }
4758   "
4761 (define_insn "*thumb_movhi_insn"
4762   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4763         (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
4764   "TARGET_THUMB
4765    && (   register_operand (operands[0], HImode)
4766        || register_operand (operands[1], HImode))"
4767   "*
4768   switch (which_alternative)
4769     {
4770     case 0: return \"add        %0, %1, #0\";
4771     case 2: return \"strh       %1, %0\";
4772     case 3: return \"mov        %0, %1\";
4773     case 4: return \"mov        %0, %1\";
4774     case 5: return \"mov        %0, %1\";
4775     default: abort ();
4776     case 1:
4777       /* The stack pointer can end up being taken as an index register.
4778           Catch this case here and deal with it.  */
4779       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4780           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4781           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4782         {
4783           rtx ops[2];
4784           ops[0] = operands[0];
4785           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4786       
4787           output_asm_insn (\"mov        %0, %1\", ops);
4789           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4790     
4791         }
4792       return \"ldrh     %0, %1\";
4793     }"
4794   [(set_attr "length" "2,4,2,2,2,2")
4795    (set_attr "type" "*,load1,store1,*,*,*")]
4799 (define_expand "movhi_bytes"
4800   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4801    (set (match_dup 3)
4802         (zero_extend:SI (match_dup 6)))
4803    (set (match_operand:SI 0 "" "")
4804          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4805   "TARGET_ARM"
4806   "
4807   {
4808     rtx mem1, mem2;
4809     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4811     mem1 = gen_rtx_MEM (QImode, addr);
4812     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4813     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4814     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4815     operands[0] = gen_lowpart (SImode, operands[0]);
4816     operands[1] = mem1;
4817     operands[2] = gen_reg_rtx (SImode);
4818     operands[3] = gen_reg_rtx (SImode);
4819     operands[6] = mem2;
4821     if (BYTES_BIG_ENDIAN)
4822       {
4823         operands[4] = operands[2];
4824         operands[5] = operands[3];
4825       }
4826     else
4827       {
4828         operands[4] = operands[3];
4829         operands[5] = operands[2];
4830       }
4831   }"
4834 (define_expand "movhi_bigend"
4835   [(set (match_dup 2)
4836         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4837                    (const_int 16)))
4838    (set (match_dup 3)
4839         (ashiftrt:SI (match_dup 2) (const_int 16)))
4840    (set (match_operand:HI 0 "s_register_operand" "")
4841         (match_dup 4))]
4842   "TARGET_ARM"
4843   "
4844   operands[2] = gen_reg_rtx (SImode);
4845   operands[3] = gen_reg_rtx (SImode);
4846   operands[4] = gen_lowpart (HImode, operands[3]);
4847   "
4850 ;; Pattern to recognize insn generated default case above
4851 (define_insn "*movhi_insn_arch4"
4852   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4853         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4854   "TARGET_ARM
4855    && arm_arch4
4856    && (GET_CODE (operands[1]) != CONST_INT
4857        || const_ok_for_arm (INTVAL (operands[1]))
4858        || const_ok_for_arm (~INTVAL (operands[1])))"
4859   "@
4860    mov%?\\t%0, %1\\t%@ movhi
4861    mvn%?\\t%0, #%B1\\t%@ movhi
4862    str%?h\\t%1, %0\\t%@ movhi 
4863    ldr%?h\\t%0, %1\\t%@ movhi"
4864   [(set_attr "type" "*,*,store1,load1")
4865    (set_attr "predicable" "yes")
4866    (set_attr "pool_range" "*,*,*,256")
4867    (set_attr "neg_pool_range" "*,*,*,244")]
4870 (define_insn "*movhi_bytes"
4871   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4872         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4873   "TARGET_ARM"
4874   "@
4875    mov%?\\t%0, %1\\t%@ movhi
4876    mvn%?\\t%0, #%B1\\t%@ movhi"
4877   [(set_attr "predicable" "yes")]
4880 (define_insn "thumb_movhi_clobber"
4881   [(set (match_operand:HI     0 "memory_operand"   "=m")
4882         (match_operand:HI     1 "register_operand" "l"))
4883    (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4884   "TARGET_THUMB"
4885   "*
4886   abort ();"
4888         
4889 ;; We use a DImode scratch because we may occasionally need an additional
4890 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4891 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4892 (define_expand "reload_outhi"
4893   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4894               (match_operand:HI 1 "s_register_operand"        "r")
4895               (match_operand:DI 2 "s_register_operand"        "=&l")])]
4896   "TARGET_EITHER"
4897   "if (TARGET_ARM)
4898      arm_reload_out_hi (operands);
4899    else
4900      thumb_reload_out_hi (operands);
4901   DONE;
4902   "
4905 (define_expand "reload_inhi"
4906   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4907               (match_operand:HI 1 "arm_reload_memory_operand" "o")
4908               (match_operand:DI 2 "s_register_operand" "=&r")])]
4909   "TARGET_EITHER"
4910   "
4911   if (TARGET_ARM)
4912     arm_reload_in_hi (operands);
4913   else
4914     thumb_reload_out_hi (operands);
4915   DONE;
4918 (define_expand "movqi"
4919   [(set (match_operand:QI 0 "general_operand" "")
4920         (match_operand:QI 1 "general_operand" ""))]
4921   "TARGET_EITHER"
4922   "
4923   if (TARGET_ARM)
4924     {
4925       /* Everything except mem = const or mem = mem can be done easily */
4927       if (!no_new_pseudos)
4928         {
4929           if (GET_CODE (operands[1]) == CONST_INT)
4930             {
4931               rtx reg = gen_reg_rtx (SImode);
4933               emit_insn (gen_movsi (reg, operands[1]));
4934               operands[1] = gen_lowpart (QImode, reg);
4935             }
4936           if (GET_CODE (operands[1]) == MEM && optimize > 0)
4937             {
4938               rtx reg = gen_reg_rtx (SImode);
4940               emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4941               operands[1] = gen_lowpart (QImode, reg);
4942             }
4943           if (GET_CODE (operands[0]) == MEM)
4944             operands[1] = force_reg (QImode, operands[1]);
4945         }
4946     }
4947   else /* TARGET_THUMB */
4948     {
4949       if (!no_new_pseudos)
4950         {
4951           if (GET_CODE (operands[0]) != REG)
4952             operands[1] = force_reg (QImode, operands[1]);
4954           /* ??? We shouldn't really get invalid addresses here, but this can
4955              happen if we are passed a SP (never OK for HImode/QImode) or
4956              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4957              HImode/QImode) relative address.  */
4958           /* ??? This should perhaps be fixed elsewhere, for instance, in
4959              fixup_stack_1, by checking for other kinds of invalid addresses,
4960              e.g. a bare reference to a virtual register.  This may confuse the
4961              alpha though, which must handle this case differently.  */
4962           if (GET_CODE (operands[0]) == MEM
4963               && !memory_address_p (GET_MODE (operands[0]),
4964                                      XEXP (operands[0], 0)))
4965             operands[0]
4966               = replace_equiv_address (operands[0],
4967                                        copy_to_reg (XEXP (operands[0], 0)));
4968           if (GET_CODE (operands[1]) == MEM
4969               && !memory_address_p (GET_MODE (operands[1]),
4970                                     XEXP (operands[1], 0)))
4971              operands[1]
4972                = replace_equiv_address (operands[1],
4973                                         copy_to_reg (XEXP (operands[1], 0)));
4974         }
4975       /* Handle loading a large integer during reload.  */
4976       else if (GET_CODE (operands[1]) == CONST_INT
4977                && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4978         {
4979           /* Writing a constant to memory needs a scratch, which should
4980              be handled with SECONDARY_RELOADs.  */
4981           if (GET_CODE (operands[0]) != REG)
4982             abort ();
4984           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4985           emit_insn (gen_movsi (operands[0], operands[1]));
4986           DONE;
4987        }
4988     }
4989   "
4993 (define_insn "*arm_movqi_insn"
4994   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4995         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4996   "TARGET_ARM
4997    && (   register_operand (operands[0], QImode)
4998        || register_operand (operands[1], QImode))"
4999   "@
5000    mov%?\\t%0, %1
5001    mvn%?\\t%0, #%B1
5002    ldr%?b\\t%0, %1
5003    str%?b\\t%1, %0"
5004   [(set_attr "type" "*,*,load1,store1")
5005    (set_attr "predicable" "yes")]
5008 (define_insn "*thumb_movqi_insn"
5009   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5010         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
5011   "TARGET_THUMB
5012    && (   register_operand (operands[0], QImode)
5013        || register_operand (operands[1], QImode))"
5014   "@
5015    add\\t%0, %1, #0
5016    ldrb\\t%0, %1
5017    strb\\t%1, %0
5018    mov\\t%0, %1
5019    mov\\t%0, %1
5020    mov\\t%0, %1"
5021   [(set_attr "length" "2")
5022    (set_attr "type" "*,load1,store1,*,*,*")
5023    (set_attr "pool_range" "*,32,*,*,*,*")]
5026 (define_expand "movsf"
5027   [(set (match_operand:SF 0 "general_operand" "")
5028         (match_operand:SF 1 "general_operand" ""))]
5029   "TARGET_EITHER"
5030   "
5031   if (TARGET_ARM)
5032     {
5033       if (GET_CODE (operands[0]) == MEM)
5034         operands[1] = force_reg (SFmode, operands[1]);
5035     }
5036   else /* TARGET_THUMB */
5037     {
5038       if (!no_new_pseudos)
5039         {
5040            if (GET_CODE (operands[0]) != REG)
5041              operands[1] = force_reg (SFmode, operands[1]);
5042         }
5043     }
5044   "
5047 (define_split
5048   [(set (match_operand:SF 0 "nonimmediate_operand" "")
5049         (match_operand:SF 1 "immediate_operand" ""))]
5050   "TARGET_ARM
5051    && !(TARGET_HARD_FLOAT && TARGET_FPA)
5052    && reload_completed
5053    && GET_CODE (operands[1]) == CONST_DOUBLE"
5054   [(set (match_dup 2) (match_dup 3))]
5055   "
5056   operands[2] = gen_lowpart (SImode, operands[0]);
5057   operands[3] = gen_lowpart (SImode, operands[1]);
5058   if (operands[2] == 0 || operands[3] == 0)
5059     FAIL;
5060   "
5063 (define_insn "*arm_movsf_soft_insn"
5064   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5065         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
5066   "TARGET_ARM
5067    && TARGET_SOFT_FLOAT
5068    && (GET_CODE (operands[0]) != MEM
5069        || register_operand (operands[1], SFmode))"
5070   "@
5071    mov%?\\t%0, %1
5072    ldr%?\\t%0, %1\\t%@ float
5073    str%?\\t%1, %0\\t%@ float"
5074   [(set_attr "length" "4,4,4")
5075    (set_attr "predicable" "yes")
5076    (set_attr "type" "*,load1,store1")
5077    (set_attr "pool_range" "*,4096,*")
5078    (set_attr "neg_pool_range" "*,4084,*")]
5081 ;;; ??? This should have alternatives for constants.
5082 (define_insn "*thumb_movsf_insn"
5083   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5084         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5085   "TARGET_THUMB
5086    && (   register_operand (operands[0], SFmode) 
5087        || register_operand (operands[1], SFmode))"
5088   "@
5089    add\\t%0, %1, #0
5090    ldmia\\t%1, {%0}
5091    stmia\\t%0, {%1}
5092    ldr\\t%0, %1
5093    str\\t%1, %0
5094    mov\\t%0, %1
5095    mov\\t%0, %1"
5096   [(set_attr "length" "2")
5097    (set_attr "type" "*,load1,store1,load1,store1,*,*")
5098    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5101 (define_expand "movdf"
5102   [(set (match_operand:DF 0 "general_operand" "")
5103         (match_operand:DF 1 "general_operand" ""))]
5104   "TARGET_EITHER"
5105   "
5106   if (TARGET_ARM)
5107     {
5108       if (GET_CODE (operands[0]) == MEM)
5109         operands[1] = force_reg (DFmode, operands[1]);
5110     }
5111   else /* TARGET_THUMB */
5112     {
5113       if (!no_new_pseudos)
5114         {
5115           if (GET_CODE (operands[0]) != REG)
5116             operands[1] = force_reg (DFmode, operands[1]);
5117         }
5118     }
5119   "
5122 ;; Reloading a df mode value stored in integer regs to memory can require a
5123 ;; scratch reg.
5124 (define_expand "reload_outdf"
5125   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5126    (match_operand:DF 1 "s_register_operand" "r")
5127    (match_operand:SI 2 "s_register_operand" "=&r")]
5128   "TARGET_ARM"
5129   "
5130   {
5131     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5133     if (code == REG)
5134       operands[2] = XEXP (operands[0], 0);
5135     else if (code == POST_INC || code == PRE_DEC)
5136       {
5137         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5138         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5139         emit_insn (gen_movdi (operands[0], operands[1]));
5140         DONE;
5141       }
5142     else if (code == PRE_INC)
5143       {
5144         rtx reg = XEXP (XEXP (operands[0], 0), 0);
5146         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5147         operands[2] = reg;
5148       }
5149     else if (code == POST_DEC)
5150       operands[2] = XEXP (XEXP (operands[0], 0), 0);
5151     else
5152       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5153                              XEXP (XEXP (operands[0], 0), 1)));
5155     emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5156                             operands[1]));
5158     if (code == POST_DEC)
5159       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5161     DONE;
5162   }"
5165 (define_insn "*movdf_soft_insn"
5166   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
5167         (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
5168   "TARGET_ARM && TARGET_SOFT_FLOAT
5169   "
5170   "* return output_move_double (operands);"
5171   [(set_attr "length" "8,8,8")
5172    (set_attr "type" "*,load2,store2")
5173    (set_attr "pool_range" "1020")
5174    (set_attr "neg_pool_range" "1008")]
5177 ;;; ??? This should have alternatives for constants.
5178 ;;; ??? This was originally identical to the movdi_insn pattern.
5179 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5180 ;;; thumb_reorg with a memory reference.
5181 (define_insn "*thumb_movdf_insn"
5182   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5183         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5184   "TARGET_THUMB
5185    && (   register_operand (operands[0], DFmode)
5186        || register_operand (operands[1], DFmode))"
5187   "*
5188   switch (which_alternative)
5189     {
5190     default:
5191     case 0:
5192       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5193         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5194       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5195     case 1:
5196       return \"ldmia\\t%1, {%0, %H0}\";
5197     case 2:
5198       return \"stmia\\t%0, {%1, %H1}\";
5199     case 3:
5200       return thumb_load_double_from_address (operands);
5201     case 4:
5202       operands[2] = gen_rtx_MEM (SImode,
5203                                  plus_constant (XEXP (operands[0], 0), 4));
5204       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5205       return \"\";
5206     case 5:
5207       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5208         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5209       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5210     }
5211   "
5212   [(set_attr "length" "4,2,2,6,4,4")
5213    (set_attr "type" "*,load2,store2,load2,store2,*")
5214    (set_attr "pool_range" "*,*,*,1020,*,*")]
5217 ;; Vector Moves
5218 (define_expand "movv2si"
5219   [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5220         (match_operand:V2SI 1 "general_operand" ""))]
5221   "TARGET_REALLY_IWMMXT"
5225 (define_expand "movv4hi"
5226   [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5227         (match_operand:V4HI 1 "general_operand" ""))]
5228   "TARGET_REALLY_IWMMXT"
5232 (define_expand "movv8qi"
5233   [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5234         (match_operand:V8QI 1 "general_operand" ""))]
5235   "TARGET_REALLY_IWMMXT"
5240 ;; load- and store-multiple insns
5241 ;; The arm can load/store any set of registers, provided that they are in
5242 ;; ascending order; but that is beyond GCC so stick with what it knows.
5244 (define_expand "load_multiple"
5245   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5246                           (match_operand:SI 1 "" ""))
5247                      (use (match_operand:SI 2 "" ""))])]
5248   "TARGET_ARM"
5250   HOST_WIDE_INT offset = 0;
5252   /* Support only fixed point registers.  */
5253   if (GET_CODE (operands[2]) != CONST_INT
5254       || INTVAL (operands[2]) > 14
5255       || INTVAL (operands[2]) < 2
5256       || GET_CODE (operands[1]) != MEM
5257       || GET_CODE (operands[0]) != REG
5258       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5259       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5260     FAIL;
5262   operands[3]
5263     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5264                              force_reg (SImode, XEXP (operands[1], 0)),
5265                              TRUE, FALSE, operands[1], &offset);
5268 ;; Load multiple with write-back
5270 (define_insn "*ldmsi_postinc4"
5271   [(match_parallel 0 "load_multiple_operation"
5272     [(set (match_operand:SI 1 "s_register_operand" "=r")
5273           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5274                    (const_int 16)))
5275      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5276           (mem:SI (match_dup 2)))
5277      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5278           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5279      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5280           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5281      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5282           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5283   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5284   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5285   [(set_attr "type" "load4")
5286    (set_attr "predicable" "yes")]
5289 (define_insn "*ldmsi_postinc3"
5290   [(match_parallel 0 "load_multiple_operation"
5291     [(set (match_operand:SI 1 "s_register_operand" "=r")
5292           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5293                    (const_int 12)))
5294      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5295           (mem:SI (match_dup 2)))
5296      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5297           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5298      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5299           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5300   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5301   "ldm%?ia\\t%1!, {%3, %4, %5}"
5302   [(set_attr "type" "load3")
5303    (set_attr "predicable" "yes")]
5306 (define_insn "*ldmsi_postinc2"
5307   [(match_parallel 0 "load_multiple_operation"
5308     [(set (match_operand:SI 1 "s_register_operand" "=r")
5309           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5310                    (const_int 8)))
5311      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5312           (mem:SI (match_dup 2)))
5313      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5314           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5315   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5316   "ldm%?ia\\t%1!, {%3, %4}"
5317   [(set_attr "type" "load2")
5318    (set_attr "predicable" "yes")]
5321 ;; Ordinary load multiple
5323 (define_insn "*ldmsi4"
5324   [(match_parallel 0 "load_multiple_operation"
5325     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5326           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5327      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5328           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5329      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5330           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5331      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5332           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5333   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5334   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5335   [(set_attr "type" "load4")
5336    (set_attr "predicable" "yes")]
5339 (define_insn "*ldmsi3"
5340   [(match_parallel 0 "load_multiple_operation"
5341     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5342           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5343      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5344           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5345      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5346           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5347   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5348   "ldm%?ia\\t%1, {%2, %3, %4}"
5349   [(set_attr "type" "load3")
5350    (set_attr "predicable" "yes")]
5353 (define_insn "*ldmsi2"
5354   [(match_parallel 0 "load_multiple_operation"
5355     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5356           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5357      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5358           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5359   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5360   "ldm%?ia\\t%1, {%2, %3}"
5361   [(set_attr "type" "load2")
5362    (set_attr "predicable" "yes")]
5365 (define_expand "store_multiple"
5366   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5367                           (match_operand:SI 1 "" ""))
5368                      (use (match_operand:SI 2 "" ""))])]
5369   "TARGET_ARM"
5371   HOST_WIDE_INT offset = 0;
5373   /* Support only fixed point registers.  */
5374   if (GET_CODE (operands[2]) != CONST_INT
5375       || INTVAL (operands[2]) > 14
5376       || INTVAL (operands[2]) < 2
5377       || GET_CODE (operands[1]) != REG
5378       || GET_CODE (operands[0]) != MEM
5379       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5380       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5381     FAIL;
5383   operands[3]
5384     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5385                               force_reg (SImode, XEXP (operands[0], 0)),
5386                               TRUE, FALSE, operands[0], &offset);
5389 ;; Store multiple with write-back
5391 (define_insn "*stmsi_postinc4"
5392   [(match_parallel 0 "store_multiple_operation"
5393     [(set (match_operand:SI 1 "s_register_operand" "=r")
5394           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5395                    (const_int 16)))
5396      (set (mem:SI (match_dup 2))
5397           (match_operand:SI 3 "arm_hard_register_operand" ""))
5398      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5399           (match_operand:SI 4 "arm_hard_register_operand" ""))
5400      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5401           (match_operand:SI 5 "arm_hard_register_operand" ""))
5402      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5403           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5404   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5405   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5406   [(set_attr "predicable" "yes")
5407    (set_attr "type" "store4")]
5410 (define_insn "*stmsi_postinc3"
5411   [(match_parallel 0 "store_multiple_operation"
5412     [(set (match_operand:SI 1 "s_register_operand" "=r")
5413           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5414                    (const_int 12)))
5415      (set (mem:SI (match_dup 2))
5416           (match_operand:SI 3 "arm_hard_register_operand" ""))
5417      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5418           (match_operand:SI 4 "arm_hard_register_operand" ""))
5419      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5420           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5421   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5422   "stm%?ia\\t%1!, {%3, %4, %5}"
5423   [(set_attr "predicable" "yes")
5424    (set_attr "type" "store3")]
5427 (define_insn "*stmsi_postinc2"
5428   [(match_parallel 0 "store_multiple_operation"
5429     [(set (match_operand:SI 1 "s_register_operand" "=r")
5430           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5431                    (const_int 8)))
5432      (set (mem:SI (match_dup 2))
5433           (match_operand:SI 3 "arm_hard_register_operand" ""))
5434      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5435           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5436   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5437   "stm%?ia\\t%1!, {%3, %4}"
5438   [(set_attr "predicable" "yes")
5439    (set_attr "type" "store2")]
5442 ;; Ordinary store multiple
5444 (define_insn "*stmsi4"
5445   [(match_parallel 0 "store_multiple_operation"
5446     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5447           (match_operand:SI 2 "arm_hard_register_operand" ""))
5448      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5449           (match_operand:SI 3 "arm_hard_register_operand" ""))
5450      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5451           (match_operand:SI 4 "arm_hard_register_operand" ""))
5452      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5453           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5454   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5455   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5456   [(set_attr "predicable" "yes")
5457    (set_attr "type" "store4")]
5460 (define_insn "*stmsi3"
5461   [(match_parallel 0 "store_multiple_operation"
5462     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5463           (match_operand:SI 2 "arm_hard_register_operand" ""))
5464      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5465           (match_operand:SI 3 "arm_hard_register_operand" ""))
5466      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5467           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5468   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5469   "stm%?ia\\t%1, {%2, %3, %4}"
5470   [(set_attr "predicable" "yes")
5471    (set_attr "type" "store3")]
5474 (define_insn "*stmsi2"
5475   [(match_parallel 0 "store_multiple_operation"
5476     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5477           (match_operand:SI 2 "arm_hard_register_operand" ""))
5478      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5479           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5480   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5481   "stm%?ia\\t%1, {%2, %3}"
5482   [(set_attr "predicable" "yes")
5483    (set_attr "type" "store2")]
5486 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5487 ;; We could let this apply for blocks of less than this, but it clobbers so
5488 ;; many registers that there is then probably a better way.
5490 (define_expand "movmemqi"
5491   [(match_operand:BLK 0 "general_operand" "")
5492    (match_operand:BLK 1 "general_operand" "")
5493    (match_operand:SI 2 "const_int_operand" "")
5494    (match_operand:SI 3 "const_int_operand" "")]
5495   "TARGET_EITHER"
5496   "
5497   if (TARGET_ARM)
5498     {
5499       if (arm_gen_movmemqi (operands))
5500         DONE;
5501       FAIL;
5502     }
5503   else /* TARGET_THUMB */
5504     {
5505       if (   INTVAL (operands[3]) != 4
5506           || INTVAL (operands[2]) > 48)
5507         FAIL;
5509       thumb_expand_movmemqi (operands);
5510       DONE;
5511     }
5512   "
5515 ;; Thumb block-move insns
5517 (define_insn "movmem12b"
5518   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5519         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5520    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5521         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5522    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5523         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5524    (set (match_operand:SI 0 "register_operand" "=l")
5525         (plus:SI (match_dup 2) (const_int 12)))
5526    (set (match_operand:SI 1 "register_operand" "=l")
5527         (plus:SI (match_dup 3) (const_int 12)))
5528    (clobber (match_scratch:SI 4 "=&l"))
5529    (clobber (match_scratch:SI 5 "=&l"))
5530    (clobber (match_scratch:SI 6 "=&l"))]
5531   "TARGET_THUMB"
5532   "* return thumb_output_move_mem_multiple (3, operands);"
5533   [(set_attr "length" "4")
5534    ; This isn't entirely accurate...  It loads as well, but in terms of
5535    ; scheduling the following insn it is better to consider it as a store
5536    (set_attr "type" "store3")]
5539 (define_insn "movmem8b"
5540   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5541         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5542    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5543         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5544    (set (match_operand:SI 0 "register_operand" "=l")
5545         (plus:SI (match_dup 2) (const_int 8)))
5546    (set (match_operand:SI 1 "register_operand" "=l")
5547         (plus:SI (match_dup 3) (const_int 8)))
5548    (clobber (match_scratch:SI 4 "=&l"))
5549    (clobber (match_scratch:SI 5 "=&l"))]
5550   "TARGET_THUMB"
5551   "* return thumb_output_move_mem_multiple (2, operands);"
5552   [(set_attr "length" "4")
5553    ; This isn't entirely accurate...  It loads as well, but in terms of
5554    ; scheduling the following insn it is better to consider it as a store
5555    (set_attr "type" "store2")]
5560 ;; Compare & branch insns
5561 ;; The range calculations are based as follows:
5562 ;; For forward branches, the address calculation returns the address of
5563 ;; the next instruction.  This is 2 beyond the branch instruction.
5564 ;; For backward branches, the address calculation returns the address of
5565 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5566 ;; instruction for the shortest sequence, and 4 before the branch instruction
5567 ;; if we have to jump around an unconditional branch.
5568 ;; To the basic branch range the PC offset must be added (this is +4).
5569 ;; So for forward branches we have 
5570 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5571 ;; And for backward branches we have 
5572 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5574 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5575 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5577 (define_expand "cbranchsi4"
5578   [(set (pc) (if_then_else
5579               (match_operator 0 "arm_comparison_operator"
5580                [(match_operand:SI 1 "s_register_operand" "")
5581                 (match_operand:SI 2 "nonmemory_operand" "")])
5582               (label_ref (match_operand 3 "" ""))
5583               (pc)))]
5584   "TARGET_THUMB"
5585   "
5586   if (thumb_cmpneg_operand (operands[2], SImode))
5587     {
5588       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5589                                               operands[3], operands[0]));
5590       DONE;
5591     }
5592   if (!thumb_cmp_operand (operands[2], SImode))
5593     operands[2] = force_reg (SImode, operands[2]);
5594   ")
5596 (define_insn "*cbranchsi4_insn"
5597   [(set (pc) (if_then_else
5598               (match_operator 0 "arm_comparison_operator"
5599                [(match_operand:SI 1 "s_register_operand" "l,*h")
5600                 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5601               (label_ref (match_operand 3 "" ""))
5602               (pc)))]
5603   "TARGET_THUMB"
5604   "*
5605   output_asm_insn (\"cmp\\t%1, %2\", operands);
5607   switch (get_attr_length (insn))
5608     {
5609     case 4:  return \"b%d0\\t%l3\";
5610     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5611     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5612     }
5613   "
5614   [(set (attr "far_jump")
5615         (if_then_else
5616             (eq_attr "length" "8")
5617             (const_string "yes")
5618             (const_string "no")))
5619    (set (attr "length") 
5620         (if_then_else
5621             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5622                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5623             (const_int 4)
5624             (if_then_else
5625                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5626                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5627                 (const_int 6)
5628                 (const_int 8))))]
5631 (define_insn "cbranchsi4_scratch"
5632   [(set (pc) (if_then_else
5633               (match_operator 4 "arm_comparison_operator"
5634                [(match_operand:SI 1 "s_register_operand" "l,0")
5635                 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5636               (label_ref (match_operand 3 "" ""))
5637               (pc)))
5638    (clobber (match_scratch:SI 0 "=l,l"))]
5639   "TARGET_THUMB"
5640   "*
5641   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5643   switch (get_attr_length (insn))
5644     {
5645     case 4:  return \"b%d4\\t%l3\";
5646     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5647     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5648     }
5649   "
5650   [(set (attr "far_jump")
5651         (if_then_else
5652             (eq_attr "length" "8")
5653             (const_string "yes")
5654             (const_string "no")))
5655    (set (attr "length") 
5656         (if_then_else
5657             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5658                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5659             (const_int 4)
5660             (if_then_else
5661                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5662                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5663                 (const_int 6)
5664                 (const_int 8))))]
5666 (define_insn "*movsi_cbranchsi4"
5667   [(set (pc)
5668         (if_then_else
5669          (match_operator 3 "arm_comparison_operator"
5670           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5671            (const_int 0)])
5672          (label_ref (match_operand 2 "" ""))
5673          (pc)))
5674    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5675         (match_dup 1))]
5676   "TARGET_THUMB"
5677   "*{
5678   if (which_alternative == 0)
5679     output_asm_insn (\"cmp\t%0, #0\", operands);
5680   else if (which_alternative == 1)
5681     output_asm_insn (\"sub\t%0, %1, #0\", operands);
5682   else
5683     {
5684       output_asm_insn (\"cmp\t%1, #0\", operands);
5685       if (which_alternative == 2)
5686         output_asm_insn (\"mov\t%0, %1\", operands);
5687       else
5688         output_asm_insn (\"str\t%1, %0\", operands);
5689     }
5690   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5691     {
5692     case 4:  return \"b%d3\\t%l2\";
5693     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5694     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5695     }
5696   }"
5697   [(set (attr "far_jump")
5698         (if_then_else
5699             (ior (and (gt (symbol_ref ("which_alternative"))
5700                           (const_int 1))
5701                       (eq_attr "length" "8"))
5702                  (eq_attr "length" "10"))
5703             (const_string "yes")
5704             (const_string "no")))
5705    (set (attr "length")
5706      (if_then_else
5707        (le (symbol_ref ("which_alternative"))
5708                        (const_int 1))
5709        (if_then_else
5710          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5711               (le (minus (match_dup 2) (pc)) (const_int 256)))
5712          (const_int 4)
5713          (if_then_else
5714            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5715                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5716            (const_int 6)
5717            (const_int 8)))
5718        (if_then_else
5719          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5720               (le (minus (match_dup 2) (pc)) (const_int 256)))
5721          (const_int 6)
5722          (if_then_else
5723            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5724                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5725            (const_int 8)
5726            (const_int 10)))))]
5729 (define_insn "*negated_cbranchsi4"
5730   [(set (pc)
5731         (if_then_else
5732          (match_operator 0 "arm_comparison_operator"
5733           [(match_operand:SI 1 "s_register_operand" "l")
5734            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5735          (label_ref (match_operand 3 "" ""))
5736          (pc)))]
5737   "TARGET_THUMB"
5738   "*
5739   output_asm_insn (\"cmn\\t%1, %2\", operands);
5740   switch (get_attr_length (insn))
5741     {
5742     case 4:  return \"b%d0\\t%l3\";
5743     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5744     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5745     }
5746   "
5747   [(set (attr "far_jump")
5748         (if_then_else
5749             (eq_attr "length" "8")
5750             (const_string "yes")
5751             (const_string "no")))
5752    (set (attr "length") 
5753         (if_then_else
5754             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5755                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5756             (const_int 4)
5757             (if_then_else
5758                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5759                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5760                 (const_int 6)
5761                 (const_int 8))))]
5764 (define_insn "*tbit_cbranch"
5765   [(set (pc)
5766         (if_then_else
5767          (match_operator 0 "equality_operator"
5768           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5769                             (const_int 1)
5770                             (match_operand:SI 2 "const_int_operand" "i"))
5771            (const_int 0)])
5772          (label_ref (match_operand 3 "" ""))
5773          (pc)))
5774    (clobber (match_scratch:SI 4 "=l"))]
5775   "TARGET_THUMB"
5776   "*
5777   {
5778   rtx op[3];
5779   op[0] = operands[4];
5780   op[1] = operands[1];
5781   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5783   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5784   switch (get_attr_length (insn))
5785     {
5786     case 4:  return \"b%d0\\t%l3\";
5787     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5788     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5789     }
5790   }"
5791   [(set (attr "far_jump")
5792         (if_then_else
5793             (eq_attr "length" "8")
5794             (const_string "yes")
5795             (const_string "no")))
5796    (set (attr "length") 
5797         (if_then_else
5798             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5799                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5800             (const_int 4)
5801             (if_then_else
5802                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5803                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5804                 (const_int 6)
5805                 (const_int 8))))]
5807   
5808 (define_insn "*tstsi3_cbranch"
5809   [(set (pc)
5810         (if_then_else
5811          (match_operator 3 "equality_operator"
5812           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5813                    (match_operand:SI 1 "s_register_operand" "l"))
5814            (const_int 0)])
5815          (label_ref (match_operand 2 "" ""))
5816          (pc)))]
5817   "TARGET_THUMB"
5818   "*
5819   {
5820   output_asm_insn (\"tst\\t%0, %1\", operands);
5821   switch (get_attr_length (insn))
5822     {
5823     case 4:  return \"b%d3\\t%l2\";
5824     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5825     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5826     }
5827   }"
5828   [(set (attr "far_jump")
5829         (if_then_else
5830             (eq_attr "length" "8")
5831             (const_string "yes")
5832             (const_string "no")))
5833    (set (attr "length") 
5834         (if_then_else
5835             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5836                  (le (minus (match_dup 2) (pc)) (const_int 256)))
5837             (const_int 4)
5838             (if_then_else
5839                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5840                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
5841                 (const_int 6)
5842                 (const_int 8))))]
5844   
5845 (define_insn "*andsi3_cbranch"
5846   [(set (pc)
5847         (if_then_else
5848          (match_operator 5 "equality_operator"
5849           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5850                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5851            (const_int 0)])
5852          (label_ref (match_operand 4 "" ""))
5853          (pc)))
5854    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5855         (and:SI (match_dup 2) (match_dup 3)))
5856    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5857   "TARGET_THUMB"
5858   "*
5859   {
5860   if (which_alternative == 0)
5861     output_asm_insn (\"and\\t%0, %3\", operands);
5862   else if (which_alternative == 1)
5863     {
5864       output_asm_insn (\"and\\t%1, %3\", operands);
5865       output_asm_insn (\"mov\\t%0, %1\", operands);
5866     }
5867   else
5868     {
5869       output_asm_insn (\"and\\t%1, %3\", operands);
5870       output_asm_insn (\"str\\t%1, %0\", operands);
5871     }
5873   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5874     {
5875     case 4:  return \"b%d5\\t%l4\";
5876     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5877     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5878     }
5879   }"
5880   [(set (attr "far_jump")
5881         (if_then_else
5882             (ior (and (eq (symbol_ref ("which_alternative"))
5883                           (const_int 0))
5884                       (eq_attr "length" "8"))
5885                  (eq_attr "length" "10"))
5886             (const_string "yes")
5887             (const_string "no")))
5888    (set (attr "length")
5889      (if_then_else
5890        (eq (symbol_ref ("which_alternative"))
5891                        (const_int 0))
5892        (if_then_else
5893          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5894               (le (minus (match_dup 4) (pc)) (const_int 256)))
5895          (const_int 4)
5896          (if_then_else
5897            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5898                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5899            (const_int 6)
5900            (const_int 8)))
5901        (if_then_else
5902          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5903               (le (minus (match_dup 4) (pc)) (const_int 256)))
5904          (const_int 6)
5905          (if_then_else
5906            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5907                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5908            (const_int 8)
5909            (const_int 10)))))]
5912 (define_insn "*orrsi3_cbranch_scratch"
5913   [(set (pc)
5914         (if_then_else
5915          (match_operator 4 "equality_operator"
5916           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
5917                    (match_operand:SI 2 "s_register_operand" "l"))
5918            (const_int 0)])
5919          (label_ref (match_operand 3 "" ""))
5920          (pc)))
5921    (clobber (match_scratch:SI 0 "=l"))]
5922   "TARGET_THUMB"
5923   "*
5924   {
5925   output_asm_insn (\"orr\\t%0, %2\", operands);
5926   switch (get_attr_length (insn))
5927     {
5928     case 4:  return \"b%d4\\t%l3\";
5929     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5930     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5931     }
5932   }"
5933   [(set (attr "far_jump")
5934         (if_then_else
5935             (eq_attr "length" "8")
5936             (const_string "yes")
5937             (const_string "no")))
5938    (set (attr "length") 
5939         (if_then_else
5940             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5941                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5942             (const_int 4)
5943             (if_then_else
5944                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5945                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5946                 (const_int 6)
5947                 (const_int 8))))]
5949   
5950 (define_insn "*orrsi3_cbranch"
5951   [(set (pc)
5952         (if_then_else
5953          (match_operator 5 "equality_operator"
5954           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5955                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5956            (const_int 0)])
5957          (label_ref (match_operand 4 "" ""))
5958          (pc)))
5959    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5960         (ior:SI (match_dup 2) (match_dup 3)))
5961    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5962   "TARGET_THUMB"
5963   "*
5964   {
5965   if (which_alternative == 0)
5966     output_asm_insn (\"orr\\t%0, %3\", operands);
5967   else if (which_alternative == 1)
5968     {
5969       output_asm_insn (\"orr\\t%1, %3\", operands);
5970       output_asm_insn (\"mov\\t%0, %1\", operands);
5971     }
5972   else
5973     {
5974       output_asm_insn (\"orr\\t%1, %3\", operands);
5975       output_asm_insn (\"str\\t%1, %0\", operands);
5976     }
5978   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5979     {
5980     case 4:  return \"b%d5\\t%l4\";
5981     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5982     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5983     }
5984   }"
5985   [(set (attr "far_jump")
5986         (if_then_else
5987             (ior (and (eq (symbol_ref ("which_alternative"))
5988                           (const_int 0))
5989                       (eq_attr "length" "8"))
5990                  (eq_attr "length" "10"))
5991             (const_string "yes")
5992             (const_string "no")))
5993    (set (attr "length")
5994      (if_then_else
5995        (eq (symbol_ref ("which_alternative"))
5996                        (const_int 0))
5997        (if_then_else
5998          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5999               (le (minus (match_dup 4) (pc)) (const_int 256)))
6000          (const_int 4)
6001          (if_then_else
6002            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6003                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6004            (const_int 6)
6005            (const_int 8)))
6006        (if_then_else
6007          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6008               (le (minus (match_dup 4) (pc)) (const_int 256)))
6009          (const_int 6)
6010          (if_then_else
6011            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6012                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6013            (const_int 8)
6014            (const_int 10)))))]
6017 (define_insn "*xorsi3_cbranch_scratch"
6018   [(set (pc)
6019         (if_then_else
6020          (match_operator 4 "equality_operator"
6021           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6022                    (match_operand:SI 2 "s_register_operand" "l"))
6023            (const_int 0)])
6024          (label_ref (match_operand 3 "" ""))
6025          (pc)))
6026    (clobber (match_scratch:SI 0 "=l"))]
6027   "TARGET_THUMB"
6028   "*
6029   {
6030   output_asm_insn (\"eor\\t%0, %2\", operands);
6031   switch (get_attr_length (insn))
6032     {
6033     case 4:  return \"b%d4\\t%l3\";
6034     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6035     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6036     }
6037   }"
6038   [(set (attr "far_jump")
6039         (if_then_else
6040             (eq_attr "length" "8")
6041             (const_string "yes")
6042             (const_string "no")))
6043    (set (attr "length") 
6044         (if_then_else
6045             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6046                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6047             (const_int 4)
6048             (if_then_else
6049                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6050                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6051                 (const_int 6)
6052                 (const_int 8))))]
6054   
6055 (define_insn "*xorsi3_cbranch"
6056   [(set (pc)
6057         (if_then_else
6058          (match_operator 5 "equality_operator"
6059           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6060                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6061            (const_int 0)])
6062          (label_ref (match_operand 4 "" ""))
6063          (pc)))
6064    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6065         (xor:SI (match_dup 2) (match_dup 3)))
6066    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6067   "TARGET_THUMB"
6068   "*
6069   {
6070   if (which_alternative == 0)
6071     output_asm_insn (\"eor\\t%0, %3\", operands);
6072   else if (which_alternative == 1)
6073     {
6074       output_asm_insn (\"eor\\t%1, %3\", operands);
6075       output_asm_insn (\"mov\\t%0, %1\", operands);
6076     }
6077   else
6078     {
6079       output_asm_insn (\"eor\\t%1, %3\", operands);
6080       output_asm_insn (\"str\\t%1, %0\", operands);
6081     }
6083   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6084     {
6085     case 4:  return \"b%d5\\t%l4\";
6086     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6087     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6088     }
6089   }"
6090   [(set (attr "far_jump")
6091         (if_then_else
6092             (ior (and (eq (symbol_ref ("which_alternative"))
6093                           (const_int 0))
6094                       (eq_attr "length" "8"))
6095                  (eq_attr "length" "10"))
6096             (const_string "yes")
6097             (const_string "no")))
6098    (set (attr "length")
6099      (if_then_else
6100        (eq (symbol_ref ("which_alternative"))
6101                        (const_int 0))
6102        (if_then_else
6103          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6104               (le (minus (match_dup 4) (pc)) (const_int 256)))
6105          (const_int 4)
6106          (if_then_else
6107            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6108                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6109            (const_int 6)
6110            (const_int 8)))
6111        (if_then_else
6112          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6113               (le (minus (match_dup 4) (pc)) (const_int 256)))
6114          (const_int 6)
6115          (if_then_else
6116            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6117                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6118            (const_int 8)
6119            (const_int 10)))))]
6122 (define_insn "*bicsi3_cbranch_scratch"
6123   [(set (pc)
6124         (if_then_else
6125          (match_operator 4 "equality_operator"
6126           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6127                    (match_operand:SI 1 "s_register_operand" "0"))
6128            (const_int 0)])
6129          (label_ref (match_operand 3 "" ""))
6130          (pc)))
6131    (clobber (match_scratch:SI 0 "=l"))]
6132   "TARGET_THUMB"
6133   "*
6134   {
6135   output_asm_insn (\"bic\\t%0, %2\", operands);
6136   switch (get_attr_length (insn))
6137     {
6138     case 4:  return \"b%d4\\t%l3\";
6139     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6140     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6141     }
6142   }"
6143   [(set (attr "far_jump")
6144         (if_then_else
6145             (eq_attr "length" "8")
6146             (const_string "yes")
6147             (const_string "no")))
6148    (set (attr "length") 
6149         (if_then_else
6150             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6151                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6152             (const_int 4)
6153             (if_then_else
6154                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6155                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6156                 (const_int 6)
6157                 (const_int 8))))]
6159   
6160 (define_insn "*bicsi3_cbranch"
6161   [(set (pc)
6162         (if_then_else
6163          (match_operator 5 "equality_operator"
6164           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6165                    (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6166            (const_int 0)])
6167          (label_ref (match_operand 4 "" ""))
6168          (pc)))
6169    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6170         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6171    (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6172   "TARGET_THUMB"
6173   "*
6174   {
6175   if (which_alternative == 0)
6176     output_asm_insn (\"bic\\t%0, %3\", operands);
6177   else if (which_alternative <= 2)
6178     {
6179       output_asm_insn (\"bic\\t%1, %3\", operands);
6180       /* It's ok if OP0 is a lo-reg, even though the mov will set the
6181          conditions again, since we're only testing for equality.  */
6182       output_asm_insn (\"mov\\t%0, %1\", operands);
6183     }
6184   else
6185     {
6186       output_asm_insn (\"bic\\t%1, %3\", operands);
6187       output_asm_insn (\"str\\t%1, %0\", operands);
6188     }
6190   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6191     {
6192     case 4:  return \"b%d5\\t%l4\";
6193     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6194     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6195     }
6196   }"
6197   [(set (attr "far_jump")
6198         (if_then_else
6199             (ior (and (eq (symbol_ref ("which_alternative"))
6200                           (const_int 0))
6201                       (eq_attr "length" "8"))
6202                  (eq_attr "length" "10"))
6203             (const_string "yes")
6204             (const_string "no")))
6205    (set (attr "length")
6206      (if_then_else
6207        (eq (symbol_ref ("which_alternative"))
6208                        (const_int 0))
6209        (if_then_else
6210          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6211               (le (minus (match_dup 4) (pc)) (const_int 256)))
6212          (const_int 4)
6213          (if_then_else
6214            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6215                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6216            (const_int 6)
6217            (const_int 8)))
6218        (if_then_else
6219          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6220               (le (minus (match_dup 4) (pc)) (const_int 256)))
6221          (const_int 6)
6222          (if_then_else
6223            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6224                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6225            (const_int 8)
6226            (const_int 10)))))]
6229 (define_insn "*cbranchne_decr1"
6230   [(set (pc)
6231         (if_then_else (match_operator 3 "equality_operator"
6232                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6233                         (const_int 0)])
6234                       (label_ref (match_operand 4 "" ""))
6235                       (pc)))
6236    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6237         (plus:SI (match_dup 2) (const_int -1)))
6238    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6239   "TARGET_THUMB"
6240   "*
6241    {
6242      rtx cond[2];
6243      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6244                                 ? GEU : LTU),
6245                                VOIDmode, operands[2], const1_rtx);
6246      cond[1] = operands[4];
6248      if (which_alternative == 0)
6249        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6250      else if (which_alternative == 1)
6251        {
6252          /* We must provide an alternative for a hi reg because reload 
6253             cannot handle output reloads on a jump instruction, but we
6254             can't subtract into that.  Fortunately a mov from lo to hi
6255             does not clobber the condition codes.  */
6256          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6257          output_asm_insn (\"mov\\t%0, %1\", operands);
6258        }
6259      else
6260        {
6261          /* Similarly, but the target is memory.  */
6262          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6263          output_asm_insn (\"str\\t%1, %0\", operands);
6264        }
6266      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6267        {
6268          case 4:
6269            output_asm_insn (\"b%d0\\t%l1\", cond);
6270            return \"\";
6271          case 6:
6272            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6273            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6274          default:
6275            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6276            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6277        }
6278    }
6279   "
6280   [(set (attr "far_jump")
6281         (if_then_else
6282             (ior (and (eq (symbol_ref ("which_alternative"))
6283                           (const_int 0))
6284                       (eq_attr "length" "8"))
6285                  (eq_attr "length" "10"))
6286             (const_string "yes")
6287             (const_string "no")))
6288    (set_attr_alternative "length"
6289       [
6290        ;; Alternative 0
6291        (if_then_else
6292          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6293               (le (minus (match_dup 4) (pc)) (const_int 256)))
6294          (const_int 4)
6295          (if_then_else
6296            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6297                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6298            (const_int 6)
6299            (const_int 8)))
6300        ;; Alternative 1
6301        (if_then_else
6302          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6303               (le (minus (match_dup 4) (pc)) (const_int 256)))
6304          (const_int 6)
6305          (if_then_else
6306            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6307                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6308            (const_int 8)
6309            (const_int 10)))
6310        ;; Alternative 2
6311        (if_then_else
6312          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6313               (le (minus (match_dup 4) (pc)) (const_int 256)))
6314          (const_int 6)
6315          (if_then_else
6316            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6317                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6318            (const_int 8)
6319            (const_int 10)))
6320        ;; Alternative 3
6321        (if_then_else
6322          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6323               (le (minus (match_dup 4) (pc)) (const_int 256)))
6324          (const_int 6)
6325          (if_then_else
6326            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6327                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6328            (const_int 8)
6329            (const_int 10)))])]
6332 (define_insn "*addsi3_cbranch"
6333   [(set (pc)
6334         (if_then_else
6335          (match_operator 4 "comparison_operator"
6336           [(plus:SI
6337             (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6338             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6339            (const_int 0)])
6340          (label_ref (match_operand 5 "" ""))
6341          (pc)))
6342    (set
6343     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6344     (plus:SI (match_dup 2) (match_dup 3)))
6345    (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6346   "TARGET_THUMB
6347    && (GET_CODE (operands[4]) == EQ
6348        || GET_CODE (operands[4]) == NE
6349        || GET_CODE (operands[4]) == GE
6350        || GET_CODE (operands[4]) == LT)"
6351   "*
6352    {
6353      rtx cond[3];
6355      
6356      cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6357      cond[1] = operands[2];
6358      cond[2] = operands[3];
6360      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6361        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6362      else
6363        output_asm_insn (\"add\\t%0, %1, %2\", cond);
6365      if (which_alternative >= 3
6366          && which_alternative < 4)
6367        output_asm_insn (\"mov\\t%0, %1\", operands);
6368      else if (which_alternative >= 4)
6369        output_asm_insn (\"str\\t%1, %0\", operands);
6371      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6372        {
6373          case 4:
6374            return \"b%d4\\t%l5\";
6375          case 6:
6376            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6377          default:
6378            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6379        }
6380    }
6381   "
6382   [(set (attr "far_jump")
6383         (if_then_else
6384             (ior (and (lt (symbol_ref ("which_alternative"))
6385                           (const_int 3))
6386                       (eq_attr "length" "8"))
6387                  (eq_attr "length" "10"))
6388             (const_string "yes")
6389             (const_string "no")))
6390    (set (attr "length")
6391      (if_then_else
6392        (lt (symbol_ref ("which_alternative"))
6393                        (const_int 3))
6394        (if_then_else
6395          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6396               (le (minus (match_dup 5) (pc)) (const_int 256)))
6397          (const_int 4)
6398          (if_then_else
6399            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6400                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6401            (const_int 6)
6402            (const_int 8)))
6403        (if_then_else
6404          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6405               (le (minus (match_dup 5) (pc)) (const_int 256)))
6406          (const_int 6)
6407          (if_then_else
6408            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6409                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6410            (const_int 8)
6411            (const_int 10)))))]
6414 (define_insn "*addsi3_cbranch_scratch"
6415   [(set (pc)
6416         (if_then_else
6417          (match_operator 3 "comparison_operator"
6418           [(plus:SI
6419             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6420             (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
6421            (const_int 0)])
6422          (label_ref (match_operand 4 "" ""))
6423          (pc)))
6424    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6425   "TARGET_THUMB
6426    && (GET_CODE (operands[3]) == EQ
6427        || GET_CODE (operands[3]) == NE
6428        || GET_CODE (operands[3]) == GE
6429        || GET_CODE (operands[3]) == LT)"
6430   "*
6431    {
6432      switch (which_alternative)
6433        {
6434        case 0:
6435          output_asm_insn (\"cmp\t%1, #%n2\", operands);
6436          break;
6437        case 1:
6438          output_asm_insn (\"cmn\t%1, %2\", operands);
6439          break;
6440        case 2:
6441          if (INTVAL (operands[2]) < 0)
6442            output_asm_insn (\"sub\t%0, %1, %2\", operands);
6443          else
6444            output_asm_insn (\"add\t%0, %1, %2\", operands);
6445          break;
6446        case 3:
6447          if (INTVAL (operands[2]) < 0)
6448            output_asm_insn (\"sub\t%0, %0, %2\", operands);
6449          else
6450            output_asm_insn (\"add\t%0, %0, %2\", operands);
6451          break;
6452        }
6454      switch (get_attr_length (insn))
6455        {
6456          case 4:
6457            return \"b%d3\\t%l4\";
6458          case 6:
6459            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6460          default:
6461            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6462        }
6463    }
6464   "
6465   [(set (attr "far_jump")
6466         (if_then_else
6467             (eq_attr "length" "8")
6468             (const_string "yes")
6469             (const_string "no")))
6470    (set (attr "length")
6471        (if_then_else
6472          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6473               (le (minus (match_dup 4) (pc)) (const_int 256)))
6474          (const_int 4)
6475          (if_then_else
6476            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6477                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6478            (const_int 6)
6479            (const_int 8))))]
6482 (define_insn "*subsi3_cbranch"
6483   [(set (pc)
6484         (if_then_else
6485          (match_operator 4 "comparison_operator"
6486           [(minus:SI
6487             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6488             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6489            (const_int 0)])
6490          (label_ref (match_operand 5 "" ""))
6491          (pc)))
6492    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6493         (minus:SI (match_dup 2) (match_dup 3)))
6494    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6495   "TARGET_THUMB
6496    && (GET_CODE (operands[4]) == EQ
6497        || GET_CODE (operands[4]) == NE
6498        || GET_CODE (operands[4]) == GE
6499        || GET_CODE (operands[4]) == LT)"
6500   "*
6501    {
6502      if (which_alternative == 0)
6503        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6504      else if (which_alternative == 1)
6505        {
6506          /* We must provide an alternative for a hi reg because reload 
6507             cannot handle output reloads on a jump instruction, but we
6508             can't subtract into that.  Fortunately a mov from lo to hi
6509             does not clobber the condition codes.  */
6510          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6511          output_asm_insn (\"mov\\t%0, %1\", operands);
6512        }
6513      else
6514        {
6515          /* Similarly, but the target is memory.  */
6516          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6517          output_asm_insn (\"str\\t%1, %0\", operands);
6518        }
6520      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6521        {
6522          case 4:
6523            return \"b%d4\\t%l5\";
6524          case 6:
6525            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6526          default:
6527            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6528        }
6529    }
6530   "
6531   [(set (attr "far_jump")
6532         (if_then_else
6533             (ior (and (eq (symbol_ref ("which_alternative"))
6534                           (const_int 0))
6535                       (eq_attr "length" "8"))
6536                  (eq_attr "length" "10"))
6537             (const_string "yes")
6538             (const_string "no")))
6539    (set (attr "length")
6540      (if_then_else
6541        (eq (symbol_ref ("which_alternative"))
6542                        (const_int 0))
6543        (if_then_else
6544          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6545               (le (minus (match_dup 5) (pc)) (const_int 256)))
6546          (const_int 4)
6547          (if_then_else
6548            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6549                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6550            (const_int 6)
6551            (const_int 8)))
6552        (if_then_else
6553          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6554               (le (minus (match_dup 5) (pc)) (const_int 256)))
6555          (const_int 6)
6556          (if_then_else
6557            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6558                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6559            (const_int 8)
6560            (const_int 10)))))]
6563 (define_insn "*subsi3_cbranch_scratch"
6564   [(set (pc)
6565         (if_then_else
6566          (match_operator 0 "arm_comparison_operator"
6567           [(minus:SI (match_operand:SI 1 "register_operand" "l")
6568                      (match_operand:SI 2 "nonmemory_operand" "l"))
6569            (const_int 0)])
6570          (label_ref (match_operand 3 "" ""))
6571          (pc)))]
6572   "TARGET_THUMB
6573    && (GET_CODE (operands[0]) == EQ
6574        || GET_CODE (operands[0]) == NE
6575        || GET_CODE (operands[0]) == GE
6576        || GET_CODE (operands[0]) == LT)"
6577   "*
6578   output_asm_insn (\"cmp\\t%1, %2\", operands);
6579   switch (get_attr_length (insn))
6580     {
6581     case 4:  return \"b%d0\\t%l3\";
6582     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6583     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6584     }
6585   "
6586   [(set (attr "far_jump")
6587         (if_then_else
6588             (eq_attr "length" "8")
6589             (const_string "yes")
6590             (const_string "no")))
6591    (set (attr "length") 
6592         (if_then_else
6593             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6594                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6595             (const_int 4)
6596             (if_then_else
6597                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6598                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6599                 (const_int 6)
6600                 (const_int 8))))]
6603 ;; Comparison and test insns
6605 (define_expand "cmpsi"
6606   [(match_operand:SI 0 "s_register_operand" "")
6607    (match_operand:SI 1 "arm_add_operand" "")]
6608   "TARGET_ARM"
6609   "{
6610     arm_compare_op0 = operands[0];
6611     arm_compare_op1 = operands[1];
6612     DONE;
6613   }"
6616 (define_expand "cmpsf"
6617   [(match_operand:SF 0 "s_register_operand" "")
6618    (match_operand:SF 1 "arm_float_compare_operand" "")]
6619   "TARGET_ARM && TARGET_HARD_FLOAT"
6620   "
6621   arm_compare_op0 = operands[0];
6622   arm_compare_op1 = operands[1];
6623   DONE;
6624   "
6627 (define_expand "cmpdf"
6628   [(match_operand:DF 0 "s_register_operand" "")
6629    (match_operand:DF 1 "arm_float_compare_operand" "")]
6630   "TARGET_ARM && TARGET_HARD_FLOAT"
6631   "
6632   arm_compare_op0 = operands[0];
6633   arm_compare_op1 = operands[1];
6634   DONE;
6635   "
6638 (define_insn "*arm_cmpsi_insn"
6639   [(set (reg:CC CC_REGNUM)
6640         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6641                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
6642   "TARGET_ARM"
6643   "@
6644    cmp%?\\t%0, %1
6645    cmn%?\\t%0, #%n1"
6646   [(set_attr "conds" "set")]
6649 (define_insn "*cmpsi_shiftsi"
6650   [(set (reg:CC CC_REGNUM)
6651         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
6652                     (match_operator:SI  3 "shift_operator"
6653                      [(match_operand:SI 1 "s_register_operand" "r")
6654                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
6655   "TARGET_ARM"
6656   "cmp%?\\t%0, %1%S3"
6657   [(set_attr "conds" "set")
6658    (set_attr "shift" "1")
6659    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6660                       (const_string "alu_shift")
6661                       (const_string "alu_shift_reg")))]
6664 (define_insn "*cmpsi_shiftsi_swp"
6665   [(set (reg:CC_SWP CC_REGNUM)
6666         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6667                          [(match_operand:SI 1 "s_register_operand" "r")
6668                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
6669                         (match_operand:SI 0 "s_register_operand" "r")))]
6670   "TARGET_ARM"
6671   "cmp%?\\t%0, %1%S3"
6672   [(set_attr "conds" "set")
6673    (set_attr "shift" "1")
6674    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6675                       (const_string "alu_shift")
6676                       (const_string "alu_shift_reg")))]
6679 (define_insn "*cmpsi_neg_shiftsi"
6680   [(set (reg:CC CC_REGNUM)
6681         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6682                     (neg:SI (match_operator:SI 3 "shift_operator"
6683                              [(match_operand:SI 1 "s_register_operand" "r")
6684                               (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
6685   "TARGET_ARM"
6686   "cmn%?\\t%0, %1%S3"
6687   [(set_attr "conds" "set")
6688    (set_attr "shift" "1")
6689    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6690                       (const_string "alu_shift")
6691                       (const_string "alu_shift_reg")))]
6694 ;; Cirrus SF compare instruction
6695 (define_insn "*cirrus_cmpsf"
6696   [(set (reg:CCFP CC_REGNUM)
6697         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6698                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
6699   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6700   "cfcmps%?\\tr15, %V0, %V1"
6701   [(set_attr "type"   "mav_farith")
6702    (set_attr "cirrus" "compare")]
6705 ;; Cirrus DF compare instruction
6706 (define_insn "*cirrus_cmpdf"
6707   [(set (reg:CCFP CC_REGNUM)
6708         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6709                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
6710   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6711   "cfcmpd%?\\tr15, %V0, %V1"
6712   [(set_attr "type"   "mav_farith")
6713    (set_attr "cirrus" "compare")]
6716 ;; Cirrus DI compare instruction
6717 (define_expand "cmpdi"
6718   [(match_operand:DI 0 "cirrus_fp_register" "")
6719    (match_operand:DI 1 "cirrus_fp_register" "")]
6720   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6721   "{
6722      arm_compare_op0 = operands[0];
6723      arm_compare_op1 = operands[1];
6724      DONE;
6725    }")
6727 (define_insn "*cirrus_cmpdi"
6728   [(set (reg:CC CC_REGNUM)
6729         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6730                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
6731   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6732   "cfcmp64%?\\tr15, %V0, %V1"
6733   [(set_attr "type"   "mav_farith")
6734    (set_attr "cirrus" "compare")]
6737 ; This insn allows redundant compares to be removed by cse, nothing should
6738 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6739 ; is deleted later on. The match_dup will match the mode here, so that
6740 ; mode changes of the condition codes aren't lost by this even though we don't
6741 ; specify what they are.
6743 (define_insn "*deleted_compare"
6744   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6745   "TARGET_ARM"
6746   "\\t%@ deleted compare"
6747   [(set_attr "conds" "set")
6748    (set_attr "length" "0")]
6752 ;; Conditional branch insns
6754 (define_expand "beq"
6755   [(set (pc)
6756         (if_then_else (eq (match_dup 1) (const_int 0))
6757                       (label_ref (match_operand 0 "" ""))
6758                       (pc)))]
6759   "TARGET_ARM"
6760   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6763 (define_expand "bne"
6764   [(set (pc)
6765         (if_then_else (ne (match_dup 1) (const_int 0))
6766                       (label_ref (match_operand 0 "" ""))
6767                       (pc)))]
6768   "TARGET_ARM"
6769   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6772 (define_expand "bgt"
6773   [(set (pc)
6774         (if_then_else (gt (match_dup 1) (const_int 0))
6775                       (label_ref (match_operand 0 "" ""))
6776                       (pc)))]
6777   "TARGET_ARM"
6778   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6781 (define_expand "ble"
6782   [(set (pc)
6783         (if_then_else (le (match_dup 1) (const_int 0))
6784                       (label_ref (match_operand 0 "" ""))
6785                       (pc)))]
6786   "TARGET_ARM"
6787   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6790 (define_expand "bge"
6791   [(set (pc)
6792         (if_then_else (ge (match_dup 1) (const_int 0))
6793                       (label_ref (match_operand 0 "" ""))
6794                       (pc)))]
6795   "TARGET_ARM"
6796   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6799 (define_expand "blt"
6800   [(set (pc)
6801         (if_then_else (lt (match_dup 1) (const_int 0))
6802                       (label_ref (match_operand 0 "" ""))
6803                       (pc)))]
6804   "TARGET_ARM"
6805   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6808 (define_expand "bgtu"
6809   [(set (pc)
6810         (if_then_else (gtu (match_dup 1) (const_int 0))
6811                       (label_ref (match_operand 0 "" ""))
6812                       (pc)))]
6813   "TARGET_ARM"
6814   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6817 (define_expand "bleu"
6818   [(set (pc)
6819         (if_then_else (leu (match_dup 1) (const_int 0))
6820                       (label_ref (match_operand 0 "" ""))
6821                       (pc)))]
6822   "TARGET_ARM"
6823   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6826 (define_expand "bgeu"
6827   [(set (pc)
6828         (if_then_else (geu (match_dup 1) (const_int 0))
6829                       (label_ref (match_operand 0 "" ""))
6830                       (pc)))]
6831   "TARGET_ARM"
6832   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6835 (define_expand "bltu"
6836   [(set (pc)
6837         (if_then_else (ltu (match_dup 1) (const_int 0))
6838                       (label_ref (match_operand 0 "" ""))
6839                       (pc)))]
6840   "TARGET_ARM"
6841   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6844 (define_expand "bunordered"
6845   [(set (pc)
6846         (if_then_else (unordered (match_dup 1) (const_int 0))
6847                       (label_ref (match_operand 0 "" ""))
6848                       (pc)))]
6849   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6850   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6851                                       arm_compare_op1);"
6854 (define_expand "bordered"
6855   [(set (pc)
6856         (if_then_else (ordered (match_dup 1) (const_int 0))
6857                       (label_ref (match_operand 0 "" ""))
6858                       (pc)))]
6859   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6860   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6861                                       arm_compare_op1);"
6864 (define_expand "bungt"
6865   [(set (pc)
6866         (if_then_else (ungt (match_dup 1) (const_int 0))
6867                       (label_ref (match_operand 0 "" ""))
6868                       (pc)))]
6869   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6870   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
6873 (define_expand "bunlt"
6874   [(set (pc)
6875         (if_then_else (unlt (match_dup 1) (const_int 0))
6876                       (label_ref (match_operand 0 "" ""))
6877                       (pc)))]
6878   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6879   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
6882 (define_expand "bunge"
6883   [(set (pc)
6884         (if_then_else (unge (match_dup 1) (const_int 0))
6885                       (label_ref (match_operand 0 "" ""))
6886                       (pc)))]
6887   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6888   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
6891 (define_expand "bunle"
6892   [(set (pc)
6893         (if_then_else (unle (match_dup 1) (const_int 0))
6894                       (label_ref (match_operand 0 "" ""))
6895                       (pc)))]
6896   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6897   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
6900 ;; The following two patterns need two branch instructions, since there is
6901 ;; no single instruction that will handle all cases.
6902 (define_expand "buneq"
6903   [(set (pc)
6904         (if_then_else (uneq (match_dup 1) (const_int 0))
6905                       (label_ref (match_operand 0 "" ""))
6906                       (pc)))]
6907   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6908   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6911 (define_expand "bltgt"
6912   [(set (pc)
6913         (if_then_else (ltgt (match_dup 1) (const_int 0))
6914                       (label_ref (match_operand 0 "" ""))
6915                       (pc)))]
6916   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6917   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6921 ;; Patterns to match conditional branch insns.
6924 ; Special pattern to match UNEQ.
6925 (define_insn "*arm_buneq"
6926   [(set (pc)
6927         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6928                       (label_ref (match_operand 0 "" ""))
6929                       (pc)))]
6930   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6931   "*
6932   if (arm_ccfsm_state != 0)
6933     abort ();
6935   return \"bvs\\t%l0\;beq\\t%l0\";
6936   "
6937   [(set_attr "conds" "jump_clob")
6938    (set_attr "length" "8")]
6941 ; Special pattern to match LTGT.
6942 (define_insn "*arm_bltgt"
6943   [(set (pc)
6944         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6945                       (label_ref (match_operand 0 "" ""))
6946                       (pc)))]
6947   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6948   "*
6949   if (arm_ccfsm_state != 0)
6950     abort ();
6952   return \"bmi\\t%l0\;bgt\\t%l0\";
6953   "
6954   [(set_attr "conds" "jump_clob")
6955    (set_attr "length" "8")]
6958 (define_insn "*arm_cond_branch"
6959   [(set (pc)
6960         (if_then_else (match_operator 1 "arm_comparison_operator"
6961                        [(match_operand 2 "cc_register" "") (const_int 0)])
6962                       (label_ref (match_operand 0 "" ""))
6963                       (pc)))]
6964   "TARGET_ARM"
6965   "*
6966   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6967     {
6968       arm_ccfsm_state += 2;
6969       return \"\";
6970     }
6971   return \"b%d1\\t%l0\";
6972   "
6973   [(set_attr "conds" "use")
6974    (set_attr "type" "branch")]
6977 ; Special pattern to match reversed UNEQ.
6978 (define_insn "*arm_buneq_reversed"
6979   [(set (pc)
6980         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6981                       (pc)
6982                       (label_ref (match_operand 0 "" ""))))]
6983   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6984   "*
6985   if (arm_ccfsm_state != 0)
6986     abort ();
6988   return \"bmi\\t%l0\;bgt\\t%l0\";
6989   "
6990   [(set_attr "conds" "jump_clob")
6991    (set_attr "length" "8")]
6994 ; Special pattern to match reversed LTGT.
6995 (define_insn "*arm_bltgt_reversed"
6996   [(set (pc)
6997         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6998                       (pc)
6999                       (label_ref (match_operand 0 "" ""))))]
7000   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7001   "*
7002   if (arm_ccfsm_state != 0)
7003     abort ();
7005   return \"bvs\\t%l0\;beq\\t%l0\";
7006   "
7007   [(set_attr "conds" "jump_clob")
7008    (set_attr "length" "8")]
7011 (define_insn "*arm_cond_branch_reversed"
7012   [(set (pc)
7013         (if_then_else (match_operator 1 "arm_comparison_operator"
7014                        [(match_operand 2 "cc_register" "") (const_int 0)])
7015                       (pc)
7016                       (label_ref (match_operand 0 "" ""))))]
7017   "TARGET_ARM"
7018   "*
7019   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7020     {
7021       arm_ccfsm_state += 2;
7022       return \"\";
7023     }
7024   return \"b%D1\\t%l0\";
7025   "
7026   [(set_attr "conds" "use")
7027    (set_attr "type" "branch")]
7032 ; scc insns
7034 (define_expand "seq"
7035   [(set (match_operand:SI 0 "s_register_operand" "")
7036         (eq:SI (match_dup 1) (const_int 0)))]
7037   "TARGET_ARM"
7038   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7041 (define_expand "sne"
7042   [(set (match_operand:SI 0 "s_register_operand" "")
7043         (ne:SI (match_dup 1) (const_int 0)))]
7044   "TARGET_ARM"
7045   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7048 (define_expand "sgt"
7049   [(set (match_operand:SI 0 "s_register_operand" "")
7050         (gt:SI (match_dup 1) (const_int 0)))]
7051   "TARGET_ARM"
7052   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7055 (define_expand "sle"
7056   [(set (match_operand:SI 0 "s_register_operand" "")
7057         (le:SI (match_dup 1) (const_int 0)))]
7058   "TARGET_ARM"
7059   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7062 (define_expand "sge"
7063   [(set (match_operand:SI 0 "s_register_operand" "")
7064         (ge:SI (match_dup 1) (const_int 0)))]
7065   "TARGET_ARM"
7066   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7069 (define_expand "slt"
7070   [(set (match_operand:SI 0 "s_register_operand" "")
7071         (lt:SI (match_dup 1) (const_int 0)))]
7072   "TARGET_ARM"
7073   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7076 (define_expand "sgtu"
7077   [(set (match_operand:SI 0 "s_register_operand" "")
7078         (gtu:SI (match_dup 1) (const_int 0)))]
7079   "TARGET_ARM"
7080   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7083 (define_expand "sleu"
7084   [(set (match_operand:SI 0 "s_register_operand" "")
7085         (leu:SI (match_dup 1) (const_int 0)))]
7086   "TARGET_ARM"
7087   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7090 (define_expand "sgeu"
7091   [(set (match_operand:SI 0 "s_register_operand" "")
7092         (geu:SI (match_dup 1) (const_int 0)))]
7093   "TARGET_ARM"
7094   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7097 (define_expand "sltu"
7098   [(set (match_operand:SI 0 "s_register_operand" "")
7099         (ltu:SI (match_dup 1) (const_int 0)))]
7100   "TARGET_ARM"
7101   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7104 (define_expand "sunordered"
7105   [(set (match_operand:SI 0 "s_register_operand" "")
7106         (unordered:SI (match_dup 1) (const_int 0)))]
7107   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7108   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7109                                       arm_compare_op1);"
7112 (define_expand "sordered"
7113   [(set (match_operand:SI 0 "s_register_operand" "")
7114         (ordered:SI (match_dup 1) (const_int 0)))]
7115   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7116   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7117                                       arm_compare_op1);"
7120 (define_expand "sungt"
7121   [(set (match_operand:SI 0 "s_register_operand" "")
7122         (ungt:SI (match_dup 1) (const_int 0)))]
7123   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7124   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7125                                       arm_compare_op1);"
7128 (define_expand "sunge"
7129   [(set (match_operand:SI 0 "s_register_operand" "")
7130         (unge:SI (match_dup 1) (const_int 0)))]
7131   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7132   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7133                                       arm_compare_op1);"
7136 (define_expand "sunlt"
7137   [(set (match_operand:SI 0 "s_register_operand" "")
7138         (unlt:SI (match_dup 1) (const_int 0)))]
7139   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7140   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7141                                       arm_compare_op1);"
7144 (define_expand "sunle"
7145   [(set (match_operand:SI 0 "s_register_operand" "")
7146         (unle:SI (match_dup 1) (const_int 0)))]
7147   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7148   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7149                                       arm_compare_op1);"
7152 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7153 ;;; simple ARM instructions. 
7155 ; (define_expand "suneq"
7156 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7157 ;       (uneq:SI (match_dup 1) (const_int 0)))]
7158 ;   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7159 ;   "abort ();"
7160 ; )
7162 ; (define_expand "sltgt"
7163 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7164 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
7165 ;   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7166 ;   "abort ();"
7167 ; )
7169 (define_insn "*mov_scc"
7170   [(set (match_operand:SI 0 "s_register_operand" "=r")
7171         (match_operator:SI 1 "arm_comparison_operator"
7172          [(match_operand 2 "cc_register" "") (const_int 0)]))]
7173   "TARGET_ARM"
7174   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7175   [(set_attr "conds" "use")
7176    (set_attr "length" "8")]
7179 (define_insn "*mov_negscc"
7180   [(set (match_operand:SI 0 "s_register_operand" "=r")
7181         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7182                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7183   "TARGET_ARM"
7184   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7185   [(set_attr "conds" "use")
7186    (set_attr "length" "8")]
7189 (define_insn "*mov_notscc"
7190   [(set (match_operand:SI 0 "s_register_operand" "=r")
7191         (not:SI (match_operator:SI 1 "arm_comparison_operator"
7192                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7193   "TARGET_ARM"
7194   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7195   [(set_attr "conds" "use")
7196    (set_attr "length" "8")]
7200 ;; Conditional move insns
7202 (define_expand "movsicc"
7203   [(set (match_operand:SI 0 "s_register_operand" "")
7204         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7205                          (match_operand:SI 2 "arm_not_operand" "")
7206                          (match_operand:SI 3 "arm_not_operand" "")))]
7207   "TARGET_ARM"
7208   "
7209   {
7210     enum rtx_code code = GET_CODE (operands[1]);
7211     rtx ccreg;
7213     if (code == UNEQ || code == LTGT)
7214       FAIL;
7216     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7217     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7218   }"
7221 (define_expand "movsfcc"
7222   [(set (match_operand:SF 0 "s_register_operand" "")
7223         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7224                          (match_operand:SF 2 "s_register_operand" "")
7225                          (match_operand:SF 3 "nonmemory_operand" "")))]
7226   "TARGET_ARM"
7227   "
7228   {
7229     enum rtx_code code = GET_CODE (operands[1]);
7230     rtx ccreg;
7232     if (code == UNEQ || code == LTGT)
7233       FAIL;
7235     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
7236        Otherwise, ensure it is a valid FP add operand */
7237     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7238         || (!arm_float_add_operand (operands[3], SFmode)))
7239       operands[3] = force_reg (SFmode, operands[3]);
7241     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7242     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7243   }"
7246 (define_expand "movdfcc"
7247   [(set (match_operand:DF 0 "s_register_operand" "")
7248         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7249                          (match_operand:DF 2 "s_register_operand" "")
7250                          (match_operand:DF 3 "arm_float_add_operand" "")))]
7251   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7252   "
7253   {
7254     enum rtx_code code = GET_CODE (operands[1]);
7255     rtx ccreg;
7257     if (code == UNEQ || code == LTGT)
7258       FAIL;
7260     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7261     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7262   }"
7265 (define_insn "*movsicc_insn"
7266   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7267         (if_then_else:SI
7268          (match_operator 3 "arm_comparison_operator"
7269           [(match_operand 4 "cc_register" "") (const_int 0)])
7270          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7271          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7272   "TARGET_ARM"
7273   "@
7274    mov%D3\\t%0, %2
7275    mvn%D3\\t%0, #%B2
7276    mov%d3\\t%0, %1
7277    mvn%d3\\t%0, #%B1
7278    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7279    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7280    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7281    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7282   [(set_attr "length" "4,4,4,4,8,8,8,8")
7283    (set_attr "conds" "use")]
7286 (define_insn "*movsfcc_soft_insn"
7287   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7288         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7289                           [(match_operand 4 "cc_register" "") (const_int 0)])
7290                          (match_operand:SF 1 "s_register_operand" "0,r")
7291                          (match_operand:SF 2 "s_register_operand" "r,0")))]
7292   "TARGET_ARM && TARGET_SOFT_FLOAT"
7293   "@
7294    mov%D3\\t%0, %2
7295    mov%d3\\t%0, %1"
7296   [(set_attr "conds" "use")]
7300 ;; Jump and linkage insns
7302 (define_expand "jump"
7303   [(set (pc)
7304         (label_ref (match_operand 0 "" "")))]
7305   "TARGET_EITHER"
7306   ""
7309 (define_insn "*arm_jump"
7310   [(set (pc)
7311         (label_ref (match_operand 0 "" "")))]
7312   "TARGET_ARM"
7313   "*
7314   {
7315     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7316       {
7317         arm_ccfsm_state += 2;
7318         return \"\";
7319       }
7320     return \"b%?\\t%l0\";
7321   }
7322   "
7323   [(set_attr "predicable" "yes")]
7326 (define_insn "*thumb_jump"
7327   [(set (pc)
7328         (label_ref (match_operand 0 "" "")))]
7329   "TARGET_THUMB"
7330   "*
7331   if (get_attr_length (insn) == 2)
7332     return \"b\\t%l0\";
7333   return \"bl\\t%l0\\t%@ far jump\";
7334   "
7335   [(set (attr "far_jump")
7336         (if_then_else
7337             (eq_attr "length" "4")
7338             (const_string "yes")
7339             (const_string "no")))
7340    (set (attr "length") 
7341         (if_then_else
7342             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7343                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
7344             (const_int 2)
7345             (const_int 4)))]
7348 (define_expand "call"
7349   [(parallel [(call (match_operand 0 "memory_operand" "")
7350                     (match_operand 1 "general_operand" ""))
7351               (use (match_operand 2 "" ""))
7352               (clobber (reg:SI LR_REGNUM))])]
7353   "TARGET_EITHER"
7354   "
7355   {
7356     rtx callee;
7357     
7358     /* In an untyped call, we can get NULL for operand 2.  */
7359     if (operands[2] == NULL_RTX)
7360       operands[2] = const0_rtx;
7361       
7362     /* This is to decide if we should generate indirect calls by loading the
7363        32 bit address of the callee into a register before performing the
7364        branch and link.  operand[2] encodes the long_call/short_call
7365        attribute of the function being called.  This attribute is set whenever
7366        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7367        is used, and the short_call attribute can also be set if function is
7368        declared as static or if it has already been defined in the current
7369        compilation unit.  See arm.c and arm.h for info about this.  The third
7370        parameter to arm_is_longcall_p is used to tell it which pattern
7371        invoked it.  */
7372     callee  = XEXP (operands[0], 0);
7373     
7374     if (GET_CODE (callee) != REG
7375        && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7376       XEXP (operands[0], 0) = force_reg (Pmode, callee);
7377   }"
7380 (define_insn "*call_reg_armv5"
7381   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7382          (match_operand 1 "" ""))
7383    (use (match_operand 2 "" ""))
7384    (clobber (reg:SI LR_REGNUM))]
7385   "TARGET_ARM && arm_arch5"
7386   "blx%?\\t%0"
7387   [(set_attr "type" "call")]
7390 (define_insn "*call_reg_arm"
7391   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7392          (match_operand 1 "" ""))
7393    (use (match_operand 2 "" ""))
7394    (clobber (reg:SI LR_REGNUM))]
7395   "TARGET_ARM && !arm_arch5"
7396   "*
7397   return output_call (operands);
7398   "
7399   ;; length is worst case, normally it is only two
7400   [(set_attr "length" "12")
7401    (set_attr "type" "call")]
7404 (define_insn "*call_mem"
7405   [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7406          (match_operand 1 "" ""))
7407    (use (match_operand 2 "" ""))
7408    (clobber (reg:SI LR_REGNUM))]
7409   "TARGET_ARM"
7410   "*
7411   return output_call_mem (operands);
7412   "
7413   [(set_attr "length" "12")
7414    (set_attr "type" "call")]
7417 (define_insn "*call_reg_thumb_v5"
7418   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7419          (match_operand 1 "" ""))
7420    (use (match_operand 2 "" ""))
7421    (clobber (reg:SI LR_REGNUM))]
7422   "TARGET_THUMB && arm_arch5"
7423   "blx\\t%0"
7424   [(set_attr "length" "2")
7425    (set_attr "type" "call")]
7428 (define_insn "*call_reg_thumb"
7429   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7430          (match_operand 1 "" ""))
7431    (use (match_operand 2 "" ""))
7432    (clobber (reg:SI LR_REGNUM))]
7433   "TARGET_THUMB && !arm_arch5"
7434   "*
7435   {
7436     if (TARGET_CALLER_INTERWORKING)
7437       return \"bl\\t%__interwork_call_via_%0\";
7438     else
7439       return \"bl\\t%__call_via_%0\";
7440   }"
7441   [(set_attr "type" "call")]
7444 (define_expand "call_value"
7445   [(parallel [(set (match_operand       0 "" "")
7446                    (call (match_operand 1 "memory_operand" "")
7447                          (match_operand 2 "general_operand" "")))
7448               (use (match_operand 3 "" ""))
7449               (clobber (reg:SI LR_REGNUM))])]
7450   "TARGET_EITHER"
7451   "
7452   {
7453     rtx callee = XEXP (operands[1], 0);
7454     
7455     /* In an untyped call, we can get NULL for operand 2.  */
7456     if (operands[3] == 0)
7457       operands[3] = const0_rtx;
7458       
7459     /* See the comment in define_expand \"call\".  */
7460     if (GET_CODE (callee) != REG
7461         && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7462       XEXP (operands[1], 0) = force_reg (Pmode, callee);
7463   }"
7466 (define_insn "*call_value_reg_armv5"
7467   [(set (match_operand 0 "" "")
7468         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7469               (match_operand 2 "" "")))
7470    (use (match_operand 3 "" ""))
7471    (clobber (reg:SI LR_REGNUM))]
7472   "TARGET_ARM && arm_arch5"
7473   "blx%?\\t%1"
7474   [(set_attr "type" "call")]
7477 (define_insn "*call_value_reg_arm"
7478   [(set (match_operand 0 "" "")
7479         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7480               (match_operand 2 "" "")))
7481    (use (match_operand 3 "" ""))
7482    (clobber (reg:SI LR_REGNUM))]
7483   "TARGET_ARM && !arm_arch5"
7484   "*
7485   return output_call (&operands[1]);
7486   "
7487   [(set_attr "length" "12")
7488    (set_attr "type" "call")]
7491 (define_insn "*call_value_mem"
7492   [(set (match_operand 0 "" "")
7493         (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7494               (match_operand 2 "" "")))
7495    (use (match_operand 3 "" ""))
7496    (clobber (reg:SI LR_REGNUM))]
7497   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7498   "*
7499   return output_call_mem (&operands[1]);
7500   "
7501   [(set_attr "length" "12")
7502    (set_attr "type" "call")]
7505 (define_insn "*call_value_reg_thumb_v5"
7506   [(set (match_operand 0 "" "")
7507         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7508               (match_operand 2 "" "")))
7509    (use (match_operand 3 "" ""))
7510    (clobber (reg:SI LR_REGNUM))]
7511   "TARGET_THUMB && arm_arch5"
7512   "blx\\t%1"
7513   [(set_attr "length" "2")
7514    (set_attr "type" "call")]
7517 (define_insn "*call_value_reg_thumb"
7518   [(set (match_operand 0 "" "")
7519         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7520               (match_operand 2 "" "")))
7521    (use (match_operand 3 "" ""))
7522    (clobber (reg:SI LR_REGNUM))]
7523   "TARGET_THUMB && !arm_arch5"
7524   "*
7525   {
7526     if (TARGET_CALLER_INTERWORKING)
7527       return \"bl\\t%__interwork_call_via_%1\";
7528     else
7529       return \"bl\\t%__call_via_%1\";
7530   }"
7531   [(set_attr "type" "call")]
7534 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7535 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7537 (define_insn "*call_symbol"
7538   [(call (mem:SI (match_operand:SI 0 "" ""))
7539          (match_operand 1 "" ""))
7540    (use (match_operand 2 "" ""))
7541    (clobber (reg:SI LR_REGNUM))]
7542   "TARGET_ARM
7543    && (GET_CODE (operands[0]) == SYMBOL_REF)
7544    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7545   "*
7546   {
7547     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7548   }"
7549   [(set_attr "type" "call")]
7552 (define_insn "*call_value_symbol"
7553   [(set (match_operand 0 "s_register_operand" "")
7554         (call (mem:SI (match_operand:SI 1 "" ""))
7555         (match_operand:SI 2 "" "")))
7556    (use (match_operand 3 "" ""))
7557    (clobber (reg:SI LR_REGNUM))]
7558   "TARGET_ARM
7559    && (GET_CODE (operands[1]) == SYMBOL_REF)
7560    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7561   "*
7562   {
7563     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7564   }"
7565   [(set_attr "type" "call")]
7568 (define_insn "*call_insn"
7569   [(call (mem:SI (match_operand:SI 0 "" ""))
7570          (match_operand:SI 1 "" ""))
7571    (use (match_operand 2 "" ""))
7572    (clobber (reg:SI LR_REGNUM))]
7573   "TARGET_THUMB
7574    && GET_CODE (operands[0]) == SYMBOL_REF
7575    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7576   "bl\\t%a0"
7577   [(set_attr "length" "4")
7578    (set_attr "type" "call")]
7581 (define_insn "*call_value_insn"
7582   [(set (match_operand 0 "register_operand" "")
7583         (call (mem:SI (match_operand 1 "" ""))
7584               (match_operand 2 "" "")))
7585    (use (match_operand 3 "" ""))
7586    (clobber (reg:SI LR_REGNUM))]
7587   "TARGET_THUMB
7588    && GET_CODE (operands[1]) == SYMBOL_REF
7589    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7590   "bl\\t%a1"
7591   [(set_attr "length" "4")
7592    (set_attr "type" "call")]
7595 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7596 (define_expand "sibcall"
7597   [(parallel [(call (match_operand 0 "memory_operand" "")
7598                     (match_operand 1 "general_operand" ""))
7599               (return)
7600               (use (match_operand 2 "" ""))])]
7601   "TARGET_ARM"
7602   "
7603   {
7604     if (operands[2] == NULL_RTX)
7605       operands[2] = const0_rtx;
7606   }"
7609 (define_expand "sibcall_value"
7610   [(parallel [(set (match_operand 0 "register_operand" "")
7611                    (call (match_operand 1 "memory_operand" "")
7612                          (match_operand 2 "general_operand" "")))
7613               (return)
7614               (use (match_operand 3 "" ""))])]
7615   "TARGET_ARM"
7616   "
7617   {
7618     if (operands[3] == NULL_RTX)
7619       operands[3] = const0_rtx;
7620   }"
7623 (define_insn "*sibcall_insn"
7624  [(call (mem:SI (match_operand:SI 0 "" "X"))
7625         (match_operand 1 "" ""))
7626   (return)
7627   (use (match_operand 2 "" ""))]
7628   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7629   "*
7630   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7631   "
7632   [(set_attr "type" "call")]
7635 (define_insn "*sibcall_value_insn"
7636  [(set (match_operand 0 "s_register_operand" "")
7637        (call (mem:SI (match_operand:SI 1 "" "X"))
7638              (match_operand 2 "" "")))
7639   (return)
7640   (use (match_operand 3 "" ""))]
7641   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7642   "*
7643   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7644   "
7645   [(set_attr "type" "call")]
7648 ;; Often the return insn will be the same as loading from memory, so set attr
7649 (define_insn "return"
7650   [(return)]
7651   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7652   "*
7653   {
7654     if (arm_ccfsm_state == 2)
7655       {
7656         arm_ccfsm_state += 2;
7657         return \"\";
7658       }
7659     return output_return_instruction (const_true_rtx, TRUE, FALSE);
7660   }"
7661   [(set_attr "type" "load1")
7662    (set_attr "length" "12")
7663    (set_attr "predicable" "yes")]
7666 (define_insn "*cond_return"
7667   [(set (pc)
7668         (if_then_else (match_operator 0 "arm_comparison_operator"
7669                        [(match_operand 1 "cc_register" "") (const_int 0)])
7670                       (return)
7671                       (pc)))]
7672   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7673   "*
7674   {
7675     if (arm_ccfsm_state == 2)
7676       {
7677         arm_ccfsm_state += 2;
7678         return \"\";
7679       }
7680     return output_return_instruction (operands[0], TRUE, FALSE);
7681   }"
7682   [(set_attr "conds" "use")
7683    (set_attr "length" "12")
7684    (set_attr "type" "load1")]
7687 (define_insn "*cond_return_inverted"
7688   [(set (pc)
7689         (if_then_else (match_operator 0 "arm_comparison_operator"
7690                        [(match_operand 1 "cc_register" "") (const_int 0)])
7691                       (pc)
7692                       (return)))]
7693   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7694   "*
7695   {
7696     if (arm_ccfsm_state == 2)
7697       {
7698         arm_ccfsm_state += 2;
7699         return \"\";
7700       }
7701     return output_return_instruction (operands[0], TRUE, TRUE);
7702   }"
7703   [(set_attr "conds" "use")
7704    (set_attr "length" "12")
7705    (set_attr "type" "load1")]
7708 ;; Generate a sequence of instructions to determine if the processor is
7709 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7710 ;; mask.
7712 (define_expand "return_addr_mask"
7713   [(set (match_dup 1)
7714       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7715                        (const_int 0)))
7716    (set (match_operand:SI 0 "s_register_operand" "")
7717       (if_then_else:SI (eq (match_dup 1) (const_int 0))
7718                        (const_int -1)
7719                        (const_int 67108860)))] ; 0x03fffffc
7720   "TARGET_ARM"
7721   "
7722   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7723   ")
7725 (define_insn "*check_arch2"
7726   [(set (match_operand:CC_NOOV 0 "cc_register" "")
7727       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7728                        (const_int 0)))]
7729   "TARGET_ARM"
7730   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7731   [(set_attr "length" "8")
7732    (set_attr "conds" "set")]
7735 ;; Call subroutine returning any type.
7737 (define_expand "untyped_call"
7738   [(parallel [(call (match_operand 0 "" "")
7739                     (const_int 0))
7740               (match_operand 1 "" "")
7741               (match_operand 2 "" "")])]
7742   "TARGET_ARM"
7743   "
7744   {
7745     int i;
7747     emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
7749     for (i = 0; i < XVECLEN (operands[2], 0); i++)
7750       {
7751         rtx set = XVECEXP (operands[2], 0, i);
7753         emit_move_insn (SET_DEST (set), SET_SRC (set));
7754       }
7756     /* The optimizer does not know that the call sets the function value
7757        registers we stored in the result block.  We avoid problems by
7758        claiming that all hard registers are used and clobbered at this
7759        point.  */
7760     emit_insn (gen_blockage ());
7762     DONE;
7763   }"
7766 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7767 ;; all of memory.  This blocks insns from being moved across this point.
7769 (define_insn "blockage"
7770   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
7771   "TARGET_EITHER"
7772   ""
7773   [(set_attr "length" "0")
7774    (set_attr "type" "block")]
7777 (define_expand "casesi"
7778   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
7779    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
7780    (match_operand:SI 2 "const_int_operand" "")  ; total range
7781    (match_operand:SI 3 "" "")                   ; table label
7782    (match_operand:SI 4 "" "")]                  ; Out of range label
7783   "TARGET_ARM"
7784   "
7785   {
7786     rtx reg;
7787     if (operands[1] != const0_rtx)
7788       {
7789         reg = gen_reg_rtx (SImode);
7791         emit_insn (gen_addsi3 (reg, operands[0],
7792                                GEN_INT (-INTVAL (operands[1]))));
7793         operands[0] = reg;
7794       }
7796     if (!const_ok_for_arm (INTVAL (operands[2])))
7797       operands[2] = force_reg (SImode, operands[2]);
7799     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
7800                                          operands[4]));
7801     DONE;
7802   }"
7805 ;; The USE in this pattern is needed to tell flow analysis that this is
7806 ;; a CASESI insn.  It has no other purpose.
7807 (define_insn "casesi_internal"
7808   [(parallel [(set (pc)
7809                (if_then_else
7810                 (leu (match_operand:SI 0 "s_register_operand" "r")
7811                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
7812                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
7813                                  (label_ref (match_operand 2 "" ""))))
7814                 (label_ref (match_operand 3 "" ""))))
7815               (clobber (reg:CC CC_REGNUM))
7816               (use (label_ref (match_dup 2)))])]
7817   "TARGET_ARM"
7818   "*
7819     if (flag_pic)
7820       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
7821     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
7822   "
7823   [(set_attr "conds" "clob")
7824    (set_attr "length" "12")]
7827 (define_expand "indirect_jump"
7828   [(set (pc)
7829         (match_operand:SI 0 "s_register_operand" ""))]
7830   "TARGET_EITHER"
7831   ""
7834 ;; NB Never uses BX.
7835 (define_insn "*arm_indirect_jump"
7836   [(set (pc)
7837         (match_operand:SI 0 "s_register_operand" "r"))]
7838   "TARGET_ARM"
7839   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
7840   [(set_attr "predicable" "yes")]
7843 (define_insn "*load_indirect_jump"
7844   [(set (pc)
7845         (match_operand:SI 0 "memory_operand" "m"))]
7846   "TARGET_ARM"
7847   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
7848   [(set_attr "type" "load1")
7849    (set_attr "pool_range" "4096")
7850    (set_attr "neg_pool_range" "4084")
7851    (set_attr "predicable" "yes")]
7854 ;; NB Never uses BX.
7855 (define_insn "*thumb_indirect_jump"
7856   [(set (pc)
7857         (match_operand:SI 0 "register_operand" "l*r"))]
7858   "TARGET_THUMB"
7859   "mov\\tpc, %0"
7860   [(set_attr "conds" "clob")
7861    (set_attr "length" "2")]
7865 ;; Misc insns
7867 (define_insn "nop"
7868   [(const_int 0)]
7869   "TARGET_EITHER"
7870   "*
7871   if (TARGET_ARM)
7872     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
7873   return  \"mov\\tr8, r8\";
7874   "
7875   [(set (attr "length")
7876         (if_then_else (eq_attr "is_thumb" "yes")
7877                       (const_int 2)
7878                       (const_int 4)))]
7882 ;; Patterns to allow combination of arithmetic, cond code and shifts
7884 (define_insn "*arith_shiftsi"
7885   [(set (match_operand:SI 0 "s_register_operand" "=r")
7886         (match_operator:SI 1 "shiftable_operator"
7887           [(match_operator:SI 3 "shift_operator"
7888              [(match_operand:SI 4 "s_register_operand" "r")
7889               (match_operand:SI 5 "reg_or_int_operand" "rI")])
7890            (match_operand:SI 2 "s_register_operand" "r")]))]
7891   "TARGET_ARM"
7892   "%i1%?\\t%0, %2, %4%S3"
7893   [(set_attr "predicable" "yes")
7894    (set_attr "shift" "4")
7895    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7896                       (const_string "alu_shift")
7897                       (const_string "alu_shift_reg")))]
7900 (define_split
7901   [(set (match_operand:SI 0 "s_register_operand" "")
7902         (match_operator:SI 1 "shiftable_operator"
7903          [(match_operator:SI 2 "shiftable_operator"
7904            [(match_operator:SI 3 "shift_operator"
7905              [(match_operand:SI 4 "s_register_operand" "")
7906               (match_operand:SI 5 "reg_or_int_operand" "")])
7907             (match_operand:SI 6 "s_register_operand" "")])
7908           (match_operand:SI 7 "arm_rhs_operand" "")]))
7909    (clobber (match_operand:SI 8 "s_register_operand" ""))]
7910   "TARGET_ARM"
7911   [(set (match_dup 8)
7912         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7913                          (match_dup 6)]))
7914    (set (match_dup 0)
7915         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
7916   "")
7918 (define_insn "*arith_shiftsi_compare0"
7919   [(set (reg:CC_NOOV CC_REGNUM)
7920         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7921                           [(match_operator:SI 3 "shift_operator"
7922                             [(match_operand:SI 4 "s_register_operand" "r")
7923                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
7924                            (match_operand:SI 2 "s_register_operand" "r")])
7925                          (const_int 0)))
7926    (set (match_operand:SI 0 "s_register_operand" "=r")
7927         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7928                          (match_dup 2)]))]
7929   "TARGET_ARM"
7930   "%i1%?s\\t%0, %2, %4%S3"
7931   [(set_attr "conds" "set")
7932    (set_attr "shift" "4")
7933    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7934                       (const_string "alu_shift")
7935                       (const_string "alu_shift_reg")))]
7938 (define_insn "*arith_shiftsi_compare0_scratch"
7939   [(set (reg:CC_NOOV CC_REGNUM)
7940         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7941                           [(match_operator:SI 3 "shift_operator"
7942                             [(match_operand:SI 4 "s_register_operand" "r")
7943                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
7944                            (match_operand:SI 2 "s_register_operand" "r")])
7945                          (const_int 0)))
7946    (clobber (match_scratch:SI 0 "=r"))]
7947   "TARGET_ARM"
7948   "%i1%?s\\t%0, %2, %4%S3"
7949   [(set_attr "conds" "set")
7950    (set_attr "shift" "4")
7951    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7952                       (const_string "alu_shift")
7953                       (const_string "alu_shift_reg")))]
7956 (define_insn "*sub_shiftsi"
7957   [(set (match_operand:SI 0 "s_register_operand" "=r")
7958         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7959                   (match_operator:SI 2 "shift_operator"
7960                    [(match_operand:SI 3 "s_register_operand" "r")
7961                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
7962   "TARGET_ARM"
7963   "sub%?\\t%0, %1, %3%S2"
7964   [(set_attr "predicable" "yes")
7965    (set_attr "shift" "3")
7966    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7967                       (const_string "alu_shift")
7968                       (const_string "alu_shift_reg")))]
7971 (define_insn "*sub_shiftsi_compare0"
7972   [(set (reg:CC_NOOV CC_REGNUM)
7973         (compare:CC_NOOV
7974          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7975                    (match_operator:SI 2 "shift_operator"
7976                     [(match_operand:SI 3 "s_register_operand" "r")
7977                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7978          (const_int 0)))
7979    (set (match_operand:SI 0 "s_register_operand" "=r")
7980         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7981                                                  (match_dup 4)])))]
7982   "TARGET_ARM"
7983   "sub%?s\\t%0, %1, %3%S2"
7984   [(set_attr "conds" "set")
7985    (set_attr "shift" "3")
7986    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7987                       (const_string "alu_shift")
7988                       (const_string "alu_shift_reg")))]
7991 (define_insn "*sub_shiftsi_compare0_scratch"
7992   [(set (reg:CC_NOOV CC_REGNUM)
7993         (compare:CC_NOOV
7994          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7995                    (match_operator:SI 2 "shift_operator"
7996                     [(match_operand:SI 3 "s_register_operand" "r")
7997                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7998          (const_int 0)))
7999    (clobber (match_scratch:SI 0 "=r"))]
8000   "TARGET_ARM"
8001   "sub%?s\\t%0, %1, %3%S2"
8002   [(set_attr "conds" "set")
8003    (set_attr "shift" "3")
8004    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8005                       (const_string "alu_shift")
8006                       (const_string "alu_shift_reg")))]
8011 (define_insn "*and_scc"
8012   [(set (match_operand:SI 0 "s_register_operand" "=r")
8013         (and:SI (match_operator:SI 1 "arm_comparison_operator"
8014                  [(match_operand 3 "cc_register" "") (const_int 0)])
8015                 (match_operand:SI 2 "s_register_operand" "r")))]
8016   "TARGET_ARM"
8017   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8018   [(set_attr "conds" "use")
8019    (set_attr "length" "8")]
8022 (define_insn "*ior_scc"
8023   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8024         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8025                  [(match_operand 3 "cc_register" "") (const_int 0)])
8026                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8027   "TARGET_ARM"
8028   "@
8029    orr%d2\\t%0, %1, #1
8030    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8031   [(set_attr "conds" "use")
8032    (set_attr "length" "4,8")]
8035 (define_insn "*compare_scc"
8036   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8037         (match_operator:SI 1 "arm_comparison_operator"
8038          [(match_operand:SI 2 "s_register_operand" "r,r")
8039           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8040    (clobber (reg:CC CC_REGNUM))]
8041   "TARGET_ARM"
8042   "*
8043     if (operands[3] == const0_rtx)
8044       {
8045         if (GET_CODE (operands[1]) == LT)
8046           return \"mov\\t%0, %2, lsr #31\";
8048         if (GET_CODE (operands[1]) == GE)
8049           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8051         if (GET_CODE (operands[1]) == EQ)
8052           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8053       }
8055     if (GET_CODE (operands[1]) == NE)
8056       {
8057         if (which_alternative == 1)
8058           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8059         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8060       }
8061     if (which_alternative == 1)
8062       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8063     else
8064       output_asm_insn (\"cmp\\t%2, %3\", operands);
8065     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8066   "
8067   [(set_attr "conds" "clob")
8068    (set_attr "length" "12")]
8071 (define_insn "*cond_move"
8072   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8073         (if_then_else:SI (match_operator 3 "equality_operator"
8074                           [(match_operator 4 "arm_comparison_operator"
8075                             [(match_operand 5 "cc_register" "") (const_int 0)])
8076                            (const_int 0)])
8077                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8078                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8079   "TARGET_ARM"
8080   "*
8081     if (GET_CODE (operands[3]) == NE)
8082       {
8083         if (which_alternative != 1)
8084           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8085         if (which_alternative != 0)
8086           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8087         return \"\";
8088       }
8089     if (which_alternative != 0)
8090       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8091     if (which_alternative != 1)
8092       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8093     return \"\";
8094   "
8095   [(set_attr "conds" "use")
8096    (set_attr "length" "4,4,8")]
8099 (define_insn "*cond_arith"
8100   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8101         (match_operator:SI 5 "shiftable_operator" 
8102          [(match_operator:SI 4 "arm_comparison_operator"
8103            [(match_operand:SI 2 "s_register_operand" "r,r")
8104             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8105           (match_operand:SI 1 "s_register_operand" "0,?r")]))
8106    (clobber (reg:CC CC_REGNUM))]
8107   "TARGET_ARM"
8108   "*
8109     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8110       return \"%i5\\t%0, %1, %2, lsr #31\";
8112     output_asm_insn (\"cmp\\t%2, %3\", operands);
8113     if (GET_CODE (operands[5]) == AND)
8114       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8115     else if (GET_CODE (operands[5]) == MINUS)
8116       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8117     else if (which_alternative != 0)
8118       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8119     return \"%i5%d4\\t%0, %1, #1\";
8120   "
8121   [(set_attr "conds" "clob")
8122    (set_attr "length" "12")]
8125 (define_insn "*cond_sub"
8126   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8127         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8128                   (match_operator:SI 4 "arm_comparison_operator"
8129                    [(match_operand:SI 2 "s_register_operand" "r,r")
8130                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8131    (clobber (reg:CC CC_REGNUM))]
8132   "TARGET_ARM"
8133   "*
8134     output_asm_insn (\"cmp\\t%2, %3\", operands);
8135     if (which_alternative != 0)
8136       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8137     return \"sub%d4\\t%0, %1, #1\";
8138   "
8139   [(set_attr "conds" "clob")
8140    (set_attr "length" "8,12")]
8143 (define_insn "*cmp_ite0"
8144   [(set (match_operand 6 "dominant_cc_register" "")
8145         (compare
8146          (if_then_else:SI
8147           (match_operator 4 "arm_comparison_operator"
8148            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8149             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8150           (match_operator:SI 5 "arm_comparison_operator"
8151            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8152             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8153           (const_int 0))
8154          (const_int 0)))]
8155   "TARGET_ARM"
8156   "*
8157   {
8158     static const char * const opcodes[4][2] =
8159     {
8160       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8161        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8162       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8163        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8164       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8165        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8166       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8167        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8168     };
8169     int swap =
8170       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8172     return opcodes[which_alternative][swap];
8173   }"
8174   [(set_attr "conds" "set")
8175    (set_attr "length" "8")]
8178 (define_insn "*cmp_ite1"
8179   [(set (match_operand 6 "dominant_cc_register" "")
8180         (compare
8181          (if_then_else:SI
8182           (match_operator 4 "arm_comparison_operator"
8183            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8184             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8185           (match_operator:SI 5 "arm_comparison_operator"
8186            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8187             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8188           (const_int 1))
8189          (const_int 0)))]
8190   "TARGET_ARM"
8191   "*
8192   {
8193     static const char * const opcodes[4][2] =
8194     {
8195       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8196        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8197       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8198        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8199       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8200        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8201       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8202        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8203     };
8204     int swap =
8205       comparison_dominates_p (GET_CODE (operands[5]),
8206                               reverse_condition (GET_CODE (operands[4])));
8208     return opcodes[which_alternative][swap];
8209   }"
8210   [(set_attr "conds" "set")
8211    (set_attr "length" "8")]
8214 (define_insn "*cmp_and"
8215   [(set (match_operand 6 "dominant_cc_register" "")
8216         (compare
8217          (and:SI
8218           (match_operator 4 "arm_comparison_operator"
8219            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8220             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8221           (match_operator:SI 5 "arm_comparison_operator"
8222            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8223             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8224          (const_int 0)))]
8225   "TARGET_ARM"
8226   "*
8227   {
8228     static const char *const opcodes[4][2] =
8229     {
8230       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8231        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8232       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8233        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8234       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8235        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8236       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8237        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8238     };
8239     int swap =
8240       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8242     return opcodes[which_alternative][swap];
8243   }"
8244   [(set_attr "conds" "set")
8245    (set_attr "predicable" "no")
8246    (set_attr "length" "8")]
8249 (define_insn "*cmp_ior"
8250   [(set (match_operand 6 "dominant_cc_register" "")
8251         (compare
8252          (ior:SI
8253           (match_operator 4 "arm_comparison_operator"
8254            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8255             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8256           (match_operator:SI 5 "arm_comparison_operator"
8257            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8258             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8259          (const_int 0)))]
8260   "TARGET_ARM"
8261   "*
8263   static const char *const opcodes[4][2] =
8264   {
8265     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8266      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8267     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8268      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8269     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8270      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8271     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8272      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8273   };
8274   int swap =
8275     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8277   return opcodes[which_alternative][swap];
8280   [(set_attr "conds" "set")
8281    (set_attr "length" "8")]
8284 (define_insn_and_split "*ior_scc_scc"
8285   [(set (match_operand:SI 0 "s_register_operand" "=r")
8286         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8287                  [(match_operand:SI 1 "s_register_operand" "r")
8288                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8289                 (match_operator:SI 6 "arm_comparison_operator"
8290                  [(match_operand:SI 4 "s_register_operand" "r")
8291                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8292    (clobber (reg:CC CC_REGNUM))]
8293   "TARGET_ARM
8294    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8295        != CCmode)"
8296   "#"
8297   "TARGET_ARM && reload_completed"
8298   [(set (match_dup 7)
8299         (compare
8300          (ior:SI
8301           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8302           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8303          (const_int 0)))
8304    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8305   "operands[7]
8306      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8307                                                   DOM_CC_X_OR_Y),
8308                     CC_REGNUM);"
8309   [(set_attr "conds" "clob")
8310    (set_attr "length" "16")])
8312 ; If the above pattern is followed by a CMP insn, then the compare is 
8313 ; redundant, since we can rework the conditional instruction that follows.
8314 (define_insn_and_split "*ior_scc_scc_cmp"
8315   [(set (match_operand 0 "dominant_cc_register" "")
8316         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8317                           [(match_operand:SI 1 "s_register_operand" "r")
8318                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8319                          (match_operator:SI 6 "arm_comparison_operator"
8320                           [(match_operand:SI 4 "s_register_operand" "r")
8321                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8322                  (const_int 0)))
8323    (set (match_operand:SI 7 "s_register_operand" "=r")
8324         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8325                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8326   "TARGET_ARM"
8327   "#"
8328   "TARGET_ARM && reload_completed"
8329   [(set (match_dup 0)
8330         (compare
8331          (ior:SI
8332           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8333           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8334          (const_int 0)))
8335    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8336   ""
8337   [(set_attr "conds" "set")
8338    (set_attr "length" "16")])
8340 (define_insn_and_split "*and_scc_scc"
8341   [(set (match_operand:SI 0 "s_register_operand" "=r")
8342         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8343                  [(match_operand:SI 1 "s_register_operand" "r")
8344                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8345                 (match_operator:SI 6 "arm_comparison_operator"
8346                  [(match_operand:SI 4 "s_register_operand" "r")
8347                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8348    (clobber (reg:CC CC_REGNUM))]
8349   "TARGET_ARM
8350    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8351        != CCmode)"
8352   "#"
8353   "TARGET_ARM && reload_completed
8354    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8355        != CCmode)"
8356   [(set (match_dup 7)
8357         (compare
8358          (and:SI
8359           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8360           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8361          (const_int 0)))
8362    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8363   "operands[7]
8364      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8365                                                   DOM_CC_X_AND_Y),
8366                     CC_REGNUM);"
8367   [(set_attr "conds" "clob")
8368    (set_attr "length" "16")])
8370 ; If the above pattern is followed by a CMP insn, then the compare is 
8371 ; redundant, since we can rework the conditional instruction that follows.
8372 (define_insn_and_split "*and_scc_scc_cmp"
8373   [(set (match_operand 0 "dominant_cc_register" "")
8374         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8375                           [(match_operand:SI 1 "s_register_operand" "r")
8376                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8377                          (match_operator:SI 6 "arm_comparison_operator"
8378                           [(match_operand:SI 4 "s_register_operand" "r")
8379                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8380                  (const_int 0)))
8381    (set (match_operand:SI 7 "s_register_operand" "=r")
8382         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8383                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8384   "TARGET_ARM"
8385   "#"
8386   "TARGET_ARM && reload_completed"
8387   [(set (match_dup 0)
8388         (compare
8389          (and:SI
8390           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8391           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8392          (const_int 0)))
8393    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8394   ""
8395   [(set_attr "conds" "set")
8396    (set_attr "length" "16")])
8398 ;; If there is no dominance in the comparison, then we can still save an
8399 ;; instruction in the AND case, since we can know that the second compare
8400 ;; need only zero the value if false (if true, then the value is already
8401 ;; correct).
8402 (define_insn_and_split "*and_scc_scc_nodom"
8403   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8404         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8405                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
8406                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8407                 (match_operator:SI 6 "arm_comparison_operator"
8408                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
8409                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8410    (clobber (reg:CC CC_REGNUM))]
8411   "TARGET_ARM
8412    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8413        == CCmode)"
8414   "#"
8415   "TARGET_ARM && reload_completed"
8416   [(parallel [(set (match_dup 0)
8417                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8418               (clobber (reg:CC CC_REGNUM))])
8419    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8420    (set (match_dup 0)
8421         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8422                          (match_dup 0)
8423                          (const_int 0)))]
8424   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8425                                               operands[4], operands[5]),
8426                               CC_REGNUM);
8427    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8428                                   operands[5]);"
8429   [(set_attr "conds" "clob")
8430    (set_attr "length" "20")])
8432 (define_split
8433   [(set (reg:CC_NOOV CC_REGNUM)
8434         (compare:CC_NOOV (ior:SI
8435                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8436                                   (const_int 1))
8437                           (match_operator:SI 1 "comparison_operator"
8438                            [(match_operand:SI 2 "s_register_operand" "")
8439                             (match_operand:SI 3 "arm_add_operand" "")]))
8440                          (const_int 0)))
8441    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8442   "TARGET_ARM"
8443   [(set (match_dup 4)
8444         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8445                 (match_dup 0)))
8446    (set (reg:CC_NOOV CC_REGNUM)
8447         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8448                          (const_int 0)))]
8449   "")
8451 (define_split
8452   [(set (reg:CC_NOOV CC_REGNUM)
8453         (compare:CC_NOOV (ior:SI
8454                           (match_operator:SI 1 "comparison_operator"
8455                            [(match_operand:SI 2 "s_register_operand" "")
8456                             (match_operand:SI 3 "arm_add_operand" "")])
8457                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8458                                   (const_int 1)))
8459                          (const_int 0)))
8460    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8461   "TARGET_ARM"
8462   [(set (match_dup 4)
8463         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8464                 (match_dup 0)))
8465    (set (reg:CC_NOOV CC_REGNUM)
8466         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8467                          (const_int 0)))]
8468   "")
8470 (define_insn "*negscc"
8471   [(set (match_operand:SI 0 "s_register_operand" "=r")
8472         (neg:SI (match_operator 3 "arm_comparison_operator"
8473                  [(match_operand:SI 1 "s_register_operand" "r")
8474                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8475    (clobber (reg:CC CC_REGNUM))]
8476   "TARGET_ARM"
8477   "*
8478   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8479     return \"mov\\t%0, %1, asr #31\";
8481   if (GET_CODE (operands[3]) == NE)
8482     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8484   if (GET_CODE (operands[3]) == GT)
8485     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8487   output_asm_insn (\"cmp\\t%1, %2\", operands);
8488   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8489   return \"mvn%d3\\t%0, #0\";
8490   "
8491   [(set_attr "conds" "clob")
8492    (set_attr "length" "12")]
8495 (define_insn "movcond"
8496   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8497         (if_then_else:SI
8498          (match_operator 5 "arm_comparison_operator"
8499           [(match_operand:SI 3 "s_register_operand" "r,r,r")
8500            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8501          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8502          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8503    (clobber (reg:CC CC_REGNUM))]
8504   "TARGET_ARM"
8505   "*
8506   if (GET_CODE (operands[5]) == LT
8507       && (operands[4] == const0_rtx))
8508     {
8509       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8510         {
8511           if (operands[2] == const0_rtx)
8512             return \"and\\t%0, %1, %3, asr #31\";
8513           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8514         }
8515       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8516         {
8517           if (operands[1] == const0_rtx)
8518             return \"bic\\t%0, %2, %3, asr #31\";
8519           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8520         }
8521       /* The only case that falls through to here is when both ops 1 & 2
8522          are constants.  */
8523     }
8525   if (GET_CODE (operands[5]) == GE
8526       && (operands[4] == const0_rtx))
8527     {
8528       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8529         {
8530           if (operands[2] == const0_rtx)
8531             return \"bic\\t%0, %1, %3, asr #31\";
8532           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8533         }
8534       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8535         {
8536           if (operands[1] == const0_rtx)
8537             return \"and\\t%0, %2, %3, asr #31\";
8538           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8539         }
8540       /* The only case that falls through to here is when both ops 1 & 2
8541          are constants.  */
8542     }
8543   if (GET_CODE (operands[4]) == CONST_INT
8544       && !const_ok_for_arm (INTVAL (operands[4])))
8545     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8546   else
8547     output_asm_insn (\"cmp\\t%3, %4\", operands);
8548   if (which_alternative != 0)
8549     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8550   if (which_alternative != 1)
8551     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8552   return \"\";
8553   "
8554   [(set_attr "conds" "clob")
8555    (set_attr "length" "8,8,12")]
8558 (define_insn "*ifcompare_plus_move"
8559   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8560         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8561                           [(match_operand:SI 4 "s_register_operand" "r,r")
8562                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8563                          (plus:SI
8564                           (match_operand:SI 2 "s_register_operand" "r,r")
8565                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8566                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8567    (clobber (reg:CC CC_REGNUM))]
8568   "TARGET_ARM"
8569   "#"
8570   [(set_attr "conds" "clob")
8571    (set_attr "length" "8,12")]
8574 (define_insn "*if_plus_move"
8575   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8576         (if_then_else:SI
8577          (match_operator 4 "arm_comparison_operator"
8578           [(match_operand 5 "cc_register" "") (const_int 0)])
8579          (plus:SI
8580           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8581           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8582          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8583   "TARGET_ARM"
8584   "@
8585    add%d4\\t%0, %2, %3
8586    sub%d4\\t%0, %2, #%n3
8587    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8588    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8589   [(set_attr "conds" "use")
8590    (set_attr "length" "4,4,8,8")
8591    (set_attr "type" "*,*,*,*")]
8594 (define_insn "*ifcompare_move_plus"
8595   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8596         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8597                           [(match_operand:SI 4 "s_register_operand" "r,r")
8598                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8599                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8600                          (plus:SI
8601                           (match_operand:SI 2 "s_register_operand" "r,r")
8602                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8603    (clobber (reg:CC CC_REGNUM))]
8604   "TARGET_ARM"
8605   "#"
8606   [(set_attr "conds" "clob")
8607    (set_attr "length" "8,12")]
8610 (define_insn "*if_move_plus"
8611   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8612         (if_then_else:SI
8613          (match_operator 4 "arm_comparison_operator"
8614           [(match_operand 5 "cc_register" "") (const_int 0)])
8615          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8616          (plus:SI
8617           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8618           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8619   "TARGET_ARM"
8620   "@
8621    add%D4\\t%0, %2, %3
8622    sub%D4\\t%0, %2, #%n3
8623    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8624    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8625   [(set_attr "conds" "use")
8626    (set_attr "length" "4,4,8,8")
8627    (set_attr "type" "*,*,*,*")]
8630 (define_insn "*ifcompare_arith_arith"
8631   [(set (match_operand:SI 0 "s_register_operand" "=r")
8632         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8633                           [(match_operand:SI 5 "s_register_operand" "r")
8634                            (match_operand:SI 6 "arm_add_operand" "rIL")])
8635                          (match_operator:SI 8 "shiftable_operator"
8636                           [(match_operand:SI 1 "s_register_operand" "r")
8637                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8638                          (match_operator:SI 7 "shiftable_operator"
8639                           [(match_operand:SI 3 "s_register_operand" "r")
8640                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8641    (clobber (reg:CC CC_REGNUM))]
8642   "TARGET_ARM"
8643   "#"
8644   [(set_attr "conds" "clob")
8645    (set_attr "length" "12")]
8648 (define_insn "*if_arith_arith"
8649   [(set (match_operand:SI 0 "s_register_operand" "=r")
8650         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8651                           [(match_operand 8 "cc_register" "") (const_int 0)])
8652                          (match_operator:SI 6 "shiftable_operator"
8653                           [(match_operand:SI 1 "s_register_operand" "r")
8654                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8655                          (match_operator:SI 7 "shiftable_operator"
8656                           [(match_operand:SI 3 "s_register_operand" "r")
8657                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8658   "TARGET_ARM"
8659   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8660   [(set_attr "conds" "use")
8661    (set_attr "length" "8")]
8664 (define_insn "*ifcompare_arith_move"
8665   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8666         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8667                           [(match_operand:SI 2 "s_register_operand" "r,r")
8668                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8669                          (match_operator:SI 7 "shiftable_operator"
8670                           [(match_operand:SI 4 "s_register_operand" "r,r")
8671                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8672                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8673    (clobber (reg:CC CC_REGNUM))]
8674   "TARGET_ARM"
8675   "*
8676   /* If we have an operation where (op x 0) is the identity operation and
8677      the conditional operator is LT or GE and we are comparing against zero and
8678      everything is in registers then we can do this in two instructions.  */
8679   if (operands[3] == const0_rtx
8680       && GET_CODE (operands[7]) != AND
8681       && GET_CODE (operands[5]) == REG
8682       && GET_CODE (operands[1]) == REG 
8683       && REGNO (operands[1]) == REGNO (operands[4])
8684       && REGNO (operands[4]) != REGNO (operands[0]))
8685     {
8686       if (GET_CODE (operands[6]) == LT)
8687         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8688       else if (GET_CODE (operands[6]) == GE)
8689         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8690     }
8691   if (GET_CODE (operands[3]) == CONST_INT
8692       && !const_ok_for_arm (INTVAL (operands[3])))
8693     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8694   else
8695     output_asm_insn (\"cmp\\t%2, %3\", operands);
8696   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8697   if (which_alternative != 0)
8698     return \"mov%D6\\t%0, %1\";
8699   return \"\";
8700   "
8701   [(set_attr "conds" "clob")
8702    (set_attr "length" "8,12")]
8705 (define_insn "*if_arith_move"
8706   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8707         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8708                           [(match_operand 6 "cc_register" "") (const_int 0)])
8709                          (match_operator:SI 5 "shiftable_operator"
8710                           [(match_operand:SI 2 "s_register_operand" "r,r")
8711                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8712                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8713   "TARGET_ARM"
8714   "@
8715    %I5%d4\\t%0, %2, %3
8716    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8717   [(set_attr "conds" "use")
8718    (set_attr "length" "4,8")
8719    (set_attr "type" "*,*")]
8722 (define_insn "*ifcompare_move_arith"
8723   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8724         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8725                           [(match_operand:SI 4 "s_register_operand" "r,r")
8726                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8727                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8728                          (match_operator:SI 7 "shiftable_operator"
8729                           [(match_operand:SI 2 "s_register_operand" "r,r")
8730                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8731    (clobber (reg:CC CC_REGNUM))]
8732   "TARGET_ARM"
8733   "*
8734   /* If we have an operation where (op x 0) is the identity operation and
8735      the conditional operator is LT or GE and we are comparing against zero and
8736      everything is in registers then we can do this in two instructions */
8737   if (operands[5] == const0_rtx
8738       && GET_CODE (operands[7]) != AND
8739       && GET_CODE (operands[3]) == REG
8740       && GET_CODE (operands[1]) == REG 
8741       && REGNO (operands[1]) == REGNO (operands[2])
8742       && REGNO (operands[2]) != REGNO (operands[0]))
8743     {
8744       if (GET_CODE (operands[6]) == GE)
8745         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8746       else if (GET_CODE (operands[6]) == LT)
8747         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8748     }
8750   if (GET_CODE (operands[5]) == CONST_INT
8751       && !const_ok_for_arm (INTVAL (operands[5])))
8752     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
8753   else
8754     output_asm_insn (\"cmp\\t%4, %5\", operands);
8756   if (which_alternative != 0)
8757     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
8758   return \"%I7%D6\\t%0, %2, %3\";
8759   "
8760   [(set_attr "conds" "clob")
8761    (set_attr "length" "8,12")]
8764 (define_insn "*if_move_arith"
8765   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8766         (if_then_else:SI
8767          (match_operator 4 "arm_comparison_operator"
8768           [(match_operand 6 "cc_register" "") (const_int 0)])
8769          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8770          (match_operator:SI 5 "shiftable_operator"
8771           [(match_operand:SI 2 "s_register_operand" "r,r")
8772            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
8773   "TARGET_ARM"
8774   "@
8775    %I5%D4\\t%0, %2, %3
8776    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8777   [(set_attr "conds" "use")
8778    (set_attr "length" "4,8")
8779    (set_attr "type" "*,*")]
8782 (define_insn "*ifcompare_move_not"
8783   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8784         (if_then_else:SI
8785          (match_operator 5 "arm_comparison_operator"
8786           [(match_operand:SI 3 "s_register_operand" "r,r")
8787            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8788          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8789          (not:SI
8790           (match_operand:SI 2 "s_register_operand" "r,r"))))
8791    (clobber (reg:CC CC_REGNUM))]
8792   "TARGET_ARM"
8793   "#"
8794   [(set_attr "conds" "clob")
8795    (set_attr "length" "8,12")]
8798 (define_insn "*if_move_not"
8799   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8800         (if_then_else:SI
8801          (match_operator 4 "arm_comparison_operator"
8802           [(match_operand 3 "cc_register" "") (const_int 0)])
8803          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8804          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8805   "TARGET_ARM"
8806   "@
8807    mvn%D4\\t%0, %2
8808    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
8809    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8810   [(set_attr "conds" "use")
8811    (set_attr "length" "4,8,8")]
8814 (define_insn "*ifcompare_not_move"
8815   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8816         (if_then_else:SI 
8817          (match_operator 5 "arm_comparison_operator"
8818           [(match_operand:SI 3 "s_register_operand" "r,r")
8819            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8820          (not:SI
8821           (match_operand:SI 2 "s_register_operand" "r,r"))
8822          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8823    (clobber (reg:CC CC_REGNUM))]
8824   "TARGET_ARM"
8825   "#"
8826   [(set_attr "conds" "clob")
8827    (set_attr "length" "8,12")]
8830 (define_insn "*if_not_move"
8831   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8832         (if_then_else:SI
8833          (match_operator 4 "arm_comparison_operator"
8834           [(match_operand 3 "cc_register" "") (const_int 0)])
8835          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8836          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8837   "TARGET_ARM"
8838   "@
8839    mvn%d4\\t%0, %2
8840    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
8841    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8842   [(set_attr "conds" "use")
8843    (set_attr "length" "4,8,8")]
8846 (define_insn "*ifcompare_shift_move"
8847   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8848         (if_then_else:SI
8849          (match_operator 6 "arm_comparison_operator"
8850           [(match_operand:SI 4 "s_register_operand" "r,r")
8851            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8852          (match_operator:SI 7 "shift_operator"
8853           [(match_operand:SI 2 "s_register_operand" "r,r")
8854            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
8855          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8856    (clobber (reg:CC CC_REGNUM))]
8857   "TARGET_ARM"
8858   "#"
8859   [(set_attr "conds" "clob")
8860    (set_attr "length" "8,12")]
8863 (define_insn "*if_shift_move"
8864   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8865         (if_then_else:SI
8866          (match_operator 5 "arm_comparison_operator"
8867           [(match_operand 6 "cc_register" "") (const_int 0)])
8868          (match_operator:SI 4 "shift_operator"
8869           [(match_operand:SI 2 "s_register_operand" "r,r,r")
8870            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
8871          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8872   "TARGET_ARM"
8873   "@
8874    mov%d5\\t%0, %2%S4
8875    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
8876    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8877   [(set_attr "conds" "use")
8878    (set_attr "shift" "2")
8879    (set_attr "length" "4,8,8")
8880    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
8881                       (const_string "alu_shift")
8882                       (const_string "alu_shift_reg")))]
8885 (define_insn "*ifcompare_move_shift"
8886   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8887         (if_then_else:SI
8888          (match_operator 6 "arm_comparison_operator"
8889           [(match_operand:SI 4 "s_register_operand" "r,r")
8890            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8891          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8892          (match_operator:SI 7 "shift_operator"
8893           [(match_operand:SI 2 "s_register_operand" "r,r")
8894            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
8895    (clobber (reg:CC CC_REGNUM))]
8896   "TARGET_ARM"
8897   "#"
8898   [(set_attr "conds" "clob")
8899    (set_attr "length" "8,12")]
8902 (define_insn "*if_move_shift"
8903   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8904         (if_then_else:SI
8905          (match_operator 5 "arm_comparison_operator"
8906           [(match_operand 6 "cc_register" "") (const_int 0)])
8907          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8908          (match_operator:SI 4 "shift_operator"
8909           [(match_operand:SI 2 "s_register_operand" "r,r,r")
8910            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
8911   "TARGET_ARM"
8912   "@
8913    mov%D5\\t%0, %2%S4
8914    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
8915    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8916   [(set_attr "conds" "use")
8917    (set_attr "shift" "2")
8918    (set_attr "length" "4,8,8")
8919    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
8920                       (const_string "alu_shift")
8921                       (const_string "alu_shift_reg")))]
8924 (define_insn "*ifcompare_shift_shift"
8925   [(set (match_operand:SI 0 "s_register_operand" "=r")
8926         (if_then_else:SI
8927          (match_operator 7 "arm_comparison_operator"
8928           [(match_operand:SI 5 "s_register_operand" "r")
8929            (match_operand:SI 6 "arm_add_operand" "rIL")])
8930          (match_operator:SI 8 "shift_operator"
8931           [(match_operand:SI 1 "s_register_operand" "r")
8932            (match_operand:SI 2 "arm_rhs_operand" "rM")])
8933          (match_operator:SI 9 "shift_operator"
8934           [(match_operand:SI 3 "s_register_operand" "r")
8935            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
8936    (clobber (reg:CC CC_REGNUM))]
8937   "TARGET_ARM"
8938   "#"
8939   [(set_attr "conds" "clob")
8940    (set_attr "length" "12")]
8943 (define_insn "*if_shift_shift"
8944   [(set (match_operand:SI 0 "s_register_operand" "=r")
8945         (if_then_else:SI
8946          (match_operator 5 "arm_comparison_operator"
8947           [(match_operand 8 "cc_register" "") (const_int 0)])
8948          (match_operator:SI 6 "shift_operator"
8949           [(match_operand:SI 1 "s_register_operand" "r")
8950            (match_operand:SI 2 "arm_rhs_operand" "rM")])
8951          (match_operator:SI 7 "shift_operator"
8952           [(match_operand:SI 3 "s_register_operand" "r")
8953            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
8954   "TARGET_ARM"
8955   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8956   [(set_attr "conds" "use")
8957    (set_attr "shift" "1")
8958    (set_attr "length" "8")
8959    (set (attr "type") (if_then_else
8960                         (and (match_operand 2 "const_int_operand" "")
8961                              (match_operand 4 "const_int_operand" ""))
8962                       (const_string "alu_shift")
8963                       (const_string "alu_shift_reg")))]
8966 (define_insn "*ifcompare_not_arith"
8967   [(set (match_operand:SI 0 "s_register_operand" "=r")
8968         (if_then_else:SI
8969          (match_operator 6 "arm_comparison_operator"
8970           [(match_operand:SI 4 "s_register_operand" "r")
8971            (match_operand:SI 5 "arm_add_operand" "rIL")])
8972          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8973          (match_operator:SI 7 "shiftable_operator"
8974           [(match_operand:SI 2 "s_register_operand" "r")
8975            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
8976    (clobber (reg:CC CC_REGNUM))]
8977   "TARGET_ARM"
8978   "#"
8979   [(set_attr "conds" "clob")
8980    (set_attr "length" "12")]
8983 (define_insn "*if_not_arith"
8984   [(set (match_operand:SI 0 "s_register_operand" "=r")
8985         (if_then_else:SI
8986          (match_operator 5 "arm_comparison_operator"
8987           [(match_operand 4 "cc_register" "") (const_int 0)])
8988          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8989          (match_operator:SI 6 "shiftable_operator"
8990           [(match_operand:SI 2 "s_register_operand" "r")
8991            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
8992   "TARGET_ARM"
8993   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8994   [(set_attr "conds" "use")
8995    (set_attr "length" "8")]
8998 (define_insn "*ifcompare_arith_not"
8999   [(set (match_operand:SI 0 "s_register_operand" "=r")
9000         (if_then_else:SI
9001          (match_operator 6 "arm_comparison_operator"
9002           [(match_operand:SI 4 "s_register_operand" "r")
9003            (match_operand:SI 5 "arm_add_operand" "rIL")])
9004          (match_operator:SI 7 "shiftable_operator"
9005           [(match_operand:SI 2 "s_register_operand" "r")
9006            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9007          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9008    (clobber (reg:CC CC_REGNUM))]
9009   "TARGET_ARM"
9010   "#"
9011   [(set_attr "conds" "clob")
9012    (set_attr "length" "12")]
9015 (define_insn "*if_arith_not"
9016   [(set (match_operand:SI 0 "s_register_operand" "=r")
9017         (if_then_else:SI
9018          (match_operator 5 "arm_comparison_operator"
9019           [(match_operand 4 "cc_register" "") (const_int 0)])
9020          (match_operator:SI 6 "shiftable_operator"
9021           [(match_operand:SI 2 "s_register_operand" "r")
9022            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9023          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9024   "TARGET_ARM"
9025   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9026   [(set_attr "conds" "use")
9027    (set_attr "length" "8")]
9030 (define_insn "*ifcompare_neg_move"
9031   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9032         (if_then_else:SI
9033          (match_operator 5 "arm_comparison_operator"
9034           [(match_operand:SI 3 "s_register_operand" "r,r")
9035            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9036          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9037          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9038    (clobber (reg:CC CC_REGNUM))]
9039   "TARGET_ARM"
9040   "#"
9041   [(set_attr "conds" "clob")
9042    (set_attr "length" "8,12")]
9045 (define_insn "*if_neg_move"
9046   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9047         (if_then_else:SI
9048          (match_operator 4 "arm_comparison_operator"
9049           [(match_operand 3 "cc_register" "") (const_int 0)])
9050          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9051          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9052   "TARGET_ARM"
9053   "@
9054    rsb%d4\\t%0, %2, #0
9055    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9056    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9057   [(set_attr "conds" "use")
9058    (set_attr "length" "4,8,8")]
9061 (define_insn "*ifcompare_move_neg"
9062   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9063         (if_then_else:SI
9064          (match_operator 5 "arm_comparison_operator"
9065           [(match_operand:SI 3 "s_register_operand" "r,r")
9066            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9067          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9068          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9069    (clobber (reg:CC CC_REGNUM))]
9070   "TARGET_ARM"
9071   "#"
9072   [(set_attr "conds" "clob")
9073    (set_attr "length" "8,12")]
9076 (define_insn "*if_move_neg"
9077   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9078         (if_then_else:SI
9079          (match_operator 4 "arm_comparison_operator"
9080           [(match_operand 3 "cc_register" "") (const_int 0)])
9081          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9082          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9083   "TARGET_ARM"
9084   "@
9085    rsb%D4\\t%0, %2, #0
9086    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9087    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9088   [(set_attr "conds" "use")
9089    (set_attr "length" "4,8,8")]
9092 (define_insn "*arith_adjacentmem"
9093   [(set (match_operand:SI 0 "s_register_operand" "=r")
9094         (match_operator:SI 1 "shiftable_operator"
9095          [(match_operand:SI 2 "memory_operand" "m")
9096           (match_operand:SI 3 "memory_operand" "m")]))
9097    (clobber (match_scratch:SI 4 "=r"))]
9098   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9099   "*
9100   {
9101     rtx ldm[3];
9102     rtx arith[4];
9103     int val1 = 0, val2 = 0;
9105     if (REGNO (operands[0]) > REGNO (operands[4]))
9106       {
9107         ldm[1] = operands[4];
9108         ldm[2] = operands[0];
9109       }
9110     else
9111       {
9112         ldm[1] = operands[0];
9113         ldm[2] = operands[4];
9114       }
9115     if (GET_CODE (XEXP (operands[2], 0)) != REG)
9116       val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
9117     if (GET_CODE (XEXP (operands[3], 0)) != REG)
9118       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9119     arith[0] = operands[0];
9120     arith[3] = operands[1];
9121     if (val1 < val2)
9122       {
9123         arith[1] = ldm[1];
9124         arith[2] = ldm[2];
9125       }
9126     else
9127       {
9128         arith[1] = ldm[2];
9129         arith[2] = ldm[1];
9130       }
9131    if (val1 && val2)
9132       {
9133         rtx ops[3];
9134         ldm[0] = ops[0] = operands[4];
9135         ops[1] = XEXP (XEXP (operands[2], 0), 0);
9136         ops[2] = XEXP (XEXP (operands[2], 0), 1);
9137         output_add_immediate (ops);
9138         if (val1 < val2)
9139           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9140         else
9141           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9142       }
9143     else if (val1)
9144       {
9145         ldm[0] = XEXP (operands[3], 0);
9146         if (val1 < val2)
9147           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9148         else
9149           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9150       }
9151     else
9152       {
9153         ldm[0] = XEXP (operands[2], 0);
9154         if (val1 < val2)
9155           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9156         else
9157           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9158       }
9159     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9160     return \"\";
9161   }"
9162   [(set_attr "length" "12")
9163    (set_attr "predicable" "yes")
9164    (set_attr "type" "load1")]
9167 ;; the arm can support extended pre-inc instructions
9169 ;; In all these cases, we use operands 0 and 1 for the register being
9170 ;; incremented because those are the operands that local-alloc will
9171 ;; tie and these are the pair most likely to be tieable (and the ones
9172 ;; that will benefit the most).
9174 ;; We reject the frame pointer if it occurs anywhere in these patterns since
9175 ;; elimination will cause too many headaches.
9177 (define_insn "*strqi_preinc"
9178   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9179                          (match_operand:SI 2 "index_operand" "rJ")))
9180         (match_operand:QI 3 "s_register_operand" "r"))
9181    (set (match_operand:SI 0 "s_register_operand" "=r")
9182         (plus:SI (match_dup 1) (match_dup 2)))]
9183   "TARGET_ARM
9184    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9185    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9186    && (GET_CODE (operands[2]) != REG
9187        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9188   "str%?b\\t%3, [%0, %2]!"
9189   [(set_attr "type" "store1")
9190    (set_attr "predicable" "yes")]
9193 (define_insn "*strqi_predec"
9194   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9195                           (match_operand:SI 2 "s_register_operand" "r")))
9196         (match_operand:QI 3 "s_register_operand" "r"))
9197    (set (match_operand:SI 0 "s_register_operand" "=r")
9198         (minus:SI (match_dup 1) (match_dup 2)))]
9199   "TARGET_ARM
9200    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9201    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9202    && (GET_CODE (operands[2]) != REG
9203        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9204   "str%?b\\t%3, [%0, -%2]!"
9205   [(set_attr "type" "store1")
9206    (set_attr "predicable" "yes")]
9209 (define_insn "*loadqi_preinc"
9210   [(set (match_operand:QI 3 "s_register_operand" "=r")
9211         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9212                          (match_operand:SI 2 "index_operand" "rJ"))))
9213    (set (match_operand:SI 0 "s_register_operand" "=r")
9214         (plus:SI (match_dup 1) (match_dup 2)))]
9215   "TARGET_ARM
9216    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9217    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9218    && (GET_CODE (operands[2]) != REG
9219        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9220   "ldr%?b\\t%3, [%0, %2]!"
9221   [(set_attr "type" "load_byte")
9222    (set_attr "predicable" "yes")]
9225 (define_insn "*loadqi_predec"
9226   [(set (match_operand:QI 3 "s_register_operand" "=r")
9227         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9228                           (match_operand:SI 2 "s_register_operand" "r"))))
9229    (set (match_operand:SI 0 "s_register_operand" "=r")
9230         (minus:SI (match_dup 1) (match_dup 2)))]
9231   "TARGET_ARM
9232    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9233    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9234    && (GET_CODE (operands[2]) != REG
9235        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9236   "ldr%?b\\t%3, [%0, -%2]!"
9237   [(set_attr "type" "load_byte")
9238    (set_attr "predicable" "yes")]
9241 (define_insn "*loadqisi_preinc"
9242   [(set (match_operand:SI 3 "s_register_operand" "=r")
9243         (zero_extend:SI
9244          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9245                           (match_operand:SI 2 "index_operand" "rJ")))))
9246    (set (match_operand:SI 0 "s_register_operand" "=r")
9247         (plus:SI (match_dup 1) (match_dup 2)))]
9248   "TARGET_ARM
9249    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9250    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9251    && (GET_CODE (operands[2]) != REG
9252        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9253   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
9254   [(set_attr "type" "load_byte")
9255    (set_attr "predicable" "yes")]
9258 (define_insn "*loadqisi_predec"
9259   [(set (match_operand:SI 3 "s_register_operand" "=r")
9260         (zero_extend:SI
9261          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9262                            (match_operand:SI 2 "s_register_operand" "r")))))
9263    (set (match_operand:SI 0 "s_register_operand" "=r")
9264         (minus:SI (match_dup 1) (match_dup 2)))]
9265   "TARGET_ARM
9266    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9267    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9268    && (GET_CODE (operands[2]) != REG
9269        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9270   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
9271   [(set_attr "type" "load_byte")
9272    (set_attr "predicable" "yes")]
9275 (define_insn "*strsi_preinc"
9276   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9277                          (match_operand:SI 2 "index_operand" "rJ")))
9278         (match_operand:SI 3 "s_register_operand" "r"))
9279    (set (match_operand:SI 0 "s_register_operand" "=r")
9280         (plus:SI (match_dup 1) (match_dup 2)))]
9281   "TARGET_ARM
9282    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9283    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9284    && (GET_CODE (operands[2]) != REG
9285        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9286   "str%?\\t%3, [%0, %2]!"
9287   [(set_attr "type" "store1")
9288    (set_attr "predicable" "yes")]
9291 (define_insn "*strsi_predec"
9292   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9293                           (match_operand:SI 2 "s_register_operand" "r")))
9294         (match_operand:SI 3 "s_register_operand" "r"))
9295    (set (match_operand:SI 0 "s_register_operand" "=r")
9296         (minus:SI (match_dup 1) (match_dup 2)))]
9297   "TARGET_ARM
9298    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9299    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9300    && (GET_CODE (operands[2]) != REG
9301        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9302   "str%?\\t%3, [%0, -%2]!"
9303   [(set_attr "type" "store1")
9304    (set_attr "predicable" "yes")]
9307 (define_insn "*loadsi_preinc"
9308   [(set (match_operand:SI 3 "s_register_operand" "=r")
9309         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9310                          (match_operand:SI 2 "index_operand" "rJ"))))
9311    (set (match_operand:SI 0 "s_register_operand" "=r")
9312         (plus:SI (match_dup 1) (match_dup 2)))]
9313   "TARGET_ARM
9314    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9315    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9316    && (GET_CODE (operands[2]) != REG
9317        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9318   "ldr%?\\t%3, [%0, %2]!"
9319   [(set_attr "type" "load1")
9320    (set_attr "predicable" "yes")]
9323 (define_insn "*loadsi_predec"
9324   [(set (match_operand:SI 3 "s_register_operand" "=r")
9325         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9326                           (match_operand:SI 2 "s_register_operand" "r"))))
9327    (set (match_operand:SI 0 "s_register_operand" "=r")
9328         (minus:SI (match_dup 1) (match_dup 2)))]
9329   "TARGET_ARM
9330    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9331    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9332    && (GET_CODE (operands[2]) != REG
9333        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9334   "ldr%?\\t%3, [%0, -%2]!"
9335   [(set_attr "type" "load1")
9336    (set_attr "predicable" "yes")]
9339 (define_insn "*strqi_shiftpreinc"
9340   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9341                           [(match_operand:SI 3 "s_register_operand" "r")
9342                            (match_operand:SI 4 "const_shift_operand" "n")])
9343                          (match_operand:SI 1 "s_register_operand" "0")))
9344         (match_operand:QI 5 "s_register_operand" "r"))
9345    (set (match_operand:SI 0 "s_register_operand" "=r")
9346         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9347                  (match_dup 1)))]
9348   "TARGET_ARM
9349    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9350    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9351    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9352   "str%?b\\t%5, [%0, %3%S2]!"
9353   [(set_attr "type" "store1")
9354    (set_attr "predicable" "yes")]
9357 (define_insn "*strqi_shiftpredec"
9358   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9359                           (match_operator:SI 2 "shift_operator"
9360                            [(match_operand:SI 3 "s_register_operand" "r")
9361                             (match_operand:SI 4 "const_shift_operand" "n")])))
9362         (match_operand:QI 5 "s_register_operand" "r"))
9363    (set (match_operand:SI 0 "s_register_operand" "=r")
9364         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9365                                                  (match_dup 4)])))]
9366   "TARGET_ARM
9367    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9368    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9369    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9370   "str%?b\\t%5, [%0, -%3%S2]!"
9371   [(set_attr "type" "store1")
9372    (set_attr "predicable" "yes")]
9375 (define_insn "*loadqi_shiftpreinc"
9376   [(set (match_operand:QI 5 "s_register_operand" "=r")
9377         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9378                           [(match_operand:SI 3 "s_register_operand" "r")
9379                            (match_operand:SI 4 "const_shift_operand" "n")])
9380                          (match_operand:SI 1 "s_register_operand" "0"))))
9381    (set (match_operand:SI 0 "s_register_operand" "=r")
9382         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9383                  (match_dup 1)))]
9384   "TARGET_ARM
9385    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9386    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9387    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9388   "ldr%?b\\t%5, [%0, %3%S2]!"
9389   [(set_attr "type" "load_byte")
9390    (set_attr "predicable" "yes")]
9393 (define_insn "*loadqi_shiftpredec"
9394   [(set (match_operand:QI 5 "s_register_operand" "=r")
9395         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9396                           (match_operator:SI 2 "shift_operator"
9397                            [(match_operand:SI 3 "s_register_operand" "r")
9398                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9399    (set (match_operand:SI 0 "s_register_operand" "=r")
9400         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9401                                                  (match_dup 4)])))]
9402   "TARGET_ARM
9403    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9404    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9405    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9406   "ldr%?b\\t%5, [%0, -%3%S2]!"
9407   [(set_attr "type" "load_byte")
9408    (set_attr "predicable" "yes")]
9411 (define_insn "*strsi_shiftpreinc"
9412   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9413                           [(match_operand:SI 3 "s_register_operand" "r")
9414                            (match_operand:SI 4 "const_shift_operand" "n")])
9415                          (match_operand:SI 1 "s_register_operand" "0")))
9416         (match_operand:SI 5 "s_register_operand" "r"))
9417    (set (match_operand:SI 0 "s_register_operand" "=r")
9418         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9419                  (match_dup 1)))]
9420   "TARGET_ARM
9421    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9422    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9423    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9424   "str%?\\t%5, [%0, %3%S2]!"
9425   [(set_attr "type" "store1")
9426    (set_attr "predicable" "yes")]
9429 (define_insn "*strsi_shiftpredec"
9430   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9431                           (match_operator:SI 2 "shift_operator"
9432                            [(match_operand:SI 3 "s_register_operand" "r")
9433                             (match_operand:SI 4 "const_shift_operand" "n")])))
9434         (match_operand:SI 5 "s_register_operand" "r"))
9435    (set (match_operand:SI 0 "s_register_operand" "=r")
9436         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9437                                                  (match_dup 4)])))]
9438   "TARGET_ARM
9439    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9440    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9441    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9442   "str%?\\t%5, [%0, -%3%S2]!"
9443   [(set_attr "type" "store1")
9444    (set_attr "predicable" "yes")]
9447 (define_insn "*loadsi_shiftpreinc"
9448   [(set (match_operand:SI 5 "s_register_operand" "=r")
9449         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9450                           [(match_operand:SI 3 "s_register_operand" "r")
9451                            (match_operand:SI 4 "const_shift_operand" "n")])
9452                          (match_operand:SI 1 "s_register_operand" "0"))))
9453    (set (match_operand:SI 0 "s_register_operand" "=r")
9454         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9455                  (match_dup 1)))]
9456   "TARGET_ARM
9457    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9458    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9459    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9460   "ldr%?\\t%5, [%0, %3%S2]!"
9461   [(set_attr "type" "load1")
9462    (set_attr "predicable" "yes")]
9465 (define_insn "*loadsi_shiftpredec"
9466   [(set (match_operand:SI 5 "s_register_operand" "=r")
9467         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9468                           (match_operator:SI 2 "shift_operator"
9469                            [(match_operand:SI 3 "s_register_operand" "r")
9470                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9471    (set (match_operand:SI 0 "s_register_operand" "=r")
9472         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9473                                                  (match_dup 4)])))]
9474   "TARGET_ARM
9475    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9476    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9477    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9478   "ldr%?\\t%5, [%0, -%3%S2]!"
9479   [(set_attr "type" "load1")
9480    (set_attr "predicable" "yes")])
9482 ; It can also support extended post-inc expressions, but combine doesn't
9483 ; try these....
9484 ; It doesn't seem worth adding peepholes for anything but the most common
9485 ; cases since, unlike combine, the increment must immediately follow the load
9486 ; for this pattern to match.
9487 ; We must watch to see that the source/destination register isn't also the
9488 ; same as the base address register, and that if the index is a register,
9489 ; that it is not the same as the base address register.  In such cases the
9490 ; instruction that we would generate would have UNPREDICTABLE behavior so 
9491 ; we cannot use it.
9493 (define_peephole
9494   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9495         (match_operand:QI 2 "s_register_operand" "r"))
9496    (set (match_dup 0)
9497         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9498   "TARGET_ARM
9499    && (REGNO (operands[2]) != REGNO (operands[0]))
9500    && (GET_CODE (operands[1]) != REG
9501        || (REGNO (operands[1]) != REGNO (operands[0])))"
9502   "str%?b\\t%2, [%0], %1"
9505 (define_peephole
9506   [(set (match_operand:QI 0 "s_register_operand" "=r")
9507         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9508    (set (match_dup 1)
9509         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9510   "TARGET_ARM
9511    && REGNO (operands[0]) != REGNO(operands[1])
9512    && (GET_CODE (operands[2]) != REG
9513        || REGNO(operands[0]) != REGNO (operands[2]))"
9514   "ldr%?b\\t%0, [%1], %2"
9517 (define_peephole
9518   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9519         (match_operand:SI 2 "s_register_operand" "r"))
9520    (set (match_dup 0)
9521         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9522   "TARGET_ARM
9523    && (REGNO (operands[2]) != REGNO (operands[0]))
9524    && (GET_CODE (operands[1]) != REG
9525        || (REGNO (operands[1]) != REGNO (operands[0])))"
9526   "str%?\\t%2, [%0], %1"
9529 (define_peephole
9530   [(set (match_operand:SI 0 "s_register_operand" "=r")
9531         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9532    (set (match_dup 1)
9533         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9534   "TARGET_ARM
9535    && REGNO (operands[0]) != REGNO(operands[1])
9536    && (GET_CODE (operands[2]) != REG
9537        || REGNO(operands[0]) != REGNO (operands[2]))"
9538   "ldr%?\\t%0, [%1], %2"
9541 (define_peephole
9542   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9543                          (match_operand:SI 1 "index_operand" "rJ")))
9544         (match_operand:QI 2 "s_register_operand" "r"))
9545    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
9546   "TARGET_ARM
9547    && (REGNO (operands[2]) != REGNO (operands[0]))
9548    && (GET_CODE (operands[1]) != REG
9549        || (REGNO (operands[1]) != REGNO (operands[0])))"
9550   "str%?b\\t%2, [%0, %1]!"
9553 (define_peephole
9554   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9555                           [(match_operand:SI 0 "s_register_operand" "r")
9556                            (match_operand:SI 1 "const_int_operand" "n")])
9557                          (match_operand:SI 2 "s_register_operand" "+r")))
9558         (match_operand:QI 3 "s_register_operand" "r"))
9559    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9560                                (match_dup 2)))]
9561   "TARGET_ARM
9562    && (REGNO (operands[3]) != REGNO (operands[2]))
9563    && (REGNO (operands[0]) != REGNO (operands[2]))"
9564   "str%?b\\t%3, [%2, %0%S4]!"
9567 ; This pattern is never tried by combine, so do it as a peephole
9569 (define_peephole2
9570   [(set (match_operand:SI 0 "arm_general_register_operand" "")
9571         (match_operand:SI 1 "arm_general_register_operand" ""))
9572    (set (reg:CC CC_REGNUM)
9573         (compare:CC (match_dup 1) (const_int 0)))]
9574   "TARGET_ARM"
9575   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9576               (set (match_dup 0) (match_dup 1))])]
9577   ""
9580 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9581 ; reversed, check that the memory references aren't volatile.
9583 (define_peephole
9584   [(set (match_operand:SI 0 "s_register_operand" "=r")
9585         (match_operand:SI 4 "memory_operand" "m"))
9586    (set (match_operand:SI 1 "s_register_operand" "=r")
9587         (match_operand:SI 5 "memory_operand" "m"))
9588    (set (match_operand:SI 2 "s_register_operand" "=r")
9589         (match_operand:SI 6 "memory_operand" "m"))
9590    (set (match_operand:SI 3 "s_register_operand" "=r")
9591         (match_operand:SI 7 "memory_operand" "m"))]
9592   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9593   "*
9594   return emit_ldm_seq (operands, 4);
9595   "
9598 (define_peephole
9599   [(set (match_operand:SI 0 "s_register_operand" "=r")
9600         (match_operand:SI 3 "memory_operand" "m"))
9601    (set (match_operand:SI 1 "s_register_operand" "=r")
9602         (match_operand:SI 4 "memory_operand" "m"))
9603    (set (match_operand:SI 2 "s_register_operand" "=r")
9604         (match_operand:SI 5 "memory_operand" "m"))]
9605   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9606   "*
9607   return emit_ldm_seq (operands, 3);
9608   "
9611 (define_peephole
9612   [(set (match_operand:SI 0 "s_register_operand" "=r")
9613         (match_operand:SI 2 "memory_operand" "m"))
9614    (set (match_operand:SI 1 "s_register_operand" "=r")
9615         (match_operand:SI 3 "memory_operand" "m"))]
9616   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9617   "*
9618   return emit_ldm_seq (operands, 2);
9619   "
9622 (define_peephole
9623   [(set (match_operand:SI 4 "memory_operand" "=m")
9624         (match_operand:SI 0 "s_register_operand" "r"))
9625    (set (match_operand:SI 5 "memory_operand" "=m")
9626         (match_operand:SI 1 "s_register_operand" "r"))
9627    (set (match_operand:SI 6 "memory_operand" "=m")
9628         (match_operand:SI 2 "s_register_operand" "r"))
9629    (set (match_operand:SI 7 "memory_operand" "=m")
9630         (match_operand:SI 3 "s_register_operand" "r"))]
9631   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9632   "*
9633   return emit_stm_seq (operands, 4);
9634   "
9637 (define_peephole
9638   [(set (match_operand:SI 3 "memory_operand" "=m")
9639         (match_operand:SI 0 "s_register_operand" "r"))
9640    (set (match_operand:SI 4 "memory_operand" "=m")
9641         (match_operand:SI 1 "s_register_operand" "r"))
9642    (set (match_operand:SI 5 "memory_operand" "=m")
9643         (match_operand:SI 2 "s_register_operand" "r"))]
9644   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9645   "*
9646   return emit_stm_seq (operands, 3);
9647   "
9650 (define_peephole
9651   [(set (match_operand:SI 2 "memory_operand" "=m")
9652         (match_operand:SI 0 "s_register_operand" "r"))
9653    (set (match_operand:SI 3 "memory_operand" "=m")
9654         (match_operand:SI 1 "s_register_operand" "r"))]
9655   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9656   "*
9657   return emit_stm_seq (operands, 2);
9658   "
9661 (define_split
9662   [(set (match_operand:SI 0 "s_register_operand" "")
9663         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9664                        (const_int 0))
9665                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9666                          [(match_operand:SI 3 "s_register_operand" "")
9667                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
9668    (clobber (match_operand:SI 5 "s_register_operand" ""))]
9669   "TARGET_ARM"
9670   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9671    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9672                               (match_dup 5)))]
9673   ""
9676 ;; This split can be used because CC_Z mode implies that the following
9677 ;; branch will be an equality, or an unsigned inequality, so the sign
9678 ;; extension is not needed.
9680 (define_split
9681   [(set (reg:CC_Z CC_REGNUM)
9682         (compare:CC_Z
9683          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9684                     (const_int 24))
9685          (match_operand 1 "const_int_operand" "")))
9686    (clobber (match_scratch:SI 2 ""))]
9687   "TARGET_ARM
9688    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9689        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9690   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9691    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9692   "
9693   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9694   "
9697 (define_expand "prologue"
9698   [(clobber (const_int 0))]
9699   "TARGET_EITHER"
9700   "if (TARGET_ARM)
9701      arm_expand_prologue ();
9702    else
9703      thumb_expand_prologue ();
9704   DONE;
9705   "
9708 (define_expand "epilogue"
9709   [(clobber (const_int 0))]
9710   "TARGET_EITHER"
9711   "
9712   if (current_function_calls_eh_return)
9713     emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
9714   if (TARGET_THUMB)
9715     thumb_expand_epilogue ();
9716   else if (USE_RETURN_INSN (FALSE))
9717     {
9718       emit_jump_insn (gen_return ());
9719       DONE;
9720     }
9721   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9722         gen_rtvec (1,
9723                 gen_rtx_RETURN (VOIDmode)),
9724         VUNSPEC_EPILOGUE));
9725   DONE;
9726   "
9729 ;; Note - although unspec_volatile's USE all hard registers,
9730 ;; USEs are ignored after relaod has completed.  Thus we need
9731 ;; to add an unspec of the link register to ensure that flow
9732 ;; does not think that it is unused by the sibcall branch that
9733 ;; will replace the standard function epilogue.
9734 (define_insn "sibcall_epilogue"
9735   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9736               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9737   "TARGET_ARM"
9738   "*
9739   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9740     return output_return_instruction (const_true_rtx, FALSE, FALSE);
9741   return arm_output_epilogue (next_nonnote_insn (insn));
9742   "
9743 ;; Length is absolute worst case
9744   [(set_attr "length" "44")
9745    (set_attr "type" "block")
9746    ;; We don't clobber the conditions, but the potential length of this
9747    ;; operation is sufficient to make conditionalizing the sequence 
9748    ;; unlikely to be profitable.
9749    (set_attr "conds" "clob")]
9752 (define_insn "*epilogue_insns"
9753   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9754   "TARGET_EITHER"
9755   "*
9756   if (TARGET_ARM)
9757     return arm_output_epilogue (NULL);
9758   else /* TARGET_THUMB */
9759     return thumb_unexpanded_epilogue ();
9760   "
9761   ; Length is absolute worst case
9762   [(set_attr "length" "44")
9763    (set_attr "type" "block")
9764    ;; We don't clobber the conditions, but the potential length of this
9765    ;; operation is sufficient to make conditionalizing the sequence 
9766    ;; unlikely to be profitable.
9767    (set_attr "conds" "clob")]
9770 (define_expand "eh_epilogue"
9771   [(use (match_operand:SI 0 "register_operand" ""))
9772    (use (match_operand:SI 1 "register_operand" ""))
9773    (use (match_operand:SI 2 "register_operand" ""))]
9774   "TARGET_EITHER"
9775   "
9776   {
9777     cfun->machine->eh_epilogue_sp_ofs = operands[1];
9778     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9779       {
9780         rtx ra = gen_rtx_REG (Pmode, 2);
9782         emit_move_insn (ra, operands[2]);
9783         operands[2] = ra;
9784       }
9785     /* This is a hack -- we may have crystalized the function type too
9786        early.  */
9787     cfun->machine->func_type = 0;
9788   }"
9791 ;; This split is only used during output to reduce the number of patterns
9792 ;; that need assembler instructions adding to them.  We allowed the setting
9793 ;; of the conditions to be implicit during rtl generation so that
9794 ;; the conditional compare patterns would work.  However this conflicts to
9795 ;; some extent with the conditional data operations, so we have to split them
9796 ;; up again here.
9798 (define_split
9799   [(set (match_operand:SI 0 "s_register_operand" "")
9800         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9801                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9802                          (match_dup 0)
9803                          (match_operand 4 "" "")))
9804    (clobber (reg:CC CC_REGNUM))]
9805   "TARGET_ARM && reload_completed"
9806   [(set (match_dup 5) (match_dup 6))
9807    (cond_exec (match_dup 7)
9808               (set (match_dup 0) (match_dup 4)))]
9809   "
9810   {
9811     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9812                                              operands[2], operands[3]);
9813     enum rtx_code rc = GET_CODE (operands[1]);
9815     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9816     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9817     if (mode == CCFPmode || mode == CCFPEmode)
9818       rc = reverse_condition_maybe_unordered (rc);
9819     else
9820       rc = reverse_condition (rc);
9822     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9823   }"
9826 (define_split
9827   [(set (match_operand:SI 0 "s_register_operand" "")
9828         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9829                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9830                          (match_operand 4 "" "")
9831                          (match_dup 0)))
9832    (clobber (reg:CC CC_REGNUM))]
9833   "TARGET_ARM && reload_completed"
9834   [(set (match_dup 5) (match_dup 6))
9835    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9836               (set (match_dup 0) (match_dup 4)))]
9837   "
9838   {
9839     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9840                                              operands[2], operands[3]);
9842     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9843     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9844   }"
9847 (define_split
9848   [(set (match_operand:SI 0 "s_register_operand" "")
9849         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9850                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9851                          (match_operand 4 "" "")
9852                          (match_operand 5 "" "")))
9853    (clobber (reg:CC CC_REGNUM))]
9854   "TARGET_ARM && reload_completed"
9855   [(set (match_dup 6) (match_dup 7))
9856    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9857               (set (match_dup 0) (match_dup 4)))
9858    (cond_exec (match_dup 8)
9859               (set (match_dup 0) (match_dup 5)))]
9860   "
9861   {
9862     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9863                                              operands[2], operands[3]);
9864     enum rtx_code rc = GET_CODE (operands[1]);
9866     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9867     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9868     if (mode == CCFPmode || mode == CCFPEmode)
9869       rc = reverse_condition_maybe_unordered (rc);
9870     else
9871       rc = reverse_condition (rc);
9873     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9874   }"
9877 (define_split
9878   [(set (match_operand:SI 0 "s_register_operand" "")
9879         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9880                           [(match_operand:SI 2 "s_register_operand" "")
9881                            (match_operand:SI 3 "arm_add_operand" "")])
9882                          (match_operand:SI 4 "arm_rhs_operand" "")
9883                          (not:SI
9884                           (match_operand:SI 5 "s_register_operand" ""))))
9885    (clobber (reg:CC CC_REGNUM))]
9886   "TARGET_ARM && reload_completed"
9887   [(set (match_dup 6) (match_dup 7))
9888    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9889               (set (match_dup 0) (match_dup 4)))
9890    (cond_exec (match_dup 8)
9891               (set (match_dup 0) (not:SI (match_dup 5))))]
9892   "
9893   {
9894     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9895                                              operands[2], operands[3]);
9896     enum rtx_code rc = GET_CODE (operands[1]);
9898     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9899     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9900     if (mode == CCFPmode || mode == CCFPEmode)
9901       rc = reverse_condition_maybe_unordered (rc);
9902     else
9903       rc = reverse_condition (rc);
9905     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9906   }"
9909 (define_insn "*cond_move_not"
9910   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9911         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9912                           [(match_operand 3 "cc_register" "") (const_int 0)])
9913                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9914                          (not:SI
9915                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
9916   "TARGET_ARM"
9917   "@
9918    mvn%D4\\t%0, %2
9919    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
9920   [(set_attr "conds" "use")
9921    (set_attr "length" "4,8")]
9924 ;; The next two patterns occur when an AND operation is followed by a
9925 ;; scc insn sequence 
9927 (define_insn "*sign_extract_onebit"
9928   [(set (match_operand:SI 0 "s_register_operand" "=r")
9929         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9930                          (const_int 1)
9931                          (match_operand:SI 2 "const_int_operand" "n")))
9932     (clobber (reg:CC CC_REGNUM))]
9933   "TARGET_ARM"
9934   "*
9935     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9936     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
9937     return \"mvnne\\t%0, #0\";
9938   "
9939   [(set_attr "conds" "clob")
9940    (set_attr "length" "8")]
9943 (define_insn "*not_signextract_onebit"
9944   [(set (match_operand:SI 0 "s_register_operand" "=r")
9945         (not:SI
9946          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9947                           (const_int 1)
9948                           (match_operand:SI 2 "const_int_operand" "n"))))
9949    (clobber (reg:CC CC_REGNUM))]
9950   "TARGET_ARM"
9951   "*
9952     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9953     output_asm_insn (\"tst\\t%1, %2\", operands);
9954     output_asm_insn (\"mvneq\\t%0, #0\", operands);
9955     return \"movne\\t%0, #0\";
9956   "
9957   [(set_attr "conds" "clob")
9958    (set_attr "length" "12")]
9961 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
9962 ;; expressions.  For simplicity, the first register is also in the unspec
9963 ;; part.
9964 (define_insn "*push_multi"
9965   [(match_parallel 2 "multi_register_push"
9966     [(set (match_operand:BLK 0 "memory_operand" "=m")
9967           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
9968                       UNSPEC_PUSH_MULT))])]
9969   "TARGET_ARM"
9970   "*
9971   {
9972     int num_saves = XVECLEN (operands[2], 0);
9973      
9974     /* For the StrongARM at least it is faster to
9975        use STR to store only a single register.  */
9976     if (num_saves == 1)
9977       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9978     else
9979       {
9980         int i;
9981         char pattern[100];
9983         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9985         for (i = 1; i < num_saves; i++)
9986           {
9987             strcat (pattern, \", %|\");
9988             strcat (pattern,
9989                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9990           }
9992         strcat (pattern, \"}\");
9993         output_asm_insn (pattern, operands);
9994       }
9996     return \"\";
9997   }"
9998   [(set_attr "type" "store4")]
10001 (define_insn "stack_tie"
10002   [(set (mem:BLK (scratch))
10003         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
10004                      (match_operand:SI 1 "s_register_operand" "r")]
10005                     UNSPEC_PRLG_STK))]
10006   ""
10007   ""
10008   [(set_attr "length" "0")]
10011 ;; Similarly for the floating point registers
10012 (define_insn "*push_fp_multi"
10013   [(match_parallel 2 "multi_register_push"
10014     [(set (match_operand:BLK 0 "memory_operand" "=m")
10015           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10016                       UNSPEC_PUSH_MULT))])]
10017   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
10018   "*
10019   {
10020     char pattern[100];
10022     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10023     output_asm_insn (pattern, operands);
10024     return \"\";
10025   }"
10026   [(set_attr "type" "f_store")]
10029 ;; Special patterns for dealing with the constant pool
10031 (define_insn "align_4"
10032   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10033   "TARGET_EITHER"
10034   "*
10035   assemble_align (32);
10036   return \"\";
10037   "
10040 (define_insn "align_8"
10041   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10042   "TARGET_EITHER"
10043   "*
10044   assemble_align (64);
10045   return \"\";
10046   "
10049 (define_insn "consttable_end"
10050   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10051   "TARGET_EITHER"
10052   "*
10053   making_const_table = FALSE;
10054   return \"\";
10055   "
10058 (define_insn "consttable_1"
10059   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10060   "TARGET_THUMB"
10061   "*
10062   making_const_table = TRUE;
10063   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10064   assemble_zeros (3);
10065   return \"\";
10066   "
10067   [(set_attr "length" "4")]
10070 (define_insn "consttable_2"
10071   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10072   "TARGET_THUMB"
10073   "*
10074   making_const_table = TRUE;
10075   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10076   assemble_zeros (2);
10077   return \"\";
10078   "
10079   [(set_attr "length" "4")]
10082 (define_insn "consttable_4"
10083   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10084   "TARGET_EITHER"
10085   "*
10086   {
10087     making_const_table = TRUE;
10088     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10089       {
10090       case MODE_FLOAT:
10091       {
10092         REAL_VALUE_TYPE r;
10093         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10094         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10095         break;
10096       }
10097       default:
10098         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
10099         break;
10100       }
10101     return \"\";
10102   }"
10103   [(set_attr "length" "4")]
10106 (define_insn "consttable_8"
10107   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10108   "TARGET_EITHER"
10109   "*
10110   {
10111     making_const_table = TRUE;
10112     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10113       {
10114        case MODE_FLOAT:
10115         {
10116           REAL_VALUE_TYPE r;
10117           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10118           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10119           break;
10120         }
10121       default:
10122         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10123         break;
10124       }
10125     return \"\";
10126   }"
10127   [(set_attr "length" "8")]
10130 ;; Miscellaneous Thumb patterns
10132 (define_expand "tablejump"
10133   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10134               (use (label_ref (match_operand 1 "" "")))])]
10135   "TARGET_THUMB"
10136   "
10137   if (flag_pic)
10138     {
10139       /* Hopefully, CSE will eliminate this copy.  */
10140       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10141       rtx reg2 = gen_reg_rtx (SImode);
10143       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10144       operands[0] = reg2;
10145     }
10146   "
10149 ;; NB never uses BX.
10150 (define_insn "*thumb_tablejump"
10151   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10152    (use (label_ref (match_operand 1 "" "")))]
10153   "TARGET_THUMB"
10154   "mov\\t%|pc, %0"
10155   [(set_attr "length" "2")]
10158 ;; V5 Instructions,
10160 (define_insn "clzsi2"
10161   [(set (match_operand:SI 0 "s_register_operand" "=r")
10162         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10163   "TARGET_ARM && arm_arch5"
10164   "clz%?\\t%0, %1"
10165   [(set_attr "predicable" "yes")])
10167 (define_expand "ffssi2"
10168   [(set (match_operand:SI 0 "s_register_operand" "")
10169         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10170   "TARGET_ARM && arm_arch5"
10171   "
10172   {
10173     rtx t1, t2, t3;
10175     t1 = gen_reg_rtx (SImode);
10176     t2 = gen_reg_rtx (SImode);
10177     t3 = gen_reg_rtx (SImode);
10179     emit_insn (gen_negsi2 (t1, operands[1]));
10180     emit_insn (gen_andsi3 (t2, operands[1], t1));
10181     emit_insn (gen_clzsi2 (t3, t2));
10182     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10183     DONE;
10184   }"
10187 (define_expand "ctzsi2"
10188   [(set (match_operand:SI 0 "s_register_operand" "")
10189         (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10190   "TARGET_ARM && arm_arch5"
10191   "
10192   {
10193     rtx t1, t2, t3;
10195     t1 = gen_reg_rtx (SImode);
10196     t2 = gen_reg_rtx (SImode);
10197     t3 = gen_reg_rtx (SImode);
10199     emit_insn (gen_negsi2 (t1, operands[1]));
10200     emit_insn (gen_andsi3 (t2, operands[1], t1));
10201     emit_insn (gen_clzsi2 (t3, t2));
10202     emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10203     DONE;
10204   }"
10207 ;; V5E instructions.
10209 (define_insn "prefetch"
10210   [(prefetch (match_operand:SI 0 "address_operand" "p")
10211              (match_operand:SI 1 "" "")
10212              (match_operand:SI 2 "" ""))]
10213   "TARGET_ARM && arm_arch5e"
10214   "pld\\t%a0")
10216 ;; General predication pattern
10218 (define_cond_exec
10219   [(match_operator 0 "arm_comparison_operator"
10220     [(match_operand 1 "cc_register" "")
10221      (const_int 0)])]
10222   "TARGET_ARM"
10223   ""
10226 (define_insn "prologue_use"
10227   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10228   ""
10229   "%@ %0 needed for prologue"
10233 ;; Patterns for exception handling
10235 (define_expand "eh_return"
10236   [(use (match_operand 0 "general_operand" ""))]
10237   "TARGET_EITHER"
10238   "
10239   {
10240     if (TARGET_ARM)
10241       emit_insn (gen_arm_eh_return (operands[0]));
10242     else
10243       emit_insn (gen_thumb_eh_return (operands[0]));
10244     DONE;
10245   }"
10247                                    
10248 ;; We can't expand this before we know where the link register is stored.
10249 (define_insn_and_split "arm_eh_return"
10250   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10251                     VUNSPEC_EH_RETURN)
10252    (clobber (match_scratch:SI 1 "=&r"))]
10253   "TARGET_ARM"
10254   "#"
10255   "&& reload_completed"
10256   [(const_int 0)]
10257   "
10258   {
10259     arm_set_return_address (operands[0], operands[1]);
10260     DONE;
10261   }"
10264 (define_insn_and_split "thumb_eh_return"
10265   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10266                     VUNSPEC_EH_RETURN)
10267    (clobber (match_scratch:SI 1 "=&l"))]
10268   "TARGET_THUMB"
10269   "#"
10270   "&& reload_completed"
10271   [(const_int 0)]
10272   "
10273   {
10274     thumb_set_return_address (operands[0], operands[1]);
10275     DONE;
10276   }"
10279 ;; Load the FPA co-processor patterns
10280 (include "fpa.md")
10281 ;; Load the Maverick co-processor patterns
10282 (include "cirrus.md")
10283 ;; Load the Intel Wireless Multimedia Extension patterns
10284 (include "iwmmxt.md")
10285 ;; Load the VFP co-processor patterns
10286 (include "vfp.md")