* config/darwin.c, config/alpha/alpha.h, config/arm/arm.c,
[official-gcc.git] / gcc / config / arm / arm.md
blob13e81e495edc73b6e7ce5ee2a08f6b76db04d6c7
1 ;;- Machine description for ARM for GNU compiler
2 ;;  Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;;  2001, 2002, 2003 2004  Free Software Foundation, Inc.
4 ;;  Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
5 ;;  and Martin Simmons (@harleqn.co.uk).
6 ;;  More major hacks by Richard Earnshaw (rearnsha@arm.com).
8 ;; This file is part of GCC.
10 ;; GCC is free software; you can redistribute it and/or modify it
11 ;; under the terms of the GNU General Public License as published
12 ;; by the Free Software Foundation; either version 2, or (at your
13 ;; option) any later version.
15 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
16 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
18 ;; License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GCC; see the file COPYING.  If not, write to
22 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
28 ;;---------------------------------------------------------------------------
29 ;; Constants
31 ;; Register numbers
32 (define_constants
33   [(IP_REGNUM       12)         ; Scratch register
34    (SP_REGNUM       13)         ; Stack pointer
35    (LR_REGNUM       14)         ; Return address register
36    (PC_REGNUM       15)         ; Program counter
37    (CC_REGNUM       24)         ; Condition code pseudo register
38    (LAST_ARM_REGNUM 15)
39   ]
41 ;; 3rd operand to select_dominance_cc_mode
42 (define_constants
43   [(DOM_CC_X_AND_Y  0)
44    (DOM_CC_NX_OR_Y  1)
45    (DOM_CC_X_OR_Y   2)
46   ]
49 ;; UNSPEC Usage:
50 ;; Note: sin and cos are no-longer used.
52 (define_constants
53   [(UNSPEC_SIN       0) ; `sin' operation (MODE_FLOAT):
54                         ;   operand 0 is the result,
55                         ;   operand 1 the parameter.
56    (UNPSEC_COS       1) ; `cos' operation (MODE_FLOAT):
57                         ;   operand 0 is the result,
58                         ;   operand 1 the parameter.
59    (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
60                         ;   operand 0 is the first register,
61                         ;   subsequent registers are in parallel (use ...)
62                         ;   expressions.
63    (UNSPEC_PIC_SYM   3) ; A symbol that has been treated properly for pic
64                         ;   usage, that is, we will add the pic_register
65                         ;   value to it before trying to dereference it.
66    (UNSPEC_PIC_BASE  4) ; Adding the PC value to the offset to the
67                         ;   GLOBAL_OFFSET_TABLE.  The operation is fully
68                         ;   described by the RTL but must be wrapped to
69                         ;   prevent combine from trying to rip it apart.
70    (UNSPEC_PRLG_STK  5) ; A special barrier that prevents frame accesses 
71                         ;   being scheduled before the stack adjustment insn.
72    (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
73                         ; this unspec is used to prevent the deletion of
74                         ; instructions setting registers for EH handling
75                         ; and stack frame generation.  Operand 0 is the
76                         ; register to "use".
77    (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
78    (UNSPEC_WSHUFH    8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
79    (UNSPEC_WACC      9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
80    (UNSPEC_TMOVMSK  10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
81    (UNSPEC_WSAD     11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
82    (UNSPEC_WSADZ    12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
83    (UNSPEC_WMACS    13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
84    (UNSPEC_WMACU    14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
85    (UNSPEC_WMACSZ   15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
86    (UNSPEC_WMACUZ   16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
87    (UNSPEC_CLRDI    17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
88    (UNSPEC_WMADDS   18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
89    (UNSPEC_WMADDU   19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
90   ]
93 ;; UNSPEC_VOLATILE Usage:
95 (define_constants
96   [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
97                         ;   insn in the code.
98    (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
99                         ;   instruction epilogue sequence that isn't expanded
100                         ;   into normal RTL.  Used for both normal and sibcall
101                         ;   epilogues.
102    (VUNSPEC_ALIGN    2) ; `align' insn.  Used at the head of a minipool table 
103                         ;   for inlined constants.
104    (VUNSPEC_POOL_END 3) ; `end-of-table'.  Used to mark the end of a minipool
105                         ;   table.
106    (VUNSPEC_POOL_1   4) ; `pool-entry(1)'.  An entry in the constant pool for
107                         ;   an 8-bit object.
108    (VUNSPEC_POOL_2   5) ; `pool-entry(2)'.  An entry in the constant pool for
109                         ;   a 16-bit object.
110    (VUNSPEC_POOL_4   6) ; `pool-entry(4)'.  An entry in the constant pool for
111                         ;   a 32-bit object.
112    (VUNSPEC_POOL_8   7) ; `pool-entry(8)'.  An entry in the constant pool for
113                         ;   a 64-bit object.
114    (VUNSPEC_TMRC     8) ; Used by the iWMMXt TMRC instruction.
115    (VUNSPEC_TMCR     9) ; Used by the iWMMXt TMCR instruction.
116    (VUNSPEC_ALIGN8   10) ; 8-byte alignment version of VUNSPEC_ALIGN
117    (VUNSPEC_WCMP_EQ  11) ; Used by the iWMMXt WCMPEQ instructions
118    (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
119    (VUNSPEC_WCMP_GT  13) ; Used by the iwMMXT WCMPGT instructions
120    (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
121                          ; handling.
122   ]
125 ;;---------------------------------------------------------------------------
126 ;; Attributes
128 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
129 ; generating ARM code.  This is used to control the length of some insn
130 ; patterns that share the same RTL in both ARM and Thumb code.
131 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
133 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
134 ; scheduling decisions for the load unit and the multiplier.
135 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
137 ; IS_XSCALE is set to 'yes' when compiling for XScale.
138 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
140 ;; Operand number of an input operand that is shifted.  Zero if the
141 ;; given instruction does not shift one of its input operands.
142 (define_attr "shift" "" (const_int 0))
144 ; Floating Point Unit.  If we only have floating point emulation, then there
145 ; is no point in scheduling the floating point insns.  (Well, for best
146 ; performance we should try and group them together).
147 (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
148   (const (symbol_ref "arm_fpu_attr")))
150 ; LENGTH of an instruction (in bytes)
151 (define_attr "length" "" (const_int 4))
153 ; POOL_RANGE is how far away from a constant pool entry that this insn
154 ; can be placed.  If the distance is zero, then this insn will never
155 ; reference the pool.
156 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
157 ; before its address.
158 (define_attr "pool_range" "" (const_int 0))
159 (define_attr "neg_pool_range" "" (const_int 0))
161 ; An assembler sequence may clobber the condition codes without us knowing.
162 ; If such an insn references the pool, then we have no way of knowing how,
163 ; so use the most conservative value for pool_range.
164 (define_asm_attributes
165  [(set_attr "conds" "clob")
166   (set_attr "length" "4")
167   (set_attr "pool_range" "250")])
169 ;; The instruction used to implement a particular pattern.  This
170 ;; information is used by pipeline descriptions to provide accurate
171 ;; scheduling information.
173 (define_attr "insn"
174         "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals,smlawy,smuad,smuadx,smlad,smladx,smusd,smusdx,smlsd,smlsdx,smmul,smmulr,other"
175         (const_string "other"))
177 ; TYPE attribute is used to detect floating point instructions which, if
178 ; running on a co-processor can run in parallel with other, basic instructions
179 ; If write-buffer scheduling is enabled then it can also be used in the
180 ; scheduling of writes.
182 ; Classification of each insn
183 ; alu           any alu  instruction that doesn't hit memory or fp
184 ;               regs or have a shifted source operand
185 ; alu_shift     any data instruction that doesn't hit memory or fp
186 ;               regs, but has a source operand shifted by a constant
187 ; alu_shift_reg any data instruction that doesn't hit memory or fp
188 ;               regs, but has a source operand shifted by a register value
189 ; mult          a multiply instruction
190 ; block         blockage insn, this blocks all functional units
191 ; float         a floating point arithmetic operation (subject to expansion)
192 ; fdivd         DFmode floating point division
193 ; fdivs         SFmode floating point division
194 ; fmul          Floating point multiply
195 ; ffmul         Fast floating point multiply
196 ; farith        Floating point arithmetic (4 cycle)
197 ; ffarith       Fast floating point arithmetic (2 cycle)
198 ; float_em      a floating point arithmetic operation that is normally emulated
199 ;               even on a machine with an fpa.
200 ; f_load        a floating point load from memory
201 ; f_store       a floating point store to memory
202 ; f_mem_r       a transfer of a floating point register to a real reg via mem
203 ; r_mem_f       the reverse of f_mem_r
204 ; f_2_r         fast transfer float to arm (no memory needed)
205 ; r_2_f         fast transfer arm to float
206 ; branch        a branch
207 ; call          a subroutine call
208 ; load_byte     load byte(s) from memory to arm registers
209 ; load1         load 1 word from memory to arm registers
210 ; load2         load 2 words from memory to arm registers
211 ; load3         load 3 words from memory to arm registers
212 ; load4         load 4 words from memory to arm registers
213 ; store         store 1 word to memory from arm registers
214 ; store2        store 2 words
215 ; store3        store 3 words
216 ; store4        store 4 (or more) words
217 ;  Additions for Cirrus Maverick co-processor:
218 ; mav_farith    Floating point arithmetic (4 cycle)
219 ; mav_dmult     Double multiplies (7 cycle)
221 (define_attr "type"
222         "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,float_em,f_load,f_store,f_mem_r,r_mem_f,f_2_r,r_2_f,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult" 
223         (if_then_else 
224          (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
225          (const_string "mult")
226          (const_string "alu")))
228 ; Load scheduling, set from the arm_ld_sched variable
229 ; initialized by arm_override_options() 
230 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
232 ; condition codes: this one is used by final_prescan_insn to speed up
233 ; conditionalizing instructions.  It saves having to scan the rtl to see if
234 ; it uses or alters the condition codes.
236 ; USE means that the condition codes are used by the insn in the process of
237 ;   outputting code, this means (at present) that we can't use the insn in
238 ;   inlined branches
240 ; SET means that the purpose of the insn is to set the condition codes in a
241 ;   well defined manner.
243 ; CLOB means that the condition codes are altered in an undefined manner, if
244 ;   they are altered at all
246 ; JUMP_CLOB is used when the condition cannot be represented by a single
247 ;   instruction (UNEQ and LTGT).  These cannot be predicated.
249 ; NOCOND means that the condition codes are neither altered nor affect the
250 ;   output of this insn
252 (define_attr "conds" "use,set,clob,jump_clob,nocond"
253         (if_then_else (eq_attr "type" "call")
254          (const_string "clob")
255          (const_string "nocond")))
257 ; Predicable means that the insn can be conditionally executed based on
258 ; an automatically added predicate (additional patterns are generated by 
259 ; gen...).  We default to 'no' because no Thumb patterns match this rule
260 ; and not all ARM patterns do.
261 (define_attr "predicable" "no,yes" (const_string "no"))
263 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
264 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
265 ; suffer blockages enough to warrant modelling this (and it can adversely
266 ; affect the schedule).
267 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
269 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
270 ; to stall the processor.  Used with model_wbuf above.
271 (define_attr "write_conflict" "no,yes"
272   (if_then_else (eq_attr "type"
273                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
274                 (const_string "yes")
275                 (const_string "no")))
277 ; Classify the insns into those that take one cycle and those that take more
278 ; than one on the main cpu execution unit.
279 (define_attr "core_cycles" "single,multi"
280   (if_then_else (eq_attr "type"
281                  "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
282                 (const_string "single")
283                 (const_string "multi")))
285 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
286 ;; distant label.  Only applicable to Thumb code.
287 (define_attr "far_jump" "yes,no" (const_string "no"))
289 (include "predicates.md")
291 ;;---------------------------------------------------------------------------
292 ;; Pipeline descriptions
294 ;; Processor type.  This is created automatically from arm-cores.def.
295 (include "arm-tune.md")
297 ;; True if the generic scheduling description should be used.
299 (define_attr "generic_sched" "yes,no"
300         (if_then_else 
301          (eq_attr "tune" "arm926ejs,arm1026ejs,arm1136js,arm1136jfs") 
302          (const_string "no")
303          (const_string "yes")))
304         
305 (include "arm-generic.md")
306 (include "arm926ejs.md")
307 (include "arm1026ejs.md")
308 (include "arm1136jfs.md")
311 ;;---------------------------------------------------------------------------
312 ;; Insn patterns
314 ;; Addition insns.
316 ;; Note: For DImode insns, there is normally no reason why operands should
317 ;; not be in the same register, what we don't want is for something being
318 ;; written to partially overlap something that is an input.
319 ;; Cirrus 64bit additions should not be split because we have a native
320 ;; 64bit addition instructions.
322 (define_expand "adddi3"
323  [(parallel
324    [(set (match_operand:DI           0 "s_register_operand" "")
325           (plus:DI (match_operand:DI 1 "s_register_operand" "")
326                    (match_operand:DI 2 "s_register_operand" "")))
327     (clobber (reg:CC CC_REGNUM))])]
328   "TARGET_EITHER"
329   "
330   if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
331     {
332       if (!cirrus_fp_register (operands[0], DImode))
333         operands[0] = force_reg (DImode, operands[0]);
334       if (!cirrus_fp_register (operands[1], DImode))
335         operands[1] = force_reg (DImode, operands[1]);
336       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
337       DONE;
338     }
340   if (TARGET_THUMB)
341     {
342       if (GET_CODE (operands[1]) != REG)
343         operands[1] = force_reg (SImode, operands[1]);
344       if (GET_CODE (operands[2]) != REG)
345         operands[2] = force_reg (SImode, operands[2]);
346      }
347   "
350 (define_insn "*thumb_adddi3"
351   [(set (match_operand:DI          0 "register_operand" "=l")
352         (plus:DI (match_operand:DI 1 "register_operand" "%0")
353                  (match_operand:DI 2 "register_operand" "l")))
354    (clobber (reg:CC CC_REGNUM))
355   ]
356   "TARGET_THUMB"
357   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
358   [(set_attr "length" "4")]
361 (define_insn_and_split "*arm_adddi3"
362   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
363         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
364                  (match_operand:DI 2 "s_register_operand" "r,  0")))
365    (clobber (reg:CC CC_REGNUM))]
366   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
367   "#"
368   "TARGET_ARM && reload_completed"
369   [(parallel [(set (reg:CC_C CC_REGNUM)
370                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
371                                  (match_dup 1)))
372               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
373    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
374                                (plus:SI (match_dup 4) (match_dup 5))))]
375   "
376   {
377     operands[3] = gen_highpart (SImode, operands[0]);
378     operands[0] = gen_lowpart (SImode, operands[0]);
379     operands[4] = gen_highpart (SImode, operands[1]);
380     operands[1] = gen_lowpart (SImode, operands[1]);
381     operands[5] = gen_highpart (SImode, operands[2]);
382     operands[2] = gen_lowpart (SImode, operands[2]);
383   }"
384   [(set_attr "conds" "clob")
385    (set_attr "length" "8")]
388 (define_insn_and_split "*adddi_sesidi_di"
389   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
390         (plus:DI (sign_extend:DI
391                   (match_operand:SI 2 "s_register_operand" "r,r"))
392                  (match_operand:DI 1 "s_register_operand" "r,0")))
393    (clobber (reg:CC CC_REGNUM))]
394   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
395   "#"
396   "TARGET_ARM && reload_completed"
397   [(parallel [(set (reg:CC_C CC_REGNUM)
398                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
399                                  (match_dup 1)))
400               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
401    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
402                                (plus:SI (ashiftrt:SI (match_dup 2)
403                                                      (const_int 31))
404                                         (match_dup 4))))]
405   "
406   {
407     operands[3] = gen_highpart (SImode, operands[0]);
408     operands[0] = gen_lowpart (SImode, operands[0]);
409     operands[4] = gen_highpart (SImode, operands[1]);
410     operands[1] = gen_lowpart (SImode, operands[1]);
411     operands[2] = gen_lowpart (SImode, operands[2]);
412   }"
413   [(set_attr "conds" "clob")
414    (set_attr "length" "8")]
417 (define_insn_and_split "*adddi_zesidi_di"
418   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
419         (plus:DI (zero_extend:DI
420                   (match_operand:SI 2 "s_register_operand" "r,r"))
421                  (match_operand:DI 1 "s_register_operand" "r,0")))
422    (clobber (reg:CC CC_REGNUM))]
423   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
424   "#"
425   "TARGET_ARM && reload_completed"
426   [(parallel [(set (reg:CC_C CC_REGNUM)
427                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
428                                  (match_dup 1)))
429               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
430    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
431                                (plus:SI (match_dup 4) (const_int 0))))]
432   "
433   {
434     operands[3] = gen_highpart (SImode, operands[0]);
435     operands[0] = gen_lowpart (SImode, operands[0]);
436     operands[4] = gen_highpart (SImode, operands[1]);
437     operands[1] = gen_lowpart (SImode, operands[1]);
438     operands[2] = gen_lowpart (SImode, operands[2]);
439   }"
440   [(set_attr "conds" "clob")
441    (set_attr "length" "8")]
444 (define_expand "addsi3"
445   [(set (match_operand:SI          0 "s_register_operand" "")
446         (plus:SI (match_operand:SI 1 "s_register_operand" "")
447                  (match_operand:SI 2 "reg_or_int_operand" "")))]
448   "TARGET_EITHER"
449   "
450   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
451     {
452       arm_split_constant (PLUS, SImode, NULL_RTX,
453                           INTVAL (operands[2]), operands[0], operands[1],
454                           optimize && !no_new_pseudos);
455       DONE;
456     }
457   "
460 ; If there is a scratch available, this will be faster than synthesizing the
461 ; addition.
462 (define_peephole2
463   [(match_scratch:SI 3 "r")
464    (set (match_operand:SI          0 "arm_general_register_operand" "")
465         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
466                  (match_operand:SI 2 "const_int_operand"  "")))]
467   "TARGET_ARM &&
468    !(const_ok_for_arm (INTVAL (operands[2]))
469      || const_ok_for_arm (-INTVAL (operands[2])))
470     && const_ok_for_arm (~INTVAL (operands[2]))"
471   [(set (match_dup 3) (match_dup 2))
472    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
473   ""
476 (define_insn_and_split "*arm_addsi3"
477   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
478         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
479                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
480   "TARGET_ARM"
481   "@
482    add%?\\t%0, %1, %2
483    sub%?\\t%0, %1, #%n2
484    #"
485   "TARGET_ARM &&
486    GET_CODE (operands[2]) == CONST_INT
487    && !(const_ok_for_arm (INTVAL (operands[2]))
488         || const_ok_for_arm (-INTVAL (operands[2])))"
489   [(clobber (const_int 0))]
490   "
491   arm_split_constant (PLUS, SImode, curr_insn,
492                       INTVAL (operands[2]), operands[0],
493                       operands[1], 0);
494   DONE;
495   "
496   [(set_attr "length" "4,4,16")
497    (set_attr "predicable" "yes")]
500 ;; Register group 'k' is a single register group containing only the stack
501 ;; register.  Trying to reload it will always fail catastrophically,
502 ;; so never allow those alternatives to match if reloading is needed.
504 (define_insn "*thumb_addsi3"
505   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
506         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
507                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
508   "TARGET_THUMB"
509   "*
510    static const char * const asms[] = 
511    {
512      \"add\\t%0, %0, %2\",
513      \"sub\\t%0, %0, #%n2\",
514      \"add\\t%0, %1, %2\",
515      \"add\\t%0, %0, %2\",
516      \"add\\t%0, %0, %2\",
517      \"add\\t%0, %1, %2\",
518      \"add\\t%0, %1, %2\"
519    };
520    if ((which_alternative == 2 || which_alternative == 6)
521        && GET_CODE (operands[2]) == CONST_INT
522        && INTVAL (operands[2]) < 0)
523      return \"sub\\t%0, %1, #%n2\";
524    return asms[which_alternative];
525   "
526   [(set_attr "length" "2")]
529 ;; Reloading and elimination of the frame pointer can
530 ;; sometimes cause this optimization to be missed.
531 (define_peephole2
532   [(set (match_operand:SI 0 "arm_general_register_operand" "")
533         (match_operand:SI 1 "const_int_operand" ""))
534    (set (match_dup 0)
535         (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
536   "TARGET_THUMB
537    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
538    && (INTVAL (operands[1]) & 3) == 0"
539   [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
540   ""
543 (define_insn "*addsi3_compare0"
544   [(set (reg:CC_NOOV CC_REGNUM)
545         (compare:CC_NOOV
546          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
547                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
548          (const_int 0)))
549    (set (match_operand:SI 0 "s_register_operand" "=r,r")
550         (plus:SI (match_dup 1) (match_dup 2)))]
551   "TARGET_ARM"
552   "@
553    add%?s\\t%0, %1, %2
554    sub%?s\\t%0, %1, #%n2"
555   [(set_attr "conds" "set")]
558 (define_insn "*addsi3_compare0_scratch"
559   [(set (reg:CC_NOOV CC_REGNUM)
560         (compare:CC_NOOV
561          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
562                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
563          (const_int 0)))]
564   "TARGET_ARM"
565   "@
566    cmn%?\\t%0, %1
567    cmp%?\\t%0, #%n1"
568   [(set_attr "conds" "set")]
571 ;; These patterns are the same ones as the two regular addsi3_compare0
572 ;; patterns, except we write them slightly different - the combiner
573 ;; tends to generate them this way.
574 (define_insn "*addsi3_compare0_for_combiner"
575   [(set (reg:CC CC_REGNUM)
576         (compare:CC
577          (match_operand:SI 1 "s_register_operand" "r,r")
578          (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
579    (set (match_operand:SI 0 "s_register_operand" "=r,r")
580         (plus:SI (match_dup 1) (match_dup 2)))]
581   "TARGET_ARM"
582   "@
583    add%?s\\t%0, %1, %2
584    sub%?s\\t%0, %1, #%n2"
585   [(set_attr "conds" "set")]
588 (define_insn "*addsi3_compare0_scratch_for_combiner"
589   [(set (reg:CC CC_REGNUM)
590         (compare:CC
591          (match_operand:SI 0 "s_register_operand" "r,r")
592          (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
593   "TARGET_ARM"
594   "@
595    cmn%?\\t%0, %1
596    cmp%?\\t%0, #%n1"
597   [(set_attr "conds" "set")]
600 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
601 ;; addend is a constant.
602 (define_insn "*cmpsi2_addneg"
603   [(set (reg:CC CC_REGNUM)
604         (compare:CC
605          (match_operand:SI 1 "s_register_operand" "r,r")
606          (match_operand:SI 2 "arm_addimm_operand" "I,L")))
607    (set (match_operand:SI 0 "s_register_operand" "=r,r")
608         (plus:SI (match_dup 1)
609                  (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
610   "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
611   "@
612    sub%?s\\t%0, %1, %2
613    add%?s\\t%0, %1, #%n2"
614   [(set_attr "conds" "set")]
617 ;; Convert the sequence
618 ;;  sub  rd, rn, #1
619 ;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
620 ;;  bne  dest
621 ;; into
622 ;;  subs rd, rn, #1
623 ;;  bcs  dest   ((unsigned)rn >= 1)
624 ;; similarly for the beq variant using bcc.
625 ;; This is a common looping idiom (while (n--))
626 (define_peephole2
627   [(set (match_operand:SI 0 "arm_general_register_operand" "")
628         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
629                  (const_int -1)))
630    (set (match_operand 2 "cc_register" "")
631         (compare (match_dup 0) (const_int -1)))
632    (set (pc)
633         (if_then_else (match_operator 3 "equality_operator"
634                        [(match_dup 2) (const_int 0)])
635                       (match_operand 4 "" "")
636                       (match_operand 5 "" "")))]
637   "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
638   [(parallel[
639     (set (match_dup 2)
640          (compare:CC
641           (match_dup 1) (const_int 1)))
642     (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
643    (set (pc)
644         (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
645                       (match_dup 4)
646                       (match_dup 5)))]
647   "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
648    operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
649                                   ? GEU : LTU),
650                                  VOIDmode, 
651                                  operands[2], const0_rtx);"
654 ;; The next four insns work because they compare the result with one of
655 ;; the operands, and we know that the use of the condition code is
656 ;; either GEU or LTU, so we can use the carry flag from the addition
657 ;; instead of doing the compare a second time.
658 (define_insn "*addsi3_compare_op1"
659   [(set (reg:CC_C CC_REGNUM)
660         (compare:CC_C
661          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
662                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
663          (match_dup 1)))
664    (set (match_operand:SI 0 "s_register_operand" "=r,r")
665         (plus:SI (match_dup 1) (match_dup 2)))]
666   "TARGET_ARM"
667   "@
668    add%?s\\t%0, %1, %2
669    sub%?s\\t%0, %1, #%n2"
670   [(set_attr "conds" "set")]
673 (define_insn "*addsi3_compare_op2"
674   [(set (reg:CC_C CC_REGNUM)
675         (compare:CC_C
676          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
677                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
678          (match_dup 2)))
679    (set (match_operand:SI 0 "s_register_operand" "=r,r")
680         (plus:SI (match_dup 1) (match_dup 2)))]
681   "TARGET_ARM"
682   "@
683    add%?s\\t%0, %1, %2
684    sub%?s\\t%0, %1, #%n2"
685   [(set_attr "conds" "set")]
688 (define_insn "*compare_addsi2_op0"
689   [(set (reg:CC_C CC_REGNUM)
690         (compare:CC_C
691          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
692                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
693          (match_dup 0)))]
694   "TARGET_ARM"
695   "@
696    cmn%?\\t%0, %1
697    cmp%?\\t%0, #%n1"
698   [(set_attr "conds" "set")]
701 (define_insn "*compare_addsi2_op1"
702   [(set (reg:CC_C CC_REGNUM)
703         (compare:CC_C
704          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
705                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
706          (match_dup 1)))]
707   "TARGET_ARM"
708   "@
709    cmn%?\\t%0, %1
710    cmp%?\\t%0, #%n1"
711   [(set_attr "conds" "set")]
714 (define_insn "*addsi3_carryin"
715   [(set (match_operand:SI 0 "s_register_operand" "=r")
716         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
717                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
718                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
719   "TARGET_ARM"
720   "adc%?\\t%0, %1, %2"
721   [(set_attr "conds" "use")]
724 (define_insn "*addsi3_carryin_shift"
725   [(set (match_operand:SI 0 "s_register_operand" "=r")
726         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
727                  (plus:SI
728                    (match_operator:SI 2 "shift_operator"
729                       [(match_operand:SI 3 "s_register_operand" "r")
730                        (match_operand:SI 4 "reg_or_int_operand" "rM")])
731                     (match_operand:SI 1 "s_register_operand" "r"))))]
732   "TARGET_ARM"
733   "adc%?\\t%0, %1, %3%S2"
734   [(set_attr "conds" "use")
735    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
736                       (const_string "alu_shift")
737                       (const_string "alu_shift_reg")))]
740 (define_insn "*addsi3_carryin_alt1"
741   [(set (match_operand:SI 0 "s_register_operand" "=r")
742         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
743                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
744                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
745   "TARGET_ARM"
746   "adc%?\\t%0, %1, %2"
747   [(set_attr "conds" "use")]
750 (define_insn "*addsi3_carryin_alt2"
751   [(set (match_operand:SI 0 "s_register_operand" "=r")
752         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
753                           (match_operand:SI 1 "s_register_operand" "r"))
754                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
755   "TARGET_ARM"
756   "adc%?\\t%0, %1, %2"
757   [(set_attr "conds" "use")]
760 (define_insn "*addsi3_carryin_alt3"
761   [(set (match_operand:SI 0 "s_register_operand" "=r")
762         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
763                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
764                  (match_operand:SI 1 "s_register_operand" "r")))]
765   "TARGET_ARM"
766   "adc%?\\t%0, %1, %2"
767   [(set_attr "conds" "use")]
770 (define_insn "incscc"
771   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
772         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
773                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
774                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
775   "TARGET_ARM"
776   "@
777   add%d2\\t%0, %1, #1
778   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
779   [(set_attr "conds" "use")
780    (set_attr "length" "4,8")]
783 ; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
784 (define_split
785   [(set (match_operand:SI 0 "s_register_operand" "")
786         (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
787                             (match_operand:SI 2 "s_register_operand" ""))
788                  (const_int -1)))
789    (clobber (match_operand:SI 3 "s_register_operand" ""))]
790   "TARGET_ARM"
791   [(set (match_dup 3) (match_dup 1))
792    (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
793   "
794   operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
797 (define_expand "addsf3"
798   [(set (match_operand:SF          0 "s_register_operand" "")
799         (plus:SF (match_operand:SF 1 "s_register_operand" "")
800                  (match_operand:SF 2 "arm_float_add_operand" "")))]
801   "TARGET_ARM && TARGET_HARD_FLOAT"
802   "
803   if (TARGET_MAVERICK
804       && !cirrus_fp_register (operands[2], SFmode))
805     operands[2] = force_reg (SFmode, operands[2]);
808 (define_expand "adddf3"
809   [(set (match_operand:DF          0 "s_register_operand" "")
810         (plus:DF (match_operand:DF 1 "s_register_operand" "")
811                  (match_operand:DF 2 "arm_float_add_operand" "")))]
812   "TARGET_ARM && TARGET_HARD_FLOAT"
813   "
814   if (TARGET_MAVERICK
815       && !cirrus_fp_register (operands[2], DFmode))
816     operands[2] = force_reg (DFmode, operands[2]);
819 (define_expand "subdi3"
820  [(parallel
821    [(set (match_operand:DI            0 "s_register_operand" "")
822           (minus:DI (match_operand:DI 1 "s_register_operand" "")
823                     (match_operand:DI 2 "s_register_operand" "")))
824     (clobber (reg:CC CC_REGNUM))])]
825   "TARGET_EITHER"
826   "
827   if (TARGET_HARD_FLOAT && TARGET_MAVERICK
828       && TARGET_ARM
829       && cirrus_fp_register (operands[0], DImode)
830       && cirrus_fp_register (operands[1], DImode))
831     {
832       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
833       DONE;
834     }
836   if (TARGET_THUMB)
837     {
838       if (GET_CODE (operands[1]) != REG)
839         operands[1] = force_reg (SImode, operands[1]);
840       if (GET_CODE (operands[2]) != REG)
841         operands[2] = force_reg (SImode, operands[2]);
842      }  
843   "
846 (define_insn "*arm_subdi3"
847   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
848         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
849                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
850    (clobber (reg:CC CC_REGNUM))]
851   "TARGET_ARM"
852   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
853   [(set_attr "conds" "clob")
854    (set_attr "length" "8")]
857 (define_insn "*thumb_subdi3"
858   [(set (match_operand:DI           0 "register_operand" "=l")
859         (minus:DI (match_operand:DI 1 "register_operand"  "0")
860                   (match_operand:DI 2 "register_operand"  "l")))
861    (clobber (reg:CC CC_REGNUM))]
862   "TARGET_THUMB"
863   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
864   [(set_attr "length" "4")]
867 (define_insn "*subdi_di_zesidi"
868   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
869         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
870                   (zero_extend:DI
871                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
872    (clobber (reg:CC CC_REGNUM))]
873   "TARGET_ARM"
874   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
875   [(set_attr "conds" "clob")
876    (set_attr "length" "8")]
879 (define_insn "*subdi_di_sesidi"
880   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
881         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
882                   (sign_extend:DI
883                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
884    (clobber (reg:CC CC_REGNUM))]
885   "TARGET_ARM"
886   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
887   [(set_attr "conds" "clob")
888    (set_attr "length" "8")]
891 (define_insn "*subdi_zesidi_di"
892   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
893         (minus:DI (zero_extend:DI
894                    (match_operand:SI 2 "s_register_operand"  "r,r"))
895                   (match_operand:DI  1 "s_register_operand" "?r,0")))
896    (clobber (reg:CC CC_REGNUM))]
897   "TARGET_ARM"
898   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
899   [(set_attr "conds" "clob")
900    (set_attr "length" "8")]
903 (define_insn "*subdi_sesidi_di"
904   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
905         (minus:DI (sign_extend:DI
906                    (match_operand:SI 2 "s_register_operand"   "r,r"))
907                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
908    (clobber (reg:CC CC_REGNUM))]
909   "TARGET_ARM"
910   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
911   [(set_attr "conds" "clob")
912    (set_attr "length" "8")]
915 (define_insn "*subdi_zesidi_zesidi"
916   [(set (match_operand:DI            0 "s_register_operand" "=r")
917         (minus:DI (zero_extend:DI
918                    (match_operand:SI 1 "s_register_operand"  "r"))
919                   (zero_extend:DI
920                    (match_operand:SI 2 "s_register_operand"  "r"))))
921    (clobber (reg:CC CC_REGNUM))]
922   "TARGET_ARM"
923   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
924   [(set_attr "conds" "clob")
925    (set_attr "length" "8")]
928 (define_expand "subsi3"
929   [(set (match_operand:SI           0 "s_register_operand" "")
930         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
931                   (match_operand:SI 2 "s_register_operand" "")))]
932   "TARGET_EITHER"
933   "
934   if (GET_CODE (operands[1]) == CONST_INT)
935     {
936       if (TARGET_ARM)
937         {
938           arm_split_constant (MINUS, SImode, NULL_RTX,
939                               INTVAL (operands[1]), operands[0],
940                               operands[2], optimize && !no_new_pseudos);
941           DONE;
942         }
943       else /* TARGET_THUMB */
944         operands[1] = force_reg (SImode, operands[1]);
945     }
946   "
949 (define_insn "*thumb_subsi3_insn"
950   [(set (match_operand:SI           0 "register_operand" "=l")
951         (minus:SI (match_operand:SI 1 "register_operand" "l")
952                   (match_operand:SI 2 "register_operand" "l")))]
953   "TARGET_THUMB"
954   "sub\\t%0, %1, %2"
955   [(set_attr "length" "2")]
958 (define_insn_and_split "*arm_subsi3_insn"
959   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
960         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
961                   (match_operand:SI 2 "s_register_operand" "r,r")))]
962   "TARGET_ARM"
963   "@
964    rsb%?\\t%0, %2, %1
965    #"
966   "TARGET_ARM
967    && GET_CODE (operands[1]) == CONST_INT
968    && !const_ok_for_arm (INTVAL (operands[1]))"
969   [(clobber (const_int 0))]
970   "
971   arm_split_constant (MINUS, SImode, curr_insn,
972                       INTVAL (operands[1]), operands[0], operands[2], 0);
973   DONE;
974   "
975   [(set_attr "length" "4,16")
976    (set_attr "predicable" "yes")]
979 (define_peephole2
980   [(match_scratch:SI 3 "r")
981    (set (match_operand:SI 0 "arm_general_register_operand" "")
982         (minus:SI (match_operand:SI 1 "const_int_operand" "")
983                   (match_operand:SI 2 "arm_general_register_operand" "")))]
984   "TARGET_ARM
985    && !const_ok_for_arm (INTVAL (operands[1]))
986    && const_ok_for_arm (~INTVAL (operands[1]))"
987   [(set (match_dup 3) (match_dup 1))
988    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
989   ""
992 (define_insn "*subsi3_compare0"
993   [(set (reg:CC_NOOV CC_REGNUM)
994         (compare:CC_NOOV
995          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
996                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
997          (const_int 0)))
998    (set (match_operand:SI 0 "s_register_operand" "=r,r")
999         (minus:SI (match_dup 1) (match_dup 2)))]
1000   "TARGET_ARM"
1001   "@
1002    sub%?s\\t%0, %1, %2
1003    rsb%?s\\t%0, %2, %1"
1004   [(set_attr "conds" "set")]
1007 (define_insn "decscc"
1008   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1009         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1010                   (match_operator:SI 2 "arm_comparison_operator"
1011                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1012   "TARGET_ARM"
1013   "@
1014    sub%d2\\t%0, %1, #1
1015    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1016   [(set_attr "conds" "use")
1017    (set_attr "length" "*,8")]
1020 (define_expand "subsf3"
1021   [(set (match_operand:SF           0 "s_register_operand" "")
1022         (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1023                   (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1024   "TARGET_ARM && TARGET_HARD_FLOAT"
1025   "
1026   if (TARGET_MAVERICK)
1027     {
1028       if (!cirrus_fp_register (operands[1], SFmode))
1029         operands[1] = force_reg (SFmode, operands[1]);
1030       if (!cirrus_fp_register (operands[2], SFmode))
1031         operands[2] = force_reg (SFmode, operands[2]);
1032     }
1035 (define_expand "subdf3"
1036   [(set (match_operand:DF           0 "s_register_operand" "")
1037         (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1038                   (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1039   "TARGET_ARM && TARGET_HARD_FLOAT"
1040   "
1041   if (TARGET_MAVERICK)
1042     {
1043        if (!cirrus_fp_register (operands[1], DFmode))
1044          operands[1] = force_reg (DFmode, operands[1]);
1045        if (!cirrus_fp_register (operands[2], DFmode))
1046          operands[2] = force_reg (DFmode, operands[2]);
1047     }
1051 ;; Multiplication insns
1053 (define_expand "mulsi3"
1054   [(set (match_operand:SI          0 "s_register_operand" "")
1055         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1056                  (match_operand:SI 1 "s_register_operand" "")))]
1057   "TARGET_EITHER"
1058   ""
1061 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1062 (define_insn "*arm_mulsi3"
1063   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1064         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1065                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1066   "TARGET_ARM"
1067   "mul%?\\t%0, %2, %1"
1068   [(set_attr "insn" "mul")
1069    (set_attr "predicable" "yes")]
1072 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1073 ; 1 and 2; are the same, because reload will make operand 0 match 
1074 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1075 ; this by adding another alternative to match this case, and then `reload' 
1076 ; it ourselves.  This alternative must come first.
1077 (define_insn "*thumb_mulsi3"
1078   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1079         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1080                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1081   "TARGET_THUMB"
1082   "*
1083   if (which_alternative < 2)
1084     return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1085   else
1086     return \"mul\\t%0, %0, %2\";
1087   "
1088   [(set_attr "length" "4,4,2")
1089    (set_attr "insn" "mul")]
1092 (define_insn "*mulsi3_compare0"
1093   [(set (reg:CC_NOOV CC_REGNUM)
1094         (compare:CC_NOOV (mult:SI
1095                           (match_operand:SI 2 "s_register_operand" "r,r")
1096                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1097                          (const_int 0)))
1098    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1099         (mult:SI (match_dup 2) (match_dup 1)))]
1100   "TARGET_ARM && !arm_arch_xscale"
1101   "mul%?s\\t%0, %2, %1"
1102   [(set_attr "conds" "set")
1103    (set_attr "insn" "muls")]
1106 (define_insn "*mulsi_compare0_scratch"
1107   [(set (reg:CC_NOOV CC_REGNUM)
1108         (compare:CC_NOOV (mult:SI
1109                           (match_operand:SI 2 "s_register_operand" "r,r")
1110                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1111                          (const_int 0)))
1112    (clobber (match_scratch:SI 0 "=&r,&r"))]
1113   "TARGET_ARM && !arm_arch_xscale"
1114   "mul%?s\\t%0, %2, %1"
1115   [(set_attr "conds" "set")
1116    (set_attr "insn" "muls")]
1119 ;; Unnamed templates to match MLA instruction.
1121 (define_insn "*mulsi3addsi"
1122   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1123         (plus:SI
1124           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1125                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1126           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1127   "TARGET_ARM"
1128   "mla%?\\t%0, %2, %1, %3"
1129   [(set_attr "insn" "mla")
1130    (set_attr "predicable" "yes")]
1133 (define_insn "*mulsi3addsi_compare0"
1134   [(set (reg:CC_NOOV CC_REGNUM)
1135         (compare:CC_NOOV
1136          (plus:SI (mult:SI
1137                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1138                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1139                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1140          (const_int 0)))
1141    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1142         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1143                  (match_dup 3)))]
1144   "TARGET_ARM && !arm_arch_xscale"
1145   "mla%?s\\t%0, %2, %1, %3"
1146   [(set_attr "conds" "set")
1147    (set_attr "insn" "mlas")]
1150 (define_insn "*mulsi3addsi_compare0_scratch"
1151   [(set (reg:CC_NOOV CC_REGNUM)
1152         (compare:CC_NOOV
1153          (plus:SI (mult:SI
1154                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1155                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1156                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1157          (const_int 0)))
1158    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1159   "TARGET_ARM && !arm_arch_xscale"
1160   "mla%?s\\t%0, %2, %1, %3"
1161   [(set_attr "conds" "set")
1162    (set_attr "insn" "mlas")]
1165 ;; Unnamed template to match long long multiply-accumulate (smlal)
1167 (define_insn "*mulsidi3adddi"
1168   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1169         (plus:DI
1170          (mult:DI
1171           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1172           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1173          (match_operand:DI 1 "s_register_operand" "0")))]
1174   "TARGET_ARM && arm_arch3m"
1175   "smlal%?\\t%Q0, %R0, %3, %2"
1176   [(set_attr "insn" "smlal")
1177    (set_attr "predicable" "yes")]
1180 (define_insn "mulsidi3"
1181   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1182         (mult:DI
1183          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1184          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1185   "TARGET_ARM && arm_arch3m"
1186   "smull%?\\t%Q0, %R0, %1, %2"
1187   [(set_attr "insn" "smull")
1188    (set_attr "predicable" "yes")]
1191 (define_insn "umulsidi3"
1192   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1193         (mult:DI
1194          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1195          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1196   "TARGET_ARM && arm_arch3m"
1197   "umull%?\\t%Q0, %R0, %1, %2"
1198   [(set_attr "insn" "umull")
1199    (set_attr "predicable" "yes")]
1202 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1204 (define_insn "*umulsidi3adddi"
1205   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1206         (plus:DI
1207          (mult:DI
1208           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1209           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1210          (match_operand:DI 1 "s_register_operand" "0")))]
1211   "TARGET_ARM && arm_arch3m"
1212   "umlal%?\\t%Q0, %R0, %3, %2"
1213   [(set_attr "insn" "umlal")
1214    (set_attr "predicable" "yes")]
1217 (define_insn "smulsi3_highpart"
1218   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1219         (truncate:SI
1220          (lshiftrt:DI
1221           (mult:DI
1222            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1223            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1224           (const_int 32))))
1225    (clobber (match_scratch:SI 3 "=&r,&r"))]
1226   "TARGET_ARM && arm_arch3m"
1227   "smull%?\\t%3, %0, %2, %1"
1228   [(set_attr "insn" "smull")
1229    (set_attr "predicable" "yes")]
1232 (define_insn "umulsi3_highpart"
1233   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1234         (truncate:SI
1235          (lshiftrt:DI
1236           (mult:DI
1237            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1238            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1239           (const_int 32))))
1240    (clobber (match_scratch:SI 3 "=&r,&r"))]
1241   "TARGET_ARM && arm_arch3m"
1242   "umull%?\\t%3, %0, %2, %1"
1243   [(set_attr "insn" "umull")
1244    (set_attr "predicable" "yes")]
1247 (define_insn "mulhisi3"
1248   [(set (match_operand:SI 0 "s_register_operand" "=r")
1249         (mult:SI (sign_extend:SI
1250                   (match_operand:HI 1 "s_register_operand" "%r"))
1251                  (sign_extend:SI
1252                   (match_operand:HI 2 "s_register_operand" "r"))))]
1253   "TARGET_ARM && arm_arch5e"
1254   "smulbb%?\\t%0, %1, %2"
1255   [(set_attr "insn" "smulxy")
1256    (set_attr "predicable" "yes")]
1259 (define_insn "*mulhisi3tb"
1260   [(set (match_operand:SI 0 "s_register_operand" "=r")
1261         (mult:SI (ashiftrt:SI
1262                   (match_operand:SI 1 "s_register_operand" "r")
1263                   (const_int 16))
1264                  (sign_extend:SI
1265                   (match_operand:HI 2 "s_register_operand" "r"))))]
1266   "TARGET_ARM && arm_arch5e"
1267   "smultb%?\\t%0, %1, %2"
1268   [(set_attr "insn" "smulxy")
1269    (set_attr "predicable" "yes")]
1272 (define_insn "*mulhisi3bt"
1273   [(set (match_operand:SI 0 "s_register_operand" "=r")
1274         (mult:SI (sign_extend:SI
1275                   (match_operand:HI 1 "s_register_operand" "r"))
1276                  (ashiftrt:SI
1277                   (match_operand:SI 2 "s_register_operand" "r")
1278                   (const_int 16))))]
1279   "TARGET_ARM && arm_arch5e"
1280   "smulbt%?\\t%0, %1, %2"
1281   [(set_attr "insn" "smulxy")
1282    (set_attr "predicable" "yes")]
1285 (define_insn "*mulhisi3tt"
1286   [(set (match_operand:SI 0 "s_register_operand" "=r")
1287         (mult:SI (ashiftrt:SI
1288                   (match_operand:SI 1 "s_register_operand" "r")
1289                   (const_int 16))
1290                  (ashiftrt:SI
1291                   (match_operand:SI 2 "s_register_operand" "r")
1292                   (const_int 16))))]
1293   "TARGET_ARM && arm_arch5e"
1294   "smultt%?\\t%0, %1, %2"
1295   [(set_attr "insn" "smulxy")
1296    (set_attr "predicable" "yes")]
1299 (define_insn "*mulhisi3addsi"
1300   [(set (match_operand:SI 0 "s_register_operand" "=r")
1301         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1302                  (mult:SI (sign_extend:SI
1303                            (match_operand:HI 2 "s_register_operand" "%r"))
1304                           (sign_extend:SI
1305                            (match_operand:HI 3 "s_register_operand" "r")))))]
1306   "TARGET_ARM && arm_arch5e"
1307   "smlabb%?\\t%0, %2, %3, %1"
1308   [(set_attr "insn" "smlaxy")
1309    (set_attr "predicable" "yes")]
1312 (define_insn "*mulhidi3adddi"
1313   [(set (match_operand:DI 0 "s_register_operand" "=r")
1314         (plus:DI
1315           (match_operand:DI 1 "s_register_operand" "0")
1316           (mult:DI (sign_extend:DI
1317                     (match_operand:HI 2 "s_register_operand" "%r"))
1318                    (sign_extend:DI
1319                     (match_operand:HI 3 "s_register_operand" "r")))))]
1320   "TARGET_ARM && arm_arch5e"
1321   "smlalbb%?\\t%Q0, %R0, %2, %3"
1322   [(set_attr "insn" "smlalxy")
1323    (set_attr "predicable" "yes")])
1325 (define_expand "mulsf3"
1326   [(set (match_operand:SF          0 "s_register_operand" "")
1327         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1328                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1329   "TARGET_ARM && TARGET_HARD_FLOAT"
1330   "
1331   if (TARGET_MAVERICK
1332       && !cirrus_fp_register (operands[2], SFmode))
1333     operands[2] = force_reg (SFmode, operands[2]);
1336 (define_expand "muldf3"
1337   [(set (match_operand:DF          0 "s_register_operand" "")
1338         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1339                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1340   "TARGET_ARM && TARGET_HARD_FLOAT"
1341   "
1342   if (TARGET_MAVERICK
1343       && !cirrus_fp_register (operands[2], DFmode))
1344     operands[2] = force_reg (DFmode, operands[2]);
1347 ;; Division insns
1349 (define_expand "divsf3"
1350   [(set (match_operand:SF 0 "s_register_operand" "")
1351         (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1352                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1353   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1354   "")
1356 (define_expand "divdf3"
1357   [(set (match_operand:DF 0 "s_register_operand" "")
1358         (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1359                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1360   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1361   "")
1363 ;; Modulo insns
1365 (define_expand "modsf3"
1366   [(set (match_operand:SF 0 "s_register_operand" "")
1367         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1368                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1369   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1370   "")
1372 (define_expand "moddf3"
1373   [(set (match_operand:DF 0 "s_register_operand" "")
1374         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1375                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1376   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1377   "")
1379 ;; Boolean and,ior,xor insns
1381 ;; Split up double word logical operations
1383 ;; Split up simple DImode logical operations.  Simply perform the logical
1384 ;; operation on the upper and lower halves of the registers.
1385 (define_split
1386   [(set (match_operand:DI 0 "s_register_operand" "")
1387         (match_operator:DI 6 "logical_binary_operator"
1388           [(match_operand:DI 1 "s_register_operand" "")
1389            (match_operand:DI 2 "s_register_operand" "")]))]
1390   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1391   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1392    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1393   "
1394   {
1395     operands[3] = gen_highpart (SImode, operands[0]);
1396     operands[0] = gen_lowpart (SImode, operands[0]);
1397     operands[4] = gen_highpart (SImode, operands[1]);
1398     operands[1] = gen_lowpart (SImode, operands[1]);
1399     operands[5] = gen_highpart (SImode, operands[2]);
1400     operands[2] = gen_lowpart (SImode, operands[2]);
1401   }"
1404 (define_split
1405   [(set (match_operand:DI 0 "s_register_operand" "")
1406         (match_operator:DI 6 "logical_binary_operator"
1407           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1408            (match_operand:DI 1 "s_register_operand" "")]))]
1409   "TARGET_ARM && reload_completed"
1410   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1411    (set (match_dup 3) (match_op_dup:SI 6
1412                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1413                          (match_dup 4)]))]
1414   "
1415   {
1416     operands[3] = gen_highpart (SImode, operands[0]);
1417     operands[0] = gen_lowpart (SImode, operands[0]);
1418     operands[4] = gen_highpart (SImode, operands[1]);
1419     operands[1] = gen_lowpart (SImode, operands[1]);
1420     operands[5] = gen_highpart (SImode, operands[2]);
1421     operands[2] = gen_lowpart (SImode, operands[2]);
1422   }"
1425 ;; The zero extend of operand 2 means we can just copy the high part of
1426 ;; operand1 into operand0.
1427 (define_split
1428   [(set (match_operand:DI 0 "s_register_operand" "")
1429         (ior:DI
1430           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1431           (match_operand:DI 1 "s_register_operand" "")))]
1432   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1433   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1434    (set (match_dup 3) (match_dup 4))]
1435   "
1436   {
1437     operands[4] = gen_highpart (SImode, operands[1]);
1438     operands[3] = gen_highpart (SImode, operands[0]);
1439     operands[0] = gen_lowpart (SImode, operands[0]);
1440     operands[1] = gen_lowpart (SImode, operands[1]);
1441   }"
1444 ;; The zero extend of operand 2 means we can just copy the high part of
1445 ;; operand1 into operand0.
1446 (define_split
1447   [(set (match_operand:DI 0 "s_register_operand" "")
1448         (xor:DI
1449           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1450           (match_operand:DI 1 "s_register_operand" "")))]
1451   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1452   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1453    (set (match_dup 3) (match_dup 4))]
1454   "
1455   {
1456     operands[4] = gen_highpart (SImode, operands[1]);
1457     operands[3] = gen_highpart (SImode, operands[0]);
1458     operands[0] = gen_lowpart (SImode, operands[0]);
1459     operands[1] = gen_lowpart (SImode, operands[1]);
1460   }"
1463 (define_insn "anddi3"
1464   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1465         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1466                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1467   "TARGET_ARM && ! TARGET_IWMMXT"
1468   "#"
1469   [(set_attr "length" "8")]
1472 (define_insn_and_split "*anddi_zesidi_di"
1473   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1474         (and:DI (zero_extend:DI
1475                  (match_operand:SI 2 "s_register_operand" "r,r"))
1476                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1477   "TARGET_ARM"
1478   "#"
1479   "TARGET_ARM && reload_completed"
1480   ; The zero extend of operand 2 clears the high word of the output
1481   ; operand.
1482   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1483    (set (match_dup 3) (const_int 0))]
1484   "
1485   {
1486     operands[3] = gen_highpart (SImode, operands[0]);
1487     operands[0] = gen_lowpart (SImode, operands[0]);
1488     operands[1] = gen_lowpart (SImode, operands[1]);
1489   }"
1490   [(set_attr "length" "8")]
1493 (define_insn "*anddi_sesdi_di"
1494   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1495         (and:DI (sign_extend:DI
1496                  (match_operand:SI 2 "s_register_operand" "r,r"))
1497                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1498   "TARGET_ARM"
1499   "#"
1500   [(set_attr "length" "8")]
1503 (define_expand "andsi3"
1504   [(set (match_operand:SI         0 "s_register_operand" "")
1505         (and:SI (match_operand:SI 1 "s_register_operand" "")
1506                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1507   "TARGET_EITHER"
1508   "
1509   if (TARGET_ARM)
1510     {
1511       if (GET_CODE (operands[2]) == CONST_INT)
1512         {
1513           arm_split_constant (AND, SImode, NULL_RTX,
1514                               INTVAL (operands[2]), operands[0],
1515                               operands[1], optimize && !no_new_pseudos);
1517           DONE;
1518         }
1519     }
1520   else /* TARGET_THUMB */
1521     {
1522       if (GET_CODE (operands[2]) != CONST_INT)
1523         operands[2] = force_reg (SImode, operands[2]);
1524       else
1525         {
1526           int i;
1527           
1528           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1529             {
1530               operands[2] = force_reg (SImode,
1531                                        GEN_INT (~INTVAL (operands[2])));
1532               
1533               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1534               
1535               DONE;
1536             }
1538           for (i = 9; i <= 31; i++)
1539             {
1540               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1541                 {
1542                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1543                                         const0_rtx));
1544                   DONE;
1545                 }
1546               else if ((((HOST_WIDE_INT) 1) << i) - 1
1547                        == ~INTVAL (operands[2]))
1548                 {
1549                   rtx shift = GEN_INT (i);
1550                   rtx reg = gen_reg_rtx (SImode);
1551                 
1552                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1553                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1554                   
1555                   DONE;
1556                 }
1557             }
1559           operands[2] = force_reg (SImode, operands[2]);
1560         }
1561     }
1562   "
1565 (define_insn_and_split "*arm_andsi3_insn"
1566   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1567         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1568                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1569   "TARGET_ARM"
1570   "@
1571    and%?\\t%0, %1, %2
1572    bic%?\\t%0, %1, #%B2
1573    #"
1574   "TARGET_ARM
1575    && GET_CODE (operands[2]) == CONST_INT
1576    && !(const_ok_for_arm (INTVAL (operands[2]))
1577         || const_ok_for_arm (~INTVAL (operands[2])))"
1578   [(clobber (const_int 0))]
1579   "
1580   arm_split_constant  (AND, SImode, curr_insn, 
1581                        INTVAL (operands[2]), operands[0], operands[1], 0);
1582   DONE;
1583   "
1584   [(set_attr "length" "4,4,16")
1585    (set_attr "predicable" "yes")]
1588 (define_insn "*thumb_andsi3_insn"
1589   [(set (match_operand:SI         0 "register_operand" "=l")
1590         (and:SI (match_operand:SI 1 "register_operand" "%0")
1591                 (match_operand:SI 2 "register_operand" "l")))]
1592   "TARGET_THUMB"
1593   "and\\t%0, %0, %2"
1594   [(set_attr "length" "2")]
1597 (define_insn "*andsi3_compare0"
1598   [(set (reg:CC_NOOV CC_REGNUM)
1599         (compare:CC_NOOV
1600          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1601                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1602          (const_int 0)))
1603    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1604         (and:SI (match_dup 1) (match_dup 2)))]
1605   "TARGET_ARM"
1606   "@
1607    and%?s\\t%0, %1, %2
1608    bic%?s\\t%0, %1, #%B2"
1609   [(set_attr "conds" "set")]
1612 (define_insn "*andsi3_compare0_scratch"
1613   [(set (reg:CC_NOOV CC_REGNUM)
1614         (compare:CC_NOOV
1615          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1616                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1617          (const_int 0)))
1618    (clobber (match_scratch:SI 2 "=X,r"))]
1619   "TARGET_ARM"
1620   "@
1621    tst%?\\t%0, %1
1622    bic%?s\\t%2, %0, #%B1"
1623   [(set_attr "conds" "set")]
1626 (define_insn "*zeroextractsi_compare0_scratch"
1627   [(set (reg:CC_NOOV CC_REGNUM)
1628         (compare:CC_NOOV (zero_extract:SI
1629                           (match_operand:SI 0 "s_register_operand" "r")
1630                           (match_operand 1 "const_int_operand" "n")
1631                           (match_operand 2 "const_int_operand" "n"))
1632                          (const_int 0)))]
1633   "TARGET_ARM
1634   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1635       && INTVAL (operands[1]) > 0 
1636       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1637       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1638   "*
1639   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1640                          << INTVAL (operands[2]));
1641   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1642   return \"\";
1643   "
1644   [(set_attr "conds" "set")]
1647 (define_insn_and_split "*ne_zeroextractsi"
1648   [(set (match_operand:SI 0 "s_register_operand" "=r")
1649         (ne:SI (zero_extract:SI
1650                 (match_operand:SI 1 "s_register_operand" "r")
1651                 (match_operand:SI 2 "const_int_operand" "n")
1652                 (match_operand:SI 3 "const_int_operand" "n"))
1653                (const_int 0)))
1654    (clobber (reg:CC CC_REGNUM))]
1655   "TARGET_ARM
1656    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1657        && INTVAL (operands[2]) > 0 
1658        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1659        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1660   "#"
1661   "TARGET_ARM
1662    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1663        && INTVAL (operands[2]) > 0 
1664        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1665        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1666   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1667                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1668                                     (const_int 0)))
1669               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1670    (set (match_dup 0)
1671         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1672                          (match_dup 0) (const_int 1)))]
1673   "
1674   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1675                          << INTVAL (operands[3])); 
1676   "
1677   [(set_attr "conds" "clob")
1678    (set_attr "length" "8")]
1681 (define_insn_and_split "*ne_zeroextractsi_shifted"
1682   [(set (match_operand:SI 0 "s_register_operand" "=r")
1683         (ne:SI (zero_extract:SI
1684                 (match_operand:SI 1 "s_register_operand" "r")
1685                 (match_operand:SI 2 "const_int_operand" "n")
1686                 (const_int 0))
1687                (const_int 0)))
1688    (clobber (reg:CC CC_REGNUM))]
1689   "TARGET_ARM"
1690   "#"
1691   "TARGET_ARM"
1692   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1693                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1694                                     (const_int 0)))
1695               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1696    (set (match_dup 0)
1697         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1698                          (match_dup 0) (const_int 1)))]
1699   "
1700   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1701   "
1702   [(set_attr "conds" "clob")
1703    (set_attr "length" "8")]
1706 (define_insn_and_split "*ite_ne_zeroextractsi"
1707   [(set (match_operand:SI 0 "s_register_operand" "=r")
1708         (if_then_else:SI (ne (zero_extract:SI
1709                               (match_operand:SI 1 "s_register_operand" "r")
1710                               (match_operand:SI 2 "const_int_operand" "n")
1711                               (match_operand:SI 3 "const_int_operand" "n"))
1712                              (const_int 0))
1713                          (match_operand:SI 4 "arm_not_operand" "rIK")
1714                          (const_int 0)))
1715    (clobber (reg:CC CC_REGNUM))]
1716   "TARGET_ARM
1717    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1718        && INTVAL (operands[2]) > 0 
1719        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1720        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1721    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1722   "#"
1723   "TARGET_ARM
1724    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1725        && INTVAL (operands[2]) > 0 
1726        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1727        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1728    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1729   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1730                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1731                                     (const_int 0)))
1732               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1733    (set (match_dup 0)
1734         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1735                          (match_dup 0) (match_dup 4)))]
1736   "
1737   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1738                          << INTVAL (operands[3])); 
1739   "
1740   [(set_attr "conds" "clob")
1741    (set_attr "length" "8")]
1744 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1745   [(set (match_operand:SI 0 "s_register_operand" "=r")
1746         (if_then_else:SI (ne (zero_extract:SI
1747                               (match_operand:SI 1 "s_register_operand" "r")
1748                               (match_operand:SI 2 "const_int_operand" "n")
1749                               (const_int 0))
1750                              (const_int 0))
1751                          (match_operand:SI 3 "arm_not_operand" "rIK")
1752                          (const_int 0)))
1753    (clobber (reg:CC CC_REGNUM))]
1754   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1755   "#"
1756   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1757   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1758                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1759                                     (const_int 0)))
1760               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1761    (set (match_dup 0)
1762         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1763                          (match_dup 0) (match_dup 3)))]
1764   "
1765   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1766   "
1767   [(set_attr "conds" "clob")
1768    (set_attr "length" "8")]
1771 (define_split
1772   [(set (match_operand:SI 0 "s_register_operand" "")
1773         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1774                          (match_operand:SI 2 "const_int_operand" "")
1775                          (match_operand:SI 3 "const_int_operand" "")))
1776    (clobber (match_operand:SI 4 "s_register_operand" ""))]
1777   "TARGET_THUMB"
1778   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1779    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1780   "{
1781      HOST_WIDE_INT temp = INTVAL (operands[2]);
1783      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1784      operands[3] = GEN_INT (32 - temp);
1785    }"
1788 (define_split
1789   [(set (match_operand:SI 0 "s_register_operand" "")
1790         (match_operator:SI 1 "shiftable_operator"
1791          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1792                            (match_operand:SI 3 "const_int_operand" "")
1793                            (match_operand:SI 4 "const_int_operand" ""))
1794           (match_operand:SI 5 "s_register_operand" "")]))
1795    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1796   "TARGET_ARM"
1797   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1798    (set (match_dup 0)
1799         (match_op_dup 1
1800          [(lshiftrt:SI (match_dup 6) (match_dup 4))
1801           (match_dup 5)]))]
1802   "{
1803      HOST_WIDE_INT temp = INTVAL (operands[3]);
1805      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1806      operands[4] = GEN_INT (32 - temp);
1807    }"
1809   
1810 (define_split
1811   [(set (match_operand:SI 0 "s_register_operand" "")
1812         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1813                          (match_operand:SI 2 "const_int_operand" "")
1814                          (match_operand:SI 3 "const_int_operand" "")))]
1815   "TARGET_THUMB"
1816   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1817    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1818   "{
1819      HOST_WIDE_INT temp = INTVAL (operands[2]);
1821      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1822      operands[3] = GEN_INT (32 - temp);
1823    }"
1826 (define_split
1827   [(set (match_operand:SI 0 "s_register_operand" "")
1828         (match_operator:SI 1 "shiftable_operator"
1829          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1830                            (match_operand:SI 3 "const_int_operand" "")
1831                            (match_operand:SI 4 "const_int_operand" ""))
1832           (match_operand:SI 5 "s_register_operand" "")]))
1833    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1834   "TARGET_ARM"
1835   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1836    (set (match_dup 0)
1837         (match_op_dup 1
1838          [(ashiftrt:SI (match_dup 6) (match_dup 4))
1839           (match_dup 5)]))]
1840   "{
1841      HOST_WIDE_INT temp = INTVAL (operands[3]);
1843      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1844      operands[4] = GEN_INT (32 - temp);
1845    }"
1847   
1848 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1849 ;;; represented by the bitfield, then this will produce incorrect results.
1850 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1851 ;;; which have a real bit-field insert instruction, the truncation happens
1852 ;;; in the bit-field insert instruction itself.  Since arm does not have a
1853 ;;; bit-field insert instruction, we would have to emit code here to truncate
1854 ;;; the value before we insert.  This loses some of the advantage of having
1855 ;;; this insv pattern, so this pattern needs to be reevalutated.
1857 (define_expand "insv"
1858   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1859                          (match_operand:SI 1 "general_operand" "")
1860                          (match_operand:SI 2 "general_operand" ""))
1861         (match_operand:SI 3 "reg_or_int_operand" ""))]
1862   "TARGET_ARM"
1863   "
1864   {
1865     int start_bit = INTVAL (operands[2]);
1866     int width = INTVAL (operands[1]);
1867     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1868     rtx target, subtarget;
1870     target = operands[0];
1871     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1872        subreg as the final target.  */
1873     if (GET_CODE (target) == SUBREG)
1874       {
1875         subtarget = gen_reg_rtx (SImode);
1876         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1877             < GET_MODE_SIZE (SImode))
1878           target = SUBREG_REG (target);
1879       }
1880     else
1881       subtarget = target;    
1883     if (GET_CODE (operands[3]) == CONST_INT)
1884       {
1885         /* Since we are inserting a known constant, we may be able to
1886            reduce the number of bits that we have to clear so that
1887            the mask becomes simple.  */
1888         /* ??? This code does not check to see if the new mask is actually
1889            simpler.  It may not be.  */
1890         rtx op1 = gen_reg_rtx (SImode);
1891         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1892            start of this pattern.  */
1893         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1894         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1896         emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1897         emit_insn (gen_iorsi3 (subtarget, op1,
1898                                GEN_INT (op3_value << start_bit)));
1899       }
1900     else if (start_bit == 0
1901              && !(const_ok_for_arm (mask)
1902                   || const_ok_for_arm (~mask)))
1903       {
1904         /* A Trick, since we are setting the bottom bits in the word,
1905            we can shift operand[3] up, operand[0] down, OR them together
1906            and rotate the result back again.  This takes 3 insns, and
1907            the third might be mergeable into another op.  */
1908         /* The shift up copes with the possibility that operand[3] is
1909            wider than the bitfield.  */
1910         rtx op0 = gen_reg_rtx (SImode);
1911         rtx op1 = gen_reg_rtx (SImode);
1913         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1914         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1915         emit_insn (gen_iorsi3  (op1, op1, op0));
1916         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1917       }
1918     else if ((width + start_bit == 32)
1919              && !(const_ok_for_arm (mask)
1920                   || const_ok_for_arm (~mask)))
1921       {
1922         /* Similar trick, but slightly less efficient.  */
1924         rtx op0 = gen_reg_rtx (SImode);
1925         rtx op1 = gen_reg_rtx (SImode);
1927         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1928         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1929         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1930         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1931       }
1932     else
1933       {
1934         rtx op0 = GEN_INT (mask);
1935         rtx op1 = gen_reg_rtx (SImode);
1936         rtx op2 = gen_reg_rtx (SImode);
1938         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1939           {
1940             rtx tmp = gen_reg_rtx (SImode);
1942             emit_insn (gen_movsi (tmp, op0));
1943             op0 = tmp;
1944           }
1946         /* Mask out any bits in operand[3] that are not needed.  */
1947            emit_insn (gen_andsi3 (op1, operands[3], op0));
1949         if (GET_CODE (op0) == CONST_INT
1950             && (const_ok_for_arm (mask << start_bit)
1951                 || const_ok_for_arm (~(mask << start_bit))))
1952           {
1953             op0 = GEN_INT (~(mask << start_bit));
1954             emit_insn (gen_andsi3 (op2, operands[0], op0));
1955           }
1956         else
1957           {
1958             if (GET_CODE (op0) == CONST_INT)
1959               {
1960                 rtx tmp = gen_reg_rtx (SImode);
1962                 emit_insn (gen_movsi (tmp, op0));
1963                 op0 = tmp;
1964               }
1966             if (start_bit != 0)
1967               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1968             
1969             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1970           }
1972         if (start_bit != 0)
1973           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1975         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1976       }
1978     if (subtarget != target)
1979       {
1980         /* If TARGET is still a SUBREG, then it must be wider than a word,
1981            so we must be careful only to set the subword we were asked to.  */
1982         if (GET_CODE (target) == SUBREG)
1983           emit_move_insn (target, subtarget);
1984         else
1985           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1986       }
1988     DONE;
1989   }"
1992 ; constants for op 2 will never be given to these patterns.
1993 (define_insn_and_split "*anddi_notdi_di"
1994   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1995         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1996                 (match_operand:DI 2 "s_register_operand" "0,r")))]
1997   "TARGET_ARM"
1998   "#"
1999   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2000   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2001    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2002   "
2003   {
2004     operands[3] = gen_highpart (SImode, operands[0]);
2005     operands[0] = gen_lowpart (SImode, operands[0]);
2006     operands[4] = gen_highpart (SImode, operands[1]);
2007     operands[1] = gen_lowpart (SImode, operands[1]);
2008     operands[5] = gen_highpart (SImode, operands[2]);
2009     operands[2] = gen_lowpart (SImode, operands[2]);
2010   }"
2011   [(set_attr "length" "8")
2012    (set_attr "predicable" "yes")]
2014   
2015 (define_insn_and_split "*anddi_notzesidi_di"
2016   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2017         (and:DI (not:DI (zero_extend:DI
2018                          (match_operand:SI 2 "s_register_operand" "r,r")))
2019                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2020   "TARGET_ARM"
2021   "@
2022    bic%?\\t%Q0, %Q1, %2
2023    #"
2024   ; (not (zero_extend ...)) allows us to just copy the high word from
2025   ; operand1 to operand0.
2026   "TARGET_ARM
2027    && reload_completed
2028    && operands[0] != operands[1]"
2029   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2030    (set (match_dup 3) (match_dup 4))]
2031   "
2032   {
2033     operands[3] = gen_highpart (SImode, operands[0]);
2034     operands[0] = gen_lowpart (SImode, operands[0]);
2035     operands[4] = gen_highpart (SImode, operands[1]);
2036     operands[1] = gen_lowpart (SImode, operands[1]);
2037   }"
2038   [(set_attr "length" "4,8")
2039    (set_attr "predicable" "yes")]
2041   
2042 (define_insn_and_split "*anddi_notsesidi_di"
2043   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2044         (and:DI (not:DI (sign_extend:DI
2045                          (match_operand:SI 2 "s_register_operand" "r,r")))
2046                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2047   "TARGET_ARM"
2048   "#"
2049   "TARGET_ARM && reload_completed"
2050   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2051    (set (match_dup 3) (and:SI (not:SI
2052                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2053                                (match_dup 4)))]
2054   "
2055   {
2056     operands[3] = gen_highpart (SImode, operands[0]);
2057     operands[0] = gen_lowpart (SImode, operands[0]);
2058     operands[4] = gen_highpart (SImode, operands[1]);
2059     operands[1] = gen_lowpart (SImode, operands[1]);
2060   }"
2061   [(set_attr "length" "8")
2062    (set_attr "predicable" "yes")]
2064   
2065 (define_insn "andsi_notsi_si"
2066   [(set (match_operand:SI 0 "s_register_operand" "=r")
2067         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2068                 (match_operand:SI 1 "s_register_operand" "r")))]
2069   "TARGET_ARM"
2070   "bic%?\\t%0, %1, %2"
2071   [(set_attr "predicable" "yes")]
2074 (define_insn "bicsi3"
2075   [(set (match_operand:SI                 0 "register_operand" "=l")
2076         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2077                 (match_operand:SI         2 "register_operand" "0")))]
2078   "TARGET_THUMB"
2079   "bic\\t%0, %0, %1"
2080   [(set_attr "length" "2")]
2083 (define_insn "andsi_not_shiftsi_si"
2084   [(set (match_operand:SI 0 "s_register_operand" "=r")
2085         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2086                          [(match_operand:SI 2 "s_register_operand" "r")
2087                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2088                 (match_operand:SI 1 "s_register_operand" "r")))]
2089   "TARGET_ARM"
2090   "bic%?\\t%0, %1, %2%S4"
2091   [(set_attr "predicable" "yes")
2092    (set_attr "shift" "2")
2093    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2094                       (const_string "alu_shift")
2095                       (const_string "alu_shift_reg")))]
2098 (define_insn "*andsi_notsi_si_compare0"
2099   [(set (reg:CC_NOOV CC_REGNUM)
2100         (compare:CC_NOOV
2101          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2102                  (match_operand:SI 1 "s_register_operand" "r"))
2103          (const_int 0)))
2104    (set (match_operand:SI 0 "s_register_operand" "=r")
2105         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2106   "TARGET_ARM"
2107   "bic%?s\\t%0, %1, %2"
2108   [(set_attr "conds" "set")]
2111 (define_insn "*andsi_notsi_si_compare0_scratch"
2112   [(set (reg:CC_NOOV CC_REGNUM)
2113         (compare:CC_NOOV
2114          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2115                  (match_operand:SI 1 "s_register_operand" "r"))
2116          (const_int 0)))
2117    (clobber (match_scratch:SI 0 "=r"))]
2118   "TARGET_ARM"
2119   "bic%?s\\t%0, %1, %2"
2120   [(set_attr "conds" "set")]
2123 (define_insn "iordi3"
2124   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2125         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2126                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2127   "TARGET_ARM && ! TARGET_IWMMXT"
2128   "#"
2129   [(set_attr "length" "8")
2130    (set_attr "predicable" "yes")]
2133 (define_insn "*iordi_zesidi_di"
2134   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2135         (ior:DI (zero_extend:DI
2136                  (match_operand:SI 2 "s_register_operand" "r,r"))
2137                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2138   "TARGET_ARM"
2139   "@
2140    orr%?\\t%Q0, %Q1, %2
2141    #"
2142   [(set_attr "length" "4,8")
2143    (set_attr "predicable" "yes")]
2146 (define_insn "*iordi_sesidi_di"
2147   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2148         (ior:DI (sign_extend:DI
2149                  (match_operand:SI 2 "s_register_operand" "r,r"))
2150                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2151   "TARGET_ARM"
2152   "#"
2153   [(set_attr "length" "8")
2154    (set_attr "predicable" "yes")]
2157 (define_expand "iorsi3"
2158   [(set (match_operand:SI         0 "s_register_operand" "")
2159         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2160                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2161   "TARGET_EITHER"
2162   "
2163   if (GET_CODE (operands[2]) == CONST_INT)
2164     {
2165       if (TARGET_ARM)
2166         {
2167           arm_split_constant (IOR, SImode, NULL_RTX,
2168                               INTVAL (operands[2]), operands[0], operands[1],
2169                               optimize && !no_new_pseudos);
2170           DONE;
2171         }
2172       else /* TARGET_THUMB */
2173         operands [2] = force_reg (SImode, operands [2]);
2174     }
2175   "
2178 (define_insn_and_split "*arm_iorsi3"
2179   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2180         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2181                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2182   "TARGET_ARM"
2183   "@
2184    orr%?\\t%0, %1, %2
2185    #"
2186   "TARGET_ARM
2187    && GET_CODE (operands[2]) == CONST_INT
2188    && !const_ok_for_arm (INTVAL (operands[2]))"
2189   [(clobber (const_int 0))]
2190   "
2191   arm_split_constant (IOR, SImode, curr_insn, 
2192                       INTVAL (operands[2]), operands[0], operands[1], 0);
2193   DONE;
2194   "
2195   [(set_attr "length" "4,16")
2196    (set_attr "predicable" "yes")]
2199 (define_insn "*thumb_iorsi3"
2200   [(set (match_operand:SI         0 "register_operand" "=l")
2201         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2202                 (match_operand:SI 2 "register_operand" "l")))]
2203   "TARGET_THUMB"
2204   "orr\\t%0, %0, %2"
2205   [(set_attr "length" "2")]
2208 (define_peephole2
2209   [(match_scratch:SI 3 "r")
2210    (set (match_operand:SI 0 "arm_general_register_operand" "")
2211         (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2212                 (match_operand:SI 2 "const_int_operand" "")))]
2213   "TARGET_ARM
2214    && !const_ok_for_arm (INTVAL (operands[2]))
2215    && const_ok_for_arm (~INTVAL (operands[2]))"
2216   [(set (match_dup 3) (match_dup 2))
2217    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2218   ""
2221 (define_insn "*iorsi3_compare0"
2222   [(set (reg:CC_NOOV CC_REGNUM)
2223         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2224                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2225                          (const_int 0)))
2226    (set (match_operand:SI 0 "s_register_operand" "=r")
2227         (ior:SI (match_dup 1) (match_dup 2)))]
2228   "TARGET_ARM"
2229   "orr%?s\\t%0, %1, %2"
2230   [(set_attr "conds" "set")]
2233 (define_insn "*iorsi3_compare0_scratch"
2234   [(set (reg:CC_NOOV CC_REGNUM)
2235         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2236                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2237                          (const_int 0)))
2238    (clobber (match_scratch:SI 0 "=r"))]
2239   "TARGET_ARM"
2240   "orr%?s\\t%0, %1, %2"
2241   [(set_attr "conds" "set")]
2244 (define_insn "xordi3"
2245   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2246         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2247                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2248   "TARGET_ARM && !TARGET_IWMMXT"
2249   "#"
2250   [(set_attr "length" "8")
2251    (set_attr "predicable" "yes")]
2254 (define_insn "*xordi_zesidi_di"
2255   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2256         (xor:DI (zero_extend:DI
2257                  (match_operand:SI 2 "s_register_operand" "r,r"))
2258                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2259   "TARGET_ARM"
2260   "@
2261    eor%?\\t%Q0, %Q1, %2
2262    #"
2263   [(set_attr "length" "4,8")
2264    (set_attr "predicable" "yes")]
2267 (define_insn "*xordi_sesidi_di"
2268   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2269         (xor:DI (sign_extend:DI
2270                  (match_operand:SI 2 "s_register_operand" "r,r"))
2271                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2272   "TARGET_ARM"
2273   "#"
2274   [(set_attr "length" "8")
2275    (set_attr "predicable" "yes")]
2278 (define_expand "xorsi3"
2279   [(set (match_operand:SI         0 "s_register_operand" "")
2280         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2281                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2282   "TARGET_EITHER"
2283   "if (TARGET_THUMB)
2284      if (GET_CODE (operands[2]) == CONST_INT)
2285        operands[2] = force_reg (SImode, operands[2]);
2286   "
2289 (define_insn "*arm_xorsi3"
2290   [(set (match_operand:SI         0 "s_register_operand" "=r")
2291         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2292                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2293   "TARGET_ARM"
2294   "eor%?\\t%0, %1, %2"
2295   [(set_attr "predicable" "yes")]
2298 (define_insn "*thumb_xorsi3"
2299   [(set (match_operand:SI         0 "register_operand" "=l")
2300         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2301                 (match_operand:SI 2 "register_operand" "l")))]
2302   "TARGET_THUMB"
2303   "eor\\t%0, %0, %2"
2304   [(set_attr "length" "2")]
2307 (define_insn "*xorsi3_compare0"
2308   [(set (reg:CC_NOOV CC_REGNUM)
2309         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2310                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2311                          (const_int 0)))
2312    (set (match_operand:SI 0 "s_register_operand" "=r")
2313         (xor:SI (match_dup 1) (match_dup 2)))]
2314   "TARGET_ARM"
2315   "eor%?s\\t%0, %1, %2"
2316   [(set_attr "conds" "set")]
2319 (define_insn "*xorsi3_compare0_scratch"
2320   [(set (reg:CC_NOOV CC_REGNUM)
2321         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2322                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2323                          (const_int 0)))]
2324   "TARGET_ARM"
2325   "teq%?\\t%0, %1"
2326   [(set_attr "conds" "set")]
2329 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2330 ; (NOT D) we can sometimes merge the final NOT into one of the following
2331 ; insns.
2333 (define_split
2334   [(set (match_operand:SI 0 "s_register_operand" "")
2335         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2336                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2337                 (match_operand:SI 3 "arm_rhs_operand" "")))
2338    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2339   "TARGET_ARM"
2340   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2341                               (not:SI (match_dup 3))))
2342    (set (match_dup 0) (not:SI (match_dup 4)))]
2343   ""
2346 (define_insn "*andsi_iorsi3_notsi"
2347   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2348         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2349                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2350                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2351   "TARGET_ARM"
2352   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2353   [(set_attr "length" "8")
2354    (set_attr "predicable" "yes")]
2357 (define_split
2358   [(set (match_operand:SI 0 "s_register_operand" "")
2359         (match_operator:SI 1 "logical_binary_operator"
2360          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2361                            (match_operand:SI 3 "const_int_operand" "")
2362                            (match_operand:SI 4 "const_int_operand" ""))
2363           (match_operator:SI 9 "logical_binary_operator"
2364            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2365                          (match_operand:SI 6 "const_int_operand" ""))
2366             (match_operand:SI 7 "s_register_operand" "")])]))
2367    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2368   "TARGET_ARM
2369    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2370    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2371   [(set (match_dup 8)
2372         (match_op_dup 1
2373          [(ashift:SI (match_dup 2) (match_dup 4))
2374           (match_dup 5)]))
2375    (set (match_dup 0)
2376         (match_op_dup 1
2377          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2378           (match_dup 7)]))]
2379   "
2380   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2383 (define_split
2384   [(set (match_operand:SI 0 "s_register_operand" "")
2385         (match_operator:SI 1 "logical_binary_operator"
2386          [(match_operator:SI 9 "logical_binary_operator"
2387            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2388                          (match_operand:SI 6 "const_int_operand" ""))
2389             (match_operand:SI 7 "s_register_operand" "")])
2390           (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2391                            (match_operand:SI 3 "const_int_operand" "")
2392                            (match_operand:SI 4 "const_int_operand" ""))]))
2393    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2394   "TARGET_ARM
2395    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2396    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2397   [(set (match_dup 8)
2398         (match_op_dup 1
2399          [(ashift:SI (match_dup 2) (match_dup 4))
2400           (match_dup 5)]))
2401    (set (match_dup 0)
2402         (match_op_dup 1
2403          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2404           (match_dup 7)]))]
2405   "
2406   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2409 (define_split
2410   [(set (match_operand:SI 0 "s_register_operand" "")
2411         (match_operator:SI 1 "logical_binary_operator"
2412          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2413                            (match_operand:SI 3 "const_int_operand" "")
2414                            (match_operand:SI 4 "const_int_operand" ""))
2415           (match_operator:SI 9 "logical_binary_operator"
2416            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2417                          (match_operand:SI 6 "const_int_operand" ""))
2418             (match_operand:SI 7 "s_register_operand" "")])]))
2419    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2420   "TARGET_ARM
2421    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2422    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2423   [(set (match_dup 8)
2424         (match_op_dup 1
2425          [(ashift:SI (match_dup 2) (match_dup 4))
2426           (match_dup 5)]))
2427    (set (match_dup 0)
2428         (match_op_dup 1
2429          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2430           (match_dup 7)]))]
2431   "
2432   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2435 (define_split
2436   [(set (match_operand:SI 0 "s_register_operand" "")
2437         (match_operator:SI 1 "logical_binary_operator"
2438          [(match_operator:SI 9 "logical_binary_operator"
2439            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2440                          (match_operand:SI 6 "const_int_operand" ""))
2441             (match_operand:SI 7 "s_register_operand" "")])
2442           (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2443                            (match_operand:SI 3 "const_int_operand" "")
2444                            (match_operand:SI 4 "const_int_operand" ""))]))
2445    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2446   "TARGET_ARM
2447    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2448    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2449   [(set (match_dup 8)
2450         (match_op_dup 1
2451          [(ashift:SI (match_dup 2) (match_dup 4))
2452           (match_dup 5)]))
2453    (set (match_dup 0)
2454         (match_op_dup 1
2455          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2456           (match_dup 7)]))]
2457   "
2458   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2462 ;; Minimum and maximum insns
2464 (define_insn "smaxsi3"
2465   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2466         (smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2467                  (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2468    (clobber (reg:CC CC_REGNUM))]
2469   "TARGET_ARM"
2470   "@
2471    cmp\\t%1, %2\;movlt\\t%0, %2
2472    cmp\\t%1, %2\;movge\\t%0, %1
2473    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2474   [(set_attr "conds" "clob")
2475    (set_attr "length" "8,8,12")]
2478 (define_insn "sminsi3"
2479   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2480         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2481                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2482    (clobber (reg:CC CC_REGNUM))]
2483   "TARGET_ARM"
2484   "@
2485    cmp\\t%1, %2\;movge\\t%0, %2
2486    cmp\\t%1, %2\;movlt\\t%0, %1
2487    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2488   [(set_attr "conds" "clob")
2489    (set_attr "length" "8,8,12")]
2492 (define_insn "umaxsi3"
2493   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2494         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2495                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2496    (clobber (reg:CC CC_REGNUM))]
2497   "TARGET_ARM"
2498   "@
2499    cmp\\t%1, %2\;movcc\\t%0, %2
2500    cmp\\t%1, %2\;movcs\\t%0, %1
2501    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2502   [(set_attr "conds" "clob")
2503    (set_attr "length" "8,8,12")]
2506 (define_insn "uminsi3"
2507   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2508         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2509                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2510    (clobber (reg:CC CC_REGNUM))]
2511   "TARGET_ARM"
2512   "@
2513    cmp\\t%1, %2\;movcs\\t%0, %2
2514    cmp\\t%1, %2\;movcc\\t%0, %1
2515    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2516   [(set_attr "conds" "clob")
2517    (set_attr "length" "8,8,12")]
2520 (define_insn "*store_minmaxsi"
2521   [(set (match_operand:SI 0 "memory_operand" "=m")
2522         (match_operator:SI 3 "minmax_operator"
2523          [(match_operand:SI 1 "s_register_operand" "r")
2524           (match_operand:SI 2 "s_register_operand" "r")]))
2525    (clobber (reg:CC CC_REGNUM))]
2526   "TARGET_ARM"
2527   "*
2528   operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2529                                 operands[1], operands[2]);
2530   output_asm_insn (\"cmp\\t%1, %2\", operands);
2531   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2532   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2533   return \"\";
2534   "
2535   [(set_attr "conds" "clob")
2536    (set_attr "length" "12")
2537    (set_attr "type" "store1")]
2540 ; Reject the frame pointer in operand[1], since reloading this after
2541 ; it has been eliminated can cause carnage.
2542 (define_insn "*minmax_arithsi"
2543   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2544         (match_operator:SI 4 "shiftable_operator"
2545          [(match_operator:SI 5 "minmax_operator"
2546            [(match_operand:SI 2 "s_register_operand" "r,r")
2547             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2548           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2549    (clobber (reg:CC CC_REGNUM))]
2550   "TARGET_ARM
2551    && (GET_CODE (operands[1]) != REG
2552        || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2553            && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2554   "*
2555   {
2556     enum rtx_code code = GET_CODE (operands[4]);
2558     operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2559                                   operands[2], operands[3]);
2560     output_asm_insn (\"cmp\\t%2, %3\", operands);
2561     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2562     if (which_alternative != 0 || operands[3] != const0_rtx
2563         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2564       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2565     return \"\";
2566   }"
2567   [(set_attr "conds" "clob")
2568    (set_attr "length" "12")]
2572 ;; Shift and rotation insns
2574 (define_expand "ashldi3"
2575   [(set (match_operand:DI            0 "s_register_operand" "")
2576         (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2577                    (match_operand:SI 2 "reg_or_int_operand" "")))]
2578   "TARGET_ARM"
2579   "
2580   if (GET_CODE (operands[2]) == CONST_INT)
2581     {
2582       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2583         {
2584           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2585           DONE;
2586         }
2587         /* Ideally we shouldn't fail here if we could know that operands[1] 
2588            ends up already living in an iwmmxt register. Otherwise it's
2589            cheaper to have the alternate code being generated than moving
2590            values to iwmmxt regs and back.  */
2591         FAIL;
2592     }
2593   else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2594     FAIL;
2595   "
2598 (define_insn "arm_ashldi3_1bit"
2599   [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
2600         (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2601                    (const_int 1)))
2602    (clobber (reg:CC CC_REGNUM))]
2603   "TARGET_ARM"
2604   "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2605   [(set_attr "conds" "clob")
2606    (set_attr "length" "8")]
2609 (define_expand "ashlsi3"
2610   [(set (match_operand:SI            0 "s_register_operand" "")
2611         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2612                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2613   "TARGET_EITHER"
2614   "
2615   if (GET_CODE (operands[2]) == CONST_INT
2616       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2617     {
2618       emit_insn (gen_movsi (operands[0], const0_rtx));
2619       DONE;
2620     }
2621   "
2624 (define_insn "*thumb_ashlsi3"
2625   [(set (match_operand:SI            0 "register_operand" "=l,l")
2626         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2627                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2628   "TARGET_THUMB"
2629   "lsl\\t%0, %1, %2"
2630   [(set_attr "length" "2")]
2633 (define_expand "ashrdi3"
2634   [(set (match_operand:DI              0 "s_register_operand" "")
2635         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2636                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2637   "TARGET_ARM"
2638   "
2639   if (GET_CODE (operands[2]) == CONST_INT)
2640     {
2641       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2642         {
2643           emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2644           DONE;
2645         }
2646         /* Ideally we shouldn't fail here if we could know that operands[1] 
2647            ends up already living in an iwmmxt register. Otherwise it's
2648            cheaper to have the alternate code being generated than moving
2649            values to iwmmxt regs and back.  */
2650         FAIL;
2651     }
2652   else if (!TARGET_REALLY_IWMMXT)
2653     FAIL;
2654   "
2657 (define_insn "arm_ashrdi3_1bit"
2658   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2659         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2660                      (const_int 1)))
2661    (clobber (reg:CC CC_REGNUM))]
2662   "TARGET_ARM"
2663   "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2664   [(set_attr "conds" "clob")
2665    (set_attr "length" "8")]
2668 (define_expand "ashrsi3"
2669   [(set (match_operand:SI              0 "s_register_operand" "")
2670         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2671                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2672   "TARGET_EITHER"
2673   "
2674   if (GET_CODE (operands[2]) == CONST_INT
2675       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2676     operands[2] = GEN_INT (31);
2677   "
2680 (define_insn "*thumb_ashrsi3"
2681   [(set (match_operand:SI              0 "register_operand" "=l,l")
2682         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2683                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2684   "TARGET_THUMB"
2685   "asr\\t%0, %1, %2"
2686   [(set_attr "length" "2")]
2689 (define_expand "lshrdi3"
2690   [(set (match_operand:DI              0 "s_register_operand" "")
2691         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2692                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2693   "TARGET_ARM"
2694   "
2695   if (GET_CODE (operands[2]) == CONST_INT)
2696     {
2697       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2698         {
2699           emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2700           DONE;
2701         }
2702         /* Ideally we shouldn't fail here if we could know that operands[1] 
2703            ends up already living in an iwmmxt register. Otherwise it's
2704            cheaper to have the alternate code being generated than moving
2705            values to iwmmxt regs and back.  */
2706         FAIL;
2707     }
2708   else if (!TARGET_REALLY_IWMMXT)
2709     FAIL;
2710   "
2713 (define_insn "arm_lshrdi3_1bit"
2714   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2715         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2716                      (const_int 1)))
2717    (clobber (reg:CC CC_REGNUM))]
2718   "TARGET_ARM"
2719   "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2720   [(set_attr "conds" "clob")
2721    (set_attr "length" "8")]
2724 (define_expand "lshrsi3"
2725   [(set (match_operand:SI              0 "s_register_operand" "")
2726         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2727                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2728   "TARGET_EITHER"
2729   "
2730   if (GET_CODE (operands[2]) == CONST_INT
2731       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2732     {
2733       emit_insn (gen_movsi (operands[0], const0_rtx));
2734       DONE;
2735     }
2736   "
2739 (define_insn "*thumb_lshrsi3"
2740   [(set (match_operand:SI              0 "register_operand" "=l,l")
2741         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2742                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2743   "TARGET_THUMB"
2744   "lsr\\t%0, %1, %2"
2745   [(set_attr "length" "2")]
2748 (define_expand "rotlsi3"
2749   [(set (match_operand:SI              0 "s_register_operand" "")
2750         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2751                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2752   "TARGET_ARM"
2753   "
2754   if (GET_CODE (operands[2]) == CONST_INT)
2755     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2756   else
2757     {
2758       rtx reg = gen_reg_rtx (SImode);
2759       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2760       operands[2] = reg;
2761     }
2762   "
2765 (define_expand "rotrsi3"
2766   [(set (match_operand:SI              0 "s_register_operand" "")
2767         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2768                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2769   "TARGET_EITHER"
2770   "
2771   if (TARGET_ARM)
2772     {
2773       if (GET_CODE (operands[2]) == CONST_INT
2774           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2775         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2776     }
2777   else /* TARGET_THUMB */
2778     {
2779       if (GET_CODE (operands [2]) == CONST_INT)
2780         operands [2] = force_reg (SImode, operands[2]);
2781     }
2782   "
2785 (define_insn "*thumb_rotrsi3"
2786   [(set (match_operand:SI              0 "register_operand" "=l")
2787         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2788                      (match_operand:SI 2 "register_operand" "l")))]
2789   "TARGET_THUMB"
2790   "ror\\t%0, %0, %2"
2791   [(set_attr "length" "2")]
2794 (define_insn "*arm_shiftsi3"
2795   [(set (match_operand:SI   0 "s_register_operand" "=r")
2796         (match_operator:SI  3 "shift_operator"
2797          [(match_operand:SI 1 "s_register_operand"  "r")
2798           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2799   "TARGET_ARM"
2800   "mov%?\\t%0, %1%S3"
2801   [(set_attr "predicable" "yes")
2802    (set_attr "shift" "1")
2803    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2804                       (const_string "alu_shift")
2805                       (const_string "alu_shift_reg")))]
2808 (define_insn "*shiftsi3_compare0"
2809   [(set (reg:CC_NOOV CC_REGNUM)
2810         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2811                           [(match_operand:SI 1 "s_register_operand" "r")
2812                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2813                          (const_int 0)))
2814    (set (match_operand:SI 0 "s_register_operand" "=r")
2815         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2816   "TARGET_ARM"
2817   "mov%?s\\t%0, %1%S3"
2818   [(set_attr "conds" "set")
2819    (set_attr "shift" "1")
2820    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2821                       (const_string "alu_shift")
2822                       (const_string "alu_shift_reg")))]
2825 (define_insn "*shiftsi3_compare0_scratch"
2826   [(set (reg:CC_NOOV CC_REGNUM)
2827         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2828                           [(match_operand:SI 1 "s_register_operand" "r")
2829                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2830                          (const_int 0)))
2831    (clobber (match_scratch:SI 0 "=r"))]
2832   "TARGET_ARM"
2833   "mov%?s\\t%0, %1%S3"
2834   [(set_attr "conds" "set")
2835    (set_attr "shift" "1")]
2838 (define_insn "*notsi_shiftsi"
2839   [(set (match_operand:SI 0 "s_register_operand" "=r")
2840         (not:SI (match_operator:SI 3 "shift_operator"
2841                  [(match_operand:SI 1 "s_register_operand" "r")
2842                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2843   "TARGET_ARM"
2844   "mvn%?\\t%0, %1%S3"
2845   [(set_attr "predicable" "yes")
2846    (set_attr "shift" "1")
2847    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2848                       (const_string "alu_shift")
2849                       (const_string "alu_shift_reg")))]
2852 (define_insn "*notsi_shiftsi_compare0"
2853   [(set (reg:CC_NOOV CC_REGNUM)
2854         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2855                           [(match_operand:SI 1 "s_register_operand" "r")
2856                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2857                          (const_int 0)))
2858    (set (match_operand:SI 0 "s_register_operand" "=r")
2859         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2860   "TARGET_ARM"
2861   "mvn%?s\\t%0, %1%S3"
2862   [(set_attr "conds" "set")
2863    (set_attr "shift" "1")
2864    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2865                       (const_string "alu_shift")
2866                       (const_string "alu_shift_reg")))]
2869 (define_insn "*not_shiftsi_compare0_scratch"
2870   [(set (reg:CC_NOOV CC_REGNUM)
2871         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2872                           [(match_operand:SI 1 "s_register_operand" "r")
2873                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2874                          (const_int 0)))
2875    (clobber (match_scratch:SI 0 "=r"))]
2876   "TARGET_ARM"
2877   "mvn%?s\\t%0, %1%S3"
2878   [(set_attr "conds" "set")
2879    (set_attr "shift" "1")
2880    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2881                       (const_string "alu_shift")
2882                       (const_string "alu_shift_reg")))]
2885 ;; We don't really have extzv, but defining this using shifts helps
2886 ;; to reduce register pressure later on.
2888 (define_expand "extzv"
2889   [(set (match_dup 4)
2890         (ashift:SI (match_operand:SI   1 "register_operand" "")
2891                    (match_operand:SI   2 "const_int_operand" "")))
2892    (set (match_operand:SI              0 "register_operand" "")
2893         (lshiftrt:SI (match_dup 4)
2894                      (match_operand:SI 3 "const_int_operand" "")))]
2895   "TARGET_THUMB"
2896   "
2897   {
2898     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2899     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2900     
2901     operands[3] = GEN_INT (rshift);
2902     
2903     if (lshift == 0)
2904       {
2905         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2906         DONE;
2907       }
2908       
2909     operands[2] = GEN_INT (lshift);
2910     operands[4] = gen_reg_rtx (SImode);
2911   }"
2915 ;; Unary arithmetic insns
2917 (define_expand "negdi2"
2918  [(parallel
2919    [(set (match_operand:DI          0 "s_register_operand" "")
2920           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2921     (clobber (reg:CC CC_REGNUM))])]
2922   "TARGET_EITHER"
2923   "
2924   if (TARGET_THUMB)
2925     {
2926       if (GET_CODE (operands[1]) != REG)
2927         operands[1] = force_reg (SImode, operands[1]);
2928      }
2929   "
2932 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2933 ;; The second alternative is to allow the common case of a *full* overlap.
2934 (define_insn "*arm_negdi2"
2935   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2936         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2937    (clobber (reg:CC CC_REGNUM))]
2938   "TARGET_ARM"
2939   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2940   [(set_attr "conds" "clob")
2941    (set_attr "length" "8")]
2944 (define_insn "*thumb_negdi2"
2945   [(set (match_operand:DI         0 "register_operand" "=&l")
2946         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
2947    (clobber (reg:CC CC_REGNUM))]
2948   "TARGET_THUMB"
2949   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2950   [(set_attr "length" "6")]
2953 (define_expand "negsi2"
2954   [(set (match_operand:SI         0 "s_register_operand" "")
2955         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2956   "TARGET_EITHER"
2957   ""
2960 (define_insn "*arm_negsi2"
2961   [(set (match_operand:SI         0 "s_register_operand" "=r")
2962         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2963   "TARGET_ARM"
2964   "rsb%?\\t%0, %1, #0"
2965   [(set_attr "predicable" "yes")]
2968 (define_insn "*thumb_negsi2"
2969   [(set (match_operand:SI         0 "register_operand" "=l")
2970         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2971   "TARGET_THUMB"
2972   "neg\\t%0, %1"
2973   [(set_attr "length" "2")]
2976 (define_expand "negsf2"
2977   [(set (match_operand:SF         0 "s_register_operand" "")
2978         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2979   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2980   ""
2983 (define_expand "negdf2"
2984   [(set (match_operand:DF         0 "s_register_operand" "")
2985         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2986   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2987   "")
2989 ;; abssi2 doesn't really clobber the condition codes if a different register
2990 ;; is being set.  To keep things simple, assume during rtl manipulations that
2991 ;; it does, but tell the final scan operator the truth.  Similarly for
2992 ;; (neg (abs...))
2994 (define_expand "abssi2"
2995   [(parallel
2996     [(set (match_operand:SI         0 "s_register_operand" "")
2997           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
2998      (clobber (reg:CC CC_REGNUM))])]
2999   "TARGET_ARM"
3000   "")
3002 (define_insn "*arm_abssi2"
3003   [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
3004         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3005    (clobber (reg:CC CC_REGNUM))]
3006   "TARGET_ARM"
3007   "@
3008    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3009    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3010   [(set_attr "conds" "clob,*")
3011    (set_attr "shift" "1")
3012    ;; predicable can't be set based on the variant, so left as no
3013    (set_attr "length" "8")]
3016 (define_insn "*neg_abssi2"
3017   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3018         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3019    (clobber (reg:CC CC_REGNUM))]
3020   "TARGET_ARM"
3021   "@
3022    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3023    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3024   [(set_attr "conds" "clob,*")
3025    (set_attr "shift" "1")
3026    ;; predicable can't be set based on the variant, so left as no
3027    (set_attr "length" "8")]
3030 (define_expand "abssf2"
3031   [(set (match_operand:SF         0 "s_register_operand" "")
3032         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3033   "TARGET_ARM && TARGET_HARD_FLOAT"
3034   "")
3036 (define_expand "absdf2"
3037   [(set (match_operand:DF         0 "s_register_operand" "")
3038         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3039   "TARGET_ARM && TARGET_HARD_FLOAT"
3040   "")
3042 (define_expand "sqrtsf2"
3043   [(set (match_operand:SF 0 "s_register_operand" "")
3044         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3045   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3046   "")
3048 (define_expand "sqrtdf2"
3049   [(set (match_operand:DF 0 "s_register_operand" "")
3050         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3051   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3052   "")
3054 (define_insn_and_split "one_cmpldi2"
3055   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3056         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3057   "TARGET_ARM"
3058   "#"
3059   "TARGET_ARM && reload_completed"
3060   [(set (match_dup 0) (not:SI (match_dup 1)))
3061    (set (match_dup 2) (not:SI (match_dup 3)))]
3062   "
3063   {
3064     operands[2] = gen_highpart (SImode, operands[0]);
3065     operands[0] = gen_lowpart (SImode, operands[0]);
3066     operands[3] = gen_highpart (SImode, operands[1]);
3067     operands[1] = gen_lowpart (SImode, operands[1]);
3068   }"
3069   [(set_attr "length" "8")
3070    (set_attr "predicable" "yes")]
3073 (define_expand "one_cmplsi2"
3074   [(set (match_operand:SI         0 "s_register_operand" "")
3075         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3076   "TARGET_EITHER"
3077   ""
3080 (define_insn "*arm_one_cmplsi2"
3081   [(set (match_operand:SI         0 "s_register_operand" "=r")
3082         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3083   "TARGET_ARM"
3084   "mvn%?\\t%0, %1"
3085   [(set_attr "predicable" "yes")]
3088 (define_insn "*thumb_one_cmplsi2"
3089   [(set (match_operand:SI         0 "register_operand" "=l")
3090         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3091   "TARGET_THUMB"
3092   "mvn\\t%0, %1"
3093   [(set_attr "length" "2")]
3096 (define_insn "*notsi_compare0"
3097   [(set (reg:CC_NOOV CC_REGNUM)
3098         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3099                          (const_int 0)))
3100    (set (match_operand:SI 0 "s_register_operand" "=r")
3101         (not:SI (match_dup 1)))]
3102   "TARGET_ARM"
3103   "mvn%?s\\t%0, %1"
3104   [(set_attr "conds" "set")]
3107 (define_insn "*notsi_compare0_scratch"
3108   [(set (reg:CC_NOOV CC_REGNUM)
3109         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3110                          (const_int 0)))
3111    (clobber (match_scratch:SI 0 "=r"))]
3112   "TARGET_ARM"
3113   "mvn%?s\\t%0, %1"
3114   [(set_attr "conds" "set")]
3117 ;; Fixed <--> Floating conversion insns
3119 (define_expand "floatsisf2"
3120   [(set (match_operand:SF           0 "s_register_operand" "")
3121         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3122   "TARGET_ARM && TARGET_HARD_FLOAT"
3123   "
3124   if (TARGET_MAVERICK)
3125     {
3126       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3127       DONE;
3128     }
3131 (define_expand "floatsidf2"
3132   [(set (match_operand:DF           0 "s_register_operand" "")
3133         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3134   "TARGET_ARM && TARGET_HARD_FLOAT"
3135   "
3136   if (TARGET_MAVERICK)
3137     {
3138       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3139       DONE;
3140     }
3143 (define_expand "fix_truncsfsi2"
3144   [(set (match_operand:SI         0 "s_register_operand" "")
3145         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3146   "TARGET_ARM && TARGET_HARD_FLOAT"
3147   "
3148   if (TARGET_MAVERICK)
3149     {
3150       if (!cirrus_fp_register (operands[0], SImode))
3151         operands[0] = force_reg (SImode, operands[0]);
3152       if (!cirrus_fp_register (operands[1], SFmode))
3153         operands[1] = force_reg (SFmode, operands[0]);
3154       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3155       DONE;
3156     }
3159 (define_expand "fix_truncdfsi2"
3160   [(set (match_operand:SI         0 "s_register_operand" "")
3161         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3162   "TARGET_ARM && TARGET_HARD_FLOAT"
3163   "
3164   if (TARGET_MAVERICK)
3165     {
3166       if (!cirrus_fp_register (operands[1], DFmode))
3167         operands[1] = force_reg (DFmode, operands[0]);
3168       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3169       DONE;
3170     }
3173 ;; Truncation insns
3175 (define_expand "truncdfsf2"
3176   [(set (match_operand:SF  0 "s_register_operand" "")
3177         (float_truncate:SF
3178          (match_operand:DF 1 "s_register_operand" "")))]
3179   "TARGET_ARM && TARGET_HARD_FLOAT"
3180   ""
3183 ;; Zero and sign extension instructions.
3185 (define_insn "zero_extendsidi2"
3186   [(set (match_operand:DI 0 "s_register_operand" "=r")
3187         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3188   "TARGET_ARM"
3189   "*
3190     if (REGNO (operands[1])
3191         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3192       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3193     return \"mov%?\\t%R0, #0\";
3194   "
3195   [(set_attr "length" "8")
3196    (set_attr "predicable" "yes")]
3199 (define_insn "zero_extendqidi2"
3200   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3201         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3202   "TARGET_ARM"
3203   "@
3204    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3205    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3206   [(set_attr "length" "8")
3207    (set_attr "predicable" "yes")
3208    (set_attr "type" "*,load_byte")
3209    (set_attr "pool_range" "*,4092")
3210    (set_attr "neg_pool_range" "*,4084")]
3213 (define_insn "extendsidi2"
3214   [(set (match_operand:DI 0 "s_register_operand" "=r")
3215         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3216   "TARGET_ARM"
3217   "*
3218     if (REGNO (operands[1])
3219         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3220       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3221     return \"mov%?\\t%R0, %Q0, asr #31\";
3222   "
3223   [(set_attr "length" "8")
3224    (set_attr "shift" "1")
3225    (set_attr "predicable" "yes")]
3228 (define_expand "zero_extendhisi2"
3229   [(set (match_dup 2)
3230         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3231                    (const_int 16)))
3232    (set (match_operand:SI 0 "s_register_operand" "")
3233         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3234   "TARGET_EITHER"
3235   "
3236   {
3237     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3238       {
3239         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3240                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3241         DONE;
3242       }
3244     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3245       {
3246         emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3247         DONE;
3248       }
3250     if (!s_register_operand (operands[1], HImode))
3251       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3253     if (arm_arch6)
3254       {
3255         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3256                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3257         DONE;
3258       }
3260     operands[1] = gen_lowpart (SImode, operands[1]);
3261     operands[2] = gen_reg_rtx (SImode);
3262   }"
3265 (define_insn "*thumb_zero_extendhisi2"
3266   [(set (match_operand:SI 0 "register_operand" "=l")
3267         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3268   "TARGET_THUMB && !arm_arch6"
3269   "*
3270   rtx mem = XEXP (operands[1], 0);
3272   if (GET_CODE (mem) == CONST)
3273     mem = XEXP (mem, 0);
3274     
3275   if (GET_CODE (mem) == LABEL_REF)
3276     return \"ldr\\t%0, %1\";
3277     
3278   if (GET_CODE (mem) == PLUS)
3279     {
3280       rtx a = XEXP (mem, 0);
3281       rtx b = XEXP (mem, 1);
3283       /* This can happen due to bugs in reload.  */
3284       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3285         {
3286           rtx ops[2];
3287           ops[0] = operands[0];
3288           ops[1] = a;
3289       
3290           output_asm_insn (\"mov        %0, %1\", ops);
3292           XEXP (mem, 0) = operands[0];
3293        }
3295       else if (   GET_CODE (a) == LABEL_REF
3296                && GET_CODE (b) == CONST_INT)
3297         return \"ldr\\t%0, %1\";
3298     }
3299     
3300   return \"ldrh\\t%0, %1\";
3301   "
3302   [(set_attr "length" "4")
3303    (set_attr "type" "load_byte")
3304    (set_attr "pool_range" "60")]
3307 (define_insn "*thumb_zero_extendhisi2_v6"
3308   [(set (match_operand:SI 0 "register_operand" "=l,l")
3309         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3310   "TARGET_THUMB && arm_arch6"
3311   "*
3312   rtx mem;
3314   if (which_alternative == 0)
3315     return \"uxth\\t%0, %1\";
3317   mem = XEXP (operands[1], 0);
3319   if (GET_CODE (mem) == CONST)
3320     mem = XEXP (mem, 0);
3321     
3322   if (GET_CODE (mem) == LABEL_REF)
3323     return \"ldr\\t%0, %1\";
3324     
3325   if (GET_CODE (mem) == PLUS)
3326     {
3327       rtx a = XEXP (mem, 0);
3328       rtx b = XEXP (mem, 1);
3330       /* This can happen due to bugs in reload.  */
3331       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3332         {
3333           rtx ops[2];
3334           ops[0] = operands[0];
3335           ops[1] = a;
3336       
3337           output_asm_insn (\"mov        %0, %1\", ops);
3339           XEXP (mem, 0) = operands[0];
3340        }
3342       else if (   GET_CODE (a) == LABEL_REF
3343                && GET_CODE (b) == CONST_INT)
3344         return \"ldr\\t%0, %1\";
3345     }
3346     
3347   return \"ldrh\\t%0, %1\";
3348   "
3349   [(set_attr "length" "2,4")
3350    (set_attr "type" "alu_shift,load_byte")
3351    (set_attr "pool_range" "*,60")]
3354 (define_insn "*arm_zero_extendhisi2"
3355   [(set (match_operand:SI 0 "s_register_operand" "=r")
3356         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3357   "TARGET_ARM && arm_arch4 && !arm_arch6"
3358   "ldr%?h\\t%0, %1"
3359   [(set_attr "type" "load_byte")
3360    (set_attr "predicable" "yes")
3361    (set_attr "pool_range" "256")
3362    (set_attr "neg_pool_range" "244")]
3365 (define_insn "*arm_zero_extendhisi2_v6"
3366   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3367         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3368   "TARGET_ARM && arm_arch6"
3369   "@
3370    uxth%?\\t%0, %1
3371    ldr%?h\\t%0, %1"
3372   [(set_attr "type" "alu_shift,load_byte")
3373    (set_attr "predicable" "yes")
3374    (set_attr "pool_range" "*,256")
3375    (set_attr "neg_pool_range" "*,244")]
3378 (define_insn "*arm_zero_extendhisi2addsi"
3379   [(set (match_operand:SI 0 "s_register_operand" "=r")
3380         (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3381                  (match_operand:SI 2 "s_register_operand" "r")))]
3382   "TARGET_ARM && arm_arch6"
3383   "uxtah%?\\t%0, %2, %1"
3384   [(set_attr "type" "alu_shift")
3385    (set_attr "predicable" "yes")]
3388 (define_split
3389   [(set (match_operand:SI 0 "s_register_operand" "")
3390         (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3391    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3392   "TARGET_ARM && (!arm_arch4)"
3393   [(set (match_dup 2) (match_dup 1))
3394    (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3395   "
3396   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3397     FAIL;
3398   "
3401 (define_split
3402   [(set (match_operand:SI 0 "s_register_operand" "")
3403         (match_operator:SI 3 "shiftable_operator"
3404          [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3405           (match_operand:SI 4 "s_register_operand" "")]))
3406    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3407   "TARGET_ARM && (!arm_arch4)"
3408   [(set (match_dup 2) (match_dup 1))
3409    (set (match_dup 0)
3410         (match_op_dup 3
3411          [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3412   "
3413   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3414     FAIL;
3415   "
3418 (define_expand "zero_extendqisi2"
3419   [(set (match_operand:SI 0 "s_register_operand" "")
3420         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3421   "TARGET_EITHER"
3422   "
3423   if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3424     {
3425       if (TARGET_ARM)
3426         {
3427           emit_insn (gen_andsi3 (operands[0],
3428                                  gen_lowpart (SImode, operands[1]),
3429                                  GEN_INT (255)));
3430         }
3431       else /* TARGET_THUMB */
3432         {
3433           rtx temp = gen_reg_rtx (SImode);
3434           rtx ops[3];
3435           
3436           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3437           operands[1] = gen_lowpart (SImode, operands[1]);
3439           ops[0] = temp;
3440           ops[1] = operands[1];
3441           ops[2] = GEN_INT (24);
3443           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3444                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3445           
3446           ops[0] = operands[0];
3447           ops[1] = temp;
3448           ops[2] = GEN_INT (24);
3450           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3451                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3452         }
3453       DONE;
3454     }
3455   "
3458 (define_insn "*thumb_zero_extendqisi2"
3459   [(set (match_operand:SI 0 "register_operand" "=l")
3460         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3461   "TARGET_THUMB && !arm_arch6"
3462   "ldrb\\t%0, %1"
3463   [(set_attr "length" "2")
3464    (set_attr "type" "load_byte")
3465    (set_attr "pool_range" "32")]
3468 (define_insn "*thumb_zero_extendqisi2_v6"
3469   [(set (match_operand:SI 0 "register_operand" "=l,l")
3470         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3471   "TARGET_THUMB && arm_arch6"
3472   "@
3473    uxtb\\t%0, %1
3474    ldrb\\t%0, %1"
3475   [(set_attr "length" "2,2")
3476    (set_attr "type" "alu_shift,load_byte")
3477    (set_attr "pool_range" "*,32")]
3480 (define_insn "*arm_zero_extendqisi2"
3481   [(set (match_operand:SI 0 "s_register_operand" "=r")
3482         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3483   "TARGET_ARM && !arm_arch6"
3484   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3485   [(set_attr "type" "load_byte")
3486    (set_attr "predicable" "yes")
3487    (set_attr "pool_range" "4096")
3488    (set_attr "neg_pool_range" "4084")]
3491 (define_insn "*arm_zero_extendqisi2_v6"
3492   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3493         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3494   "TARGET_ARM && arm_arch6"
3495   "@
3496    uxtb%?\\t%0, %1
3497    ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3498   [(set_attr "type" "alu_shift,load_byte")
3499    (set_attr "predicable" "yes")
3500    (set_attr "pool_range" "*,4096")
3501    (set_attr "neg_pool_range" "*,4084")]
3504 (define_insn "*arm_zero_extendqisi2addsi"
3505   [(set (match_operand:SI 0 "s_register_operand" "=r")
3506         (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3507                  (match_operand:SI 2 "s_register_operand" "r")))]
3508   "TARGET_ARM && arm_arch6"
3509   "uxtab%?\\t%0, %2, %1"
3510   [(set_attr "predicable" "yes")
3511    (set_attr "type" "alu_shift")]
3514 (define_split
3515   [(set (match_operand:SI 0 "s_register_operand" "")
3516         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3517    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3518   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3519   [(set (match_dup 2) (match_dup 1))
3520    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3521   ""
3524 (define_insn "*compareqi_eq0"
3525   [(set (reg:CC_Z CC_REGNUM)
3526         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3527                          (const_int 0)))]
3528   "TARGET_ARM"
3529   "tst\\t%0, #255"
3530   [(set_attr "conds" "set")]
3533 (define_expand "extendhisi2"
3534   [(set (match_dup 2)
3535         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3536                    (const_int 16)))
3537    (set (match_operand:SI 0 "s_register_operand" "")
3538         (ashiftrt:SI (match_dup 2)
3539                      (const_int 16)))]
3540   "TARGET_EITHER"
3541   "
3542   {
3543     if (GET_CODE (operands[1]) == MEM)
3544       {
3545         if (TARGET_THUMB)
3546           {
3547             emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3548             DONE;
3549           }
3550         else if (arm_arch4)
3551           {
3552             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3553                        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3554             DONE;
3555           }
3556       }
3558     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3559       {
3560         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3561         DONE;
3562       }
3564     if (!s_register_operand (operands[1], HImode))
3565       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3567     if (arm_arch6)
3568       {
3569         if (TARGET_THUMB)
3570           emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3571         else
3572           emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3573                      gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3575         DONE;
3576       }
3578     operands[1] = gen_lowpart (SImode, operands[1]);
3579     operands[2] = gen_reg_rtx (SImode);
3580   }"
3583 (define_insn "thumb_extendhisi2"
3584   [(set (match_operand:SI 0 "register_operand" "=l")
3585         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3586    (clobber (match_scratch:SI 2 "=&l"))]
3587   "TARGET_THUMB && !arm_arch6"
3588   "*
3589   {
3590     rtx ops[4];
3591     rtx mem = XEXP (operands[1], 0);
3593     /* This code used to try to use 'V', and fix the address only if it was
3594        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3595        range of QImode offsets, and offsettable_address_p does a QImode
3596        address check.  */
3597        
3598     if (GET_CODE (mem) == CONST)
3599       mem = XEXP (mem, 0);
3600     
3601     if (GET_CODE (mem) == LABEL_REF)
3602       return \"ldr\\t%0, %1\";
3603     
3604     if (GET_CODE (mem) == PLUS)
3605       {
3606         rtx a = XEXP (mem, 0);
3607         rtx b = XEXP (mem, 1);
3609         if (GET_CODE (a) == LABEL_REF
3610             && GET_CODE (b) == CONST_INT)
3611           return \"ldr\\t%0, %1\";
3613         if (GET_CODE (b) == REG)
3614           return \"ldrsh\\t%0, %1\";
3615           
3616         ops[1] = a;
3617         ops[2] = b;
3618       }
3619     else
3620       {
3621         ops[1] = mem;
3622         ops[2] = const0_rtx;
3623       }
3624       
3625     if (GET_CODE (ops[1]) != REG)
3626       {
3627         debug_rtx (ops[1]);
3628         abort ();
3629       }
3631     ops[0] = operands[0];
3632     ops[3] = operands[2];
3633     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3634     return \"\";
3635   }"
3636   [(set_attr "length" "4")
3637    (set_attr "type" "load_byte")
3638    (set_attr "pool_range" "1020")]
3641 ;; We used to have an early-clobber on the scratch register here.
3642 ;; However, there's a bug somewhere in reload which means that this
3643 ;; can be partially ignored during spill allocation if the memory
3644 ;; address also needs reloading; this causes an abort later on when
3645 ;; we try to verify the operands.  Fortunately, we don't really need
3646 ;; the early-clobber: we can always use operand 0 if operand 2
3647 ;; overlaps the address.
3648 (define_insn "*thumb_extendhisi2_insn_v6"
3649   [(set (match_operand:SI 0 "register_operand" "=l,l")
3650         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3651    (clobber (match_scratch:SI 2 "=X,l"))]
3652   "TARGET_THUMB && arm_arch6"
3653   "*
3654   {
3655     rtx ops[4];
3656     rtx mem;
3658     if (which_alternative == 0)
3659       return \"sxth\\t%0, %1\";
3661     mem = XEXP (operands[1], 0);
3663     /* This code used to try to use 'V', and fix the address only if it was
3664        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3665        range of QImode offsets, and offsettable_address_p does a QImode
3666        address check.  */
3667        
3668     if (GET_CODE (mem) == CONST)
3669       mem = XEXP (mem, 0);
3670     
3671     if (GET_CODE (mem) == LABEL_REF)
3672       return \"ldr\\t%0, %1\";
3673     
3674     if (GET_CODE (mem) == PLUS)
3675       {
3676         rtx a = XEXP (mem, 0);
3677         rtx b = XEXP (mem, 1);
3679         if (GET_CODE (a) == LABEL_REF
3680             && GET_CODE (b) == CONST_INT)
3681           return \"ldr\\t%0, %1\";
3683         if (GET_CODE (b) == REG)
3684           return \"ldrsh\\t%0, %1\";
3685           
3686         ops[1] = a;
3687         ops[2] = b;
3688       }
3689     else
3690       {
3691         ops[1] = mem;
3692         ops[2] = const0_rtx;
3693       }
3694       
3695     if (GET_CODE (ops[1]) != REG)
3696       {
3697         debug_rtx (ops[1]);
3698         abort ();
3699       }
3701     ops[0] = operands[0];
3702     if (reg_mentioned_p (operands[2], ops[1]))
3703       ops[3] = ops[0];
3704     else
3705       ops[3] = operands[2];
3706     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3707     return \"\";
3708   }"
3709   [(set_attr "length" "2,4")
3710    (set_attr "type" "alu_shift,load_byte")
3711    (set_attr "pool_range" "*,1020")]
3714 (define_expand "extendhisi2_mem"
3715   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3716    (set (match_dup 3)
3717         (zero_extend:SI (match_dup 7)))
3718    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3719    (set (match_operand:SI 0 "" "")
3720         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3721   "TARGET_ARM"
3722   "
3723   {
3724     rtx mem1, mem2;
3725     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3727     mem1 = gen_rtx_MEM (QImode, addr);
3728     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3729     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3730     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3731     operands[0] = gen_lowpart (SImode, operands[0]);
3732     operands[1] = mem1;
3733     operands[2] = gen_reg_rtx (SImode);
3734     operands[3] = gen_reg_rtx (SImode);
3735     operands[6] = gen_reg_rtx (SImode);
3736     operands[7] = mem2;
3738     if (BYTES_BIG_ENDIAN)
3739       {
3740         operands[4] = operands[2];
3741         operands[5] = operands[3];
3742       }
3743     else
3744       {
3745         operands[4] = operands[3];
3746         operands[5] = operands[2];
3747       }
3748   }"
3751 (define_insn "*arm_extendhisi2"
3752   [(set (match_operand:SI 0 "s_register_operand" "=r")
3753         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3754   "TARGET_ARM && arm_arch4 && !arm_arch6"
3755   "ldr%?sh\\t%0, %1"
3756   [(set_attr "type" "load_byte")
3757    (set_attr "predicable" "yes")
3758    (set_attr "pool_range" "256")
3759    (set_attr "neg_pool_range" "244")]
3762 (define_insn "*arm_extendhisi2_v6"
3763   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3764         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3765   "TARGET_ARM && arm_arch6"
3766   "@
3767    sxth%?\\t%0, %1
3768    ldr%?sh\\t%0, %1"
3769   [(set_attr "type" "alu_shift,load_byte")
3770    (set_attr "predicable" "yes")
3771    (set_attr "pool_range" "*,256")
3772    (set_attr "neg_pool_range" "*,244")]
3775 (define_insn "*arm_extendhisi2addsi"
3776   [(set (match_operand:SI 0 "s_register_operand" "=r")
3777         (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3778                  (match_operand:SI 2 "s_register_operand" "r")))]
3779   "TARGET_ARM && arm_arch6"
3780   "sxtah%?\\t%0, %2, %1"
3783 (define_split
3784   [(set (match_operand:SI                 0 "s_register_operand" "")
3785         (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3786    (clobber (match_operand:SI             2 "s_register_operand" ""))]
3787   "TARGET_ARM && (!arm_arch4)"
3788   [(set (match_dup 2) (match_dup 1))
3789    (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3790   "
3791   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3792     FAIL;
3793   "
3796 (define_split
3797   [(set (match_operand:SI                   0 "s_register_operand" "")
3798         (match_operator:SI                  3 "shiftable_operator"
3799          [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3800           (match_operand:SI                 4 "s_register_operand" "")]))
3801    (clobber (match_operand:SI               2 "s_register_operand" ""))]
3802   "TARGET_ARM && (!arm_arch4)"
3803   [(set (match_dup 2) (match_dup 1))
3804    (set (match_dup 0)
3805         (match_op_dup 3
3806          [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3807   "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3808      FAIL;
3809   "
3812 (define_expand "extendqihi2"
3813   [(set (match_dup 2)
3814         (ashift:SI (match_operand:QI 1 "general_operand" "")
3815                    (const_int 24)))
3816    (set (match_operand:HI 0 "s_register_operand" "")
3817         (ashiftrt:SI (match_dup 2)
3818                      (const_int 24)))]
3819   "TARGET_ARM"
3820   "
3821   {
3822     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3823       {
3824         emit_insn (gen_rtx_SET (VOIDmode,
3825                                 operands[0],
3826                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3827         DONE;
3828       }
3829     if (!s_register_operand (operands[1], QImode))
3830       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3831     operands[0] = gen_lowpart (SImode, operands[0]);
3832     operands[1] = gen_lowpart (SImode, operands[1]);
3833     operands[2] = gen_reg_rtx (SImode);
3834   }"
3837 (define_insn "*extendqihi_insn"
3838   [(set (match_operand:HI 0 "s_register_operand" "=r")
3839         (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3840   "TARGET_ARM && arm_arch4"
3841   "ldr%?sb\\t%0, %1"
3842   [(set_attr "type" "load_byte")
3843    (set_attr "predicable" "yes")
3844    (set_attr "pool_range" "256")
3845    (set_attr "neg_pool_range" "244")]
3848 (define_expand "extendqisi2"
3849   [(set (match_dup 2)
3850         (ashift:SI (match_operand:QI 1 "general_operand" "")
3851                    (const_int 24)))
3852    (set (match_operand:SI 0 "s_register_operand" "")
3853         (ashiftrt:SI (match_dup 2)
3854                      (const_int 24)))]
3855   "TARGET_EITHER"
3856   "
3857   {
3858     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3859       {
3860         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3861                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3862         DONE;
3863       }
3865     if (!s_register_operand (operands[1], QImode))
3866       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3868     if (arm_arch6)
3869       {
3870         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3871                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3872         DONE;
3873       }
3875     operands[1] = gen_lowpart (SImode, operands[1]);
3876     operands[2] = gen_reg_rtx (SImode);
3877   }"
3880 (define_insn "*arm_extendqisi"
3881   [(set (match_operand:SI 0 "s_register_operand" "=r")
3882         (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3883   "TARGET_ARM && arm_arch4 && !arm_arch6"
3884   "ldr%?sb\\t%0, %1"
3885   [(set_attr "type" "load_byte")
3886    (set_attr "predicable" "yes")
3887    (set_attr "pool_range" "256")
3888    (set_attr "neg_pool_range" "244")]
3891 (define_insn "*arm_extendqisi_v6"
3892   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3893         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3894   "TARGET_ARM && arm_arch6"
3895   "@
3896    sxtb%?\\t%0, %1
3897    ldr%?sb\\t%0, %1"
3898   [(set_attr "type" "alu_shift,load_byte")
3899    (set_attr "predicable" "yes")
3900    (set_attr "pool_range" "*,256")
3901    (set_attr "neg_pool_range" "*,244")]
3904 (define_insn "*arm_extendqisi2addsi"
3905   [(set (match_operand:SI 0 "s_register_operand" "=r")
3906         (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3907                  (match_operand:SI 2 "s_register_operand" "r")))]
3908   "TARGET_ARM && arm_arch6"
3909   "sxtab%?\\t%0, %2, %1"
3910   [(set_attr "type" "alu_shift")
3911    (set_attr "predicable" "yes")]
3914 (define_insn "*thumb_extendqisi2"
3915   [(set (match_operand:SI 0 "register_operand" "=l,l")
3916         (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3917   "TARGET_THUMB && !arm_arch6"
3918   "*
3919   {
3920     rtx ops[3];
3921     rtx mem = XEXP (operands[1], 0);
3922     
3923     if (GET_CODE (mem) == CONST)
3924       mem = XEXP (mem, 0);
3925     
3926     if (GET_CODE (mem) == LABEL_REF)
3927       return \"ldr\\t%0, %1\";
3929     if (GET_CODE (mem) == PLUS
3930         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3931       return \"ldr\\t%0, %1\";
3932       
3933     if (which_alternative == 0)
3934       return \"ldrsb\\t%0, %1\";
3935       
3936     ops[0] = operands[0];
3937     
3938     if (GET_CODE (mem) == PLUS)
3939       {
3940         rtx a = XEXP (mem, 0);
3941         rtx b = XEXP (mem, 1);
3942         
3943         ops[1] = a;
3944         ops[2] = b;
3946         if (GET_CODE (a) == REG)
3947           {
3948             if (GET_CODE (b) == REG)
3949               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3950             else if (REGNO (a) == REGNO (ops[0]))
3951               {
3952                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3953                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3954                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3955               }
3956             else
3957               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3958           }
3959         else if (GET_CODE (b) != REG)
3960           abort ();
3961         else
3962           {
3963             if (REGNO (b) == REGNO (ops[0]))
3964               {
3965                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3966                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3967                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3968               }
3969             else
3970               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3971           }
3972       }
3973     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3974       {
3975         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3976         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3977         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3978       }
3979     else
3980       {
3981         ops[1] = mem;
3982         ops[2] = const0_rtx;
3983         
3984         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3985       }
3986     return \"\";
3987   }"
3988   [(set_attr "length" "2,6")
3989    (set_attr "type" "load_byte,load_byte")
3990    (set_attr "pool_range" "32,32")]
3993 (define_insn "*thumb_extendqisi2_v6"
3994   [(set (match_operand:SI 0 "register_operand" "=l,l,l")
3995         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
3996   "TARGET_THUMB && arm_arch6"
3997   "*
3998   {
3999     rtx ops[3];
4000     rtx mem;
4002     if (which_alternative == 0)
4003       return \"sxtb\\t%0, %1\";
4005     mem = XEXP (operands[1], 0);
4006     
4007     if (GET_CODE (mem) == CONST)
4008       mem = XEXP (mem, 0);
4009     
4010     if (GET_CODE (mem) == LABEL_REF)
4011       return \"ldr\\t%0, %1\";
4013     if (GET_CODE (mem) == PLUS
4014         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4015       return \"ldr\\t%0, %1\";
4016       
4017     if (which_alternative == 0)
4018       return \"ldrsb\\t%0, %1\";
4019       
4020     ops[0] = operands[0];
4021     
4022     if (GET_CODE (mem) == PLUS)
4023       {
4024         rtx a = XEXP (mem, 0);
4025         rtx b = XEXP (mem, 1);
4026         
4027         ops[1] = a;
4028         ops[2] = b;
4030         if (GET_CODE (a) == REG)
4031           {
4032             if (GET_CODE (b) == REG)
4033               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4034             else if (REGNO (a) == REGNO (ops[0]))
4035               {
4036                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4037                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4038               }
4039             else
4040               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4041           }
4042         else if (GET_CODE (b) != REG)
4043           abort ();
4044         else
4045           {
4046             if (REGNO (b) == REGNO (ops[0]))
4047               {
4048                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4049                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4050               }
4051             else
4052               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4053           }
4054       }
4055     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4056       {
4057         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4058         output_asm_insn (\"sxtb\\t%0, %0\", ops);
4059       }
4060     else
4061       {
4062         ops[1] = mem;
4063         ops[2] = const0_rtx;
4064         
4065         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4066       }
4067     return \"\";
4068   }"
4069   [(set_attr "length" "2,2,4")
4070    (set_attr "type" "alu_shift,load_byte,load_byte")
4071    (set_attr "pool_range" "*,32,32")]
4074 (define_expand "extendsfdf2"
4075   [(set (match_operand:DF                  0 "s_register_operand" "")
4076         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
4077   "TARGET_ARM && TARGET_HARD_FLOAT"
4078   ""
4081 ;; Move insns (including loads and stores)
4083 ;; XXX Just some ideas about movti.
4084 ;; I don't think these are a good idea on the arm, there just aren't enough
4085 ;; registers
4086 ;;(define_expand "loadti"
4087 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
4088 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
4089 ;;  "" "")
4091 ;;(define_expand "storeti"
4092 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4093 ;;      (match_operand:TI 1 "s_register_operand" ""))]
4094 ;;  "" "")
4096 ;;(define_expand "movti"
4097 ;;  [(set (match_operand:TI 0 "general_operand" "")
4098 ;;      (match_operand:TI 1 "general_operand" ""))]
4099 ;;  ""
4100 ;;  "
4102 ;;  rtx insn;
4104 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4105 ;;    operands[1] = copy_to_reg (operands[1]);
4106 ;;  if (GET_CODE (operands[0]) == MEM)
4107 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4108 ;;  else if (GET_CODE (operands[1]) == MEM)
4109 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4110 ;;  else
4111 ;;    FAIL;
4113 ;;  emit_insn (insn);
4114 ;;  DONE;
4115 ;;}")
4117 ;; Recognize garbage generated above.
4119 ;;(define_insn ""
4120 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4121 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4122 ;;  ""
4123 ;;  "*
4124 ;;  {
4125 ;;    register mem = (which_alternative < 3);
4126 ;;    register const char *template;
4128 ;;    operands[mem] = XEXP (operands[mem], 0);
4129 ;;    switch (which_alternative)
4130 ;;      {
4131 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4132 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
4133 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
4134 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
4135 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
4136 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
4137 ;;      }
4138 ;;    output_asm_insn (template, operands);
4139 ;;    return \"\";
4140 ;;  }")
4142 (define_expand "movdi"
4143   [(set (match_operand:DI 0 "general_operand" "")
4144         (match_operand:DI 1 "general_operand" ""))]
4145   "TARGET_EITHER"
4146   "
4147   if (TARGET_THUMB)
4148     {
4149       if (!no_new_pseudos)
4150         {
4151           if (GET_CODE (operands[0]) != REG)
4152             operands[1] = force_reg (DImode, operands[1]);
4153         }
4154     }
4155   "
4158 (define_insn "*arm_movdi"
4159   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r ,m")
4160         (match_operand:DI 1 "di_operand"              "rIK,mi,r"))]
4161   "TARGET_ARM
4162   && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4163   && !TARGET_IWMMXT"
4164   "*
4165   return (output_move_double (operands));
4166   "
4167   [(set_attr "length" "8")
4168    (set_attr "type" "*,load2,store2")
4169    (set_attr "pool_range" "*,1020,*")
4170    (set_attr "neg_pool_range" "*,1008,*")]
4173 ;; We can't actually do base+index doubleword loads if the index and
4174 ;; destination overlap.  Split here so that we at least have chance to
4175 ;; schedule.
4176 (define_split
4177   [(set (match_operand:DI 0 "s_register_operand" "")
4178         (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4179                          (match_operand:SI 2 "s_register_operand" ""))))]
4180   "TARGET_LDRD
4181   && reg_overlap_mentioned_p (operands[0], operands[1])
4182   && reg_overlap_mentioned_p (operands[0], operands[2])"
4183   [(set (match_dup 4)
4184         (plus:SI (match_dup 1)
4185                  (match_dup 2)))
4186    (set (match_dup 0)
4187         (mem:DI (match_dup 4)))]
4188   "
4189   operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4190   "
4193 ;;; ??? This should have alternatives for constants.
4194 ;;; ??? This was originally identical to the movdf_insn pattern.
4195 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4196 ;;; thumb_reorg with a memory reference.
4197 (define_insn "*thumb_movdi_insn"
4198   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4199         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
4200   "TARGET_THUMB
4201    && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4202    && (   register_operand (operands[0], DImode)
4203        || register_operand (operands[1], DImode))"
4204   "*
4205   {
4206   switch (which_alternative)
4207     {
4208     default:
4209     case 0:
4210       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4211         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
4212       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
4213     case 1:
4214       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4215     case 2:
4216       operands[1] = GEN_INT (- INTVAL (operands[1]));
4217       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4218     case 3:
4219       return \"ldmia\\t%1, {%0, %H0}\";
4220     case 4:
4221       return \"stmia\\t%0, {%1, %H1}\";
4222     case 5:
4223       return thumb_load_double_from_address (operands);
4224     case 6:
4225       operands[2] = gen_rtx_MEM (SImode,
4226                              plus_constant (XEXP (operands[0], 0), 4));
4227       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4228       return \"\";
4229     case 7:
4230       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4231         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4232       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4233     }
4234   }"
4235   [(set_attr "length" "4,4,6,2,2,6,4,4")
4236    (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4237    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4240 (define_expand "movsi"
4241   [(set (match_operand:SI 0 "general_operand" "")
4242         (match_operand:SI 1 "general_operand" ""))]
4243   "TARGET_EITHER"
4244   "
4245   if (TARGET_ARM)
4246     {
4247       /* Everything except mem = const or mem = mem can be done easily.  */
4248       if (GET_CODE (operands[0]) == MEM)
4249         operands[1] = force_reg (SImode, operands[1]);
4250       if (arm_general_register_operand (operands[0], SImode)
4251           && GET_CODE (operands[1]) == CONST_INT
4252           && !(const_ok_for_arm (INTVAL (operands[1]))
4253                || const_ok_for_arm (~INTVAL (operands[1]))))
4254         {
4255            arm_split_constant (SET, SImode, NULL_RTX,
4256                                INTVAL (operands[1]), operands[0], NULL_RTX,
4257                                optimize && !no_new_pseudos);
4258           DONE;
4259         }
4260     }
4261   else /* TARGET_THUMB....  */
4262     {
4263       if (!no_new_pseudos)
4264         {
4265           if (GET_CODE (operands[0]) != REG)
4266             operands[1] = force_reg (SImode, operands[1]);
4267         }
4268     }
4269     
4270   if (flag_pic
4271       && (CONSTANT_P (operands[1])
4272          || symbol_mentioned_p (operands[1])
4273          || label_mentioned_p (operands[1])))
4274     operands[1] = legitimize_pic_address (operands[1], SImode,
4275                                           (no_new_pseudos ? operands[0] : 0));
4276   "
4279 (define_insn "*arm_movsi_insn"
4280   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4281         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
4282   "TARGET_ARM && ! TARGET_IWMMXT
4283    && !(TARGET_HARD_FLOAT && TARGET_VFP)
4284    && (   register_operand (operands[0], SImode)
4285        || register_operand (operands[1], SImode))"
4286   "@
4287    mov%?\\t%0, %1
4288    mvn%?\\t%0, #%B1
4289    ldr%?\\t%0, %1
4290    str%?\\t%1, %0"
4291   [(set_attr "type" "*,*,load1,store1")
4292    (set_attr "predicable" "yes")
4293    (set_attr "pool_range" "*,*,4096,*")
4294    (set_attr "neg_pool_range" "*,*,4084,*")]
4297 (define_split
4298   [(set (match_operand:SI 0 "arm_general_register_operand" "")
4299         (match_operand:SI 1 "const_int_operand" ""))]
4300   "TARGET_ARM
4301   && (!(const_ok_for_arm (INTVAL (operands[1]))
4302         || const_ok_for_arm (~INTVAL (operands[1]))))"
4303   [(clobber (const_int 0))]
4304   "
4305   arm_split_constant (SET, SImode, NULL_RTX, 
4306                       INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4307   DONE;
4308   "
4311 (define_insn "*thumb_movsi_insn"
4312   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4313         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4314   "TARGET_THUMB
4315    && (   register_operand (operands[0], SImode) 
4316        || register_operand (operands[1], SImode))"
4317   "@
4318    mov  %0, %1
4319    mov  %0, %1
4320    #
4321    #
4322    ldmia\\t%1, {%0}
4323    stmia\\t%0, {%1}
4324    ldr\\t%0, %1
4325    str\\t%1, %0
4326    mov\\t%0, %1"
4327   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4328    (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4329    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4332 (define_split 
4333   [(set (match_operand:SI 0 "register_operand" "")
4334         (match_operand:SI 1 "const_int_operand" ""))]
4335   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4336   [(set (match_dup 0) (match_dup 1))
4337    (set (match_dup 0) (neg:SI (match_dup 0)))]
4338   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4341 (define_split 
4342   [(set (match_operand:SI 0 "register_operand" "")
4343         (match_operand:SI 1 "const_int_operand" ""))]
4344   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4345   [(set (match_dup 0) (match_dup 1))
4346    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4347   "
4348   {
4349     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4350     unsigned HOST_WIDE_INT mask = 0xff;
4351     int i;
4352     
4353     for (i = 0; i < 25; i++)
4354       if ((val & (mask << i)) == val)
4355         break;
4357     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4358     if (i == 0)
4359       FAIL;
4361     operands[1] = GEN_INT (val >> i);
4362     operands[2] = GEN_INT (i);
4363   }"
4366 ;; When generating pic, we need to load the symbol offset into a register.
4367 ;; So that the optimizer does not confuse this with a normal symbol load
4368 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
4369 ;; since that is the only type of relocation we can use.
4371 ;; The rather odd constraints on the following are to force reload to leave
4372 ;; the insn alone, and to force the minipool generation pass to then move
4373 ;; the GOT symbol to memory.
4375 (define_insn "pic_load_addr_arm"
4376   [(set (match_operand:SI 0 "s_register_operand" "=r")
4377         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4378   "TARGET_ARM && flag_pic"
4379   "ldr%?\\t%0, %1"
4380   [(set_attr "type" "load1")
4381    (set (attr "pool_range")     (const_int 4096))
4382    (set (attr "neg_pool_range") (const_int 4084))]
4385 (define_insn "pic_load_addr_thumb"
4386   [(set (match_operand:SI 0 "s_register_operand" "=l")
4387         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4388   "TARGET_THUMB && flag_pic"
4389   "ldr\\t%0, %1"
4390   [(set_attr "type" "load1")
4391    (set (attr "pool_range") (const_int 1024))]
4394 ;; This variant is used for AOF assembly, since it needs to mention the
4395 ;; pic register in the rtl.
4396 (define_expand "pic_load_addr_based"
4397   [(set (match_operand:SI 0 "s_register_operand" "")
4398         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4399   "TARGET_ARM && flag_pic"
4400   "operands[2] = pic_offset_table_rtx;"
4403 (define_insn "*pic_load_addr_based_insn"
4404   [(set (match_operand:SI 0 "s_register_operand" "=r")
4405         (unspec:SI [(match_operand 1 "" "")
4406                     (match_operand 2 "s_register_operand" "r")]
4407                    UNSPEC_PIC_SYM))]
4408   "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4409   "*
4410 #ifdef AOF_ASSEMBLER
4411   operands[1] = aof_pic_entry (operands[1]);
4412 #endif
4413   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4414   return \"\";
4415   "
4416   [(set_attr "type" "load1")
4417    (set (attr "pool_range")
4418         (if_then_else (eq_attr "is_thumb" "yes")
4419                       (const_int 1024)
4420                       (const_int 4096)))
4421    (set (attr "neg_pool_range")
4422         (if_then_else (eq_attr "is_thumb" "yes")
4423                       (const_int 0)
4424                       (const_int 4084)))]
4427 (define_insn "pic_add_dot_plus_four"
4428   [(set (match_operand:SI 0 "register_operand" "+r")
4429         (unspec:SI [(plus:SI (match_dup 0)
4430                              (const (plus:SI (pc) (const_int 4))))]
4431                    UNSPEC_PIC_BASE))
4432    (use (label_ref (match_operand 1 "" "")))]
4433   "TARGET_THUMB && flag_pic"
4434   "*
4435   (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4436                              CODE_LABEL_NUMBER (operands[1]));
4437   return \"add\\t%0, %|pc\";
4438   "
4439   [(set_attr "length" "2")]
4442 (define_insn "pic_add_dot_plus_eight"
4443   [(set (match_operand:SI 0 "register_operand" "+r")
4444         (unspec:SI [(plus:SI (match_dup 0)
4445                              (const (plus:SI (pc) (const_int 8))))]
4446                    UNSPEC_PIC_BASE))
4447    (use (label_ref (match_operand 1 "" "")))]
4448   "TARGET_ARM && flag_pic"
4449   "*
4450     (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4451                                CODE_LABEL_NUMBER (operands[1]));
4452     return \"add%?\\t%0, %|pc, %0\";
4453   "
4454   [(set_attr "predicable" "yes")]
4457 (define_expand "builtin_setjmp_receiver"
4458   [(label_ref (match_operand 0 "" ""))]
4459   "flag_pic"
4460   "
4462   arm_load_pic_register ();
4463   DONE;
4466 ;; If copying one reg to another we can set the condition codes according to
4467 ;; its value.  Such a move is common after a return from subroutine and the
4468 ;; result is being tested against zero.
4470 (define_insn "*movsi_compare0"
4471   [(set (reg:CC CC_REGNUM)
4472         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4473                     (const_int 0)))
4474    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4475         (match_dup 1))]
4476   "TARGET_ARM"
4477   "@
4478    cmp%?\\t%0, #0
4479    sub%?s\\t%0, %1, #0"
4480   [(set_attr "conds" "set")]
4483 ;; Subroutine to store a half word from a register into memory.
4484 ;; Operand 0 is the source register (HImode)
4485 ;; Operand 1 is the destination address in a register (SImode)
4487 ;; In both this routine and the next, we must be careful not to spill
4488 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4489 ;; can generate unrecognizable rtl.
4491 (define_expand "storehi"
4492   [;; store the low byte
4493    (set (match_operand 1 "" "") (match_dup 3))
4494    ;; extract the high byte
4495    (set (match_dup 2)
4496         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4497    ;; store the high byte
4498    (set (match_dup 4) (match_dup 5))]
4499   "TARGET_ARM"
4500   "
4501   {
4502     rtx op1 = operands[1];
4503     rtx addr = XEXP (op1, 0);
4504     enum rtx_code code = GET_CODE (addr);
4506     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4507         || code == MINUS)
4508       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4510     operands[4] = adjust_address (op1, QImode, 1);
4511     operands[1] = adjust_address (operands[1], QImode, 0);
4512     operands[3] = gen_lowpart (QImode, operands[0]);
4513     operands[0] = gen_lowpart (SImode, operands[0]);
4514     operands[2] = gen_reg_rtx (SImode);
4515     operands[5] = gen_lowpart (QImode, operands[2]);
4516   }"
4519 (define_expand "storehi_bigend"
4520   [(set (match_dup 4) (match_dup 3))
4521    (set (match_dup 2)
4522         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4523    (set (match_operand 1 "" "") (match_dup 5))]
4524   "TARGET_ARM"
4525   "
4526   {
4527     rtx op1 = operands[1];
4528     rtx addr = XEXP (op1, 0);
4529     enum rtx_code code = GET_CODE (addr);
4531     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4532         || code == MINUS)
4533       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4535     operands[4] = adjust_address (op1, QImode, 1);
4536     operands[1] = adjust_address (operands[1], QImode, 0);
4537     operands[3] = gen_lowpart (QImode, operands[0]);
4538     operands[0] = gen_lowpart (SImode, operands[0]);
4539     operands[2] = gen_reg_rtx (SImode);
4540     operands[5] = gen_lowpart (QImode, operands[2]);
4541   }"
4544 ;; Subroutine to store a half word integer constant into memory.
4545 (define_expand "storeinthi"
4546   [(set (match_operand 0 "" "")
4547         (match_operand 1 "" ""))
4548    (set (match_dup 3) (match_dup 2))]
4549   "TARGET_ARM"
4550   "
4551   {
4552     HOST_WIDE_INT value = INTVAL (operands[1]);
4553     rtx addr = XEXP (operands[0], 0);
4554     rtx op0 = operands[0];
4555     enum rtx_code code = GET_CODE (addr);
4557     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4558         || code == MINUS)
4559       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4561     operands[1] = gen_reg_rtx (SImode);
4562     if (BYTES_BIG_ENDIAN)
4563       {
4564         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4565         if ((value & 255) == ((value >> 8) & 255))
4566           operands[2] = operands[1];
4567         else
4568           {
4569             operands[2] = gen_reg_rtx (SImode);
4570             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4571           }
4572       }
4573     else
4574       {
4575         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4576         if ((value & 255) == ((value >> 8) & 255))
4577           operands[2] = operands[1];
4578         else
4579           {
4580             operands[2] = gen_reg_rtx (SImode);
4581             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4582           }
4583       }
4585     operands[3] = adjust_address (op0, QImode, 1);
4586     operands[0] = adjust_address (operands[0], QImode, 0);
4587     operands[2] = gen_lowpart (QImode, operands[2]);
4588     operands[1] = gen_lowpart (QImode, operands[1]);
4589   }"
4592 (define_expand "storehi_single_op"
4593   [(set (match_operand:HI 0 "memory_operand" "")
4594         (match_operand:HI 1 "general_operand" ""))]
4595   "TARGET_ARM && arm_arch4"
4596   "
4597   if (!s_register_operand (operands[1], HImode))
4598     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4599   "
4602 (define_expand "movhi"
4603   [(set (match_operand:HI 0 "general_operand" "")
4604         (match_operand:HI 1 "general_operand" ""))]
4605   "TARGET_EITHER"
4606   "
4607   if (TARGET_ARM)
4608     {
4609       if (!no_new_pseudos)
4610         {
4611           if (GET_CODE (operands[0]) == MEM)
4612             {
4613               if (arm_arch4)
4614                 {
4615                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4616                   DONE;
4617                 }
4618               if (GET_CODE (operands[1]) == CONST_INT)
4619                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4620               else
4621                 {
4622                   if (GET_CODE (operands[1]) == MEM)
4623                     operands[1] = force_reg (HImode, operands[1]);
4624                   if (BYTES_BIG_ENDIAN)
4625                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4626                   else
4627                    emit_insn (gen_storehi (operands[1], operands[0]));
4628                 }
4629               DONE;
4630             }
4631           /* Sign extend a constant, and keep it in an SImode reg.  */
4632           else if (GET_CODE (operands[1]) == CONST_INT)
4633             {
4634               rtx reg = gen_reg_rtx (SImode);
4635               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4637               /* If the constant is already valid, leave it alone.  */
4638               if (!const_ok_for_arm (val))
4639                 {
4640                   /* If setting all the top bits will make the constant 
4641                      loadable in a single instruction, then set them.  
4642                      Otherwise, sign extend the number.  */
4644                   if (const_ok_for_arm (~(val | ~0xffff)))
4645                     val |= ~0xffff;
4646                   else if (val & 0x8000)
4647                     val |= ~0xffff;
4648                 }
4650               emit_insn (gen_movsi (reg, GEN_INT (val)));
4651               operands[1] = gen_lowpart (HImode, reg);
4652             }
4653           else if (arm_arch4 && optimize && !no_new_pseudos
4654                    && GET_CODE (operands[1]) == MEM)
4655             {
4656               rtx reg = gen_reg_rtx (SImode);
4658               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4659               operands[1] = gen_lowpart (HImode, reg);
4660             }
4661           else if (!arm_arch4)
4662             {
4663               if (GET_CODE (operands[1]) == MEM)
4664                 {
4665                   rtx base;
4666                   rtx offset = const0_rtx;
4667                   rtx reg = gen_reg_rtx (SImode);
4669                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4670                        || (GET_CODE (base) == PLUS
4671                            && (GET_CODE (offset = XEXP (base, 1))
4672                                == CONST_INT)
4673                            && ((INTVAL(offset) & 1) != 1)
4674                            && GET_CODE (base = XEXP (base, 0)) == REG))
4675                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4676                     {
4677                       HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4678                       rtx new;
4680                       new = gen_rtx_MEM (SImode,
4681                                          plus_constant (base, new_offset));
4682                       MEM_COPY_ATTRIBUTES (new, operands[1]);
4683                       emit_insn (gen_movsi (reg, new));
4684                       if (((INTVAL (offset) & 2) != 0)
4685                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4686                         {
4687                           rtx reg2 = gen_reg_rtx (SImode);
4689                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4690                           reg = reg2;
4691                         }
4692                     }
4693                   else
4694                     emit_insn (gen_movhi_bytes (reg, operands[1]));
4696                   operands[1] = gen_lowpart (HImode, reg);
4697                }
4698            }
4699         }
4700       /* Handle loading a large integer during reload.  */
4701       else if (GET_CODE (operands[1]) == CONST_INT
4702                && !const_ok_for_arm (INTVAL (operands[1]))
4703                && !const_ok_for_arm (~INTVAL (operands[1])))
4704         {
4705           /* Writing a constant to memory needs a scratch, which should
4706              be handled with SECONDARY_RELOADs.  */
4707           if (GET_CODE (operands[0]) != REG)
4708             abort ();
4710           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4711           emit_insn (gen_movsi (operands[0], operands[1]));
4712           DONE;
4713        }
4714     }
4715   else /* TARGET_THUMB */
4716     {
4717       if (!no_new_pseudos)
4718         {
4719           if (GET_CODE (operands[0]) != REG)
4720             operands[1] = force_reg (HImode, operands[1]);
4722           /* ??? We shouldn't really get invalid addresses here, but this can
4723              happen if we are passed a SP (never OK for HImode/QImode) or 
4724              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4725              HImode/QImode) relative address.  */
4726           /* ??? This should perhaps be fixed elsewhere, for instance, in
4727              fixup_stack_1, by checking for other kinds of invalid addresses,
4728              e.g. a bare reference to a virtual register.  This may confuse the
4729              alpha though, which must handle this case differently.  */
4730           if (GET_CODE (operands[0]) == MEM
4731               && !memory_address_p (GET_MODE (operands[0]),
4732                                     XEXP (operands[0], 0)))
4733             operands[0]
4734               = replace_equiv_address (operands[0],
4735                                        copy_to_reg (XEXP (operands[0], 0)));
4736    
4737           if (GET_CODE (operands[1]) == MEM
4738               && !memory_address_p (GET_MODE (operands[1]),
4739                                     XEXP (operands[1], 0)))
4740             operands[1]
4741               = replace_equiv_address (operands[1],
4742                                        copy_to_reg (XEXP (operands[1], 0)));
4743         }
4744       /* Handle loading a large integer during reload.  */
4745       else if (GET_CODE (operands[1]) == CONST_INT
4746                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4747         {
4748           /* Writing a constant to memory needs a scratch, which should
4749              be handled with SECONDARY_RELOADs.  */
4750           if (GET_CODE (operands[0]) != REG)
4751             abort ();
4753           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4754           emit_insn (gen_movsi (operands[0], operands[1]));
4755           DONE;
4756         }
4757     }
4758   "
4761 (define_insn "*thumb_movhi_insn"
4762   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4763         (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
4764   "TARGET_THUMB
4765    && (   register_operand (operands[0], HImode)
4766        || register_operand (operands[1], HImode))"
4767   "*
4768   switch (which_alternative)
4769     {
4770     case 0: return \"add        %0, %1, #0\";
4771     case 2: return \"strh       %1, %0\";
4772     case 3: return \"mov        %0, %1\";
4773     case 4: return \"mov        %0, %1\";
4774     case 5: return \"mov        %0, %1\";
4775     default: abort ();
4776     case 1:
4777       /* The stack pointer can end up being taken as an index register.
4778           Catch this case here and deal with it.  */
4779       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4780           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4781           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4782         {
4783           rtx ops[2];
4784           ops[0] = operands[0];
4785           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4786       
4787           output_asm_insn (\"mov        %0, %1\", ops);
4789           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4790     
4791         }
4792       return \"ldrh     %0, %1\";
4793     }"
4794   [(set_attr "length" "2,4,2,2,2,2")
4795    (set_attr "type" "*,load1,store1,*,*,*")]
4799 (define_expand "movhi_bytes"
4800   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4801    (set (match_dup 3)
4802         (zero_extend:SI (match_dup 6)))
4803    (set (match_operand:SI 0 "" "")
4804          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4805   "TARGET_ARM"
4806   "
4807   {
4808     rtx mem1, mem2;
4809     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4811     mem1 = gen_rtx_MEM (QImode, addr);
4812     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4813     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4814     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4815     operands[0] = gen_lowpart (SImode, operands[0]);
4816     operands[1] = mem1;
4817     operands[2] = gen_reg_rtx (SImode);
4818     operands[3] = gen_reg_rtx (SImode);
4819     operands[6] = mem2;
4821     if (BYTES_BIG_ENDIAN)
4822       {
4823         operands[4] = operands[2];
4824         operands[5] = operands[3];
4825       }
4826     else
4827       {
4828         operands[4] = operands[3];
4829         operands[5] = operands[2];
4830       }
4831   }"
4834 (define_expand "movhi_bigend"
4835   [(set (match_dup 2)
4836         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4837                    (const_int 16)))
4838    (set (match_dup 3)
4839         (ashiftrt:SI (match_dup 2) (const_int 16)))
4840    (set (match_operand:HI 0 "s_register_operand" "")
4841         (match_dup 4))]
4842   "TARGET_ARM"
4843   "
4844   operands[2] = gen_reg_rtx (SImode);
4845   operands[3] = gen_reg_rtx (SImode);
4846   operands[4] = gen_lowpart (HImode, operands[3]);
4847   "
4850 ;; Pattern to recognize insn generated default case above
4851 (define_insn "*movhi_insn_arch4"
4852   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4853         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4854   "TARGET_ARM
4855    && arm_arch4
4856    && (GET_CODE (operands[1]) != CONST_INT
4857        || const_ok_for_arm (INTVAL (operands[1]))
4858        || const_ok_for_arm (~INTVAL (operands[1])))"
4859   "@
4860    mov%?\\t%0, %1\\t%@ movhi
4861    mvn%?\\t%0, #%B1\\t%@ movhi
4862    str%?h\\t%1, %0\\t%@ movhi 
4863    ldr%?h\\t%0, %1\\t%@ movhi"
4864   [(set_attr "type" "*,*,store1,load1")
4865    (set_attr "predicable" "yes")
4866    (set_attr "pool_range" "*,*,*,256")
4867    (set_attr "neg_pool_range" "*,*,*,244")]
4870 (define_insn "*movhi_bytes"
4871   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4872         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4873   "TARGET_ARM"
4874   "@
4875    mov%?\\t%0, %1\\t%@ movhi
4876    mvn%?\\t%0, #%B1\\t%@ movhi"
4877   [(set_attr "predicable" "yes")]
4880 (define_insn "thumb_movhi_clobber"
4881   [(set (match_operand:HI     0 "memory_operand"   "=m")
4882         (match_operand:HI     1 "register_operand" "l"))
4883    (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4884   "TARGET_THUMB"
4885   "*
4886   abort ();"
4888         
4889 ;; We use a DImode scratch because we may occasionally need an additional
4890 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4891 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4892 (define_expand "reload_outhi"
4893   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4894               (match_operand:HI 1 "s_register_operand"        "r")
4895               (match_operand:DI 2 "s_register_operand"        "=&l")])]
4896   "TARGET_EITHER"
4897   "if (TARGET_ARM)
4898      arm_reload_out_hi (operands);
4899    else
4900      thumb_reload_out_hi (operands);
4901   DONE;
4902   "
4905 (define_expand "reload_inhi"
4906   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4907               (match_operand:HI 1 "arm_reload_memory_operand" "o")
4908               (match_operand:DI 2 "s_register_operand" "=&r")])]
4909   "TARGET_EITHER"
4910   "
4911   if (TARGET_ARM)
4912     arm_reload_in_hi (operands);
4913   else
4914     thumb_reload_out_hi (operands);
4915   DONE;
4918 (define_expand "movqi"
4919   [(set (match_operand:QI 0 "general_operand" "")
4920         (match_operand:QI 1 "general_operand" ""))]
4921   "TARGET_EITHER"
4922   "
4923   if (TARGET_ARM)
4924     {
4925       /* Everything except mem = const or mem = mem can be done easily */
4927       if (!no_new_pseudos)
4928         {
4929           if (GET_CODE (operands[1]) == CONST_INT)
4930             {
4931               rtx reg = gen_reg_rtx (SImode);
4933               emit_insn (gen_movsi (reg, operands[1]));
4934               operands[1] = gen_lowpart (QImode, reg);
4935             }
4936           if (GET_CODE (operands[1]) == MEM && optimize > 0)
4937             {
4938               rtx reg = gen_reg_rtx (SImode);
4940               emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4941               operands[1] = gen_lowpart (QImode, reg);
4942             }
4943           if (GET_CODE (operands[0]) == MEM)
4944             operands[1] = force_reg (QImode, operands[1]);
4945         }
4946     }
4947   else /* TARGET_THUMB */
4948     {
4949       if (!no_new_pseudos)
4950         {
4951           if (GET_CODE (operands[0]) != REG)
4952             operands[1] = force_reg (QImode, operands[1]);
4954           /* ??? We shouldn't really get invalid addresses here, but this can
4955              happen if we are passed a SP (never OK for HImode/QImode) or
4956              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4957              HImode/QImode) relative address.  */
4958           /* ??? This should perhaps be fixed elsewhere, for instance, in
4959              fixup_stack_1, by checking for other kinds of invalid addresses,
4960              e.g. a bare reference to a virtual register.  This may confuse the
4961              alpha though, which must handle this case differently.  */
4962           if (GET_CODE (operands[0]) == MEM
4963               && !memory_address_p (GET_MODE (operands[0]),
4964                                      XEXP (operands[0], 0)))
4965             operands[0]
4966               = replace_equiv_address (operands[0],
4967                                        copy_to_reg (XEXP (operands[0], 0)));
4968           if (GET_CODE (operands[1]) == MEM
4969               && !memory_address_p (GET_MODE (operands[1]),
4970                                     XEXP (operands[1], 0)))
4971              operands[1]
4972                = replace_equiv_address (operands[1],
4973                                         copy_to_reg (XEXP (operands[1], 0)));
4974         }
4975       /* Handle loading a large integer during reload.  */
4976       else if (GET_CODE (operands[1]) == CONST_INT
4977                && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4978         {
4979           /* Writing a constant to memory needs a scratch, which should
4980              be handled with SECONDARY_RELOADs.  */
4981           if (GET_CODE (operands[0]) != REG)
4982             abort ();
4984           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4985           emit_insn (gen_movsi (operands[0], operands[1]));
4986           DONE;
4987        }
4988     }
4989   "
4993 (define_insn "*arm_movqi_insn"
4994   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4995         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4996   "TARGET_ARM
4997    && (   register_operand (operands[0], QImode)
4998        || register_operand (operands[1], QImode))"
4999   "@
5000    mov%?\\t%0, %1
5001    mvn%?\\t%0, #%B1
5002    ldr%?b\\t%0, %1
5003    str%?b\\t%1, %0"
5004   [(set_attr "type" "*,*,load1,store1")
5005    (set_attr "predicable" "yes")]
5008 (define_insn "*thumb_movqi_insn"
5009   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5010         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
5011   "TARGET_THUMB
5012    && (   register_operand (operands[0], QImode)
5013        || register_operand (operands[1], QImode))"
5014   "@
5015    add\\t%0, %1, #0
5016    ldrb\\t%0, %1
5017    strb\\t%1, %0
5018    mov\\t%0, %1
5019    mov\\t%0, %1
5020    mov\\t%0, %1"
5021   [(set_attr "length" "2")
5022    (set_attr "type" "*,load1,store1,*,*,*")
5023    (set_attr "pool_range" "*,32,*,*,*,*")]
5026 (define_expand "movsf"
5027   [(set (match_operand:SF 0 "general_operand" "")
5028         (match_operand:SF 1 "general_operand" ""))]
5029   "TARGET_EITHER"
5030   "
5031   if (TARGET_ARM)
5032     {
5033       if (GET_CODE (operands[0]) == MEM)
5034         operands[1] = force_reg (SFmode, operands[1]);
5035     }
5036   else /* TARGET_THUMB */
5037     {
5038       if (!no_new_pseudos)
5039         {
5040            if (GET_CODE (operands[0]) != REG)
5041              operands[1] = force_reg (SFmode, operands[1]);
5042         }
5043     }
5044   "
5047 (define_split
5048   [(set (match_operand:SF 0 "nonimmediate_operand" "")
5049         (match_operand:SF 1 "immediate_operand" ""))]
5050   "TARGET_ARM
5051    && !(TARGET_HARD_FLOAT && TARGET_FPA)
5052    && reload_completed
5053    && GET_CODE (operands[1]) == CONST_DOUBLE"
5054   [(set (match_dup 2) (match_dup 3))]
5055   "
5056   operands[2] = gen_lowpart (SImode, operands[0]);
5057   operands[3] = gen_lowpart (SImode, operands[1]);
5058   if (operands[2] == 0 || operands[3] == 0)
5059     FAIL;
5060   "
5063 (define_insn "*arm_movsf_soft_insn"
5064   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5065         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
5066   "TARGET_ARM
5067    && TARGET_SOFT_FLOAT
5068    && (GET_CODE (operands[0]) != MEM
5069        || register_operand (operands[1], SFmode))"
5070   "@
5071    mov%?\\t%0, %1
5072    ldr%?\\t%0, %1\\t%@ float
5073    str%?\\t%1, %0\\t%@ float"
5074   [(set_attr "length" "4,4,4")
5075    (set_attr "predicable" "yes")
5076    (set_attr "type" "*,load1,store1")
5077    (set_attr "pool_range" "*,4096,*")
5078    (set_attr "neg_pool_range" "*,4084,*")]
5081 ;;; ??? This should have alternatives for constants.
5082 (define_insn "*thumb_movsf_insn"
5083   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5084         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5085   "TARGET_THUMB
5086    && (   register_operand (operands[0], SFmode) 
5087        || register_operand (operands[1], SFmode))"
5088   "@
5089    add\\t%0, %1, #0
5090    ldmia\\t%1, {%0}
5091    stmia\\t%0, {%1}
5092    ldr\\t%0, %1
5093    str\\t%1, %0
5094    mov\\t%0, %1
5095    mov\\t%0, %1"
5096   [(set_attr "length" "2")
5097    (set_attr "type" "*,load1,store1,load1,store1,*,*")
5098    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5101 (define_expand "movdf"
5102   [(set (match_operand:DF 0 "general_operand" "")
5103         (match_operand:DF 1 "general_operand" ""))]
5104   "TARGET_EITHER"
5105   "
5106   if (TARGET_ARM)
5107     {
5108       if (GET_CODE (operands[0]) == MEM)
5109         operands[1] = force_reg (DFmode, operands[1]);
5110     }
5111   else /* TARGET_THUMB */
5112     {
5113       if (!no_new_pseudos)
5114         {
5115           if (GET_CODE (operands[0]) != REG)
5116             operands[1] = force_reg (DFmode, operands[1]);
5117         }
5118     }
5119   "
5122 ;; Reloading a df mode value stored in integer regs to memory can require a
5123 ;; scratch reg.
5124 (define_expand "reload_outdf"
5125   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5126    (match_operand:DF 1 "s_register_operand" "r")
5127    (match_operand:SI 2 "s_register_operand" "=&r")]
5128   "TARGET_ARM"
5129   "
5130   {
5131     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5133     if (code == REG)
5134       operands[2] = XEXP (operands[0], 0);
5135     else if (code == POST_INC || code == PRE_DEC)
5136       {
5137         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5138         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5139         emit_insn (gen_movdi (operands[0], operands[1]));
5140         DONE;
5141       }
5142     else if (code == PRE_INC)
5143       {
5144         rtx reg = XEXP (XEXP (operands[0], 0), 0);
5146         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5147         operands[2] = reg;
5148       }
5149     else if (code == POST_DEC)
5150       operands[2] = XEXP (XEXP (operands[0], 0), 0);
5151     else
5152       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5153                              XEXP (XEXP (operands[0], 0), 1)));
5155     emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5156                             operands[1]));
5158     if (code == POST_DEC)
5159       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5161     DONE;
5162   }"
5165 (define_insn "*movdf_soft_insn"
5166   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
5167         (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
5168   "TARGET_ARM && TARGET_SOFT_FLOAT
5169   "
5170   "* return output_move_double (operands);"
5171   [(set_attr "length" "8,8,8")
5172    (set_attr "type" "*,load2,store2")
5173    (set_attr "pool_range" "1020")
5174    (set_attr "neg_pool_range" "1008")]
5177 ;;; ??? This should have alternatives for constants.
5178 ;;; ??? This was originally identical to the movdi_insn pattern.
5179 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5180 ;;; thumb_reorg with a memory reference.
5181 (define_insn "*thumb_movdf_insn"
5182   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5183         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5184   "TARGET_THUMB
5185    && (   register_operand (operands[0], DFmode)
5186        || register_operand (operands[1], DFmode))"
5187   "*
5188   switch (which_alternative)
5189     {
5190     default:
5191     case 0:
5192       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5193         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5194       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5195     case 1:
5196       return \"ldmia\\t%1, {%0, %H0}\";
5197     case 2:
5198       return \"stmia\\t%0, {%1, %H1}\";
5199     case 3:
5200       return thumb_load_double_from_address (operands);
5201     case 4:
5202       operands[2] = gen_rtx_MEM (SImode,
5203                                  plus_constant (XEXP (operands[0], 0), 4));
5204       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5205       return \"\";
5206     case 5:
5207       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5208         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5209       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5210     }
5211   "
5212   [(set_attr "length" "4,2,2,6,4,4")
5213    (set_attr "type" "*,load2,store2,load2,store2,*")
5214    (set_attr "pool_range" "*,*,*,1020,*,*")]
5217 ;; Vector Moves
5218 (define_expand "movv2si"
5219   [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5220         (match_operand:V2SI 1 "general_operand" ""))]
5221   "TARGET_REALLY_IWMMXT"
5225 (define_expand "movv4hi"
5226   [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5227         (match_operand:V4HI 1 "general_operand" ""))]
5228   "TARGET_REALLY_IWMMXT"
5232 (define_expand "movv8qi"
5233   [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5234         (match_operand:V8QI 1 "general_operand" ""))]
5235   "TARGET_REALLY_IWMMXT"
5240 ;; load- and store-multiple insns
5241 ;; The arm can load/store any set of registers, provided that they are in
5242 ;; ascending order; but that is beyond GCC so stick with what it knows.
5244 (define_expand "load_multiple"
5245   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5246                           (match_operand:SI 1 "" ""))
5247                      (use (match_operand:SI 2 "" ""))])]
5248   "TARGET_ARM"
5250   HOST_WIDE_INT offset = 0;
5252   /* Support only fixed point registers.  */
5253   if (GET_CODE (operands[2]) != CONST_INT
5254       || INTVAL (operands[2]) > 14
5255       || INTVAL (operands[2]) < 2
5256       || GET_CODE (operands[1]) != MEM
5257       || GET_CODE (operands[0]) != REG
5258       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5259       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5260     FAIL;
5262   operands[3]
5263     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5264                              force_reg (SImode, XEXP (operands[1], 0)),
5265                              TRUE, FALSE, operands[1], &offset);
5268 ;; Load multiple with write-back
5270 (define_insn "*ldmsi_postinc4"
5271   [(match_parallel 0 "load_multiple_operation"
5272     [(set (match_operand:SI 1 "s_register_operand" "=r")
5273           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5274                    (const_int 16)))
5275      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5276           (mem:SI (match_dup 2)))
5277      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5278           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5279      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5280           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5281      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5282           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5283   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5284   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5285   [(set_attr "type" "load4")
5286    (set_attr "predicable" "yes")]
5289 (define_insn "*ldmsi_postinc3"
5290   [(match_parallel 0 "load_multiple_operation"
5291     [(set (match_operand:SI 1 "s_register_operand" "=r")
5292           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5293                    (const_int 12)))
5294      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5295           (mem:SI (match_dup 2)))
5296      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5297           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5298      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5299           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5300   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5301   "ldm%?ia\\t%1!, {%3, %4, %5}"
5302   [(set_attr "type" "load3")
5303    (set_attr "predicable" "yes")]
5306 (define_insn "*ldmsi_postinc2"
5307   [(match_parallel 0 "load_multiple_operation"
5308     [(set (match_operand:SI 1 "s_register_operand" "=r")
5309           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5310                    (const_int 8)))
5311      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5312           (mem:SI (match_dup 2)))
5313      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5314           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5315   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5316   "ldm%?ia\\t%1!, {%3, %4}"
5317   [(set_attr "type" "load2")
5318    (set_attr "predicable" "yes")]
5321 ;; Ordinary load multiple
5323 (define_insn "*ldmsi4"
5324   [(match_parallel 0 "load_multiple_operation"
5325     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5326           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5327      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5328           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5329      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5330           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5331      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5332           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5333   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5334   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5335   [(set_attr "type" "load4")
5336    (set_attr "predicable" "yes")]
5339 (define_insn "*ldmsi3"
5340   [(match_parallel 0 "load_multiple_operation"
5341     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5342           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5343      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5344           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5345      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5346           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5347   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5348   "ldm%?ia\\t%1, {%2, %3, %4}"
5349   [(set_attr "type" "load3")
5350    (set_attr "predicable" "yes")]
5353 (define_insn "*ldmsi2"
5354   [(match_parallel 0 "load_multiple_operation"
5355     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5356           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5357      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5358           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5359   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5360   "ldm%?ia\\t%1, {%2, %3}"
5361   [(set_attr "type" "load2")
5362    (set_attr "predicable" "yes")]
5365 (define_expand "store_multiple"
5366   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5367                           (match_operand:SI 1 "" ""))
5368                      (use (match_operand:SI 2 "" ""))])]
5369   "TARGET_ARM"
5371   HOST_WIDE_INT offset = 0;
5373   /* Support only fixed point registers.  */
5374   if (GET_CODE (operands[2]) != CONST_INT
5375       || INTVAL (operands[2]) > 14
5376       || INTVAL (operands[2]) < 2
5377       || GET_CODE (operands[1]) != REG
5378       || GET_CODE (operands[0]) != MEM
5379       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5380       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5381     FAIL;
5383   operands[3]
5384     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5385                               force_reg (SImode, XEXP (operands[0], 0)),
5386                               TRUE, FALSE, operands[0], &offset);
5389 ;; Store multiple with write-back
5391 (define_insn "*stmsi_postinc4"
5392   [(match_parallel 0 "store_multiple_operation"
5393     [(set (match_operand:SI 1 "s_register_operand" "=r")
5394           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5395                    (const_int 16)))
5396      (set (mem:SI (match_dup 2))
5397           (match_operand:SI 3 "arm_hard_register_operand" ""))
5398      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5399           (match_operand:SI 4 "arm_hard_register_operand" ""))
5400      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5401           (match_operand:SI 5 "arm_hard_register_operand" ""))
5402      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5403           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5404   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5405   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5406   [(set_attr "predicable" "yes")
5407    (set_attr "type" "store4")]
5410 (define_insn "*stmsi_postinc3"
5411   [(match_parallel 0 "store_multiple_operation"
5412     [(set (match_operand:SI 1 "s_register_operand" "=r")
5413           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5414                    (const_int 12)))
5415      (set (mem:SI (match_dup 2))
5416           (match_operand:SI 3 "arm_hard_register_operand" ""))
5417      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5418           (match_operand:SI 4 "arm_hard_register_operand" ""))
5419      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5420           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5421   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5422   "stm%?ia\\t%1!, {%3, %4, %5}"
5423   [(set_attr "predicable" "yes")
5424    (set_attr "type" "store3")]
5427 (define_insn "*stmsi_postinc2"
5428   [(match_parallel 0 "store_multiple_operation"
5429     [(set (match_operand:SI 1 "s_register_operand" "=r")
5430           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5431                    (const_int 8)))
5432      (set (mem:SI (match_dup 2))
5433           (match_operand:SI 3 "arm_hard_register_operand" ""))
5434      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5435           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5436   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5437   "stm%?ia\\t%1!, {%3, %4}"
5438   [(set_attr "predicable" "yes")
5439    (set_attr "type" "store2")]
5442 ;; Ordinary store multiple
5444 (define_insn "*stmsi4"
5445   [(match_parallel 0 "store_multiple_operation"
5446     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5447           (match_operand:SI 2 "arm_hard_register_operand" ""))
5448      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5449           (match_operand:SI 3 "arm_hard_register_operand" ""))
5450      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5451           (match_operand:SI 4 "arm_hard_register_operand" ""))
5452      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5453           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5454   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5455   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5456   [(set_attr "predicable" "yes")
5457    (set_attr "type" "store4")]
5460 (define_insn "*stmsi3"
5461   [(match_parallel 0 "store_multiple_operation"
5462     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5463           (match_operand:SI 2 "arm_hard_register_operand" ""))
5464      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5465           (match_operand:SI 3 "arm_hard_register_operand" ""))
5466      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5467           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5468   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5469   "stm%?ia\\t%1, {%2, %3, %4}"
5470   [(set_attr "predicable" "yes")
5471    (set_attr "type" "store3")]
5474 (define_insn "*stmsi2"
5475   [(match_parallel 0 "store_multiple_operation"
5476     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5477           (match_operand:SI 2 "arm_hard_register_operand" ""))
5478      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5479           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5480   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5481   "stm%?ia\\t%1, {%2, %3}"
5482   [(set_attr "predicable" "yes")
5483    (set_attr "type" "store2")]
5486 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5487 ;; We could let this apply for blocks of less than this, but it clobbers so
5488 ;; many registers that there is then probably a better way.
5490 (define_expand "movmemqi"
5491   [(match_operand:BLK 0 "general_operand" "")
5492    (match_operand:BLK 1 "general_operand" "")
5493    (match_operand:SI 2 "const_int_operand" "")
5494    (match_operand:SI 3 "const_int_operand" "")]
5495   "TARGET_EITHER"
5496   "
5497   if (TARGET_ARM)
5498     {
5499       if (arm_gen_movmemqi (operands))
5500         DONE;
5501       FAIL;
5502     }
5503   else /* TARGET_THUMB */
5504     {
5505       if (   INTVAL (operands[3]) != 4
5506           || INTVAL (operands[2]) > 48)
5507         FAIL;
5509       thumb_expand_movmemqi (operands);
5510       DONE;
5511     }
5512   "
5515 ;; Thumb block-move insns
5517 (define_insn "movmem12b"
5518   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5519         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5520    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5521         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5522    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5523         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5524    (set (match_operand:SI 0 "register_operand" "=l")
5525         (plus:SI (match_dup 2) (const_int 12)))
5526    (set (match_operand:SI 1 "register_operand" "=l")
5527         (plus:SI (match_dup 3) (const_int 12)))
5528    (clobber (match_scratch:SI 4 "=&l"))
5529    (clobber (match_scratch:SI 5 "=&l"))
5530    (clobber (match_scratch:SI 6 "=&l"))]
5531   "TARGET_THUMB"
5532   "* return thumb_output_move_mem_multiple (3, operands);"
5533   [(set_attr "length" "4")
5534    ; This isn't entirely accurate...  It loads as well, but in terms of
5535    ; scheduling the following insn it is better to consider it as a store
5536    (set_attr "type" "store3")]
5539 (define_insn "movmem8b"
5540   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5541         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5542    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5543         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5544    (set (match_operand:SI 0 "register_operand" "=l")
5545         (plus:SI (match_dup 2) (const_int 8)))
5546    (set (match_operand:SI 1 "register_operand" "=l")
5547         (plus:SI (match_dup 3) (const_int 8)))
5548    (clobber (match_scratch:SI 4 "=&l"))
5549    (clobber (match_scratch:SI 5 "=&l"))]
5550   "TARGET_THUMB"
5551   "* return thumb_output_move_mem_multiple (2, operands);"
5552   [(set_attr "length" "4")
5553    ; This isn't entirely accurate...  It loads as well, but in terms of
5554    ; scheduling the following insn it is better to consider it as a store
5555    (set_attr "type" "store2")]
5560 ;; Compare & branch insns
5561 ;; The range calculations are based as follows:
5562 ;; For forward branches, the address calculation returns the address of
5563 ;; the next instruction.  This is 2 beyond the branch instruction.
5564 ;; For backward branches, the address calculation returns the address of
5565 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5566 ;; instruction for the shortest sequence, and 4 before the branch instruction
5567 ;; if we have to jump around an unconditional branch.
5568 ;; To the basic branch range the PC offset must be added (this is +4).
5569 ;; So for forward branches we have 
5570 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5571 ;; And for backward branches we have 
5572 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5574 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5575 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5577 (define_expand "cbranchsi4"
5578   [(set (pc) (if_then_else
5579               (match_operator 0 "arm_comparison_operator"
5580                [(match_operand:SI 1 "s_register_operand" "")
5581                 (match_operand:SI 2 "nonmemory_operand" "")])
5582               (label_ref (match_operand 3 "" ""))
5583               (pc)))]
5584   "TARGET_THUMB"
5585   "
5586   if (thumb_cmpneg_operand (operands[2], SImode))
5587     {
5588       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5589                                               operands[3], operands[0]));
5590       DONE;
5591     }
5592   if (!thumb_cmp_operand (operands[2], SImode))
5593     operands[2] = force_reg (SImode, operands[2]);
5594   ")
5596 (define_insn "*cbranchsi4_insn"
5597   [(set (pc) (if_then_else
5598               (match_operator 0 "arm_comparison_operator"
5599                [(match_operand:SI 1 "s_register_operand" "l,*h")
5600                 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5601               (label_ref (match_operand 3 "" ""))
5602               (pc)))]
5603   "TARGET_THUMB"
5604   "*
5605   output_asm_insn (\"cmp\\t%1, %2\", operands);
5607   switch (get_attr_length (insn))
5608     {
5609     case 4:  return \"b%d0\\t%l3\";
5610     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5611     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5612     }
5613   "
5614   [(set (attr "far_jump")
5615         (if_then_else
5616             (eq_attr "length" "8")
5617             (const_string "yes")
5618             (const_string "no")))
5619    (set (attr "length") 
5620         (if_then_else
5621             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5622                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5623             (const_int 4)
5624             (if_then_else
5625                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5626                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5627                 (const_int 6)
5628                 (const_int 8))))]
5631 (define_insn "cbranchsi4_scratch"
5632   [(set (pc) (if_then_else
5633               (match_operator 4 "arm_comparison_operator"
5634                [(match_operand:SI 1 "s_register_operand" "l,0")
5635                 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5636               (label_ref (match_operand 3 "" ""))
5637               (pc)))
5638    (clobber (match_scratch:SI 0 "=l,l"))]
5639   "TARGET_THUMB"
5640   "*
5641   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5643   switch (get_attr_length (insn))
5644     {
5645     case 4:  return \"b%d4\\t%l3\";
5646     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5647     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5648     }
5649   "
5650   [(set (attr "far_jump")
5651         (if_then_else
5652             (eq_attr "length" "8")
5653             (const_string "yes")
5654             (const_string "no")))
5655    (set (attr "length") 
5656         (if_then_else
5657             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5658                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5659             (const_int 4)
5660             (if_then_else
5661                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5662                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5663                 (const_int 6)
5664                 (const_int 8))))]
5666 (define_insn "*movsi_cbranchsi4"
5667   [(set (pc)
5668         (if_then_else
5669          (match_operator 3 "arm_comparison_operator"
5670           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5671            (const_int 0)])
5672          (label_ref (match_operand 2 "" ""))
5673          (pc)))
5674    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5675         (match_dup 1))]
5676   "TARGET_THUMB"
5677   "*{
5678   if (which_alternative == 0)
5679     output_asm_insn (\"cmp\t%0, #0\", operands);
5680   else if (which_alternative == 1)
5681     output_asm_insn (\"sub\t%0, %1, #0\", operands);
5682   else
5683     {
5684       output_asm_insn (\"cmp\t%1, #0\", operands);
5685       if (which_alternative == 2)
5686         output_asm_insn (\"mov\t%0, %1\", operands);
5687       else
5688         output_asm_insn (\"str\t%1, %0\", operands);
5689     }
5690   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5691     {
5692     case 4:  return \"b%d3\\t%l2\";
5693     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5694     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5695     }
5696   }"
5697   [(set (attr "far_jump")
5698         (if_then_else
5699             (ior (and (gt (symbol_ref ("which_alternative"))
5700                           (const_int 1))
5701                       (eq_attr "length" "8"))
5702                  (eq_attr "length" "10"))
5703             (const_string "yes")
5704             (const_string "no")))
5705    (set (attr "length")
5706      (if_then_else
5707        (le (symbol_ref ("which_alternative"))
5708                        (const_int 1))
5709        (if_then_else
5710          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5711               (le (minus (match_dup 2) (pc)) (const_int 256)))
5712          (const_int 4)
5713          (if_then_else
5714            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5715                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5716            (const_int 6)
5717            (const_int 8)))
5718        (if_then_else
5719          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5720               (le (minus (match_dup 2) (pc)) (const_int 256)))
5721          (const_int 6)
5722          (if_then_else
5723            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5724                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5725            (const_int 8)
5726            (const_int 10)))))]
5729 (define_insn "*negated_cbranchsi4"
5730   [(set (pc)
5731         (if_then_else
5732          (match_operator 0 "arm_comparison_operator"
5733           [(match_operand:SI 1 "s_register_operand" "l")
5734            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5735          (label_ref (match_operand 3 "" ""))
5736          (pc)))]
5737   "TARGET_THUMB"
5738   "*
5739   output_asm_insn (\"cmn\\t%1, %2\", operands);
5740   switch (get_attr_length (insn))
5741     {
5742     case 4:  return \"b%d0\\t%l3\";
5743     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5744     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5745     }
5746   "
5747   [(set (attr "far_jump")
5748         (if_then_else
5749             (eq_attr "length" "8")
5750             (const_string "yes")
5751             (const_string "no")))
5752    (set (attr "length") 
5753         (if_then_else
5754             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5755                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5756             (const_int 4)
5757             (if_then_else
5758                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5759                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5760                 (const_int 6)
5761                 (const_int 8))))]
5764 (define_insn "*tbit_cbranch"
5765   [(set (pc)
5766         (if_then_else
5767          (match_operator 0 "equality_operator"
5768           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5769                             (const_int 1)
5770                             (match_operand:SI 2 "const_int_operand" "i"))
5771            (const_int 0)])
5772          (label_ref (match_operand 3 "" ""))
5773          (pc)))
5774    (clobber (match_scratch:SI 4 "=l"))]
5775   "TARGET_THUMB"
5776   "*
5777   {
5778   rtx op[3];
5779   op[0] = operands[4];
5780   op[1] = operands[1];
5781   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5783   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5784   switch (get_attr_length (insn))
5785     {
5786     case 4:  return \"b%d0\\t%l3\";
5787     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5788     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5789     }
5790   }"
5791   [(set (attr "far_jump")
5792         (if_then_else
5793             (eq_attr "length" "8")
5794             (const_string "yes")
5795             (const_string "no")))
5796    (set (attr "length") 
5797         (if_then_else
5798             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5799                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5800             (const_int 4)
5801             (if_then_else
5802                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5803                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5804                 (const_int 6)
5805                 (const_int 8))))]
5807   
5808 (define_insn "*tstsi3_cbranch"
5809   [(set (pc)
5810         (if_then_else
5811          (match_operator 3 "equality_operator"
5812           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5813                    (match_operand:SI 1 "s_register_operand" "l"))
5814            (const_int 0)])
5815          (label_ref (match_operand 2 "" ""))
5816          (pc)))]
5817   "TARGET_THUMB"
5818   "*
5819   {
5820   output_asm_insn (\"tst\\t%0, %1\", operands);
5821   switch (get_attr_length (insn))
5822     {
5823     case 4:  return \"b%d3\\t%l2\";
5824     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5825     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5826     }
5827   }"
5828   [(set (attr "far_jump")
5829         (if_then_else
5830             (eq_attr "length" "8")
5831             (const_string "yes")
5832             (const_string "no")))
5833    (set (attr "length") 
5834         (if_then_else
5835             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5836                  (le (minus (match_dup 2) (pc)) (const_int 256)))
5837             (const_int 4)
5838             (if_then_else
5839                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5840                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
5841                 (const_int 6)
5842                 (const_int 8))))]
5844   
5845 (define_insn "*andsi3_cbranch"
5846   [(set (pc)
5847         (if_then_else
5848          (match_operator 5 "equality_operator"
5849           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5850                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5851            (const_int 0)])
5852          (label_ref (match_operand 4 "" ""))
5853          (pc)))
5854    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5855         (and:SI (match_dup 2) (match_dup 3)))
5856    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5857   "TARGET_THUMB"
5858   "*
5859   {
5860   if (which_alternative == 0)
5861     output_asm_insn (\"and\\t%0, %3\", operands);
5862   else if (which_alternative == 1)
5863     {
5864       output_asm_insn (\"and\\t%1, %3\", operands);
5865       output_asm_insn (\"mov\\t%0, %1\", operands);
5866     }
5867   else
5868     {
5869       output_asm_insn (\"and\\t%1, %3\", operands);
5870       output_asm_insn (\"str\\t%1, %0\", operands);
5871     }
5873   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5874     {
5875     case 4:  return \"b%d5\\t%l4\";
5876     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5877     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5878     }
5879   }"
5880   [(set (attr "far_jump")
5881         (if_then_else
5882             (ior (and (eq (symbol_ref ("which_alternative"))
5883                           (const_int 0))
5884                       (eq_attr "length" "8"))
5885                  (eq_attr "length" "10"))
5886             (const_string "yes")
5887             (const_string "no")))
5888    (set (attr "length")
5889      (if_then_else
5890        (eq (symbol_ref ("which_alternative"))
5891                        (const_int 0))
5892        (if_then_else
5893          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5894               (le (minus (match_dup 4) (pc)) (const_int 256)))
5895          (const_int 4)
5896          (if_then_else
5897            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5898                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5899            (const_int 6)
5900            (const_int 8)))
5901        (if_then_else
5902          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5903               (le (minus (match_dup 4) (pc)) (const_int 256)))
5904          (const_int 6)
5905          (if_then_else
5906            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5907                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5908            (const_int 8)
5909            (const_int 10)))))]
5912 (define_insn "*orrsi3_cbranch_scratch"
5913   [(set (pc)
5914         (if_then_else
5915          (match_operator 4 "equality_operator"
5916           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
5917                    (match_operand:SI 2 "s_register_operand" "l"))
5918            (const_int 0)])
5919          (label_ref (match_operand 3 "" ""))
5920          (pc)))
5921    (clobber (match_scratch:SI 0 "=l"))]
5922   "TARGET_THUMB"
5923   "*
5924   {
5925   output_asm_insn (\"orr\\t%0, %2\", operands);
5926   switch (get_attr_length (insn))
5927     {
5928     case 4:  return \"b%d4\\t%l3\";
5929     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5930     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5931     }
5932   }"
5933   [(set (attr "far_jump")
5934         (if_then_else
5935             (eq_attr "length" "8")
5936             (const_string "yes")
5937             (const_string "no")))
5938    (set (attr "length") 
5939         (if_then_else
5940             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5941                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5942             (const_int 4)
5943             (if_then_else
5944                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5945                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5946                 (const_int 6)
5947                 (const_int 8))))]
5949   
5950 (define_insn "*orrsi3_cbranch"
5951   [(set (pc)
5952         (if_then_else
5953          (match_operator 5 "equality_operator"
5954           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5955                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5956            (const_int 0)])
5957          (label_ref (match_operand 4 "" ""))
5958          (pc)))
5959    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5960         (ior:SI (match_dup 2) (match_dup 3)))
5961    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5962   "TARGET_THUMB"
5963   "*
5964   {
5965   if (which_alternative == 0)
5966     output_asm_insn (\"orr\\t%0, %3\", operands);
5967   else if (which_alternative == 1)
5968     {
5969       output_asm_insn (\"orr\\t%1, %3\", operands);
5970       output_asm_insn (\"mov\\t%0, %1\", operands);
5971     }
5972   else
5973     {
5974       output_asm_insn (\"orr\\t%1, %3\", operands);
5975       output_asm_insn (\"str\\t%1, %0\", operands);
5976     }
5978   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5979     {
5980     case 4:  return \"b%d5\\t%l4\";
5981     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5982     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5983     }
5984   }"
5985   [(set (attr "far_jump")
5986         (if_then_else
5987             (ior (and (eq (symbol_ref ("which_alternative"))
5988                           (const_int 0))
5989                       (eq_attr "length" "8"))
5990                  (eq_attr "length" "10"))
5991             (const_string "yes")
5992             (const_string "no")))
5993    (set (attr "length")
5994      (if_then_else
5995        (eq (symbol_ref ("which_alternative"))
5996                        (const_int 0))
5997        (if_then_else
5998          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5999               (le (minus (match_dup 4) (pc)) (const_int 256)))
6000          (const_int 4)
6001          (if_then_else
6002            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6003                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6004            (const_int 6)
6005            (const_int 8)))
6006        (if_then_else
6007          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6008               (le (minus (match_dup 4) (pc)) (const_int 256)))
6009          (const_int 6)
6010          (if_then_else
6011            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6012                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6013            (const_int 8)
6014            (const_int 10)))))]
6017 (define_insn "*xorsi3_cbranch_scratch"
6018   [(set (pc)
6019         (if_then_else
6020          (match_operator 4 "equality_operator"
6021           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6022                    (match_operand:SI 2 "s_register_operand" "l"))
6023            (const_int 0)])
6024          (label_ref (match_operand 3 "" ""))
6025          (pc)))
6026    (clobber (match_scratch:SI 0 "=l"))]
6027   "TARGET_THUMB"
6028   "*
6029   {
6030   output_asm_insn (\"eor\\t%0, %2\", operands);
6031   switch (get_attr_length (insn))
6032     {
6033     case 4:  return \"b%d4\\t%l3\";
6034     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6035     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6036     }
6037   }"
6038   [(set (attr "far_jump")
6039         (if_then_else
6040             (eq_attr "length" "8")
6041             (const_string "yes")
6042             (const_string "no")))
6043    (set (attr "length") 
6044         (if_then_else
6045             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6046                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6047             (const_int 4)
6048             (if_then_else
6049                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6050                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6051                 (const_int 6)
6052                 (const_int 8))))]
6054   
6055 (define_insn "*xorsi3_cbranch"
6056   [(set (pc)
6057         (if_then_else
6058          (match_operator 5 "equality_operator"
6059           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6060                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6061            (const_int 0)])
6062          (label_ref (match_operand 4 "" ""))
6063          (pc)))
6064    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6065         (xor:SI (match_dup 2) (match_dup 3)))
6066    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6067   "TARGET_THUMB"
6068   "*
6069   {
6070   if (which_alternative == 0)
6071     output_asm_insn (\"eor\\t%0, %3\", operands);
6072   else if (which_alternative == 1)
6073     {
6074       output_asm_insn (\"eor\\t%1, %3\", operands);
6075       output_asm_insn (\"mov\\t%0, %1\", operands);
6076     }
6077   else
6078     {
6079       output_asm_insn (\"eor\\t%1, %3\", operands);
6080       output_asm_insn (\"str\\t%1, %0\", operands);
6081     }
6083   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6084     {
6085     case 4:  return \"b%d5\\t%l4\";
6086     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6087     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6088     }
6089   }"
6090   [(set (attr "far_jump")
6091         (if_then_else
6092             (ior (and (eq (symbol_ref ("which_alternative"))
6093                           (const_int 0))
6094                       (eq_attr "length" "8"))
6095                  (eq_attr "length" "10"))
6096             (const_string "yes")
6097             (const_string "no")))
6098    (set (attr "length")
6099      (if_then_else
6100        (eq (symbol_ref ("which_alternative"))
6101                        (const_int 0))
6102        (if_then_else
6103          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6104               (le (minus (match_dup 4) (pc)) (const_int 256)))
6105          (const_int 4)
6106          (if_then_else
6107            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6108                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6109            (const_int 6)
6110            (const_int 8)))
6111        (if_then_else
6112          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6113               (le (minus (match_dup 4) (pc)) (const_int 256)))
6114          (const_int 6)
6115          (if_then_else
6116            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6117                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6118            (const_int 8)
6119            (const_int 10)))))]
6122 (define_insn "*bicsi3_cbranch_scratch"
6123   [(set (pc)
6124         (if_then_else
6125          (match_operator 4 "equality_operator"
6126           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6127                    (match_operand:SI 1 "s_register_operand" "0"))
6128            (const_int 0)])
6129          (label_ref (match_operand 3 "" ""))
6130          (pc)))
6131    (clobber (match_scratch:SI 0 "=l"))]
6132   "TARGET_THUMB"
6133   "*
6134   {
6135   output_asm_insn (\"bic\\t%0, %2\", operands);
6136   switch (get_attr_length (insn))
6137     {
6138     case 4:  return \"b%d4\\t%l3\";
6139     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6140     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6141     }
6142   }"
6143   [(set (attr "far_jump")
6144         (if_then_else
6145             (eq_attr "length" "8")
6146             (const_string "yes")
6147             (const_string "no")))
6148    (set (attr "length") 
6149         (if_then_else
6150             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6151                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6152             (const_int 4)
6153             (if_then_else
6154                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6155                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6156                 (const_int 6)
6157                 (const_int 8))))]
6159   
6160 (define_insn "*bicsi3_cbranch"
6161   [(set (pc)
6162         (if_then_else
6163          (match_operator 5 "equality_operator"
6164           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6165                    (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6166            (const_int 0)])
6167          (label_ref (match_operand 4 "" ""))
6168          (pc)))
6169    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6170         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6171    (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6172   "TARGET_THUMB"
6173   "*
6174   {
6175   if (which_alternative == 0)
6176     output_asm_insn (\"bic\\t%0, %3\", operands);
6177   else if (which_alternative <= 2)
6178     {
6179       output_asm_insn (\"bic\\t%1, %3\", operands);
6180       /* It's ok if OP0 is a lo-reg, even though the mov will set the
6181          conditions again, since we're only testing for equality.  */
6182       output_asm_insn (\"mov\\t%0, %1\", operands);
6183     }
6184   else
6185     {
6186       output_asm_insn (\"bic\\t%1, %3\", operands);
6187       output_asm_insn (\"str\\t%1, %0\", operands);
6188     }
6190   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6191     {
6192     case 4:  return \"b%d5\\t%l4\";
6193     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6194     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6195     }
6196   }"
6197   [(set (attr "far_jump")
6198         (if_then_else
6199             (ior (and (eq (symbol_ref ("which_alternative"))
6200                           (const_int 0))
6201                       (eq_attr "length" "8"))
6202                  (eq_attr "length" "10"))
6203             (const_string "yes")
6204             (const_string "no")))
6205    (set (attr "length")
6206      (if_then_else
6207        (eq (symbol_ref ("which_alternative"))
6208                        (const_int 0))
6209        (if_then_else
6210          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6211               (le (minus (match_dup 4) (pc)) (const_int 256)))
6212          (const_int 4)
6213          (if_then_else
6214            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6215                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6216            (const_int 6)
6217            (const_int 8)))
6218        (if_then_else
6219          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6220               (le (minus (match_dup 4) (pc)) (const_int 256)))
6221          (const_int 6)
6222          (if_then_else
6223            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6224                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6225            (const_int 8)
6226            (const_int 10)))))]
6229 (define_insn "*cbranchne_decr1"
6230   [(set (pc)
6231         (if_then_else (match_operator 3 "equality_operator"
6232                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6233                         (const_int 0)])
6234                       (label_ref (match_operand 4 "" ""))
6235                       (pc)))
6236    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6237         (plus:SI (match_dup 2) (const_int -1)))
6238    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6239   "TARGET_THUMB"
6240   "*
6241    {
6242      rtx cond[2];
6243      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6244                                 ? GEU : LTU),
6245                                VOIDmode, operands[2], const1_rtx);
6246      cond[1] = operands[4];
6248      if (which_alternative == 0)
6249        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6250      else if (which_alternative == 1)
6251        {
6252          /* We must provide an alternative for a hi reg because reload 
6253             cannot handle output reloads on a jump instruction, but we
6254             can't subtract into that.  Fortunately a mov from lo to hi
6255             does not clobber the condition codes.  */
6256          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6257          output_asm_insn (\"mov\\t%0, %1\", operands);
6258        }
6259      else
6260        {
6261          /* Similarly, but the target is memory.  */
6262          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6263          output_asm_insn (\"str\\t%1, %0\", operands);
6264        }
6266      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6267        {
6268          case 4:
6269            output_asm_insn (\"b%d0\\t%l1\", cond);
6270            return \"\";
6271          case 6:
6272            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6273            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6274          default:
6275            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6276            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6277        }
6278    }
6279   "
6280   [(set (attr "far_jump")
6281         (if_then_else
6282             (ior (and (eq (symbol_ref ("which_alternative"))
6283                           (const_int 0))
6284                       (eq_attr "length" "8"))
6285                  (eq_attr "length" "10"))
6286             (const_string "yes")
6287             (const_string "no")))
6288    (set_attr_alternative "length"
6289       [
6290        ;; Alternative 0
6291        (if_then_else
6292          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6293               (le (minus (match_dup 4) (pc)) (const_int 256)))
6294          (const_int 4)
6295          (if_then_else
6296            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6297                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6298            (const_int 6)
6299            (const_int 8)))
6300        ;; Alternative 1
6301        (if_then_else
6302          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6303               (le (minus (match_dup 4) (pc)) (const_int 256)))
6304          (const_int 6)
6305          (if_then_else
6306            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6307                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6308            (const_int 8)
6309            (const_int 10)))
6310        ;; Alternative 2
6311        (if_then_else
6312          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6313               (le (minus (match_dup 4) (pc)) (const_int 256)))
6314          (const_int 6)
6315          (if_then_else
6316            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6317                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6318            (const_int 8)
6319            (const_int 10)))
6320        ;; Alternative 3
6321        (if_then_else
6322          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6323               (le (minus (match_dup 4) (pc)) (const_int 256)))
6324          (const_int 6)
6325          (if_then_else
6326            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6327                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6328            (const_int 8)
6329            (const_int 10)))])]
6332 (define_insn "*addsi3_cbranch"
6333   [(set (pc)
6334         (if_then_else
6335          (match_operator 4 "comparison_operator"
6336           [(plus:SI
6337             (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6338             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6339            (const_int 0)])
6340          (label_ref (match_operand 5 "" ""))
6341          (pc)))
6342    (set
6343     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6344     (plus:SI (match_dup 2) (match_dup 3)))
6345    (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6346   "TARGET_THUMB
6347    && (GET_CODE (operands[4]) == EQ
6348        || GET_CODE (operands[4]) == NE
6349        || GET_CODE (operands[4]) == GE
6350        || GET_CODE (operands[4]) == LT)"
6351   "*
6352    {
6353      rtx cond[3];
6355      
6356      cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6357      cond[1] = operands[2];
6358      cond[2] = operands[3];
6360      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6361        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6362      else
6363        output_asm_insn (\"add\\t%0, %1, %2\", cond);
6365      if (which_alternative >= 3
6366          && which_alternative < 4)
6367        output_asm_insn (\"mov\\t%0, %1\", operands);
6368      else if (which_alternative >= 4)
6369        output_asm_insn (\"str\\t%1, %0\", operands);
6371      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6372        {
6373          case 4:
6374            return \"b%d4\\t%l5\";
6375          case 6:
6376            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6377          default:
6378            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6379        }
6380    }
6381   "
6382   [(set (attr "far_jump")
6383         (if_then_else
6384             (ior (and (lt (symbol_ref ("which_alternative"))
6385                           (const_int 3))
6386                       (eq_attr "length" "8"))
6387                  (eq_attr "length" "10"))
6388             (const_string "yes")
6389             (const_string "no")))
6390    (set (attr "length")
6391      (if_then_else
6392        (lt (symbol_ref ("which_alternative"))
6393                        (const_int 3))
6394        (if_then_else
6395          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6396               (le (minus (match_dup 5) (pc)) (const_int 256)))
6397          (const_int 4)
6398          (if_then_else
6399            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6400                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6401            (const_int 6)
6402            (const_int 8)))
6403        (if_then_else
6404          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6405               (le (minus (match_dup 5) (pc)) (const_int 256)))
6406          (const_int 6)
6407          (if_then_else
6408            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6409                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6410            (const_int 8)
6411            (const_int 10)))))]
6414 (define_insn "*addsi3_cbranch_scratch"
6415   [(set (pc)
6416         (if_then_else
6417          (match_operator 3 "comparison_operator"
6418           [(plus:SI
6419             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6420             (match_operand:SI 2 "reg_or_int_operand" "J,l,I,L"))
6421            (const_int 0)])
6422          (label_ref (match_operand 4 "" ""))
6423          (pc)))
6424    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6425   "TARGET_THUMB
6426    && (GET_CODE (operands[3]) == EQ
6427        || GET_CODE (operands[3]) == NE
6428        || GET_CODE (operands[3]) == GE
6429        || GET_CODE (operands[3]) == LT)"
6430   "*
6431    {
6432      switch (which_alternative)
6433        {
6434        case 0:
6435          output_asm_insn (\"cmp\t%1, #%n2\", operands);
6436          break;
6437        case 1:
6438          output_asm_insn (\"cmn\t%1, %2\", operands);
6439          break;
6440        case 2:
6441          output_asm_insn (\"add\t%0, %1, %2\", operands);
6442          break;
6443        case 3:
6444          output_asm_insn (\"add\t%0, %0, %2\", operands);
6445          break;
6446        }
6448      switch (get_attr_length (insn))
6449        {
6450          case 4:
6451            return \"b%d3\\t%l4\";
6452          case 6:
6453            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6454          default:
6455            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6456        }
6457    }
6458   "
6459   [(set (attr "far_jump")
6460         (if_then_else
6461             (eq_attr "length" "8")
6462             (const_string "yes")
6463             (const_string "no")))
6464    (set (attr "length")
6465        (if_then_else
6466          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6467               (le (minus (match_dup 4) (pc)) (const_int 256)))
6468          (const_int 4)
6469          (if_then_else
6470            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6471                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6472            (const_int 6)
6473            (const_int 8))))]
6476 (define_insn "*subsi3_cbranch"
6477   [(set (pc)
6478         (if_then_else
6479          (match_operator 4 "comparison_operator"
6480           [(minus:SI
6481             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6482             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6483            (const_int 0)])
6484          (label_ref (match_operand 5 "" ""))
6485          (pc)))
6486    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6487         (minus:SI (match_dup 2) (match_dup 3)))
6488    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6489   "TARGET_THUMB
6490    && (GET_CODE (operands[4]) == EQ
6491        || GET_CODE (operands[4]) == NE
6492        || GET_CODE (operands[4]) == GE
6493        || GET_CODE (operands[4]) == LT)"
6494   "*
6495    {
6496      if (which_alternative == 0)
6497        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6498      else if (which_alternative == 1)
6499        {
6500          /* We must provide an alternative for a hi reg because reload 
6501             cannot handle output reloads on a jump instruction, but we
6502             can't subtract into that.  Fortunately a mov from lo to hi
6503             does not clobber the condition codes.  */
6504          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6505          output_asm_insn (\"mov\\t%0, %1\", operands);
6506        }
6507      else
6508        {
6509          /* Similarly, but the target is memory.  */
6510          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6511          output_asm_insn (\"str\\t%1, %0\", operands);
6512        }
6514      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6515        {
6516          case 4:
6517            return \"b%d4\\t%l5\";
6518          case 6:
6519            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6520          default:
6521            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6522        }
6523    }
6524   "
6525   [(set (attr "far_jump")
6526         (if_then_else
6527             (ior (and (eq (symbol_ref ("which_alternative"))
6528                           (const_int 0))
6529                       (eq_attr "length" "8"))
6530                  (eq_attr "length" "10"))
6531             (const_string "yes")
6532             (const_string "no")))
6533    (set (attr "length")
6534      (if_then_else
6535        (eq (symbol_ref ("which_alternative"))
6536                        (const_int 0))
6537        (if_then_else
6538          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6539               (le (minus (match_dup 5) (pc)) (const_int 256)))
6540          (const_int 4)
6541          (if_then_else
6542            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6543                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6544            (const_int 6)
6545            (const_int 8)))
6546        (if_then_else
6547          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6548               (le (minus (match_dup 5) (pc)) (const_int 256)))
6549          (const_int 6)
6550          (if_then_else
6551            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6552                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6553            (const_int 8)
6554            (const_int 10)))))]
6557 (define_insn "*subsi3_cbranch_scratch"
6558   [(set (pc)
6559         (if_then_else
6560          (match_operator 0 "arm_comparison_operator"
6561           [(minus:SI (match_operand:SI 1 "register_operand" "l")
6562                      (match_operand:SI 2 "nonmemory_operand" "l"))
6563            (const_int 0)])
6564          (label_ref (match_operand 3 "" ""))
6565          (pc)))]
6566   "TARGET_THUMB
6567    && (GET_CODE (operands[0]) == EQ
6568        || GET_CODE (operands[0]) == NE
6569        || GET_CODE (operands[0]) == GE
6570        || GET_CODE (operands[0]) == LT)"
6571   "*
6572   output_asm_insn (\"cmp\\t%1, %2\", operands);
6573   switch (get_attr_length (insn))
6574     {
6575     case 4:  return \"b%d0\\t%l3\";
6576     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6577     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6578     }
6579   "
6580   [(set (attr "far_jump")
6581         (if_then_else
6582             (eq_attr "length" "8")
6583             (const_string "yes")
6584             (const_string "no")))
6585    (set (attr "length") 
6586         (if_then_else
6587             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6588                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6589             (const_int 4)
6590             (if_then_else
6591                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6592                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6593                 (const_int 6)
6594                 (const_int 8))))]
6597 ;; Comparison and test insns
6599 (define_expand "cmpsi"
6600   [(match_operand:SI 0 "s_register_operand" "")
6601    (match_operand:SI 1 "arm_add_operand" "")]
6602   "TARGET_ARM"
6603   "{
6604     arm_compare_op0 = operands[0];
6605     arm_compare_op1 = operands[1];
6606     DONE;
6607   }"
6610 (define_expand "cmpsf"
6611   [(match_operand:SF 0 "s_register_operand" "")
6612    (match_operand:SF 1 "arm_float_compare_operand" "")]
6613   "TARGET_ARM && TARGET_HARD_FLOAT"
6614   "
6615   arm_compare_op0 = operands[0];
6616   arm_compare_op1 = operands[1];
6617   DONE;
6618   "
6621 (define_expand "cmpdf"
6622   [(match_operand:DF 0 "s_register_operand" "")
6623    (match_operand:DF 1 "arm_float_compare_operand" "")]
6624   "TARGET_ARM && TARGET_HARD_FLOAT"
6625   "
6626   arm_compare_op0 = operands[0];
6627   arm_compare_op1 = operands[1];
6628   DONE;
6629   "
6632 (define_insn "*arm_cmpsi_insn"
6633   [(set (reg:CC CC_REGNUM)
6634         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6635                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
6636   "TARGET_ARM"
6637   "@
6638    cmp%?\\t%0, %1
6639    cmn%?\\t%0, #%n1"
6640   [(set_attr "conds" "set")]
6643 (define_insn "*cmpsi_shiftsi"
6644   [(set (reg:CC CC_REGNUM)
6645         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
6646                     (match_operator:SI  3 "shift_operator"
6647                      [(match_operand:SI 1 "s_register_operand" "r")
6648                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
6649   "TARGET_ARM"
6650   "cmp%?\\t%0, %1%S3"
6651   [(set_attr "conds" "set")
6652    (set_attr "shift" "1")
6653    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6654                       (const_string "alu_shift")
6655                       (const_string "alu_shift_reg")))]
6658 (define_insn "*cmpsi_shiftsi_swp"
6659   [(set (reg:CC_SWP CC_REGNUM)
6660         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6661                          [(match_operand:SI 1 "s_register_operand" "r")
6662                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
6663                         (match_operand:SI 0 "s_register_operand" "r")))]
6664   "TARGET_ARM"
6665   "cmp%?\\t%0, %1%S3"
6666   [(set_attr "conds" "set")
6667    (set_attr "shift" "1")
6668    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6669                       (const_string "alu_shift")
6670                       (const_string "alu_shift_reg")))]
6673 (define_insn "*cmpsi_neg_shiftsi"
6674   [(set (reg:CC CC_REGNUM)
6675         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6676                     (neg:SI (match_operator:SI 3 "shift_operator"
6677                              [(match_operand:SI 1 "s_register_operand" "r")
6678                               (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
6679   "TARGET_ARM"
6680   "cmn%?\\t%0, %1%S3"
6681   [(set_attr "conds" "set")
6682    (set_attr "shift" "1")
6683    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6684                       (const_string "alu_shift")
6685                       (const_string "alu_shift_reg")))]
6688 ;; Cirrus SF compare instruction
6689 (define_insn "*cirrus_cmpsf"
6690   [(set (reg:CCFP CC_REGNUM)
6691         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6692                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
6693   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6694   "cfcmps%?\\tr15, %V0, %V1"
6695   [(set_attr "type"   "mav_farith")
6696    (set_attr "cirrus" "compare")]
6699 ;; Cirrus DF compare instruction
6700 (define_insn "*cirrus_cmpdf"
6701   [(set (reg:CCFP CC_REGNUM)
6702         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6703                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
6704   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6705   "cfcmpd%?\\tr15, %V0, %V1"
6706   [(set_attr "type"   "mav_farith")
6707    (set_attr "cirrus" "compare")]
6710 ;; Cirrus DI compare instruction
6711 (define_expand "cmpdi"
6712   [(match_operand:DI 0 "cirrus_fp_register" "")
6713    (match_operand:DI 1 "cirrus_fp_register" "")]
6714   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6715   "{
6716      arm_compare_op0 = operands[0];
6717      arm_compare_op1 = operands[1];
6718      DONE;
6719    }")
6721 (define_insn "*cirrus_cmpdi"
6722   [(set (reg:CC CC_REGNUM)
6723         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6724                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
6725   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6726   "cfcmp64%?\\tr15, %V0, %V1"
6727   [(set_attr "type"   "mav_farith")
6728    (set_attr "cirrus" "compare")]
6731 ; This insn allows redundant compares to be removed by cse, nothing should
6732 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6733 ; is deleted later on. The match_dup will match the mode here, so that
6734 ; mode changes of the condition codes aren't lost by this even though we don't
6735 ; specify what they are.
6737 (define_insn "*deleted_compare"
6738   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6739   "TARGET_ARM"
6740   "\\t%@ deleted compare"
6741   [(set_attr "conds" "set")
6742    (set_attr "length" "0")]
6746 ;; Conditional branch insns
6748 (define_expand "beq"
6749   [(set (pc)
6750         (if_then_else (eq (match_dup 1) (const_int 0))
6751                       (label_ref (match_operand 0 "" ""))
6752                       (pc)))]
6753   "TARGET_ARM"
6754   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6757 (define_expand "bne"
6758   [(set (pc)
6759         (if_then_else (ne (match_dup 1) (const_int 0))
6760                       (label_ref (match_operand 0 "" ""))
6761                       (pc)))]
6762   "TARGET_ARM"
6763   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6766 (define_expand "bgt"
6767   [(set (pc)
6768         (if_then_else (gt (match_dup 1) (const_int 0))
6769                       (label_ref (match_operand 0 "" ""))
6770                       (pc)))]
6771   "TARGET_ARM"
6772   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6775 (define_expand "ble"
6776   [(set (pc)
6777         (if_then_else (le (match_dup 1) (const_int 0))
6778                       (label_ref (match_operand 0 "" ""))
6779                       (pc)))]
6780   "TARGET_ARM"
6781   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6784 (define_expand "bge"
6785   [(set (pc)
6786         (if_then_else (ge (match_dup 1) (const_int 0))
6787                       (label_ref (match_operand 0 "" ""))
6788                       (pc)))]
6789   "TARGET_ARM"
6790   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6793 (define_expand "blt"
6794   [(set (pc)
6795         (if_then_else (lt (match_dup 1) (const_int 0))
6796                       (label_ref (match_operand 0 "" ""))
6797                       (pc)))]
6798   "TARGET_ARM"
6799   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6802 (define_expand "bgtu"
6803   [(set (pc)
6804         (if_then_else (gtu (match_dup 1) (const_int 0))
6805                       (label_ref (match_operand 0 "" ""))
6806                       (pc)))]
6807   "TARGET_ARM"
6808   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6811 (define_expand "bleu"
6812   [(set (pc)
6813         (if_then_else (leu (match_dup 1) (const_int 0))
6814                       (label_ref (match_operand 0 "" ""))
6815                       (pc)))]
6816   "TARGET_ARM"
6817   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6820 (define_expand "bgeu"
6821   [(set (pc)
6822         (if_then_else (geu (match_dup 1) (const_int 0))
6823                       (label_ref (match_operand 0 "" ""))
6824                       (pc)))]
6825   "TARGET_ARM"
6826   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6829 (define_expand "bltu"
6830   [(set (pc)
6831         (if_then_else (ltu (match_dup 1) (const_int 0))
6832                       (label_ref (match_operand 0 "" ""))
6833                       (pc)))]
6834   "TARGET_ARM"
6835   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6838 (define_expand "bunordered"
6839   [(set (pc)
6840         (if_then_else (unordered (match_dup 1) (const_int 0))
6841                       (label_ref (match_operand 0 "" ""))
6842                       (pc)))]
6843   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6844   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6845                                       arm_compare_op1);"
6848 (define_expand "bordered"
6849   [(set (pc)
6850         (if_then_else (ordered (match_dup 1) (const_int 0))
6851                       (label_ref (match_operand 0 "" ""))
6852                       (pc)))]
6853   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6854   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6855                                       arm_compare_op1);"
6858 (define_expand "bungt"
6859   [(set (pc)
6860         (if_then_else (ungt (match_dup 1) (const_int 0))
6861                       (label_ref (match_operand 0 "" ""))
6862                       (pc)))]
6863   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6864   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
6867 (define_expand "bunlt"
6868   [(set (pc)
6869         (if_then_else (unlt (match_dup 1) (const_int 0))
6870                       (label_ref (match_operand 0 "" ""))
6871                       (pc)))]
6872   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6873   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
6876 (define_expand "bunge"
6877   [(set (pc)
6878         (if_then_else (unge (match_dup 1) (const_int 0))
6879                       (label_ref (match_operand 0 "" ""))
6880                       (pc)))]
6881   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6882   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
6885 (define_expand "bunle"
6886   [(set (pc)
6887         (if_then_else (unle (match_dup 1) (const_int 0))
6888                       (label_ref (match_operand 0 "" ""))
6889                       (pc)))]
6890   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6891   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
6894 ;; The following two patterns need two branch instructions, since there is
6895 ;; no single instruction that will handle all cases.
6896 (define_expand "buneq"
6897   [(set (pc)
6898         (if_then_else (uneq (match_dup 1) (const_int 0))
6899                       (label_ref (match_operand 0 "" ""))
6900                       (pc)))]
6901   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6902   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6905 (define_expand "bltgt"
6906   [(set (pc)
6907         (if_then_else (ltgt (match_dup 1) (const_int 0))
6908                       (label_ref (match_operand 0 "" ""))
6909                       (pc)))]
6910   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6911   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6915 ;; Patterns to match conditional branch insns.
6918 ; Special pattern to match UNEQ.
6919 (define_insn "*arm_buneq"
6920   [(set (pc)
6921         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6922                       (label_ref (match_operand 0 "" ""))
6923                       (pc)))]
6924   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6925   "*
6926   if (arm_ccfsm_state != 0)
6927     abort ();
6929   return \"bvs\\t%l0\;beq\\t%l0\";
6930   "
6931   [(set_attr "conds" "jump_clob")
6932    (set_attr "length" "8")]
6935 ; Special pattern to match LTGT.
6936 (define_insn "*arm_bltgt"
6937   [(set (pc)
6938         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6939                       (label_ref (match_operand 0 "" ""))
6940                       (pc)))]
6941   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6942   "*
6943   if (arm_ccfsm_state != 0)
6944     abort ();
6946   return \"bmi\\t%l0\;bgt\\t%l0\";
6947   "
6948   [(set_attr "conds" "jump_clob")
6949    (set_attr "length" "8")]
6952 (define_insn "*arm_cond_branch"
6953   [(set (pc)
6954         (if_then_else (match_operator 1 "arm_comparison_operator"
6955                        [(match_operand 2 "cc_register" "") (const_int 0)])
6956                       (label_ref (match_operand 0 "" ""))
6957                       (pc)))]
6958   "TARGET_ARM"
6959   "*
6960   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6961     {
6962       arm_ccfsm_state += 2;
6963       return \"\";
6964     }
6965   return \"b%d1\\t%l0\";
6966   "
6967   [(set_attr "conds" "use")
6968    (set_attr "type" "branch")]
6971 ; Special pattern to match reversed UNEQ.
6972 (define_insn "*arm_buneq_reversed"
6973   [(set (pc)
6974         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6975                       (pc)
6976                       (label_ref (match_operand 0 "" ""))))]
6977   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6978   "*
6979   if (arm_ccfsm_state != 0)
6980     abort ();
6982   return \"bmi\\t%l0\;bgt\\t%l0\";
6983   "
6984   [(set_attr "conds" "jump_clob")
6985    (set_attr "length" "8")]
6988 ; Special pattern to match reversed LTGT.
6989 (define_insn "*arm_bltgt_reversed"
6990   [(set (pc)
6991         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6992                       (pc)
6993                       (label_ref (match_operand 0 "" ""))))]
6994   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6995   "*
6996   if (arm_ccfsm_state != 0)
6997     abort ();
6999   return \"bvs\\t%l0\;beq\\t%l0\";
7000   "
7001   [(set_attr "conds" "jump_clob")
7002    (set_attr "length" "8")]
7005 (define_insn "*arm_cond_branch_reversed"
7006   [(set (pc)
7007         (if_then_else (match_operator 1 "arm_comparison_operator"
7008                        [(match_operand 2 "cc_register" "") (const_int 0)])
7009                       (pc)
7010                       (label_ref (match_operand 0 "" ""))))]
7011   "TARGET_ARM"
7012   "*
7013   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7014     {
7015       arm_ccfsm_state += 2;
7016       return \"\";
7017     }
7018   return \"b%D1\\t%l0\";
7019   "
7020   [(set_attr "conds" "use")
7021    (set_attr "type" "branch")]
7026 ; scc insns
7028 (define_expand "seq"
7029   [(set (match_operand:SI 0 "s_register_operand" "")
7030         (eq:SI (match_dup 1) (const_int 0)))]
7031   "TARGET_ARM"
7032   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7035 (define_expand "sne"
7036   [(set (match_operand:SI 0 "s_register_operand" "")
7037         (ne:SI (match_dup 1) (const_int 0)))]
7038   "TARGET_ARM"
7039   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7042 (define_expand "sgt"
7043   [(set (match_operand:SI 0 "s_register_operand" "")
7044         (gt:SI (match_dup 1) (const_int 0)))]
7045   "TARGET_ARM"
7046   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7049 (define_expand "sle"
7050   [(set (match_operand:SI 0 "s_register_operand" "")
7051         (le:SI (match_dup 1) (const_int 0)))]
7052   "TARGET_ARM"
7053   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7056 (define_expand "sge"
7057   [(set (match_operand:SI 0 "s_register_operand" "")
7058         (ge:SI (match_dup 1) (const_int 0)))]
7059   "TARGET_ARM"
7060   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7063 (define_expand "slt"
7064   [(set (match_operand:SI 0 "s_register_operand" "")
7065         (lt:SI (match_dup 1) (const_int 0)))]
7066   "TARGET_ARM"
7067   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7070 (define_expand "sgtu"
7071   [(set (match_operand:SI 0 "s_register_operand" "")
7072         (gtu:SI (match_dup 1) (const_int 0)))]
7073   "TARGET_ARM"
7074   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7077 (define_expand "sleu"
7078   [(set (match_operand:SI 0 "s_register_operand" "")
7079         (leu:SI (match_dup 1) (const_int 0)))]
7080   "TARGET_ARM"
7081   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7084 (define_expand "sgeu"
7085   [(set (match_operand:SI 0 "s_register_operand" "")
7086         (geu:SI (match_dup 1) (const_int 0)))]
7087   "TARGET_ARM"
7088   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7091 (define_expand "sltu"
7092   [(set (match_operand:SI 0 "s_register_operand" "")
7093         (ltu:SI (match_dup 1) (const_int 0)))]
7094   "TARGET_ARM"
7095   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7098 (define_expand "sunordered"
7099   [(set (match_operand:SI 0 "s_register_operand" "")
7100         (unordered:SI (match_dup 1) (const_int 0)))]
7101   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7102   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7103                                       arm_compare_op1);"
7106 (define_expand "sordered"
7107   [(set (match_operand:SI 0 "s_register_operand" "")
7108         (ordered:SI (match_dup 1) (const_int 0)))]
7109   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7110   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7111                                       arm_compare_op1);"
7114 (define_expand "sungt"
7115   [(set (match_operand:SI 0 "s_register_operand" "")
7116         (ungt:SI (match_dup 1) (const_int 0)))]
7117   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7118   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7119                                       arm_compare_op1);"
7122 (define_expand "sunge"
7123   [(set (match_operand:SI 0 "s_register_operand" "")
7124         (unge:SI (match_dup 1) (const_int 0)))]
7125   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7126   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7127                                       arm_compare_op1);"
7130 (define_expand "sunlt"
7131   [(set (match_operand:SI 0 "s_register_operand" "")
7132         (unlt:SI (match_dup 1) (const_int 0)))]
7133   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7134   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7135                                       arm_compare_op1);"
7138 (define_expand "sunle"
7139   [(set (match_operand:SI 0 "s_register_operand" "")
7140         (unle:SI (match_dup 1) (const_int 0)))]
7141   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7142   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7143                                       arm_compare_op1);"
7146 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7147 ;;; simple ARM instructions. 
7149 ; (define_expand "suneq"
7150 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7151 ;       (uneq:SI (match_dup 1) (const_int 0)))]
7152 ;   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7153 ;   "abort ();"
7154 ; )
7156 ; (define_expand "sltgt"
7157 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7158 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
7159 ;   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7160 ;   "abort ();"
7161 ; )
7163 (define_insn "*mov_scc"
7164   [(set (match_operand:SI 0 "s_register_operand" "=r")
7165         (match_operator:SI 1 "arm_comparison_operator"
7166          [(match_operand 2 "cc_register" "") (const_int 0)]))]
7167   "TARGET_ARM"
7168   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7169   [(set_attr "conds" "use")
7170    (set_attr "length" "8")]
7173 (define_insn "*mov_negscc"
7174   [(set (match_operand:SI 0 "s_register_operand" "=r")
7175         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7176                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7177   "TARGET_ARM"
7178   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7179   [(set_attr "conds" "use")
7180    (set_attr "length" "8")]
7183 (define_insn "*mov_notscc"
7184   [(set (match_operand:SI 0 "s_register_operand" "=r")
7185         (not:SI (match_operator:SI 1 "arm_comparison_operator"
7186                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7187   "TARGET_ARM"
7188   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7189   [(set_attr "conds" "use")
7190    (set_attr "length" "8")]
7194 ;; Conditional move insns
7196 (define_expand "movsicc"
7197   [(set (match_operand:SI 0 "s_register_operand" "")
7198         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7199                          (match_operand:SI 2 "arm_not_operand" "")
7200                          (match_operand:SI 3 "arm_not_operand" "")))]
7201   "TARGET_ARM"
7202   "
7203   {
7204     enum rtx_code code = GET_CODE (operands[1]);
7205     rtx ccreg;
7207     if (code == UNEQ || code == LTGT)
7208       FAIL;
7210     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7211     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7212   }"
7215 (define_expand "movsfcc"
7216   [(set (match_operand:SF 0 "s_register_operand" "")
7217         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7218                          (match_operand:SF 2 "s_register_operand" "")
7219                          (match_operand:SF 3 "nonmemory_operand" "")))]
7220   "TARGET_ARM"
7221   "
7222   {
7223     enum rtx_code code = GET_CODE (operands[1]);
7224     rtx ccreg;
7226     if (code == UNEQ || code == LTGT)
7227       FAIL;
7229     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
7230        Otherwise, ensure it is a valid FP add operand */
7231     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7232         || (!arm_float_add_operand (operands[3], SFmode)))
7233       operands[3] = force_reg (SFmode, operands[3]);
7235     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7236     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7237   }"
7240 (define_expand "movdfcc"
7241   [(set (match_operand:DF 0 "s_register_operand" "")
7242         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7243                          (match_operand:DF 2 "s_register_operand" "")
7244                          (match_operand:DF 3 "arm_float_add_operand" "")))]
7245   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7246   "
7247   {
7248     enum rtx_code code = GET_CODE (operands[1]);
7249     rtx ccreg;
7251     if (code == UNEQ || code == LTGT)
7252       FAIL;
7254     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7255     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7256   }"
7259 (define_insn "*movsicc_insn"
7260   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7261         (if_then_else:SI
7262          (match_operator 3 "arm_comparison_operator"
7263           [(match_operand 4 "cc_register" "") (const_int 0)])
7264          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7265          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7266   "TARGET_ARM"
7267   "@
7268    mov%D3\\t%0, %2
7269    mvn%D3\\t%0, #%B2
7270    mov%d3\\t%0, %1
7271    mvn%d3\\t%0, #%B1
7272    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7273    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7274    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7275    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7276   [(set_attr "length" "4,4,4,4,8,8,8,8")
7277    (set_attr "conds" "use")]
7280 (define_insn "*movsfcc_soft_insn"
7281   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7282         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7283                           [(match_operand 4 "cc_register" "") (const_int 0)])
7284                          (match_operand:SF 1 "s_register_operand" "0,r")
7285                          (match_operand:SF 2 "s_register_operand" "r,0")))]
7286   "TARGET_ARM && TARGET_SOFT_FLOAT"
7287   "@
7288    mov%D3\\t%0, %2
7289    mov%d3\\t%0, %1"
7290   [(set_attr "conds" "use")]
7294 ;; Jump and linkage insns
7296 (define_expand "jump"
7297   [(set (pc)
7298         (label_ref (match_operand 0 "" "")))]
7299   "TARGET_EITHER"
7300   ""
7303 (define_insn "*arm_jump"
7304   [(set (pc)
7305         (label_ref (match_operand 0 "" "")))]
7306   "TARGET_ARM"
7307   "*
7308   {
7309     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7310       {
7311         arm_ccfsm_state += 2;
7312         return \"\";
7313       }
7314     return \"b%?\\t%l0\";
7315   }
7316   "
7317   [(set_attr "predicable" "yes")]
7320 (define_insn "*thumb_jump"
7321   [(set (pc)
7322         (label_ref (match_operand 0 "" "")))]
7323   "TARGET_THUMB"
7324   "*
7325   if (get_attr_length (insn) == 2)
7326     return \"b\\t%l0\";
7327   return \"bl\\t%l0\\t%@ far jump\";
7328   "
7329   [(set (attr "far_jump")
7330         (if_then_else
7331             (eq_attr "length" "4")
7332             (const_string "yes")
7333             (const_string "no")))
7334    (set (attr "length") 
7335         (if_then_else
7336             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7337                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
7338             (const_int 2)
7339             (const_int 4)))]
7342 (define_expand "call"
7343   [(parallel [(call (match_operand 0 "memory_operand" "")
7344                     (match_operand 1 "general_operand" ""))
7345               (use (match_operand 2 "" ""))
7346               (clobber (reg:SI LR_REGNUM))])]
7347   "TARGET_EITHER"
7348   "
7349   {
7350     rtx callee;
7351     
7352     /* In an untyped call, we can get NULL for operand 2.  */
7353     if (operands[2] == NULL_RTX)
7354       operands[2] = const0_rtx;
7355       
7356     /* This is to decide if we should generate indirect calls by loading the
7357        32 bit address of the callee into a register before performing the
7358        branch and link.  operand[2] encodes the long_call/short_call
7359        attribute of the function being called.  This attribute is set whenever
7360        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7361        is used, and the short_call attribute can also be set if function is
7362        declared as static or if it has already been defined in the current
7363        compilation unit.  See arm.c and arm.h for info about this.  The third
7364        parameter to arm_is_longcall_p is used to tell it which pattern
7365        invoked it.  */
7366     callee  = XEXP (operands[0], 0);
7367     
7368     if (GET_CODE (callee) != REG
7369        && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7370       XEXP (operands[0], 0) = force_reg (Pmode, callee);
7371   }"
7374 (define_insn "*call_reg_armv5"
7375   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7376          (match_operand 1 "" ""))
7377    (use (match_operand 2 "" ""))
7378    (clobber (reg:SI LR_REGNUM))]
7379   "TARGET_ARM && arm_arch5"
7380   "blx%?\\t%0"
7381   [(set_attr "type" "call")]
7384 (define_insn "*call_reg_arm"
7385   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7386          (match_operand 1 "" ""))
7387    (use (match_operand 2 "" ""))
7388    (clobber (reg:SI LR_REGNUM))]
7389   "TARGET_ARM && !arm_arch5"
7390   "*
7391   return output_call (operands);
7392   "
7393   ;; length is worst case, normally it is only two
7394   [(set_attr "length" "12")
7395    (set_attr "type" "call")]
7398 (define_insn "*call_mem"
7399   [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7400          (match_operand 1 "" ""))
7401    (use (match_operand 2 "" ""))
7402    (clobber (reg:SI LR_REGNUM))]
7403   "TARGET_ARM"
7404   "*
7405   return output_call_mem (operands);
7406   "
7407   [(set_attr "length" "12")
7408    (set_attr "type" "call")]
7411 (define_insn "*call_reg_thumb_v5"
7412   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7413          (match_operand 1 "" ""))
7414    (use (match_operand 2 "" ""))
7415    (clobber (reg:SI LR_REGNUM))]
7416   "TARGET_THUMB && arm_arch5"
7417   "blx\\t%0"
7418   [(set_attr "length" "2")
7419    (set_attr "type" "call")]
7422 (define_insn "*call_reg_thumb"
7423   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7424          (match_operand 1 "" ""))
7425    (use (match_operand 2 "" ""))
7426    (clobber (reg:SI LR_REGNUM))]
7427   "TARGET_THUMB && !arm_arch5"
7428   "*
7429   {
7430     if (TARGET_CALLER_INTERWORKING)
7431       return \"bl\\t%__interwork_call_via_%0\";
7432     else
7433       return \"bl\\t%__call_via_%0\";
7434   }"
7435   [(set_attr "type" "call")]
7438 (define_expand "call_value"
7439   [(parallel [(set (match_operand       0 "" "")
7440                    (call (match_operand 1 "memory_operand" "")
7441                          (match_operand 2 "general_operand" "")))
7442               (use (match_operand 3 "" ""))
7443               (clobber (reg:SI LR_REGNUM))])]
7444   "TARGET_EITHER"
7445   "
7446   {
7447     rtx callee = XEXP (operands[1], 0);
7448     
7449     /* In an untyped call, we can get NULL for operand 2.  */
7450     if (operands[3] == 0)
7451       operands[3] = const0_rtx;
7452       
7453     /* See the comment in define_expand \"call\".  */
7454     if (GET_CODE (callee) != REG
7455         && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7456       XEXP (operands[1], 0) = force_reg (Pmode, callee);
7457   }"
7460 (define_insn "*call_value_reg_armv5"
7461   [(set (match_operand 0 "" "")
7462         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7463               (match_operand 2 "" "")))
7464    (use (match_operand 3 "" ""))
7465    (clobber (reg:SI LR_REGNUM))]
7466   "TARGET_ARM && arm_arch5"
7467   "blx%?\\t%1"
7468   [(set_attr "type" "call")]
7471 (define_insn "*call_value_reg_arm"
7472   [(set (match_operand 0 "" "")
7473         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7474               (match_operand 2 "" "")))
7475    (use (match_operand 3 "" ""))
7476    (clobber (reg:SI LR_REGNUM))]
7477   "TARGET_ARM && !arm_arch5"
7478   "*
7479   return output_call (&operands[1]);
7480   "
7481   [(set_attr "length" "12")
7482    (set_attr "type" "call")]
7485 (define_insn "*call_value_mem"
7486   [(set (match_operand 0 "" "")
7487         (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7488               (match_operand 2 "" "")))
7489    (use (match_operand 3 "" ""))
7490    (clobber (reg:SI LR_REGNUM))]
7491   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7492   "*
7493   return output_call_mem (&operands[1]);
7494   "
7495   [(set_attr "length" "12")
7496    (set_attr "type" "call")]
7499 (define_insn "*call_value_reg_thumb_v5"
7500   [(set (match_operand 0 "" "")
7501         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7502               (match_operand 2 "" "")))
7503    (use (match_operand 3 "" ""))
7504    (clobber (reg:SI LR_REGNUM))]
7505   "TARGET_THUMB && arm_arch5"
7506   "blx\\t%1"
7507   [(set_attr "length" "2")
7508    (set_attr "type" "call")]
7511 (define_insn "*call_value_reg_thumb"
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   "*
7519   {
7520     if (TARGET_CALLER_INTERWORKING)
7521       return \"bl\\t%__interwork_call_via_%1\";
7522     else
7523       return \"bl\\t%__call_via_%1\";
7524   }"
7525   [(set_attr "type" "call")]
7528 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7529 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7531 (define_insn "*call_symbol"
7532   [(call (mem:SI (match_operand:SI 0 "" ""))
7533          (match_operand 1 "" ""))
7534    (use (match_operand 2 "" ""))
7535    (clobber (reg:SI LR_REGNUM))]
7536   "TARGET_ARM
7537    && (GET_CODE (operands[0]) == SYMBOL_REF)
7538    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7539   "*
7540   {
7541     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7542   }"
7543   [(set_attr "type" "call")]
7546 (define_insn "*call_value_symbol"
7547   [(set (match_operand 0 "s_register_operand" "")
7548         (call (mem:SI (match_operand:SI 1 "" ""))
7549         (match_operand:SI 2 "" "")))
7550    (use (match_operand 3 "" ""))
7551    (clobber (reg:SI LR_REGNUM))]
7552   "TARGET_ARM
7553    && (GET_CODE (operands[1]) == SYMBOL_REF)
7554    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7555   "*
7556   {
7557     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7558   }"
7559   [(set_attr "type" "call")]
7562 (define_insn "*call_insn"
7563   [(call (mem:SI (match_operand:SI 0 "" ""))
7564          (match_operand:SI 1 "" ""))
7565    (use (match_operand 2 "" ""))
7566    (clobber (reg:SI LR_REGNUM))]
7567   "TARGET_THUMB
7568    && GET_CODE (operands[0]) == SYMBOL_REF
7569    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7570   "bl\\t%a0"
7571   [(set_attr "length" "4")
7572    (set_attr "type" "call")]
7575 (define_insn "*call_value_insn"
7576   [(set (match_operand 0 "register_operand" "")
7577         (call (mem:SI (match_operand 1 "" ""))
7578               (match_operand 2 "" "")))
7579    (use (match_operand 3 "" ""))
7580    (clobber (reg:SI LR_REGNUM))]
7581   "TARGET_THUMB
7582    && GET_CODE (operands[1]) == SYMBOL_REF
7583    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7584   "bl\\t%a1"
7585   [(set_attr "length" "4")
7586    (set_attr "type" "call")]
7589 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7590 (define_expand "sibcall"
7591   [(parallel [(call (match_operand 0 "memory_operand" "")
7592                     (match_operand 1 "general_operand" ""))
7593               (return)
7594               (use (match_operand 2 "" ""))])]
7595   "TARGET_ARM"
7596   "
7597   {
7598     if (operands[2] == NULL_RTX)
7599       operands[2] = const0_rtx;
7600   }"
7603 (define_expand "sibcall_value"
7604   [(parallel [(set (match_operand 0 "register_operand" "")
7605                    (call (match_operand 1 "memory_operand" "")
7606                          (match_operand 2 "general_operand" "")))
7607               (return)
7608               (use (match_operand 3 "" ""))])]
7609   "TARGET_ARM"
7610   "
7611   {
7612     if (operands[3] == NULL_RTX)
7613       operands[3] = const0_rtx;
7614   }"
7617 (define_insn "*sibcall_insn"
7618  [(call (mem:SI (match_operand:SI 0 "" "X"))
7619         (match_operand 1 "" ""))
7620   (return)
7621   (use (match_operand 2 "" ""))]
7622   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7623   "*
7624   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7625   "
7626   [(set_attr "type" "call")]
7629 (define_insn "*sibcall_value_insn"
7630  [(set (match_operand 0 "s_register_operand" "")
7631        (call (mem:SI (match_operand:SI 1 "" "X"))
7632              (match_operand 2 "" "")))
7633   (return)
7634   (use (match_operand 3 "" ""))]
7635   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7636   "*
7637   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7638   "
7639   [(set_attr "type" "call")]
7642 ;; Often the return insn will be the same as loading from memory, so set attr
7643 (define_insn "return"
7644   [(return)]
7645   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7646   "*
7647   {
7648     if (arm_ccfsm_state == 2)
7649       {
7650         arm_ccfsm_state += 2;
7651         return \"\";
7652       }
7653     return output_return_instruction (const_true_rtx, TRUE, FALSE);
7654   }"
7655   [(set_attr "type" "load1")
7656    (set_attr "length" "12")
7657    (set_attr "predicable" "yes")]
7660 (define_insn "*cond_return"
7661   [(set (pc)
7662         (if_then_else (match_operator 0 "arm_comparison_operator"
7663                        [(match_operand 1 "cc_register" "") (const_int 0)])
7664                       (return)
7665                       (pc)))]
7666   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7667   "*
7668   {
7669     if (arm_ccfsm_state == 2)
7670       {
7671         arm_ccfsm_state += 2;
7672         return \"\";
7673       }
7674     return output_return_instruction (operands[0], TRUE, FALSE);
7675   }"
7676   [(set_attr "conds" "use")
7677    (set_attr "length" "12")
7678    (set_attr "type" "load1")]
7681 (define_insn "*cond_return_inverted"
7682   [(set (pc)
7683         (if_then_else (match_operator 0 "arm_comparison_operator"
7684                        [(match_operand 1 "cc_register" "") (const_int 0)])
7685                       (pc)
7686                       (return)))]
7687   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7688   "*
7689   {
7690     if (arm_ccfsm_state == 2)
7691       {
7692         arm_ccfsm_state += 2;
7693         return \"\";
7694       }
7695     return output_return_instruction (operands[0], TRUE, TRUE);
7696   }"
7697   [(set_attr "conds" "use")
7698    (set_attr "length" "12")
7699    (set_attr "type" "load1")]
7702 ;; Generate a sequence of instructions to determine if the processor is
7703 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7704 ;; mask.
7706 (define_expand "return_addr_mask"
7707   [(set (match_dup 1)
7708       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7709                        (const_int 0)))
7710    (set (match_operand:SI 0 "s_register_operand" "")
7711       (if_then_else:SI (eq (match_dup 1) (const_int 0))
7712                        (const_int -1)
7713                        (const_int 67108860)))] ; 0x03fffffc
7714   "TARGET_ARM"
7715   "
7716   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7717   ")
7719 (define_insn "*check_arch2"
7720   [(set (match_operand:CC_NOOV 0 "cc_register" "")
7721       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7722                        (const_int 0)))]
7723   "TARGET_ARM"
7724   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7725   [(set_attr "length" "8")
7726    (set_attr "conds" "set")]
7729 ;; Call subroutine returning any type.
7731 (define_expand "untyped_call"
7732   [(parallel [(call (match_operand 0 "" "")
7733                     (const_int 0))
7734               (match_operand 1 "" "")
7735               (match_operand 2 "" "")])]
7736   "TARGET_ARM"
7737   "
7738   {
7739     int i;
7741     emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
7743     for (i = 0; i < XVECLEN (operands[2], 0); i++)
7744       {
7745         rtx set = XVECEXP (operands[2], 0, i);
7747         emit_move_insn (SET_DEST (set), SET_SRC (set));
7748       }
7750     /* The optimizer does not know that the call sets the function value
7751        registers we stored in the result block.  We avoid problems by
7752        claiming that all hard registers are used and clobbered at this
7753        point.  */
7754     emit_insn (gen_blockage ());
7756     DONE;
7757   }"
7760 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7761 ;; all of memory.  This blocks insns from being moved across this point.
7763 (define_insn "blockage"
7764   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
7765   "TARGET_EITHER"
7766   ""
7767   [(set_attr "length" "0")
7768    (set_attr "type" "block")]
7771 (define_expand "casesi"
7772   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
7773    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
7774    (match_operand:SI 2 "const_int_operand" "")  ; total range
7775    (match_operand:SI 3 "" "")                   ; table label
7776    (match_operand:SI 4 "" "")]                  ; Out of range label
7777   "TARGET_ARM"
7778   "
7779   {
7780     rtx reg;
7781     if (operands[1] != const0_rtx)
7782       {
7783         reg = gen_reg_rtx (SImode);
7785         emit_insn (gen_addsi3 (reg, operands[0],
7786                                GEN_INT (-INTVAL (operands[1]))));
7787         operands[0] = reg;
7788       }
7790     if (!const_ok_for_arm (INTVAL (operands[2])))
7791       operands[2] = force_reg (SImode, operands[2]);
7793     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
7794                                          operands[4]));
7795     DONE;
7796   }"
7799 ;; The USE in this pattern is needed to tell flow analysis that this is
7800 ;; a CASESI insn.  It has no other purpose.
7801 (define_insn "casesi_internal"
7802   [(parallel [(set (pc)
7803                (if_then_else
7804                 (leu (match_operand:SI 0 "s_register_operand" "r")
7805                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
7806                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
7807                                  (label_ref (match_operand 2 "" ""))))
7808                 (label_ref (match_operand 3 "" ""))))
7809               (clobber (reg:CC CC_REGNUM))
7810               (use (label_ref (match_dup 2)))])]
7811   "TARGET_ARM"
7812   "*
7813     if (flag_pic)
7814       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
7815     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
7816   "
7817   [(set_attr "conds" "clob")
7818    (set_attr "length" "12")]
7821 (define_expand "indirect_jump"
7822   [(set (pc)
7823         (match_operand:SI 0 "s_register_operand" ""))]
7824   "TARGET_EITHER"
7825   ""
7828 ;; NB Never uses BX.
7829 (define_insn "*arm_indirect_jump"
7830   [(set (pc)
7831         (match_operand:SI 0 "s_register_operand" "r"))]
7832   "TARGET_ARM"
7833   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
7834   [(set_attr "predicable" "yes")]
7837 (define_insn "*load_indirect_jump"
7838   [(set (pc)
7839         (match_operand:SI 0 "memory_operand" "m"))]
7840   "TARGET_ARM"
7841   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
7842   [(set_attr "type" "load1")
7843    (set_attr "pool_range" "4096")
7844    (set_attr "neg_pool_range" "4084")
7845    (set_attr "predicable" "yes")]
7848 ;; NB Never uses BX.
7849 (define_insn "*thumb_indirect_jump"
7850   [(set (pc)
7851         (match_operand:SI 0 "register_operand" "l*r"))]
7852   "TARGET_THUMB"
7853   "mov\\tpc, %0"
7854   [(set_attr "conds" "clob")
7855    (set_attr "length" "2")]
7859 ;; Misc insns
7861 (define_insn "nop"
7862   [(const_int 0)]
7863   "TARGET_EITHER"
7864   "*
7865   if (TARGET_ARM)
7866     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
7867   return  \"mov\\tr8, r8\";
7868   "
7869   [(set (attr "length")
7870         (if_then_else (eq_attr "is_thumb" "yes")
7871                       (const_int 2)
7872                       (const_int 4)))]
7876 ;; Patterns to allow combination of arithmetic, cond code and shifts
7878 (define_insn "*arith_shiftsi"
7879   [(set (match_operand:SI 0 "s_register_operand" "=r")
7880         (match_operator:SI 1 "shiftable_operator"
7881           [(match_operator:SI 3 "shift_operator"
7882              [(match_operand:SI 4 "s_register_operand" "r")
7883               (match_operand:SI 5 "reg_or_int_operand" "rI")])
7884            (match_operand:SI 2 "s_register_operand" "r")]))]
7885   "TARGET_ARM"
7886   "%i1%?\\t%0, %2, %4%S3"
7887   [(set_attr "predicable" "yes")
7888    (set_attr "shift" "4")
7889    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7890                       (const_string "alu_shift")
7891                       (const_string "alu_shift_reg")))]
7894 (define_split
7895   [(set (match_operand:SI 0 "s_register_operand" "")
7896         (match_operator:SI 1 "shiftable_operator"
7897          [(match_operator:SI 2 "shiftable_operator"
7898            [(match_operator:SI 3 "shift_operator"
7899              [(match_operand:SI 4 "s_register_operand" "")
7900               (match_operand:SI 5 "reg_or_int_operand" "")])
7901             (match_operand:SI 6 "s_register_operand" "")])
7902           (match_operand:SI 7 "arm_rhs_operand" "")]))
7903    (clobber (match_operand:SI 8 "s_register_operand" ""))]
7904   "TARGET_ARM"
7905   [(set (match_dup 8)
7906         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7907                          (match_dup 6)]))
7908    (set (match_dup 0)
7909         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
7910   "")
7912 (define_insn "*arith_shiftsi_compare0"
7913   [(set (reg:CC_NOOV CC_REGNUM)
7914         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7915                           [(match_operator:SI 3 "shift_operator"
7916                             [(match_operand:SI 4 "s_register_operand" "r")
7917                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
7918                            (match_operand:SI 2 "s_register_operand" "r")])
7919                          (const_int 0)))
7920    (set (match_operand:SI 0 "s_register_operand" "=r")
7921         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7922                          (match_dup 2)]))]
7923   "TARGET_ARM"
7924   "%i1%?s\\t%0, %2, %4%S3"
7925   [(set_attr "conds" "set")
7926    (set_attr "shift" "4")
7927    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7928                       (const_string "alu_shift")
7929                       (const_string "alu_shift_reg")))]
7932 (define_insn "*arith_shiftsi_compare0_scratch"
7933   [(set (reg:CC_NOOV CC_REGNUM)
7934         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7935                           [(match_operator:SI 3 "shift_operator"
7936                             [(match_operand:SI 4 "s_register_operand" "r")
7937                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
7938                            (match_operand:SI 2 "s_register_operand" "r")])
7939                          (const_int 0)))
7940    (clobber (match_scratch:SI 0 "=r"))]
7941   "TARGET_ARM"
7942   "%i1%?s\\t%0, %2, %4%S3"
7943   [(set_attr "conds" "set")
7944    (set_attr "shift" "4")
7945    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7946                       (const_string "alu_shift")
7947                       (const_string "alu_shift_reg")))]
7950 (define_insn "*sub_shiftsi"
7951   [(set (match_operand:SI 0 "s_register_operand" "=r")
7952         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7953                   (match_operator:SI 2 "shift_operator"
7954                    [(match_operand:SI 3 "s_register_operand" "r")
7955                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
7956   "TARGET_ARM"
7957   "sub%?\\t%0, %1, %3%S2"
7958   [(set_attr "predicable" "yes")
7959    (set_attr "shift" "3")
7960    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7961                       (const_string "alu_shift")
7962                       (const_string "alu_shift_reg")))]
7965 (define_insn "*sub_shiftsi_compare0"
7966   [(set (reg:CC_NOOV CC_REGNUM)
7967         (compare:CC_NOOV
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          (const_int 0)))
7973    (set (match_operand:SI 0 "s_register_operand" "=r")
7974         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7975                                                  (match_dup 4)])))]
7976   "TARGET_ARM"
7977   "sub%?s\\t%0, %1, %3%S2"
7978   [(set_attr "conds" "set")
7979    (set_attr "shift" "3")
7980    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7981                       (const_string "alu_shift")
7982                       (const_string "alu_shift_reg")))]
7985 (define_insn "*sub_shiftsi_compare0_scratch"
7986   [(set (reg:CC_NOOV CC_REGNUM)
7987         (compare:CC_NOOV
7988          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7989                    (match_operator:SI 2 "shift_operator"
7990                     [(match_operand:SI 3 "s_register_operand" "r")
7991                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7992          (const_int 0)))
7993    (clobber (match_scratch:SI 0 "=r"))]
7994   "TARGET_ARM"
7995   "sub%?s\\t%0, %1, %3%S2"
7996   [(set_attr "conds" "set")
7997    (set_attr "shift" "3")
7998    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7999                       (const_string "alu_shift")
8000                       (const_string "alu_shift_reg")))]
8005 (define_insn "*and_scc"
8006   [(set (match_operand:SI 0 "s_register_operand" "=r")
8007         (and:SI (match_operator:SI 1 "arm_comparison_operator"
8008                  [(match_operand 3 "cc_register" "") (const_int 0)])
8009                 (match_operand:SI 2 "s_register_operand" "r")))]
8010   "TARGET_ARM"
8011   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8012   [(set_attr "conds" "use")
8013    (set_attr "length" "8")]
8016 (define_insn "*ior_scc"
8017   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8018         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8019                  [(match_operand 3 "cc_register" "") (const_int 0)])
8020                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8021   "TARGET_ARM"
8022   "@
8023    orr%d2\\t%0, %1, #1
8024    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8025   [(set_attr "conds" "use")
8026    (set_attr "length" "4,8")]
8029 (define_insn "*compare_scc"
8030   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8031         (match_operator:SI 1 "arm_comparison_operator"
8032          [(match_operand:SI 2 "s_register_operand" "r,r")
8033           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8034    (clobber (reg:CC CC_REGNUM))]
8035   "TARGET_ARM"
8036   "*
8037     if (operands[3] == const0_rtx)
8038       {
8039         if (GET_CODE (operands[1]) == LT)
8040           return \"mov\\t%0, %2, lsr #31\";
8042         if (GET_CODE (operands[1]) == GE)
8043           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8045         if (GET_CODE (operands[1]) == EQ)
8046           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8047       }
8049     if (GET_CODE (operands[1]) == NE)
8050       {
8051         if (which_alternative == 1)
8052           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8053         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8054       }
8055     if (which_alternative == 1)
8056       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8057     else
8058       output_asm_insn (\"cmp\\t%2, %3\", operands);
8059     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8060   "
8061   [(set_attr "conds" "clob")
8062    (set_attr "length" "12")]
8065 (define_insn "*cond_move"
8066   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8067         (if_then_else:SI (match_operator 3 "equality_operator"
8068                           [(match_operator 4 "arm_comparison_operator"
8069                             [(match_operand 5 "cc_register" "") (const_int 0)])
8070                            (const_int 0)])
8071                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8072                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8073   "TARGET_ARM"
8074   "*
8075     if (GET_CODE (operands[3]) == NE)
8076       {
8077         if (which_alternative != 1)
8078           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8079         if (which_alternative != 0)
8080           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8081         return \"\";
8082       }
8083     if (which_alternative != 0)
8084       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8085     if (which_alternative != 1)
8086       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8087     return \"\";
8088   "
8089   [(set_attr "conds" "use")
8090    (set_attr "length" "4,4,8")]
8093 (define_insn "*cond_arith"
8094   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8095         (match_operator:SI 5 "shiftable_operator" 
8096          [(match_operator:SI 4 "arm_comparison_operator"
8097            [(match_operand:SI 2 "s_register_operand" "r,r")
8098             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8099           (match_operand:SI 1 "s_register_operand" "0,?r")]))
8100    (clobber (reg:CC CC_REGNUM))]
8101   "TARGET_ARM"
8102   "*
8103     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8104       return \"%i5\\t%0, %1, %2, lsr #31\";
8106     output_asm_insn (\"cmp\\t%2, %3\", operands);
8107     if (GET_CODE (operands[5]) == AND)
8108       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8109     else if (GET_CODE (operands[5]) == MINUS)
8110       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8111     else if (which_alternative != 0)
8112       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8113     return \"%i5%d4\\t%0, %1, #1\";
8114   "
8115   [(set_attr "conds" "clob")
8116    (set_attr "length" "12")]
8119 (define_insn "*cond_sub"
8120   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8121         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8122                   (match_operator:SI 4 "arm_comparison_operator"
8123                    [(match_operand:SI 2 "s_register_operand" "r,r")
8124                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8125    (clobber (reg:CC CC_REGNUM))]
8126   "TARGET_ARM"
8127   "*
8128     output_asm_insn (\"cmp\\t%2, %3\", operands);
8129     if (which_alternative != 0)
8130       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8131     return \"sub%d4\\t%0, %1, #1\";
8132   "
8133   [(set_attr "conds" "clob")
8134    (set_attr "length" "8,12")]
8137 (define_insn "*cmp_ite0"
8138   [(set (match_operand 6 "dominant_cc_register" "")
8139         (compare
8140          (if_then_else:SI
8141           (match_operator 4 "arm_comparison_operator"
8142            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8143             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8144           (match_operator:SI 5 "arm_comparison_operator"
8145            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8146             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8147           (const_int 0))
8148          (const_int 0)))]
8149   "TARGET_ARM"
8150   "*
8151   {
8152     static const char * const opcodes[4][2] =
8153     {
8154       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8155        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8156       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8157        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8158       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8159        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8160       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8161        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8162     };
8163     int swap =
8164       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8166     return opcodes[which_alternative][swap];
8167   }"
8168   [(set_attr "conds" "set")
8169    (set_attr "length" "8")]
8172 (define_insn "*cmp_ite1"
8173   [(set (match_operand 6 "dominant_cc_register" "")
8174         (compare
8175          (if_then_else:SI
8176           (match_operator 4 "arm_comparison_operator"
8177            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8178             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8179           (match_operator:SI 5 "arm_comparison_operator"
8180            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8181             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8182           (const_int 1))
8183          (const_int 0)))]
8184   "TARGET_ARM"
8185   "*
8186   {
8187     static const char * const opcodes[4][2] =
8188     {
8189       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8190        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8191       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8192        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8193       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8194        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8195       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8196        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8197     };
8198     int swap =
8199       comparison_dominates_p (GET_CODE (operands[5]),
8200                               reverse_condition (GET_CODE (operands[4])));
8202     return opcodes[which_alternative][swap];
8203   }"
8204   [(set_attr "conds" "set")
8205    (set_attr "length" "8")]
8208 (define_insn "*cmp_and"
8209   [(set (match_operand 6 "dominant_cc_register" "")
8210         (compare
8211          (and:SI
8212           (match_operator 4 "arm_comparison_operator"
8213            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8214             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8215           (match_operator:SI 5 "arm_comparison_operator"
8216            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8217             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8218          (const_int 0)))]
8219   "TARGET_ARM"
8220   "*
8221   {
8222     static const char *const opcodes[4][2] =
8223     {
8224       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8225        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8226       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8227        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8228       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8229        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8230       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8231        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8232     };
8233     int swap =
8234       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8236     return opcodes[which_alternative][swap];
8237   }"
8238   [(set_attr "conds" "set")
8239    (set_attr "predicable" "no")
8240    (set_attr "length" "8")]
8243 (define_insn "*cmp_ior"
8244   [(set (match_operand 6 "dominant_cc_register" "")
8245         (compare
8246          (ior:SI
8247           (match_operator 4 "arm_comparison_operator"
8248            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8249             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8250           (match_operator:SI 5 "arm_comparison_operator"
8251            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8252             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8253          (const_int 0)))]
8254   "TARGET_ARM"
8255   "*
8257   static const char *const opcodes[4][2] =
8258   {
8259     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8260      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8261     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8262      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8263     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8264      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8265     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8266      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8267   };
8268   int swap =
8269     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8271   return opcodes[which_alternative][swap];
8274   [(set_attr "conds" "set")
8275    (set_attr "length" "8")]
8278 (define_insn_and_split "*ior_scc_scc"
8279   [(set (match_operand:SI 0 "s_register_operand" "=r")
8280         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8281                  [(match_operand:SI 1 "s_register_operand" "r")
8282                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8283                 (match_operator:SI 6 "arm_comparison_operator"
8284                  [(match_operand:SI 4 "s_register_operand" "r")
8285                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8286    (clobber (reg:CC CC_REGNUM))]
8287   "TARGET_ARM
8288    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8289        != CCmode)"
8290   "#"
8291   "TARGET_ARM && reload_completed"
8292   [(set (match_dup 7)
8293         (compare
8294          (ior:SI
8295           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8296           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8297          (const_int 0)))
8298    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8299   "operands[7]
8300      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8301                                                   DOM_CC_X_OR_Y),
8302                     CC_REGNUM);"
8303   [(set_attr "conds" "clob")
8304    (set_attr "length" "16")])
8306 ; If the above pattern is followed by a CMP insn, then the compare is 
8307 ; redundant, since we can rework the conditional instruction that follows.
8308 (define_insn_and_split "*ior_scc_scc_cmp"
8309   [(set (match_operand 0 "dominant_cc_register" "")
8310         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8311                           [(match_operand:SI 1 "s_register_operand" "r")
8312                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8313                          (match_operator:SI 6 "arm_comparison_operator"
8314                           [(match_operand:SI 4 "s_register_operand" "r")
8315                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8316                  (const_int 0)))
8317    (set (match_operand:SI 7 "s_register_operand" "=r")
8318         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8319                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8320   "TARGET_ARM"
8321   "#"
8322   "TARGET_ARM && reload_completed"
8323   [(set (match_dup 0)
8324         (compare
8325          (ior:SI
8326           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8327           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8328          (const_int 0)))
8329    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8330   ""
8331   [(set_attr "conds" "set")
8332    (set_attr "length" "16")])
8334 (define_insn_and_split "*and_scc_scc"
8335   [(set (match_operand:SI 0 "s_register_operand" "=r")
8336         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8337                  [(match_operand:SI 1 "s_register_operand" "r")
8338                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8339                 (match_operator:SI 6 "arm_comparison_operator"
8340                  [(match_operand:SI 4 "s_register_operand" "r")
8341                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8342    (clobber (reg:CC CC_REGNUM))]
8343   "TARGET_ARM
8344    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8345        != CCmode)"
8346   "#"
8347   "TARGET_ARM && reload_completed
8348    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8349        != CCmode)"
8350   [(set (match_dup 7)
8351         (compare
8352          (and:SI
8353           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8354           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8355          (const_int 0)))
8356    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8357   "operands[7]
8358      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8359                                                   DOM_CC_X_AND_Y),
8360                     CC_REGNUM);"
8361   [(set_attr "conds" "clob")
8362    (set_attr "length" "16")])
8364 ; If the above pattern is followed by a CMP insn, then the compare is 
8365 ; redundant, since we can rework the conditional instruction that follows.
8366 (define_insn_and_split "*and_scc_scc_cmp"
8367   [(set (match_operand 0 "dominant_cc_register" "")
8368         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8369                           [(match_operand:SI 1 "s_register_operand" "r")
8370                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8371                          (match_operator:SI 6 "arm_comparison_operator"
8372                           [(match_operand:SI 4 "s_register_operand" "r")
8373                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8374                  (const_int 0)))
8375    (set (match_operand:SI 7 "s_register_operand" "=r")
8376         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8377                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8378   "TARGET_ARM"
8379   "#"
8380   "TARGET_ARM && reload_completed"
8381   [(set (match_dup 0)
8382         (compare
8383          (and:SI
8384           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8385           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8386          (const_int 0)))
8387    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8388   ""
8389   [(set_attr "conds" "set")
8390    (set_attr "length" "16")])
8392 ;; If there is no dominance in the comparison, then we can still save an
8393 ;; instruction in the AND case, since we can know that the second compare
8394 ;; need only zero the value if false (if true, then the value is already
8395 ;; correct).
8396 (define_insn_and_split "*and_scc_scc_nodom"
8397   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8398         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8399                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
8400                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8401                 (match_operator:SI 6 "arm_comparison_operator"
8402                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
8403                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8404    (clobber (reg:CC CC_REGNUM))]
8405   "TARGET_ARM
8406    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8407        == CCmode)"
8408   "#"
8409   "TARGET_ARM && reload_completed"
8410   [(parallel [(set (match_dup 0)
8411                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8412               (clobber (reg:CC CC_REGNUM))])
8413    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8414    (set (match_dup 0)
8415         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8416                          (match_dup 0)
8417                          (const_int 0)))]
8418   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8419                                               operands[4], operands[5]),
8420                               CC_REGNUM);
8421    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8422                                   operands[5]);"
8423   [(set_attr "conds" "clob")
8424    (set_attr "length" "20")])
8426 (define_split
8427   [(set (reg:CC_NOOV CC_REGNUM)
8428         (compare:CC_NOOV (ior:SI
8429                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8430                                   (const_int 1))
8431                           (match_operator:SI 1 "comparison_operator"
8432                            [(match_operand:SI 2 "s_register_operand" "")
8433                             (match_operand:SI 3 "arm_add_operand" "")]))
8434                          (const_int 0)))
8435    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8436   "TARGET_ARM"
8437   [(set (match_dup 4)
8438         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8439                 (match_dup 0)))
8440    (set (reg:CC_NOOV CC_REGNUM)
8441         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8442                          (const_int 0)))]
8443   "")
8445 (define_split
8446   [(set (reg:CC_NOOV CC_REGNUM)
8447         (compare:CC_NOOV (ior:SI
8448                           (match_operator:SI 1 "comparison_operator"
8449                            [(match_operand:SI 2 "s_register_operand" "")
8450                             (match_operand:SI 3 "arm_add_operand" "")])
8451                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8452                                   (const_int 1)))
8453                          (const_int 0)))
8454    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8455   "TARGET_ARM"
8456   [(set (match_dup 4)
8457         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8458                 (match_dup 0)))
8459    (set (reg:CC_NOOV CC_REGNUM)
8460         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8461                          (const_int 0)))]
8462   "")
8464 (define_insn "*negscc"
8465   [(set (match_operand:SI 0 "s_register_operand" "=r")
8466         (neg:SI (match_operator 3 "arm_comparison_operator"
8467                  [(match_operand:SI 1 "s_register_operand" "r")
8468                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8469    (clobber (reg:CC CC_REGNUM))]
8470   "TARGET_ARM"
8471   "*
8472   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8473     return \"mov\\t%0, %1, asr #31\";
8475   if (GET_CODE (operands[3]) == NE)
8476     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8478   if (GET_CODE (operands[3]) == GT)
8479     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8481   output_asm_insn (\"cmp\\t%1, %2\", operands);
8482   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8483   return \"mvn%d3\\t%0, #0\";
8484   "
8485   [(set_attr "conds" "clob")
8486    (set_attr "length" "12")]
8489 (define_insn "movcond"
8490   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8491         (if_then_else:SI
8492          (match_operator 5 "arm_comparison_operator"
8493           [(match_operand:SI 3 "s_register_operand" "r,r,r")
8494            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8495          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8496          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8497    (clobber (reg:CC CC_REGNUM))]
8498   "TARGET_ARM"
8499   "*
8500   if (GET_CODE (operands[5]) == LT
8501       && (operands[4] == const0_rtx))
8502     {
8503       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8504         {
8505           if (operands[2] == const0_rtx)
8506             return \"and\\t%0, %1, %3, asr #31\";
8507           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8508         }
8509       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8510         {
8511           if (operands[1] == const0_rtx)
8512             return \"bic\\t%0, %2, %3, asr #31\";
8513           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8514         }
8515       /* The only case that falls through to here is when both ops 1 & 2
8516          are constants.  */
8517     }
8519   if (GET_CODE (operands[5]) == GE
8520       && (operands[4] == const0_rtx))
8521     {
8522       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8523         {
8524           if (operands[2] == const0_rtx)
8525             return \"bic\\t%0, %1, %3, asr #31\";
8526           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8527         }
8528       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8529         {
8530           if (operands[1] == const0_rtx)
8531             return \"and\\t%0, %2, %3, asr #31\";
8532           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8533         }
8534       /* The only case that falls through to here is when both ops 1 & 2
8535          are constants.  */
8536     }
8537   if (GET_CODE (operands[4]) == CONST_INT
8538       && !const_ok_for_arm (INTVAL (operands[4])))
8539     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8540   else
8541     output_asm_insn (\"cmp\\t%3, %4\", operands);
8542   if (which_alternative != 0)
8543     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8544   if (which_alternative != 1)
8545     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8546   return \"\";
8547   "
8548   [(set_attr "conds" "clob")
8549    (set_attr "length" "8,8,12")]
8552 (define_insn "*ifcompare_plus_move"
8553   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8554         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8555                           [(match_operand:SI 4 "s_register_operand" "r,r")
8556                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8557                          (plus:SI
8558                           (match_operand:SI 2 "s_register_operand" "r,r")
8559                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8560                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8561    (clobber (reg:CC CC_REGNUM))]
8562   "TARGET_ARM"
8563   "#"
8564   [(set_attr "conds" "clob")
8565    (set_attr "length" "8,12")]
8568 (define_insn "*if_plus_move"
8569   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8570         (if_then_else:SI
8571          (match_operator 4 "arm_comparison_operator"
8572           [(match_operand 5 "cc_register" "") (const_int 0)])
8573          (plus:SI
8574           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8575           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8576          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8577   "TARGET_ARM"
8578   "@
8579    add%d4\\t%0, %2, %3
8580    sub%d4\\t%0, %2, #%n3
8581    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8582    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8583   [(set_attr "conds" "use")
8584    (set_attr "length" "4,4,8,8")
8585    (set_attr "type" "*,*,*,*")]
8588 (define_insn "*ifcompare_move_plus"
8589   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8590         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8591                           [(match_operand:SI 4 "s_register_operand" "r,r")
8592                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8593                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8594                          (plus:SI
8595                           (match_operand:SI 2 "s_register_operand" "r,r")
8596                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8597    (clobber (reg:CC CC_REGNUM))]
8598   "TARGET_ARM"
8599   "#"
8600   [(set_attr "conds" "clob")
8601    (set_attr "length" "8,12")]
8604 (define_insn "*if_move_plus"
8605   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8606         (if_then_else:SI
8607          (match_operator 4 "arm_comparison_operator"
8608           [(match_operand 5 "cc_register" "") (const_int 0)])
8609          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8610          (plus:SI
8611           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8612           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8613   "TARGET_ARM"
8614   "@
8615    add%D4\\t%0, %2, %3
8616    sub%D4\\t%0, %2, #%n3
8617    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8618    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8619   [(set_attr "conds" "use")
8620    (set_attr "length" "4,4,8,8")
8621    (set_attr "type" "*,*,*,*")]
8624 (define_insn "*ifcompare_arith_arith"
8625   [(set (match_operand:SI 0 "s_register_operand" "=r")
8626         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8627                           [(match_operand:SI 5 "s_register_operand" "r")
8628                            (match_operand:SI 6 "arm_add_operand" "rIL")])
8629                          (match_operator:SI 8 "shiftable_operator"
8630                           [(match_operand:SI 1 "s_register_operand" "r")
8631                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8632                          (match_operator:SI 7 "shiftable_operator"
8633                           [(match_operand:SI 3 "s_register_operand" "r")
8634                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8635    (clobber (reg:CC CC_REGNUM))]
8636   "TARGET_ARM"
8637   "#"
8638   [(set_attr "conds" "clob")
8639    (set_attr "length" "12")]
8642 (define_insn "*if_arith_arith"
8643   [(set (match_operand:SI 0 "s_register_operand" "=r")
8644         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8645                           [(match_operand 8 "cc_register" "") (const_int 0)])
8646                          (match_operator:SI 6 "shiftable_operator"
8647                           [(match_operand:SI 1 "s_register_operand" "r")
8648                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8649                          (match_operator:SI 7 "shiftable_operator"
8650                           [(match_operand:SI 3 "s_register_operand" "r")
8651                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8652   "TARGET_ARM"
8653   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8654   [(set_attr "conds" "use")
8655    (set_attr "length" "8")]
8658 (define_insn "*ifcompare_arith_move"
8659   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8660         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8661                           [(match_operand:SI 2 "s_register_operand" "r,r")
8662                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8663                          (match_operator:SI 7 "shiftable_operator"
8664                           [(match_operand:SI 4 "s_register_operand" "r,r")
8665                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8666                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8667    (clobber (reg:CC CC_REGNUM))]
8668   "TARGET_ARM"
8669   "*
8670   /* If we have an operation where (op x 0) is the identity operation and
8671      the conditional operator is LT or GE and we are comparing against zero and
8672      everything is in registers then we can do this in two instructions.  */
8673   if (operands[3] == const0_rtx
8674       && GET_CODE (operands[7]) != AND
8675       && GET_CODE (operands[5]) == REG
8676       && GET_CODE (operands[1]) == REG 
8677       && REGNO (operands[1]) == REGNO (operands[4])
8678       && REGNO (operands[4]) != REGNO (operands[0]))
8679     {
8680       if (GET_CODE (operands[6]) == LT)
8681         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8682       else if (GET_CODE (operands[6]) == GE)
8683         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8684     }
8685   if (GET_CODE (operands[3]) == CONST_INT
8686       && !const_ok_for_arm (INTVAL (operands[3])))
8687     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8688   else
8689     output_asm_insn (\"cmp\\t%2, %3\", operands);
8690   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8691   if (which_alternative != 0)
8692     return \"mov%D6\\t%0, %1\";
8693   return \"\";
8694   "
8695   [(set_attr "conds" "clob")
8696    (set_attr "length" "8,12")]
8699 (define_insn "*if_arith_move"
8700   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8701         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8702                           [(match_operand 6 "cc_register" "") (const_int 0)])
8703                          (match_operator:SI 5 "shiftable_operator"
8704                           [(match_operand:SI 2 "s_register_operand" "r,r")
8705                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8706                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8707   "TARGET_ARM"
8708   "@
8709    %I5%d4\\t%0, %2, %3
8710    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8711   [(set_attr "conds" "use")
8712    (set_attr "length" "4,8")
8713    (set_attr "type" "*,*")]
8716 (define_insn "*ifcompare_move_arith"
8717   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8718         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8719                           [(match_operand:SI 4 "s_register_operand" "r,r")
8720                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8721                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8722                          (match_operator:SI 7 "shiftable_operator"
8723                           [(match_operand:SI 2 "s_register_operand" "r,r")
8724                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8725    (clobber (reg:CC CC_REGNUM))]
8726   "TARGET_ARM"
8727   "*
8728   /* If we have an operation where (op x 0) is the identity operation and
8729      the conditional operator is LT or GE and we are comparing against zero and
8730      everything is in registers then we can do this in two instructions */
8731   if (operands[5] == const0_rtx
8732       && GET_CODE (operands[7]) != AND
8733       && GET_CODE (operands[3]) == REG
8734       && GET_CODE (operands[1]) == REG 
8735       && REGNO (operands[1]) == REGNO (operands[2])
8736       && REGNO (operands[2]) != REGNO (operands[0]))
8737     {
8738       if (GET_CODE (operands[6]) == GE)
8739         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8740       else if (GET_CODE (operands[6]) == LT)
8741         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8742     }
8744   if (GET_CODE (operands[5]) == CONST_INT
8745       && !const_ok_for_arm (INTVAL (operands[5])))
8746     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
8747   else
8748     output_asm_insn (\"cmp\\t%4, %5\", operands);
8750   if (which_alternative != 0)
8751     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
8752   return \"%I7%D6\\t%0, %2, %3\";
8753   "
8754   [(set_attr "conds" "clob")
8755    (set_attr "length" "8,12")]
8758 (define_insn "*if_move_arith"
8759   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8760         (if_then_else:SI
8761          (match_operator 4 "arm_comparison_operator"
8762           [(match_operand 6 "cc_register" "") (const_int 0)])
8763          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8764          (match_operator:SI 5 "shiftable_operator"
8765           [(match_operand:SI 2 "s_register_operand" "r,r")
8766            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
8767   "TARGET_ARM"
8768   "@
8769    %I5%D4\\t%0, %2, %3
8770    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8771   [(set_attr "conds" "use")
8772    (set_attr "length" "4,8")
8773    (set_attr "type" "*,*")]
8776 (define_insn "*ifcompare_move_not"
8777   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8778         (if_then_else:SI
8779          (match_operator 5 "arm_comparison_operator"
8780           [(match_operand:SI 3 "s_register_operand" "r,r")
8781            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8782          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8783          (not:SI
8784           (match_operand:SI 2 "s_register_operand" "r,r"))))
8785    (clobber (reg:CC CC_REGNUM))]
8786   "TARGET_ARM"
8787   "#"
8788   [(set_attr "conds" "clob")
8789    (set_attr "length" "8,12")]
8792 (define_insn "*if_move_not"
8793   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8794         (if_then_else:SI
8795          (match_operator 4 "arm_comparison_operator"
8796           [(match_operand 3 "cc_register" "") (const_int 0)])
8797          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8798          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8799   "TARGET_ARM"
8800   "@
8801    mvn%D4\\t%0, %2
8802    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
8803    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8804   [(set_attr "conds" "use")
8805    (set_attr "length" "4,8,8")]
8808 (define_insn "*ifcompare_not_move"
8809   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8810         (if_then_else:SI 
8811          (match_operator 5 "arm_comparison_operator"
8812           [(match_operand:SI 3 "s_register_operand" "r,r")
8813            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8814          (not:SI
8815           (match_operand:SI 2 "s_register_operand" "r,r"))
8816          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8817    (clobber (reg:CC CC_REGNUM))]
8818   "TARGET_ARM"
8819   "#"
8820   [(set_attr "conds" "clob")
8821    (set_attr "length" "8,12")]
8824 (define_insn "*if_not_move"
8825   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8826         (if_then_else:SI
8827          (match_operator 4 "arm_comparison_operator"
8828           [(match_operand 3 "cc_register" "") (const_int 0)])
8829          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8830          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8831   "TARGET_ARM"
8832   "@
8833    mvn%d4\\t%0, %2
8834    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
8835    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8836   [(set_attr "conds" "use")
8837    (set_attr "length" "4,8,8")]
8840 (define_insn "*ifcompare_shift_move"
8841   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8842         (if_then_else:SI
8843          (match_operator 6 "arm_comparison_operator"
8844           [(match_operand:SI 4 "s_register_operand" "r,r")
8845            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8846          (match_operator:SI 7 "shift_operator"
8847           [(match_operand:SI 2 "s_register_operand" "r,r")
8848            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
8849          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8850    (clobber (reg:CC CC_REGNUM))]
8851   "TARGET_ARM"
8852   "#"
8853   [(set_attr "conds" "clob")
8854    (set_attr "length" "8,12")]
8857 (define_insn "*if_shift_move"
8858   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8859         (if_then_else:SI
8860          (match_operator 5 "arm_comparison_operator"
8861           [(match_operand 6 "cc_register" "") (const_int 0)])
8862          (match_operator:SI 4 "shift_operator"
8863           [(match_operand:SI 2 "s_register_operand" "r,r,r")
8864            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
8865          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8866   "TARGET_ARM"
8867   "@
8868    mov%d5\\t%0, %2%S4
8869    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
8870    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8871   [(set_attr "conds" "use")
8872    (set_attr "shift" "2")
8873    (set_attr "length" "4,8,8")
8874    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
8875                       (const_string "alu_shift")
8876                       (const_string "alu_shift_reg")))]
8879 (define_insn "*ifcompare_move_shift"
8880   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8881         (if_then_else:SI
8882          (match_operator 6 "arm_comparison_operator"
8883           [(match_operand:SI 4 "s_register_operand" "r,r")
8884            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8885          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8886          (match_operator:SI 7 "shift_operator"
8887           [(match_operand:SI 2 "s_register_operand" "r,r")
8888            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
8889    (clobber (reg:CC CC_REGNUM))]
8890   "TARGET_ARM"
8891   "#"
8892   [(set_attr "conds" "clob")
8893    (set_attr "length" "8,12")]
8896 (define_insn "*if_move_shift"
8897   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8898         (if_then_else:SI
8899          (match_operator 5 "arm_comparison_operator"
8900           [(match_operand 6 "cc_register" "") (const_int 0)])
8901          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8902          (match_operator:SI 4 "shift_operator"
8903           [(match_operand:SI 2 "s_register_operand" "r,r,r")
8904            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
8905   "TARGET_ARM"
8906   "@
8907    mov%D5\\t%0, %2%S4
8908    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
8909    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8910   [(set_attr "conds" "use")
8911    (set_attr "shift" "2")
8912    (set_attr "length" "4,8,8")
8913    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
8914                       (const_string "alu_shift")
8915                       (const_string "alu_shift_reg")))]
8918 (define_insn "*ifcompare_shift_shift"
8919   [(set (match_operand:SI 0 "s_register_operand" "=r")
8920         (if_then_else:SI
8921          (match_operator 7 "arm_comparison_operator"
8922           [(match_operand:SI 5 "s_register_operand" "r")
8923            (match_operand:SI 6 "arm_add_operand" "rIL")])
8924          (match_operator:SI 8 "shift_operator"
8925           [(match_operand:SI 1 "s_register_operand" "r")
8926            (match_operand:SI 2 "arm_rhs_operand" "rM")])
8927          (match_operator:SI 9 "shift_operator"
8928           [(match_operand:SI 3 "s_register_operand" "r")
8929            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
8930    (clobber (reg:CC CC_REGNUM))]
8931   "TARGET_ARM"
8932   "#"
8933   [(set_attr "conds" "clob")
8934    (set_attr "length" "12")]
8937 (define_insn "*if_shift_shift"
8938   [(set (match_operand:SI 0 "s_register_operand" "=r")
8939         (if_then_else:SI
8940          (match_operator 5 "arm_comparison_operator"
8941           [(match_operand 8 "cc_register" "") (const_int 0)])
8942          (match_operator:SI 6 "shift_operator"
8943           [(match_operand:SI 1 "s_register_operand" "r")
8944            (match_operand:SI 2 "arm_rhs_operand" "rM")])
8945          (match_operator:SI 7 "shift_operator"
8946           [(match_operand:SI 3 "s_register_operand" "r")
8947            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
8948   "TARGET_ARM"
8949   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8950   [(set_attr "conds" "use")
8951    (set_attr "shift" "1")
8952    (set_attr "length" "8")
8953    (set (attr "type") (if_then_else
8954                         (and (match_operand 2 "const_int_operand" "")
8955                              (match_operand 4 "const_int_operand" ""))
8956                       (const_string "alu_shift")
8957                       (const_string "alu_shift_reg")))]
8960 (define_insn "*ifcompare_not_arith"
8961   [(set (match_operand:SI 0 "s_register_operand" "=r")
8962         (if_then_else:SI
8963          (match_operator 6 "arm_comparison_operator"
8964           [(match_operand:SI 4 "s_register_operand" "r")
8965            (match_operand:SI 5 "arm_add_operand" "rIL")])
8966          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8967          (match_operator:SI 7 "shiftable_operator"
8968           [(match_operand:SI 2 "s_register_operand" "r")
8969            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
8970    (clobber (reg:CC CC_REGNUM))]
8971   "TARGET_ARM"
8972   "#"
8973   [(set_attr "conds" "clob")
8974    (set_attr "length" "12")]
8977 (define_insn "*if_not_arith"
8978   [(set (match_operand:SI 0 "s_register_operand" "=r")
8979         (if_then_else:SI
8980          (match_operator 5 "arm_comparison_operator"
8981           [(match_operand 4 "cc_register" "") (const_int 0)])
8982          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8983          (match_operator:SI 6 "shiftable_operator"
8984           [(match_operand:SI 2 "s_register_operand" "r")
8985            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
8986   "TARGET_ARM"
8987   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8988   [(set_attr "conds" "use")
8989    (set_attr "length" "8")]
8992 (define_insn "*ifcompare_arith_not"
8993   [(set (match_operand:SI 0 "s_register_operand" "=r")
8994         (if_then_else:SI
8995          (match_operator 6 "arm_comparison_operator"
8996           [(match_operand:SI 4 "s_register_operand" "r")
8997            (match_operand:SI 5 "arm_add_operand" "rIL")])
8998          (match_operator:SI 7 "shiftable_operator"
8999           [(match_operand:SI 2 "s_register_operand" "r")
9000            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9001          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9002    (clobber (reg:CC CC_REGNUM))]
9003   "TARGET_ARM"
9004   "#"
9005   [(set_attr "conds" "clob")
9006    (set_attr "length" "12")]
9009 (define_insn "*if_arith_not"
9010   [(set (match_operand:SI 0 "s_register_operand" "=r")
9011         (if_then_else:SI
9012          (match_operator 5 "arm_comparison_operator"
9013           [(match_operand 4 "cc_register" "") (const_int 0)])
9014          (match_operator:SI 6 "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   "TARGET_ARM"
9019   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9020   [(set_attr "conds" "use")
9021    (set_attr "length" "8")]
9024 (define_insn "*ifcompare_neg_move"
9025   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9026         (if_then_else:SI
9027          (match_operator 5 "arm_comparison_operator"
9028           [(match_operand:SI 3 "s_register_operand" "r,r")
9029            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9030          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9031          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9032    (clobber (reg:CC CC_REGNUM))]
9033   "TARGET_ARM"
9034   "#"
9035   [(set_attr "conds" "clob")
9036    (set_attr "length" "8,12")]
9039 (define_insn "*if_neg_move"
9040   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9041         (if_then_else:SI
9042          (match_operator 4 "arm_comparison_operator"
9043           [(match_operand 3 "cc_register" "") (const_int 0)])
9044          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9045          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9046   "TARGET_ARM"
9047   "@
9048    rsb%d4\\t%0, %2, #0
9049    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9050    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9051   [(set_attr "conds" "use")
9052    (set_attr "length" "4,8,8")]
9055 (define_insn "*ifcompare_move_neg"
9056   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9057         (if_then_else:SI
9058          (match_operator 5 "arm_comparison_operator"
9059           [(match_operand:SI 3 "s_register_operand" "r,r")
9060            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9061          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9062          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9063    (clobber (reg:CC CC_REGNUM))]
9064   "TARGET_ARM"
9065   "#"
9066   [(set_attr "conds" "clob")
9067    (set_attr "length" "8,12")]
9070 (define_insn "*if_move_neg"
9071   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9072         (if_then_else:SI
9073          (match_operator 4 "arm_comparison_operator"
9074           [(match_operand 3 "cc_register" "") (const_int 0)])
9075          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9076          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9077   "TARGET_ARM"
9078   "@
9079    rsb%D4\\t%0, %2, #0
9080    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9081    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9082   [(set_attr "conds" "use")
9083    (set_attr "length" "4,8,8")]
9086 (define_insn "*arith_adjacentmem"
9087   [(set (match_operand:SI 0 "s_register_operand" "=r")
9088         (match_operator:SI 1 "shiftable_operator"
9089          [(match_operand:SI 2 "memory_operand" "m")
9090           (match_operand:SI 3 "memory_operand" "m")]))
9091    (clobber (match_scratch:SI 4 "=r"))]
9092   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9093   "*
9094   {
9095     rtx ldm[3];
9096     rtx arith[4];
9097     int val1 = 0, val2 = 0;
9099     if (REGNO (operands[0]) > REGNO (operands[4]))
9100       {
9101         ldm[1] = operands[4];
9102         ldm[2] = operands[0];
9103       }
9104     else
9105       {
9106         ldm[1] = operands[0];
9107         ldm[2] = operands[4];
9108       }
9109     if (GET_CODE (XEXP (operands[2], 0)) != REG)
9110       val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
9111     if (GET_CODE (XEXP (operands[3], 0)) != REG)
9112       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9113     arith[0] = operands[0];
9114     arith[3] = operands[1];
9115     if (val1 < val2)
9116       {
9117         arith[1] = ldm[1];
9118         arith[2] = ldm[2];
9119       }
9120     else
9121       {
9122         arith[1] = ldm[2];
9123         arith[2] = ldm[1];
9124       }
9125    if (val1 && val2)
9126       {
9127         rtx ops[3];
9128         ldm[0] = ops[0] = operands[4];
9129         ops[1] = XEXP (XEXP (operands[2], 0), 0);
9130         ops[2] = XEXP (XEXP (operands[2], 0), 1);
9131         output_add_immediate (ops);
9132         if (val1 < val2)
9133           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9134         else
9135           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9136       }
9137     else if (val1)
9138       {
9139         ldm[0] = XEXP (operands[3], 0);
9140         if (val1 < val2)
9141           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9142         else
9143           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9144       }
9145     else
9146       {
9147         ldm[0] = XEXP (operands[2], 0);
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     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9154     return \"\";
9155   }"
9156   [(set_attr "length" "12")
9157    (set_attr "predicable" "yes")
9158    (set_attr "type" "load1")]
9161 ;; the arm can support extended pre-inc instructions
9163 ;; In all these cases, we use operands 0 and 1 for the register being
9164 ;; incremented because those are the operands that local-alloc will
9165 ;; tie and these are the pair most likely to be tieable (and the ones
9166 ;; that will benefit the most).
9168 ;; We reject the frame pointer if it occurs anywhere in these patterns since
9169 ;; elimination will cause too many headaches.
9171 (define_insn "*strqi_preinc"
9172   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9173                          (match_operand:SI 2 "index_operand" "rJ")))
9174         (match_operand:QI 3 "s_register_operand" "r"))
9175    (set (match_operand:SI 0 "s_register_operand" "=r")
9176         (plus:SI (match_dup 1) (match_dup 2)))]
9177   "TARGET_ARM
9178    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9179    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9180    && (GET_CODE (operands[2]) != REG
9181        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9182   "str%?b\\t%3, [%0, %2]!"
9183   [(set_attr "type" "store1")
9184    (set_attr "predicable" "yes")]
9187 (define_insn "*strqi_predec"
9188   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9189                           (match_operand:SI 2 "s_register_operand" "r")))
9190         (match_operand:QI 3 "s_register_operand" "r"))
9191    (set (match_operand:SI 0 "s_register_operand" "=r")
9192         (minus: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 "*loadqi_preinc"
9204   [(set (match_operand:QI 3 "s_register_operand" "=r")
9205         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9206                          (match_operand:SI 2 "index_operand" "rJ"))))
9207    (set (match_operand:SI 0 "s_register_operand" "=r")
9208         (plus: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   "ldr%?b\\t%3, [%0, %2]!"
9215   [(set_attr "type" "load_byte")
9216    (set_attr "predicable" "yes")]
9219 (define_insn "*loadqi_predec"
9220   [(set (match_operand:QI 3 "s_register_operand" "=r")
9221         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9222                           (match_operand:SI 2 "s_register_operand" "r"))))
9223    (set (match_operand:SI 0 "s_register_operand" "=r")
9224         (minus: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 "*loadqisi_preinc"
9236   [(set (match_operand:SI 3 "s_register_operand" "=r")
9237         (zero_extend:SI
9238          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9239                           (match_operand:SI 2 "index_operand" "rJ")))))
9240    (set (match_operand:SI 0 "s_register_operand" "=r")
9241         (plus:SI (match_dup 1) (match_dup 2)))]
9242   "TARGET_ARM
9243    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9244    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9245    && (GET_CODE (operands[2]) != REG
9246        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9247   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
9248   [(set_attr "type" "load_byte")
9249    (set_attr "predicable" "yes")]
9252 (define_insn "*loadqisi_predec"
9253   [(set (match_operand:SI 3 "s_register_operand" "=r")
9254         (zero_extend:SI
9255          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9256                            (match_operand:SI 2 "s_register_operand" "r")))))
9257    (set (match_operand:SI 0 "s_register_operand" "=r")
9258         (minus:SI (match_dup 1) (match_dup 2)))]
9259   "TARGET_ARM
9260    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9261    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9262    && (GET_CODE (operands[2]) != REG
9263        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9264   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
9265   [(set_attr "type" "load_byte")
9266    (set_attr "predicable" "yes")]
9269 (define_insn "*strsi_preinc"
9270   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9271                          (match_operand:SI 2 "index_operand" "rJ")))
9272         (match_operand:SI 3 "s_register_operand" "r"))
9273    (set (match_operand:SI 0 "s_register_operand" "=r")
9274         (plus: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   "str%?\\t%3, [%0, %2]!"
9281   [(set_attr "type" "store1")
9282    (set_attr "predicable" "yes")]
9285 (define_insn "*strsi_predec"
9286   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9287                           (match_operand:SI 2 "s_register_operand" "r")))
9288         (match_operand:SI 3 "s_register_operand" "r"))
9289    (set (match_operand:SI 0 "s_register_operand" "=r")
9290         (minus: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 "*loadsi_preinc"
9302   [(set (match_operand:SI 3 "s_register_operand" "=r")
9303         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9304                          (match_operand:SI 2 "index_operand" "rJ"))))
9305    (set (match_operand:SI 0 "s_register_operand" "=r")
9306         (plus: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   "ldr%?\\t%3, [%0, %2]!"
9313   [(set_attr "type" "load1")
9314    (set_attr "predicable" "yes")]
9317 (define_insn "*loadsi_predec"
9318   [(set (match_operand:SI 3 "s_register_operand" "=r")
9319         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9320                           (match_operand:SI 2 "s_register_operand" "r"))))
9321    (set (match_operand:SI 0 "s_register_operand" "=r")
9322         (minus: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 "*strqi_shiftpreinc"
9334   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9335                           [(match_operand:SI 3 "s_register_operand" "r")
9336                            (match_operand:SI 4 "const_shift_operand" "n")])
9337                          (match_operand:SI 1 "s_register_operand" "0")))
9338         (match_operand:QI 5 "s_register_operand" "r"))
9339    (set (match_operand:SI 0 "s_register_operand" "=r")
9340         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9341                  (match_dup 1)))]
9342   "TARGET_ARM
9343    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9344    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9345    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9346   "str%?b\\t%5, [%0, %3%S2]!"
9347   [(set_attr "type" "store1")
9348    (set_attr "predicable" "yes")]
9351 (define_insn "*strqi_shiftpredec"
9352   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9353                           (match_operator:SI 2 "shift_operator"
9354                            [(match_operand:SI 3 "s_register_operand" "r")
9355                             (match_operand:SI 4 "const_shift_operand" "n")])))
9356         (match_operand:QI 5 "s_register_operand" "r"))
9357    (set (match_operand:SI 0 "s_register_operand" "=r")
9358         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9359                                                  (match_dup 4)])))]
9360   "TARGET_ARM
9361    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9362    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9363    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9364   "str%?b\\t%5, [%0, -%3%S2]!"
9365   [(set_attr "type" "store1")
9366    (set_attr "predicable" "yes")]
9369 (define_insn "*loadqi_shiftpreinc"
9370   [(set (match_operand:QI 5 "s_register_operand" "=r")
9371         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9372                           [(match_operand:SI 3 "s_register_operand" "r")
9373                            (match_operand:SI 4 "const_shift_operand" "n")])
9374                          (match_operand:SI 1 "s_register_operand" "0"))))
9375    (set (match_operand:SI 0 "s_register_operand" "=r")
9376         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9377                  (match_dup 1)))]
9378   "TARGET_ARM
9379    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9380    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9381    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9382   "ldr%?b\\t%5, [%0, %3%S2]!"
9383   [(set_attr "type" "load_byte")
9384    (set_attr "predicable" "yes")]
9387 (define_insn "*loadqi_shiftpredec"
9388   [(set (match_operand:QI 5 "s_register_operand" "=r")
9389         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9390                           (match_operator:SI 2 "shift_operator"
9391                            [(match_operand:SI 3 "s_register_operand" "r")
9392                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9393    (set (match_operand:SI 0 "s_register_operand" "=r")
9394         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9395                                                  (match_dup 4)])))]
9396   "TARGET_ARM
9397    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9398    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9399    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9400   "ldr%?b\\t%5, [%0, -%3%S2]!"
9401   [(set_attr "type" "load_byte")
9402    (set_attr "predicable" "yes")]
9405 (define_insn "*strsi_shiftpreinc"
9406   [(set (mem:SI (plus:SI (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                          (match_operand:SI 1 "s_register_operand" "0")))
9410         (match_operand:SI 5 "s_register_operand" "r"))
9411    (set (match_operand:SI 0 "s_register_operand" "=r")
9412         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9413                  (match_dup 1)))]
9414   "TARGET_ARM
9415    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9416    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9417    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9418   "str%?\\t%5, [%0, %3%S2]!"
9419   [(set_attr "type" "store1")
9420    (set_attr "predicable" "yes")]
9423 (define_insn "*strsi_shiftpredec"
9424   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9425                           (match_operator:SI 2 "shift_operator"
9426                            [(match_operand:SI 3 "s_register_operand" "r")
9427                             (match_operand:SI 4 "const_shift_operand" "n")])))
9428         (match_operand:SI 5 "s_register_operand" "r"))
9429    (set (match_operand:SI 0 "s_register_operand" "=r")
9430         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9431                                                  (match_dup 4)])))]
9432   "TARGET_ARM
9433    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9434    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9435    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9436   "str%?\\t%5, [%0, -%3%S2]!"
9437   [(set_attr "type" "store1")
9438    (set_attr "predicable" "yes")]
9441 (define_insn "*loadsi_shiftpreinc"
9442   [(set (match_operand:SI 5 "s_register_operand" "=r")
9443         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9444                           [(match_operand:SI 3 "s_register_operand" "r")
9445                            (match_operand:SI 4 "const_shift_operand" "n")])
9446                          (match_operand:SI 1 "s_register_operand" "0"))))
9447    (set (match_operand:SI 0 "s_register_operand" "=r")
9448         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9449                  (match_dup 1)))]
9450   "TARGET_ARM
9451    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9452    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9453    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9454   "ldr%?\\t%5, [%0, %3%S2]!"
9455   [(set_attr "type" "load1")
9456    (set_attr "predicable" "yes")]
9459 (define_insn "*loadsi_shiftpredec"
9460   [(set (match_operand:SI 5 "s_register_operand" "=r")
9461         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9462                           (match_operator:SI 2 "shift_operator"
9463                            [(match_operand:SI 3 "s_register_operand" "r")
9464                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9465    (set (match_operand:SI 0 "s_register_operand" "=r")
9466         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9467                                                  (match_dup 4)])))]
9468   "TARGET_ARM
9469    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9470    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9471    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9472   "ldr%?\\t%5, [%0, -%3%S2]!"
9473   [(set_attr "type" "load1")
9474    (set_attr "predicable" "yes")])
9476 ; It can also support extended post-inc expressions, but combine doesn't
9477 ; try these....
9478 ; It doesn't seem worth adding peepholes for anything but the most common
9479 ; cases since, unlike combine, the increment must immediately follow the load
9480 ; for this pattern to match.
9481 ; We must watch to see that the source/destination register isn't also the
9482 ; same as the base address register, and that if the index is a register,
9483 ; that it is not the same as the base address register.  In such cases the
9484 ; instruction that we would generate would have UNPREDICTABLE behavior so 
9485 ; we cannot use it.
9487 (define_peephole
9488   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9489         (match_operand:QI 2 "s_register_operand" "r"))
9490    (set (match_dup 0)
9491         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9492   "TARGET_ARM
9493    && (REGNO (operands[2]) != REGNO (operands[0]))
9494    && (GET_CODE (operands[1]) != REG
9495        || (REGNO (operands[1]) != REGNO (operands[0])))"
9496   "str%?b\\t%2, [%0], %1"
9499 (define_peephole
9500   [(set (match_operand:QI 0 "s_register_operand" "=r")
9501         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9502    (set (match_dup 1)
9503         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9504   "TARGET_ARM
9505    && REGNO (operands[0]) != REGNO(operands[1])
9506    && (GET_CODE (operands[2]) != REG
9507        || REGNO(operands[0]) != REGNO (operands[2]))"
9508   "ldr%?b\\t%0, [%1], %2"
9511 (define_peephole
9512   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9513         (match_operand:SI 2 "s_register_operand" "r"))
9514    (set (match_dup 0)
9515         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9516   "TARGET_ARM
9517    && (REGNO (operands[2]) != REGNO (operands[0]))
9518    && (GET_CODE (operands[1]) != REG
9519        || (REGNO (operands[1]) != REGNO (operands[0])))"
9520   "str%?\\t%2, [%0], %1"
9523 (define_peephole
9524   [(set (match_operand:SI 0 "s_register_operand" "=r")
9525         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9526    (set (match_dup 1)
9527         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9528   "TARGET_ARM
9529    && REGNO (operands[0]) != REGNO(operands[1])
9530    && (GET_CODE (operands[2]) != REG
9531        || REGNO(operands[0]) != REGNO (operands[2]))"
9532   "ldr%?\\t%0, [%1], %2"
9535 (define_peephole
9536   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9537                          (match_operand:SI 1 "index_operand" "rJ")))
9538         (match_operand:QI 2 "s_register_operand" "r"))
9539    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
9540   "TARGET_ARM
9541    && (REGNO (operands[2]) != REGNO (operands[0]))
9542    && (GET_CODE (operands[1]) != REG
9543        || (REGNO (operands[1]) != REGNO (operands[0])))"
9544   "str%?b\\t%2, [%0, %1]!"
9547 (define_peephole
9548   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9549                           [(match_operand:SI 0 "s_register_operand" "r")
9550                            (match_operand:SI 1 "const_int_operand" "n")])
9551                          (match_operand:SI 2 "s_register_operand" "+r")))
9552         (match_operand:QI 3 "s_register_operand" "r"))
9553    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9554                                (match_dup 2)))]
9555   "TARGET_ARM
9556    && (REGNO (operands[3]) != REGNO (operands[2]))
9557    && (REGNO (operands[0]) != REGNO (operands[2]))"
9558   "str%?b\\t%3, [%2, %0%S4]!"
9561 ; This pattern is never tried by combine, so do it as a peephole
9563 (define_peephole2
9564   [(set (match_operand:SI 0 "arm_general_register_operand" "")
9565         (match_operand:SI 1 "arm_general_register_operand" ""))
9566    (set (reg:CC CC_REGNUM)
9567         (compare:CC (match_dup 1) (const_int 0)))]
9568   "TARGET_ARM"
9569   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9570               (set (match_dup 0) (match_dup 1))])]
9571   ""
9574 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9575 ; reversed, check that the memory references aren't volatile.
9577 (define_peephole
9578   [(set (match_operand:SI 0 "s_register_operand" "=r")
9579         (match_operand:SI 4 "memory_operand" "m"))
9580    (set (match_operand:SI 1 "s_register_operand" "=r")
9581         (match_operand:SI 5 "memory_operand" "m"))
9582    (set (match_operand:SI 2 "s_register_operand" "=r")
9583         (match_operand:SI 6 "memory_operand" "m"))
9584    (set (match_operand:SI 3 "s_register_operand" "=r")
9585         (match_operand:SI 7 "memory_operand" "m"))]
9586   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9587   "*
9588   return emit_ldm_seq (operands, 4);
9589   "
9592 (define_peephole
9593   [(set (match_operand:SI 0 "s_register_operand" "=r")
9594         (match_operand:SI 3 "memory_operand" "m"))
9595    (set (match_operand:SI 1 "s_register_operand" "=r")
9596         (match_operand:SI 4 "memory_operand" "m"))
9597    (set (match_operand:SI 2 "s_register_operand" "=r")
9598         (match_operand:SI 5 "memory_operand" "m"))]
9599   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9600   "*
9601   return emit_ldm_seq (operands, 3);
9602   "
9605 (define_peephole
9606   [(set (match_operand:SI 0 "s_register_operand" "=r")
9607         (match_operand:SI 2 "memory_operand" "m"))
9608    (set (match_operand:SI 1 "s_register_operand" "=r")
9609         (match_operand:SI 3 "memory_operand" "m"))]
9610   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9611   "*
9612   return emit_ldm_seq (operands, 2);
9613   "
9616 (define_peephole
9617   [(set (match_operand:SI 4 "memory_operand" "=m")
9618         (match_operand:SI 0 "s_register_operand" "r"))
9619    (set (match_operand:SI 5 "memory_operand" "=m")
9620         (match_operand:SI 1 "s_register_operand" "r"))
9621    (set (match_operand:SI 6 "memory_operand" "=m")
9622         (match_operand:SI 2 "s_register_operand" "r"))
9623    (set (match_operand:SI 7 "memory_operand" "=m")
9624         (match_operand:SI 3 "s_register_operand" "r"))]
9625   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9626   "*
9627   return emit_stm_seq (operands, 4);
9628   "
9631 (define_peephole
9632   [(set (match_operand:SI 3 "memory_operand" "=m")
9633         (match_operand:SI 0 "s_register_operand" "r"))
9634    (set (match_operand:SI 4 "memory_operand" "=m")
9635         (match_operand:SI 1 "s_register_operand" "r"))
9636    (set (match_operand:SI 5 "memory_operand" "=m")
9637         (match_operand:SI 2 "s_register_operand" "r"))]
9638   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9639   "*
9640   return emit_stm_seq (operands, 3);
9641   "
9644 (define_peephole
9645   [(set (match_operand:SI 2 "memory_operand" "=m")
9646         (match_operand:SI 0 "s_register_operand" "r"))
9647    (set (match_operand:SI 3 "memory_operand" "=m")
9648         (match_operand:SI 1 "s_register_operand" "r"))]
9649   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9650   "*
9651   return emit_stm_seq (operands, 2);
9652   "
9655 (define_split
9656   [(set (match_operand:SI 0 "s_register_operand" "")
9657         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9658                        (const_int 0))
9659                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9660                          [(match_operand:SI 3 "s_register_operand" "")
9661                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
9662    (clobber (match_operand:SI 5 "s_register_operand" ""))]
9663   "TARGET_ARM"
9664   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9665    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9666                               (match_dup 5)))]
9667   ""
9670 ;; This split can be used because CC_Z mode implies that the following
9671 ;; branch will be an equality, or an unsigned inequality, so the sign
9672 ;; extension is not needed.
9674 (define_split
9675   [(set (reg:CC_Z CC_REGNUM)
9676         (compare:CC_Z
9677          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9678                     (const_int 24))
9679          (match_operand 1 "const_int_operand" "")))
9680    (clobber (match_scratch:SI 2 ""))]
9681   "TARGET_ARM
9682    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9683        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9684   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9685    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9686   "
9687   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9688   "
9691 (define_expand "prologue"
9692   [(clobber (const_int 0))]
9693   "TARGET_EITHER"
9694   "if (TARGET_ARM)
9695      arm_expand_prologue ();
9696    else
9697      thumb_expand_prologue ();
9698   DONE;
9699   "
9702 (define_expand "epilogue"
9703   [(clobber (const_int 0))]
9704   "TARGET_EITHER"
9705   "
9706   if (current_function_calls_eh_return)
9707     emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
9708   if (TARGET_THUMB)
9709     thumb_expand_epilogue ();
9710   else if (USE_RETURN_INSN (FALSE))
9711     {
9712       emit_jump_insn (gen_return ());
9713       DONE;
9714     }
9715   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9716         gen_rtvec (1,
9717                 gen_rtx_RETURN (VOIDmode)),
9718         VUNSPEC_EPILOGUE));
9719   DONE;
9720   "
9723 ;; Note - although unspec_volatile's USE all hard registers,
9724 ;; USEs are ignored after relaod has completed.  Thus we need
9725 ;; to add an unspec of the link register to ensure that flow
9726 ;; does not think that it is unused by the sibcall branch that
9727 ;; will replace the standard function epilogue.
9728 (define_insn "sibcall_epilogue"
9729   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9730               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9731   "TARGET_ARM"
9732   "*
9733   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9734     return output_return_instruction (const_true_rtx, FALSE, FALSE);
9735   return arm_output_epilogue (next_nonnote_insn (insn));
9736   "
9737 ;; Length is absolute worst case
9738   [(set_attr "length" "44")
9739    (set_attr "type" "block")
9740    ;; We don't clobber the conditions, but the potential length of this
9741    ;; operation is sufficient to make conditionalizing the sequence 
9742    ;; unlikely to be profitable.
9743    (set_attr "conds" "clob")]
9746 (define_insn "*epilogue_insns"
9747   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9748   "TARGET_EITHER"
9749   "*
9750   if (TARGET_ARM)
9751     return arm_output_epilogue (NULL);
9752   else /* TARGET_THUMB */
9753     return thumb_unexpanded_epilogue ();
9754   "
9755   ; Length is absolute worst case
9756   [(set_attr "length" "44")
9757    (set_attr "type" "block")
9758    ;; We don't clobber the conditions, but the potential length of this
9759    ;; operation is sufficient to make conditionalizing the sequence 
9760    ;; unlikely to be profitable.
9761    (set_attr "conds" "clob")]
9764 (define_expand "eh_epilogue"
9765   [(use (match_operand:SI 0 "register_operand" ""))
9766    (use (match_operand:SI 1 "register_operand" ""))
9767    (use (match_operand:SI 2 "register_operand" ""))]
9768   "TARGET_EITHER"
9769   "
9770   {
9771     cfun->machine->eh_epilogue_sp_ofs = operands[1];
9772     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9773       {
9774         rtx ra = gen_rtx_REG (Pmode, 2);
9776         emit_move_insn (ra, operands[2]);
9777         operands[2] = ra;
9778       }
9779     /* This is a hack -- we may have crystalized the function type too
9780        early.  */
9781     cfun->machine->func_type = 0;
9782   }"
9785 ;; This split is only used during output to reduce the number of patterns
9786 ;; that need assembler instructions adding to them.  We allowed the setting
9787 ;; of the conditions to be implicit during rtl generation so that
9788 ;; the conditional compare patterns would work.  However this conflicts to
9789 ;; some extent with the conditional data operations, so we have to split them
9790 ;; up again here.
9792 (define_split
9793   [(set (match_operand:SI 0 "s_register_operand" "")
9794         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9795                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9796                          (match_dup 0)
9797                          (match_operand 4 "" "")))
9798    (clobber (reg:CC CC_REGNUM))]
9799   "TARGET_ARM && reload_completed"
9800   [(set (match_dup 5) (match_dup 6))
9801    (cond_exec (match_dup 7)
9802               (set (match_dup 0) (match_dup 4)))]
9803   "
9804   {
9805     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9806                                              operands[2], operands[3]);
9807     enum rtx_code rc = GET_CODE (operands[1]);
9809     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9810     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9811     if (mode == CCFPmode || mode == CCFPEmode)
9812       rc = reverse_condition_maybe_unordered (rc);
9813     else
9814       rc = reverse_condition (rc);
9816     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9817   }"
9820 (define_split
9821   [(set (match_operand:SI 0 "s_register_operand" "")
9822         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9823                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9824                          (match_operand 4 "" "")
9825                          (match_dup 0)))
9826    (clobber (reg:CC CC_REGNUM))]
9827   "TARGET_ARM && reload_completed"
9828   [(set (match_dup 5) (match_dup 6))
9829    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9830               (set (match_dup 0) (match_dup 4)))]
9831   "
9832   {
9833     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9834                                              operands[2], operands[3]);
9836     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9837     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9838   }"
9841 (define_split
9842   [(set (match_operand:SI 0 "s_register_operand" "")
9843         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9844                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9845                          (match_operand 4 "" "")
9846                          (match_operand 5 "" "")))
9847    (clobber (reg:CC CC_REGNUM))]
9848   "TARGET_ARM && reload_completed"
9849   [(set (match_dup 6) (match_dup 7))
9850    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9851               (set (match_dup 0) (match_dup 4)))
9852    (cond_exec (match_dup 8)
9853               (set (match_dup 0) (match_dup 5)))]
9854   "
9855   {
9856     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9857                                              operands[2], operands[3]);
9858     enum rtx_code rc = GET_CODE (operands[1]);
9860     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9861     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9862     if (mode == CCFPmode || mode == CCFPEmode)
9863       rc = reverse_condition_maybe_unordered (rc);
9864     else
9865       rc = reverse_condition (rc);
9867     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9868   }"
9871 (define_split
9872   [(set (match_operand:SI 0 "s_register_operand" "")
9873         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9874                           [(match_operand:SI 2 "s_register_operand" "")
9875                            (match_operand:SI 3 "arm_add_operand" "")])
9876                          (match_operand:SI 4 "arm_rhs_operand" "")
9877                          (not:SI
9878                           (match_operand:SI 5 "s_register_operand" ""))))
9879    (clobber (reg:CC CC_REGNUM))]
9880   "TARGET_ARM && reload_completed"
9881   [(set (match_dup 6) (match_dup 7))
9882    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9883               (set (match_dup 0) (match_dup 4)))
9884    (cond_exec (match_dup 8)
9885               (set (match_dup 0) (not:SI (match_dup 5))))]
9886   "
9887   {
9888     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9889                                              operands[2], operands[3]);
9890     enum rtx_code rc = GET_CODE (operands[1]);
9892     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9893     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9894     if (mode == CCFPmode || mode == CCFPEmode)
9895       rc = reverse_condition_maybe_unordered (rc);
9896     else
9897       rc = reverse_condition (rc);
9899     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9900   }"
9903 (define_insn "*cond_move_not"
9904   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9905         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9906                           [(match_operand 3 "cc_register" "") (const_int 0)])
9907                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9908                          (not:SI
9909                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
9910   "TARGET_ARM"
9911   "@
9912    mvn%D4\\t%0, %2
9913    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
9914   [(set_attr "conds" "use")
9915    (set_attr "length" "4,8")]
9918 ;; The next two patterns occur when an AND operation is followed by a
9919 ;; scc insn sequence 
9921 (define_insn "*sign_extract_onebit"
9922   [(set (match_operand:SI 0 "s_register_operand" "=r")
9923         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9924                          (const_int 1)
9925                          (match_operand:SI 2 "const_int_operand" "n")))
9926     (clobber (reg:CC CC_REGNUM))]
9927   "TARGET_ARM"
9928   "*
9929     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9930     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
9931     return \"mvnne\\t%0, #0\";
9932   "
9933   [(set_attr "conds" "clob")
9934    (set_attr "length" "8")]
9937 (define_insn "*not_signextract_onebit"
9938   [(set (match_operand:SI 0 "s_register_operand" "=r")
9939         (not:SI
9940          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9941                           (const_int 1)
9942                           (match_operand:SI 2 "const_int_operand" "n"))))
9943    (clobber (reg:CC CC_REGNUM))]
9944   "TARGET_ARM"
9945   "*
9946     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9947     output_asm_insn (\"tst\\t%1, %2\", operands);
9948     output_asm_insn (\"mvneq\\t%0, #0\", operands);
9949     return \"movne\\t%0, #0\";
9950   "
9951   [(set_attr "conds" "clob")
9952    (set_attr "length" "12")]
9955 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
9956 ;; expressions.  For simplicity, the first register is also in the unspec
9957 ;; part.
9958 (define_insn "*push_multi"
9959   [(match_parallel 2 "multi_register_push"
9960     [(set (match_operand:BLK 0 "memory_operand" "=m")
9961           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
9962                       UNSPEC_PUSH_MULT))])]
9963   "TARGET_ARM"
9964   "*
9965   {
9966     int num_saves = XVECLEN (operands[2], 0);
9967      
9968     /* For the StrongARM at least it is faster to
9969        use STR to store only a single register.  */
9970     if (num_saves == 1)
9971       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9972     else
9973       {
9974         int i;
9975         char pattern[100];
9977         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9979         for (i = 1; i < num_saves; i++)
9980           {
9981             strcat (pattern, \", %|\");
9982             strcat (pattern,
9983                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9984           }
9986         strcat (pattern, \"}\");
9987         output_asm_insn (pattern, operands);
9988       }
9990     return \"\";
9991   }"
9992   [(set_attr "type" "store4")]
9995 (define_insn "stack_tie"
9996   [(set (mem:BLK (scratch))
9997         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
9998                      (match_operand:SI 1 "s_register_operand" "r")]
9999                     UNSPEC_PRLG_STK))]
10000   ""
10001   ""
10002   [(set_attr "length" "0")]
10005 ;; Similarly for the floating point registers
10006 (define_insn "*push_fp_multi"
10007   [(match_parallel 2 "multi_register_push"
10008     [(set (match_operand:BLK 0 "memory_operand" "=m")
10009           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10010                       UNSPEC_PUSH_MULT))])]
10011   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
10012   "*
10013   {
10014     char pattern[100];
10016     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10017     output_asm_insn (pattern, operands);
10018     return \"\";
10019   }"
10020   [(set_attr "type" "f_store")]
10023 ;; Special patterns for dealing with the constant pool
10025 (define_insn "align_4"
10026   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10027   "TARGET_EITHER"
10028   "*
10029   assemble_align (32);
10030   return \"\";
10031   "
10034 (define_insn "align_8"
10035   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10036   "TARGET_EITHER"
10037   "*
10038   assemble_align (64);
10039   return \"\";
10040   "
10043 (define_insn "consttable_end"
10044   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10045   "TARGET_EITHER"
10046   "*
10047   making_const_table = FALSE;
10048   return \"\";
10049   "
10052 (define_insn "consttable_1"
10053   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10054   "TARGET_THUMB"
10055   "*
10056   making_const_table = TRUE;
10057   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10058   assemble_zeros (3);
10059   return \"\";
10060   "
10061   [(set_attr "length" "4")]
10064 (define_insn "consttable_2"
10065   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10066   "TARGET_THUMB"
10067   "*
10068   making_const_table = TRUE;
10069   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10070   assemble_zeros (2);
10071   return \"\";
10072   "
10073   [(set_attr "length" "4")]
10076 (define_insn "consttable_4"
10077   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10078   "TARGET_EITHER"
10079   "*
10080   {
10081     making_const_table = TRUE;
10082     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10083       {
10084       case MODE_FLOAT:
10085       {
10086         REAL_VALUE_TYPE r;
10087         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10088         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10089         break;
10090       }
10091       default:
10092         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
10093         break;
10094       }
10095     return \"\";
10096   }"
10097   [(set_attr "length" "4")]
10100 (define_insn "consttable_8"
10101   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10102   "TARGET_EITHER"
10103   "*
10104   {
10105     making_const_table = TRUE;
10106     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10107       {
10108        case MODE_FLOAT:
10109         {
10110           REAL_VALUE_TYPE r;
10111           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10112           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10113           break;
10114         }
10115       default:
10116         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10117         break;
10118       }
10119     return \"\";
10120   }"
10121   [(set_attr "length" "8")]
10124 ;; Miscellaneous Thumb patterns
10126 (define_expand "tablejump"
10127   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10128               (use (label_ref (match_operand 1 "" "")))])]
10129   "TARGET_THUMB"
10130   "
10131   if (flag_pic)
10132     {
10133       /* Hopefully, CSE will eliminate this copy.  */
10134       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10135       rtx reg2 = gen_reg_rtx (SImode);
10137       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10138       operands[0] = reg2;
10139     }
10140   "
10143 ;; NB never uses BX.
10144 (define_insn "*thumb_tablejump"
10145   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10146    (use (label_ref (match_operand 1 "" "")))]
10147   "TARGET_THUMB"
10148   "mov\\t%|pc, %0"
10149   [(set_attr "length" "2")]
10152 ;; V5 Instructions,
10154 (define_insn "clzsi2"
10155   [(set (match_operand:SI 0 "s_register_operand" "=r")
10156         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10157   "TARGET_ARM && arm_arch5"
10158   "clz%?\\t%0, %1"
10159   [(set_attr "predicable" "yes")])
10161 (define_expand "ffssi2"
10162   [(set (match_operand:SI 0 "s_register_operand" "")
10163         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10164   "TARGET_ARM && arm_arch5"
10165   "
10166   {
10167     rtx t1, t2, t3;
10169     t1 = gen_reg_rtx (SImode);
10170     t2 = gen_reg_rtx (SImode);
10171     t3 = gen_reg_rtx (SImode);
10173     emit_insn (gen_negsi2 (t1, operands[1]));
10174     emit_insn (gen_andsi3 (t2, operands[1], t1));
10175     emit_insn (gen_clzsi2 (t3, t2));
10176     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10177     DONE;
10178   }"
10181 (define_expand "ctzsi2"
10182   [(set (match_operand:SI 0 "s_register_operand" "")
10183         (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10184   "TARGET_ARM && arm_arch5"
10185   "
10186   {
10187     rtx t1, t2, t3;
10189     t1 = gen_reg_rtx (SImode);
10190     t2 = gen_reg_rtx (SImode);
10191     t3 = gen_reg_rtx (SImode);
10193     emit_insn (gen_negsi2 (t1, operands[1]));
10194     emit_insn (gen_andsi3 (t2, operands[1], t1));
10195     emit_insn (gen_clzsi2 (t3, t2));
10196     emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10197     DONE;
10198   }"
10201 ;; V5E instructions.
10203 (define_insn "prefetch"
10204   [(prefetch (match_operand:SI 0 "address_operand" "p")
10205              (match_operand:SI 1 "" "")
10206              (match_operand:SI 2 "" ""))]
10207   "TARGET_ARM && arm_arch5e"
10208   "pld\\t%a0")
10210 ;; General predication pattern
10212 (define_cond_exec
10213   [(match_operator 0 "arm_comparison_operator"
10214     [(match_operand 1 "cc_register" "")
10215      (const_int 0)])]
10216   "TARGET_ARM"
10217   ""
10220 (define_insn "prologue_use"
10221   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10222   ""
10223   "%@ %0 needed for prologue"
10227 ;; Patterns for exception handling
10229 (define_expand "eh_return"
10230   [(use (match_operand 0 "general_operand" ""))]
10231   "TARGET_EITHER"
10232   "
10233   {
10234     if (TARGET_ARM)
10235       emit_insn (gen_arm_eh_return (operands[0]));
10236     else
10237       emit_insn (gen_thumb_eh_return (operands[0]));
10238     DONE;
10239   }"
10241                                    
10242 ;; We can't expand this before we know where the link register is stored.
10243 (define_insn_and_split "arm_eh_return"
10244   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10245                     VUNSPEC_EH_RETURN)
10246    (clobber (match_scratch:SI 1 "=&r"))]
10247   "TARGET_ARM"
10248   "#"
10249   "&& reload_completed"
10250   [(const_int 0)]
10251   "
10252   {
10253     arm_set_return_address (operands[0], operands[1]);
10254     DONE;
10255   }"
10258 (define_insn_and_split "thumb_eh_return"
10259   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10260                     VUNSPEC_EH_RETURN)
10261    (clobber (match_scratch:SI 1 "=&l"))]
10262   "TARGET_THUMB"
10263   "#"
10264   "&& reload_completed"
10265   [(const_int 0)]
10266   "
10267   {
10268     thumb_set_return_address (operands[0], operands[1]);
10269     DONE;
10270   }"
10273 ;; Load the FPA co-processor patterns
10274 (include "fpa.md")
10275 ;; Load the Maverick co-processor patterns
10276 (include "cirrus.md")
10277 ;; Load the Intel Wireless Multimedia Extension patterns
10278 (include "iwmmxt.md")
10279 ;; Load the VFP co-processor patterns
10280 (include "vfp.md")