* config/arm/arm.h (CONDITIONAL_REGISTER_USAGE): Make r11 fixed and
[official-gcc.git] / gcc / config / arm / arm.md
blob375f92eef54fd73938115c331a9eebb2fcfc88cf
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   /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4463      register.  */
4464   arm_load_pic_register (3);
4465   DONE;
4468 ;; If copying one reg to another we can set the condition codes according to
4469 ;; its value.  Such a move is common after a return from subroutine and the
4470 ;; result is being tested against zero.
4472 (define_insn "*movsi_compare0"
4473   [(set (reg:CC CC_REGNUM)
4474         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4475                     (const_int 0)))
4476    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4477         (match_dup 1))]
4478   "TARGET_ARM"
4479   "@
4480    cmp%?\\t%0, #0
4481    sub%?s\\t%0, %1, #0"
4482   [(set_attr "conds" "set")]
4485 ;; Subroutine to store a half word from a register into memory.
4486 ;; Operand 0 is the source register (HImode)
4487 ;; Operand 1 is the destination address in a register (SImode)
4489 ;; In both this routine and the next, we must be careful not to spill
4490 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4491 ;; can generate unrecognizable rtl.
4493 (define_expand "storehi"
4494   [;; store the low byte
4495    (set (match_operand 1 "" "") (match_dup 3))
4496    ;; extract the high byte
4497    (set (match_dup 2)
4498         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4499    ;; store the high byte
4500    (set (match_dup 4) (match_dup 5))]
4501   "TARGET_ARM"
4502   "
4503   {
4504     rtx op1 = operands[1];
4505     rtx addr = XEXP (op1, 0);
4506     enum rtx_code code = GET_CODE (addr);
4508     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4509         || code == MINUS)
4510       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4512     operands[4] = adjust_address (op1, QImode, 1);
4513     operands[1] = adjust_address (operands[1], QImode, 0);
4514     operands[3] = gen_lowpart (QImode, operands[0]);
4515     operands[0] = gen_lowpart (SImode, operands[0]);
4516     operands[2] = gen_reg_rtx (SImode);
4517     operands[5] = gen_lowpart (QImode, operands[2]);
4518   }"
4521 (define_expand "storehi_bigend"
4522   [(set (match_dup 4) (match_dup 3))
4523    (set (match_dup 2)
4524         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4525    (set (match_operand 1 "" "") (match_dup 5))]
4526   "TARGET_ARM"
4527   "
4528   {
4529     rtx op1 = operands[1];
4530     rtx addr = XEXP (op1, 0);
4531     enum rtx_code code = GET_CODE (addr);
4533     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4534         || code == MINUS)
4535       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4537     operands[4] = adjust_address (op1, QImode, 1);
4538     operands[1] = adjust_address (operands[1], QImode, 0);
4539     operands[3] = gen_lowpart (QImode, operands[0]);
4540     operands[0] = gen_lowpart (SImode, operands[0]);
4541     operands[2] = gen_reg_rtx (SImode);
4542     operands[5] = gen_lowpart (QImode, operands[2]);
4543   }"
4546 ;; Subroutine to store a half word integer constant into memory.
4547 (define_expand "storeinthi"
4548   [(set (match_operand 0 "" "")
4549         (match_operand 1 "" ""))
4550    (set (match_dup 3) (match_dup 2))]
4551   "TARGET_ARM"
4552   "
4553   {
4554     HOST_WIDE_INT value = INTVAL (operands[1]);
4555     rtx addr = XEXP (operands[0], 0);
4556     rtx op0 = operands[0];
4557     enum rtx_code code = GET_CODE (addr);
4559     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4560         || code == MINUS)
4561       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4563     operands[1] = gen_reg_rtx (SImode);
4564     if (BYTES_BIG_ENDIAN)
4565       {
4566         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4567         if ((value & 255) == ((value >> 8) & 255))
4568           operands[2] = operands[1];
4569         else
4570           {
4571             operands[2] = gen_reg_rtx (SImode);
4572             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4573           }
4574       }
4575     else
4576       {
4577         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4578         if ((value & 255) == ((value >> 8) & 255))
4579           operands[2] = operands[1];
4580         else
4581           {
4582             operands[2] = gen_reg_rtx (SImode);
4583             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4584           }
4585       }
4587     operands[3] = adjust_address (op0, QImode, 1);
4588     operands[0] = adjust_address (operands[0], QImode, 0);
4589     operands[2] = gen_lowpart (QImode, operands[2]);
4590     operands[1] = gen_lowpart (QImode, operands[1]);
4591   }"
4594 (define_expand "storehi_single_op"
4595   [(set (match_operand:HI 0 "memory_operand" "")
4596         (match_operand:HI 1 "general_operand" ""))]
4597   "TARGET_ARM && arm_arch4"
4598   "
4599   if (!s_register_operand (operands[1], HImode))
4600     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4601   "
4604 (define_expand "movhi"
4605   [(set (match_operand:HI 0 "general_operand" "")
4606         (match_operand:HI 1 "general_operand" ""))]
4607   "TARGET_EITHER"
4608   "
4609   if (TARGET_ARM)
4610     {
4611       if (!no_new_pseudos)
4612         {
4613           if (GET_CODE (operands[0]) == MEM)
4614             {
4615               if (arm_arch4)
4616                 {
4617                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4618                   DONE;
4619                 }
4620               if (GET_CODE (operands[1]) == CONST_INT)
4621                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4622               else
4623                 {
4624                   if (GET_CODE (operands[1]) == MEM)
4625                     operands[1] = force_reg (HImode, operands[1]);
4626                   if (BYTES_BIG_ENDIAN)
4627                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4628                   else
4629                    emit_insn (gen_storehi (operands[1], operands[0]));
4630                 }
4631               DONE;
4632             }
4633           /* Sign extend a constant, and keep it in an SImode reg.  */
4634           else if (GET_CODE (operands[1]) == CONST_INT)
4635             {
4636               rtx reg = gen_reg_rtx (SImode);
4637               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4639               /* If the constant is already valid, leave it alone.  */
4640               if (!const_ok_for_arm (val))
4641                 {
4642                   /* If setting all the top bits will make the constant 
4643                      loadable in a single instruction, then set them.  
4644                      Otherwise, sign extend the number.  */
4646                   if (const_ok_for_arm (~(val | ~0xffff)))
4647                     val |= ~0xffff;
4648                   else if (val & 0x8000)
4649                     val |= ~0xffff;
4650                 }
4652               emit_insn (gen_movsi (reg, GEN_INT (val)));
4653               operands[1] = gen_lowpart (HImode, reg);
4654             }
4655           else if (arm_arch4 && optimize && !no_new_pseudos
4656                    && GET_CODE (operands[1]) == MEM)
4657             {
4658               rtx reg = gen_reg_rtx (SImode);
4660               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4661               operands[1] = gen_lowpart (HImode, reg);
4662             }
4663           else if (!arm_arch4)
4664             {
4665               if (GET_CODE (operands[1]) == MEM)
4666                 {
4667                   rtx base;
4668                   rtx offset = const0_rtx;
4669                   rtx reg = gen_reg_rtx (SImode);
4671                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4672                        || (GET_CODE (base) == PLUS
4673                            && (GET_CODE (offset = XEXP (base, 1))
4674                                == CONST_INT)
4675                            && ((INTVAL(offset) & 1) != 1)
4676                            && GET_CODE (base = XEXP (base, 0)) == REG))
4677                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4678                     {
4679                       HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4680                       rtx new;
4682                       new = gen_rtx_MEM (SImode,
4683                                          plus_constant (base, new_offset));
4684                       MEM_COPY_ATTRIBUTES (new, operands[1]);
4685                       emit_insn (gen_movsi (reg, new));
4686                       if (((INTVAL (offset) & 2) != 0)
4687                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4688                         {
4689                           rtx reg2 = gen_reg_rtx (SImode);
4691                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4692                           reg = reg2;
4693                         }
4694                     }
4695                   else
4696                     emit_insn (gen_movhi_bytes (reg, operands[1]));
4698                   operands[1] = gen_lowpart (HImode, reg);
4699                }
4700            }
4701         }
4702       /* Handle loading a large integer during reload.  */
4703       else if (GET_CODE (operands[1]) == CONST_INT
4704                && !const_ok_for_arm (INTVAL (operands[1]))
4705                && !const_ok_for_arm (~INTVAL (operands[1])))
4706         {
4707           /* Writing a constant to memory needs a scratch, which should
4708              be handled with SECONDARY_RELOADs.  */
4709           if (GET_CODE (operands[0]) != REG)
4710             abort ();
4712           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4713           emit_insn (gen_movsi (operands[0], operands[1]));
4714           DONE;
4715        }
4716     }
4717   else /* TARGET_THUMB */
4718     {
4719       if (!no_new_pseudos)
4720         {
4721           if (GET_CODE (operands[0]) != REG)
4722             operands[1] = force_reg (HImode, operands[1]);
4724           /* ??? We shouldn't really get invalid addresses here, but this can
4725              happen if we are passed a SP (never OK for HImode/QImode) or 
4726              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4727              HImode/QImode) relative address.  */
4728           /* ??? This should perhaps be fixed elsewhere, for instance, in
4729              fixup_stack_1, by checking for other kinds of invalid addresses,
4730              e.g. a bare reference to a virtual register.  This may confuse the
4731              alpha though, which must handle this case differently.  */
4732           if (GET_CODE (operands[0]) == MEM
4733               && !memory_address_p (GET_MODE (operands[0]),
4734                                     XEXP (operands[0], 0)))
4735             operands[0]
4736               = replace_equiv_address (operands[0],
4737                                        copy_to_reg (XEXP (operands[0], 0)));
4738    
4739           if (GET_CODE (operands[1]) == MEM
4740               && !memory_address_p (GET_MODE (operands[1]),
4741                                     XEXP (operands[1], 0)))
4742             operands[1]
4743               = replace_equiv_address (operands[1],
4744                                        copy_to_reg (XEXP (operands[1], 0)));
4745         }
4746       /* Handle loading a large integer during reload.  */
4747       else if (GET_CODE (operands[1]) == CONST_INT
4748                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4749         {
4750           /* Writing a constant to memory needs a scratch, which should
4751              be handled with SECONDARY_RELOADs.  */
4752           if (GET_CODE (operands[0]) != REG)
4753             abort ();
4755           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4756           emit_insn (gen_movsi (operands[0], operands[1]));
4757           DONE;
4758         }
4759     }
4760   "
4763 (define_insn "*thumb_movhi_insn"
4764   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4765         (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
4766   "TARGET_THUMB
4767    && (   register_operand (operands[0], HImode)
4768        || register_operand (operands[1], HImode))"
4769   "*
4770   switch (which_alternative)
4771     {
4772     case 0: return \"add        %0, %1, #0\";
4773     case 2: return \"strh       %1, %0\";
4774     case 3: return \"mov        %0, %1\";
4775     case 4: return \"mov        %0, %1\";
4776     case 5: return \"mov        %0, %1\";
4777     default: abort ();
4778     case 1:
4779       /* The stack pointer can end up being taken as an index register.
4780           Catch this case here and deal with it.  */
4781       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4782           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4783           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4784         {
4785           rtx ops[2];
4786           ops[0] = operands[0];
4787           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4788       
4789           output_asm_insn (\"mov        %0, %1\", ops);
4791           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4792     
4793         }
4794       return \"ldrh     %0, %1\";
4795     }"
4796   [(set_attr "length" "2,4,2,2,2,2")
4797    (set_attr "type" "*,load1,store1,*,*,*")]
4801 (define_expand "movhi_bytes"
4802   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4803    (set (match_dup 3)
4804         (zero_extend:SI (match_dup 6)))
4805    (set (match_operand:SI 0 "" "")
4806          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4807   "TARGET_ARM"
4808   "
4809   {
4810     rtx mem1, mem2;
4811     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4813     mem1 = gen_rtx_MEM (QImode, addr);
4814     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4815     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4816     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4817     operands[0] = gen_lowpart (SImode, operands[0]);
4818     operands[1] = mem1;
4819     operands[2] = gen_reg_rtx (SImode);
4820     operands[3] = gen_reg_rtx (SImode);
4821     operands[6] = mem2;
4823     if (BYTES_BIG_ENDIAN)
4824       {
4825         operands[4] = operands[2];
4826         operands[5] = operands[3];
4827       }
4828     else
4829       {
4830         operands[4] = operands[3];
4831         operands[5] = operands[2];
4832       }
4833   }"
4836 (define_expand "movhi_bigend"
4837   [(set (match_dup 2)
4838         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4839                    (const_int 16)))
4840    (set (match_dup 3)
4841         (ashiftrt:SI (match_dup 2) (const_int 16)))
4842    (set (match_operand:HI 0 "s_register_operand" "")
4843         (match_dup 4))]
4844   "TARGET_ARM"
4845   "
4846   operands[2] = gen_reg_rtx (SImode);
4847   operands[3] = gen_reg_rtx (SImode);
4848   operands[4] = gen_lowpart (HImode, operands[3]);
4849   "
4852 ;; Pattern to recognize insn generated default case above
4853 (define_insn "*movhi_insn_arch4"
4854   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4855         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4856   "TARGET_ARM
4857    && arm_arch4
4858    && (GET_CODE (operands[1]) != CONST_INT
4859        || const_ok_for_arm (INTVAL (operands[1]))
4860        || const_ok_for_arm (~INTVAL (operands[1])))"
4861   "@
4862    mov%?\\t%0, %1\\t%@ movhi
4863    mvn%?\\t%0, #%B1\\t%@ movhi
4864    str%?h\\t%1, %0\\t%@ movhi 
4865    ldr%?h\\t%0, %1\\t%@ movhi"
4866   [(set_attr "type" "*,*,store1,load1")
4867    (set_attr "predicable" "yes")
4868    (set_attr "pool_range" "*,*,*,256")
4869    (set_attr "neg_pool_range" "*,*,*,244")]
4872 (define_insn "*movhi_bytes"
4873   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4874         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4875   "TARGET_ARM"
4876   "@
4877    mov%?\\t%0, %1\\t%@ movhi
4878    mvn%?\\t%0, #%B1\\t%@ movhi"
4879   [(set_attr "predicable" "yes")]
4882 (define_insn "thumb_movhi_clobber"
4883   [(set (match_operand:HI     0 "memory_operand"   "=m")
4884         (match_operand:HI     1 "register_operand" "l"))
4885    (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4886   "TARGET_THUMB"
4887   "*
4888   abort ();"
4890         
4891 ;; We use a DImode scratch because we may occasionally need an additional
4892 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4893 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4894 (define_expand "reload_outhi"
4895   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4896               (match_operand:HI 1 "s_register_operand"        "r")
4897               (match_operand:DI 2 "s_register_operand"        "=&l")])]
4898   "TARGET_EITHER"
4899   "if (TARGET_ARM)
4900      arm_reload_out_hi (operands);
4901    else
4902      thumb_reload_out_hi (operands);
4903   DONE;
4904   "
4907 (define_expand "reload_inhi"
4908   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4909               (match_operand:HI 1 "arm_reload_memory_operand" "o")
4910               (match_operand:DI 2 "s_register_operand" "=&r")])]
4911   "TARGET_EITHER"
4912   "
4913   if (TARGET_ARM)
4914     arm_reload_in_hi (operands);
4915   else
4916     thumb_reload_out_hi (operands);
4917   DONE;
4920 (define_expand "movqi"
4921   [(set (match_operand:QI 0 "general_operand" "")
4922         (match_operand:QI 1 "general_operand" ""))]
4923   "TARGET_EITHER"
4924   "
4925   if (TARGET_ARM)
4926     {
4927       /* Everything except mem = const or mem = mem can be done easily */
4929       if (!no_new_pseudos)
4930         {
4931           if (GET_CODE (operands[1]) == CONST_INT)
4932             {
4933               rtx reg = gen_reg_rtx (SImode);
4935               emit_insn (gen_movsi (reg, operands[1]));
4936               operands[1] = gen_lowpart (QImode, reg);
4937             }
4938           if (GET_CODE (operands[1]) == MEM && optimize > 0)
4939             {
4940               rtx reg = gen_reg_rtx (SImode);
4942               emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4943               operands[1] = gen_lowpart (QImode, reg);
4944             }
4945           if (GET_CODE (operands[0]) == MEM)
4946             operands[1] = force_reg (QImode, operands[1]);
4947         }
4948     }
4949   else /* TARGET_THUMB */
4950     {
4951       if (!no_new_pseudos)
4952         {
4953           if (GET_CODE (operands[0]) != REG)
4954             operands[1] = force_reg (QImode, operands[1]);
4956           /* ??? We shouldn't really get invalid addresses here, but this can
4957              happen if we are passed a SP (never OK for HImode/QImode) or
4958              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4959              HImode/QImode) relative address.  */
4960           /* ??? This should perhaps be fixed elsewhere, for instance, in
4961              fixup_stack_1, by checking for other kinds of invalid addresses,
4962              e.g. a bare reference to a virtual register.  This may confuse the
4963              alpha though, which must handle this case differently.  */
4964           if (GET_CODE (operands[0]) == MEM
4965               && !memory_address_p (GET_MODE (operands[0]),
4966                                      XEXP (operands[0], 0)))
4967             operands[0]
4968               = replace_equiv_address (operands[0],
4969                                        copy_to_reg (XEXP (operands[0], 0)));
4970           if (GET_CODE (operands[1]) == MEM
4971               && !memory_address_p (GET_MODE (operands[1]),
4972                                     XEXP (operands[1], 0)))
4973              operands[1]
4974                = replace_equiv_address (operands[1],
4975                                         copy_to_reg (XEXP (operands[1], 0)));
4976         }
4977       /* Handle loading a large integer during reload.  */
4978       else if (GET_CODE (operands[1]) == CONST_INT
4979                && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4980         {
4981           /* Writing a constant to memory needs a scratch, which should
4982              be handled with SECONDARY_RELOADs.  */
4983           if (GET_CODE (operands[0]) != REG)
4984             abort ();
4986           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4987           emit_insn (gen_movsi (operands[0], operands[1]));
4988           DONE;
4989        }
4990     }
4991   "
4995 (define_insn "*arm_movqi_insn"
4996   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4997         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4998   "TARGET_ARM
4999    && (   register_operand (operands[0], QImode)
5000        || register_operand (operands[1], QImode))"
5001   "@
5002    mov%?\\t%0, %1
5003    mvn%?\\t%0, #%B1
5004    ldr%?b\\t%0, %1
5005    str%?b\\t%1, %0"
5006   [(set_attr "type" "*,*,load1,store1")
5007    (set_attr "predicable" "yes")]
5010 (define_insn "*thumb_movqi_insn"
5011   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5012         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
5013   "TARGET_THUMB
5014    && (   register_operand (operands[0], QImode)
5015        || register_operand (operands[1], QImode))"
5016   "@
5017    add\\t%0, %1, #0
5018    ldrb\\t%0, %1
5019    strb\\t%1, %0
5020    mov\\t%0, %1
5021    mov\\t%0, %1
5022    mov\\t%0, %1"
5023   [(set_attr "length" "2")
5024    (set_attr "type" "*,load1,store1,*,*,*")
5025    (set_attr "pool_range" "*,32,*,*,*,*")]
5028 (define_expand "movsf"
5029   [(set (match_operand:SF 0 "general_operand" "")
5030         (match_operand:SF 1 "general_operand" ""))]
5031   "TARGET_EITHER"
5032   "
5033   if (TARGET_ARM)
5034     {
5035       if (GET_CODE (operands[0]) == MEM)
5036         operands[1] = force_reg (SFmode, operands[1]);
5037     }
5038   else /* TARGET_THUMB */
5039     {
5040       if (!no_new_pseudos)
5041         {
5042            if (GET_CODE (operands[0]) != REG)
5043              operands[1] = force_reg (SFmode, operands[1]);
5044         }
5045     }
5046   "
5049 (define_split
5050   [(set (match_operand:SF 0 "nonimmediate_operand" "")
5051         (match_operand:SF 1 "immediate_operand" ""))]
5052   "TARGET_ARM
5053    && !(TARGET_HARD_FLOAT && TARGET_FPA)
5054    && reload_completed
5055    && GET_CODE (operands[1]) == CONST_DOUBLE"
5056   [(set (match_dup 2) (match_dup 3))]
5057   "
5058   operands[2] = gen_lowpart (SImode, operands[0]);
5059   operands[3] = gen_lowpart (SImode, operands[1]);
5060   if (operands[2] == 0 || operands[3] == 0)
5061     FAIL;
5062   "
5065 (define_insn "*arm_movsf_soft_insn"
5066   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5067         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
5068   "TARGET_ARM
5069    && TARGET_SOFT_FLOAT
5070    && (GET_CODE (operands[0]) != MEM
5071        || register_operand (operands[1], SFmode))"
5072   "@
5073    mov%?\\t%0, %1
5074    ldr%?\\t%0, %1\\t%@ float
5075    str%?\\t%1, %0\\t%@ float"
5076   [(set_attr "length" "4,4,4")
5077    (set_attr "predicable" "yes")
5078    (set_attr "type" "*,load1,store1")
5079    (set_attr "pool_range" "*,4096,*")
5080    (set_attr "neg_pool_range" "*,4084,*")]
5083 ;;; ??? This should have alternatives for constants.
5084 (define_insn "*thumb_movsf_insn"
5085   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5086         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5087   "TARGET_THUMB
5088    && (   register_operand (operands[0], SFmode) 
5089        || register_operand (operands[1], SFmode))"
5090   "@
5091    add\\t%0, %1, #0
5092    ldmia\\t%1, {%0}
5093    stmia\\t%0, {%1}
5094    ldr\\t%0, %1
5095    str\\t%1, %0
5096    mov\\t%0, %1
5097    mov\\t%0, %1"
5098   [(set_attr "length" "2")
5099    (set_attr "type" "*,load1,store1,load1,store1,*,*")
5100    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5103 (define_expand "movdf"
5104   [(set (match_operand:DF 0 "general_operand" "")
5105         (match_operand:DF 1 "general_operand" ""))]
5106   "TARGET_EITHER"
5107   "
5108   if (TARGET_ARM)
5109     {
5110       if (GET_CODE (operands[0]) == MEM)
5111         operands[1] = force_reg (DFmode, operands[1]);
5112     }
5113   else /* TARGET_THUMB */
5114     {
5115       if (!no_new_pseudos)
5116         {
5117           if (GET_CODE (operands[0]) != REG)
5118             operands[1] = force_reg (DFmode, operands[1]);
5119         }
5120     }
5121   "
5124 ;; Reloading a df mode value stored in integer regs to memory can require a
5125 ;; scratch reg.
5126 (define_expand "reload_outdf"
5127   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5128    (match_operand:DF 1 "s_register_operand" "r")
5129    (match_operand:SI 2 "s_register_operand" "=&r")]
5130   "TARGET_ARM"
5131   "
5132   {
5133     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5135     if (code == REG)
5136       operands[2] = XEXP (operands[0], 0);
5137     else if (code == POST_INC || code == PRE_DEC)
5138       {
5139         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5140         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5141         emit_insn (gen_movdi (operands[0], operands[1]));
5142         DONE;
5143       }
5144     else if (code == PRE_INC)
5145       {
5146         rtx reg = XEXP (XEXP (operands[0], 0), 0);
5148         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5149         operands[2] = reg;
5150       }
5151     else if (code == POST_DEC)
5152       operands[2] = XEXP (XEXP (operands[0], 0), 0);
5153     else
5154       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5155                              XEXP (XEXP (operands[0], 0), 1)));
5157     emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5158                             operands[1]));
5160     if (code == POST_DEC)
5161       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5163     DONE;
5164   }"
5167 (define_insn "*movdf_soft_insn"
5168   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
5169         (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
5170   "TARGET_ARM && TARGET_SOFT_FLOAT
5171   "
5172   "* return output_move_double (operands);"
5173   [(set_attr "length" "8,8,8")
5174    (set_attr "type" "*,load2,store2")
5175    (set_attr "pool_range" "1020")
5176    (set_attr "neg_pool_range" "1008")]
5179 ;;; ??? This should have alternatives for constants.
5180 ;;; ??? This was originally identical to the movdi_insn pattern.
5181 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5182 ;;; thumb_reorg with a memory reference.
5183 (define_insn "*thumb_movdf_insn"
5184   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5185         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5186   "TARGET_THUMB
5187    && (   register_operand (operands[0], DFmode)
5188        || register_operand (operands[1], DFmode))"
5189   "*
5190   switch (which_alternative)
5191     {
5192     default:
5193     case 0:
5194       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5195         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5196       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5197     case 1:
5198       return \"ldmia\\t%1, {%0, %H0}\";
5199     case 2:
5200       return \"stmia\\t%0, {%1, %H1}\";
5201     case 3:
5202       return thumb_load_double_from_address (operands);
5203     case 4:
5204       operands[2] = gen_rtx_MEM (SImode,
5205                                  plus_constant (XEXP (operands[0], 0), 4));
5206       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5207       return \"\";
5208     case 5:
5209       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5210         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5211       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5212     }
5213   "
5214   [(set_attr "length" "4,2,2,6,4,4")
5215    (set_attr "type" "*,load2,store2,load2,store2,*")
5216    (set_attr "pool_range" "*,*,*,1020,*,*")]
5219 ;; Vector Moves
5220 (define_expand "movv2si"
5221   [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5222         (match_operand:V2SI 1 "general_operand" ""))]
5223   "TARGET_REALLY_IWMMXT"
5227 (define_expand "movv4hi"
5228   [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5229         (match_operand:V4HI 1 "general_operand" ""))]
5230   "TARGET_REALLY_IWMMXT"
5234 (define_expand "movv8qi"
5235   [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5236         (match_operand:V8QI 1 "general_operand" ""))]
5237   "TARGET_REALLY_IWMMXT"
5242 ;; load- and store-multiple insns
5243 ;; The arm can load/store any set of registers, provided that they are in
5244 ;; ascending order; but that is beyond GCC so stick with what it knows.
5246 (define_expand "load_multiple"
5247   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5248                           (match_operand:SI 1 "" ""))
5249                      (use (match_operand:SI 2 "" ""))])]
5250   "TARGET_ARM"
5252   HOST_WIDE_INT offset = 0;
5254   /* Support only fixed point registers.  */
5255   if (GET_CODE (operands[2]) != CONST_INT
5256       || INTVAL (operands[2]) > 14
5257       || INTVAL (operands[2]) < 2
5258       || GET_CODE (operands[1]) != MEM
5259       || GET_CODE (operands[0]) != REG
5260       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5261       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5262     FAIL;
5264   operands[3]
5265     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5266                              force_reg (SImode, XEXP (operands[1], 0)),
5267                              TRUE, FALSE, operands[1], &offset);
5270 ;; Load multiple with write-back
5272 (define_insn "*ldmsi_postinc4"
5273   [(match_parallel 0 "load_multiple_operation"
5274     [(set (match_operand:SI 1 "s_register_operand" "=r")
5275           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5276                    (const_int 16)))
5277      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5278           (mem:SI (match_dup 2)))
5279      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5280           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5281      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5282           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5283      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5284           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5285   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5286   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5287   [(set_attr "type" "load4")
5288    (set_attr "predicable" "yes")]
5291 (define_insn "*ldmsi_postinc3"
5292   [(match_parallel 0 "load_multiple_operation"
5293     [(set (match_operand:SI 1 "s_register_operand" "=r")
5294           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5295                    (const_int 12)))
5296      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5297           (mem:SI (match_dup 2)))
5298      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5299           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5300      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5301           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5302   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5303   "ldm%?ia\\t%1!, {%3, %4, %5}"
5304   [(set_attr "type" "load3")
5305    (set_attr "predicable" "yes")]
5308 (define_insn "*ldmsi_postinc2"
5309   [(match_parallel 0 "load_multiple_operation"
5310     [(set (match_operand:SI 1 "s_register_operand" "=r")
5311           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5312                    (const_int 8)))
5313      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5314           (mem:SI (match_dup 2)))
5315      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5316           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5317   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5318   "ldm%?ia\\t%1!, {%3, %4}"
5319   [(set_attr "type" "load2")
5320    (set_attr "predicable" "yes")]
5323 ;; Ordinary load multiple
5325 (define_insn "*ldmsi4"
5326   [(match_parallel 0 "load_multiple_operation"
5327     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5328           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5329      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5330           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5331      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5332           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5333      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5334           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5335   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5336   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5337   [(set_attr "type" "load4")
5338    (set_attr "predicable" "yes")]
5341 (define_insn "*ldmsi3"
5342   [(match_parallel 0 "load_multiple_operation"
5343     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5344           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5345      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5346           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5347      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5348           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5349   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5350   "ldm%?ia\\t%1, {%2, %3, %4}"
5351   [(set_attr "type" "load3")
5352    (set_attr "predicable" "yes")]
5355 (define_insn "*ldmsi2"
5356   [(match_parallel 0 "load_multiple_operation"
5357     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5358           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5359      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5360           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5361   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5362   "ldm%?ia\\t%1, {%2, %3}"
5363   [(set_attr "type" "load2")
5364    (set_attr "predicable" "yes")]
5367 (define_expand "store_multiple"
5368   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5369                           (match_operand:SI 1 "" ""))
5370                      (use (match_operand:SI 2 "" ""))])]
5371   "TARGET_ARM"
5373   HOST_WIDE_INT offset = 0;
5375   /* Support only fixed point registers.  */
5376   if (GET_CODE (operands[2]) != CONST_INT
5377       || INTVAL (operands[2]) > 14
5378       || INTVAL (operands[2]) < 2
5379       || GET_CODE (operands[1]) != REG
5380       || GET_CODE (operands[0]) != MEM
5381       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5382       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5383     FAIL;
5385   operands[3]
5386     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5387                               force_reg (SImode, XEXP (operands[0], 0)),
5388                               TRUE, FALSE, operands[0], &offset);
5391 ;; Store multiple with write-back
5393 (define_insn "*stmsi_postinc4"
5394   [(match_parallel 0 "store_multiple_operation"
5395     [(set (match_operand:SI 1 "s_register_operand" "=r")
5396           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5397                    (const_int 16)))
5398      (set (mem:SI (match_dup 2))
5399           (match_operand:SI 3 "arm_hard_register_operand" ""))
5400      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5401           (match_operand:SI 4 "arm_hard_register_operand" ""))
5402      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5403           (match_operand:SI 5 "arm_hard_register_operand" ""))
5404      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5405           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5406   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5407   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5408   [(set_attr "predicable" "yes")
5409    (set_attr "type" "store4")]
5412 (define_insn "*stmsi_postinc3"
5413   [(match_parallel 0 "store_multiple_operation"
5414     [(set (match_operand:SI 1 "s_register_operand" "=r")
5415           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5416                    (const_int 12)))
5417      (set (mem:SI (match_dup 2))
5418           (match_operand:SI 3 "arm_hard_register_operand" ""))
5419      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5420           (match_operand:SI 4 "arm_hard_register_operand" ""))
5421      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5422           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5423   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5424   "stm%?ia\\t%1!, {%3, %4, %5}"
5425   [(set_attr "predicable" "yes")
5426    (set_attr "type" "store3")]
5429 (define_insn "*stmsi_postinc2"
5430   [(match_parallel 0 "store_multiple_operation"
5431     [(set (match_operand:SI 1 "s_register_operand" "=r")
5432           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5433                    (const_int 8)))
5434      (set (mem:SI (match_dup 2))
5435           (match_operand:SI 3 "arm_hard_register_operand" ""))
5436      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5437           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5438   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5439   "stm%?ia\\t%1!, {%3, %4}"
5440   [(set_attr "predicable" "yes")
5441    (set_attr "type" "store2")]
5444 ;; Ordinary store multiple
5446 (define_insn "*stmsi4"
5447   [(match_parallel 0 "store_multiple_operation"
5448     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5449           (match_operand:SI 2 "arm_hard_register_operand" ""))
5450      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5451           (match_operand:SI 3 "arm_hard_register_operand" ""))
5452      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5453           (match_operand:SI 4 "arm_hard_register_operand" ""))
5454      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5455           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5456   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5457   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5458   [(set_attr "predicable" "yes")
5459    (set_attr "type" "store4")]
5462 (define_insn "*stmsi3"
5463   [(match_parallel 0 "store_multiple_operation"
5464     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5465           (match_operand:SI 2 "arm_hard_register_operand" ""))
5466      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5467           (match_operand:SI 3 "arm_hard_register_operand" ""))
5468      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5469           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5470   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5471   "stm%?ia\\t%1, {%2, %3, %4}"
5472   [(set_attr "predicable" "yes")
5473    (set_attr "type" "store3")]
5476 (define_insn "*stmsi2"
5477   [(match_parallel 0 "store_multiple_operation"
5478     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5479           (match_operand:SI 2 "arm_hard_register_operand" ""))
5480      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5481           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5482   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5483   "stm%?ia\\t%1, {%2, %3}"
5484   [(set_attr "predicable" "yes")
5485    (set_attr "type" "store2")]
5488 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5489 ;; We could let this apply for blocks of less than this, but it clobbers so
5490 ;; many registers that there is then probably a better way.
5492 (define_expand "movmemqi"
5493   [(match_operand:BLK 0 "general_operand" "")
5494    (match_operand:BLK 1 "general_operand" "")
5495    (match_operand:SI 2 "const_int_operand" "")
5496    (match_operand:SI 3 "const_int_operand" "")]
5497   "TARGET_EITHER"
5498   "
5499   if (TARGET_ARM)
5500     {
5501       if (arm_gen_movmemqi (operands))
5502         DONE;
5503       FAIL;
5504     }
5505   else /* TARGET_THUMB */
5506     {
5507       if (   INTVAL (operands[3]) != 4
5508           || INTVAL (operands[2]) > 48)
5509         FAIL;
5511       thumb_expand_movmemqi (operands);
5512       DONE;
5513     }
5514   "
5517 ;; Thumb block-move insns
5519 (define_insn "movmem12b"
5520   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5521         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5522    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5523         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5524    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5525         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5526    (set (match_operand:SI 0 "register_operand" "=l")
5527         (plus:SI (match_dup 2) (const_int 12)))
5528    (set (match_operand:SI 1 "register_operand" "=l")
5529         (plus:SI (match_dup 3) (const_int 12)))
5530    (clobber (match_scratch:SI 4 "=&l"))
5531    (clobber (match_scratch:SI 5 "=&l"))
5532    (clobber (match_scratch:SI 6 "=&l"))]
5533   "TARGET_THUMB"
5534   "* return thumb_output_move_mem_multiple (3, operands);"
5535   [(set_attr "length" "4")
5536    ; This isn't entirely accurate...  It loads as well, but in terms of
5537    ; scheduling the following insn it is better to consider it as a store
5538    (set_attr "type" "store3")]
5541 (define_insn "movmem8b"
5542   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5543         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5544    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5545         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5546    (set (match_operand:SI 0 "register_operand" "=l")
5547         (plus:SI (match_dup 2) (const_int 8)))
5548    (set (match_operand:SI 1 "register_operand" "=l")
5549         (plus:SI (match_dup 3) (const_int 8)))
5550    (clobber (match_scratch:SI 4 "=&l"))
5551    (clobber (match_scratch:SI 5 "=&l"))]
5552   "TARGET_THUMB"
5553   "* return thumb_output_move_mem_multiple (2, operands);"
5554   [(set_attr "length" "4")
5555    ; This isn't entirely accurate...  It loads as well, but in terms of
5556    ; scheduling the following insn it is better to consider it as a store
5557    (set_attr "type" "store2")]
5562 ;; Compare & branch insns
5563 ;; The range calculations are based as follows:
5564 ;; For forward branches, the address calculation returns the address of
5565 ;; the next instruction.  This is 2 beyond the branch instruction.
5566 ;; For backward branches, the address calculation returns the address of
5567 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5568 ;; instruction for the shortest sequence, and 4 before the branch instruction
5569 ;; if we have to jump around an unconditional branch.
5570 ;; To the basic branch range the PC offset must be added (this is +4).
5571 ;; So for forward branches we have 
5572 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5573 ;; And for backward branches we have 
5574 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5576 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5577 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5579 (define_expand "cbranchsi4"
5580   [(set (pc) (if_then_else
5581               (match_operator 0 "arm_comparison_operator"
5582                [(match_operand:SI 1 "s_register_operand" "")
5583                 (match_operand:SI 2 "nonmemory_operand" "")])
5584               (label_ref (match_operand 3 "" ""))
5585               (pc)))]
5586   "TARGET_THUMB"
5587   "
5588   if (thumb_cmpneg_operand (operands[2], SImode))
5589     {
5590       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5591                                               operands[3], operands[0]));
5592       DONE;
5593     }
5594   if (!thumb_cmp_operand (operands[2], SImode))
5595     operands[2] = force_reg (SImode, operands[2]);
5596   ")
5598 (define_insn "*cbranchsi4_insn"
5599   [(set (pc) (if_then_else
5600               (match_operator 0 "arm_comparison_operator"
5601                [(match_operand:SI 1 "s_register_operand" "l,*h")
5602                 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5603               (label_ref (match_operand 3 "" ""))
5604               (pc)))]
5605   "TARGET_THUMB"
5606   "*
5607   output_asm_insn (\"cmp\\t%1, %2\", operands);
5609   switch (get_attr_length (insn))
5610     {
5611     case 4:  return \"b%d0\\t%l3\";
5612     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5613     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5614     }
5615   "
5616   [(set (attr "far_jump")
5617         (if_then_else
5618             (eq_attr "length" "8")
5619             (const_string "yes")
5620             (const_string "no")))
5621    (set (attr "length") 
5622         (if_then_else
5623             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5624                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5625             (const_int 4)
5626             (if_then_else
5627                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5628                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5629                 (const_int 6)
5630                 (const_int 8))))]
5633 (define_insn "cbranchsi4_scratch"
5634   [(set (pc) (if_then_else
5635               (match_operator 4 "arm_comparison_operator"
5636                [(match_operand:SI 1 "s_register_operand" "l,0")
5637                 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5638               (label_ref (match_operand 3 "" ""))
5639               (pc)))
5640    (clobber (match_scratch:SI 0 "=l,l"))]
5641   "TARGET_THUMB"
5642   "*
5643   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5645   switch (get_attr_length (insn))
5646     {
5647     case 4:  return \"b%d4\\t%l3\";
5648     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5649     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5650     }
5651   "
5652   [(set (attr "far_jump")
5653         (if_then_else
5654             (eq_attr "length" "8")
5655             (const_string "yes")
5656             (const_string "no")))
5657    (set (attr "length") 
5658         (if_then_else
5659             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5660                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5661             (const_int 4)
5662             (if_then_else
5663                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5664                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5665                 (const_int 6)
5666                 (const_int 8))))]
5668 (define_insn "*movsi_cbranchsi4"
5669   [(set (pc)
5670         (if_then_else
5671          (match_operator 3 "arm_comparison_operator"
5672           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5673            (const_int 0)])
5674          (label_ref (match_operand 2 "" ""))
5675          (pc)))
5676    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5677         (match_dup 1))]
5678   "TARGET_THUMB"
5679   "*{
5680   if (which_alternative == 0)
5681     output_asm_insn (\"cmp\t%0, #0\", operands);
5682   else if (which_alternative == 1)
5683     output_asm_insn (\"sub\t%0, %1, #0\", operands);
5684   else
5685     {
5686       output_asm_insn (\"cmp\t%1, #0\", operands);
5687       if (which_alternative == 2)
5688         output_asm_insn (\"mov\t%0, %1\", operands);
5689       else
5690         output_asm_insn (\"str\t%1, %0\", operands);
5691     }
5692   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5693     {
5694     case 4:  return \"b%d3\\t%l2\";
5695     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5696     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5697     }
5698   }"
5699   [(set (attr "far_jump")
5700         (if_then_else
5701             (ior (and (gt (symbol_ref ("which_alternative"))
5702                           (const_int 1))
5703                       (eq_attr "length" "8"))
5704                  (eq_attr "length" "10"))
5705             (const_string "yes")
5706             (const_string "no")))
5707    (set (attr "length")
5708      (if_then_else
5709        (le (symbol_ref ("which_alternative"))
5710                        (const_int 1))
5711        (if_then_else
5712          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5713               (le (minus (match_dup 2) (pc)) (const_int 256)))
5714          (const_int 4)
5715          (if_then_else
5716            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5717                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5718            (const_int 6)
5719            (const_int 8)))
5720        (if_then_else
5721          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5722               (le (minus (match_dup 2) (pc)) (const_int 256)))
5723          (const_int 6)
5724          (if_then_else
5725            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5726                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5727            (const_int 8)
5728            (const_int 10)))))]
5731 (define_insn "*negated_cbranchsi4"
5732   [(set (pc)
5733         (if_then_else
5734          (match_operator 0 "arm_comparison_operator"
5735           [(match_operand:SI 1 "s_register_operand" "l")
5736            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5737          (label_ref (match_operand 3 "" ""))
5738          (pc)))]
5739   "TARGET_THUMB"
5740   "*
5741   output_asm_insn (\"cmn\\t%1, %2\", operands);
5742   switch (get_attr_length (insn))
5743     {
5744     case 4:  return \"b%d0\\t%l3\";
5745     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5746     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5747     }
5748   "
5749   [(set (attr "far_jump")
5750         (if_then_else
5751             (eq_attr "length" "8")
5752             (const_string "yes")
5753             (const_string "no")))
5754    (set (attr "length") 
5755         (if_then_else
5756             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5757                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5758             (const_int 4)
5759             (if_then_else
5760                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5761                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5762                 (const_int 6)
5763                 (const_int 8))))]
5766 (define_insn "*tbit_cbranch"
5767   [(set (pc)
5768         (if_then_else
5769          (match_operator 0 "equality_operator"
5770           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5771                             (const_int 1)
5772                             (match_operand:SI 2 "const_int_operand" "i"))
5773            (const_int 0)])
5774          (label_ref (match_operand 3 "" ""))
5775          (pc)))
5776    (clobber (match_scratch:SI 4 "=l"))]
5777   "TARGET_THUMB"
5778   "*
5779   {
5780   rtx op[3];
5781   op[0] = operands[4];
5782   op[1] = operands[1];
5783   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5785   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5786   switch (get_attr_length (insn))
5787     {
5788     case 4:  return \"b%d0\\t%l3\";
5789     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5790     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5791     }
5792   }"
5793   [(set (attr "far_jump")
5794         (if_then_else
5795             (eq_attr "length" "8")
5796             (const_string "yes")
5797             (const_string "no")))
5798    (set (attr "length") 
5799         (if_then_else
5800             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5801                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5802             (const_int 4)
5803             (if_then_else
5804                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5805                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5806                 (const_int 6)
5807                 (const_int 8))))]
5809   
5810 (define_insn "*tstsi3_cbranch"
5811   [(set (pc)
5812         (if_then_else
5813          (match_operator 3 "equality_operator"
5814           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5815                    (match_operand:SI 1 "s_register_operand" "l"))
5816            (const_int 0)])
5817          (label_ref (match_operand 2 "" ""))
5818          (pc)))]
5819   "TARGET_THUMB"
5820   "*
5821   {
5822   output_asm_insn (\"tst\\t%0, %1\", operands);
5823   switch (get_attr_length (insn))
5824     {
5825     case 4:  return \"b%d3\\t%l2\";
5826     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5827     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5828     }
5829   }"
5830   [(set (attr "far_jump")
5831         (if_then_else
5832             (eq_attr "length" "8")
5833             (const_string "yes")
5834             (const_string "no")))
5835    (set (attr "length") 
5836         (if_then_else
5837             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5838                  (le (minus (match_dup 2) (pc)) (const_int 256)))
5839             (const_int 4)
5840             (if_then_else
5841                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5842                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
5843                 (const_int 6)
5844                 (const_int 8))))]
5846   
5847 (define_insn "*andsi3_cbranch"
5848   [(set (pc)
5849         (if_then_else
5850          (match_operator 5 "equality_operator"
5851           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5852                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5853            (const_int 0)])
5854          (label_ref (match_operand 4 "" ""))
5855          (pc)))
5856    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5857         (and:SI (match_dup 2) (match_dup 3)))
5858    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5859   "TARGET_THUMB"
5860   "*
5861   {
5862   if (which_alternative == 0)
5863     output_asm_insn (\"and\\t%0, %3\", operands);
5864   else if (which_alternative == 1)
5865     {
5866       output_asm_insn (\"and\\t%1, %3\", operands);
5867       output_asm_insn (\"mov\\t%0, %1\", operands);
5868     }
5869   else
5870     {
5871       output_asm_insn (\"and\\t%1, %3\", operands);
5872       output_asm_insn (\"str\\t%1, %0\", operands);
5873     }
5875   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5876     {
5877     case 4:  return \"b%d5\\t%l4\";
5878     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5879     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5880     }
5881   }"
5882   [(set (attr "far_jump")
5883         (if_then_else
5884             (ior (and (eq (symbol_ref ("which_alternative"))
5885                           (const_int 0))
5886                       (eq_attr "length" "8"))
5887                  (eq_attr "length" "10"))
5888             (const_string "yes")
5889             (const_string "no")))
5890    (set (attr "length")
5891      (if_then_else
5892        (eq (symbol_ref ("which_alternative"))
5893                        (const_int 0))
5894        (if_then_else
5895          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5896               (le (minus (match_dup 4) (pc)) (const_int 256)))
5897          (const_int 4)
5898          (if_then_else
5899            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5900                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5901            (const_int 6)
5902            (const_int 8)))
5903        (if_then_else
5904          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5905               (le (minus (match_dup 4) (pc)) (const_int 256)))
5906          (const_int 6)
5907          (if_then_else
5908            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5909                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5910            (const_int 8)
5911            (const_int 10)))))]
5914 (define_insn "*orrsi3_cbranch_scratch"
5915   [(set (pc)
5916         (if_then_else
5917          (match_operator 4 "equality_operator"
5918           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
5919                    (match_operand:SI 2 "s_register_operand" "l"))
5920            (const_int 0)])
5921          (label_ref (match_operand 3 "" ""))
5922          (pc)))
5923    (clobber (match_scratch:SI 0 "=l"))]
5924   "TARGET_THUMB"
5925   "*
5926   {
5927   output_asm_insn (\"orr\\t%0, %2\", operands);
5928   switch (get_attr_length (insn))
5929     {
5930     case 4:  return \"b%d4\\t%l3\";
5931     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5932     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5933     }
5934   }"
5935   [(set (attr "far_jump")
5936         (if_then_else
5937             (eq_attr "length" "8")
5938             (const_string "yes")
5939             (const_string "no")))
5940    (set (attr "length") 
5941         (if_then_else
5942             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5943                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5944             (const_int 4)
5945             (if_then_else
5946                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5947                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5948                 (const_int 6)
5949                 (const_int 8))))]
5951   
5952 (define_insn "*orrsi3_cbranch"
5953   [(set (pc)
5954         (if_then_else
5955          (match_operator 5 "equality_operator"
5956           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5957                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5958            (const_int 0)])
5959          (label_ref (match_operand 4 "" ""))
5960          (pc)))
5961    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5962         (ior:SI (match_dup 2) (match_dup 3)))
5963    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5964   "TARGET_THUMB"
5965   "*
5966   {
5967   if (which_alternative == 0)
5968     output_asm_insn (\"orr\\t%0, %3\", operands);
5969   else if (which_alternative == 1)
5970     {
5971       output_asm_insn (\"orr\\t%1, %3\", operands);
5972       output_asm_insn (\"mov\\t%0, %1\", operands);
5973     }
5974   else
5975     {
5976       output_asm_insn (\"orr\\t%1, %3\", operands);
5977       output_asm_insn (\"str\\t%1, %0\", operands);
5978     }
5980   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5981     {
5982     case 4:  return \"b%d5\\t%l4\";
5983     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5984     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5985     }
5986   }"
5987   [(set (attr "far_jump")
5988         (if_then_else
5989             (ior (and (eq (symbol_ref ("which_alternative"))
5990                           (const_int 0))
5991                       (eq_attr "length" "8"))
5992                  (eq_attr "length" "10"))
5993             (const_string "yes")
5994             (const_string "no")))
5995    (set (attr "length")
5996      (if_then_else
5997        (eq (symbol_ref ("which_alternative"))
5998                        (const_int 0))
5999        (if_then_else
6000          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6001               (le (minus (match_dup 4) (pc)) (const_int 256)))
6002          (const_int 4)
6003          (if_then_else
6004            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6005                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6006            (const_int 6)
6007            (const_int 8)))
6008        (if_then_else
6009          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6010               (le (minus (match_dup 4) (pc)) (const_int 256)))
6011          (const_int 6)
6012          (if_then_else
6013            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6014                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6015            (const_int 8)
6016            (const_int 10)))))]
6019 (define_insn "*xorsi3_cbranch_scratch"
6020   [(set (pc)
6021         (if_then_else
6022          (match_operator 4 "equality_operator"
6023           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6024                    (match_operand:SI 2 "s_register_operand" "l"))
6025            (const_int 0)])
6026          (label_ref (match_operand 3 "" ""))
6027          (pc)))
6028    (clobber (match_scratch:SI 0 "=l"))]
6029   "TARGET_THUMB"
6030   "*
6031   {
6032   output_asm_insn (\"eor\\t%0, %2\", operands);
6033   switch (get_attr_length (insn))
6034     {
6035     case 4:  return \"b%d4\\t%l3\";
6036     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6037     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6038     }
6039   }"
6040   [(set (attr "far_jump")
6041         (if_then_else
6042             (eq_attr "length" "8")
6043             (const_string "yes")
6044             (const_string "no")))
6045    (set (attr "length") 
6046         (if_then_else
6047             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6048                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6049             (const_int 4)
6050             (if_then_else
6051                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6052                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6053                 (const_int 6)
6054                 (const_int 8))))]
6056   
6057 (define_insn "*xorsi3_cbranch"
6058   [(set (pc)
6059         (if_then_else
6060          (match_operator 5 "equality_operator"
6061           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6062                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6063            (const_int 0)])
6064          (label_ref (match_operand 4 "" ""))
6065          (pc)))
6066    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6067         (xor:SI (match_dup 2) (match_dup 3)))
6068    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6069   "TARGET_THUMB"
6070   "*
6071   {
6072   if (which_alternative == 0)
6073     output_asm_insn (\"eor\\t%0, %3\", operands);
6074   else if (which_alternative == 1)
6075     {
6076       output_asm_insn (\"eor\\t%1, %3\", operands);
6077       output_asm_insn (\"mov\\t%0, %1\", operands);
6078     }
6079   else
6080     {
6081       output_asm_insn (\"eor\\t%1, %3\", operands);
6082       output_asm_insn (\"str\\t%1, %0\", operands);
6083     }
6085   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6086     {
6087     case 4:  return \"b%d5\\t%l4\";
6088     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6089     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6090     }
6091   }"
6092   [(set (attr "far_jump")
6093         (if_then_else
6094             (ior (and (eq (symbol_ref ("which_alternative"))
6095                           (const_int 0))
6096                       (eq_attr "length" "8"))
6097                  (eq_attr "length" "10"))
6098             (const_string "yes")
6099             (const_string "no")))
6100    (set (attr "length")
6101      (if_then_else
6102        (eq (symbol_ref ("which_alternative"))
6103                        (const_int 0))
6104        (if_then_else
6105          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6106               (le (minus (match_dup 4) (pc)) (const_int 256)))
6107          (const_int 4)
6108          (if_then_else
6109            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6110                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6111            (const_int 6)
6112            (const_int 8)))
6113        (if_then_else
6114          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6115               (le (minus (match_dup 4) (pc)) (const_int 256)))
6116          (const_int 6)
6117          (if_then_else
6118            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6119                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6120            (const_int 8)
6121            (const_int 10)))))]
6124 (define_insn "*bicsi3_cbranch_scratch"
6125   [(set (pc)
6126         (if_then_else
6127          (match_operator 4 "equality_operator"
6128           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6129                    (match_operand:SI 1 "s_register_operand" "0"))
6130            (const_int 0)])
6131          (label_ref (match_operand 3 "" ""))
6132          (pc)))
6133    (clobber (match_scratch:SI 0 "=l"))]
6134   "TARGET_THUMB"
6135   "*
6136   {
6137   output_asm_insn (\"bic\\t%0, %2\", operands);
6138   switch (get_attr_length (insn))
6139     {
6140     case 4:  return \"b%d4\\t%l3\";
6141     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6142     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6143     }
6144   }"
6145   [(set (attr "far_jump")
6146         (if_then_else
6147             (eq_attr "length" "8")
6148             (const_string "yes")
6149             (const_string "no")))
6150    (set (attr "length") 
6151         (if_then_else
6152             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6153                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6154             (const_int 4)
6155             (if_then_else
6156                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6157                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6158                 (const_int 6)
6159                 (const_int 8))))]
6161   
6162 (define_insn "*bicsi3_cbranch"
6163   [(set (pc)
6164         (if_then_else
6165          (match_operator 5 "equality_operator"
6166           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6167                    (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6168            (const_int 0)])
6169          (label_ref (match_operand 4 "" ""))
6170          (pc)))
6171    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6172         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6173    (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6174   "TARGET_THUMB"
6175   "*
6176   {
6177   if (which_alternative == 0)
6178     output_asm_insn (\"bic\\t%0, %3\", operands);
6179   else if (which_alternative <= 2)
6180     {
6181       output_asm_insn (\"bic\\t%1, %3\", operands);
6182       /* It's ok if OP0 is a lo-reg, even though the mov will set the
6183          conditions again, since we're only testing for equality.  */
6184       output_asm_insn (\"mov\\t%0, %1\", operands);
6185     }
6186   else
6187     {
6188       output_asm_insn (\"bic\\t%1, %3\", operands);
6189       output_asm_insn (\"str\\t%1, %0\", operands);
6190     }
6192   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6193     {
6194     case 4:  return \"b%d5\\t%l4\";
6195     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6196     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6197     }
6198   }"
6199   [(set (attr "far_jump")
6200         (if_then_else
6201             (ior (and (eq (symbol_ref ("which_alternative"))
6202                           (const_int 0))
6203                       (eq_attr "length" "8"))
6204                  (eq_attr "length" "10"))
6205             (const_string "yes")
6206             (const_string "no")))
6207    (set (attr "length")
6208      (if_then_else
6209        (eq (symbol_ref ("which_alternative"))
6210                        (const_int 0))
6211        (if_then_else
6212          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6213               (le (minus (match_dup 4) (pc)) (const_int 256)))
6214          (const_int 4)
6215          (if_then_else
6216            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6217                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6218            (const_int 6)
6219            (const_int 8)))
6220        (if_then_else
6221          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6222               (le (minus (match_dup 4) (pc)) (const_int 256)))
6223          (const_int 6)
6224          (if_then_else
6225            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6226                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6227            (const_int 8)
6228            (const_int 10)))))]
6231 (define_insn "*cbranchne_decr1"
6232   [(set (pc)
6233         (if_then_else (match_operator 3 "equality_operator"
6234                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6235                         (const_int 0)])
6236                       (label_ref (match_operand 4 "" ""))
6237                       (pc)))
6238    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6239         (plus:SI (match_dup 2) (const_int -1)))
6240    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6241   "TARGET_THUMB"
6242   "*
6243    {
6244      rtx cond[2];
6245      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6246                                 ? GEU : LTU),
6247                                VOIDmode, operands[2], const1_rtx);
6248      cond[1] = operands[4];
6250      if (which_alternative == 0)
6251        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6252      else if (which_alternative == 1)
6253        {
6254          /* We must provide an alternative for a hi reg because reload 
6255             cannot handle output reloads on a jump instruction, but we
6256             can't subtract into that.  Fortunately a mov from lo to hi
6257             does not clobber the condition codes.  */
6258          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6259          output_asm_insn (\"mov\\t%0, %1\", operands);
6260        }
6261      else
6262        {
6263          /* Similarly, but the target is memory.  */
6264          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6265          output_asm_insn (\"str\\t%1, %0\", operands);
6266        }
6268      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6269        {
6270          case 4:
6271            output_asm_insn (\"b%d0\\t%l1\", cond);
6272            return \"\";
6273          case 6:
6274            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6275            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6276          default:
6277            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6278            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6279        }
6280    }
6281   "
6282   [(set (attr "far_jump")
6283         (if_then_else
6284             (ior (and (eq (symbol_ref ("which_alternative"))
6285                           (const_int 0))
6286                       (eq_attr "length" "8"))
6287                  (eq_attr "length" "10"))
6288             (const_string "yes")
6289             (const_string "no")))
6290    (set_attr_alternative "length"
6291       [
6292        ;; Alternative 0
6293        (if_then_else
6294          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6295               (le (minus (match_dup 4) (pc)) (const_int 256)))
6296          (const_int 4)
6297          (if_then_else
6298            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6299                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6300            (const_int 6)
6301            (const_int 8)))
6302        ;; Alternative 1
6303        (if_then_else
6304          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6305               (le (minus (match_dup 4) (pc)) (const_int 256)))
6306          (const_int 6)
6307          (if_then_else
6308            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6309                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6310            (const_int 8)
6311            (const_int 10)))
6312        ;; Alternative 2
6313        (if_then_else
6314          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6315               (le (minus (match_dup 4) (pc)) (const_int 256)))
6316          (const_int 6)
6317          (if_then_else
6318            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6319                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6320            (const_int 8)
6321            (const_int 10)))
6322        ;; Alternative 3
6323        (if_then_else
6324          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6325               (le (minus (match_dup 4) (pc)) (const_int 256)))
6326          (const_int 6)
6327          (if_then_else
6328            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6329                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6330            (const_int 8)
6331            (const_int 10)))])]
6334 (define_insn "*addsi3_cbranch"
6335   [(set (pc)
6336         (if_then_else
6337          (match_operator 4 "comparison_operator"
6338           [(plus:SI
6339             (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6340             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6341            (const_int 0)])
6342          (label_ref (match_operand 5 "" ""))
6343          (pc)))
6344    (set
6345     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6346     (plus:SI (match_dup 2) (match_dup 3)))
6347    (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6348   "TARGET_THUMB
6349    && (GET_CODE (operands[4]) == EQ
6350        || GET_CODE (operands[4]) == NE
6351        || GET_CODE (operands[4]) == GE
6352        || GET_CODE (operands[4]) == LT)"
6353   "*
6354    {
6355      rtx cond[3];
6357      
6358      cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6359      cond[1] = operands[2];
6360      cond[2] = operands[3];
6362      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6363        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6364      else
6365        output_asm_insn (\"add\\t%0, %1, %2\", cond);
6367      if (which_alternative >= 3
6368          && which_alternative < 4)
6369        output_asm_insn (\"mov\\t%0, %1\", operands);
6370      else if (which_alternative >= 4)
6371        output_asm_insn (\"str\\t%1, %0\", operands);
6373      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6374        {
6375          case 4:
6376            return \"b%d4\\t%l5\";
6377          case 6:
6378            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6379          default:
6380            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6381        }
6382    }
6383   "
6384   [(set (attr "far_jump")
6385         (if_then_else
6386             (ior (and (lt (symbol_ref ("which_alternative"))
6387                           (const_int 3))
6388                       (eq_attr "length" "8"))
6389                  (eq_attr "length" "10"))
6390             (const_string "yes")
6391             (const_string "no")))
6392    (set (attr "length")
6393      (if_then_else
6394        (lt (symbol_ref ("which_alternative"))
6395                        (const_int 3))
6396        (if_then_else
6397          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6398               (le (minus (match_dup 5) (pc)) (const_int 256)))
6399          (const_int 4)
6400          (if_then_else
6401            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6402                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6403            (const_int 6)
6404            (const_int 8)))
6405        (if_then_else
6406          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6407               (le (minus (match_dup 5) (pc)) (const_int 256)))
6408          (const_int 6)
6409          (if_then_else
6410            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6411                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6412            (const_int 8)
6413            (const_int 10)))))]
6416 (define_insn "*addsi3_cbranch_scratch"
6417   [(set (pc)
6418         (if_then_else
6419          (match_operator 3 "comparison_operator"
6420           [(plus:SI
6421             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6422             (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
6423            (const_int 0)])
6424          (label_ref (match_operand 4 "" ""))
6425          (pc)))
6426    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6427   "TARGET_THUMB
6428    && (GET_CODE (operands[3]) == EQ
6429        || GET_CODE (operands[3]) == NE
6430        || GET_CODE (operands[3]) == GE
6431        || GET_CODE (operands[3]) == LT)"
6432   "*
6433    {
6434      switch (which_alternative)
6435        {
6436        case 0:
6437          output_asm_insn (\"cmp\t%1, #%n2\", operands);
6438          break;
6439        case 1:
6440          output_asm_insn (\"cmn\t%1, %2\", operands);
6441          break;
6442        case 2:
6443          if (INTVAL (operands[2]) < 0)
6444            output_asm_insn (\"sub\t%0, %1, %2\", operands);
6445          else
6446            output_asm_insn (\"add\t%0, %1, %2\", operands);
6447          break;
6448        case 3:
6449          if (INTVAL (operands[2]) < 0)
6450            output_asm_insn (\"sub\t%0, %0, %2\", operands);
6451          else
6452            output_asm_insn (\"add\t%0, %0, %2\", operands);
6453          break;
6454        }
6456      switch (get_attr_length (insn))
6457        {
6458          case 4:
6459            return \"b%d3\\t%l4\";
6460          case 6:
6461            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6462          default:
6463            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6464        }
6465    }
6466   "
6467   [(set (attr "far_jump")
6468         (if_then_else
6469             (eq_attr "length" "8")
6470             (const_string "yes")
6471             (const_string "no")))
6472    (set (attr "length")
6473        (if_then_else
6474          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6475               (le (minus (match_dup 4) (pc)) (const_int 256)))
6476          (const_int 4)
6477          (if_then_else
6478            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6479                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6480            (const_int 6)
6481            (const_int 8))))]
6484 (define_insn "*subsi3_cbranch"
6485   [(set (pc)
6486         (if_then_else
6487          (match_operator 4 "comparison_operator"
6488           [(minus:SI
6489             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6490             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6491            (const_int 0)])
6492          (label_ref (match_operand 5 "" ""))
6493          (pc)))
6494    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6495         (minus:SI (match_dup 2) (match_dup 3)))
6496    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6497   "TARGET_THUMB
6498    && (GET_CODE (operands[4]) == EQ
6499        || GET_CODE (operands[4]) == NE
6500        || GET_CODE (operands[4]) == GE
6501        || GET_CODE (operands[4]) == LT)"
6502   "*
6503    {
6504      if (which_alternative == 0)
6505        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6506      else if (which_alternative == 1)
6507        {
6508          /* We must provide an alternative for a hi reg because reload 
6509             cannot handle output reloads on a jump instruction, but we
6510             can't subtract into that.  Fortunately a mov from lo to hi
6511             does not clobber the condition codes.  */
6512          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6513          output_asm_insn (\"mov\\t%0, %1\", operands);
6514        }
6515      else
6516        {
6517          /* Similarly, but the target is memory.  */
6518          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6519          output_asm_insn (\"str\\t%1, %0\", operands);
6520        }
6522      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6523        {
6524          case 4:
6525            return \"b%d4\\t%l5\";
6526          case 6:
6527            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6528          default:
6529            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6530        }
6531    }
6532   "
6533   [(set (attr "far_jump")
6534         (if_then_else
6535             (ior (and (eq (symbol_ref ("which_alternative"))
6536                           (const_int 0))
6537                       (eq_attr "length" "8"))
6538                  (eq_attr "length" "10"))
6539             (const_string "yes")
6540             (const_string "no")))
6541    (set (attr "length")
6542      (if_then_else
6543        (eq (symbol_ref ("which_alternative"))
6544                        (const_int 0))
6545        (if_then_else
6546          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6547               (le (minus (match_dup 5) (pc)) (const_int 256)))
6548          (const_int 4)
6549          (if_then_else
6550            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6551                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6552            (const_int 6)
6553            (const_int 8)))
6554        (if_then_else
6555          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6556               (le (minus (match_dup 5) (pc)) (const_int 256)))
6557          (const_int 6)
6558          (if_then_else
6559            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6560                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6561            (const_int 8)
6562            (const_int 10)))))]
6565 (define_insn "*subsi3_cbranch_scratch"
6566   [(set (pc)
6567         (if_then_else
6568          (match_operator 0 "arm_comparison_operator"
6569           [(minus:SI (match_operand:SI 1 "register_operand" "l")
6570                      (match_operand:SI 2 "nonmemory_operand" "l"))
6571            (const_int 0)])
6572          (label_ref (match_operand 3 "" ""))
6573          (pc)))]
6574   "TARGET_THUMB
6575    && (GET_CODE (operands[0]) == EQ
6576        || GET_CODE (operands[0]) == NE
6577        || GET_CODE (operands[0]) == GE
6578        || GET_CODE (operands[0]) == LT)"
6579   "*
6580   output_asm_insn (\"cmp\\t%1, %2\", operands);
6581   switch (get_attr_length (insn))
6582     {
6583     case 4:  return \"b%d0\\t%l3\";
6584     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6585     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6586     }
6587   "
6588   [(set (attr "far_jump")
6589         (if_then_else
6590             (eq_attr "length" "8")
6591             (const_string "yes")
6592             (const_string "no")))
6593    (set (attr "length") 
6594         (if_then_else
6595             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6596                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6597             (const_int 4)
6598             (if_then_else
6599                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6600                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6601                 (const_int 6)
6602                 (const_int 8))))]
6605 ;; Comparison and test insns
6607 (define_expand "cmpsi"
6608   [(match_operand:SI 0 "s_register_operand" "")
6609    (match_operand:SI 1 "arm_add_operand" "")]
6610   "TARGET_ARM"
6611   "{
6612     arm_compare_op0 = operands[0];
6613     arm_compare_op1 = operands[1];
6614     DONE;
6615   }"
6618 (define_expand "cmpsf"
6619   [(match_operand:SF 0 "s_register_operand" "")
6620    (match_operand:SF 1 "arm_float_compare_operand" "")]
6621   "TARGET_ARM && TARGET_HARD_FLOAT"
6622   "
6623   arm_compare_op0 = operands[0];
6624   arm_compare_op1 = operands[1];
6625   DONE;
6626   "
6629 (define_expand "cmpdf"
6630   [(match_operand:DF 0 "s_register_operand" "")
6631    (match_operand:DF 1 "arm_float_compare_operand" "")]
6632   "TARGET_ARM && TARGET_HARD_FLOAT"
6633   "
6634   arm_compare_op0 = operands[0];
6635   arm_compare_op1 = operands[1];
6636   DONE;
6637   "
6640 (define_insn "*arm_cmpsi_insn"
6641   [(set (reg:CC CC_REGNUM)
6642         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6643                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
6644   "TARGET_ARM"
6645   "@
6646    cmp%?\\t%0, %1
6647    cmn%?\\t%0, #%n1"
6648   [(set_attr "conds" "set")]
6651 (define_insn "*cmpsi_shiftsi"
6652   [(set (reg:CC CC_REGNUM)
6653         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
6654                     (match_operator:SI  3 "shift_operator"
6655                      [(match_operand:SI 1 "s_register_operand" "r")
6656                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
6657   "TARGET_ARM"
6658   "cmp%?\\t%0, %1%S3"
6659   [(set_attr "conds" "set")
6660    (set_attr "shift" "1")
6661    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6662                       (const_string "alu_shift")
6663                       (const_string "alu_shift_reg")))]
6666 (define_insn "*cmpsi_shiftsi_swp"
6667   [(set (reg:CC_SWP CC_REGNUM)
6668         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6669                          [(match_operand:SI 1 "s_register_operand" "r")
6670                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
6671                         (match_operand:SI 0 "s_register_operand" "r")))]
6672   "TARGET_ARM"
6673   "cmp%?\\t%0, %1%S3"
6674   [(set_attr "conds" "set")
6675    (set_attr "shift" "1")
6676    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6677                       (const_string "alu_shift")
6678                       (const_string "alu_shift_reg")))]
6681 (define_insn "*cmpsi_neg_shiftsi"
6682   [(set (reg:CC CC_REGNUM)
6683         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6684                     (neg:SI (match_operator:SI 3 "shift_operator"
6685                              [(match_operand:SI 1 "s_register_operand" "r")
6686                               (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
6687   "TARGET_ARM"
6688   "cmn%?\\t%0, %1%S3"
6689   [(set_attr "conds" "set")
6690    (set_attr "shift" "1")
6691    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6692                       (const_string "alu_shift")
6693                       (const_string "alu_shift_reg")))]
6696 ;; Cirrus SF compare instruction
6697 (define_insn "*cirrus_cmpsf"
6698   [(set (reg:CCFP CC_REGNUM)
6699         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6700                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
6701   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6702   "cfcmps%?\\tr15, %V0, %V1"
6703   [(set_attr "type"   "mav_farith")
6704    (set_attr "cirrus" "compare")]
6707 ;; Cirrus DF compare instruction
6708 (define_insn "*cirrus_cmpdf"
6709   [(set (reg:CCFP CC_REGNUM)
6710         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6711                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
6712   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6713   "cfcmpd%?\\tr15, %V0, %V1"
6714   [(set_attr "type"   "mav_farith")
6715    (set_attr "cirrus" "compare")]
6718 ;; Cirrus DI compare instruction
6719 (define_expand "cmpdi"
6720   [(match_operand:DI 0 "cirrus_fp_register" "")
6721    (match_operand:DI 1 "cirrus_fp_register" "")]
6722   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6723   "{
6724      arm_compare_op0 = operands[0];
6725      arm_compare_op1 = operands[1];
6726      DONE;
6727    }")
6729 (define_insn "*cirrus_cmpdi"
6730   [(set (reg:CC CC_REGNUM)
6731         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6732                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
6733   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6734   "cfcmp64%?\\tr15, %V0, %V1"
6735   [(set_attr "type"   "mav_farith")
6736    (set_attr "cirrus" "compare")]
6739 ; This insn allows redundant compares to be removed by cse, nothing should
6740 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6741 ; is deleted later on. The match_dup will match the mode here, so that
6742 ; mode changes of the condition codes aren't lost by this even though we don't
6743 ; specify what they are.
6745 (define_insn "*deleted_compare"
6746   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6747   "TARGET_ARM"
6748   "\\t%@ deleted compare"
6749   [(set_attr "conds" "set")
6750    (set_attr "length" "0")]
6754 ;; Conditional branch insns
6756 (define_expand "beq"
6757   [(set (pc)
6758         (if_then_else (eq (match_dup 1) (const_int 0))
6759                       (label_ref (match_operand 0 "" ""))
6760                       (pc)))]
6761   "TARGET_ARM"
6762   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6765 (define_expand "bne"
6766   [(set (pc)
6767         (if_then_else (ne (match_dup 1) (const_int 0))
6768                       (label_ref (match_operand 0 "" ""))
6769                       (pc)))]
6770   "TARGET_ARM"
6771   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6774 (define_expand "bgt"
6775   [(set (pc)
6776         (if_then_else (gt (match_dup 1) (const_int 0))
6777                       (label_ref (match_operand 0 "" ""))
6778                       (pc)))]
6779   "TARGET_ARM"
6780   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6783 (define_expand "ble"
6784   [(set (pc)
6785         (if_then_else (le (match_dup 1) (const_int 0))
6786                       (label_ref (match_operand 0 "" ""))
6787                       (pc)))]
6788   "TARGET_ARM"
6789   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6792 (define_expand "bge"
6793   [(set (pc)
6794         (if_then_else (ge (match_dup 1) (const_int 0))
6795                       (label_ref (match_operand 0 "" ""))
6796                       (pc)))]
6797   "TARGET_ARM"
6798   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6801 (define_expand "blt"
6802   [(set (pc)
6803         (if_then_else (lt (match_dup 1) (const_int 0))
6804                       (label_ref (match_operand 0 "" ""))
6805                       (pc)))]
6806   "TARGET_ARM"
6807   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6810 (define_expand "bgtu"
6811   [(set (pc)
6812         (if_then_else (gtu (match_dup 1) (const_int 0))
6813                       (label_ref (match_operand 0 "" ""))
6814                       (pc)))]
6815   "TARGET_ARM"
6816   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6819 (define_expand "bleu"
6820   [(set (pc)
6821         (if_then_else (leu (match_dup 1) (const_int 0))
6822                       (label_ref (match_operand 0 "" ""))
6823                       (pc)))]
6824   "TARGET_ARM"
6825   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6828 (define_expand "bgeu"
6829   [(set (pc)
6830         (if_then_else (geu (match_dup 1) (const_int 0))
6831                       (label_ref (match_operand 0 "" ""))
6832                       (pc)))]
6833   "TARGET_ARM"
6834   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6837 (define_expand "bltu"
6838   [(set (pc)
6839         (if_then_else (ltu (match_dup 1) (const_int 0))
6840                       (label_ref (match_operand 0 "" ""))
6841                       (pc)))]
6842   "TARGET_ARM"
6843   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6846 (define_expand "bunordered"
6847   [(set (pc)
6848         (if_then_else (unordered (match_dup 1) (const_int 0))
6849                       (label_ref (match_operand 0 "" ""))
6850                       (pc)))]
6851   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6852   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6853                                       arm_compare_op1);"
6856 (define_expand "bordered"
6857   [(set (pc)
6858         (if_then_else (ordered (match_dup 1) (const_int 0))
6859                       (label_ref (match_operand 0 "" ""))
6860                       (pc)))]
6861   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6862   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6863                                       arm_compare_op1);"
6866 (define_expand "bungt"
6867   [(set (pc)
6868         (if_then_else (ungt (match_dup 1) (const_int 0))
6869                       (label_ref (match_operand 0 "" ""))
6870                       (pc)))]
6871   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6872   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
6875 (define_expand "bunlt"
6876   [(set (pc)
6877         (if_then_else (unlt (match_dup 1) (const_int 0))
6878                       (label_ref (match_operand 0 "" ""))
6879                       (pc)))]
6880   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6881   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
6884 (define_expand "bunge"
6885   [(set (pc)
6886         (if_then_else (unge (match_dup 1) (const_int 0))
6887                       (label_ref (match_operand 0 "" ""))
6888                       (pc)))]
6889   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6890   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
6893 (define_expand "bunle"
6894   [(set (pc)
6895         (if_then_else (unle (match_dup 1) (const_int 0))
6896                       (label_ref (match_operand 0 "" ""))
6897                       (pc)))]
6898   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6899   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
6902 ;; The following two patterns need two branch instructions, since there is
6903 ;; no single instruction that will handle all cases.
6904 (define_expand "buneq"
6905   [(set (pc)
6906         (if_then_else (uneq (match_dup 1) (const_int 0))
6907                       (label_ref (match_operand 0 "" ""))
6908                       (pc)))]
6909   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6910   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6913 (define_expand "bltgt"
6914   [(set (pc)
6915         (if_then_else (ltgt (match_dup 1) (const_int 0))
6916                       (label_ref (match_operand 0 "" ""))
6917                       (pc)))]
6918   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6919   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6923 ;; Patterns to match conditional branch insns.
6926 ; Special pattern to match UNEQ.
6927 (define_insn "*arm_buneq"
6928   [(set (pc)
6929         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6930                       (label_ref (match_operand 0 "" ""))
6931                       (pc)))]
6932   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6933   "*
6934   if (arm_ccfsm_state != 0)
6935     abort ();
6937   return \"bvs\\t%l0\;beq\\t%l0\";
6938   "
6939   [(set_attr "conds" "jump_clob")
6940    (set_attr "length" "8")]
6943 ; Special pattern to match LTGT.
6944 (define_insn "*arm_bltgt"
6945   [(set (pc)
6946         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6947                       (label_ref (match_operand 0 "" ""))
6948                       (pc)))]
6949   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6950   "*
6951   if (arm_ccfsm_state != 0)
6952     abort ();
6954   return \"bmi\\t%l0\;bgt\\t%l0\";
6955   "
6956   [(set_attr "conds" "jump_clob")
6957    (set_attr "length" "8")]
6960 (define_insn "*arm_cond_branch"
6961   [(set (pc)
6962         (if_then_else (match_operator 1 "arm_comparison_operator"
6963                        [(match_operand 2 "cc_register" "") (const_int 0)])
6964                       (label_ref (match_operand 0 "" ""))
6965                       (pc)))]
6966   "TARGET_ARM"
6967   "*
6968   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6969     {
6970       arm_ccfsm_state += 2;
6971       return \"\";
6972     }
6973   return \"b%d1\\t%l0\";
6974   "
6975   [(set_attr "conds" "use")
6976    (set_attr "type" "branch")]
6979 ; Special pattern to match reversed UNEQ.
6980 (define_insn "*arm_buneq_reversed"
6981   [(set (pc)
6982         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6983                       (pc)
6984                       (label_ref (match_operand 0 "" ""))))]
6985   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6986   "*
6987   if (arm_ccfsm_state != 0)
6988     abort ();
6990   return \"bmi\\t%l0\;bgt\\t%l0\";
6991   "
6992   [(set_attr "conds" "jump_clob")
6993    (set_attr "length" "8")]
6996 ; Special pattern to match reversed LTGT.
6997 (define_insn "*arm_bltgt_reversed"
6998   [(set (pc)
6999         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7000                       (pc)
7001                       (label_ref (match_operand 0 "" ""))))]
7002   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7003   "*
7004   if (arm_ccfsm_state != 0)
7005     abort ();
7007   return \"bvs\\t%l0\;beq\\t%l0\";
7008   "
7009   [(set_attr "conds" "jump_clob")
7010    (set_attr "length" "8")]
7013 (define_insn "*arm_cond_branch_reversed"
7014   [(set (pc)
7015         (if_then_else (match_operator 1 "arm_comparison_operator"
7016                        [(match_operand 2 "cc_register" "") (const_int 0)])
7017                       (pc)
7018                       (label_ref (match_operand 0 "" ""))))]
7019   "TARGET_ARM"
7020   "*
7021   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7022     {
7023       arm_ccfsm_state += 2;
7024       return \"\";
7025     }
7026   return \"b%D1\\t%l0\";
7027   "
7028   [(set_attr "conds" "use")
7029    (set_attr "type" "branch")]
7034 ; scc insns
7036 (define_expand "seq"
7037   [(set (match_operand:SI 0 "s_register_operand" "")
7038         (eq:SI (match_dup 1) (const_int 0)))]
7039   "TARGET_ARM"
7040   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7043 (define_expand "sne"
7044   [(set (match_operand:SI 0 "s_register_operand" "")
7045         (ne:SI (match_dup 1) (const_int 0)))]
7046   "TARGET_ARM"
7047   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7050 (define_expand "sgt"
7051   [(set (match_operand:SI 0 "s_register_operand" "")
7052         (gt:SI (match_dup 1) (const_int 0)))]
7053   "TARGET_ARM"
7054   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7057 (define_expand "sle"
7058   [(set (match_operand:SI 0 "s_register_operand" "")
7059         (le:SI (match_dup 1) (const_int 0)))]
7060   "TARGET_ARM"
7061   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7064 (define_expand "sge"
7065   [(set (match_operand:SI 0 "s_register_operand" "")
7066         (ge:SI (match_dup 1) (const_int 0)))]
7067   "TARGET_ARM"
7068   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7071 (define_expand "slt"
7072   [(set (match_operand:SI 0 "s_register_operand" "")
7073         (lt:SI (match_dup 1) (const_int 0)))]
7074   "TARGET_ARM"
7075   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7078 (define_expand "sgtu"
7079   [(set (match_operand:SI 0 "s_register_operand" "")
7080         (gtu:SI (match_dup 1) (const_int 0)))]
7081   "TARGET_ARM"
7082   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7085 (define_expand "sleu"
7086   [(set (match_operand:SI 0 "s_register_operand" "")
7087         (leu:SI (match_dup 1) (const_int 0)))]
7088   "TARGET_ARM"
7089   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7092 (define_expand "sgeu"
7093   [(set (match_operand:SI 0 "s_register_operand" "")
7094         (geu:SI (match_dup 1) (const_int 0)))]
7095   "TARGET_ARM"
7096   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7099 (define_expand "sltu"
7100   [(set (match_operand:SI 0 "s_register_operand" "")
7101         (ltu:SI (match_dup 1) (const_int 0)))]
7102   "TARGET_ARM"
7103   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7106 (define_expand "sunordered"
7107   [(set (match_operand:SI 0 "s_register_operand" "")
7108         (unordered:SI (match_dup 1) (const_int 0)))]
7109   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7110   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7111                                       arm_compare_op1);"
7114 (define_expand "sordered"
7115   [(set (match_operand:SI 0 "s_register_operand" "")
7116         (ordered:SI (match_dup 1) (const_int 0)))]
7117   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7118   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7119                                       arm_compare_op1);"
7122 (define_expand "sungt"
7123   [(set (match_operand:SI 0 "s_register_operand" "")
7124         (ungt:SI (match_dup 1) (const_int 0)))]
7125   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7126   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7127                                       arm_compare_op1);"
7130 (define_expand "sunge"
7131   [(set (match_operand:SI 0 "s_register_operand" "")
7132         (unge:SI (match_dup 1) (const_int 0)))]
7133   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7134   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7135                                       arm_compare_op1);"
7138 (define_expand "sunlt"
7139   [(set (match_operand:SI 0 "s_register_operand" "")
7140         (unlt:SI (match_dup 1) (const_int 0)))]
7141   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7142   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7143                                       arm_compare_op1);"
7146 (define_expand "sunle"
7147   [(set (match_operand:SI 0 "s_register_operand" "")
7148         (unle:SI (match_dup 1) (const_int 0)))]
7149   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7150   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7151                                       arm_compare_op1);"
7154 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7155 ;;; simple ARM instructions. 
7157 ; (define_expand "suneq"
7158 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7159 ;       (uneq:SI (match_dup 1) (const_int 0)))]
7160 ;   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7161 ;   "abort ();"
7162 ; )
7164 ; (define_expand "sltgt"
7165 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7166 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
7167 ;   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7168 ;   "abort ();"
7169 ; )
7171 (define_insn "*mov_scc"
7172   [(set (match_operand:SI 0 "s_register_operand" "=r")
7173         (match_operator:SI 1 "arm_comparison_operator"
7174          [(match_operand 2 "cc_register" "") (const_int 0)]))]
7175   "TARGET_ARM"
7176   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7177   [(set_attr "conds" "use")
7178    (set_attr "length" "8")]
7181 (define_insn "*mov_negscc"
7182   [(set (match_operand:SI 0 "s_register_operand" "=r")
7183         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7184                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7185   "TARGET_ARM"
7186   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7187   [(set_attr "conds" "use")
7188    (set_attr "length" "8")]
7191 (define_insn "*mov_notscc"
7192   [(set (match_operand:SI 0 "s_register_operand" "=r")
7193         (not:SI (match_operator:SI 1 "arm_comparison_operator"
7194                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7195   "TARGET_ARM"
7196   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7197   [(set_attr "conds" "use")
7198    (set_attr "length" "8")]
7202 ;; Conditional move insns
7204 (define_expand "movsicc"
7205   [(set (match_operand:SI 0 "s_register_operand" "")
7206         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7207                          (match_operand:SI 2 "arm_not_operand" "")
7208                          (match_operand:SI 3 "arm_not_operand" "")))]
7209   "TARGET_ARM"
7210   "
7211   {
7212     enum rtx_code code = GET_CODE (operands[1]);
7213     rtx ccreg;
7215     if (code == UNEQ || code == LTGT)
7216       FAIL;
7218     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7219     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7220   }"
7223 (define_expand "movsfcc"
7224   [(set (match_operand:SF 0 "s_register_operand" "")
7225         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7226                          (match_operand:SF 2 "s_register_operand" "")
7227                          (match_operand:SF 3 "nonmemory_operand" "")))]
7228   "TARGET_ARM"
7229   "
7230   {
7231     enum rtx_code code = GET_CODE (operands[1]);
7232     rtx ccreg;
7234     if (code == UNEQ || code == LTGT)
7235       FAIL;
7237     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
7238        Otherwise, ensure it is a valid FP add operand */
7239     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7240         || (!arm_float_add_operand (operands[3], SFmode)))
7241       operands[3] = force_reg (SFmode, operands[3]);
7243     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7244     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7245   }"
7248 (define_expand "movdfcc"
7249   [(set (match_operand:DF 0 "s_register_operand" "")
7250         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7251                          (match_operand:DF 2 "s_register_operand" "")
7252                          (match_operand:DF 3 "arm_float_add_operand" "")))]
7253   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7254   "
7255   {
7256     enum rtx_code code = GET_CODE (operands[1]);
7257     rtx ccreg;
7259     if (code == UNEQ || code == LTGT)
7260       FAIL;
7262     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7263     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7264   }"
7267 (define_insn "*movsicc_insn"
7268   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7269         (if_then_else:SI
7270          (match_operator 3 "arm_comparison_operator"
7271           [(match_operand 4 "cc_register" "") (const_int 0)])
7272          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7273          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7274   "TARGET_ARM"
7275   "@
7276    mov%D3\\t%0, %2
7277    mvn%D3\\t%0, #%B2
7278    mov%d3\\t%0, %1
7279    mvn%d3\\t%0, #%B1
7280    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7281    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7282    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7283    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7284   [(set_attr "length" "4,4,4,4,8,8,8,8")
7285    (set_attr "conds" "use")]
7288 (define_insn "*movsfcc_soft_insn"
7289   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7290         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7291                           [(match_operand 4 "cc_register" "") (const_int 0)])
7292                          (match_operand:SF 1 "s_register_operand" "0,r")
7293                          (match_operand:SF 2 "s_register_operand" "r,0")))]
7294   "TARGET_ARM && TARGET_SOFT_FLOAT"
7295   "@
7296    mov%D3\\t%0, %2
7297    mov%d3\\t%0, %1"
7298   [(set_attr "conds" "use")]
7302 ;; Jump and linkage insns
7304 (define_expand "jump"
7305   [(set (pc)
7306         (label_ref (match_operand 0 "" "")))]
7307   "TARGET_EITHER"
7308   ""
7311 (define_insn "*arm_jump"
7312   [(set (pc)
7313         (label_ref (match_operand 0 "" "")))]
7314   "TARGET_ARM"
7315   "*
7316   {
7317     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7318       {
7319         arm_ccfsm_state += 2;
7320         return \"\";
7321       }
7322     return \"b%?\\t%l0\";
7323   }
7324   "
7325   [(set_attr "predicable" "yes")]
7328 (define_insn "*thumb_jump"
7329   [(set (pc)
7330         (label_ref (match_operand 0 "" "")))]
7331   "TARGET_THUMB"
7332   "*
7333   if (get_attr_length (insn) == 2)
7334     return \"b\\t%l0\";
7335   return \"bl\\t%l0\\t%@ far jump\";
7336   "
7337   [(set (attr "far_jump")
7338         (if_then_else
7339             (eq_attr "length" "4")
7340             (const_string "yes")
7341             (const_string "no")))
7342    (set (attr "length") 
7343         (if_then_else
7344             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7345                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
7346             (const_int 2)
7347             (const_int 4)))]
7350 (define_expand "call"
7351   [(parallel [(call (match_operand 0 "memory_operand" "")
7352                     (match_operand 1 "general_operand" ""))
7353               (use (match_operand 2 "" ""))
7354               (clobber (reg:SI LR_REGNUM))])]
7355   "TARGET_EITHER"
7356   "
7357   {
7358     rtx callee;
7359     
7360     /* In an untyped call, we can get NULL for operand 2.  */
7361     if (operands[2] == NULL_RTX)
7362       operands[2] = const0_rtx;
7363       
7364     /* This is to decide if we should generate indirect calls by loading the
7365        32 bit address of the callee into a register before performing the
7366        branch and link.  operand[2] encodes the long_call/short_call
7367        attribute of the function being called.  This attribute is set whenever
7368        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7369        is used, and the short_call attribute can also be set if function is
7370        declared as static or if it has already been defined in the current
7371        compilation unit.  See arm.c and arm.h for info about this.  The third
7372        parameter to arm_is_longcall_p is used to tell it which pattern
7373        invoked it.  */
7374     callee  = XEXP (operands[0], 0);
7375     
7376     if (GET_CODE (callee) != REG
7377        && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7378       XEXP (operands[0], 0) = force_reg (Pmode, callee);
7379   }"
7382 (define_insn "*call_reg_armv5"
7383   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7384          (match_operand 1 "" ""))
7385    (use (match_operand 2 "" ""))
7386    (clobber (reg:SI LR_REGNUM))]
7387   "TARGET_ARM && arm_arch5"
7388   "blx%?\\t%0"
7389   [(set_attr "type" "call")]
7392 (define_insn "*call_reg_arm"
7393   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7394          (match_operand 1 "" ""))
7395    (use (match_operand 2 "" ""))
7396    (clobber (reg:SI LR_REGNUM))]
7397   "TARGET_ARM && !arm_arch5"
7398   "*
7399   return output_call (operands);
7400   "
7401   ;; length is worst case, normally it is only two
7402   [(set_attr "length" "12")
7403    (set_attr "type" "call")]
7406 (define_insn "*call_mem"
7407   [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7408          (match_operand 1 "" ""))
7409    (use (match_operand 2 "" ""))
7410    (clobber (reg:SI LR_REGNUM))]
7411   "TARGET_ARM"
7412   "*
7413   return output_call_mem (operands);
7414   "
7415   [(set_attr "length" "12")
7416    (set_attr "type" "call")]
7419 (define_insn "*call_reg_thumb_v5"
7420   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7421          (match_operand 1 "" ""))
7422    (use (match_operand 2 "" ""))
7423    (clobber (reg:SI LR_REGNUM))]
7424   "TARGET_THUMB && arm_arch5"
7425   "blx\\t%0"
7426   [(set_attr "length" "2")
7427    (set_attr "type" "call")]
7430 (define_insn "*call_reg_thumb"
7431   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7432          (match_operand 1 "" ""))
7433    (use (match_operand 2 "" ""))
7434    (clobber (reg:SI LR_REGNUM))]
7435   "TARGET_THUMB && !arm_arch5"
7436   "*
7437   {
7438     if (!TARGET_CALLER_INTERWORKING)
7439       return \"bl\\t%__call_via_%0\";
7440     else if (operands[1] == const0_rtx)
7441       return \"bl\\t%__interwork_call_via_%0\";
7442     else if (frame_pointer_needed)
7443       return \"bl\\t%__interwork_r7_call_via_%0\";
7444     else
7445       return \"bl\\t%__interwork_r11_call_via_%0\";
7446   }"
7447   [(set_attr "type" "call")]
7450 (define_expand "call_value"
7451   [(parallel [(set (match_operand       0 "" "")
7452                    (call (match_operand 1 "memory_operand" "")
7453                          (match_operand 2 "general_operand" "")))
7454               (use (match_operand 3 "" ""))
7455               (clobber (reg:SI LR_REGNUM))])]
7456   "TARGET_EITHER"
7457   "
7458   {
7459     rtx callee = XEXP (operands[1], 0);
7460     
7461     /* In an untyped call, we can get NULL for operand 2.  */
7462     if (operands[3] == 0)
7463       operands[3] = const0_rtx;
7464       
7465     /* See the comment in define_expand \"call\".  */
7466     if (GET_CODE (callee) != REG
7467         && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7468       XEXP (operands[1], 0) = force_reg (Pmode, callee);
7469   }"
7472 (define_insn "*call_value_reg_armv5"
7473   [(set (match_operand 0 "" "")
7474         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7475               (match_operand 2 "" "")))
7476    (use (match_operand 3 "" ""))
7477    (clobber (reg:SI LR_REGNUM))]
7478   "TARGET_ARM && arm_arch5"
7479   "blx%?\\t%1"
7480   [(set_attr "type" "call")]
7483 (define_insn "*call_value_reg_arm"
7484   [(set (match_operand 0 "" "")
7485         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7486               (match_operand 2 "" "")))
7487    (use (match_operand 3 "" ""))
7488    (clobber (reg:SI LR_REGNUM))]
7489   "TARGET_ARM && !arm_arch5"
7490   "*
7491   return output_call (&operands[1]);
7492   "
7493   [(set_attr "length" "12")
7494    (set_attr "type" "call")]
7497 (define_insn "*call_value_mem"
7498   [(set (match_operand 0 "" "")
7499         (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7500               (match_operand 2 "" "")))
7501    (use (match_operand 3 "" ""))
7502    (clobber (reg:SI LR_REGNUM))]
7503   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7504   "*
7505   return output_call_mem (&operands[1]);
7506   "
7507   [(set_attr "length" "12")
7508    (set_attr "type" "call")]
7511 (define_insn "*call_value_reg_thumb_v5"
7512   [(set (match_operand 0 "" "")
7513         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7514               (match_operand 2 "" "")))
7515    (use (match_operand 3 "" ""))
7516    (clobber (reg:SI LR_REGNUM))]
7517   "TARGET_THUMB && arm_arch5"
7518   "blx\\t%1"
7519   [(set_attr "length" "2")
7520    (set_attr "type" "call")]
7523 (define_insn "*call_value_reg_thumb"
7524   [(set (match_operand 0 "" "")
7525         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7526               (match_operand 2 "" "")))
7527    (use (match_operand 3 "" ""))
7528    (clobber (reg:SI LR_REGNUM))]
7529   "TARGET_THUMB && !arm_arch5"
7530   "*
7531   {
7532     if (!TARGET_CALLER_INTERWORKING)
7533       return \"bl\\t%__call_via_%1\";
7534     else if (operands[2] == const0_rtx)
7535       return \"bl\\t%__interwork_call_via_%1\";
7536     else if (frame_pointer_needed)
7537       return \"bl\\t%__interwork_r7_call_via_%1\";
7538     else
7539       return \"bl\\t%__interwork_r11_call_via_%1\";
7540   }"
7541   [(set_attr "type" "call")]
7544 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7545 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7547 (define_insn "*call_symbol"
7548   [(call (mem:SI (match_operand:SI 0 "" ""))
7549          (match_operand 1 "" ""))
7550    (use (match_operand 2 "" ""))
7551    (clobber (reg:SI LR_REGNUM))]
7552   "TARGET_ARM
7553    && (GET_CODE (operands[0]) == SYMBOL_REF)
7554    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7555   "*
7556   {
7557     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7558   }"
7559   [(set_attr "type" "call")]
7562 (define_insn "*call_value_symbol"
7563   [(set (match_operand 0 "s_register_operand" "")
7564         (call (mem:SI (match_operand:SI 1 "" ""))
7565         (match_operand:SI 2 "" "")))
7566    (use (match_operand 3 "" ""))
7567    (clobber (reg:SI LR_REGNUM))]
7568   "TARGET_ARM
7569    && (GET_CODE (operands[1]) == SYMBOL_REF)
7570    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7571   "*
7572   {
7573     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7574   }"
7575   [(set_attr "type" "call")]
7578 (define_insn "*call_insn"
7579   [(call (mem:SI (match_operand:SI 0 "" ""))
7580          (match_operand:SI 1 "" ""))
7581    (use (match_operand 2 "" ""))
7582    (clobber (reg:SI LR_REGNUM))]
7583   "TARGET_THUMB
7584    && GET_CODE (operands[0]) == SYMBOL_REF
7585    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7586   "bl\\t%a0"
7587   [(set_attr "length" "4")
7588    (set_attr "type" "call")]
7591 (define_insn "*call_value_insn"
7592   [(set (match_operand 0 "register_operand" "")
7593         (call (mem:SI (match_operand 1 "" ""))
7594               (match_operand 2 "" "")))
7595    (use (match_operand 3 "" ""))
7596    (clobber (reg:SI LR_REGNUM))]
7597   "TARGET_THUMB
7598    && GET_CODE (operands[1]) == SYMBOL_REF
7599    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7600   "bl\\t%a1"
7601   [(set_attr "length" "4")
7602    (set_attr "type" "call")]
7605 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7606 (define_expand "sibcall"
7607   [(parallel [(call (match_operand 0 "memory_operand" "")
7608                     (match_operand 1 "general_operand" ""))
7609               (return)
7610               (use (match_operand 2 "" ""))])]
7611   "TARGET_ARM"
7612   "
7613   {
7614     if (operands[2] == NULL_RTX)
7615       operands[2] = const0_rtx;
7616   }"
7619 (define_expand "sibcall_value"
7620   [(parallel [(set (match_operand 0 "register_operand" "")
7621                    (call (match_operand 1 "memory_operand" "")
7622                          (match_operand 2 "general_operand" "")))
7623               (return)
7624               (use (match_operand 3 "" ""))])]
7625   "TARGET_ARM"
7626   "
7627   {
7628     if (operands[3] == NULL_RTX)
7629       operands[3] = const0_rtx;
7630   }"
7633 (define_insn "*sibcall_insn"
7634  [(call (mem:SI (match_operand:SI 0 "" "X"))
7635         (match_operand 1 "" ""))
7636   (return)
7637   (use (match_operand 2 "" ""))]
7638   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7639   "*
7640   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7641   "
7642   [(set_attr "type" "call")]
7645 (define_insn "*sibcall_value_insn"
7646  [(set (match_operand 0 "s_register_operand" "")
7647        (call (mem:SI (match_operand:SI 1 "" "X"))
7648              (match_operand 2 "" "")))
7649   (return)
7650   (use (match_operand 3 "" ""))]
7651   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7652   "*
7653   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7654   "
7655   [(set_attr "type" "call")]
7658 ;; Often the return insn will be the same as loading from memory, so set attr
7659 (define_insn "return"
7660   [(return)]
7661   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7662   "*
7663   {
7664     if (arm_ccfsm_state == 2)
7665       {
7666         arm_ccfsm_state += 2;
7667         return \"\";
7668       }
7669     return output_return_instruction (const_true_rtx, TRUE, FALSE);
7670   }"
7671   [(set_attr "type" "load1")
7672    (set_attr "length" "12")
7673    (set_attr "predicable" "yes")]
7676 (define_insn "*cond_return"
7677   [(set (pc)
7678         (if_then_else (match_operator 0 "arm_comparison_operator"
7679                        [(match_operand 1 "cc_register" "") (const_int 0)])
7680                       (return)
7681                       (pc)))]
7682   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7683   "*
7684   {
7685     if (arm_ccfsm_state == 2)
7686       {
7687         arm_ccfsm_state += 2;
7688         return \"\";
7689       }
7690     return output_return_instruction (operands[0], TRUE, FALSE);
7691   }"
7692   [(set_attr "conds" "use")
7693    (set_attr "length" "12")
7694    (set_attr "type" "load1")]
7697 (define_insn "*cond_return_inverted"
7698   [(set (pc)
7699         (if_then_else (match_operator 0 "arm_comparison_operator"
7700                        [(match_operand 1 "cc_register" "") (const_int 0)])
7701                       (pc)
7702                       (return)))]
7703   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7704   "*
7705   {
7706     if (arm_ccfsm_state == 2)
7707       {
7708         arm_ccfsm_state += 2;
7709         return \"\";
7710       }
7711     return output_return_instruction (operands[0], TRUE, TRUE);
7712   }"
7713   [(set_attr "conds" "use")
7714    (set_attr "length" "12")
7715    (set_attr "type" "load1")]
7718 ;; Generate a sequence of instructions to determine if the processor is
7719 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7720 ;; mask.
7722 (define_expand "return_addr_mask"
7723   [(set (match_dup 1)
7724       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7725                        (const_int 0)))
7726    (set (match_operand:SI 0 "s_register_operand" "")
7727       (if_then_else:SI (eq (match_dup 1) (const_int 0))
7728                        (const_int -1)
7729                        (const_int 67108860)))] ; 0x03fffffc
7730   "TARGET_ARM"
7731   "
7732   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7733   ")
7735 (define_insn "*check_arch2"
7736   [(set (match_operand:CC_NOOV 0 "cc_register" "")
7737       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7738                        (const_int 0)))]
7739   "TARGET_ARM"
7740   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7741   [(set_attr "length" "8")
7742    (set_attr "conds" "set")]
7745 ;; Call subroutine returning any type.
7747 (define_expand "untyped_call"
7748   [(parallel [(call (match_operand 0 "" "")
7749                     (const_int 0))
7750               (match_operand 1 "" "")
7751               (match_operand 2 "" "")])]
7752   "TARGET_ARM"
7753   "
7754   {
7755     int i;
7757     emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
7759     for (i = 0; i < XVECLEN (operands[2], 0); i++)
7760       {
7761         rtx set = XVECEXP (operands[2], 0, i);
7763         emit_move_insn (SET_DEST (set), SET_SRC (set));
7764       }
7766     /* The optimizer does not know that the call sets the function value
7767        registers we stored in the result block.  We avoid problems by
7768        claiming that all hard registers are used and clobbered at this
7769        point.  */
7770     emit_insn (gen_blockage ());
7772     DONE;
7773   }"
7776 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7777 ;; all of memory.  This blocks insns from being moved across this point.
7779 (define_insn "blockage"
7780   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
7781   "TARGET_EITHER"
7782   ""
7783   [(set_attr "length" "0")
7784    (set_attr "type" "block")]
7787 (define_expand "casesi"
7788   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
7789    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
7790    (match_operand:SI 2 "const_int_operand" "")  ; total range
7791    (match_operand:SI 3 "" "")                   ; table label
7792    (match_operand:SI 4 "" "")]                  ; Out of range label
7793   "TARGET_ARM"
7794   "
7795   {
7796     rtx reg;
7797     if (operands[1] != const0_rtx)
7798       {
7799         reg = gen_reg_rtx (SImode);
7801         emit_insn (gen_addsi3 (reg, operands[0],
7802                                GEN_INT (-INTVAL (operands[1]))));
7803         operands[0] = reg;
7804       }
7806     if (!const_ok_for_arm (INTVAL (operands[2])))
7807       operands[2] = force_reg (SImode, operands[2]);
7809     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
7810                                          operands[4]));
7811     DONE;
7812   }"
7815 ;; The USE in this pattern is needed to tell flow analysis that this is
7816 ;; a CASESI insn.  It has no other purpose.
7817 (define_insn "casesi_internal"
7818   [(parallel [(set (pc)
7819                (if_then_else
7820                 (leu (match_operand:SI 0 "s_register_operand" "r")
7821                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
7822                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
7823                                  (label_ref (match_operand 2 "" ""))))
7824                 (label_ref (match_operand 3 "" ""))))
7825               (clobber (reg:CC CC_REGNUM))
7826               (use (label_ref (match_dup 2)))])]
7827   "TARGET_ARM"
7828   "*
7829     if (flag_pic)
7830       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
7831     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
7832   "
7833   [(set_attr "conds" "clob")
7834    (set_attr "length" "12")]
7837 (define_expand "indirect_jump"
7838   [(set (pc)
7839         (match_operand:SI 0 "s_register_operand" ""))]
7840   "TARGET_EITHER"
7841   ""
7844 ;; NB Never uses BX.
7845 (define_insn "*arm_indirect_jump"
7846   [(set (pc)
7847         (match_operand:SI 0 "s_register_operand" "r"))]
7848   "TARGET_ARM"
7849   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
7850   [(set_attr "predicable" "yes")]
7853 (define_insn "*load_indirect_jump"
7854   [(set (pc)
7855         (match_operand:SI 0 "memory_operand" "m"))]
7856   "TARGET_ARM"
7857   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
7858   [(set_attr "type" "load1")
7859    (set_attr "pool_range" "4096")
7860    (set_attr "neg_pool_range" "4084")
7861    (set_attr "predicable" "yes")]
7864 ;; NB Never uses BX.
7865 (define_insn "*thumb_indirect_jump"
7866   [(set (pc)
7867         (match_operand:SI 0 "register_operand" "l*r"))]
7868   "TARGET_THUMB"
7869   "mov\\tpc, %0"
7870   [(set_attr "conds" "clob")
7871    (set_attr "length" "2")]
7875 ;; Misc insns
7877 (define_insn "nop"
7878   [(const_int 0)]
7879   "TARGET_EITHER"
7880   "*
7881   if (TARGET_ARM)
7882     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
7883   return  \"mov\\tr8, r8\";
7884   "
7885   [(set (attr "length")
7886         (if_then_else (eq_attr "is_thumb" "yes")
7887                       (const_int 2)
7888                       (const_int 4)))]
7892 ;; Patterns to allow combination of arithmetic, cond code and shifts
7894 (define_insn "*arith_shiftsi"
7895   [(set (match_operand:SI 0 "s_register_operand" "=r")
7896         (match_operator:SI 1 "shiftable_operator"
7897           [(match_operator:SI 3 "shift_operator"
7898              [(match_operand:SI 4 "s_register_operand" "r")
7899               (match_operand:SI 5 "reg_or_int_operand" "rI")])
7900            (match_operand:SI 2 "s_register_operand" "r")]))]
7901   "TARGET_ARM"
7902   "%i1%?\\t%0, %2, %4%S3"
7903   [(set_attr "predicable" "yes")
7904    (set_attr "shift" "4")
7905    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7906                       (const_string "alu_shift")
7907                       (const_string "alu_shift_reg")))]
7910 (define_split
7911   [(set (match_operand:SI 0 "s_register_operand" "")
7912         (match_operator:SI 1 "shiftable_operator"
7913          [(match_operator:SI 2 "shiftable_operator"
7914            [(match_operator:SI 3 "shift_operator"
7915              [(match_operand:SI 4 "s_register_operand" "")
7916               (match_operand:SI 5 "reg_or_int_operand" "")])
7917             (match_operand:SI 6 "s_register_operand" "")])
7918           (match_operand:SI 7 "arm_rhs_operand" "")]))
7919    (clobber (match_operand:SI 8 "s_register_operand" ""))]
7920   "TARGET_ARM"
7921   [(set (match_dup 8)
7922         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7923                          (match_dup 6)]))
7924    (set (match_dup 0)
7925         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
7926   "")
7928 (define_insn "*arith_shiftsi_compare0"
7929   [(set (reg:CC_NOOV CC_REGNUM)
7930         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7931                           [(match_operator:SI 3 "shift_operator"
7932                             [(match_operand:SI 4 "s_register_operand" "r")
7933                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
7934                            (match_operand:SI 2 "s_register_operand" "r")])
7935                          (const_int 0)))
7936    (set (match_operand:SI 0 "s_register_operand" "=r")
7937         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7938                          (match_dup 2)]))]
7939   "TARGET_ARM"
7940   "%i1%?s\\t%0, %2, %4%S3"
7941   [(set_attr "conds" "set")
7942    (set_attr "shift" "4")
7943    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7944                       (const_string "alu_shift")
7945                       (const_string "alu_shift_reg")))]
7948 (define_insn "*arith_shiftsi_compare0_scratch"
7949   [(set (reg:CC_NOOV CC_REGNUM)
7950         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7951                           [(match_operator:SI 3 "shift_operator"
7952                             [(match_operand:SI 4 "s_register_operand" "r")
7953                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
7954                            (match_operand:SI 2 "s_register_operand" "r")])
7955                          (const_int 0)))
7956    (clobber (match_scratch:SI 0 "=r"))]
7957   "TARGET_ARM"
7958   "%i1%?s\\t%0, %2, %4%S3"
7959   [(set_attr "conds" "set")
7960    (set_attr "shift" "4")
7961    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7962                       (const_string "alu_shift")
7963                       (const_string "alu_shift_reg")))]
7966 (define_insn "*sub_shiftsi"
7967   [(set (match_operand:SI 0 "s_register_operand" "=r")
7968         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7969                   (match_operator:SI 2 "shift_operator"
7970                    [(match_operand:SI 3 "s_register_operand" "r")
7971                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
7972   "TARGET_ARM"
7973   "sub%?\\t%0, %1, %3%S2"
7974   [(set_attr "predicable" "yes")
7975    (set_attr "shift" "3")
7976    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7977                       (const_string "alu_shift")
7978                       (const_string "alu_shift_reg")))]
7981 (define_insn "*sub_shiftsi_compare0"
7982   [(set (reg:CC_NOOV CC_REGNUM)
7983         (compare:CC_NOOV
7984          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7985                    (match_operator:SI 2 "shift_operator"
7986                     [(match_operand:SI 3 "s_register_operand" "r")
7987                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7988          (const_int 0)))
7989    (set (match_operand:SI 0 "s_register_operand" "=r")
7990         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7991                                                  (match_dup 4)])))]
7992   "TARGET_ARM"
7993   "sub%?s\\t%0, %1, %3%S2"
7994   [(set_attr "conds" "set")
7995    (set_attr "shift" "3")
7996    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7997                       (const_string "alu_shift")
7998                       (const_string "alu_shift_reg")))]
8001 (define_insn "*sub_shiftsi_compare0_scratch"
8002   [(set (reg:CC_NOOV CC_REGNUM)
8003         (compare:CC_NOOV
8004          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8005                    (match_operator:SI 2 "shift_operator"
8006                     [(match_operand:SI 3 "s_register_operand" "r")
8007                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8008          (const_int 0)))
8009    (clobber (match_scratch:SI 0 "=r"))]
8010   "TARGET_ARM"
8011   "sub%?s\\t%0, %1, %3%S2"
8012   [(set_attr "conds" "set")
8013    (set_attr "shift" "3")
8014    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8015                       (const_string "alu_shift")
8016                       (const_string "alu_shift_reg")))]
8021 (define_insn "*and_scc"
8022   [(set (match_operand:SI 0 "s_register_operand" "=r")
8023         (and:SI (match_operator:SI 1 "arm_comparison_operator"
8024                  [(match_operand 3 "cc_register" "") (const_int 0)])
8025                 (match_operand:SI 2 "s_register_operand" "r")))]
8026   "TARGET_ARM"
8027   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8028   [(set_attr "conds" "use")
8029    (set_attr "length" "8")]
8032 (define_insn "*ior_scc"
8033   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8034         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8035                  [(match_operand 3 "cc_register" "") (const_int 0)])
8036                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8037   "TARGET_ARM"
8038   "@
8039    orr%d2\\t%0, %1, #1
8040    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8041   [(set_attr "conds" "use")
8042    (set_attr "length" "4,8")]
8045 (define_insn "*compare_scc"
8046   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8047         (match_operator:SI 1 "arm_comparison_operator"
8048          [(match_operand:SI 2 "s_register_operand" "r,r")
8049           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8050    (clobber (reg:CC CC_REGNUM))]
8051   "TARGET_ARM"
8052   "*
8053     if (operands[3] == const0_rtx)
8054       {
8055         if (GET_CODE (operands[1]) == LT)
8056           return \"mov\\t%0, %2, lsr #31\";
8058         if (GET_CODE (operands[1]) == GE)
8059           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8061         if (GET_CODE (operands[1]) == EQ)
8062           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8063       }
8065     if (GET_CODE (operands[1]) == NE)
8066       {
8067         if (which_alternative == 1)
8068           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8069         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8070       }
8071     if (which_alternative == 1)
8072       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8073     else
8074       output_asm_insn (\"cmp\\t%2, %3\", operands);
8075     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8076   "
8077   [(set_attr "conds" "clob")
8078    (set_attr "length" "12")]
8081 (define_insn "*cond_move"
8082   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8083         (if_then_else:SI (match_operator 3 "equality_operator"
8084                           [(match_operator 4 "arm_comparison_operator"
8085                             [(match_operand 5 "cc_register" "") (const_int 0)])
8086                            (const_int 0)])
8087                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8088                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8089   "TARGET_ARM"
8090   "*
8091     if (GET_CODE (operands[3]) == NE)
8092       {
8093         if (which_alternative != 1)
8094           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8095         if (which_alternative != 0)
8096           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8097         return \"\";
8098       }
8099     if (which_alternative != 0)
8100       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8101     if (which_alternative != 1)
8102       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8103     return \"\";
8104   "
8105   [(set_attr "conds" "use")
8106    (set_attr "length" "4,4,8")]
8109 (define_insn "*cond_arith"
8110   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8111         (match_operator:SI 5 "shiftable_operator" 
8112          [(match_operator:SI 4 "arm_comparison_operator"
8113            [(match_operand:SI 2 "s_register_operand" "r,r")
8114             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8115           (match_operand:SI 1 "s_register_operand" "0,?r")]))
8116    (clobber (reg:CC CC_REGNUM))]
8117   "TARGET_ARM"
8118   "*
8119     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8120       return \"%i5\\t%0, %1, %2, lsr #31\";
8122     output_asm_insn (\"cmp\\t%2, %3\", operands);
8123     if (GET_CODE (operands[5]) == AND)
8124       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8125     else if (GET_CODE (operands[5]) == MINUS)
8126       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8127     else if (which_alternative != 0)
8128       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8129     return \"%i5%d4\\t%0, %1, #1\";
8130   "
8131   [(set_attr "conds" "clob")
8132    (set_attr "length" "12")]
8135 (define_insn "*cond_sub"
8136   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8137         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8138                   (match_operator:SI 4 "arm_comparison_operator"
8139                    [(match_operand:SI 2 "s_register_operand" "r,r")
8140                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8141    (clobber (reg:CC CC_REGNUM))]
8142   "TARGET_ARM"
8143   "*
8144     output_asm_insn (\"cmp\\t%2, %3\", operands);
8145     if (which_alternative != 0)
8146       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8147     return \"sub%d4\\t%0, %1, #1\";
8148   "
8149   [(set_attr "conds" "clob")
8150    (set_attr "length" "8,12")]
8153 (define_insn "*cmp_ite0"
8154   [(set (match_operand 6 "dominant_cc_register" "")
8155         (compare
8156          (if_then_else:SI
8157           (match_operator 4 "arm_comparison_operator"
8158            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8159             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8160           (match_operator:SI 5 "arm_comparison_operator"
8161            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8162             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8163           (const_int 0))
8164          (const_int 0)))]
8165   "TARGET_ARM"
8166   "*
8167   {
8168     static const char * const opcodes[4][2] =
8169     {
8170       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8171        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8172       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8173        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8174       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8175        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8176       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8177        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8178     };
8179     int swap =
8180       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8182     return opcodes[which_alternative][swap];
8183   }"
8184   [(set_attr "conds" "set")
8185    (set_attr "length" "8")]
8188 (define_insn "*cmp_ite1"
8189   [(set (match_operand 6 "dominant_cc_register" "")
8190         (compare
8191          (if_then_else:SI
8192           (match_operator 4 "arm_comparison_operator"
8193            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8194             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8195           (match_operator:SI 5 "arm_comparison_operator"
8196            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8197             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8198           (const_int 1))
8199          (const_int 0)))]
8200   "TARGET_ARM"
8201   "*
8202   {
8203     static const char * const opcodes[4][2] =
8204     {
8205       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8206        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8207       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8208        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8209       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8210        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8211       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8212        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8213     };
8214     int swap =
8215       comparison_dominates_p (GET_CODE (operands[5]),
8216                               reverse_condition (GET_CODE (operands[4])));
8218     return opcodes[which_alternative][swap];
8219   }"
8220   [(set_attr "conds" "set")
8221    (set_attr "length" "8")]
8224 (define_insn "*cmp_and"
8225   [(set (match_operand 6 "dominant_cc_register" "")
8226         (compare
8227          (and:SI
8228           (match_operator 4 "arm_comparison_operator"
8229            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8230             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8231           (match_operator:SI 5 "arm_comparison_operator"
8232            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8233             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8234          (const_int 0)))]
8235   "TARGET_ARM"
8236   "*
8237   {
8238     static const char *const opcodes[4][2] =
8239     {
8240       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8241        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8242       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8243        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8244       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8245        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8246       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8247        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8248     };
8249     int swap =
8250       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8252     return opcodes[which_alternative][swap];
8253   }"
8254   [(set_attr "conds" "set")
8255    (set_attr "predicable" "no")
8256    (set_attr "length" "8")]
8259 (define_insn "*cmp_ior"
8260   [(set (match_operand 6 "dominant_cc_register" "")
8261         (compare
8262          (ior:SI
8263           (match_operator 4 "arm_comparison_operator"
8264            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8265             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8266           (match_operator:SI 5 "arm_comparison_operator"
8267            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8268             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8269          (const_int 0)))]
8270   "TARGET_ARM"
8271   "*
8273   static const char *const opcodes[4][2] =
8274   {
8275     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8276      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8277     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8278      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8279     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8280      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8281     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8282      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8283   };
8284   int swap =
8285     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8287   return opcodes[which_alternative][swap];
8290   [(set_attr "conds" "set")
8291    (set_attr "length" "8")]
8294 (define_insn_and_split "*ior_scc_scc"
8295   [(set (match_operand:SI 0 "s_register_operand" "=r")
8296         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8297                  [(match_operand:SI 1 "s_register_operand" "r")
8298                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8299                 (match_operator:SI 6 "arm_comparison_operator"
8300                  [(match_operand:SI 4 "s_register_operand" "r")
8301                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8302    (clobber (reg:CC CC_REGNUM))]
8303   "TARGET_ARM
8304    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8305        != CCmode)"
8306   "#"
8307   "TARGET_ARM && reload_completed"
8308   [(set (match_dup 7)
8309         (compare
8310          (ior:SI
8311           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8312           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8313          (const_int 0)))
8314    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8315   "operands[7]
8316      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8317                                                   DOM_CC_X_OR_Y),
8318                     CC_REGNUM);"
8319   [(set_attr "conds" "clob")
8320    (set_attr "length" "16")])
8322 ; If the above pattern is followed by a CMP insn, then the compare is 
8323 ; redundant, since we can rework the conditional instruction that follows.
8324 (define_insn_and_split "*ior_scc_scc_cmp"
8325   [(set (match_operand 0 "dominant_cc_register" "")
8326         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8327                           [(match_operand:SI 1 "s_register_operand" "r")
8328                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8329                          (match_operator:SI 6 "arm_comparison_operator"
8330                           [(match_operand:SI 4 "s_register_operand" "r")
8331                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8332                  (const_int 0)))
8333    (set (match_operand:SI 7 "s_register_operand" "=r")
8334         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8335                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8336   "TARGET_ARM"
8337   "#"
8338   "TARGET_ARM && reload_completed"
8339   [(set (match_dup 0)
8340         (compare
8341          (ior:SI
8342           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8343           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8344          (const_int 0)))
8345    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8346   ""
8347   [(set_attr "conds" "set")
8348    (set_attr "length" "16")])
8350 (define_insn_and_split "*and_scc_scc"
8351   [(set (match_operand:SI 0 "s_register_operand" "=r")
8352         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8353                  [(match_operand:SI 1 "s_register_operand" "r")
8354                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8355                 (match_operator:SI 6 "arm_comparison_operator"
8356                  [(match_operand:SI 4 "s_register_operand" "r")
8357                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8358    (clobber (reg:CC CC_REGNUM))]
8359   "TARGET_ARM
8360    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8361        != CCmode)"
8362   "#"
8363   "TARGET_ARM && reload_completed
8364    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8365        != CCmode)"
8366   [(set (match_dup 7)
8367         (compare
8368          (and:SI
8369           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8370           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8371          (const_int 0)))
8372    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8373   "operands[7]
8374      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8375                                                   DOM_CC_X_AND_Y),
8376                     CC_REGNUM);"
8377   [(set_attr "conds" "clob")
8378    (set_attr "length" "16")])
8380 ; If the above pattern is followed by a CMP insn, then the compare is 
8381 ; redundant, since we can rework the conditional instruction that follows.
8382 (define_insn_and_split "*and_scc_scc_cmp"
8383   [(set (match_operand 0 "dominant_cc_register" "")
8384         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8385                           [(match_operand:SI 1 "s_register_operand" "r")
8386                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8387                          (match_operator:SI 6 "arm_comparison_operator"
8388                           [(match_operand:SI 4 "s_register_operand" "r")
8389                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8390                  (const_int 0)))
8391    (set (match_operand:SI 7 "s_register_operand" "=r")
8392         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8393                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8394   "TARGET_ARM"
8395   "#"
8396   "TARGET_ARM && reload_completed"
8397   [(set (match_dup 0)
8398         (compare
8399          (and:SI
8400           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8401           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8402          (const_int 0)))
8403    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8404   ""
8405   [(set_attr "conds" "set")
8406    (set_attr "length" "16")])
8408 ;; If there is no dominance in the comparison, then we can still save an
8409 ;; instruction in the AND case, since we can know that the second compare
8410 ;; need only zero the value if false (if true, then the value is already
8411 ;; correct).
8412 (define_insn_and_split "*and_scc_scc_nodom"
8413   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8414         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8415                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
8416                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8417                 (match_operator:SI 6 "arm_comparison_operator"
8418                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
8419                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8420    (clobber (reg:CC CC_REGNUM))]
8421   "TARGET_ARM
8422    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8423        == CCmode)"
8424   "#"
8425   "TARGET_ARM && reload_completed"
8426   [(parallel [(set (match_dup 0)
8427                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8428               (clobber (reg:CC CC_REGNUM))])
8429    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8430    (set (match_dup 0)
8431         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8432                          (match_dup 0)
8433                          (const_int 0)))]
8434   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8435                                               operands[4], operands[5]),
8436                               CC_REGNUM);
8437    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8438                                   operands[5]);"
8439   [(set_attr "conds" "clob")
8440    (set_attr "length" "20")])
8442 (define_split
8443   [(set (reg:CC_NOOV CC_REGNUM)
8444         (compare:CC_NOOV (ior:SI
8445                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8446                                   (const_int 1))
8447                           (match_operator:SI 1 "comparison_operator"
8448                            [(match_operand:SI 2 "s_register_operand" "")
8449                             (match_operand:SI 3 "arm_add_operand" "")]))
8450                          (const_int 0)))
8451    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8452   "TARGET_ARM"
8453   [(set (match_dup 4)
8454         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8455                 (match_dup 0)))
8456    (set (reg:CC_NOOV CC_REGNUM)
8457         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8458                          (const_int 0)))]
8459   "")
8461 (define_split
8462   [(set (reg:CC_NOOV CC_REGNUM)
8463         (compare:CC_NOOV (ior:SI
8464                           (match_operator:SI 1 "comparison_operator"
8465                            [(match_operand:SI 2 "s_register_operand" "")
8466                             (match_operand:SI 3 "arm_add_operand" "")])
8467                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8468                                   (const_int 1)))
8469                          (const_int 0)))
8470    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8471   "TARGET_ARM"
8472   [(set (match_dup 4)
8473         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8474                 (match_dup 0)))
8475    (set (reg:CC_NOOV CC_REGNUM)
8476         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8477                          (const_int 0)))]
8478   "")
8480 (define_insn "*negscc"
8481   [(set (match_operand:SI 0 "s_register_operand" "=r")
8482         (neg:SI (match_operator 3 "arm_comparison_operator"
8483                  [(match_operand:SI 1 "s_register_operand" "r")
8484                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8485    (clobber (reg:CC CC_REGNUM))]
8486   "TARGET_ARM"
8487   "*
8488   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8489     return \"mov\\t%0, %1, asr #31\";
8491   if (GET_CODE (operands[3]) == NE)
8492     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8494   if (GET_CODE (operands[3]) == GT)
8495     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8497   output_asm_insn (\"cmp\\t%1, %2\", operands);
8498   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8499   return \"mvn%d3\\t%0, #0\";
8500   "
8501   [(set_attr "conds" "clob")
8502    (set_attr "length" "12")]
8505 (define_insn "movcond"
8506   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8507         (if_then_else:SI
8508          (match_operator 5 "arm_comparison_operator"
8509           [(match_operand:SI 3 "s_register_operand" "r,r,r")
8510            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8511          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8512          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8513    (clobber (reg:CC CC_REGNUM))]
8514   "TARGET_ARM"
8515   "*
8516   if (GET_CODE (operands[5]) == LT
8517       && (operands[4] == const0_rtx))
8518     {
8519       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8520         {
8521           if (operands[2] == const0_rtx)
8522             return \"and\\t%0, %1, %3, asr #31\";
8523           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8524         }
8525       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8526         {
8527           if (operands[1] == const0_rtx)
8528             return \"bic\\t%0, %2, %3, asr #31\";
8529           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8530         }
8531       /* The only case that falls through to here is when both ops 1 & 2
8532          are constants.  */
8533     }
8535   if (GET_CODE (operands[5]) == GE
8536       && (operands[4] == const0_rtx))
8537     {
8538       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8539         {
8540           if (operands[2] == const0_rtx)
8541             return \"bic\\t%0, %1, %3, asr #31\";
8542           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8543         }
8544       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8545         {
8546           if (operands[1] == const0_rtx)
8547             return \"and\\t%0, %2, %3, asr #31\";
8548           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8549         }
8550       /* The only case that falls through to here is when both ops 1 & 2
8551          are constants.  */
8552     }
8553   if (GET_CODE (operands[4]) == CONST_INT
8554       && !const_ok_for_arm (INTVAL (operands[4])))
8555     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8556   else
8557     output_asm_insn (\"cmp\\t%3, %4\", operands);
8558   if (which_alternative != 0)
8559     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8560   if (which_alternative != 1)
8561     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8562   return \"\";
8563   "
8564   [(set_attr "conds" "clob")
8565    (set_attr "length" "8,8,12")]
8568 (define_insn "*ifcompare_plus_move"
8569   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8570         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8571                           [(match_operand:SI 4 "s_register_operand" "r,r")
8572                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8573                          (plus:SI
8574                           (match_operand:SI 2 "s_register_operand" "r,r")
8575                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8576                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8577    (clobber (reg:CC CC_REGNUM))]
8578   "TARGET_ARM"
8579   "#"
8580   [(set_attr "conds" "clob")
8581    (set_attr "length" "8,12")]
8584 (define_insn "*if_plus_move"
8585   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8586         (if_then_else:SI
8587          (match_operator 4 "arm_comparison_operator"
8588           [(match_operand 5 "cc_register" "") (const_int 0)])
8589          (plus:SI
8590           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8591           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8592          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8593   "TARGET_ARM"
8594   "@
8595    add%d4\\t%0, %2, %3
8596    sub%d4\\t%0, %2, #%n3
8597    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8598    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8599   [(set_attr "conds" "use")
8600    (set_attr "length" "4,4,8,8")
8601    (set_attr "type" "*,*,*,*")]
8604 (define_insn "*ifcompare_move_plus"
8605   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8606         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8607                           [(match_operand:SI 4 "s_register_operand" "r,r")
8608                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8609                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8610                          (plus:SI
8611                           (match_operand:SI 2 "s_register_operand" "r,r")
8612                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8613    (clobber (reg:CC CC_REGNUM))]
8614   "TARGET_ARM"
8615   "#"
8616   [(set_attr "conds" "clob")
8617    (set_attr "length" "8,12")]
8620 (define_insn "*if_move_plus"
8621   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8622         (if_then_else:SI
8623          (match_operator 4 "arm_comparison_operator"
8624           [(match_operand 5 "cc_register" "") (const_int 0)])
8625          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8626          (plus:SI
8627           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8628           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8629   "TARGET_ARM"
8630   "@
8631    add%D4\\t%0, %2, %3
8632    sub%D4\\t%0, %2, #%n3
8633    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8634    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8635   [(set_attr "conds" "use")
8636    (set_attr "length" "4,4,8,8")
8637    (set_attr "type" "*,*,*,*")]
8640 (define_insn "*ifcompare_arith_arith"
8641   [(set (match_operand:SI 0 "s_register_operand" "=r")
8642         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8643                           [(match_operand:SI 5 "s_register_operand" "r")
8644                            (match_operand:SI 6 "arm_add_operand" "rIL")])
8645                          (match_operator:SI 8 "shiftable_operator"
8646                           [(match_operand:SI 1 "s_register_operand" "r")
8647                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8648                          (match_operator:SI 7 "shiftable_operator"
8649                           [(match_operand:SI 3 "s_register_operand" "r")
8650                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8651    (clobber (reg:CC CC_REGNUM))]
8652   "TARGET_ARM"
8653   "#"
8654   [(set_attr "conds" "clob")
8655    (set_attr "length" "12")]
8658 (define_insn "*if_arith_arith"
8659   [(set (match_operand:SI 0 "s_register_operand" "=r")
8660         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8661                           [(match_operand 8 "cc_register" "") (const_int 0)])
8662                          (match_operator:SI 6 "shiftable_operator"
8663                           [(match_operand:SI 1 "s_register_operand" "r")
8664                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8665                          (match_operator:SI 7 "shiftable_operator"
8666                           [(match_operand:SI 3 "s_register_operand" "r")
8667                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8668   "TARGET_ARM"
8669   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8670   [(set_attr "conds" "use")
8671    (set_attr "length" "8")]
8674 (define_insn "*ifcompare_arith_move"
8675   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8676         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8677                           [(match_operand:SI 2 "s_register_operand" "r,r")
8678                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8679                          (match_operator:SI 7 "shiftable_operator"
8680                           [(match_operand:SI 4 "s_register_operand" "r,r")
8681                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8682                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8683    (clobber (reg:CC CC_REGNUM))]
8684   "TARGET_ARM"
8685   "*
8686   /* If we have an operation where (op x 0) is the identity operation and
8687      the conditional operator is LT or GE and we are comparing against zero and
8688      everything is in registers then we can do this in two instructions.  */
8689   if (operands[3] == const0_rtx
8690       && GET_CODE (operands[7]) != AND
8691       && GET_CODE (operands[5]) == REG
8692       && GET_CODE (operands[1]) == REG 
8693       && REGNO (operands[1]) == REGNO (operands[4])
8694       && REGNO (operands[4]) != REGNO (operands[0]))
8695     {
8696       if (GET_CODE (operands[6]) == LT)
8697         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8698       else if (GET_CODE (operands[6]) == GE)
8699         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8700     }
8701   if (GET_CODE (operands[3]) == CONST_INT
8702       && !const_ok_for_arm (INTVAL (operands[3])))
8703     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8704   else
8705     output_asm_insn (\"cmp\\t%2, %3\", operands);
8706   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8707   if (which_alternative != 0)
8708     return \"mov%D6\\t%0, %1\";
8709   return \"\";
8710   "
8711   [(set_attr "conds" "clob")
8712    (set_attr "length" "8,12")]
8715 (define_insn "*if_arith_move"
8716   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8717         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8718                           [(match_operand 6 "cc_register" "") (const_int 0)])
8719                          (match_operator:SI 5 "shiftable_operator"
8720                           [(match_operand:SI 2 "s_register_operand" "r,r")
8721                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8722                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8723   "TARGET_ARM"
8724   "@
8725    %I5%d4\\t%0, %2, %3
8726    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8727   [(set_attr "conds" "use")
8728    (set_attr "length" "4,8")
8729    (set_attr "type" "*,*")]
8732 (define_insn "*ifcompare_move_arith"
8733   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8734         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8735                           [(match_operand:SI 4 "s_register_operand" "r,r")
8736                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8737                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8738                          (match_operator:SI 7 "shiftable_operator"
8739                           [(match_operand:SI 2 "s_register_operand" "r,r")
8740                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8741    (clobber (reg:CC CC_REGNUM))]
8742   "TARGET_ARM"
8743   "*
8744   /* If we have an operation where (op x 0) is the identity operation and
8745      the conditional operator is LT or GE and we are comparing against zero and
8746      everything is in registers then we can do this in two instructions */
8747   if (operands[5] == const0_rtx
8748       && GET_CODE (operands[7]) != AND
8749       && GET_CODE (operands[3]) == REG
8750       && GET_CODE (operands[1]) == REG 
8751       && REGNO (operands[1]) == REGNO (operands[2])
8752       && REGNO (operands[2]) != REGNO (operands[0]))
8753     {
8754       if (GET_CODE (operands[6]) == GE)
8755         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8756       else if (GET_CODE (operands[6]) == LT)
8757         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8758     }
8760   if (GET_CODE (operands[5]) == CONST_INT
8761       && !const_ok_for_arm (INTVAL (operands[5])))
8762     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
8763   else
8764     output_asm_insn (\"cmp\\t%4, %5\", operands);
8766   if (which_alternative != 0)
8767     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
8768   return \"%I7%D6\\t%0, %2, %3\";
8769   "
8770   [(set_attr "conds" "clob")
8771    (set_attr "length" "8,12")]
8774 (define_insn "*if_move_arith"
8775   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8776         (if_then_else:SI
8777          (match_operator 4 "arm_comparison_operator"
8778           [(match_operand 6 "cc_register" "") (const_int 0)])
8779          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8780          (match_operator:SI 5 "shiftable_operator"
8781           [(match_operand:SI 2 "s_register_operand" "r,r")
8782            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
8783   "TARGET_ARM"
8784   "@
8785    %I5%D4\\t%0, %2, %3
8786    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8787   [(set_attr "conds" "use")
8788    (set_attr "length" "4,8")
8789    (set_attr "type" "*,*")]
8792 (define_insn "*ifcompare_move_not"
8793   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8794         (if_then_else:SI
8795          (match_operator 5 "arm_comparison_operator"
8796           [(match_operand:SI 3 "s_register_operand" "r,r")
8797            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8798          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8799          (not:SI
8800           (match_operand:SI 2 "s_register_operand" "r,r"))))
8801    (clobber (reg:CC CC_REGNUM))]
8802   "TARGET_ARM"
8803   "#"
8804   [(set_attr "conds" "clob")
8805    (set_attr "length" "8,12")]
8808 (define_insn "*if_move_not"
8809   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8810         (if_then_else:SI
8811          (match_operator 4 "arm_comparison_operator"
8812           [(match_operand 3 "cc_register" "") (const_int 0)])
8813          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8814          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8815   "TARGET_ARM"
8816   "@
8817    mvn%D4\\t%0, %2
8818    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
8819    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8820   [(set_attr "conds" "use")
8821    (set_attr "length" "4,8,8")]
8824 (define_insn "*ifcompare_not_move"
8825   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8826         (if_then_else:SI 
8827          (match_operator 5 "arm_comparison_operator"
8828           [(match_operand:SI 3 "s_register_operand" "r,r")
8829            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8830          (not:SI
8831           (match_operand:SI 2 "s_register_operand" "r,r"))
8832          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8833    (clobber (reg:CC CC_REGNUM))]
8834   "TARGET_ARM"
8835   "#"
8836   [(set_attr "conds" "clob")
8837    (set_attr "length" "8,12")]
8840 (define_insn "*if_not_move"
8841   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8842         (if_then_else:SI
8843          (match_operator 4 "arm_comparison_operator"
8844           [(match_operand 3 "cc_register" "") (const_int 0)])
8845          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8846          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8847   "TARGET_ARM"
8848   "@
8849    mvn%d4\\t%0, %2
8850    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
8851    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8852   [(set_attr "conds" "use")
8853    (set_attr "length" "4,8,8")]
8856 (define_insn "*ifcompare_shift_move"
8857   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8858         (if_then_else:SI
8859          (match_operator 6 "arm_comparison_operator"
8860           [(match_operand:SI 4 "s_register_operand" "r,r")
8861            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8862          (match_operator:SI 7 "shift_operator"
8863           [(match_operand:SI 2 "s_register_operand" "r,r")
8864            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
8865          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8866    (clobber (reg:CC CC_REGNUM))]
8867   "TARGET_ARM"
8868   "#"
8869   [(set_attr "conds" "clob")
8870    (set_attr "length" "8,12")]
8873 (define_insn "*if_shift_move"
8874   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8875         (if_then_else:SI
8876          (match_operator 5 "arm_comparison_operator"
8877           [(match_operand 6 "cc_register" "") (const_int 0)])
8878          (match_operator:SI 4 "shift_operator"
8879           [(match_operand:SI 2 "s_register_operand" "r,r,r")
8880            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
8881          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8882   "TARGET_ARM"
8883   "@
8884    mov%d5\\t%0, %2%S4
8885    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
8886    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8887   [(set_attr "conds" "use")
8888    (set_attr "shift" "2")
8889    (set_attr "length" "4,8,8")
8890    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
8891                       (const_string "alu_shift")
8892                       (const_string "alu_shift_reg")))]
8895 (define_insn "*ifcompare_move_shift"
8896   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8897         (if_then_else:SI
8898          (match_operator 6 "arm_comparison_operator"
8899           [(match_operand:SI 4 "s_register_operand" "r,r")
8900            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8901          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8902          (match_operator:SI 7 "shift_operator"
8903           [(match_operand:SI 2 "s_register_operand" "r,r")
8904            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
8905    (clobber (reg:CC CC_REGNUM))]
8906   "TARGET_ARM"
8907   "#"
8908   [(set_attr "conds" "clob")
8909    (set_attr "length" "8,12")]
8912 (define_insn "*if_move_shift"
8913   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8914         (if_then_else:SI
8915          (match_operator 5 "arm_comparison_operator"
8916           [(match_operand 6 "cc_register" "") (const_int 0)])
8917          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8918          (match_operator:SI 4 "shift_operator"
8919           [(match_operand:SI 2 "s_register_operand" "r,r,r")
8920            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
8921   "TARGET_ARM"
8922   "@
8923    mov%D5\\t%0, %2%S4
8924    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
8925    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8926   [(set_attr "conds" "use")
8927    (set_attr "shift" "2")
8928    (set_attr "length" "4,8,8")
8929    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
8930                       (const_string "alu_shift")
8931                       (const_string "alu_shift_reg")))]
8934 (define_insn "*ifcompare_shift_shift"
8935   [(set (match_operand:SI 0 "s_register_operand" "=r")
8936         (if_then_else:SI
8937          (match_operator 7 "arm_comparison_operator"
8938           [(match_operand:SI 5 "s_register_operand" "r")
8939            (match_operand:SI 6 "arm_add_operand" "rIL")])
8940          (match_operator:SI 8 "shift_operator"
8941           [(match_operand:SI 1 "s_register_operand" "r")
8942            (match_operand:SI 2 "arm_rhs_operand" "rM")])
8943          (match_operator:SI 9 "shift_operator"
8944           [(match_operand:SI 3 "s_register_operand" "r")
8945            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
8946    (clobber (reg:CC CC_REGNUM))]
8947   "TARGET_ARM"
8948   "#"
8949   [(set_attr "conds" "clob")
8950    (set_attr "length" "12")]
8953 (define_insn "*if_shift_shift"
8954   [(set (match_operand:SI 0 "s_register_operand" "=r")
8955         (if_then_else:SI
8956          (match_operator 5 "arm_comparison_operator"
8957           [(match_operand 8 "cc_register" "") (const_int 0)])
8958          (match_operator:SI 6 "shift_operator"
8959           [(match_operand:SI 1 "s_register_operand" "r")
8960            (match_operand:SI 2 "arm_rhs_operand" "rM")])
8961          (match_operator:SI 7 "shift_operator"
8962           [(match_operand:SI 3 "s_register_operand" "r")
8963            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
8964   "TARGET_ARM"
8965   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8966   [(set_attr "conds" "use")
8967    (set_attr "shift" "1")
8968    (set_attr "length" "8")
8969    (set (attr "type") (if_then_else
8970                         (and (match_operand 2 "const_int_operand" "")
8971                              (match_operand 4 "const_int_operand" ""))
8972                       (const_string "alu_shift")
8973                       (const_string "alu_shift_reg")))]
8976 (define_insn "*ifcompare_not_arith"
8977   [(set (match_operand:SI 0 "s_register_operand" "=r")
8978         (if_then_else:SI
8979          (match_operator 6 "arm_comparison_operator"
8980           [(match_operand:SI 4 "s_register_operand" "r")
8981            (match_operand:SI 5 "arm_add_operand" "rIL")])
8982          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8983          (match_operator:SI 7 "shiftable_operator"
8984           [(match_operand:SI 2 "s_register_operand" "r")
8985            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
8986    (clobber (reg:CC CC_REGNUM))]
8987   "TARGET_ARM"
8988   "#"
8989   [(set_attr "conds" "clob")
8990    (set_attr "length" "12")]
8993 (define_insn "*if_not_arith"
8994   [(set (match_operand:SI 0 "s_register_operand" "=r")
8995         (if_then_else:SI
8996          (match_operator 5 "arm_comparison_operator"
8997           [(match_operand 4 "cc_register" "") (const_int 0)])
8998          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8999          (match_operator:SI 6 "shiftable_operator"
9000           [(match_operand:SI 2 "s_register_operand" "r")
9001            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
9002   "TARGET_ARM"
9003   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
9004   [(set_attr "conds" "use")
9005    (set_attr "length" "8")]
9008 (define_insn "*ifcompare_arith_not"
9009   [(set (match_operand:SI 0 "s_register_operand" "=r")
9010         (if_then_else:SI
9011          (match_operator 6 "arm_comparison_operator"
9012           [(match_operand:SI 4 "s_register_operand" "r")
9013            (match_operand:SI 5 "arm_add_operand" "rIL")])
9014          (match_operator:SI 7 "shiftable_operator"
9015           [(match_operand:SI 2 "s_register_operand" "r")
9016            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9017          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9018    (clobber (reg:CC CC_REGNUM))]
9019   "TARGET_ARM"
9020   "#"
9021   [(set_attr "conds" "clob")
9022    (set_attr "length" "12")]
9025 (define_insn "*if_arith_not"
9026   [(set (match_operand:SI 0 "s_register_operand" "=r")
9027         (if_then_else:SI
9028          (match_operator 5 "arm_comparison_operator"
9029           [(match_operand 4 "cc_register" "") (const_int 0)])
9030          (match_operator:SI 6 "shiftable_operator"
9031           [(match_operand:SI 2 "s_register_operand" "r")
9032            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9033          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9034   "TARGET_ARM"
9035   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9036   [(set_attr "conds" "use")
9037    (set_attr "length" "8")]
9040 (define_insn "*ifcompare_neg_move"
9041   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9042         (if_then_else:SI
9043          (match_operator 5 "arm_comparison_operator"
9044           [(match_operand:SI 3 "s_register_operand" "r,r")
9045            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9046          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9047          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9048    (clobber (reg:CC CC_REGNUM))]
9049   "TARGET_ARM"
9050   "#"
9051   [(set_attr "conds" "clob")
9052    (set_attr "length" "8,12")]
9055 (define_insn "*if_neg_move"
9056   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9057         (if_then_else:SI
9058          (match_operator 4 "arm_comparison_operator"
9059           [(match_operand 3 "cc_register" "") (const_int 0)])
9060          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9061          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9062   "TARGET_ARM"
9063   "@
9064    rsb%d4\\t%0, %2, #0
9065    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9066    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9067   [(set_attr "conds" "use")
9068    (set_attr "length" "4,8,8")]
9071 (define_insn "*ifcompare_move_neg"
9072   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9073         (if_then_else:SI
9074          (match_operator 5 "arm_comparison_operator"
9075           [(match_operand:SI 3 "s_register_operand" "r,r")
9076            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9077          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9078          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9079    (clobber (reg:CC CC_REGNUM))]
9080   "TARGET_ARM"
9081   "#"
9082   [(set_attr "conds" "clob")
9083    (set_attr "length" "8,12")]
9086 (define_insn "*if_move_neg"
9087   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9088         (if_then_else:SI
9089          (match_operator 4 "arm_comparison_operator"
9090           [(match_operand 3 "cc_register" "") (const_int 0)])
9091          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9092          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9093   "TARGET_ARM"
9094   "@
9095    rsb%D4\\t%0, %2, #0
9096    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9097    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9098   [(set_attr "conds" "use")
9099    (set_attr "length" "4,8,8")]
9102 (define_insn "*arith_adjacentmem"
9103   [(set (match_operand:SI 0 "s_register_operand" "=r")
9104         (match_operator:SI 1 "shiftable_operator"
9105          [(match_operand:SI 2 "memory_operand" "m")
9106           (match_operand:SI 3 "memory_operand" "m")]))
9107    (clobber (match_scratch:SI 4 "=r"))]
9108   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9109   "*
9110   {
9111     rtx ldm[3];
9112     rtx arith[4];
9113     int val1 = 0, val2 = 0;
9115     if (REGNO (operands[0]) > REGNO (operands[4]))
9116       {
9117         ldm[1] = operands[4];
9118         ldm[2] = operands[0];
9119       }
9120     else
9121       {
9122         ldm[1] = operands[0];
9123         ldm[2] = operands[4];
9124       }
9125     if (GET_CODE (XEXP (operands[2], 0)) != REG)
9126       val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
9127     if (GET_CODE (XEXP (operands[3], 0)) != REG)
9128       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9129     arith[0] = operands[0];
9130     arith[3] = operands[1];
9131     if (val1 < val2)
9132       {
9133         arith[1] = ldm[1];
9134         arith[2] = ldm[2];
9135       }
9136     else
9137       {
9138         arith[1] = ldm[2];
9139         arith[2] = ldm[1];
9140       }
9141    if (val1 && val2)
9142       {
9143         rtx ops[3];
9144         ldm[0] = ops[0] = operands[4];
9145         ops[1] = XEXP (XEXP (operands[2], 0), 0);
9146         ops[2] = XEXP (XEXP (operands[2], 0), 1);
9147         output_add_immediate (ops);
9148         if (val1 < val2)
9149           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9150         else
9151           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9152       }
9153     else if (val1)
9154       {
9155         ldm[0] = XEXP (operands[3], 0);
9156         if (val1 < val2)
9157           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9158         else
9159           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9160       }
9161     else
9162       {
9163         ldm[0] = XEXP (operands[2], 0);
9164         if (val1 < val2)
9165           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9166         else
9167           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9168       }
9169     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9170     return \"\";
9171   }"
9172   [(set_attr "length" "12")
9173    (set_attr "predicable" "yes")
9174    (set_attr "type" "load1")]
9177 ;; the arm can support extended pre-inc instructions
9179 ;; In all these cases, we use operands 0 and 1 for the register being
9180 ;; incremented because those are the operands that local-alloc will
9181 ;; tie and these are the pair most likely to be tieable (and the ones
9182 ;; that will benefit the most).
9184 ;; We reject the frame pointer if it occurs anywhere in these patterns since
9185 ;; elimination will cause too many headaches.
9187 (define_insn "*strqi_preinc"
9188   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9189                          (match_operand:SI 2 "index_operand" "rJ")))
9190         (match_operand:QI 3 "s_register_operand" "r"))
9191    (set (match_operand:SI 0 "s_register_operand" "=r")
9192         (plus:SI (match_dup 1) (match_dup 2)))]
9193   "TARGET_ARM
9194    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9195    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9196    && (GET_CODE (operands[2]) != REG
9197        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9198   "str%?b\\t%3, [%0, %2]!"
9199   [(set_attr "type" "store1")
9200    (set_attr "predicable" "yes")]
9203 (define_insn "*strqi_predec"
9204   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9205                           (match_operand:SI 2 "s_register_operand" "r")))
9206         (match_operand:QI 3 "s_register_operand" "r"))
9207    (set (match_operand:SI 0 "s_register_operand" "=r")
9208         (minus:SI (match_dup 1) (match_dup 2)))]
9209   "TARGET_ARM
9210    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9211    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9212    && (GET_CODE (operands[2]) != REG
9213        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9214   "str%?b\\t%3, [%0, -%2]!"
9215   [(set_attr "type" "store1")
9216    (set_attr "predicable" "yes")]
9219 (define_insn "*loadqi_preinc"
9220   [(set (match_operand:QI 3 "s_register_operand" "=r")
9221         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9222                          (match_operand:SI 2 "index_operand" "rJ"))))
9223    (set (match_operand:SI 0 "s_register_operand" "=r")
9224         (plus:SI (match_dup 1) (match_dup 2)))]
9225   "TARGET_ARM
9226    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9227    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9228    && (GET_CODE (operands[2]) != REG
9229        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9230   "ldr%?b\\t%3, [%0, %2]!"
9231   [(set_attr "type" "load_byte")
9232    (set_attr "predicable" "yes")]
9235 (define_insn "*loadqi_predec"
9236   [(set (match_operand:QI 3 "s_register_operand" "=r")
9237         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9238                           (match_operand:SI 2 "s_register_operand" "r"))))
9239    (set (match_operand:SI 0 "s_register_operand" "=r")
9240         (minus:SI (match_dup 1) (match_dup 2)))]
9241   "TARGET_ARM
9242    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9243    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9244    && (GET_CODE (operands[2]) != REG
9245        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9246   "ldr%?b\\t%3, [%0, -%2]!"
9247   [(set_attr "type" "load_byte")
9248    (set_attr "predicable" "yes")]
9251 (define_insn "*loadqisi_preinc"
9252   [(set (match_operand:SI 3 "s_register_operand" "=r")
9253         (zero_extend:SI
9254          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9255                           (match_operand:SI 2 "index_operand" "rJ")))))
9256    (set (match_operand:SI 0 "s_register_operand" "=r")
9257         (plus:SI (match_dup 1) (match_dup 2)))]
9258   "TARGET_ARM
9259    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9260    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9261    && (GET_CODE (operands[2]) != REG
9262        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9263   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
9264   [(set_attr "type" "load_byte")
9265    (set_attr "predicable" "yes")]
9268 (define_insn "*loadqisi_predec"
9269   [(set (match_operand:SI 3 "s_register_operand" "=r")
9270         (zero_extend:SI
9271          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9272                            (match_operand:SI 2 "s_register_operand" "r")))))
9273    (set (match_operand:SI 0 "s_register_operand" "=r")
9274         (minus:SI (match_dup 1) (match_dup 2)))]
9275   "TARGET_ARM
9276    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9277    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9278    && (GET_CODE (operands[2]) != REG
9279        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9280   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
9281   [(set_attr "type" "load_byte")
9282    (set_attr "predicable" "yes")]
9285 (define_insn "*strsi_preinc"
9286   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9287                          (match_operand:SI 2 "index_operand" "rJ")))
9288         (match_operand:SI 3 "s_register_operand" "r"))
9289    (set (match_operand:SI 0 "s_register_operand" "=r")
9290         (plus:SI (match_dup 1) (match_dup 2)))]
9291   "TARGET_ARM
9292    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9293    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9294    && (GET_CODE (operands[2]) != REG
9295        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9296   "str%?\\t%3, [%0, %2]!"
9297   [(set_attr "type" "store1")
9298    (set_attr "predicable" "yes")]
9301 (define_insn "*strsi_predec"
9302   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9303                           (match_operand:SI 2 "s_register_operand" "r")))
9304         (match_operand:SI 3 "s_register_operand" "r"))
9305    (set (match_operand:SI 0 "s_register_operand" "=r")
9306         (minus:SI (match_dup 1) (match_dup 2)))]
9307   "TARGET_ARM
9308    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9309    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9310    && (GET_CODE (operands[2]) != REG
9311        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9312   "str%?\\t%3, [%0, -%2]!"
9313   [(set_attr "type" "store1")
9314    (set_attr "predicable" "yes")]
9317 (define_insn "*loadsi_preinc"
9318   [(set (match_operand:SI 3 "s_register_operand" "=r")
9319         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9320                          (match_operand:SI 2 "index_operand" "rJ"))))
9321    (set (match_operand:SI 0 "s_register_operand" "=r")
9322         (plus:SI (match_dup 1) (match_dup 2)))]
9323   "TARGET_ARM
9324    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9325    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9326    && (GET_CODE (operands[2]) != REG
9327        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9328   "ldr%?\\t%3, [%0, %2]!"
9329   [(set_attr "type" "load1")
9330    (set_attr "predicable" "yes")]
9333 (define_insn "*loadsi_predec"
9334   [(set (match_operand:SI 3 "s_register_operand" "=r")
9335         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9336                           (match_operand:SI 2 "s_register_operand" "r"))))
9337    (set (match_operand:SI 0 "s_register_operand" "=r")
9338         (minus:SI (match_dup 1) (match_dup 2)))]
9339   "TARGET_ARM
9340    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9341    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9342    && (GET_CODE (operands[2]) != REG
9343        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9344   "ldr%?\\t%3, [%0, -%2]!"
9345   [(set_attr "type" "load1")
9346    (set_attr "predicable" "yes")]
9349 (define_insn "*strqi_shiftpreinc"
9350   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9351                           [(match_operand:SI 3 "s_register_operand" "r")
9352                            (match_operand:SI 4 "const_shift_operand" "n")])
9353                          (match_operand:SI 1 "s_register_operand" "0")))
9354         (match_operand:QI 5 "s_register_operand" "r"))
9355    (set (match_operand:SI 0 "s_register_operand" "=r")
9356         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9357                  (match_dup 1)))]
9358   "TARGET_ARM
9359    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9360    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9361    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9362   "str%?b\\t%5, [%0, %3%S2]!"
9363   [(set_attr "type" "store1")
9364    (set_attr "predicable" "yes")]
9367 (define_insn "*strqi_shiftpredec"
9368   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9369                           (match_operator:SI 2 "shift_operator"
9370                            [(match_operand:SI 3 "s_register_operand" "r")
9371                             (match_operand:SI 4 "const_shift_operand" "n")])))
9372         (match_operand:QI 5 "s_register_operand" "r"))
9373    (set (match_operand:SI 0 "s_register_operand" "=r")
9374         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9375                                                  (match_dup 4)])))]
9376   "TARGET_ARM
9377    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9378    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9379    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9380   "str%?b\\t%5, [%0, -%3%S2]!"
9381   [(set_attr "type" "store1")
9382    (set_attr "predicable" "yes")]
9385 (define_insn "*loadqi_shiftpreinc"
9386   [(set (match_operand:QI 5 "s_register_operand" "=r")
9387         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9388                           [(match_operand:SI 3 "s_register_operand" "r")
9389                            (match_operand:SI 4 "const_shift_operand" "n")])
9390                          (match_operand:SI 1 "s_register_operand" "0"))))
9391    (set (match_operand:SI 0 "s_register_operand" "=r")
9392         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9393                  (match_dup 1)))]
9394   "TARGET_ARM
9395    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9396    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9397    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9398   "ldr%?b\\t%5, [%0, %3%S2]!"
9399   [(set_attr "type" "load_byte")
9400    (set_attr "predicable" "yes")]
9403 (define_insn "*loadqi_shiftpredec"
9404   [(set (match_operand:QI 5 "s_register_operand" "=r")
9405         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9406                           (match_operator:SI 2 "shift_operator"
9407                            [(match_operand:SI 3 "s_register_operand" "r")
9408                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9409    (set (match_operand:SI 0 "s_register_operand" "=r")
9410         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9411                                                  (match_dup 4)])))]
9412   "TARGET_ARM
9413    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9414    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9415    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9416   "ldr%?b\\t%5, [%0, -%3%S2]!"
9417   [(set_attr "type" "load_byte")
9418    (set_attr "predicable" "yes")]
9421 (define_insn "*strsi_shiftpreinc"
9422   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9423                           [(match_operand:SI 3 "s_register_operand" "r")
9424                            (match_operand:SI 4 "const_shift_operand" "n")])
9425                          (match_operand:SI 1 "s_register_operand" "0")))
9426         (match_operand:SI 5 "s_register_operand" "r"))
9427    (set (match_operand:SI 0 "s_register_operand" "=r")
9428         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9429                  (match_dup 1)))]
9430   "TARGET_ARM
9431    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9432    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9433    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9434   "str%?\\t%5, [%0, %3%S2]!"
9435   [(set_attr "type" "store1")
9436    (set_attr "predicable" "yes")]
9439 (define_insn "*strsi_shiftpredec"
9440   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9441                           (match_operator:SI 2 "shift_operator"
9442                            [(match_operand:SI 3 "s_register_operand" "r")
9443                             (match_operand:SI 4 "const_shift_operand" "n")])))
9444         (match_operand:SI 5 "s_register_operand" "r"))
9445    (set (match_operand:SI 0 "s_register_operand" "=r")
9446         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9447                                                  (match_dup 4)])))]
9448   "TARGET_ARM
9449    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9450    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9451    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9452   "str%?\\t%5, [%0, -%3%S2]!"
9453   [(set_attr "type" "store1")
9454    (set_attr "predicable" "yes")]
9457 (define_insn "*loadsi_shiftpreinc"
9458   [(set (match_operand:SI 5 "s_register_operand" "=r")
9459         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9460                           [(match_operand:SI 3 "s_register_operand" "r")
9461                            (match_operand:SI 4 "const_shift_operand" "n")])
9462                          (match_operand:SI 1 "s_register_operand" "0"))))
9463    (set (match_operand:SI 0 "s_register_operand" "=r")
9464         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9465                  (match_dup 1)))]
9466   "TARGET_ARM
9467    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9468    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9469    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9470   "ldr%?\\t%5, [%0, %3%S2]!"
9471   [(set_attr "type" "load1")
9472    (set_attr "predicable" "yes")]
9475 (define_insn "*loadsi_shiftpredec"
9476   [(set (match_operand:SI 5 "s_register_operand" "=r")
9477         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9478                           (match_operator:SI 2 "shift_operator"
9479                            [(match_operand:SI 3 "s_register_operand" "r")
9480                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9481    (set (match_operand:SI 0 "s_register_operand" "=r")
9482         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9483                                                  (match_dup 4)])))]
9484   "TARGET_ARM
9485    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9486    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9487    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9488   "ldr%?\\t%5, [%0, -%3%S2]!"
9489   [(set_attr "type" "load1")
9490    (set_attr "predicable" "yes")])
9492 ; It can also support extended post-inc expressions, but combine doesn't
9493 ; try these....
9494 ; It doesn't seem worth adding peepholes for anything but the most common
9495 ; cases since, unlike combine, the increment must immediately follow the load
9496 ; for this pattern to match.
9497 ; We must watch to see that the source/destination register isn't also the
9498 ; same as the base address register, and that if the index is a register,
9499 ; that it is not the same as the base address register.  In such cases the
9500 ; instruction that we would generate would have UNPREDICTABLE behavior so 
9501 ; we cannot use it.
9503 (define_peephole
9504   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9505         (match_operand:QI 2 "s_register_operand" "r"))
9506    (set (match_dup 0)
9507         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9508   "TARGET_ARM
9509    && (REGNO (operands[2]) != REGNO (operands[0]))
9510    && (GET_CODE (operands[1]) != REG
9511        || (REGNO (operands[1]) != REGNO (operands[0])))"
9512   "str%?b\\t%2, [%0], %1"
9515 (define_peephole
9516   [(set (match_operand:QI 0 "s_register_operand" "=r")
9517         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9518    (set (match_dup 1)
9519         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9520   "TARGET_ARM
9521    && REGNO (operands[0]) != REGNO(operands[1])
9522    && (GET_CODE (operands[2]) != REG
9523        || REGNO(operands[0]) != REGNO (operands[2]))"
9524   "ldr%?b\\t%0, [%1], %2"
9527 (define_peephole
9528   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9529         (match_operand:SI 2 "s_register_operand" "r"))
9530    (set (match_dup 0)
9531         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9532   "TARGET_ARM
9533    && (REGNO (operands[2]) != REGNO (operands[0]))
9534    && (GET_CODE (operands[1]) != REG
9535        || (REGNO (operands[1]) != REGNO (operands[0])))"
9536   "str%?\\t%2, [%0], %1"
9539 (define_peephole
9540   [(set (match_operand:SI 0 "s_register_operand" "=r")
9541         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9542    (set (match_dup 1)
9543         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9544   "TARGET_ARM
9545    && REGNO (operands[0]) != REGNO(operands[1])
9546    && (GET_CODE (operands[2]) != REG
9547        || REGNO(operands[0]) != REGNO (operands[2]))"
9548   "ldr%?\\t%0, [%1], %2"
9551 (define_peephole
9552   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9553                          (match_operand:SI 1 "index_operand" "rJ")))
9554         (match_operand:QI 2 "s_register_operand" "r"))
9555    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
9556   "TARGET_ARM
9557    && (REGNO (operands[2]) != REGNO (operands[0]))
9558    && (GET_CODE (operands[1]) != REG
9559        || (REGNO (operands[1]) != REGNO (operands[0])))"
9560   "str%?b\\t%2, [%0, %1]!"
9563 (define_peephole
9564   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9565                           [(match_operand:SI 0 "s_register_operand" "r")
9566                            (match_operand:SI 1 "const_int_operand" "n")])
9567                          (match_operand:SI 2 "s_register_operand" "+r")))
9568         (match_operand:QI 3 "s_register_operand" "r"))
9569    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9570                                (match_dup 2)))]
9571   "TARGET_ARM
9572    && (REGNO (operands[3]) != REGNO (operands[2]))
9573    && (REGNO (operands[0]) != REGNO (operands[2]))"
9574   "str%?b\\t%3, [%2, %0%S4]!"
9577 ; This pattern is never tried by combine, so do it as a peephole
9579 (define_peephole2
9580   [(set (match_operand:SI 0 "arm_general_register_operand" "")
9581         (match_operand:SI 1 "arm_general_register_operand" ""))
9582    (set (reg:CC CC_REGNUM)
9583         (compare:CC (match_dup 1) (const_int 0)))]
9584   "TARGET_ARM"
9585   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9586               (set (match_dup 0) (match_dup 1))])]
9587   ""
9590 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9591 ; reversed, check that the memory references aren't volatile.
9593 (define_peephole
9594   [(set (match_operand:SI 0 "s_register_operand" "=r")
9595         (match_operand:SI 4 "memory_operand" "m"))
9596    (set (match_operand:SI 1 "s_register_operand" "=r")
9597         (match_operand:SI 5 "memory_operand" "m"))
9598    (set (match_operand:SI 2 "s_register_operand" "=r")
9599         (match_operand:SI 6 "memory_operand" "m"))
9600    (set (match_operand:SI 3 "s_register_operand" "=r")
9601         (match_operand:SI 7 "memory_operand" "m"))]
9602   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9603   "*
9604   return emit_ldm_seq (operands, 4);
9605   "
9608 (define_peephole
9609   [(set (match_operand:SI 0 "s_register_operand" "=r")
9610         (match_operand:SI 3 "memory_operand" "m"))
9611    (set (match_operand:SI 1 "s_register_operand" "=r")
9612         (match_operand:SI 4 "memory_operand" "m"))
9613    (set (match_operand:SI 2 "s_register_operand" "=r")
9614         (match_operand:SI 5 "memory_operand" "m"))]
9615   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9616   "*
9617   return emit_ldm_seq (operands, 3);
9618   "
9621 (define_peephole
9622   [(set (match_operand:SI 0 "s_register_operand" "=r")
9623         (match_operand:SI 2 "memory_operand" "m"))
9624    (set (match_operand:SI 1 "s_register_operand" "=r")
9625         (match_operand:SI 3 "memory_operand" "m"))]
9626   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9627   "*
9628   return emit_ldm_seq (operands, 2);
9629   "
9632 (define_peephole
9633   [(set (match_operand:SI 4 "memory_operand" "=m")
9634         (match_operand:SI 0 "s_register_operand" "r"))
9635    (set (match_operand:SI 5 "memory_operand" "=m")
9636         (match_operand:SI 1 "s_register_operand" "r"))
9637    (set (match_operand:SI 6 "memory_operand" "=m")
9638         (match_operand:SI 2 "s_register_operand" "r"))
9639    (set (match_operand:SI 7 "memory_operand" "=m")
9640         (match_operand:SI 3 "s_register_operand" "r"))]
9641   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9642   "*
9643   return emit_stm_seq (operands, 4);
9644   "
9647 (define_peephole
9648   [(set (match_operand:SI 3 "memory_operand" "=m")
9649         (match_operand:SI 0 "s_register_operand" "r"))
9650    (set (match_operand:SI 4 "memory_operand" "=m")
9651         (match_operand:SI 1 "s_register_operand" "r"))
9652    (set (match_operand:SI 5 "memory_operand" "=m")
9653         (match_operand:SI 2 "s_register_operand" "r"))]
9654   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9655   "*
9656   return emit_stm_seq (operands, 3);
9657   "
9660 (define_peephole
9661   [(set (match_operand:SI 2 "memory_operand" "=m")
9662         (match_operand:SI 0 "s_register_operand" "r"))
9663    (set (match_operand:SI 3 "memory_operand" "=m")
9664         (match_operand:SI 1 "s_register_operand" "r"))]
9665   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9666   "*
9667   return emit_stm_seq (operands, 2);
9668   "
9671 (define_split
9672   [(set (match_operand:SI 0 "s_register_operand" "")
9673         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9674                        (const_int 0))
9675                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9676                          [(match_operand:SI 3 "s_register_operand" "")
9677                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
9678    (clobber (match_operand:SI 5 "s_register_operand" ""))]
9679   "TARGET_ARM"
9680   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9681    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9682                               (match_dup 5)))]
9683   ""
9686 ;; This split can be used because CC_Z mode implies that the following
9687 ;; branch will be an equality, or an unsigned inequality, so the sign
9688 ;; extension is not needed.
9690 (define_split
9691   [(set (reg:CC_Z CC_REGNUM)
9692         (compare:CC_Z
9693          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9694                     (const_int 24))
9695          (match_operand 1 "const_int_operand" "")))
9696    (clobber (match_scratch:SI 2 ""))]
9697   "TARGET_ARM
9698    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9699        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9700   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9701    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9702   "
9703   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9704   "
9707 (define_expand "prologue"
9708   [(clobber (const_int 0))]
9709   "TARGET_EITHER"
9710   "if (TARGET_ARM)
9711      arm_expand_prologue ();
9712    else
9713      thumb_expand_prologue ();
9714   DONE;
9715   "
9718 (define_expand "epilogue"
9719   [(clobber (const_int 0))]
9720   "TARGET_EITHER"
9721   "
9722   if (current_function_calls_eh_return)
9723     emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
9724   if (TARGET_THUMB)
9725     thumb_expand_epilogue ();
9726   else if (USE_RETURN_INSN (FALSE))
9727     {
9728       emit_jump_insn (gen_return ());
9729       DONE;
9730     }
9731   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9732         gen_rtvec (1,
9733                 gen_rtx_RETURN (VOIDmode)),
9734         VUNSPEC_EPILOGUE));
9735   DONE;
9736   "
9739 ;; Note - although unspec_volatile's USE all hard registers,
9740 ;; USEs are ignored after relaod has completed.  Thus we need
9741 ;; to add an unspec of the link register to ensure that flow
9742 ;; does not think that it is unused by the sibcall branch that
9743 ;; will replace the standard function epilogue.
9744 (define_insn "sibcall_epilogue"
9745   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9746               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9747   "TARGET_ARM"
9748   "*
9749   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9750     return output_return_instruction (const_true_rtx, FALSE, FALSE);
9751   return arm_output_epilogue (next_nonnote_insn (insn));
9752   "
9753 ;; Length is absolute worst case
9754   [(set_attr "length" "44")
9755    (set_attr "type" "block")
9756    ;; We don't clobber the conditions, but the potential length of this
9757    ;; operation is sufficient to make conditionalizing the sequence 
9758    ;; unlikely to be profitable.
9759    (set_attr "conds" "clob")]
9762 (define_insn "*epilogue_insns"
9763   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9764   "TARGET_EITHER"
9765   "*
9766   if (TARGET_ARM)
9767     return arm_output_epilogue (NULL);
9768   else /* TARGET_THUMB */
9769     return thumb_unexpanded_epilogue ();
9770   "
9771   ; Length is absolute worst case
9772   [(set_attr "length" "44")
9773    (set_attr "type" "block")
9774    ;; We don't clobber the conditions, but the potential length of this
9775    ;; operation is sufficient to make conditionalizing the sequence 
9776    ;; unlikely to be profitable.
9777    (set_attr "conds" "clob")]
9780 (define_expand "eh_epilogue"
9781   [(use (match_operand:SI 0 "register_operand" ""))
9782    (use (match_operand:SI 1 "register_operand" ""))
9783    (use (match_operand:SI 2 "register_operand" ""))]
9784   "TARGET_EITHER"
9785   "
9786   {
9787     cfun->machine->eh_epilogue_sp_ofs = operands[1];
9788     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9789       {
9790         rtx ra = gen_rtx_REG (Pmode, 2);
9792         emit_move_insn (ra, operands[2]);
9793         operands[2] = ra;
9794       }
9795     /* This is a hack -- we may have crystalized the function type too
9796        early.  */
9797     cfun->machine->func_type = 0;
9798   }"
9801 ;; This split is only used during output to reduce the number of patterns
9802 ;; that need assembler instructions adding to them.  We allowed the setting
9803 ;; of the conditions to be implicit during rtl generation so that
9804 ;; the conditional compare patterns would work.  However this conflicts to
9805 ;; some extent with the conditional data operations, so we have to split them
9806 ;; up again here.
9808 (define_split
9809   [(set (match_operand:SI 0 "s_register_operand" "")
9810         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9811                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9812                          (match_dup 0)
9813                          (match_operand 4 "" "")))
9814    (clobber (reg:CC CC_REGNUM))]
9815   "TARGET_ARM && reload_completed"
9816   [(set (match_dup 5) (match_dup 6))
9817    (cond_exec (match_dup 7)
9818               (set (match_dup 0) (match_dup 4)))]
9819   "
9820   {
9821     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9822                                              operands[2], operands[3]);
9823     enum rtx_code rc = GET_CODE (operands[1]);
9825     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9826     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9827     if (mode == CCFPmode || mode == CCFPEmode)
9828       rc = reverse_condition_maybe_unordered (rc);
9829     else
9830       rc = reverse_condition (rc);
9832     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9833   }"
9836 (define_split
9837   [(set (match_operand:SI 0 "s_register_operand" "")
9838         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9839                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9840                          (match_operand 4 "" "")
9841                          (match_dup 0)))
9842    (clobber (reg:CC CC_REGNUM))]
9843   "TARGET_ARM && reload_completed"
9844   [(set (match_dup 5) (match_dup 6))
9845    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9846               (set (match_dup 0) (match_dup 4)))]
9847   "
9848   {
9849     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9850                                              operands[2], operands[3]);
9852     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9853     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9854   }"
9857 (define_split
9858   [(set (match_operand:SI 0 "s_register_operand" "")
9859         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9860                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9861                          (match_operand 4 "" "")
9862                          (match_operand 5 "" "")))
9863    (clobber (reg:CC CC_REGNUM))]
9864   "TARGET_ARM && reload_completed"
9865   [(set (match_dup 6) (match_dup 7))
9866    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9867               (set (match_dup 0) (match_dup 4)))
9868    (cond_exec (match_dup 8)
9869               (set (match_dup 0) (match_dup 5)))]
9870   "
9871   {
9872     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9873                                              operands[2], operands[3]);
9874     enum rtx_code rc = GET_CODE (operands[1]);
9876     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9877     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9878     if (mode == CCFPmode || mode == CCFPEmode)
9879       rc = reverse_condition_maybe_unordered (rc);
9880     else
9881       rc = reverse_condition (rc);
9883     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9884   }"
9887 (define_split
9888   [(set (match_operand:SI 0 "s_register_operand" "")
9889         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9890                           [(match_operand:SI 2 "s_register_operand" "")
9891                            (match_operand:SI 3 "arm_add_operand" "")])
9892                          (match_operand:SI 4 "arm_rhs_operand" "")
9893                          (not:SI
9894                           (match_operand:SI 5 "s_register_operand" ""))))
9895    (clobber (reg:CC CC_REGNUM))]
9896   "TARGET_ARM && reload_completed"
9897   [(set (match_dup 6) (match_dup 7))
9898    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9899               (set (match_dup 0) (match_dup 4)))
9900    (cond_exec (match_dup 8)
9901               (set (match_dup 0) (not:SI (match_dup 5))))]
9902   "
9903   {
9904     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9905                                              operands[2], operands[3]);
9906     enum rtx_code rc = GET_CODE (operands[1]);
9908     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9909     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9910     if (mode == CCFPmode || mode == CCFPEmode)
9911       rc = reverse_condition_maybe_unordered (rc);
9912     else
9913       rc = reverse_condition (rc);
9915     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9916   }"
9919 (define_insn "*cond_move_not"
9920   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9921         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9922                           [(match_operand 3 "cc_register" "") (const_int 0)])
9923                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9924                          (not:SI
9925                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
9926   "TARGET_ARM"
9927   "@
9928    mvn%D4\\t%0, %2
9929    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
9930   [(set_attr "conds" "use")
9931    (set_attr "length" "4,8")]
9934 ;; The next two patterns occur when an AND operation is followed by a
9935 ;; scc insn sequence 
9937 (define_insn "*sign_extract_onebit"
9938   [(set (match_operand:SI 0 "s_register_operand" "=r")
9939         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9940                          (const_int 1)
9941                          (match_operand:SI 2 "const_int_operand" "n")))
9942     (clobber (reg:CC CC_REGNUM))]
9943   "TARGET_ARM"
9944   "*
9945     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9946     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
9947     return \"mvnne\\t%0, #0\";
9948   "
9949   [(set_attr "conds" "clob")
9950    (set_attr "length" "8")]
9953 (define_insn "*not_signextract_onebit"
9954   [(set (match_operand:SI 0 "s_register_operand" "=r")
9955         (not:SI
9956          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9957                           (const_int 1)
9958                           (match_operand:SI 2 "const_int_operand" "n"))))
9959    (clobber (reg:CC CC_REGNUM))]
9960   "TARGET_ARM"
9961   "*
9962     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9963     output_asm_insn (\"tst\\t%1, %2\", operands);
9964     output_asm_insn (\"mvneq\\t%0, #0\", operands);
9965     return \"movne\\t%0, #0\";
9966   "
9967   [(set_attr "conds" "clob")
9968    (set_attr "length" "12")]
9971 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
9972 ;; expressions.  For simplicity, the first register is also in the unspec
9973 ;; part.
9974 (define_insn "*push_multi"
9975   [(match_parallel 2 "multi_register_push"
9976     [(set (match_operand:BLK 0 "memory_operand" "=m")
9977           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
9978                       UNSPEC_PUSH_MULT))])]
9979   "TARGET_ARM"
9980   "*
9981   {
9982     int num_saves = XVECLEN (operands[2], 0);
9983      
9984     /* For the StrongARM at least it is faster to
9985        use STR to store only a single register.  */
9986     if (num_saves == 1)
9987       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9988     else
9989       {
9990         int i;
9991         char pattern[100];
9993         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9995         for (i = 1; i < num_saves; i++)
9996           {
9997             strcat (pattern, \", %|\");
9998             strcat (pattern,
9999                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10000           }
10002         strcat (pattern, \"}\");
10003         output_asm_insn (pattern, operands);
10004       }
10006     return \"\";
10007   }"
10008   [(set_attr "type" "store4")]
10011 (define_insn "stack_tie"
10012   [(set (mem:BLK (scratch))
10013         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
10014                      (match_operand:SI 1 "s_register_operand" "r")]
10015                     UNSPEC_PRLG_STK))]
10016   ""
10017   ""
10018   [(set_attr "length" "0")]
10021 ;; Similarly for the floating point registers
10022 (define_insn "*push_fp_multi"
10023   [(match_parallel 2 "multi_register_push"
10024     [(set (match_operand:BLK 0 "memory_operand" "=m")
10025           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10026                       UNSPEC_PUSH_MULT))])]
10027   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
10028   "*
10029   {
10030     char pattern[100];
10032     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10033     output_asm_insn (pattern, operands);
10034     return \"\";
10035   }"
10036   [(set_attr "type" "f_store")]
10039 ;; Special patterns for dealing with the constant pool
10041 (define_insn "align_4"
10042   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10043   "TARGET_EITHER"
10044   "*
10045   assemble_align (32);
10046   return \"\";
10047   "
10050 (define_insn "align_8"
10051   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10052   "TARGET_EITHER"
10053   "*
10054   assemble_align (64);
10055   return \"\";
10056   "
10059 (define_insn "consttable_end"
10060   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10061   "TARGET_EITHER"
10062   "*
10063   making_const_table = FALSE;
10064   return \"\";
10065   "
10068 (define_insn "consttable_1"
10069   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10070   "TARGET_THUMB"
10071   "*
10072   making_const_table = TRUE;
10073   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10074   assemble_zeros (3);
10075   return \"\";
10076   "
10077   [(set_attr "length" "4")]
10080 (define_insn "consttable_2"
10081   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10082   "TARGET_THUMB"
10083   "*
10084   making_const_table = TRUE;
10085   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10086   assemble_zeros (2);
10087   return \"\";
10088   "
10089   [(set_attr "length" "4")]
10092 (define_insn "consttable_4"
10093   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10094   "TARGET_EITHER"
10095   "*
10096   {
10097     making_const_table = TRUE;
10098     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10099       {
10100       case MODE_FLOAT:
10101       {
10102         REAL_VALUE_TYPE r;
10103         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10104         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10105         break;
10106       }
10107       default:
10108         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
10109         break;
10110       }
10111     return \"\";
10112   }"
10113   [(set_attr "length" "4")]
10116 (define_insn "consttable_8"
10117   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10118   "TARGET_EITHER"
10119   "*
10120   {
10121     making_const_table = TRUE;
10122     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10123       {
10124        case MODE_FLOAT:
10125         {
10126           REAL_VALUE_TYPE r;
10127           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10128           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10129           break;
10130         }
10131       default:
10132         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10133         break;
10134       }
10135     return \"\";
10136   }"
10137   [(set_attr "length" "8")]
10140 ;; Miscellaneous Thumb patterns
10142 (define_expand "tablejump"
10143   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10144               (use (label_ref (match_operand 1 "" "")))])]
10145   "TARGET_THUMB"
10146   "
10147   if (flag_pic)
10148     {
10149       /* Hopefully, CSE will eliminate this copy.  */
10150       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10151       rtx reg2 = gen_reg_rtx (SImode);
10153       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10154       operands[0] = reg2;
10155     }
10156   "
10159 ;; NB never uses BX.
10160 (define_insn "*thumb_tablejump"
10161   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10162    (use (label_ref (match_operand 1 "" "")))]
10163   "TARGET_THUMB"
10164   "mov\\t%|pc, %0"
10165   [(set_attr "length" "2")]
10168 ;; V5 Instructions,
10170 (define_insn "clzsi2"
10171   [(set (match_operand:SI 0 "s_register_operand" "=r")
10172         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10173   "TARGET_ARM && arm_arch5"
10174   "clz%?\\t%0, %1"
10175   [(set_attr "predicable" "yes")])
10177 (define_expand "ffssi2"
10178   [(set (match_operand:SI 0 "s_register_operand" "")
10179         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10180   "TARGET_ARM && arm_arch5"
10181   "
10182   {
10183     rtx t1, t2, t3;
10185     t1 = gen_reg_rtx (SImode);
10186     t2 = gen_reg_rtx (SImode);
10187     t3 = gen_reg_rtx (SImode);
10189     emit_insn (gen_negsi2 (t1, operands[1]));
10190     emit_insn (gen_andsi3 (t2, operands[1], t1));
10191     emit_insn (gen_clzsi2 (t3, t2));
10192     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10193     DONE;
10194   }"
10197 (define_expand "ctzsi2"
10198   [(set (match_operand:SI 0 "s_register_operand" "")
10199         (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10200   "TARGET_ARM && arm_arch5"
10201   "
10202   {
10203     rtx t1, t2, t3;
10205     t1 = gen_reg_rtx (SImode);
10206     t2 = gen_reg_rtx (SImode);
10207     t3 = gen_reg_rtx (SImode);
10209     emit_insn (gen_negsi2 (t1, operands[1]));
10210     emit_insn (gen_andsi3 (t2, operands[1], t1));
10211     emit_insn (gen_clzsi2 (t3, t2));
10212     emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10213     DONE;
10214   }"
10217 ;; V5E instructions.
10219 (define_insn "prefetch"
10220   [(prefetch (match_operand:SI 0 "address_operand" "p")
10221              (match_operand:SI 1 "" "")
10222              (match_operand:SI 2 "" ""))]
10223   "TARGET_ARM && arm_arch5e"
10224   "pld\\t%a0")
10226 ;; General predication pattern
10228 (define_cond_exec
10229   [(match_operator 0 "arm_comparison_operator"
10230     [(match_operand 1 "cc_register" "")
10231      (const_int 0)])]
10232   "TARGET_ARM"
10233   ""
10236 (define_insn "prologue_use"
10237   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10238   ""
10239   "%@ %0 needed for prologue"
10243 ;; Patterns for exception handling
10245 (define_expand "eh_return"
10246   [(use (match_operand 0 "general_operand" ""))]
10247   "TARGET_EITHER"
10248   "
10249   {
10250     if (TARGET_ARM)
10251       emit_insn (gen_arm_eh_return (operands[0]));
10252     else
10253       emit_insn (gen_thumb_eh_return (operands[0]));
10254     DONE;
10255   }"
10257                                    
10258 ;; We can't expand this before we know where the link register is stored.
10259 (define_insn_and_split "arm_eh_return"
10260   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10261                     VUNSPEC_EH_RETURN)
10262    (clobber (match_scratch:SI 1 "=&r"))]
10263   "TARGET_ARM"
10264   "#"
10265   "&& reload_completed"
10266   [(const_int 0)]
10267   "
10268   {
10269     arm_set_return_address (operands[0], operands[1]);
10270     DONE;
10271   }"
10274 (define_insn_and_split "thumb_eh_return"
10275   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10276                     VUNSPEC_EH_RETURN)
10277    (clobber (match_scratch:SI 1 "=&l"))]
10278   "TARGET_THUMB"
10279   "#"
10280   "&& reload_completed"
10281   [(const_int 0)]
10282   "
10283   {
10284     thumb_set_return_address (operands[0], operands[1]);
10285     DONE;
10286   }"
10289 ;; Load the FPA co-processor patterns
10290 (include "fpa.md")
10291 ;; Load the Maverick co-processor patterns
10292 (include "cirrus.md")
10293 ;; Load the Intel Wireless Multimedia Extension patterns
10294 (include "iwmmxt.md")
10295 ;; Load the VFP co-processor patterns
10296 (include "vfp.md")