* arm.c (arm_const_double_by_parts): New function.
[official-gcc.git] / gcc / config / arm / arm.md
blobe94ceb81461c2f0a17cfb8dab4fb3788d0331fd3
1 ;;- Machine description for ARM for GNU compiler
2 ;;  Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;;  2001, 2002, 2003, 2004, 2005  Free Software Foundation, Inc.
4 ;;  Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
5 ;;  and Martin Simmons (@harleqn.co.uk).
6 ;;  More major hacks by Richard Earnshaw (rearnsha@arm.com).
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   [(R0_REGNUM        0)         ; First CORE register
34    (IP_REGNUM       12)         ; Scratch register
35    (SP_REGNUM       13)         ; Stack pointer
36    (LR_REGNUM       14)         ; Return address register
37    (PC_REGNUM       15)         ; Program counter
38    (CC_REGNUM       24)         ; Condition code pseudo register
39    (LAST_ARM_REGNUM 15)         ;
40    (FPA_F0_REGNUM   16)         ; FIRST_FPA_REGNUM
41    (FPA_F7_REGNUM   23)         ; LAST_FPA_REGNUM
42   ]
44 ;; 3rd operand to select_dominance_cc_mode
45 (define_constants
46   [(DOM_CC_X_AND_Y  0)
47    (DOM_CC_NX_OR_Y  1)
48    (DOM_CC_X_OR_Y   2)
49   ]
52 ;; UNSPEC Usage:
53 ;; Note: sin and cos are no-longer used.
55 (define_constants
56   [(UNSPEC_SIN       0) ; `sin' operation (MODE_FLOAT):
57                         ;   operand 0 is the result,
58                         ;   operand 1 the parameter.
59    (UNPSEC_COS       1) ; `cos' operation (MODE_FLOAT):
60                         ;   operand 0 is the result,
61                         ;   operand 1 the parameter.
62    (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
63                         ;   operand 0 is the first register,
64                         ;   subsequent registers are in parallel (use ...)
65                         ;   expressions.
66    (UNSPEC_PIC_SYM   3) ; A symbol that has been treated properly for pic
67                         ;   usage, that is, we will add the pic_register
68                         ;   value to it before trying to dereference it.
69    (UNSPEC_PIC_BASE  4) ; Adding the PC value to the offset to the
70                         ;   GLOBAL_OFFSET_TABLE.  The operation is fully
71                         ;   described by the RTL but must be wrapped to
72                         ;   prevent combine from trying to rip it apart.
73    (UNSPEC_PRLG_STK  5) ; A special barrier that prevents frame accesses 
74                         ;   being scheduled before the stack adjustment insn.
75    (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
76                         ; this unspec is used to prevent the deletion of
77                         ; instructions setting registers for EH handling
78                         ; and stack frame generation.  Operand 0 is the
79                         ; register to "use".
80    (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
81    (UNSPEC_WSHUFH    8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
82    (UNSPEC_WACC      9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
83    (UNSPEC_TMOVMSK  10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
84    (UNSPEC_WSAD     11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
85    (UNSPEC_WSADZ    12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
86    (UNSPEC_WMACS    13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
87    (UNSPEC_WMACU    14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
88    (UNSPEC_WMACSZ   15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
89    (UNSPEC_WMACUZ   16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
90    (UNSPEC_CLRDI    17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
91    (UNSPEC_WMADDS   18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
92    (UNSPEC_WMADDU   19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
93   ]
96 ;; UNSPEC_VOLATILE Usage:
98 (define_constants
99   [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
100                         ;   insn in the code.
101    (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
102                         ;   instruction epilogue sequence that isn't expanded
103                         ;   into normal RTL.  Used for both normal and sibcall
104                         ;   epilogues.
105    (VUNSPEC_ALIGN    2) ; `align' insn.  Used at the head of a minipool table 
106                         ;   for inlined constants.
107    (VUNSPEC_POOL_END 3) ; `end-of-table'.  Used to mark the end of a minipool
108                         ;   table.
109    (VUNSPEC_POOL_1   4) ; `pool-entry(1)'.  An entry in the constant pool for
110                         ;   an 8-bit object.
111    (VUNSPEC_POOL_2   5) ; `pool-entry(2)'.  An entry in the constant pool for
112                         ;   a 16-bit object.
113    (VUNSPEC_POOL_4   6) ; `pool-entry(4)'.  An entry in the constant pool for
114                         ;   a 32-bit object.
115    (VUNSPEC_POOL_8   7) ; `pool-entry(8)'.  An entry in the constant pool for
116                         ;   a 64-bit object.
117    (VUNSPEC_TMRC     8) ; Used by the iWMMXt TMRC instruction.
118    (VUNSPEC_TMCR     9) ; Used by the iWMMXt TMCR instruction.
119    (VUNSPEC_ALIGN8   10) ; 8-byte alignment version of VUNSPEC_ALIGN
120    (VUNSPEC_WCMP_EQ  11) ; Used by the iWMMXt WCMPEQ instructions
121    (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
122    (VUNSPEC_WCMP_GT  13) ; Used by the iwMMXT WCMPGT instructions
123    (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
124                          ; handling.
125   ]
128 ;;---------------------------------------------------------------------------
129 ;; Attributes
131 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
132 ; generating ARM code.  This is used to control the length of some insn
133 ; patterns that share the same RTL in both ARM and Thumb code.
134 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
136 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
137 ; scheduling decisions for the load unit and the multiplier.
138 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
140 ; IS_XSCALE is set to 'yes' when compiling for XScale.
141 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
143 ;; Operand number of an input operand that is shifted.  Zero if the
144 ;; given instruction does not shift one of its input operands.
145 (define_attr "shift" "" (const_int 0))
147 ; Floating Point Unit.  If we only have floating point emulation, then there
148 ; is no point in scheduling the floating point insns.  (Well, for best
149 ; performance we should try and group them together).
150 (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
151   (const (symbol_ref "arm_fpu_attr")))
153 ; LENGTH of an instruction (in bytes)
154 (define_attr "length" "" (const_int 4))
156 ; POOL_RANGE is how far away from a constant pool entry that this insn
157 ; can be placed.  If the distance is zero, then this insn will never
158 ; reference the pool.
159 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
160 ; before its address.
161 (define_attr "pool_range" "" (const_int 0))
162 (define_attr "neg_pool_range" "" (const_int 0))
164 ; An assembler sequence may clobber the condition codes without us knowing.
165 ; If such an insn references the pool, then we have no way of knowing how,
166 ; so use the most conservative value for pool_range.
167 (define_asm_attributes
168  [(set_attr "conds" "clob")
169   (set_attr "length" "4")
170   (set_attr "pool_range" "250")])
172 ;; The instruction used to implement a particular pattern.  This
173 ;; information is used by pipeline descriptions to provide accurate
174 ;; scheduling information.
176 (define_attr "insn"
177         "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals,smlawy,smuad,smuadx,smlad,smladx,smusd,smusdx,smlsd,smlsdx,smmul,smmulr,other"
178         (const_string "other"))
180 ; TYPE attribute is used to detect floating point instructions which, if
181 ; running on a co-processor can run in parallel with other, basic instructions
182 ; If write-buffer scheduling is enabled then it can also be used in the
183 ; scheduling of writes.
185 ; Classification of each insn
186 ; alu           any alu  instruction that doesn't hit memory or fp
187 ;               regs or have a shifted source operand
188 ; alu_shift     any data instruction that doesn't hit memory or fp
189 ;               regs, but has a source operand shifted by a constant
190 ; alu_shift_reg any data instruction that doesn't hit memory or fp
191 ;               regs, but has a source operand shifted by a register value
192 ; mult          a multiply instruction
193 ; block         blockage insn, this blocks all functional units
194 ; float         a floating point arithmetic operation (subject to expansion)
195 ; fdivd         DFmode floating point division
196 ; fdivs         SFmode floating point division
197 ; fmul          Floating point multiply
198 ; ffmul         Fast floating point multiply
199 ; farith        Floating point arithmetic (4 cycle)
200 ; ffarith       Fast floating point arithmetic (2 cycle)
201 ; float_em      a floating point arithmetic operation that is normally emulated
202 ;               even on a machine with an fpa.
203 ; f_load        a floating point load from memory
204 ; f_store       a floating point store to memory
205 ; f_mem_r       a transfer of a floating point register to a real reg via mem
206 ; r_mem_f       the reverse of f_mem_r
207 ; f_2_r         fast transfer float to arm (no memory needed)
208 ; r_2_f         fast transfer arm to float
209 ; branch        a branch
210 ; call          a subroutine call
211 ; load_byte     load byte(s) from memory to arm registers
212 ; load1         load 1 word from memory to arm registers
213 ; load2         load 2 words from memory to arm registers
214 ; load3         load 3 words from memory to arm registers
215 ; load4         load 4 words from memory to arm registers
216 ; store         store 1 word to memory from arm registers
217 ; store2        store 2 words
218 ; store3        store 3 words
219 ; store4        store 4 (or more) words
220 ;  Additions for Cirrus Maverick co-processor:
221 ; mav_farith    Floating point arithmetic (4 cycle)
222 ; mav_dmult     Double multiplies (7 cycle)
224 (define_attr "type"
225         "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,float_em,f_load,f_store,f_mem_r,r_mem_f,f_2_r,r_2_f,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult" 
226         (if_then_else 
227          (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
228          (const_string "mult")
229          (const_string "alu")))
231 ; Load scheduling, set from the arm_ld_sched variable
232 ; initialized by arm_override_options() 
233 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
235 ; condition codes: this one is used by final_prescan_insn to speed up
236 ; conditionalizing instructions.  It saves having to scan the rtl to see if
237 ; it uses or alters the condition codes.
239 ; USE means that the condition codes are used by the insn in the process of
240 ;   outputting code, this means (at present) that we can't use the insn in
241 ;   inlined branches
243 ; SET means that the purpose of the insn is to set the condition codes in a
244 ;   well defined manner.
246 ; CLOB means that the condition codes are altered in an undefined manner, if
247 ;   they are altered at all
249 ; JUMP_CLOB is used when the condition cannot be represented by a single
250 ;   instruction (UNEQ and LTGT).  These cannot be predicated.
252 ; NOCOND means that the condition codes are neither altered nor affect the
253 ;   output of this insn
255 (define_attr "conds" "use,set,clob,jump_clob,nocond"
256         (if_then_else (eq_attr "type" "call")
257          (const_string "clob")
258          (const_string "nocond")))
260 ; Predicable means that the insn can be conditionally executed based on
261 ; an automatically added predicate (additional patterns are generated by 
262 ; gen...).  We default to 'no' because no Thumb patterns match this rule
263 ; and not all ARM patterns do.
264 (define_attr "predicable" "no,yes" (const_string "no"))
266 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
267 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
268 ; suffer blockages enough to warrant modelling this (and it can adversely
269 ; affect the schedule).
270 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
272 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
273 ; to stall the processor.  Used with model_wbuf above.
274 (define_attr "write_conflict" "no,yes"
275   (if_then_else (eq_attr "type"
276                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
277                 (const_string "yes")
278                 (const_string "no")))
280 ; Classify the insns into those that take one cycle and those that take more
281 ; than one on the main cpu execution unit.
282 (define_attr "core_cycles" "single,multi"
283   (if_then_else (eq_attr "type"
284                  "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
285                 (const_string "single")
286                 (const_string "multi")))
288 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
289 ;; distant label.  Only applicable to Thumb code.
290 (define_attr "far_jump" "yes,no" (const_string "no"))
293 ;;---------------------------------------------------------------------------
294 ;; Mode macros
296 ; A list of modes that are exactly 64 bits in size.  We use this to expand
297 ; some splits that are the same for all modes when operating on ARM 
298 ; registers.
299 (define_mode_macro ANY64 [DI DF V8QI V4HI V2SI V2SF])
301 ;;---------------------------------------------------------------------------
302 ;; Predicates
304 (include "predicates.md")
306 ;;---------------------------------------------------------------------------
307 ;; Pipeline descriptions
309 ;; Processor type.  This is created automatically from arm-cores.def.
310 (include "arm-tune.md")
312 ;; True if the generic scheduling description should be used.
314 (define_attr "generic_sched" "yes,no"
315   (const (if_then_else 
316           (eq_attr "tune" "arm926ejs,arm1026ejs,arm1136js,arm1136jfs") 
317           (const_string "no")
318           (const_string "yes"))))
320 (include "arm-generic.md")
321 (include "arm926ejs.md")
322 (include "arm1026ejs.md")
323 (include "arm1136jfs.md")
326 ;;---------------------------------------------------------------------------
327 ;; Insn patterns
329 ;; Addition insns.
331 ;; Note: For DImode insns, there is normally no reason why operands should
332 ;; not be in the same register, what we don't want is for something being
333 ;; written to partially overlap something that is an input.
334 ;; Cirrus 64bit additions should not be split because we have a native
335 ;; 64bit addition instructions.
337 (define_expand "adddi3"
338  [(parallel
339    [(set (match_operand:DI           0 "s_register_operand" "")
340           (plus:DI (match_operand:DI 1 "s_register_operand" "")
341                    (match_operand:DI 2 "s_register_operand" "")))
342     (clobber (reg:CC CC_REGNUM))])]
343   "TARGET_EITHER"
344   "
345   if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
346     {
347       if (!cirrus_fp_register (operands[0], DImode))
348         operands[0] = force_reg (DImode, operands[0]);
349       if (!cirrus_fp_register (operands[1], DImode))
350         operands[1] = force_reg (DImode, operands[1]);
351       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
352       DONE;
353     }
355   if (TARGET_THUMB)
356     {
357       if (GET_CODE (operands[1]) != REG)
358         operands[1] = force_reg (SImode, operands[1]);
359       if (GET_CODE (operands[2]) != REG)
360         operands[2] = force_reg (SImode, operands[2]);
361      }
362   "
365 (define_insn "*thumb_adddi3"
366   [(set (match_operand:DI          0 "register_operand" "=l")
367         (plus:DI (match_operand:DI 1 "register_operand" "%0")
368                  (match_operand:DI 2 "register_operand" "l")))
369    (clobber (reg:CC CC_REGNUM))
370   ]
371   "TARGET_THUMB"
372   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
373   [(set_attr "length" "4")]
376 (define_insn_and_split "*arm_adddi3"
377   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
378         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
379                  (match_operand:DI 2 "s_register_operand" "r,  0")))
380    (clobber (reg:CC CC_REGNUM))]
381   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
382   "#"
383   "TARGET_ARM && reload_completed"
384   [(parallel [(set (reg:CC_C CC_REGNUM)
385                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
386                                  (match_dup 1)))
387               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
388    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
389                                (plus:SI (match_dup 4) (match_dup 5))))]
390   "
391   {
392     operands[3] = gen_highpart (SImode, operands[0]);
393     operands[0] = gen_lowpart (SImode, operands[0]);
394     operands[4] = gen_highpart (SImode, operands[1]);
395     operands[1] = gen_lowpart (SImode, operands[1]);
396     operands[5] = gen_highpart (SImode, operands[2]);
397     operands[2] = gen_lowpart (SImode, operands[2]);
398   }"
399   [(set_attr "conds" "clob")
400    (set_attr "length" "8")]
403 (define_insn_and_split "*adddi_sesidi_di"
404   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
405         (plus:DI (sign_extend:DI
406                   (match_operand:SI 2 "s_register_operand" "r,r"))
407                  (match_operand:DI 1 "s_register_operand" "r,0")))
408    (clobber (reg:CC CC_REGNUM))]
409   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
410   "#"
411   "TARGET_ARM && reload_completed"
412   [(parallel [(set (reg:CC_C CC_REGNUM)
413                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
414                                  (match_dup 1)))
415               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
416    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
417                                (plus:SI (ashiftrt:SI (match_dup 2)
418                                                      (const_int 31))
419                                         (match_dup 4))))]
420   "
421   {
422     operands[3] = gen_highpart (SImode, operands[0]);
423     operands[0] = gen_lowpart (SImode, operands[0]);
424     operands[4] = gen_highpart (SImode, operands[1]);
425     operands[1] = gen_lowpart (SImode, operands[1]);
426     operands[2] = gen_lowpart (SImode, operands[2]);
427   }"
428   [(set_attr "conds" "clob")
429    (set_attr "length" "8")]
432 (define_insn_and_split "*adddi_zesidi_di"
433   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
434         (plus:DI (zero_extend:DI
435                   (match_operand:SI 2 "s_register_operand" "r,r"))
436                  (match_operand:DI 1 "s_register_operand" "r,0")))
437    (clobber (reg:CC CC_REGNUM))]
438   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
439   "#"
440   "TARGET_ARM && reload_completed"
441   [(parallel [(set (reg:CC_C CC_REGNUM)
442                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
443                                  (match_dup 1)))
444               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
445    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
446                                (plus:SI (match_dup 4) (const_int 0))))]
447   "
448   {
449     operands[3] = gen_highpart (SImode, operands[0]);
450     operands[0] = gen_lowpart (SImode, operands[0]);
451     operands[4] = gen_highpart (SImode, operands[1]);
452     operands[1] = gen_lowpart (SImode, operands[1]);
453     operands[2] = gen_lowpart (SImode, operands[2]);
454   }"
455   [(set_attr "conds" "clob")
456    (set_attr "length" "8")]
459 (define_expand "addsi3"
460   [(set (match_operand:SI          0 "s_register_operand" "")
461         (plus:SI (match_operand:SI 1 "s_register_operand" "")
462                  (match_operand:SI 2 "reg_or_int_operand" "")))]
463   "TARGET_EITHER"
464   "
465   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
466     {
467       arm_split_constant (PLUS, SImode, NULL_RTX,
468                           INTVAL (operands[2]), operands[0], operands[1],
469                           optimize && !no_new_pseudos);
470       DONE;
471     }
472   "
475 ; If there is a scratch available, this will be faster than synthesizing the
476 ; addition.
477 (define_peephole2
478   [(match_scratch:SI 3 "r")
479    (set (match_operand:SI          0 "arm_general_register_operand" "")
480         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
481                  (match_operand:SI 2 "const_int_operand"  "")))]
482   "TARGET_ARM &&
483    !(const_ok_for_arm (INTVAL (operands[2]))
484      || const_ok_for_arm (-INTVAL (operands[2])))
485     && const_ok_for_arm (~INTVAL (operands[2]))"
486   [(set (match_dup 3) (match_dup 2))
487    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
488   ""
491 (define_insn_and_split "*arm_addsi3"
492   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
493         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
494                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
495   "TARGET_ARM"
496   "@
497    add%?\\t%0, %1, %2
498    sub%?\\t%0, %1, #%n2
499    #"
500   "TARGET_ARM &&
501    GET_CODE (operands[2]) == CONST_INT
502    && !(const_ok_for_arm (INTVAL (operands[2]))
503         || const_ok_for_arm (-INTVAL (operands[2])))"
504   [(clobber (const_int 0))]
505   "
506   arm_split_constant (PLUS, SImode, curr_insn,
507                       INTVAL (operands[2]), operands[0],
508                       operands[1], 0);
509   DONE;
510   "
511   [(set_attr "length" "4,4,16")
512    (set_attr "predicable" "yes")]
515 ;; Register group 'k' is a single register group containing only the stack
516 ;; register.  Trying to reload it will always fail catastrophically,
517 ;; so never allow those alternatives to match if reloading is needed.
519 (define_insn "*thumb_addsi3"
520   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
521         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
522                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
523   "TARGET_THUMB"
524   "*
525    static const char * const asms[] = 
526    {
527      \"add\\t%0, %0, %2\",
528      \"sub\\t%0, %0, #%n2\",
529      \"add\\t%0, %1, %2\",
530      \"add\\t%0, %0, %2\",
531      \"add\\t%0, %0, %2\",
532      \"add\\t%0, %1, %2\",
533      \"add\\t%0, %1, %2\"
534    };
535    if ((which_alternative == 2 || which_alternative == 6)
536        && GET_CODE (operands[2]) == CONST_INT
537        && INTVAL (operands[2]) < 0)
538      return \"sub\\t%0, %1, #%n2\";
539    return asms[which_alternative];
540   "
541   [(set_attr "length" "2")]
544 ;; Reloading and elimination of the frame pointer can
545 ;; sometimes cause this optimization to be missed.
546 (define_peephole2
547   [(set (match_operand:SI 0 "arm_general_register_operand" "")
548         (match_operand:SI 1 "const_int_operand" ""))
549    (set (match_dup 0)
550         (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
551   "TARGET_THUMB
552    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
553    && (INTVAL (operands[1]) & 3) == 0"
554   [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
555   ""
558 (define_insn "*addsi3_compare0"
559   [(set (reg:CC_NOOV CC_REGNUM)
560         (compare:CC_NOOV
561          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
562                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
563          (const_int 0)))
564    (set (match_operand:SI 0 "s_register_operand" "=r,r")
565         (plus:SI (match_dup 1) (match_dup 2)))]
566   "TARGET_ARM"
567   "@
568    add%?s\\t%0, %1, %2
569    sub%?s\\t%0, %1, #%n2"
570   [(set_attr "conds" "set")]
573 (define_insn "*addsi3_compare0_scratch"
574   [(set (reg:CC_NOOV CC_REGNUM)
575         (compare:CC_NOOV
576          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
577                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
578          (const_int 0)))]
579   "TARGET_ARM"
580   "@
581    cmn%?\\t%0, %1
582    cmp%?\\t%0, #%n1"
583   [(set_attr "conds" "set")]
586 (define_insn "*compare_negsi_si"
587   [(set (reg:CC_Z CC_REGNUM)
588         (compare:CC_Z
589          (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
590          (match_operand:SI 1 "s_register_operand" "r")))]
591   "TARGET_ARM"
592   "cmn%?\\t%1, %0"
593   [(set_attr "conds" "set")]
596 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
597 ;; addend is a constant.
598 (define_insn "*cmpsi2_addneg"
599   [(set (reg:CC CC_REGNUM)
600         (compare:CC
601          (match_operand:SI 1 "s_register_operand" "r,r")
602          (match_operand:SI 2 "arm_addimm_operand" "I,L")))
603    (set (match_operand:SI 0 "s_register_operand" "=r,r")
604         (plus:SI (match_dup 1)
605                  (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
606   "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
607   "@
608    sub%?s\\t%0, %1, %2
609    add%?s\\t%0, %1, #%n2"
610   [(set_attr "conds" "set")]
613 ;; Convert the sequence
614 ;;  sub  rd, rn, #1
615 ;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
616 ;;  bne  dest
617 ;; into
618 ;;  subs rd, rn, #1
619 ;;  bcs  dest   ((unsigned)rn >= 1)
620 ;; similarly for the beq variant using bcc.
621 ;; This is a common looping idiom (while (n--))
622 (define_peephole2
623   [(set (match_operand:SI 0 "arm_general_register_operand" "")
624         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
625                  (const_int -1)))
626    (set (match_operand 2 "cc_register" "")
627         (compare (match_dup 0) (const_int -1)))
628    (set (pc)
629         (if_then_else (match_operator 3 "equality_operator"
630                        [(match_dup 2) (const_int 0)])
631                       (match_operand 4 "" "")
632                       (match_operand 5 "" "")))]
633   "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
634   [(parallel[
635     (set (match_dup 2)
636          (compare:CC
637           (match_dup 1) (const_int 1)))
638     (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
639    (set (pc)
640         (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
641                       (match_dup 4)
642                       (match_dup 5)))]
643   "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
644    operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
645                                   ? GEU : LTU),
646                                  VOIDmode, 
647                                  operands[2], const0_rtx);"
650 ;; The next four insns work because they compare the result with one of
651 ;; the operands, and we know that the use of the condition code is
652 ;; either GEU or LTU, so we can use the carry flag from the addition
653 ;; instead of doing the compare a second time.
654 (define_insn "*addsi3_compare_op1"
655   [(set (reg:CC_C CC_REGNUM)
656         (compare:CC_C
657          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
658                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
659          (match_dup 1)))
660    (set (match_operand:SI 0 "s_register_operand" "=r,r")
661         (plus:SI (match_dup 1) (match_dup 2)))]
662   "TARGET_ARM"
663   "@
664    add%?s\\t%0, %1, %2
665    sub%?s\\t%0, %1, #%n2"
666   [(set_attr "conds" "set")]
669 (define_insn "*addsi3_compare_op2"
670   [(set (reg:CC_C CC_REGNUM)
671         (compare:CC_C
672          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
673                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
674          (match_dup 2)))
675    (set (match_operand:SI 0 "s_register_operand" "=r,r")
676         (plus:SI (match_dup 1) (match_dup 2)))]
677   "TARGET_ARM"
678   "@
679    add%?s\\t%0, %1, %2
680    sub%?s\\t%0, %1, #%n2"
681   [(set_attr "conds" "set")]
684 (define_insn "*compare_addsi2_op0"
685   [(set (reg:CC_C CC_REGNUM)
686         (compare:CC_C
687          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
688                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
689          (match_dup 0)))]
690   "TARGET_ARM"
691   "@
692    cmn%?\\t%0, %1
693    cmp%?\\t%0, #%n1"
694   [(set_attr "conds" "set")]
697 (define_insn "*compare_addsi2_op1"
698   [(set (reg:CC_C CC_REGNUM)
699         (compare:CC_C
700          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
701                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
702          (match_dup 1)))]
703   "TARGET_ARM"
704   "@
705    cmn%?\\t%0, %1
706    cmp%?\\t%0, #%n1"
707   [(set_attr "conds" "set")]
710 (define_insn "*addsi3_carryin"
711   [(set (match_operand:SI 0 "s_register_operand" "=r")
712         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
713                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
714                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
715   "TARGET_ARM"
716   "adc%?\\t%0, %1, %2"
717   [(set_attr "conds" "use")]
720 (define_insn "*addsi3_carryin_shift"
721   [(set (match_operand:SI 0 "s_register_operand" "=r")
722         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
723                  (plus:SI
724                    (match_operator:SI 2 "shift_operator"
725                       [(match_operand:SI 3 "s_register_operand" "r")
726                        (match_operand:SI 4 "reg_or_int_operand" "rM")])
727                     (match_operand:SI 1 "s_register_operand" "r"))))]
728   "TARGET_ARM"
729   "adc%?\\t%0, %1, %3%S2"
730   [(set_attr "conds" "use")
731    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
732                       (const_string "alu_shift")
733                       (const_string "alu_shift_reg")))]
736 (define_insn "*addsi3_carryin_alt1"
737   [(set (match_operand:SI 0 "s_register_operand" "=r")
738         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
739                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
740                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
741   "TARGET_ARM"
742   "adc%?\\t%0, %1, %2"
743   [(set_attr "conds" "use")]
746 (define_insn "*addsi3_carryin_alt2"
747   [(set (match_operand:SI 0 "s_register_operand" "=r")
748         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
749                           (match_operand:SI 1 "s_register_operand" "r"))
750                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
751   "TARGET_ARM"
752   "adc%?\\t%0, %1, %2"
753   [(set_attr "conds" "use")]
756 (define_insn "*addsi3_carryin_alt3"
757   [(set (match_operand:SI 0 "s_register_operand" "=r")
758         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
759                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
760                  (match_operand:SI 1 "s_register_operand" "r")))]
761   "TARGET_ARM"
762   "adc%?\\t%0, %1, %2"
763   [(set_attr "conds" "use")]
766 (define_insn "incscc"
767   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
768         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
769                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
770                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
771   "TARGET_ARM"
772   "@
773   add%d2\\t%0, %1, #1
774   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
775   [(set_attr "conds" "use")
776    (set_attr "length" "4,8")]
779 ; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
780 (define_split
781   [(set (match_operand:SI 0 "s_register_operand" "")
782         (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
783                             (match_operand:SI 2 "s_register_operand" ""))
784                  (const_int -1)))
785    (clobber (match_operand:SI 3 "s_register_operand" ""))]
786   "TARGET_ARM"
787   [(set (match_dup 3) (match_dup 1))
788    (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
789   "
790   operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
793 (define_expand "addsf3"
794   [(set (match_operand:SF          0 "s_register_operand" "")
795         (plus:SF (match_operand:SF 1 "s_register_operand" "")
796                  (match_operand:SF 2 "arm_float_add_operand" "")))]
797   "TARGET_ARM && TARGET_HARD_FLOAT"
798   "
799   if (TARGET_MAVERICK
800       && !cirrus_fp_register (operands[2], SFmode))
801     operands[2] = force_reg (SFmode, operands[2]);
804 (define_expand "adddf3"
805   [(set (match_operand:DF          0 "s_register_operand" "")
806         (plus:DF (match_operand:DF 1 "s_register_operand" "")
807                  (match_operand:DF 2 "arm_float_add_operand" "")))]
808   "TARGET_ARM && TARGET_HARD_FLOAT"
809   "
810   if (TARGET_MAVERICK
811       && !cirrus_fp_register (operands[2], DFmode))
812     operands[2] = force_reg (DFmode, operands[2]);
815 (define_expand "subdi3"
816  [(parallel
817    [(set (match_operand:DI            0 "s_register_operand" "")
818           (minus:DI (match_operand:DI 1 "s_register_operand" "")
819                     (match_operand:DI 2 "s_register_operand" "")))
820     (clobber (reg:CC CC_REGNUM))])]
821   "TARGET_EITHER"
822   "
823   if (TARGET_HARD_FLOAT && TARGET_MAVERICK
824       && TARGET_ARM
825       && cirrus_fp_register (operands[0], DImode)
826       && cirrus_fp_register (operands[1], DImode))
827     {
828       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
829       DONE;
830     }
832   if (TARGET_THUMB)
833     {
834       if (GET_CODE (operands[1]) != REG)
835         operands[1] = force_reg (SImode, operands[1]);
836       if (GET_CODE (operands[2]) != REG)
837         operands[2] = force_reg (SImode, operands[2]);
838      }  
839   "
842 (define_insn "*arm_subdi3"
843   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
844         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
845                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
846    (clobber (reg:CC CC_REGNUM))]
847   "TARGET_ARM"
848   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
849   [(set_attr "conds" "clob")
850    (set_attr "length" "8")]
853 (define_insn "*thumb_subdi3"
854   [(set (match_operand:DI           0 "register_operand" "=l")
855         (minus:DI (match_operand:DI 1 "register_operand"  "0")
856                   (match_operand:DI 2 "register_operand"  "l")))
857    (clobber (reg:CC CC_REGNUM))]
858   "TARGET_THUMB"
859   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
860   [(set_attr "length" "4")]
863 (define_insn "*subdi_di_zesidi"
864   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
865         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
866                   (zero_extend:DI
867                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
868    (clobber (reg:CC CC_REGNUM))]
869   "TARGET_ARM"
870   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
871   [(set_attr "conds" "clob")
872    (set_attr "length" "8")]
875 (define_insn "*subdi_di_sesidi"
876   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
877         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
878                   (sign_extend:DI
879                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
880    (clobber (reg:CC CC_REGNUM))]
881   "TARGET_ARM"
882   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
883   [(set_attr "conds" "clob")
884    (set_attr "length" "8")]
887 (define_insn "*subdi_zesidi_di"
888   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
889         (minus:DI (zero_extend:DI
890                    (match_operand:SI 2 "s_register_operand"  "r,r"))
891                   (match_operand:DI  1 "s_register_operand" "?r,0")))
892    (clobber (reg:CC CC_REGNUM))]
893   "TARGET_ARM"
894   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
895   [(set_attr "conds" "clob")
896    (set_attr "length" "8")]
899 (define_insn "*subdi_sesidi_di"
900   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
901         (minus:DI (sign_extend:DI
902                    (match_operand:SI 2 "s_register_operand"   "r,r"))
903                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
904    (clobber (reg:CC CC_REGNUM))]
905   "TARGET_ARM"
906   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
907   [(set_attr "conds" "clob")
908    (set_attr "length" "8")]
911 (define_insn "*subdi_zesidi_zesidi"
912   [(set (match_operand:DI            0 "s_register_operand" "=r")
913         (minus:DI (zero_extend:DI
914                    (match_operand:SI 1 "s_register_operand"  "r"))
915                   (zero_extend:DI
916                    (match_operand:SI 2 "s_register_operand"  "r"))))
917    (clobber (reg:CC CC_REGNUM))]
918   "TARGET_ARM"
919   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
920   [(set_attr "conds" "clob")
921    (set_attr "length" "8")]
924 (define_expand "subsi3"
925   [(set (match_operand:SI           0 "s_register_operand" "")
926         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
927                   (match_operand:SI 2 "s_register_operand" "")))]
928   "TARGET_EITHER"
929   "
930   if (GET_CODE (operands[1]) == CONST_INT)
931     {
932       if (TARGET_ARM)
933         {
934           arm_split_constant (MINUS, SImode, NULL_RTX,
935                               INTVAL (operands[1]), operands[0],
936                               operands[2], optimize && !no_new_pseudos);
937           DONE;
938         }
939       else /* TARGET_THUMB */
940         operands[1] = force_reg (SImode, operands[1]);
941     }
942   "
945 (define_insn "*thumb_subsi3_insn"
946   [(set (match_operand:SI           0 "register_operand" "=l")
947         (minus:SI (match_operand:SI 1 "register_operand" "l")
948                   (match_operand:SI 2 "register_operand" "l")))]
949   "TARGET_THUMB"
950   "sub\\t%0, %1, %2"
951   [(set_attr "length" "2")]
954 (define_insn_and_split "*arm_subsi3_insn"
955   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
956         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
957                   (match_operand:SI 2 "s_register_operand" "r,r")))]
958   "TARGET_ARM"
959   "@
960    rsb%?\\t%0, %2, %1
961    #"
962   "TARGET_ARM
963    && GET_CODE (operands[1]) == CONST_INT
964    && !const_ok_for_arm (INTVAL (operands[1]))"
965   [(clobber (const_int 0))]
966   "
967   arm_split_constant (MINUS, SImode, curr_insn,
968                       INTVAL (operands[1]), operands[0], operands[2], 0);
969   DONE;
970   "
971   [(set_attr "length" "4,16")
972    (set_attr "predicable" "yes")]
975 (define_peephole2
976   [(match_scratch:SI 3 "r")
977    (set (match_operand:SI 0 "arm_general_register_operand" "")
978         (minus:SI (match_operand:SI 1 "const_int_operand" "")
979                   (match_operand:SI 2 "arm_general_register_operand" "")))]
980   "TARGET_ARM
981    && !const_ok_for_arm (INTVAL (operands[1]))
982    && const_ok_for_arm (~INTVAL (operands[1]))"
983   [(set (match_dup 3) (match_dup 1))
984    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
985   ""
988 (define_insn "*subsi3_compare0"
989   [(set (reg:CC_NOOV CC_REGNUM)
990         (compare:CC_NOOV
991          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
992                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
993          (const_int 0)))
994    (set (match_operand:SI 0 "s_register_operand" "=r,r")
995         (minus:SI (match_dup 1) (match_dup 2)))]
996   "TARGET_ARM"
997   "@
998    sub%?s\\t%0, %1, %2
999    rsb%?s\\t%0, %2, %1"
1000   [(set_attr "conds" "set")]
1003 (define_insn "decscc"
1004   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1005         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1006                   (match_operator:SI 2 "arm_comparison_operator"
1007                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1008   "TARGET_ARM"
1009   "@
1010    sub%d2\\t%0, %1, #1
1011    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1012   [(set_attr "conds" "use")
1013    (set_attr "length" "*,8")]
1016 (define_expand "subsf3"
1017   [(set (match_operand:SF           0 "s_register_operand" "")
1018         (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1019                   (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1020   "TARGET_ARM && TARGET_HARD_FLOAT"
1021   "
1022   if (TARGET_MAVERICK)
1023     {
1024       if (!cirrus_fp_register (operands[1], SFmode))
1025         operands[1] = force_reg (SFmode, operands[1]);
1026       if (!cirrus_fp_register (operands[2], SFmode))
1027         operands[2] = force_reg (SFmode, operands[2]);
1028     }
1031 (define_expand "subdf3"
1032   [(set (match_operand:DF           0 "s_register_operand" "")
1033         (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1034                   (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1035   "TARGET_ARM && TARGET_HARD_FLOAT"
1036   "
1037   if (TARGET_MAVERICK)
1038     {
1039        if (!cirrus_fp_register (operands[1], DFmode))
1040          operands[1] = force_reg (DFmode, operands[1]);
1041        if (!cirrus_fp_register (operands[2], DFmode))
1042          operands[2] = force_reg (DFmode, operands[2]);
1043     }
1047 ;; Multiplication insns
1049 (define_expand "mulsi3"
1050   [(set (match_operand:SI          0 "s_register_operand" "")
1051         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1052                  (match_operand:SI 1 "s_register_operand" "")))]
1053   "TARGET_EITHER"
1054   ""
1057 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1058 (define_insn "*arm_mulsi3"
1059   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1060         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1061                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1062   "TARGET_ARM"
1063   "mul%?\\t%0, %2, %1"
1064   [(set_attr "insn" "mul")
1065    (set_attr "predicable" "yes")]
1068 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1069 ; 1 and 2; are the same, because reload will make operand 0 match 
1070 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1071 ; this by adding another alternative to match this case, and then `reload' 
1072 ; it ourselves.  This alternative must come first.
1073 (define_insn "*thumb_mulsi3"
1074   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1075         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1076                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1077   "TARGET_THUMB"
1078   "*
1079   if (which_alternative < 2)
1080     return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1081   else
1082     return \"mul\\t%0, %0, %2\";
1083   "
1084   [(set_attr "length" "4,4,2")
1085    (set_attr "insn" "mul")]
1088 (define_insn "*mulsi3_compare0"
1089   [(set (reg:CC_NOOV CC_REGNUM)
1090         (compare:CC_NOOV (mult:SI
1091                           (match_operand:SI 2 "s_register_operand" "r,r")
1092                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1093                          (const_int 0)))
1094    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1095         (mult:SI (match_dup 2) (match_dup 1)))]
1096   "TARGET_ARM"
1097   "mul%?s\\t%0, %2, %1"
1098   [(set_attr "conds" "set")
1099    (set_attr "insn" "muls")]
1102 (define_insn "*mulsi_compare0_scratch"
1103   [(set (reg:CC_NOOV CC_REGNUM)
1104         (compare:CC_NOOV (mult:SI
1105                           (match_operand:SI 2 "s_register_operand" "r,r")
1106                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1107                          (const_int 0)))
1108    (clobber (match_scratch:SI 0 "=&r,&r"))]
1109   "TARGET_ARM"
1110   "mul%?s\\t%0, %2, %1"
1111   [(set_attr "conds" "set")
1112    (set_attr "insn" "muls")]
1115 ;; Unnamed templates to match MLA instruction.
1117 (define_insn "*mulsi3addsi"
1118   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1119         (plus:SI
1120           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1121                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1122           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1123   "TARGET_ARM"
1124   "mla%?\\t%0, %2, %1, %3"
1125   [(set_attr "insn" "mla")
1126    (set_attr "predicable" "yes")]
1129 (define_insn "*mulsi3addsi_compare0"
1130   [(set (reg:CC_NOOV CC_REGNUM)
1131         (compare:CC_NOOV
1132          (plus:SI (mult:SI
1133                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1134                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1135                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1136          (const_int 0)))
1137    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1138         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1139                  (match_dup 3)))]
1140   "TARGET_ARM"
1141   "mla%?s\\t%0, %2, %1, %3"
1142   [(set_attr "conds" "set")
1143    (set_attr "insn" "mlas")]
1146 (define_insn "*mulsi3addsi_compare0_scratch"
1147   [(set (reg:CC_NOOV CC_REGNUM)
1148         (compare:CC_NOOV
1149          (plus:SI (mult:SI
1150                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1151                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1152                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1153          (const_int 0)))
1154    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1155   "TARGET_ARM"
1156   "mla%?s\\t%0, %2, %1, %3"
1157   [(set_attr "conds" "set")
1158    (set_attr "insn" "mlas")]
1161 ;; Unnamed template to match long long multiply-accumulate (smlal)
1163 (define_insn "*mulsidi3adddi"
1164   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1165         (plus:DI
1166          (mult:DI
1167           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1168           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1169          (match_operand:DI 1 "s_register_operand" "0")))]
1170   "TARGET_ARM && arm_arch3m"
1171   "smlal%?\\t%Q0, %R0, %3, %2"
1172   [(set_attr "insn" "smlal")
1173    (set_attr "predicable" "yes")]
1176 (define_insn "mulsidi3"
1177   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1178         (mult:DI
1179          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1180          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1181   "TARGET_ARM && arm_arch3m"
1182   "smull%?\\t%Q0, %R0, %1, %2"
1183   [(set_attr "insn" "smull")
1184    (set_attr "predicable" "yes")]
1187 (define_insn "umulsidi3"
1188   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1189         (mult:DI
1190          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1191          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1192   "TARGET_ARM && arm_arch3m"
1193   "umull%?\\t%Q0, %R0, %1, %2"
1194   [(set_attr "insn" "umull")
1195    (set_attr "predicable" "yes")]
1198 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1200 (define_insn "*umulsidi3adddi"
1201   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1202         (plus:DI
1203          (mult:DI
1204           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1205           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1206          (match_operand:DI 1 "s_register_operand" "0")))]
1207   "TARGET_ARM && arm_arch3m"
1208   "umlal%?\\t%Q0, %R0, %3, %2"
1209   [(set_attr "insn" "umlal")
1210    (set_attr "predicable" "yes")]
1213 (define_insn "smulsi3_highpart"
1214   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1215         (truncate:SI
1216          (lshiftrt:DI
1217           (mult:DI
1218            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1219            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1220           (const_int 32))))
1221    (clobber (match_scratch:SI 3 "=&r,&r"))]
1222   "TARGET_ARM && arm_arch3m"
1223   "smull%?\\t%3, %0, %2, %1"
1224   [(set_attr "insn" "smull")
1225    (set_attr "predicable" "yes")]
1228 (define_insn "umulsi3_highpart"
1229   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1230         (truncate:SI
1231          (lshiftrt:DI
1232           (mult:DI
1233            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1234            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1235           (const_int 32))))
1236    (clobber (match_scratch:SI 3 "=&r,&r"))]
1237   "TARGET_ARM && arm_arch3m"
1238   "umull%?\\t%3, %0, %2, %1"
1239   [(set_attr "insn" "umull")
1240    (set_attr "predicable" "yes")]
1243 (define_insn "mulhisi3"
1244   [(set (match_operand:SI 0 "s_register_operand" "=r")
1245         (mult:SI (sign_extend:SI
1246                   (match_operand:HI 1 "s_register_operand" "%r"))
1247                  (sign_extend:SI
1248                   (match_operand:HI 2 "s_register_operand" "r"))))]
1249   "TARGET_ARM && arm_arch5e"
1250   "smulbb%?\\t%0, %1, %2"
1251   [(set_attr "insn" "smulxy")
1252    (set_attr "predicable" "yes")]
1255 (define_insn "*mulhisi3tb"
1256   [(set (match_operand:SI 0 "s_register_operand" "=r")
1257         (mult:SI (ashiftrt:SI
1258                   (match_operand:SI 1 "s_register_operand" "r")
1259                   (const_int 16))
1260                  (sign_extend:SI
1261                   (match_operand:HI 2 "s_register_operand" "r"))))]
1262   "TARGET_ARM && arm_arch5e"
1263   "smultb%?\\t%0, %1, %2"
1264   [(set_attr "insn" "smulxy")
1265    (set_attr "predicable" "yes")]
1268 (define_insn "*mulhisi3bt"
1269   [(set (match_operand:SI 0 "s_register_operand" "=r")
1270         (mult:SI (sign_extend:SI
1271                   (match_operand:HI 1 "s_register_operand" "r"))
1272                  (ashiftrt:SI
1273                   (match_operand:SI 2 "s_register_operand" "r")
1274                   (const_int 16))))]
1275   "TARGET_ARM && arm_arch5e"
1276   "smulbt%?\\t%0, %1, %2"
1277   [(set_attr "insn" "smulxy")
1278    (set_attr "predicable" "yes")]
1281 (define_insn "*mulhisi3tt"
1282   [(set (match_operand:SI 0 "s_register_operand" "=r")
1283         (mult:SI (ashiftrt:SI
1284                   (match_operand:SI 1 "s_register_operand" "r")
1285                   (const_int 16))
1286                  (ashiftrt:SI
1287                   (match_operand:SI 2 "s_register_operand" "r")
1288                   (const_int 16))))]
1289   "TARGET_ARM && arm_arch5e"
1290   "smultt%?\\t%0, %1, %2"
1291   [(set_attr "insn" "smulxy")
1292    (set_attr "predicable" "yes")]
1295 (define_insn "*mulhisi3addsi"
1296   [(set (match_operand:SI 0 "s_register_operand" "=r")
1297         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1298                  (mult:SI (sign_extend:SI
1299                            (match_operand:HI 2 "s_register_operand" "%r"))
1300                           (sign_extend:SI
1301                            (match_operand:HI 3 "s_register_operand" "r")))))]
1302   "TARGET_ARM && arm_arch5e"
1303   "smlabb%?\\t%0, %2, %3, %1"
1304   [(set_attr "insn" "smlaxy")
1305    (set_attr "predicable" "yes")]
1308 (define_insn "*mulhidi3adddi"
1309   [(set (match_operand:DI 0 "s_register_operand" "=r")
1310         (plus:DI
1311           (match_operand:DI 1 "s_register_operand" "0")
1312           (mult:DI (sign_extend:DI
1313                     (match_operand:HI 2 "s_register_operand" "%r"))
1314                    (sign_extend:DI
1315                     (match_operand:HI 3 "s_register_operand" "r")))))]
1316   "TARGET_ARM && arm_arch5e"
1317   "smlalbb%?\\t%Q0, %R0, %2, %3"
1318   [(set_attr "insn" "smlalxy")
1319    (set_attr "predicable" "yes")])
1321 (define_expand "mulsf3"
1322   [(set (match_operand:SF          0 "s_register_operand" "")
1323         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1324                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1325   "TARGET_ARM && TARGET_HARD_FLOAT"
1326   "
1327   if (TARGET_MAVERICK
1328       && !cirrus_fp_register (operands[2], SFmode))
1329     operands[2] = force_reg (SFmode, operands[2]);
1332 (define_expand "muldf3"
1333   [(set (match_operand:DF          0 "s_register_operand" "")
1334         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1335                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1336   "TARGET_ARM && TARGET_HARD_FLOAT"
1337   "
1338   if (TARGET_MAVERICK
1339       && !cirrus_fp_register (operands[2], DFmode))
1340     operands[2] = force_reg (DFmode, operands[2]);
1343 ;; Division insns
1345 (define_expand "divsf3"
1346   [(set (match_operand:SF 0 "s_register_operand" "")
1347         (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1348                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1349   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1350   "")
1352 (define_expand "divdf3"
1353   [(set (match_operand:DF 0 "s_register_operand" "")
1354         (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1355                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1356   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1357   "")
1359 ;; Modulo insns
1361 (define_expand "modsf3"
1362   [(set (match_operand:SF 0 "s_register_operand" "")
1363         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1364                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1365   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1366   "")
1368 (define_expand "moddf3"
1369   [(set (match_operand:DF 0 "s_register_operand" "")
1370         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1371                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1372   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1373   "")
1375 ;; Boolean and,ior,xor insns
1377 ;; Split up double word logical operations
1379 ;; Split up simple DImode logical operations.  Simply perform the logical
1380 ;; operation on the upper and lower halves of the registers.
1381 (define_split
1382   [(set (match_operand:DI 0 "s_register_operand" "")
1383         (match_operator:DI 6 "logical_binary_operator"
1384           [(match_operand:DI 1 "s_register_operand" "")
1385            (match_operand:DI 2 "s_register_operand" "")]))]
1386   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1387   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1388    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1389   "
1390   {
1391     operands[3] = gen_highpart (SImode, operands[0]);
1392     operands[0] = gen_lowpart (SImode, operands[0]);
1393     operands[4] = gen_highpart (SImode, operands[1]);
1394     operands[1] = gen_lowpart (SImode, operands[1]);
1395     operands[5] = gen_highpart (SImode, operands[2]);
1396     operands[2] = gen_lowpart (SImode, operands[2]);
1397   }"
1400 (define_split
1401   [(set (match_operand:DI 0 "s_register_operand" "")
1402         (match_operator:DI 6 "logical_binary_operator"
1403           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1404            (match_operand:DI 1 "s_register_operand" "")]))]
1405   "TARGET_ARM && reload_completed"
1406   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1407    (set (match_dup 3) (match_op_dup:SI 6
1408                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1409                          (match_dup 4)]))]
1410   "
1411   {
1412     operands[3] = gen_highpart (SImode, operands[0]);
1413     operands[0] = gen_lowpart (SImode, operands[0]);
1414     operands[4] = gen_highpart (SImode, operands[1]);
1415     operands[1] = gen_lowpart (SImode, operands[1]);
1416     operands[5] = gen_highpart (SImode, operands[2]);
1417     operands[2] = gen_lowpart (SImode, operands[2]);
1418   }"
1421 ;; The zero extend of operand 2 means we can just copy the high part of
1422 ;; operand1 into operand0.
1423 (define_split
1424   [(set (match_operand:DI 0 "s_register_operand" "")
1425         (ior:DI
1426           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1427           (match_operand:DI 1 "s_register_operand" "")))]
1428   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1429   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1430    (set (match_dup 3) (match_dup 4))]
1431   "
1432   {
1433     operands[4] = gen_highpart (SImode, operands[1]);
1434     operands[3] = gen_highpart (SImode, operands[0]);
1435     operands[0] = gen_lowpart (SImode, operands[0]);
1436     operands[1] = gen_lowpart (SImode, operands[1]);
1437   }"
1440 ;; The zero extend of operand 2 means we can just copy the high part of
1441 ;; operand1 into operand0.
1442 (define_split
1443   [(set (match_operand:DI 0 "s_register_operand" "")
1444         (xor:DI
1445           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1446           (match_operand:DI 1 "s_register_operand" "")))]
1447   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1448   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1449    (set (match_dup 3) (match_dup 4))]
1450   "
1451   {
1452     operands[4] = gen_highpart (SImode, operands[1]);
1453     operands[3] = gen_highpart (SImode, operands[0]);
1454     operands[0] = gen_lowpart (SImode, operands[0]);
1455     operands[1] = gen_lowpart (SImode, operands[1]);
1456   }"
1459 (define_insn "anddi3"
1460   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1461         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1462                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1463   "TARGET_ARM && ! TARGET_IWMMXT"
1464   "#"
1465   [(set_attr "length" "8")]
1468 (define_insn_and_split "*anddi_zesidi_di"
1469   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1470         (and:DI (zero_extend:DI
1471                  (match_operand:SI 2 "s_register_operand" "r,r"))
1472                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1473   "TARGET_ARM"
1474   "#"
1475   "TARGET_ARM && reload_completed"
1476   ; The zero extend of operand 2 clears the high word of the output
1477   ; operand.
1478   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1479    (set (match_dup 3) (const_int 0))]
1480   "
1481   {
1482     operands[3] = gen_highpart (SImode, operands[0]);
1483     operands[0] = gen_lowpart (SImode, operands[0]);
1484     operands[1] = gen_lowpart (SImode, operands[1]);
1485   }"
1486   [(set_attr "length" "8")]
1489 (define_insn "*anddi_sesdi_di"
1490   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1491         (and:DI (sign_extend:DI
1492                  (match_operand:SI 2 "s_register_operand" "r,r"))
1493                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1494   "TARGET_ARM"
1495   "#"
1496   [(set_attr "length" "8")]
1499 (define_expand "andsi3"
1500   [(set (match_operand:SI         0 "s_register_operand" "")
1501         (and:SI (match_operand:SI 1 "s_register_operand" "")
1502                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1503   "TARGET_EITHER"
1504   "
1505   if (TARGET_ARM)
1506     {
1507       if (GET_CODE (operands[2]) == CONST_INT)
1508         {
1509           arm_split_constant (AND, SImode, NULL_RTX,
1510                               INTVAL (operands[2]), operands[0],
1511                               operands[1], optimize && !no_new_pseudos);
1513           DONE;
1514         }
1515     }
1516   else /* TARGET_THUMB */
1517     {
1518       if (GET_CODE (operands[2]) != CONST_INT)
1519         operands[2] = force_reg (SImode, operands[2]);
1520       else
1521         {
1522           int i;
1523           
1524           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1525             {
1526               operands[2] = force_reg (SImode,
1527                                        GEN_INT (~INTVAL (operands[2])));
1528               
1529               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1530               
1531               DONE;
1532             }
1534           for (i = 9; i <= 31; i++)
1535             {
1536               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1537                 {
1538                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1539                                         const0_rtx));
1540                   DONE;
1541                 }
1542               else if ((((HOST_WIDE_INT) 1) << i) - 1
1543                        == ~INTVAL (operands[2]))
1544                 {
1545                   rtx shift = GEN_INT (i);
1546                   rtx reg = gen_reg_rtx (SImode);
1547                 
1548                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1549                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1550                   
1551                   DONE;
1552                 }
1553             }
1555           operands[2] = force_reg (SImode, operands[2]);
1556         }
1557     }
1558   "
1561 (define_insn_and_split "*arm_andsi3_insn"
1562   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1563         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1564                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1565   "TARGET_ARM"
1566   "@
1567    and%?\\t%0, %1, %2
1568    bic%?\\t%0, %1, #%B2
1569    #"
1570   "TARGET_ARM
1571    && GET_CODE (operands[2]) == CONST_INT
1572    && !(const_ok_for_arm (INTVAL (operands[2]))
1573         || const_ok_for_arm (~INTVAL (operands[2])))"
1574   [(clobber (const_int 0))]
1575   "
1576   arm_split_constant  (AND, SImode, curr_insn, 
1577                        INTVAL (operands[2]), operands[0], operands[1], 0);
1578   DONE;
1579   "
1580   [(set_attr "length" "4,4,16")
1581    (set_attr "predicable" "yes")]
1584 (define_insn "*thumb_andsi3_insn"
1585   [(set (match_operand:SI         0 "register_operand" "=l")
1586         (and:SI (match_operand:SI 1 "register_operand" "%0")
1587                 (match_operand:SI 2 "register_operand" "l")))]
1588   "TARGET_THUMB"
1589   "and\\t%0, %0, %2"
1590   [(set_attr "length" "2")]
1593 (define_insn "*andsi3_compare0"
1594   [(set (reg:CC_NOOV CC_REGNUM)
1595         (compare:CC_NOOV
1596          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1597                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1598          (const_int 0)))
1599    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1600         (and:SI (match_dup 1) (match_dup 2)))]
1601   "TARGET_ARM"
1602   "@
1603    and%?s\\t%0, %1, %2
1604    bic%?s\\t%0, %1, #%B2"
1605   [(set_attr "conds" "set")]
1608 (define_insn "*andsi3_compare0_scratch"
1609   [(set (reg:CC_NOOV CC_REGNUM)
1610         (compare:CC_NOOV
1611          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1612                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1613          (const_int 0)))
1614    (clobber (match_scratch:SI 2 "=X,r"))]
1615   "TARGET_ARM"
1616   "@
1617    tst%?\\t%0, %1
1618    bic%?s\\t%2, %0, #%B1"
1619   [(set_attr "conds" "set")]
1622 (define_insn "*zeroextractsi_compare0_scratch"
1623   [(set (reg:CC_NOOV CC_REGNUM)
1624         (compare:CC_NOOV (zero_extract:SI
1625                           (match_operand:SI 0 "s_register_operand" "r")
1626                           (match_operand 1 "const_int_operand" "n")
1627                           (match_operand 2 "const_int_operand" "n"))
1628                          (const_int 0)))]
1629   "TARGET_ARM
1630   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1631       && INTVAL (operands[1]) > 0 
1632       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1633       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1634   "*
1635   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1636                          << INTVAL (operands[2]));
1637   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1638   return \"\";
1639   "
1640   [(set_attr "conds" "set")]
1643 (define_insn_and_split "*ne_zeroextractsi"
1644   [(set (match_operand:SI 0 "s_register_operand" "=r")
1645         (ne:SI (zero_extract:SI
1646                 (match_operand:SI 1 "s_register_operand" "r")
1647                 (match_operand:SI 2 "const_int_operand" "n")
1648                 (match_operand:SI 3 "const_int_operand" "n"))
1649                (const_int 0)))
1650    (clobber (reg:CC CC_REGNUM))]
1651   "TARGET_ARM
1652    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1653        && INTVAL (operands[2]) > 0 
1654        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1655        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1656   "#"
1657   "TARGET_ARM
1658    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1659        && INTVAL (operands[2]) > 0 
1660        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1661        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1662   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1663                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1664                                     (const_int 0)))
1665               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1666    (set (match_dup 0)
1667         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1668                          (match_dup 0) (const_int 1)))]
1669   "
1670   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1671                          << INTVAL (operands[3])); 
1672   "
1673   [(set_attr "conds" "clob")
1674    (set_attr "length" "8")]
1677 (define_insn_and_split "*ne_zeroextractsi_shifted"
1678   [(set (match_operand:SI 0 "s_register_operand" "=r")
1679         (ne:SI (zero_extract:SI
1680                 (match_operand:SI 1 "s_register_operand" "r")
1681                 (match_operand:SI 2 "const_int_operand" "n")
1682                 (const_int 0))
1683                (const_int 0)))
1684    (clobber (reg:CC CC_REGNUM))]
1685   "TARGET_ARM"
1686   "#"
1687   "TARGET_ARM"
1688   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1689                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1690                                     (const_int 0)))
1691               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1692    (set (match_dup 0)
1693         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1694                          (match_dup 0) (const_int 1)))]
1695   "
1696   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1697   "
1698   [(set_attr "conds" "clob")
1699    (set_attr "length" "8")]
1702 (define_insn_and_split "*ite_ne_zeroextractsi"
1703   [(set (match_operand:SI 0 "s_register_operand" "=r")
1704         (if_then_else:SI (ne (zero_extract:SI
1705                               (match_operand:SI 1 "s_register_operand" "r")
1706                               (match_operand:SI 2 "const_int_operand" "n")
1707                               (match_operand:SI 3 "const_int_operand" "n"))
1708                              (const_int 0))
1709                          (match_operand:SI 4 "arm_not_operand" "rIK")
1710                          (const_int 0)))
1711    (clobber (reg:CC CC_REGNUM))]
1712   "TARGET_ARM
1713    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1714        && INTVAL (operands[2]) > 0 
1715        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1716        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1717    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1718   "#"
1719   "TARGET_ARM
1720    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1721        && INTVAL (operands[2]) > 0 
1722        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1723        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1724    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1725   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1726                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1727                                     (const_int 0)))
1728               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1729    (set (match_dup 0)
1730         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1731                          (match_dup 0) (match_dup 4)))]
1732   "
1733   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1734                          << INTVAL (operands[3])); 
1735   "
1736   [(set_attr "conds" "clob")
1737    (set_attr "length" "8")]
1740 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1741   [(set (match_operand:SI 0 "s_register_operand" "=r")
1742         (if_then_else:SI (ne (zero_extract:SI
1743                               (match_operand:SI 1 "s_register_operand" "r")
1744                               (match_operand:SI 2 "const_int_operand" "n")
1745                               (const_int 0))
1746                              (const_int 0))
1747                          (match_operand:SI 3 "arm_not_operand" "rIK")
1748                          (const_int 0)))
1749    (clobber (reg:CC CC_REGNUM))]
1750   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1751   "#"
1752   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1753   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1754                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1755                                     (const_int 0)))
1756               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1757    (set (match_dup 0)
1758         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1759                          (match_dup 0) (match_dup 3)))]
1760   "
1761   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1762   "
1763   [(set_attr "conds" "clob")
1764    (set_attr "length" "8")]
1767 (define_split
1768   [(set (match_operand:SI 0 "s_register_operand" "")
1769         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1770                          (match_operand:SI 2 "const_int_operand" "")
1771                          (match_operand:SI 3 "const_int_operand" "")))
1772    (clobber (match_operand:SI 4 "s_register_operand" ""))]
1773   "TARGET_THUMB"
1774   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1775    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1776   "{
1777      HOST_WIDE_INT temp = INTVAL (operands[2]);
1779      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1780      operands[3] = GEN_INT (32 - temp);
1781    }"
1784 (define_split
1785   [(set (match_operand:SI 0 "s_register_operand" "")
1786         (match_operator:SI 1 "shiftable_operator"
1787          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1788                            (match_operand:SI 3 "const_int_operand" "")
1789                            (match_operand:SI 4 "const_int_operand" ""))
1790           (match_operand:SI 5 "s_register_operand" "")]))
1791    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1792   "TARGET_ARM"
1793   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1794    (set (match_dup 0)
1795         (match_op_dup 1
1796          [(lshiftrt:SI (match_dup 6) (match_dup 4))
1797           (match_dup 5)]))]
1798   "{
1799      HOST_WIDE_INT temp = INTVAL (operands[3]);
1801      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1802      operands[4] = GEN_INT (32 - temp);
1803    }"
1805   
1806 (define_split
1807   [(set (match_operand:SI 0 "s_register_operand" "")
1808         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1809                          (match_operand:SI 2 "const_int_operand" "")
1810                          (match_operand:SI 3 "const_int_operand" "")))]
1811   "TARGET_THUMB"
1812   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1813    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1814   "{
1815      HOST_WIDE_INT temp = INTVAL (operands[2]);
1817      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1818      operands[3] = GEN_INT (32 - temp);
1819    }"
1822 (define_split
1823   [(set (match_operand:SI 0 "s_register_operand" "")
1824         (match_operator:SI 1 "shiftable_operator"
1825          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1826                            (match_operand:SI 3 "const_int_operand" "")
1827                            (match_operand:SI 4 "const_int_operand" ""))
1828           (match_operand:SI 5 "s_register_operand" "")]))
1829    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1830   "TARGET_ARM"
1831   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1832    (set (match_dup 0)
1833         (match_op_dup 1
1834          [(ashiftrt:SI (match_dup 6) (match_dup 4))
1835           (match_dup 5)]))]
1836   "{
1837      HOST_WIDE_INT temp = INTVAL (operands[3]);
1839      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1840      operands[4] = GEN_INT (32 - temp);
1841    }"
1843   
1844 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1845 ;;; represented by the bitfield, then this will produce incorrect results.
1846 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1847 ;;; which have a real bit-field insert instruction, the truncation happens
1848 ;;; in the bit-field insert instruction itself.  Since arm does not have a
1849 ;;; bit-field insert instruction, we would have to emit code here to truncate
1850 ;;; the value before we insert.  This loses some of the advantage of having
1851 ;;; this insv pattern, so this pattern needs to be reevalutated.
1853 (define_expand "insv"
1854   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1855                          (match_operand:SI 1 "general_operand" "")
1856                          (match_operand:SI 2 "general_operand" ""))
1857         (match_operand:SI 3 "reg_or_int_operand" ""))]
1858   "TARGET_ARM"
1859   "
1860   {
1861     int start_bit = INTVAL (operands[2]);
1862     int width = INTVAL (operands[1]);
1863     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1864     rtx target, subtarget;
1866     target = operands[0];
1867     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1868        subreg as the final target.  */
1869     if (GET_CODE (target) == SUBREG)
1870       {
1871         subtarget = gen_reg_rtx (SImode);
1872         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1873             < GET_MODE_SIZE (SImode))
1874           target = SUBREG_REG (target);
1875       }
1876     else
1877       subtarget = target;    
1879     if (GET_CODE (operands[3]) == CONST_INT)
1880       {
1881         /* Since we are inserting a known constant, we may be able to
1882            reduce the number of bits that we have to clear so that
1883            the mask becomes simple.  */
1884         /* ??? This code does not check to see if the new mask is actually
1885            simpler.  It may not be.  */
1886         rtx op1 = gen_reg_rtx (SImode);
1887         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1888            start of this pattern.  */
1889         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1890         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1892         emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1893         emit_insn (gen_iorsi3 (subtarget, op1,
1894                                gen_int_mode (op3_value << start_bit, SImode)));
1895       }
1896     else if (start_bit == 0
1897              && !(const_ok_for_arm (mask)
1898                   || const_ok_for_arm (~mask)))
1899       {
1900         /* A Trick, since we are setting the bottom bits in the word,
1901            we can shift operand[3] up, operand[0] down, OR them together
1902            and rotate the result back again.  This takes 3 insns, and
1903            the third might be mergeable into another op.  */
1904         /* The shift up copes with the possibility that operand[3] is
1905            wider than the bitfield.  */
1906         rtx op0 = gen_reg_rtx (SImode);
1907         rtx op1 = gen_reg_rtx (SImode);
1909         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1910         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1911         emit_insn (gen_iorsi3  (op1, op1, op0));
1912         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1913       }
1914     else if ((width + start_bit == 32)
1915              && !(const_ok_for_arm (mask)
1916                   || const_ok_for_arm (~mask)))
1917       {
1918         /* Similar trick, but slightly less efficient.  */
1920         rtx op0 = gen_reg_rtx (SImode);
1921         rtx op1 = gen_reg_rtx (SImode);
1923         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1924         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1925         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1926         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1927       }
1928     else
1929       {
1930         rtx op0 = GEN_INT (mask);
1931         rtx op1 = gen_reg_rtx (SImode);
1932         rtx op2 = gen_reg_rtx (SImode);
1934         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1935           {
1936             rtx tmp = gen_reg_rtx (SImode);
1938             emit_insn (gen_movsi (tmp, op0));
1939             op0 = tmp;
1940           }
1942         /* Mask out any bits in operand[3] that are not needed.  */
1943            emit_insn (gen_andsi3 (op1, operands[3], op0));
1945         if (GET_CODE (op0) == CONST_INT
1946             && (const_ok_for_arm (mask << start_bit)
1947                 || const_ok_for_arm (~(mask << start_bit))))
1948           {
1949             op0 = GEN_INT (~(mask << start_bit));
1950             emit_insn (gen_andsi3 (op2, operands[0], op0));
1951           }
1952         else
1953           {
1954             if (GET_CODE (op0) == CONST_INT)
1955               {
1956                 rtx tmp = gen_reg_rtx (SImode);
1958                 emit_insn (gen_movsi (tmp, op0));
1959                 op0 = tmp;
1960               }
1962             if (start_bit != 0)
1963               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1964             
1965             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1966           }
1968         if (start_bit != 0)
1969           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1971         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1972       }
1974     if (subtarget != target)
1975       {
1976         /* If TARGET is still a SUBREG, then it must be wider than a word,
1977            so we must be careful only to set the subword we were asked to.  */
1978         if (GET_CODE (target) == SUBREG)
1979           emit_move_insn (target, subtarget);
1980         else
1981           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1982       }
1984     DONE;
1985   }"
1988 ; constants for op 2 will never be given to these patterns.
1989 (define_insn_and_split "*anddi_notdi_di"
1990   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1991         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1992                 (match_operand:DI 2 "s_register_operand" "0,r")))]
1993   "TARGET_ARM"
1994   "#"
1995   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1996   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1997    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
1998   "
1999   {
2000     operands[3] = gen_highpart (SImode, operands[0]);
2001     operands[0] = gen_lowpart (SImode, operands[0]);
2002     operands[4] = gen_highpart (SImode, operands[1]);
2003     operands[1] = gen_lowpart (SImode, operands[1]);
2004     operands[5] = gen_highpart (SImode, operands[2]);
2005     operands[2] = gen_lowpart (SImode, operands[2]);
2006   }"
2007   [(set_attr "length" "8")
2008    (set_attr "predicable" "yes")]
2010   
2011 (define_insn_and_split "*anddi_notzesidi_di"
2012   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2013         (and:DI (not:DI (zero_extend:DI
2014                          (match_operand:SI 2 "s_register_operand" "r,r")))
2015                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2016   "TARGET_ARM"
2017   "@
2018    bic%?\\t%Q0, %Q1, %2
2019    #"
2020   ; (not (zero_extend ...)) allows us to just copy the high word from
2021   ; operand1 to operand0.
2022   "TARGET_ARM
2023    && reload_completed
2024    && operands[0] != operands[1]"
2025   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2026    (set (match_dup 3) (match_dup 4))]
2027   "
2028   {
2029     operands[3] = gen_highpart (SImode, operands[0]);
2030     operands[0] = gen_lowpart (SImode, operands[0]);
2031     operands[4] = gen_highpart (SImode, operands[1]);
2032     operands[1] = gen_lowpart (SImode, operands[1]);
2033   }"
2034   [(set_attr "length" "4,8")
2035    (set_attr "predicable" "yes")]
2037   
2038 (define_insn_and_split "*anddi_notsesidi_di"
2039   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2040         (and:DI (not:DI (sign_extend:DI
2041                          (match_operand:SI 2 "s_register_operand" "r,r")))
2042                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2043   "TARGET_ARM"
2044   "#"
2045   "TARGET_ARM && reload_completed"
2046   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2047    (set (match_dup 3) (and:SI (not:SI
2048                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2049                                (match_dup 4)))]
2050   "
2051   {
2052     operands[3] = gen_highpart (SImode, operands[0]);
2053     operands[0] = gen_lowpart (SImode, operands[0]);
2054     operands[4] = gen_highpart (SImode, operands[1]);
2055     operands[1] = gen_lowpart (SImode, operands[1]);
2056   }"
2057   [(set_attr "length" "8")
2058    (set_attr "predicable" "yes")]
2060   
2061 (define_insn "andsi_notsi_si"
2062   [(set (match_operand:SI 0 "s_register_operand" "=r")
2063         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2064                 (match_operand:SI 1 "s_register_operand" "r")))]
2065   "TARGET_ARM"
2066   "bic%?\\t%0, %1, %2"
2067   [(set_attr "predicable" "yes")]
2070 (define_insn "bicsi3"
2071   [(set (match_operand:SI                 0 "register_operand" "=l")
2072         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2073                 (match_operand:SI         2 "register_operand" "0")))]
2074   "TARGET_THUMB"
2075   "bic\\t%0, %0, %1"
2076   [(set_attr "length" "2")]
2079 (define_insn "andsi_not_shiftsi_si"
2080   [(set (match_operand:SI 0 "s_register_operand" "=r")
2081         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2082                          [(match_operand:SI 2 "s_register_operand" "r")
2083                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2084                 (match_operand:SI 1 "s_register_operand" "r")))]
2085   "TARGET_ARM"
2086   "bic%?\\t%0, %1, %2%S4"
2087   [(set_attr "predicable" "yes")
2088    (set_attr "shift" "2")
2089    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2090                       (const_string "alu_shift")
2091                       (const_string "alu_shift_reg")))]
2094 (define_insn "*andsi_notsi_si_compare0"
2095   [(set (reg:CC_NOOV CC_REGNUM)
2096         (compare:CC_NOOV
2097          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2098                  (match_operand:SI 1 "s_register_operand" "r"))
2099          (const_int 0)))
2100    (set (match_operand:SI 0 "s_register_operand" "=r")
2101         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2102   "TARGET_ARM"
2103   "bic%?s\\t%0, %1, %2"
2104   [(set_attr "conds" "set")]
2107 (define_insn "*andsi_notsi_si_compare0_scratch"
2108   [(set (reg:CC_NOOV CC_REGNUM)
2109         (compare:CC_NOOV
2110          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2111                  (match_operand:SI 1 "s_register_operand" "r"))
2112          (const_int 0)))
2113    (clobber (match_scratch:SI 0 "=r"))]
2114   "TARGET_ARM"
2115   "bic%?s\\t%0, %1, %2"
2116   [(set_attr "conds" "set")]
2119 (define_insn "iordi3"
2120   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2121         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2122                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2123   "TARGET_ARM && ! TARGET_IWMMXT"
2124   "#"
2125   [(set_attr "length" "8")
2126    (set_attr "predicable" "yes")]
2129 (define_insn "*iordi_zesidi_di"
2130   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2131         (ior:DI (zero_extend:DI
2132                  (match_operand:SI 2 "s_register_operand" "r,r"))
2133                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2134   "TARGET_ARM"
2135   "@
2136    orr%?\\t%Q0, %Q1, %2
2137    #"
2138   [(set_attr "length" "4,8")
2139    (set_attr "predicable" "yes")]
2142 (define_insn "*iordi_sesidi_di"
2143   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2144         (ior:DI (sign_extend:DI
2145                  (match_operand:SI 2 "s_register_operand" "r,r"))
2146                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2147   "TARGET_ARM"
2148   "#"
2149   [(set_attr "length" "8")
2150    (set_attr "predicable" "yes")]
2153 (define_expand "iorsi3"
2154   [(set (match_operand:SI         0 "s_register_operand" "")
2155         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2156                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2157   "TARGET_EITHER"
2158   "
2159   if (GET_CODE (operands[2]) == CONST_INT)
2160     {
2161       if (TARGET_ARM)
2162         {
2163           arm_split_constant (IOR, SImode, NULL_RTX,
2164                               INTVAL (operands[2]), operands[0], operands[1],
2165                               optimize && !no_new_pseudos);
2166           DONE;
2167         }
2168       else /* TARGET_THUMB */
2169         operands [2] = force_reg (SImode, operands [2]);
2170     }
2171   "
2174 (define_insn_and_split "*arm_iorsi3"
2175   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2176         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2177                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2178   "TARGET_ARM"
2179   "@
2180    orr%?\\t%0, %1, %2
2181    #"
2182   "TARGET_ARM
2183    && GET_CODE (operands[2]) == CONST_INT
2184    && !const_ok_for_arm (INTVAL (operands[2]))"
2185   [(clobber (const_int 0))]
2186   "
2187   arm_split_constant (IOR, SImode, curr_insn, 
2188                       INTVAL (operands[2]), operands[0], operands[1], 0);
2189   DONE;
2190   "
2191   [(set_attr "length" "4,16")
2192    (set_attr "predicable" "yes")]
2195 (define_insn "*thumb_iorsi3"
2196   [(set (match_operand:SI         0 "register_operand" "=l")
2197         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2198                 (match_operand:SI 2 "register_operand" "l")))]
2199   "TARGET_THUMB"
2200   "orr\\t%0, %0, %2"
2201   [(set_attr "length" "2")]
2204 (define_peephole2
2205   [(match_scratch:SI 3 "r")
2206    (set (match_operand:SI 0 "arm_general_register_operand" "")
2207         (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2208                 (match_operand:SI 2 "const_int_operand" "")))]
2209   "TARGET_ARM
2210    && !const_ok_for_arm (INTVAL (operands[2]))
2211    && const_ok_for_arm (~INTVAL (operands[2]))"
2212   [(set (match_dup 3) (match_dup 2))
2213    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2214   ""
2217 (define_insn "*iorsi3_compare0"
2218   [(set (reg:CC_NOOV CC_REGNUM)
2219         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2220                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2221                          (const_int 0)))
2222    (set (match_operand:SI 0 "s_register_operand" "=r")
2223         (ior:SI (match_dup 1) (match_dup 2)))]
2224   "TARGET_ARM"
2225   "orr%?s\\t%0, %1, %2"
2226   [(set_attr "conds" "set")]
2229 (define_insn "*iorsi3_compare0_scratch"
2230   [(set (reg:CC_NOOV CC_REGNUM)
2231         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2232                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2233                          (const_int 0)))
2234    (clobber (match_scratch:SI 0 "=r"))]
2235   "TARGET_ARM"
2236   "orr%?s\\t%0, %1, %2"
2237   [(set_attr "conds" "set")]
2240 (define_insn "xordi3"
2241   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2242         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2243                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2244   "TARGET_ARM && !TARGET_IWMMXT"
2245   "#"
2246   [(set_attr "length" "8")
2247    (set_attr "predicable" "yes")]
2250 (define_insn "*xordi_zesidi_di"
2251   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2252         (xor:DI (zero_extend:DI
2253                  (match_operand:SI 2 "s_register_operand" "r,r"))
2254                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2255   "TARGET_ARM"
2256   "@
2257    eor%?\\t%Q0, %Q1, %2
2258    #"
2259   [(set_attr "length" "4,8")
2260    (set_attr "predicable" "yes")]
2263 (define_insn "*xordi_sesidi_di"
2264   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2265         (xor:DI (sign_extend:DI
2266                  (match_operand:SI 2 "s_register_operand" "r,r"))
2267                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2268   "TARGET_ARM"
2269   "#"
2270   [(set_attr "length" "8")
2271    (set_attr "predicable" "yes")]
2274 (define_expand "xorsi3"
2275   [(set (match_operand:SI         0 "s_register_operand" "")
2276         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2277                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2278   "TARGET_EITHER"
2279   "if (TARGET_THUMB)
2280      if (GET_CODE (operands[2]) == CONST_INT)
2281        operands[2] = force_reg (SImode, operands[2]);
2282   "
2285 (define_insn "*arm_xorsi3"
2286   [(set (match_operand:SI         0 "s_register_operand" "=r")
2287         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2288                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2289   "TARGET_ARM"
2290   "eor%?\\t%0, %1, %2"
2291   [(set_attr "predicable" "yes")]
2294 (define_insn "*thumb_xorsi3"
2295   [(set (match_operand:SI         0 "register_operand" "=l")
2296         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2297                 (match_operand:SI 2 "register_operand" "l")))]
2298   "TARGET_THUMB"
2299   "eor\\t%0, %0, %2"
2300   [(set_attr "length" "2")]
2303 (define_insn "*xorsi3_compare0"
2304   [(set (reg:CC_NOOV CC_REGNUM)
2305         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2306                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2307                          (const_int 0)))
2308    (set (match_operand:SI 0 "s_register_operand" "=r")
2309         (xor:SI (match_dup 1) (match_dup 2)))]
2310   "TARGET_ARM"
2311   "eor%?s\\t%0, %1, %2"
2312   [(set_attr "conds" "set")]
2315 (define_insn "*xorsi3_compare0_scratch"
2316   [(set (reg:CC_NOOV CC_REGNUM)
2317         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2318                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2319                          (const_int 0)))]
2320   "TARGET_ARM"
2321   "teq%?\\t%0, %1"
2322   [(set_attr "conds" "set")]
2325 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2326 ; (NOT D) we can sometimes merge the final NOT into one of the following
2327 ; insns.
2329 (define_split
2330   [(set (match_operand:SI 0 "s_register_operand" "")
2331         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2332                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2333                 (match_operand:SI 3 "arm_rhs_operand" "")))
2334    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2335   "TARGET_ARM"
2336   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2337                               (not:SI (match_dup 3))))
2338    (set (match_dup 0) (not:SI (match_dup 4)))]
2339   ""
2342 (define_insn "*andsi_iorsi3_notsi"
2343   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2344         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2345                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2346                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2347   "TARGET_ARM"
2348   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2349   [(set_attr "length" "8")
2350    (set_attr "predicable" "yes")]
2353 (define_split
2354   [(set (match_operand:SI 0 "s_register_operand" "")
2355         (match_operator:SI 1 "logical_binary_operator"
2356          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2357                            (match_operand:SI 3 "const_int_operand" "")
2358                            (match_operand:SI 4 "const_int_operand" ""))
2359           (match_operator:SI 9 "logical_binary_operator"
2360            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2361                          (match_operand:SI 6 "const_int_operand" ""))
2362             (match_operand:SI 7 "s_register_operand" "")])]))
2363    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2364   "TARGET_ARM
2365    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2366    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2367   [(set (match_dup 8)
2368         (match_op_dup 1
2369          [(ashift:SI (match_dup 2) (match_dup 4))
2370           (match_dup 5)]))
2371    (set (match_dup 0)
2372         (match_op_dup 1
2373          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2374           (match_dup 7)]))]
2375   "
2376   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2379 (define_split
2380   [(set (match_operand:SI 0 "s_register_operand" "")
2381         (match_operator:SI 1 "logical_binary_operator"
2382          [(match_operator:SI 9 "logical_binary_operator"
2383            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2384                          (match_operand:SI 6 "const_int_operand" ""))
2385             (match_operand:SI 7 "s_register_operand" "")])
2386           (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2387                            (match_operand:SI 3 "const_int_operand" "")
2388                            (match_operand:SI 4 "const_int_operand" ""))]))
2389    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2390   "TARGET_ARM
2391    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2392    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2393   [(set (match_dup 8)
2394         (match_op_dup 1
2395          [(ashift:SI (match_dup 2) (match_dup 4))
2396           (match_dup 5)]))
2397    (set (match_dup 0)
2398         (match_op_dup 1
2399          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2400           (match_dup 7)]))]
2401   "
2402   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2405 (define_split
2406   [(set (match_operand:SI 0 "s_register_operand" "")
2407         (match_operator:SI 1 "logical_binary_operator"
2408          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2409                            (match_operand:SI 3 "const_int_operand" "")
2410                            (match_operand:SI 4 "const_int_operand" ""))
2411           (match_operator:SI 9 "logical_binary_operator"
2412            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2413                          (match_operand:SI 6 "const_int_operand" ""))
2414             (match_operand:SI 7 "s_register_operand" "")])]))
2415    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2416   "TARGET_ARM
2417    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2418    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2419   [(set (match_dup 8)
2420         (match_op_dup 1
2421          [(ashift:SI (match_dup 2) (match_dup 4))
2422           (match_dup 5)]))
2423    (set (match_dup 0)
2424         (match_op_dup 1
2425          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2426           (match_dup 7)]))]
2427   "
2428   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2431 (define_split
2432   [(set (match_operand:SI 0 "s_register_operand" "")
2433         (match_operator:SI 1 "logical_binary_operator"
2434          [(match_operator:SI 9 "logical_binary_operator"
2435            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2436                          (match_operand:SI 6 "const_int_operand" ""))
2437             (match_operand:SI 7 "s_register_operand" "")])
2438           (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2439                            (match_operand:SI 3 "const_int_operand" "")
2440                            (match_operand:SI 4 "const_int_operand" ""))]))
2441    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2442   "TARGET_ARM
2443    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2444    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2445   [(set (match_dup 8)
2446         (match_op_dup 1
2447          [(ashift:SI (match_dup 2) (match_dup 4))
2448           (match_dup 5)]))
2449    (set (match_dup 0)
2450         (match_op_dup 1
2451          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2452           (match_dup 7)]))]
2453   "
2454   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2458 ;; Minimum and maximum insns
2460 (define_insn "smaxsi3"
2461   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2462         (smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2463                  (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2464    (clobber (reg:CC CC_REGNUM))]
2465   "TARGET_ARM"
2466   "@
2467    cmp\\t%1, %2\;movlt\\t%0, %2
2468    cmp\\t%1, %2\;movge\\t%0, %1
2469    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2470   [(set_attr "conds" "clob")
2471    (set_attr "length" "8,8,12")]
2474 (define_insn "sminsi3"
2475   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2476         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2477                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2478    (clobber (reg:CC CC_REGNUM))]
2479   "TARGET_ARM"
2480   "@
2481    cmp\\t%1, %2\;movge\\t%0, %2
2482    cmp\\t%1, %2\;movlt\\t%0, %1
2483    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2484   [(set_attr "conds" "clob")
2485    (set_attr "length" "8,8,12")]
2488 (define_insn "umaxsi3"
2489   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2490         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2491                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2492    (clobber (reg:CC CC_REGNUM))]
2493   "TARGET_ARM"
2494   "@
2495    cmp\\t%1, %2\;movcc\\t%0, %2
2496    cmp\\t%1, %2\;movcs\\t%0, %1
2497    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2498   [(set_attr "conds" "clob")
2499    (set_attr "length" "8,8,12")]
2502 (define_insn "uminsi3"
2503   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2504         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2505                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2506    (clobber (reg:CC CC_REGNUM))]
2507   "TARGET_ARM"
2508   "@
2509    cmp\\t%1, %2\;movcs\\t%0, %2
2510    cmp\\t%1, %2\;movcc\\t%0, %1
2511    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2512   [(set_attr "conds" "clob")
2513    (set_attr "length" "8,8,12")]
2516 (define_insn "*store_minmaxsi"
2517   [(set (match_operand:SI 0 "memory_operand" "=m")
2518         (match_operator:SI 3 "minmax_operator"
2519          [(match_operand:SI 1 "s_register_operand" "r")
2520           (match_operand:SI 2 "s_register_operand" "r")]))
2521    (clobber (reg:CC CC_REGNUM))]
2522   "TARGET_ARM"
2523   "*
2524   operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2525                                 operands[1], operands[2]);
2526   output_asm_insn (\"cmp\\t%1, %2\", operands);
2527   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2528   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2529   return \"\";
2530   "
2531   [(set_attr "conds" "clob")
2532    (set_attr "length" "12")
2533    (set_attr "type" "store1")]
2536 ; Reject the frame pointer in operand[1], since reloading this after
2537 ; it has been eliminated can cause carnage.
2538 (define_insn "*minmax_arithsi"
2539   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2540         (match_operator:SI 4 "shiftable_operator"
2541          [(match_operator:SI 5 "minmax_operator"
2542            [(match_operand:SI 2 "s_register_operand" "r,r")
2543             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2544           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2545    (clobber (reg:CC CC_REGNUM))]
2546   "TARGET_ARM && !arm_eliminable_register (operands[1])"
2547   "*
2548   {
2549     enum rtx_code code = GET_CODE (operands[4]);
2551     operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2552                                   operands[2], operands[3]);
2553     output_asm_insn (\"cmp\\t%2, %3\", operands);
2554     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2555     if (which_alternative != 0 || operands[3] != const0_rtx
2556         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2557       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2558     return \"\";
2559   }"
2560   [(set_attr "conds" "clob")
2561    (set_attr "length" "12")]
2565 ;; Shift and rotation insns
2567 (define_expand "ashldi3"
2568   [(set (match_operand:DI            0 "s_register_operand" "")
2569         (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2570                    (match_operand:SI 2 "reg_or_int_operand" "")))]
2571   "TARGET_ARM"
2572   "
2573   if (GET_CODE (operands[2]) == CONST_INT)
2574     {
2575       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2576         {
2577           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2578           DONE;
2579         }
2580         /* Ideally we shouldn't fail here if we could know that operands[1] 
2581            ends up already living in an iwmmxt register. Otherwise it's
2582            cheaper to have the alternate code being generated than moving
2583            values to iwmmxt regs and back.  */
2584         FAIL;
2585     }
2586   else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2587     FAIL;
2588   "
2591 (define_insn "arm_ashldi3_1bit"
2592   [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
2593         (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2594                    (const_int 1)))
2595    (clobber (reg:CC CC_REGNUM))]
2596   "TARGET_ARM"
2597   "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2598   [(set_attr "conds" "clob")
2599    (set_attr "length" "8")]
2602 (define_expand "ashlsi3"
2603   [(set (match_operand:SI            0 "s_register_operand" "")
2604         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2605                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2606   "TARGET_EITHER"
2607   "
2608   if (GET_CODE (operands[2]) == CONST_INT
2609       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2610     {
2611       emit_insn (gen_movsi (operands[0], const0_rtx));
2612       DONE;
2613     }
2614   "
2617 (define_insn "*thumb_ashlsi3"
2618   [(set (match_operand:SI            0 "register_operand" "=l,l")
2619         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2620                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2621   "TARGET_THUMB"
2622   "lsl\\t%0, %1, %2"
2623   [(set_attr "length" "2")]
2626 (define_expand "ashrdi3"
2627   [(set (match_operand:DI              0 "s_register_operand" "")
2628         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2629                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2630   "TARGET_ARM"
2631   "
2632   if (GET_CODE (operands[2]) == CONST_INT)
2633     {
2634       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2635         {
2636           emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2637           DONE;
2638         }
2639         /* Ideally we shouldn't fail here if we could know that operands[1] 
2640            ends up already living in an iwmmxt register. Otherwise it's
2641            cheaper to have the alternate code being generated than moving
2642            values to iwmmxt regs and back.  */
2643         FAIL;
2644     }
2645   else if (!TARGET_REALLY_IWMMXT)
2646     FAIL;
2647   "
2650 (define_insn "arm_ashrdi3_1bit"
2651   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2652         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2653                      (const_int 1)))
2654    (clobber (reg:CC CC_REGNUM))]
2655   "TARGET_ARM"
2656   "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2657   [(set_attr "conds" "clob")
2658    (set_attr "length" "8")]
2661 (define_expand "ashrsi3"
2662   [(set (match_operand:SI              0 "s_register_operand" "")
2663         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2664                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2665   "TARGET_EITHER"
2666   "
2667   if (GET_CODE (operands[2]) == CONST_INT
2668       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2669     operands[2] = GEN_INT (31);
2670   "
2673 (define_insn "*thumb_ashrsi3"
2674   [(set (match_operand:SI              0 "register_operand" "=l,l")
2675         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2676                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2677   "TARGET_THUMB"
2678   "asr\\t%0, %1, %2"
2679   [(set_attr "length" "2")]
2682 (define_expand "lshrdi3"
2683   [(set (match_operand:DI              0 "s_register_operand" "")
2684         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2685                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2686   "TARGET_ARM"
2687   "
2688   if (GET_CODE (operands[2]) == CONST_INT)
2689     {
2690       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2691         {
2692           emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2693           DONE;
2694         }
2695         /* Ideally we shouldn't fail here if we could know that operands[1] 
2696            ends up already living in an iwmmxt register. Otherwise it's
2697            cheaper to have the alternate code being generated than moving
2698            values to iwmmxt regs and back.  */
2699         FAIL;
2700     }
2701   else if (!TARGET_REALLY_IWMMXT)
2702     FAIL;
2703   "
2706 (define_insn "arm_lshrdi3_1bit"
2707   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2708         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2709                      (const_int 1)))
2710    (clobber (reg:CC CC_REGNUM))]
2711   "TARGET_ARM"
2712   "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2713   [(set_attr "conds" "clob")
2714    (set_attr "length" "8")]
2717 (define_expand "lshrsi3"
2718   [(set (match_operand:SI              0 "s_register_operand" "")
2719         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2720                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2721   "TARGET_EITHER"
2722   "
2723   if (GET_CODE (operands[2]) == CONST_INT
2724       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2725     {
2726       emit_insn (gen_movsi (operands[0], const0_rtx));
2727       DONE;
2728     }
2729   "
2732 (define_insn "*thumb_lshrsi3"
2733   [(set (match_operand:SI              0 "register_operand" "=l,l")
2734         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2735                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2736   "TARGET_THUMB"
2737   "lsr\\t%0, %1, %2"
2738   [(set_attr "length" "2")]
2741 (define_expand "rotlsi3"
2742   [(set (match_operand:SI              0 "s_register_operand" "")
2743         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2744                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2745   "TARGET_ARM"
2746   "
2747   if (GET_CODE (operands[2]) == CONST_INT)
2748     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2749   else
2750     {
2751       rtx reg = gen_reg_rtx (SImode);
2752       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2753       operands[2] = reg;
2754     }
2755   "
2758 (define_expand "rotrsi3"
2759   [(set (match_operand:SI              0 "s_register_operand" "")
2760         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2761                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2762   "TARGET_EITHER"
2763   "
2764   if (TARGET_ARM)
2765     {
2766       if (GET_CODE (operands[2]) == CONST_INT
2767           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2768         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2769     }
2770   else /* TARGET_THUMB */
2771     {
2772       if (GET_CODE (operands [2]) == CONST_INT)
2773         operands [2] = force_reg (SImode, operands[2]);
2774     }
2775   "
2778 (define_insn "*thumb_rotrsi3"
2779   [(set (match_operand:SI              0 "register_operand" "=l")
2780         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2781                      (match_operand:SI 2 "register_operand" "l")))]
2782   "TARGET_THUMB"
2783   "ror\\t%0, %0, %2"
2784   [(set_attr "length" "2")]
2787 (define_insn "*arm_shiftsi3"
2788   [(set (match_operand:SI   0 "s_register_operand" "=r")
2789         (match_operator:SI  3 "shift_operator"
2790          [(match_operand:SI 1 "s_register_operand"  "r")
2791           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2792   "TARGET_ARM"
2793   "mov%?\\t%0, %1%S3"
2794   [(set_attr "predicable" "yes")
2795    (set_attr "shift" "1")
2796    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2797                       (const_string "alu_shift")
2798                       (const_string "alu_shift_reg")))]
2801 (define_insn "*shiftsi3_compare0"
2802   [(set (reg:CC_NOOV CC_REGNUM)
2803         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2804                           [(match_operand:SI 1 "s_register_operand" "r")
2805                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2806                          (const_int 0)))
2807    (set (match_operand:SI 0 "s_register_operand" "=r")
2808         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2809   "TARGET_ARM"
2810   "mov%?s\\t%0, %1%S3"
2811   [(set_attr "conds" "set")
2812    (set_attr "shift" "1")
2813    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2814                       (const_string "alu_shift")
2815                       (const_string "alu_shift_reg")))]
2818 (define_insn "*shiftsi3_compare0_scratch"
2819   [(set (reg:CC_NOOV CC_REGNUM)
2820         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2821                           [(match_operand:SI 1 "s_register_operand" "r")
2822                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2823                          (const_int 0)))
2824    (clobber (match_scratch:SI 0 "=r"))]
2825   "TARGET_ARM"
2826   "mov%?s\\t%0, %1%S3"
2827   [(set_attr "conds" "set")
2828    (set_attr "shift" "1")]
2831 (define_insn "*notsi_shiftsi"
2832   [(set (match_operand:SI 0 "s_register_operand" "=r")
2833         (not:SI (match_operator:SI 3 "shift_operator"
2834                  [(match_operand:SI 1 "s_register_operand" "r")
2835                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2836   "TARGET_ARM"
2837   "mvn%?\\t%0, %1%S3"
2838   [(set_attr "predicable" "yes")
2839    (set_attr "shift" "1")
2840    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2841                       (const_string "alu_shift")
2842                       (const_string "alu_shift_reg")))]
2845 (define_insn "*notsi_shiftsi_compare0"
2846   [(set (reg:CC_NOOV CC_REGNUM)
2847         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2848                           [(match_operand:SI 1 "s_register_operand" "r")
2849                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2850                          (const_int 0)))
2851    (set (match_operand:SI 0 "s_register_operand" "=r")
2852         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2853   "TARGET_ARM"
2854   "mvn%?s\\t%0, %1%S3"
2855   [(set_attr "conds" "set")
2856    (set_attr "shift" "1")
2857    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2858                       (const_string "alu_shift")
2859                       (const_string "alu_shift_reg")))]
2862 (define_insn "*not_shiftsi_compare0_scratch"
2863   [(set (reg:CC_NOOV CC_REGNUM)
2864         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2865                           [(match_operand:SI 1 "s_register_operand" "r")
2866                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2867                          (const_int 0)))
2868    (clobber (match_scratch:SI 0 "=r"))]
2869   "TARGET_ARM"
2870   "mvn%?s\\t%0, %1%S3"
2871   [(set_attr "conds" "set")
2872    (set_attr "shift" "1")
2873    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2874                       (const_string "alu_shift")
2875                       (const_string "alu_shift_reg")))]
2878 ;; We don't really have extzv, but defining this using shifts helps
2879 ;; to reduce register pressure later on.
2881 (define_expand "extzv"
2882   [(set (match_dup 4)
2883         (ashift:SI (match_operand:SI   1 "register_operand" "")
2884                    (match_operand:SI   2 "const_int_operand" "")))
2885    (set (match_operand:SI              0 "register_operand" "")
2886         (lshiftrt:SI (match_dup 4)
2887                      (match_operand:SI 3 "const_int_operand" "")))]
2888   "TARGET_THUMB"
2889   "
2890   {
2891     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2892     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2893     
2894     operands[3] = GEN_INT (rshift);
2895     
2896     if (lshift == 0)
2897       {
2898         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2899         DONE;
2900       }
2901       
2902     operands[2] = GEN_INT (lshift);
2903     operands[4] = gen_reg_rtx (SImode);
2904   }"
2908 ;; Unary arithmetic insns
2910 (define_expand "negdi2"
2911  [(parallel
2912    [(set (match_operand:DI          0 "s_register_operand" "")
2913           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2914     (clobber (reg:CC CC_REGNUM))])]
2915   "TARGET_EITHER"
2916   "
2917   if (TARGET_THUMB)
2918     {
2919       if (GET_CODE (operands[1]) != REG)
2920         operands[1] = force_reg (SImode, operands[1]);
2921      }
2922   "
2925 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2926 ;; The second alternative is to allow the common case of a *full* overlap.
2927 (define_insn "*arm_negdi2"
2928   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2929         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2930    (clobber (reg:CC CC_REGNUM))]
2931   "TARGET_ARM"
2932   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2933   [(set_attr "conds" "clob")
2934    (set_attr "length" "8")]
2937 (define_insn "*thumb_negdi2"
2938   [(set (match_operand:DI         0 "register_operand" "=&l")
2939         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
2940    (clobber (reg:CC CC_REGNUM))]
2941   "TARGET_THUMB"
2942   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2943   [(set_attr "length" "6")]
2946 (define_expand "negsi2"
2947   [(set (match_operand:SI         0 "s_register_operand" "")
2948         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2949   "TARGET_EITHER"
2950   ""
2953 (define_insn "*arm_negsi2"
2954   [(set (match_operand:SI         0 "s_register_operand" "=r")
2955         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2956   "TARGET_ARM"
2957   "rsb%?\\t%0, %1, #0"
2958   [(set_attr "predicable" "yes")]
2961 (define_insn "*thumb_negsi2"
2962   [(set (match_operand:SI         0 "register_operand" "=l")
2963         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2964   "TARGET_THUMB"
2965   "neg\\t%0, %1"
2966   [(set_attr "length" "2")]
2969 (define_expand "negsf2"
2970   [(set (match_operand:SF         0 "s_register_operand" "")
2971         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2972   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2973   ""
2976 (define_expand "negdf2"
2977   [(set (match_operand:DF         0 "s_register_operand" "")
2978         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2979   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2980   "")
2982 ;; abssi2 doesn't really clobber the condition codes if a different register
2983 ;; is being set.  To keep things simple, assume during rtl manipulations that
2984 ;; it does, but tell the final scan operator the truth.  Similarly for
2985 ;; (neg (abs...))
2987 (define_expand "abssi2"
2988   [(parallel
2989     [(set (match_operand:SI         0 "s_register_operand" "")
2990           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
2991      (clobber (reg:CC CC_REGNUM))])]
2992   "TARGET_ARM"
2993   "")
2995 (define_insn "*arm_abssi2"
2996   [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
2997         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2998    (clobber (reg:CC CC_REGNUM))]
2999   "TARGET_ARM"
3000   "@
3001    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3002    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3003   [(set_attr "conds" "clob,*")
3004    (set_attr "shift" "1")
3005    ;; predicable can't be set based on the variant, so left as no
3006    (set_attr "length" "8")]
3009 (define_insn "*neg_abssi2"
3010   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3011         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3012    (clobber (reg:CC CC_REGNUM))]
3013   "TARGET_ARM"
3014   "@
3015    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3016    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3017   [(set_attr "conds" "clob,*")
3018    (set_attr "shift" "1")
3019    ;; predicable can't be set based on the variant, so left as no
3020    (set_attr "length" "8")]
3023 (define_expand "abssf2"
3024   [(set (match_operand:SF         0 "s_register_operand" "")
3025         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3026   "TARGET_ARM && TARGET_HARD_FLOAT"
3027   "")
3029 (define_expand "absdf2"
3030   [(set (match_operand:DF         0 "s_register_operand" "")
3031         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3032   "TARGET_ARM && TARGET_HARD_FLOAT"
3033   "")
3035 (define_expand "sqrtsf2"
3036   [(set (match_operand:SF 0 "s_register_operand" "")
3037         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3038   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3039   "")
3041 (define_expand "sqrtdf2"
3042   [(set (match_operand:DF 0 "s_register_operand" "")
3043         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3044   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3045   "")
3047 (define_insn_and_split "one_cmpldi2"
3048   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3049         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3050   "TARGET_ARM"
3051   "#"
3052   "TARGET_ARM && reload_completed"
3053   [(set (match_dup 0) (not:SI (match_dup 1)))
3054    (set (match_dup 2) (not:SI (match_dup 3)))]
3055   "
3056   {
3057     operands[2] = gen_highpart (SImode, operands[0]);
3058     operands[0] = gen_lowpart (SImode, operands[0]);
3059     operands[3] = gen_highpart (SImode, operands[1]);
3060     operands[1] = gen_lowpart (SImode, operands[1]);
3061   }"
3062   [(set_attr "length" "8")
3063    (set_attr "predicable" "yes")]
3066 (define_expand "one_cmplsi2"
3067   [(set (match_operand:SI         0 "s_register_operand" "")
3068         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3069   "TARGET_EITHER"
3070   ""
3073 (define_insn "*arm_one_cmplsi2"
3074   [(set (match_operand:SI         0 "s_register_operand" "=r")
3075         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3076   "TARGET_ARM"
3077   "mvn%?\\t%0, %1"
3078   [(set_attr "predicable" "yes")]
3081 (define_insn "*thumb_one_cmplsi2"
3082   [(set (match_operand:SI         0 "register_operand" "=l")
3083         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3084   "TARGET_THUMB"
3085   "mvn\\t%0, %1"
3086   [(set_attr "length" "2")]
3089 (define_insn "*notsi_compare0"
3090   [(set (reg:CC_NOOV CC_REGNUM)
3091         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3092                          (const_int 0)))
3093    (set (match_operand:SI 0 "s_register_operand" "=r")
3094         (not:SI (match_dup 1)))]
3095   "TARGET_ARM"
3096   "mvn%?s\\t%0, %1"
3097   [(set_attr "conds" "set")]
3100 (define_insn "*notsi_compare0_scratch"
3101   [(set (reg:CC_NOOV CC_REGNUM)
3102         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3103                          (const_int 0)))
3104    (clobber (match_scratch:SI 0 "=r"))]
3105   "TARGET_ARM"
3106   "mvn%?s\\t%0, %1"
3107   [(set_attr "conds" "set")]
3110 ;; Fixed <--> Floating conversion insns
3112 (define_expand "floatsisf2"
3113   [(set (match_operand:SF           0 "s_register_operand" "")
3114         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3115   "TARGET_ARM && TARGET_HARD_FLOAT"
3116   "
3117   if (TARGET_MAVERICK)
3118     {
3119       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3120       DONE;
3121     }
3124 (define_expand "floatsidf2"
3125   [(set (match_operand:DF           0 "s_register_operand" "")
3126         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3127   "TARGET_ARM && TARGET_HARD_FLOAT"
3128   "
3129   if (TARGET_MAVERICK)
3130     {
3131       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3132       DONE;
3133     }
3136 (define_expand "fix_truncsfsi2"
3137   [(set (match_operand:SI         0 "s_register_operand" "")
3138         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3139   "TARGET_ARM && TARGET_HARD_FLOAT"
3140   "
3141   if (TARGET_MAVERICK)
3142     {
3143       if (!cirrus_fp_register (operands[0], SImode))
3144         operands[0] = force_reg (SImode, operands[0]);
3145       if (!cirrus_fp_register (operands[1], SFmode))
3146         operands[1] = force_reg (SFmode, operands[0]);
3147       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3148       DONE;
3149     }
3152 (define_expand "fix_truncdfsi2"
3153   [(set (match_operand:SI         0 "s_register_operand" "")
3154         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3155   "TARGET_ARM && TARGET_HARD_FLOAT"
3156   "
3157   if (TARGET_MAVERICK)
3158     {
3159       if (!cirrus_fp_register (operands[1], DFmode))
3160         operands[1] = force_reg (DFmode, operands[0]);
3161       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3162       DONE;
3163     }
3166 ;; Truncation insns
3168 (define_expand "truncdfsf2"
3169   [(set (match_operand:SF  0 "s_register_operand" "")
3170         (float_truncate:SF
3171          (match_operand:DF 1 "s_register_operand" "")))]
3172   "TARGET_ARM && TARGET_HARD_FLOAT"
3173   ""
3176 ;; Zero and sign extension instructions.
3178 (define_insn "zero_extendsidi2"
3179   [(set (match_operand:DI 0 "s_register_operand" "=r")
3180         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3181   "TARGET_ARM"
3182   "*
3183     if (REGNO (operands[1])
3184         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3185       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3186     return \"mov%?\\t%R0, #0\";
3187   "
3188   [(set_attr "length" "8")
3189    (set_attr "predicable" "yes")]
3192 (define_insn "zero_extendqidi2"
3193   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3194         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3195   "TARGET_ARM"
3196   "@
3197    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3198    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3199   [(set_attr "length" "8")
3200    (set_attr "predicable" "yes")
3201    (set_attr "type" "*,load_byte")
3202    (set_attr "pool_range" "*,4092")
3203    (set_attr "neg_pool_range" "*,4084")]
3206 (define_insn "extendsidi2"
3207   [(set (match_operand:DI 0 "s_register_operand" "=r")
3208         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3209   "TARGET_ARM"
3210   "*
3211     if (REGNO (operands[1])
3212         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3213       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3214     return \"mov%?\\t%R0, %Q0, asr #31\";
3215   "
3216   [(set_attr "length" "8")
3217    (set_attr "shift" "1")
3218    (set_attr "predicable" "yes")]
3221 (define_expand "zero_extendhisi2"
3222   [(set (match_dup 2)
3223         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3224                    (const_int 16)))
3225    (set (match_operand:SI 0 "s_register_operand" "")
3226         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3227   "TARGET_EITHER"
3228   "
3229   {
3230     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3231       {
3232         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3233                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3234         DONE;
3235       }
3237     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3238       {
3239         emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3240         DONE;
3241       }
3243     if (!s_register_operand (operands[1], HImode))
3244       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3246     if (arm_arch6)
3247       {
3248         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3249                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3250         DONE;
3251       }
3253     operands[1] = gen_lowpart (SImode, operands[1]);
3254     operands[2] = gen_reg_rtx (SImode);
3255   }"
3258 (define_insn "*thumb_zero_extendhisi2"
3259   [(set (match_operand:SI 0 "register_operand" "=l")
3260         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3261   "TARGET_THUMB && !arm_arch6"
3262   "*
3263   rtx mem = XEXP (operands[1], 0);
3265   if (GET_CODE (mem) == CONST)
3266     mem = XEXP (mem, 0);
3267     
3268   if (GET_CODE (mem) == LABEL_REF)
3269     return \"ldr\\t%0, %1\";
3270     
3271   if (GET_CODE (mem) == PLUS)
3272     {
3273       rtx a = XEXP (mem, 0);
3274       rtx b = XEXP (mem, 1);
3276       /* This can happen due to bugs in reload.  */
3277       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3278         {
3279           rtx ops[2];
3280           ops[0] = operands[0];
3281           ops[1] = a;
3282       
3283           output_asm_insn (\"mov        %0, %1\", ops);
3285           XEXP (mem, 0) = operands[0];
3286        }
3288       else if (   GET_CODE (a) == LABEL_REF
3289                && GET_CODE (b) == CONST_INT)
3290         return \"ldr\\t%0, %1\";
3291     }
3292     
3293   return \"ldrh\\t%0, %1\";
3294   "
3295   [(set_attr "length" "4")
3296    (set_attr "type" "load_byte")
3297    (set_attr "pool_range" "60")]
3300 (define_insn "*thumb_zero_extendhisi2_v6"
3301   [(set (match_operand:SI 0 "register_operand" "=l,l")
3302         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3303   "TARGET_THUMB && arm_arch6"
3304   "*
3305   rtx mem;
3307   if (which_alternative == 0)
3308     return \"uxth\\t%0, %1\";
3310   mem = XEXP (operands[1], 0);
3312   if (GET_CODE (mem) == CONST)
3313     mem = XEXP (mem, 0);
3314     
3315   if (GET_CODE (mem) == LABEL_REF)
3316     return \"ldr\\t%0, %1\";
3317     
3318   if (GET_CODE (mem) == PLUS)
3319     {
3320       rtx a = XEXP (mem, 0);
3321       rtx b = XEXP (mem, 1);
3323       /* This can happen due to bugs in reload.  */
3324       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3325         {
3326           rtx ops[2];
3327           ops[0] = operands[0];
3328           ops[1] = a;
3329       
3330           output_asm_insn (\"mov        %0, %1\", ops);
3332           XEXP (mem, 0) = operands[0];
3333        }
3335       else if (   GET_CODE (a) == LABEL_REF
3336                && GET_CODE (b) == CONST_INT)
3337         return \"ldr\\t%0, %1\";
3338     }
3339     
3340   return \"ldrh\\t%0, %1\";
3341   "
3342   [(set_attr "length" "2,4")
3343    (set_attr "type" "alu_shift,load_byte")
3344    (set_attr "pool_range" "*,60")]
3347 (define_insn "*arm_zero_extendhisi2"
3348   [(set (match_operand:SI 0 "s_register_operand" "=r")
3349         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3350   "TARGET_ARM && arm_arch4 && !arm_arch6"
3351   "ldr%?h\\t%0, %1"
3352   [(set_attr "type" "load_byte")
3353    (set_attr "predicable" "yes")
3354    (set_attr "pool_range" "256")
3355    (set_attr "neg_pool_range" "244")]
3358 (define_insn "*arm_zero_extendhisi2_v6"
3359   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3360         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3361   "TARGET_ARM && arm_arch6"
3362   "@
3363    uxth%?\\t%0, %1
3364    ldr%?h\\t%0, %1"
3365   [(set_attr "type" "alu_shift,load_byte")
3366    (set_attr "predicable" "yes")
3367    (set_attr "pool_range" "*,256")
3368    (set_attr "neg_pool_range" "*,244")]
3371 (define_insn "*arm_zero_extendhisi2addsi"
3372   [(set (match_operand:SI 0 "s_register_operand" "=r")
3373         (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3374                  (match_operand:SI 2 "s_register_operand" "r")))]
3375   "TARGET_ARM && arm_arch6"
3376   "uxtah%?\\t%0, %2, %1"
3377   [(set_attr "type" "alu_shift")
3378    (set_attr "predicable" "yes")]
3381 (define_split
3382   [(set (match_operand:SI 0 "s_register_operand" "")
3383         (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3384    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3385   "TARGET_ARM && (!arm_arch4)"
3386   [(set (match_dup 2) (match_dup 1))
3387    (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3388   "
3389   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3390     FAIL;
3391   "
3394 (define_split
3395   [(set (match_operand:SI 0 "s_register_operand" "")
3396         (match_operator:SI 3 "shiftable_operator"
3397          [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3398           (match_operand:SI 4 "s_register_operand" "")]))
3399    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3400   "TARGET_ARM && (!arm_arch4)"
3401   [(set (match_dup 2) (match_dup 1))
3402    (set (match_dup 0)
3403         (match_op_dup 3
3404          [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3405   "
3406   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3407     FAIL;
3408   "
3411 (define_expand "zero_extendqisi2"
3412   [(set (match_operand:SI 0 "s_register_operand" "")
3413         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3414   "TARGET_EITHER"
3415   "
3416   if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3417     {
3418       if (TARGET_ARM)
3419         {
3420           emit_insn (gen_andsi3 (operands[0],
3421                                  gen_lowpart (SImode, operands[1]),
3422                                  GEN_INT (255)));
3423         }
3424       else /* TARGET_THUMB */
3425         {
3426           rtx temp = gen_reg_rtx (SImode);
3427           rtx ops[3];
3428           
3429           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3430           operands[1] = gen_lowpart (SImode, operands[1]);
3432           ops[0] = temp;
3433           ops[1] = operands[1];
3434           ops[2] = GEN_INT (24);
3436           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3437                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3438           
3439           ops[0] = operands[0];
3440           ops[1] = temp;
3441           ops[2] = GEN_INT (24);
3443           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3444                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3445         }
3446       DONE;
3447     }
3448   "
3451 (define_insn "*thumb_zero_extendqisi2"
3452   [(set (match_operand:SI 0 "register_operand" "=l")
3453         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3454   "TARGET_THUMB && !arm_arch6"
3455   "ldrb\\t%0, %1"
3456   [(set_attr "length" "2")
3457    (set_attr "type" "load_byte")
3458    (set_attr "pool_range" "32")]
3461 (define_insn "*thumb_zero_extendqisi2_v6"
3462   [(set (match_operand:SI 0 "register_operand" "=l,l")
3463         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3464   "TARGET_THUMB && arm_arch6"
3465   "@
3466    uxtb\\t%0, %1
3467    ldrb\\t%0, %1"
3468   [(set_attr "length" "2,2")
3469    (set_attr "type" "alu_shift,load_byte")
3470    (set_attr "pool_range" "*,32")]
3473 (define_insn "*arm_zero_extendqisi2"
3474   [(set (match_operand:SI 0 "s_register_operand" "=r")
3475         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3476   "TARGET_ARM && !arm_arch6"
3477   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3478   [(set_attr "type" "load_byte")
3479    (set_attr "predicable" "yes")
3480    (set_attr "pool_range" "4096")
3481    (set_attr "neg_pool_range" "4084")]
3484 (define_insn "*arm_zero_extendqisi2_v6"
3485   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3486         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3487   "TARGET_ARM && arm_arch6"
3488   "@
3489    uxtb%?\\t%0, %1
3490    ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3491   [(set_attr "type" "alu_shift,load_byte")
3492    (set_attr "predicable" "yes")
3493    (set_attr "pool_range" "*,4096")
3494    (set_attr "neg_pool_range" "*,4084")]
3497 (define_insn "*arm_zero_extendqisi2addsi"
3498   [(set (match_operand:SI 0 "s_register_operand" "=r")
3499         (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3500                  (match_operand:SI 2 "s_register_operand" "r")))]
3501   "TARGET_ARM && arm_arch6"
3502   "uxtab%?\\t%0, %2, %1"
3503   [(set_attr "predicable" "yes")
3504    (set_attr "type" "alu_shift")]
3507 (define_split
3508   [(set (match_operand:SI 0 "s_register_operand" "")
3509         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3510    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3511   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3512   [(set (match_dup 2) (match_dup 1))
3513    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3514   ""
3517 (define_insn "*compareqi_eq0"
3518   [(set (reg:CC_Z CC_REGNUM)
3519         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3520                          (const_int 0)))]
3521   "TARGET_ARM"
3522   "tst\\t%0, #255"
3523   [(set_attr "conds" "set")]
3526 (define_expand "extendhisi2"
3527   [(set (match_dup 2)
3528         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3529                    (const_int 16)))
3530    (set (match_operand:SI 0 "s_register_operand" "")
3531         (ashiftrt:SI (match_dup 2)
3532                      (const_int 16)))]
3533   "TARGET_EITHER"
3534   "
3535   {
3536     if (GET_CODE (operands[1]) == MEM)
3537       {
3538         if (TARGET_THUMB)
3539           {
3540             emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3541             DONE;
3542           }
3543         else if (arm_arch4)
3544           {
3545             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3546                        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3547             DONE;
3548           }
3549       }
3551     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3552       {
3553         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3554         DONE;
3555       }
3557     if (!s_register_operand (operands[1], HImode))
3558       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3560     if (arm_arch6)
3561       {
3562         if (TARGET_THUMB)
3563           emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3564         else
3565           emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3566                      gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3568         DONE;
3569       }
3571     operands[1] = gen_lowpart (SImode, operands[1]);
3572     operands[2] = gen_reg_rtx (SImode);
3573   }"
3576 (define_insn "thumb_extendhisi2"
3577   [(set (match_operand:SI 0 "register_operand" "=l")
3578         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3579    (clobber (match_scratch:SI 2 "=&l"))]
3580   "TARGET_THUMB && !arm_arch6"
3581   "*
3582   {
3583     rtx ops[4];
3584     rtx mem = XEXP (operands[1], 0);
3586     /* This code used to try to use 'V', and fix the address only if it was
3587        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3588        range of QImode offsets, and offsettable_address_p does a QImode
3589        address check.  */
3590        
3591     if (GET_CODE (mem) == CONST)
3592       mem = XEXP (mem, 0);
3593     
3594     if (GET_CODE (mem) == LABEL_REF)
3595       return \"ldr\\t%0, %1\";
3596     
3597     if (GET_CODE (mem) == PLUS)
3598       {
3599         rtx a = XEXP (mem, 0);
3600         rtx b = XEXP (mem, 1);
3602         if (GET_CODE (a) == LABEL_REF
3603             && GET_CODE (b) == CONST_INT)
3604           return \"ldr\\t%0, %1\";
3606         if (GET_CODE (b) == REG)
3607           return \"ldrsh\\t%0, %1\";
3608           
3609         ops[1] = a;
3610         ops[2] = b;
3611       }
3612     else
3613       {
3614         ops[1] = mem;
3615         ops[2] = const0_rtx;
3616       }
3617       
3618     if (GET_CODE (ops[1]) != REG)
3619       {
3620         debug_rtx (ops[1]);
3621         abort ();
3622       }
3624     ops[0] = operands[0];
3625     ops[3] = operands[2];
3626     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3627     return \"\";
3628   }"
3629   [(set_attr "length" "4")
3630    (set_attr "type" "load_byte")
3631    (set_attr "pool_range" "1020")]
3634 ;; We used to have an early-clobber on the scratch register here.
3635 ;; However, there's a bug somewhere in reload which means that this
3636 ;; can be partially ignored during spill allocation if the memory
3637 ;; address also needs reloading; this causes an abort later on when
3638 ;; we try to verify the operands.  Fortunately, we don't really need
3639 ;; the early-clobber: we can always use operand 0 if operand 2
3640 ;; overlaps the address.
3641 (define_insn "*thumb_extendhisi2_insn_v6"
3642   [(set (match_operand:SI 0 "register_operand" "=l,l")
3643         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3644    (clobber (match_scratch:SI 2 "=X,l"))]
3645   "TARGET_THUMB && arm_arch6"
3646   "*
3647   {
3648     rtx ops[4];
3649     rtx mem;
3651     if (which_alternative == 0)
3652       return \"sxth\\t%0, %1\";
3654     mem = XEXP (operands[1], 0);
3656     /* This code used to try to use 'V', and fix the address only if it was
3657        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3658        range of QImode offsets, and offsettable_address_p does a QImode
3659        address check.  */
3660        
3661     if (GET_CODE (mem) == CONST)
3662       mem = XEXP (mem, 0);
3663     
3664     if (GET_CODE (mem) == LABEL_REF)
3665       return \"ldr\\t%0, %1\";
3666     
3667     if (GET_CODE (mem) == PLUS)
3668       {
3669         rtx a = XEXP (mem, 0);
3670         rtx b = XEXP (mem, 1);
3672         if (GET_CODE (a) == LABEL_REF
3673             && GET_CODE (b) == CONST_INT)
3674           return \"ldr\\t%0, %1\";
3676         if (GET_CODE (b) == REG)
3677           return \"ldrsh\\t%0, %1\";
3678           
3679         ops[1] = a;
3680         ops[2] = b;
3681       }
3682     else
3683       {
3684         ops[1] = mem;
3685         ops[2] = const0_rtx;
3686       }
3687       
3688     if (GET_CODE (ops[1]) != REG)
3689       {
3690         debug_rtx (ops[1]);
3691         abort ();
3692       }
3694     ops[0] = operands[0];
3695     if (reg_mentioned_p (operands[2], ops[1]))
3696       ops[3] = ops[0];
3697     else
3698       ops[3] = operands[2];
3699     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3700     return \"\";
3701   }"
3702   [(set_attr "length" "2,4")
3703    (set_attr "type" "alu_shift,load_byte")
3704    (set_attr "pool_range" "*,1020")]
3707 (define_expand "extendhisi2_mem"
3708   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3709    (set (match_dup 3)
3710         (zero_extend:SI (match_dup 7)))
3711    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3712    (set (match_operand:SI 0 "" "")
3713         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3714   "TARGET_ARM"
3715   "
3716   {
3717     rtx mem1, mem2;
3718     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3720     mem1 = gen_rtx_MEM (QImode, addr);
3721     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3722     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3723     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3724     operands[0] = gen_lowpart (SImode, operands[0]);
3725     operands[1] = mem1;
3726     operands[2] = gen_reg_rtx (SImode);
3727     operands[3] = gen_reg_rtx (SImode);
3728     operands[6] = gen_reg_rtx (SImode);
3729     operands[7] = mem2;
3731     if (BYTES_BIG_ENDIAN)
3732       {
3733         operands[4] = operands[2];
3734         operands[5] = operands[3];
3735       }
3736     else
3737       {
3738         operands[4] = operands[3];
3739         operands[5] = operands[2];
3740       }
3741   }"
3744 (define_insn "*arm_extendhisi2"
3745   [(set (match_operand:SI 0 "s_register_operand" "=r")
3746         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3747   "TARGET_ARM && arm_arch4 && !arm_arch6"
3748   "ldr%?sh\\t%0, %1"
3749   [(set_attr "type" "load_byte")
3750    (set_attr "predicable" "yes")
3751    (set_attr "pool_range" "256")
3752    (set_attr "neg_pool_range" "244")]
3755 (define_insn "*arm_extendhisi2_v6"
3756   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3757         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3758   "TARGET_ARM && arm_arch6"
3759   "@
3760    sxth%?\\t%0, %1
3761    ldr%?sh\\t%0, %1"
3762   [(set_attr "type" "alu_shift,load_byte")
3763    (set_attr "predicable" "yes")
3764    (set_attr "pool_range" "*,256")
3765    (set_attr "neg_pool_range" "*,244")]
3768 (define_insn "*arm_extendhisi2addsi"
3769   [(set (match_operand:SI 0 "s_register_operand" "=r")
3770         (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3771                  (match_operand:SI 2 "s_register_operand" "r")))]
3772   "TARGET_ARM && arm_arch6"
3773   "sxtah%?\\t%0, %2, %1"
3776 (define_split
3777   [(set (match_operand:SI                 0 "s_register_operand" "")
3778         (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3779    (clobber (match_operand:SI             2 "s_register_operand" ""))]
3780   "TARGET_ARM && (!arm_arch4)"
3781   [(set (match_dup 2) (match_dup 1))
3782    (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3783   "
3784   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3785     FAIL;
3786   "
3789 (define_split
3790   [(set (match_operand:SI                   0 "s_register_operand" "")
3791         (match_operator:SI                  3 "shiftable_operator"
3792          [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3793           (match_operand:SI                 4 "s_register_operand" "")]))
3794    (clobber (match_operand:SI               2 "s_register_operand" ""))]
3795   "TARGET_ARM && (!arm_arch4)"
3796   [(set (match_dup 2) (match_dup 1))
3797    (set (match_dup 0)
3798         (match_op_dup 3
3799          [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3800   "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3801      FAIL;
3802   "
3805 (define_expand "extendqihi2"
3806   [(set (match_dup 2)
3807         (ashift:SI (match_operand:QI 1 "general_operand" "")
3808                    (const_int 24)))
3809    (set (match_operand:HI 0 "s_register_operand" "")
3810         (ashiftrt:SI (match_dup 2)
3811                      (const_int 24)))]
3812   "TARGET_ARM"
3813   "
3814   {
3815     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3816       {
3817         emit_insn (gen_rtx_SET (VOIDmode,
3818                                 operands[0],
3819                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3820         DONE;
3821       }
3822     if (!s_register_operand (operands[1], QImode))
3823       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3824     operands[0] = gen_lowpart (SImode, operands[0]);
3825     operands[1] = gen_lowpart (SImode, operands[1]);
3826     operands[2] = gen_reg_rtx (SImode);
3827   }"
3830 (define_insn "*extendqihi_insn"
3831   [(set (match_operand:HI 0 "s_register_operand" "=r")
3832         (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3833   "TARGET_ARM && arm_arch4"
3834   "ldr%?sb\\t%0, %1"
3835   [(set_attr "type" "load_byte")
3836    (set_attr "predicable" "yes")
3837    (set_attr "pool_range" "256")
3838    (set_attr "neg_pool_range" "244")]
3841 (define_expand "extendqisi2"
3842   [(set (match_dup 2)
3843         (ashift:SI (match_operand:QI 1 "general_operand" "")
3844                    (const_int 24)))
3845    (set (match_operand:SI 0 "s_register_operand" "")
3846         (ashiftrt:SI (match_dup 2)
3847                      (const_int 24)))]
3848   "TARGET_EITHER"
3849   "
3850   {
3851     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3852       {
3853         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3854                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3855         DONE;
3856       }
3858     if (!s_register_operand (operands[1], QImode))
3859       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3861     if (arm_arch6)
3862       {
3863         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3864                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3865         DONE;
3866       }
3868     operands[1] = gen_lowpart (SImode, operands[1]);
3869     operands[2] = gen_reg_rtx (SImode);
3870   }"
3873 (define_insn "*arm_extendqisi"
3874   [(set (match_operand:SI 0 "s_register_operand" "=r")
3875         (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3876   "TARGET_ARM && arm_arch4 && !arm_arch6"
3877   "ldr%?sb\\t%0, %1"
3878   [(set_attr "type" "load_byte")
3879    (set_attr "predicable" "yes")
3880    (set_attr "pool_range" "256")
3881    (set_attr "neg_pool_range" "244")]
3884 (define_insn "*arm_extendqisi_v6"
3885   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3886         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3887   "TARGET_ARM && arm_arch6"
3888   "@
3889    sxtb%?\\t%0, %1
3890    ldr%?sb\\t%0, %1"
3891   [(set_attr "type" "alu_shift,load_byte")
3892    (set_attr "predicable" "yes")
3893    (set_attr "pool_range" "*,256")
3894    (set_attr "neg_pool_range" "*,244")]
3897 (define_insn "*arm_extendqisi2addsi"
3898   [(set (match_operand:SI 0 "s_register_operand" "=r")
3899         (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3900                  (match_operand:SI 2 "s_register_operand" "r")))]
3901   "TARGET_ARM && arm_arch6"
3902   "sxtab%?\\t%0, %2, %1"
3903   [(set_attr "type" "alu_shift")
3904    (set_attr "predicable" "yes")]
3907 (define_insn "*thumb_extendqisi2"
3908   [(set (match_operand:SI 0 "register_operand" "=l,l")
3909         (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3910   "TARGET_THUMB && !arm_arch6"
3911   "*
3912   {
3913     rtx ops[3];
3914     rtx mem = XEXP (operands[1], 0);
3915     
3916     if (GET_CODE (mem) == CONST)
3917       mem = XEXP (mem, 0);
3918     
3919     if (GET_CODE (mem) == LABEL_REF)
3920       return \"ldr\\t%0, %1\";
3922     if (GET_CODE (mem) == PLUS
3923         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3924       return \"ldr\\t%0, %1\";
3925       
3926     if (which_alternative == 0)
3927       return \"ldrsb\\t%0, %1\";
3928       
3929     ops[0] = operands[0];
3930     
3931     if (GET_CODE (mem) == PLUS)
3932       {
3933         rtx a = XEXP (mem, 0);
3934         rtx b = XEXP (mem, 1);
3935         
3936         ops[1] = a;
3937         ops[2] = b;
3939         if (GET_CODE (a) == REG)
3940           {
3941             if (GET_CODE (b) == REG)
3942               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3943             else if (REGNO (a) == REGNO (ops[0]))
3944               {
3945                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3946                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3947                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3948               }
3949             else
3950               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3951           }
3952         else if (GET_CODE (b) != REG)
3953           abort ();
3954         else
3955           {
3956             if (REGNO (b) == REGNO (ops[0]))
3957               {
3958                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3959                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3960                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3961               }
3962             else
3963               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3964           }
3965       }
3966     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3967       {
3968         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3969         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3970         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3971       }
3972     else
3973       {
3974         ops[1] = mem;
3975         ops[2] = const0_rtx;
3976         
3977         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3978       }
3979     return \"\";
3980   }"
3981   [(set_attr "length" "2,6")
3982    (set_attr "type" "load_byte,load_byte")
3983    (set_attr "pool_range" "32,32")]
3986 (define_insn "*thumb_extendqisi2_v6"
3987   [(set (match_operand:SI 0 "register_operand" "=l,l,l")
3988         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
3989   "TARGET_THUMB && arm_arch6"
3990   "*
3991   {
3992     rtx ops[3];
3993     rtx mem;
3995     if (which_alternative == 0)
3996       return \"sxtb\\t%0, %1\";
3998     mem = XEXP (operands[1], 0);
3999     
4000     if (GET_CODE (mem) == CONST)
4001       mem = XEXP (mem, 0);
4002     
4003     if (GET_CODE (mem) == LABEL_REF)
4004       return \"ldr\\t%0, %1\";
4006     if (GET_CODE (mem) == PLUS
4007         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4008       return \"ldr\\t%0, %1\";
4009       
4010     if (which_alternative == 0)
4011       return \"ldrsb\\t%0, %1\";
4012       
4013     ops[0] = operands[0];
4014     
4015     if (GET_CODE (mem) == PLUS)
4016       {
4017         rtx a = XEXP (mem, 0);
4018         rtx b = XEXP (mem, 1);
4019         
4020         ops[1] = a;
4021         ops[2] = b;
4023         if (GET_CODE (a) == REG)
4024           {
4025             if (GET_CODE (b) == REG)
4026               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4027             else if (REGNO (a) == REGNO (ops[0]))
4028               {
4029                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4030                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4031               }
4032             else
4033               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4034           }
4035         else if (GET_CODE (b) != REG)
4036           abort ();
4037         else
4038           {
4039             if (REGNO (b) == REGNO (ops[0]))
4040               {
4041                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4042                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4043               }
4044             else
4045               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4046           }
4047       }
4048     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4049       {
4050         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4051         output_asm_insn (\"sxtb\\t%0, %0\", ops);
4052       }
4053     else
4054       {
4055         ops[1] = mem;
4056         ops[2] = const0_rtx;
4057         
4058         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4059       }
4060     return \"\";
4061   }"
4062   [(set_attr "length" "2,2,4")
4063    (set_attr "type" "alu_shift,load_byte,load_byte")
4064    (set_attr "pool_range" "*,32,32")]
4067 (define_expand "extendsfdf2"
4068   [(set (match_operand:DF                  0 "s_register_operand" "")
4069         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
4070   "TARGET_ARM && TARGET_HARD_FLOAT"
4071   ""
4074 ;; Move insns (including loads and stores)
4076 ;; XXX Just some ideas about movti.
4077 ;; I don't think these are a good idea on the arm, there just aren't enough
4078 ;; registers
4079 ;;(define_expand "loadti"
4080 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
4081 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
4082 ;;  "" "")
4084 ;;(define_expand "storeti"
4085 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4086 ;;      (match_operand:TI 1 "s_register_operand" ""))]
4087 ;;  "" "")
4089 ;;(define_expand "movti"
4090 ;;  [(set (match_operand:TI 0 "general_operand" "")
4091 ;;      (match_operand:TI 1 "general_operand" ""))]
4092 ;;  ""
4093 ;;  "
4095 ;;  rtx insn;
4097 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4098 ;;    operands[1] = copy_to_reg (operands[1]);
4099 ;;  if (GET_CODE (operands[0]) == MEM)
4100 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4101 ;;  else if (GET_CODE (operands[1]) == MEM)
4102 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4103 ;;  else
4104 ;;    FAIL;
4106 ;;  emit_insn (insn);
4107 ;;  DONE;
4108 ;;}")
4110 ;; Recognize garbage generated above.
4112 ;;(define_insn ""
4113 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4114 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4115 ;;  ""
4116 ;;  "*
4117 ;;  {
4118 ;;    register mem = (which_alternative < 3);
4119 ;;    register const char *template;
4121 ;;    operands[mem] = XEXP (operands[mem], 0);
4122 ;;    switch (which_alternative)
4123 ;;      {
4124 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4125 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
4126 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
4127 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
4128 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
4129 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
4130 ;;      }
4131 ;;    output_asm_insn (template, operands);
4132 ;;    return \"\";
4133 ;;  }")
4135 (define_expand "movdi"
4136   [(set (match_operand:DI 0 "general_operand" "")
4137         (match_operand:DI 1 "general_operand" ""))]
4138   "TARGET_EITHER"
4139   "
4140   if (TARGET_THUMB)
4141     {
4142       if (!no_new_pseudos)
4143         {
4144           if (GET_CODE (operands[0]) != REG)
4145             operands[1] = force_reg (DImode, operands[1]);
4146         }
4147     }
4148   "
4151 (define_insn "*arm_movdi"
4152   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4153         (match_operand:DI 1 "di_operand"              "rDa,Db,Dc,mi,r"))]
4154   "TARGET_ARM
4155   && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4156   && !TARGET_IWMMXT"
4157   "*
4158   switch (which_alternative)
4159     {
4160     case 0:
4161     case 1:
4162     case 2:
4163       return \"#\";
4164     default:
4165       return output_move_double (operands);
4166     }
4167   "
4168   [(set_attr "length" "8,12,16,8,8")
4169    (set_attr "type" "*,*,*,load2,store2")
4170    (set_attr "pool_range" "*,*,*,1020,*")
4171    (set_attr "neg_pool_range" "*,*,*,1008,*")]
4174 (define_split
4175   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4176         (match_operand:ANY64 1 "const_double_operand" ""))]
4177   "TARGET_ARM
4178    && reload_completed
4179    && (arm_const_double_inline_cost (operands[1])
4180        <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4181   [(const_int 0)]
4182   "
4183   arm_split_constant (SET, SImode, curr_insn,
4184                       INTVAL (gen_lowpart (SImode, operands[1])),
4185                       gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4186   arm_split_constant (SET, SImode, curr_insn,
4187                       INTVAL (gen_highpart_mode (SImode,
4188                                                  GET_MODE (operands[0]),
4189                                                  operands[1])),
4190                       gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4191   DONE;
4192   "
4195 ; If optimizing for size, or if we have load delay slots, then 
4196 ; we want to split the constant into two separate operations. 
4197 ; In both cases this may split a trivial part into a single data op
4198 ; leaving a single complex constant to load.  We can also get longer
4199 ; offsets in a LDR which means we get better chances of sharing the pool
4200 ; entries.  Finally, we can normally do a better job of scheduling
4201 ; LDR instructions than we can with LDM.
4202 ; This pattern will only match if the one above did not.
4203 (define_split
4204   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4205         (match_operand:ANY64 1 "const_double_operand" ""))]
4206   "TARGET_ARM && reload_completed
4207    && arm_const_double_by_parts (operands[1])"
4208   [(set (match_dup 0) (match_dup 1))
4209    (set (match_dup 2) (match_dup 3))]
4210   "
4211   operands[2] = gen_highpart (SImode, operands[0]);
4212   operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4213                                    operands[1]);
4214   operands[0] = gen_lowpart (SImode, operands[0]);
4215   operands[1] = gen_lowpart (SImode, operands[1]);
4216   "
4219 (define_split
4220   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4221         (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4222   "TARGET_EITHER && reload_completed"
4223   [(set (match_dup 0) (match_dup 1))
4224    (set (match_dup 2) (match_dup 3))]
4225   "
4226   operands[2] = gen_highpart (SImode, operands[0]);
4227   operands[3] = gen_highpart (SImode, operands[1]);
4228   operands[0] = gen_lowpart (SImode, operands[0]);
4229   operands[1] = gen_lowpart (SImode, operands[1]);
4231   /* Handle a partial overlap.  */
4232   if (rtx_equal_p (operands[0], operands[3]))
4233     {
4234       rtx tmp0 = operands[0];
4235       rtx tmp1 = operands[1];
4237       operands[0] = operands[2];
4238       operands[1] = operands[3];
4239       operands[2] = tmp0;
4240       operands[3] = tmp1;
4241     }
4242   "
4245 ;; We can't actually do base+index doubleword loads if the index and
4246 ;; destination overlap.  Split here so that we at least have chance to
4247 ;; schedule.
4248 (define_split
4249   [(set (match_operand:DI 0 "s_register_operand" "")
4250         (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4251                          (match_operand:SI 2 "s_register_operand" ""))))]
4252   "TARGET_LDRD
4253   && reg_overlap_mentioned_p (operands[0], operands[1])
4254   && reg_overlap_mentioned_p (operands[0], operands[2])"
4255   [(set (match_dup 4)
4256         (plus:SI (match_dup 1)
4257                  (match_dup 2)))
4258    (set (match_dup 0)
4259         (mem:DI (match_dup 4)))]
4260   "
4261   operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4262   "
4265 ;;; ??? This should have alternatives for constants.
4266 ;;; ??? This was originally identical to the movdf_insn pattern.
4267 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4268 ;;; thumb_reorg with a memory reference.
4269 (define_insn "*thumb_movdi_insn"
4270   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4271         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
4272   "TARGET_THUMB
4273    && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4274    && (   register_operand (operands[0], DImode)
4275        || register_operand (operands[1], DImode))"
4276   "*
4277   {
4278   switch (which_alternative)
4279     {
4280     default:
4281     case 0:
4282       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4283         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
4284       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
4285     case 1:
4286       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4287     case 2:
4288       operands[1] = GEN_INT (- INTVAL (operands[1]));
4289       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4290     case 3:
4291       return \"ldmia\\t%1, {%0, %H0}\";
4292     case 4:
4293       return \"stmia\\t%0, {%1, %H1}\";
4294     case 5:
4295       return thumb_load_double_from_address (operands);
4296     case 6:
4297       operands[2] = gen_rtx_MEM (SImode,
4298                              plus_constant (XEXP (operands[0], 0), 4));
4299       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4300       return \"\";
4301     case 7:
4302       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4303         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4304       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4305     }
4306   }"
4307   [(set_attr "length" "4,4,6,2,2,6,4,4")
4308    (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4309    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4312 (define_expand "movsi"
4313   [(set (match_operand:SI 0 "general_operand" "")
4314         (match_operand:SI 1 "general_operand" ""))]
4315   "TARGET_EITHER"
4316   "
4317   if (TARGET_ARM)
4318     {
4319       /* Everything except mem = const or mem = mem can be done easily.  */
4320       if (GET_CODE (operands[0]) == MEM)
4321         operands[1] = force_reg (SImode, operands[1]);
4322       if (arm_general_register_operand (operands[0], SImode)
4323           && GET_CODE (operands[1]) == CONST_INT
4324           && !(const_ok_for_arm (INTVAL (operands[1]))
4325                || const_ok_for_arm (~INTVAL (operands[1]))))
4326         {
4327            arm_split_constant (SET, SImode, NULL_RTX,
4328                                INTVAL (operands[1]), operands[0], NULL_RTX,
4329                                optimize && !no_new_pseudos);
4330           DONE;
4331         }
4332     }
4333   else /* TARGET_THUMB....  */
4334     {
4335       if (!no_new_pseudos)
4336         {
4337           if (GET_CODE (operands[0]) != REG)
4338             operands[1] = force_reg (SImode, operands[1]);
4339         }
4340     }
4341     
4342   if (flag_pic
4343       && (CONSTANT_P (operands[1])
4344          || symbol_mentioned_p (operands[1])
4345          || label_mentioned_p (operands[1])))
4346     operands[1] = legitimize_pic_address (operands[1], SImode,
4347                                           (no_new_pseudos ? operands[0] : 0));
4348   "
4351 (define_insn "*arm_movsi_insn"
4352   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4353         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
4354   "TARGET_ARM && ! TARGET_IWMMXT
4355    && !(TARGET_HARD_FLOAT && TARGET_VFP)
4356    && (   register_operand (operands[0], SImode)
4357        || register_operand (operands[1], SImode))"
4358   "@
4359    mov%?\\t%0, %1
4360    mvn%?\\t%0, #%B1
4361    ldr%?\\t%0, %1
4362    str%?\\t%1, %0"
4363   [(set_attr "type" "*,*,load1,store1")
4364    (set_attr "predicable" "yes")
4365    (set_attr "pool_range" "*,*,4096,*")
4366    (set_attr "neg_pool_range" "*,*,4084,*")]
4369 (define_split
4370   [(set (match_operand:SI 0 "arm_general_register_operand" "")
4371         (match_operand:SI 1 "const_int_operand" ""))]
4372   "TARGET_ARM
4373   && (!(const_ok_for_arm (INTVAL (operands[1]))
4374         || const_ok_for_arm (~INTVAL (operands[1]))))"
4375   [(clobber (const_int 0))]
4376   "
4377   arm_split_constant (SET, SImode, NULL_RTX, 
4378                       INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4379   DONE;
4380   "
4383 (define_insn "*thumb_movsi_insn"
4384   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4385         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4386   "TARGET_THUMB
4387    && (   register_operand (operands[0], SImode) 
4388        || register_operand (operands[1], SImode))"
4389   "@
4390    mov  %0, %1
4391    mov  %0, %1
4392    #
4393    #
4394    ldmia\\t%1, {%0}
4395    stmia\\t%0, {%1}
4396    ldr\\t%0, %1
4397    str\\t%1, %0
4398    mov\\t%0, %1"
4399   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4400    (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4401    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4404 (define_split 
4405   [(set (match_operand:SI 0 "register_operand" "")
4406         (match_operand:SI 1 "const_int_operand" ""))]
4407   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4408   [(set (match_dup 0) (match_dup 1))
4409    (set (match_dup 0) (neg:SI (match_dup 0)))]
4410   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4413 (define_split 
4414   [(set (match_operand:SI 0 "register_operand" "")
4415         (match_operand:SI 1 "const_int_operand" ""))]
4416   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4417   [(set (match_dup 0) (match_dup 1))
4418    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4419   "
4420   {
4421     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4422     unsigned HOST_WIDE_INT mask = 0xff;
4423     int i;
4424     
4425     for (i = 0; i < 25; i++)
4426       if ((val & (mask << i)) == val)
4427         break;
4429     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4430     if (i == 0)
4431       FAIL;
4433     operands[1] = GEN_INT (val >> i);
4434     operands[2] = GEN_INT (i);
4435   }"
4438 ;; When generating pic, we need to load the symbol offset into a register.
4439 ;; So that the optimizer does not confuse this with a normal symbol load
4440 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
4441 ;; since that is the only type of relocation we can use.
4443 ;; The rather odd constraints on the following are to force reload to leave
4444 ;; the insn alone, and to force the minipool generation pass to then move
4445 ;; the GOT symbol to memory.
4447 (define_insn "pic_load_addr_arm"
4448   [(set (match_operand:SI 0 "s_register_operand" "=r")
4449         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4450   "TARGET_ARM && flag_pic"
4451   "ldr%?\\t%0, %1"
4452   [(set_attr "type" "load1")
4453    (set (attr "pool_range")     (const_int 4096))
4454    (set (attr "neg_pool_range") (const_int 4084))]
4457 (define_insn "pic_load_addr_thumb"
4458   [(set (match_operand:SI 0 "s_register_operand" "=l")
4459         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4460   "TARGET_THUMB && flag_pic"
4461   "ldr\\t%0, %1"
4462   [(set_attr "type" "load1")
4463    (set (attr "pool_range") (const_int 1024))]
4466 ;; This variant is used for AOF assembly, since it needs to mention the
4467 ;; pic register in the rtl.
4468 (define_expand "pic_load_addr_based"
4469   [(set (match_operand:SI 0 "s_register_operand" "")
4470         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4471   "TARGET_ARM && flag_pic"
4472   "operands[2] = pic_offset_table_rtx;"
4475 (define_insn "*pic_load_addr_based_insn"
4476   [(set (match_operand:SI 0 "s_register_operand" "=r")
4477         (unspec:SI [(match_operand 1 "" "")
4478                     (match_operand 2 "s_register_operand" "r")]
4479                    UNSPEC_PIC_SYM))]
4480   "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4481   "*
4482 #ifdef AOF_ASSEMBLER
4483   operands[1] = aof_pic_entry (operands[1]);
4484 #endif
4485   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4486   return \"\";
4487   "
4488   [(set_attr "type" "load1")
4489    (set (attr "pool_range")
4490         (if_then_else (eq_attr "is_thumb" "yes")
4491                       (const_int 1024)
4492                       (const_int 4096)))
4493    (set (attr "neg_pool_range")
4494         (if_then_else (eq_attr "is_thumb" "yes")
4495                       (const_int 0)
4496                       (const_int 4084)))]
4499 (define_insn "pic_add_dot_plus_four"
4500   [(set (match_operand:SI 0 "register_operand" "+r")
4501         (unspec:SI [(plus:SI (match_dup 0)
4502                              (const (plus:SI (pc) (const_int 4))))]
4503                    UNSPEC_PIC_BASE))
4504    (use (label_ref (match_operand 1 "" "")))]
4505   "TARGET_THUMB && flag_pic"
4506   "*
4507   (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4508                              CODE_LABEL_NUMBER (operands[1]));
4509   return \"add\\t%0, %|pc\";
4510   "
4511   [(set_attr "length" "2")]
4514 (define_insn "pic_add_dot_plus_eight"
4515   [(set (match_operand:SI 0 "register_operand" "+r")
4516         (unspec:SI [(plus:SI (match_dup 0)
4517                              (const (plus:SI (pc) (const_int 8))))]
4518                    UNSPEC_PIC_BASE))
4519    (use (label_ref (match_operand 1 "" "")))]
4520   "TARGET_ARM && flag_pic"
4521   "*
4522     (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4523                                CODE_LABEL_NUMBER (operands[1]));
4524     return \"add%?\\t%0, %|pc, %0\";
4525   "
4526   [(set_attr "predicable" "yes")]
4529 (define_expand "builtin_setjmp_receiver"
4530   [(label_ref (match_operand 0 "" ""))]
4531   "flag_pic"
4532   "
4534   /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4535      register.  */
4536   arm_load_pic_register (3);
4537   DONE;
4540 ;; If copying one reg to another we can set the condition codes according to
4541 ;; its value.  Such a move is common after a return from subroutine and the
4542 ;; result is being tested against zero.
4544 (define_insn "*movsi_compare0"
4545   [(set (reg:CC CC_REGNUM)
4546         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4547                     (const_int 0)))
4548    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4549         (match_dup 1))]
4550   "TARGET_ARM"
4551   "@
4552    cmp%?\\t%0, #0
4553    sub%?s\\t%0, %1, #0"
4554   [(set_attr "conds" "set")]
4557 ;; Subroutine to store a half word from a register into memory.
4558 ;; Operand 0 is the source register (HImode)
4559 ;; Operand 1 is the destination address in a register (SImode)
4561 ;; In both this routine and the next, we must be careful not to spill
4562 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4563 ;; can generate unrecognizable rtl.
4565 (define_expand "storehi"
4566   [;; store the low byte
4567    (set (match_operand 1 "" "") (match_dup 3))
4568    ;; extract the high byte
4569    (set (match_dup 2)
4570         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4571    ;; store the high byte
4572    (set (match_dup 4) (match_dup 5))]
4573   "TARGET_ARM"
4574   "
4575   {
4576     rtx op1 = operands[1];
4577     rtx addr = XEXP (op1, 0);
4578     enum rtx_code code = GET_CODE (addr);
4580     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4581         || code == MINUS)
4582       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4584     operands[4] = adjust_address (op1, QImode, 1);
4585     operands[1] = adjust_address (operands[1], QImode, 0);
4586     operands[3] = gen_lowpart (QImode, operands[0]);
4587     operands[0] = gen_lowpart (SImode, operands[0]);
4588     operands[2] = gen_reg_rtx (SImode);
4589     operands[5] = gen_lowpart (QImode, operands[2]);
4590   }"
4593 (define_expand "storehi_bigend"
4594   [(set (match_dup 4) (match_dup 3))
4595    (set (match_dup 2)
4596         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4597    (set (match_operand 1 "" "") (match_dup 5))]
4598   "TARGET_ARM"
4599   "
4600   {
4601     rtx op1 = operands[1];
4602     rtx addr = XEXP (op1, 0);
4603     enum rtx_code code = GET_CODE (addr);
4605     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4606         || code == MINUS)
4607       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4609     operands[4] = adjust_address (op1, QImode, 1);
4610     operands[1] = adjust_address (operands[1], QImode, 0);
4611     operands[3] = gen_lowpart (QImode, operands[0]);
4612     operands[0] = gen_lowpart (SImode, operands[0]);
4613     operands[2] = gen_reg_rtx (SImode);
4614     operands[5] = gen_lowpart (QImode, operands[2]);
4615   }"
4618 ;; Subroutine to store a half word integer constant into memory.
4619 (define_expand "storeinthi"
4620   [(set (match_operand 0 "" "")
4621         (match_operand 1 "" ""))
4622    (set (match_dup 3) (match_dup 2))]
4623   "TARGET_ARM"
4624   "
4625   {
4626     HOST_WIDE_INT value = INTVAL (operands[1]);
4627     rtx addr = XEXP (operands[0], 0);
4628     rtx op0 = operands[0];
4629     enum rtx_code code = GET_CODE (addr);
4631     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4632         || code == MINUS)
4633       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4635     operands[1] = gen_reg_rtx (SImode);
4636     if (BYTES_BIG_ENDIAN)
4637       {
4638         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4639         if ((value & 255) == ((value >> 8) & 255))
4640           operands[2] = operands[1];
4641         else
4642           {
4643             operands[2] = gen_reg_rtx (SImode);
4644             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4645           }
4646       }
4647     else
4648       {
4649         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4650         if ((value & 255) == ((value >> 8) & 255))
4651           operands[2] = operands[1];
4652         else
4653           {
4654             operands[2] = gen_reg_rtx (SImode);
4655             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4656           }
4657       }
4659     operands[3] = adjust_address (op0, QImode, 1);
4660     operands[0] = adjust_address (operands[0], QImode, 0);
4661     operands[2] = gen_lowpart (QImode, operands[2]);
4662     operands[1] = gen_lowpart (QImode, operands[1]);
4663   }"
4666 (define_expand "storehi_single_op"
4667   [(set (match_operand:HI 0 "memory_operand" "")
4668         (match_operand:HI 1 "general_operand" ""))]
4669   "TARGET_ARM && arm_arch4"
4670   "
4671   if (!s_register_operand (operands[1], HImode))
4672     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4673   "
4676 (define_expand "movhi"
4677   [(set (match_operand:HI 0 "general_operand" "")
4678         (match_operand:HI 1 "general_operand" ""))]
4679   "TARGET_EITHER"
4680   "
4681   if (TARGET_ARM)
4682     {
4683       if (!no_new_pseudos)
4684         {
4685           if (GET_CODE (operands[0]) == MEM)
4686             {
4687               if (arm_arch4)
4688                 {
4689                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4690                   DONE;
4691                 }
4692               if (GET_CODE (operands[1]) == CONST_INT)
4693                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4694               else
4695                 {
4696                   if (GET_CODE (operands[1]) == MEM)
4697                     operands[1] = force_reg (HImode, operands[1]);
4698                   if (BYTES_BIG_ENDIAN)
4699                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4700                   else
4701                    emit_insn (gen_storehi (operands[1], operands[0]));
4702                 }
4703               DONE;
4704             }
4705           /* Sign extend a constant, and keep it in an SImode reg.  */
4706           else if (GET_CODE (operands[1]) == CONST_INT)
4707             {
4708               rtx reg = gen_reg_rtx (SImode);
4709               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4711               /* If the constant is already valid, leave it alone.  */
4712               if (!const_ok_for_arm (val))
4713                 {
4714                   /* If setting all the top bits will make the constant 
4715                      loadable in a single instruction, then set them.  
4716                      Otherwise, sign extend the number.  */
4718                   if (const_ok_for_arm (~(val | ~0xffff)))
4719                     val |= ~0xffff;
4720                   else if (val & 0x8000)
4721                     val |= ~0xffff;
4722                 }
4724               emit_insn (gen_movsi (reg, GEN_INT (val)));
4725               operands[1] = gen_lowpart (HImode, reg);
4726             }
4727           else if (arm_arch4 && optimize && !no_new_pseudos
4728                    && GET_CODE (operands[1]) == MEM)
4729             {
4730               rtx reg = gen_reg_rtx (SImode);
4732               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4733               operands[1] = gen_lowpart (HImode, reg);
4734             }
4735           else if (!arm_arch4)
4736             {
4737               if (GET_CODE (operands[1]) == MEM)
4738                 {
4739                   rtx base;
4740                   rtx offset = const0_rtx;
4741                   rtx reg = gen_reg_rtx (SImode);
4743                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4744                        || (GET_CODE (base) == PLUS
4745                            && (GET_CODE (offset = XEXP (base, 1))
4746                                == CONST_INT)
4747                            && ((INTVAL(offset) & 1) != 1)
4748                            && GET_CODE (base = XEXP (base, 0)) == REG))
4749                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4750                     {
4751                       HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4752                       rtx new;
4754                       new = gen_rtx_MEM (SImode,
4755                                          plus_constant (base, new_offset));
4756                       MEM_COPY_ATTRIBUTES (new, operands[1]);
4757                       emit_insn (gen_movsi (reg, new));
4758                       if (((INTVAL (offset) & 2) != 0)
4759                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4760                         {
4761                           rtx reg2 = gen_reg_rtx (SImode);
4763                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4764                           reg = reg2;
4765                         }
4766                     }
4767                   else
4768                     emit_insn (gen_movhi_bytes (reg, operands[1]));
4770                   operands[1] = gen_lowpart (HImode, reg);
4771                }
4772            }
4773         }
4774       /* Handle loading a large integer during reload.  */
4775       else if (GET_CODE (operands[1]) == CONST_INT
4776                && !const_ok_for_arm (INTVAL (operands[1]))
4777                && !const_ok_for_arm (~INTVAL (operands[1])))
4778         {
4779           /* Writing a constant to memory needs a scratch, which should
4780              be handled with SECONDARY_RELOADs.  */
4781           if (GET_CODE (operands[0]) != REG)
4782             abort ();
4784           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4785           emit_insn (gen_movsi (operands[0], operands[1]));
4786           DONE;
4787        }
4788     }
4789   else /* TARGET_THUMB */
4790     {
4791       if (!no_new_pseudos)
4792         {
4793           if (GET_CODE (operands[0]) != REG)
4794             operands[1] = force_reg (HImode, operands[1]);
4796           /* ??? We shouldn't really get invalid addresses here, but this can
4797              happen if we are passed a SP (never OK for HImode/QImode) or 
4798              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4799              HImode/QImode) relative address.  */
4800           /* ??? This should perhaps be fixed elsewhere, for instance, in
4801              fixup_stack_1, by checking for other kinds of invalid addresses,
4802              e.g. a bare reference to a virtual register.  This may confuse the
4803              alpha though, which must handle this case differently.  */
4804           if (GET_CODE (operands[0]) == MEM
4805               && !memory_address_p (GET_MODE (operands[0]),
4806                                     XEXP (operands[0], 0)))
4807             operands[0]
4808               = replace_equiv_address (operands[0],
4809                                        copy_to_reg (XEXP (operands[0], 0)));
4810    
4811           if (GET_CODE (operands[1]) == MEM
4812               && !memory_address_p (GET_MODE (operands[1]),
4813                                     XEXP (operands[1], 0)))
4814             operands[1]
4815               = replace_equiv_address (operands[1],
4816                                        copy_to_reg (XEXP (operands[1], 0)));
4817         }
4818       /* Handle loading a large integer during reload.  */
4819       else if (GET_CODE (operands[1]) == CONST_INT
4820                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4821         {
4822           /* Writing a constant to memory needs a scratch, which should
4823              be handled with SECONDARY_RELOADs.  */
4824           if (GET_CODE (operands[0]) != REG)
4825             abort ();
4827           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4828           emit_insn (gen_movsi (operands[0], operands[1]));
4829           DONE;
4830         }
4831     }
4832   "
4835 (define_insn "*thumb_movhi_insn"
4836   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4837         (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
4838   "TARGET_THUMB
4839    && (   register_operand (operands[0], HImode)
4840        || register_operand (operands[1], HImode))"
4841   "*
4842   switch (which_alternative)
4843     {
4844     case 0: return \"add        %0, %1, #0\";
4845     case 2: return \"strh       %1, %0\";
4846     case 3: return \"mov        %0, %1\";
4847     case 4: return \"mov        %0, %1\";
4848     case 5: return \"mov        %0, %1\";
4849     default: abort ();
4850     case 1:
4851       /* The stack pointer can end up being taken as an index register.
4852           Catch this case here and deal with it.  */
4853       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4854           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4855           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4856         {
4857           rtx ops[2];
4858           ops[0] = operands[0];
4859           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4860       
4861           output_asm_insn (\"mov        %0, %1\", ops);
4863           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4864     
4865         }
4866       return \"ldrh     %0, %1\";
4867     }"
4868   [(set_attr "length" "2,4,2,2,2,2")
4869    (set_attr "type" "*,load1,store1,*,*,*")]
4873 (define_expand "movhi_bytes"
4874   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4875    (set (match_dup 3)
4876         (zero_extend:SI (match_dup 6)))
4877    (set (match_operand:SI 0 "" "")
4878          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4879   "TARGET_ARM"
4880   "
4881   {
4882     rtx mem1, mem2;
4883     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4885     mem1 = gen_rtx_MEM (QImode, addr);
4886     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4887     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4888     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4889     operands[0] = gen_lowpart (SImode, operands[0]);
4890     operands[1] = mem1;
4891     operands[2] = gen_reg_rtx (SImode);
4892     operands[3] = gen_reg_rtx (SImode);
4893     operands[6] = mem2;
4895     if (BYTES_BIG_ENDIAN)
4896       {
4897         operands[4] = operands[2];
4898         operands[5] = operands[3];
4899       }
4900     else
4901       {
4902         operands[4] = operands[3];
4903         operands[5] = operands[2];
4904       }
4905   }"
4908 (define_expand "movhi_bigend"
4909   [(set (match_dup 2)
4910         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4911                    (const_int 16)))
4912    (set (match_dup 3)
4913         (ashiftrt:SI (match_dup 2) (const_int 16)))
4914    (set (match_operand:HI 0 "s_register_operand" "")
4915         (match_dup 4))]
4916   "TARGET_ARM"
4917   "
4918   operands[2] = gen_reg_rtx (SImode);
4919   operands[3] = gen_reg_rtx (SImode);
4920   operands[4] = gen_lowpart (HImode, operands[3]);
4921   "
4924 ;; Pattern to recognize insn generated default case above
4925 (define_insn "*movhi_insn_arch4"
4926   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4927         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4928   "TARGET_ARM
4929    && arm_arch4
4930    && (GET_CODE (operands[1]) != CONST_INT
4931        || const_ok_for_arm (INTVAL (operands[1]))
4932        || const_ok_for_arm (~INTVAL (operands[1])))"
4933   "@
4934    mov%?\\t%0, %1\\t%@ movhi
4935    mvn%?\\t%0, #%B1\\t%@ movhi
4936    str%?h\\t%1, %0\\t%@ movhi
4937    ldr%?h\\t%0, %1\\t%@ movhi"
4938   [(set_attr "type" "*,*,store1,load1")
4939    (set_attr "predicable" "yes")
4940    (set_attr "pool_range" "*,*,*,256")
4941    (set_attr "neg_pool_range" "*,*,*,244")]
4944 (define_insn "*movhi_bytes"
4945   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4946         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4947   "TARGET_ARM"
4948   "@
4949    mov%?\\t%0, %1\\t%@ movhi
4950    mvn%?\\t%0, #%B1\\t%@ movhi"
4951   [(set_attr "predicable" "yes")]
4954 (define_insn "thumb_movhi_clobber"
4955   [(set (match_operand:HI     0 "memory_operand"   "=m")
4956         (match_operand:HI     1 "register_operand" "l"))
4957    (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4958   "TARGET_THUMB"
4959   "*
4960   abort ();"
4962         
4963 ;; We use a DImode scratch because we may occasionally need an additional
4964 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4965 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4966 (define_expand "reload_outhi"
4967   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4968               (match_operand:HI 1 "s_register_operand"        "r")
4969               (match_operand:DI 2 "s_register_operand"        "=&l")])]
4970   "TARGET_EITHER"
4971   "if (TARGET_ARM)
4972      arm_reload_out_hi (operands);
4973    else
4974      thumb_reload_out_hi (operands);
4975   DONE;
4976   "
4979 (define_expand "reload_inhi"
4980   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4981               (match_operand:HI 1 "arm_reload_memory_operand" "o")
4982               (match_operand:DI 2 "s_register_operand" "=&r")])]
4983   "TARGET_EITHER"
4984   "
4985   if (TARGET_ARM)
4986     arm_reload_in_hi (operands);
4987   else
4988     thumb_reload_out_hi (operands);
4989   DONE;
4992 (define_expand "movqi"
4993   [(set (match_operand:QI 0 "general_operand" "")
4994         (match_operand:QI 1 "general_operand" ""))]
4995   "TARGET_EITHER"
4996   "
4997   if (TARGET_ARM)
4998     {
4999       /* Everything except mem = const or mem = mem can be done easily */
5001       if (!no_new_pseudos)
5002         {
5003           if (GET_CODE (operands[1]) == CONST_INT)
5004             {
5005               rtx reg = gen_reg_rtx (SImode);
5007               emit_insn (gen_movsi (reg, operands[1]));
5008               operands[1] = gen_lowpart (QImode, reg);
5009             }
5010           if (GET_CODE (operands[1]) == MEM && optimize > 0)
5011             {
5012               rtx reg = gen_reg_rtx (SImode);
5014               emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5015               operands[1] = gen_lowpart (QImode, reg);
5016             }
5017           if (GET_CODE (operands[0]) == MEM)
5018             operands[1] = force_reg (QImode, operands[1]);
5019         }
5020     }
5021   else /* TARGET_THUMB */
5022     {
5023       if (!no_new_pseudos)
5024         {
5025           if (GET_CODE (operands[0]) != REG)
5026             operands[1] = force_reg (QImode, operands[1]);
5028           /* ??? We shouldn't really get invalid addresses here, but this can
5029              happen if we are passed a SP (never OK for HImode/QImode) or
5030              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
5031              HImode/QImode) relative address.  */
5032           /* ??? This should perhaps be fixed elsewhere, for instance, in
5033              fixup_stack_1, by checking for other kinds of invalid addresses,
5034              e.g. a bare reference to a virtual register.  This may confuse the
5035              alpha though, which must handle this case differently.  */
5036           if (GET_CODE (operands[0]) == MEM
5037               && !memory_address_p (GET_MODE (operands[0]),
5038                                      XEXP (operands[0], 0)))
5039             operands[0]
5040               = replace_equiv_address (operands[0],
5041                                        copy_to_reg (XEXP (operands[0], 0)));
5042           if (GET_CODE (operands[1]) == MEM
5043               && !memory_address_p (GET_MODE (operands[1]),
5044                                     XEXP (operands[1], 0)))
5045              operands[1]
5046                = replace_equiv_address (operands[1],
5047                                         copy_to_reg (XEXP (operands[1], 0)));
5048         }
5049       /* Handle loading a large integer during reload.  */
5050       else if (GET_CODE (operands[1]) == CONST_INT
5051                && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
5052         {
5053           /* Writing a constant to memory needs a scratch, which should
5054              be handled with SECONDARY_RELOADs.  */
5055           if (GET_CODE (operands[0]) != REG)
5056             abort ();
5058           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5059           emit_insn (gen_movsi (operands[0], operands[1]));
5060           DONE;
5061        }
5062     }
5063   "
5067 (define_insn "*arm_movqi_insn"
5068   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5069         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5070   "TARGET_ARM
5071    && (   register_operand (operands[0], QImode)
5072        || register_operand (operands[1], QImode))"
5073   "@
5074    mov%?\\t%0, %1
5075    mvn%?\\t%0, #%B1
5076    ldr%?b\\t%0, %1
5077    str%?b\\t%1, %0"
5078   [(set_attr "type" "*,*,load1,store1")
5079    (set_attr "predicable" "yes")]
5082 (define_insn "*thumb_movqi_insn"
5083   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5084         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
5085   "TARGET_THUMB
5086    && (   register_operand (operands[0], QImode)
5087        || register_operand (operands[1], QImode))"
5088   "@
5089    add\\t%0, %1, #0
5090    ldrb\\t%0, %1
5091    strb\\t%1, %0
5092    mov\\t%0, %1
5093    mov\\t%0, %1
5094    mov\\t%0, %1"
5095   [(set_attr "length" "2")
5096    (set_attr "type" "*,load1,store1,*,*,*")
5097    (set_attr "pool_range" "*,32,*,*,*,*")]
5100 (define_expand "movsf"
5101   [(set (match_operand:SF 0 "general_operand" "")
5102         (match_operand:SF 1 "general_operand" ""))]
5103   "TARGET_EITHER"
5104   "
5105   if (TARGET_ARM)
5106     {
5107       if (GET_CODE (operands[0]) == MEM)
5108         operands[1] = force_reg (SFmode, operands[1]);
5109     }
5110   else /* TARGET_THUMB */
5111     {
5112       if (!no_new_pseudos)
5113         {
5114            if (GET_CODE (operands[0]) != REG)
5115              operands[1] = force_reg (SFmode, operands[1]);
5116         }
5117     }
5118   "
5121 (define_split
5122   [(set (match_operand:SF 0 "nonimmediate_operand" "")
5123         (match_operand:SF 1 "immediate_operand" ""))]
5124   "TARGET_ARM
5125    && !(TARGET_HARD_FLOAT && TARGET_FPA)
5126    && reload_completed
5127    && GET_CODE (operands[1]) == CONST_DOUBLE"
5128   [(set (match_dup 2) (match_dup 3))]
5129   "
5130   operands[2] = gen_lowpart (SImode, operands[0]);
5131   operands[3] = gen_lowpart (SImode, operands[1]);
5132   if (operands[2] == 0 || operands[3] == 0)
5133     FAIL;
5134   "
5137 (define_insn "*arm_movsf_soft_insn"
5138   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5139         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
5140   "TARGET_ARM
5141    && TARGET_SOFT_FLOAT
5142    && (GET_CODE (operands[0]) != MEM
5143        || register_operand (operands[1], SFmode))"
5144   "@
5145    mov%?\\t%0, %1
5146    ldr%?\\t%0, %1\\t%@ float
5147    str%?\\t%1, %0\\t%@ float"
5148   [(set_attr "length" "4,4,4")
5149    (set_attr "predicable" "yes")
5150    (set_attr "type" "*,load1,store1")
5151    (set_attr "pool_range" "*,4096,*")
5152    (set_attr "neg_pool_range" "*,4084,*")]
5155 ;;; ??? This should have alternatives for constants.
5156 (define_insn "*thumb_movsf_insn"
5157   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5158         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5159   "TARGET_THUMB
5160    && (   register_operand (operands[0], SFmode) 
5161        || register_operand (operands[1], SFmode))"
5162   "@
5163    add\\t%0, %1, #0
5164    ldmia\\t%1, {%0}
5165    stmia\\t%0, {%1}
5166    ldr\\t%0, %1
5167    str\\t%1, %0
5168    mov\\t%0, %1
5169    mov\\t%0, %1"
5170   [(set_attr "length" "2")
5171    (set_attr "type" "*,load1,store1,load1,store1,*,*")
5172    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5175 (define_expand "movdf"
5176   [(set (match_operand:DF 0 "general_operand" "")
5177         (match_operand:DF 1 "general_operand" ""))]
5178   "TARGET_EITHER"
5179   "
5180   if (TARGET_ARM)
5181     {
5182       if (GET_CODE (operands[0]) == MEM)
5183         operands[1] = force_reg (DFmode, operands[1]);
5184     }
5185   else /* TARGET_THUMB */
5186     {
5187       if (!no_new_pseudos)
5188         {
5189           if (GET_CODE (operands[0]) != REG)
5190             operands[1] = force_reg (DFmode, operands[1]);
5191         }
5192     }
5193   "
5196 ;; Reloading a df mode value stored in integer regs to memory can require a
5197 ;; scratch reg.
5198 (define_expand "reload_outdf"
5199   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5200    (match_operand:DF 1 "s_register_operand" "r")
5201    (match_operand:SI 2 "s_register_operand" "=&r")]
5202   "TARGET_ARM"
5203   "
5204   {
5205     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5207     if (code == REG)
5208       operands[2] = XEXP (operands[0], 0);
5209     else if (code == POST_INC || code == PRE_DEC)
5210       {
5211         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5212         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5213         emit_insn (gen_movdi (operands[0], operands[1]));
5214         DONE;
5215       }
5216     else if (code == PRE_INC)
5217       {
5218         rtx reg = XEXP (XEXP (operands[0], 0), 0);
5220         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5221         operands[2] = reg;
5222       }
5223     else if (code == POST_DEC)
5224       operands[2] = XEXP (XEXP (operands[0], 0), 0);
5225     else
5226       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5227                              XEXP (XEXP (operands[0], 0), 1)));
5229     emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5230                             operands[1]));
5232     if (code == POST_DEC)
5233       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5235     DONE;
5236   }"
5239 (define_insn "*movdf_soft_insn"
5240   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5241         (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
5242   "TARGET_ARM && TARGET_SOFT_FLOAT
5243   "
5244   "*
5245   switch (which_alternative)
5246     {
5247     case 0:
5248     case 1:
5249     case 2:
5250       return \"#\";
5251     default:
5252       return output_move_double (operands);
5253     }
5254   "
5255   [(set_attr "length" "8,12,16,8,8")
5256    (set_attr "type" "*,*,*,load2,store2")
5257    (set_attr "pool_range" "1020")
5258    (set_attr "neg_pool_range" "1008")]
5261 ;;; ??? This should have alternatives for constants.
5262 ;;; ??? This was originally identical to the movdi_insn pattern.
5263 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5264 ;;; thumb_reorg with a memory reference.
5265 (define_insn "*thumb_movdf_insn"
5266   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5267         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5268   "TARGET_THUMB
5269    && (   register_operand (operands[0], DFmode)
5270        || register_operand (operands[1], DFmode))"
5271   "*
5272   switch (which_alternative)
5273     {
5274     default:
5275     case 0:
5276       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5277         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5278       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5279     case 1:
5280       return \"ldmia\\t%1, {%0, %H0}\";
5281     case 2:
5282       return \"stmia\\t%0, {%1, %H1}\";
5283     case 3:
5284       return thumb_load_double_from_address (operands);
5285     case 4:
5286       operands[2] = gen_rtx_MEM (SImode,
5287                                  plus_constant (XEXP (operands[0], 0), 4));
5288       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5289       return \"\";
5290     case 5:
5291       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5292         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5293       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5294     }
5295   "
5296   [(set_attr "length" "4,2,2,6,4,4")
5297    (set_attr "type" "*,load2,store2,load2,store2,*")
5298    (set_attr "pool_range" "*,*,*,1020,*,*")]
5301 (define_expand "movxf"
5302   [(set (match_operand:XF 0 "general_operand" "")
5303         (match_operand:XF 1 "general_operand" ""))]
5304   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
5305   "
5306   if (GET_CODE (operands[0]) == MEM)
5307     operands[1] = force_reg (XFmode, operands[1]);
5308   "
5311 ;; Vector Moves
5312 (define_expand "movv2si"
5313   [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5314         (match_operand:V2SI 1 "general_operand" ""))]
5315   "TARGET_REALLY_IWMMXT"
5319 (define_expand "movv4hi"
5320   [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5321         (match_operand:V4HI 1 "general_operand" ""))]
5322   "TARGET_REALLY_IWMMXT"
5326 (define_expand "movv8qi"
5327   [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5328         (match_operand:V8QI 1 "general_operand" ""))]
5329   "TARGET_REALLY_IWMMXT"
5334 ;; load- and store-multiple insns
5335 ;; The arm can load/store any set of registers, provided that they are in
5336 ;; ascending order; but that is beyond GCC so stick with what it knows.
5338 (define_expand "load_multiple"
5339   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5340                           (match_operand:SI 1 "" ""))
5341                      (use (match_operand:SI 2 "" ""))])]
5342   "TARGET_ARM"
5344   HOST_WIDE_INT offset = 0;
5346   /* Support only fixed point registers.  */
5347   if (GET_CODE (operands[2]) != CONST_INT
5348       || INTVAL (operands[2]) > 14
5349       || INTVAL (operands[2]) < 2
5350       || GET_CODE (operands[1]) != MEM
5351       || GET_CODE (operands[0]) != REG
5352       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5353       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5354     FAIL;
5356   operands[3]
5357     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5358                              force_reg (SImode, XEXP (operands[1], 0)),
5359                              TRUE, FALSE, operands[1], &offset);
5362 ;; Load multiple with write-back
5364 (define_insn "*ldmsi_postinc4"
5365   [(match_parallel 0 "load_multiple_operation"
5366     [(set (match_operand:SI 1 "s_register_operand" "=r")
5367           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5368                    (const_int 16)))
5369      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5370           (mem:SI (match_dup 2)))
5371      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5372           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5373      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5374           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5375      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5376           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5377   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5378   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5379   [(set_attr "type" "load4")
5380    (set_attr "predicable" "yes")]
5383 (define_insn "*ldmsi_postinc4_thumb"
5384   [(match_parallel 0 "load_multiple_operation"
5385     [(set (match_operand:SI 1 "s_register_operand" "=l")
5386           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5387                    (const_int 16)))
5388      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5389           (mem:SI (match_dup 2)))
5390      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5391           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5392      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5393           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5394      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5395           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5396   "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5397   "ldmia\\t%1!, {%3, %4, %5, %6}"
5398   [(set_attr "type" "load4")]
5401 (define_insn "*ldmsi_postinc3"
5402   [(match_parallel 0 "load_multiple_operation"
5403     [(set (match_operand:SI 1 "s_register_operand" "=r")
5404           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5405                    (const_int 12)))
5406      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5407           (mem:SI (match_dup 2)))
5408      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5409           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5410      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5411           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5412   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5413   "ldm%?ia\\t%1!, {%3, %4, %5}"
5414   [(set_attr "type" "load3")
5415    (set_attr "predicable" "yes")]
5418 (define_insn "*ldmsi_postinc2"
5419   [(match_parallel 0 "load_multiple_operation"
5420     [(set (match_operand:SI 1 "s_register_operand" "=r")
5421           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5422                    (const_int 8)))
5423      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5424           (mem:SI (match_dup 2)))
5425      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5426           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5427   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5428   "ldm%?ia\\t%1!, {%3, %4}"
5429   [(set_attr "type" "load2")
5430    (set_attr "predicable" "yes")]
5433 ;; Ordinary load multiple
5435 (define_insn "*ldmsi4"
5436   [(match_parallel 0 "load_multiple_operation"
5437     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5438           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5439      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5440           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5441      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5442           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5443      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5444           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5445   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5446   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5447   [(set_attr "type" "load4")
5448    (set_attr "predicable" "yes")]
5451 (define_insn "*ldmsi3"
5452   [(match_parallel 0 "load_multiple_operation"
5453     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5454           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5455      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5456           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5457      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5458           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5459   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5460   "ldm%?ia\\t%1, {%2, %3, %4}"
5461   [(set_attr "type" "load3")
5462    (set_attr "predicable" "yes")]
5465 (define_insn "*ldmsi2"
5466   [(match_parallel 0 "load_multiple_operation"
5467     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5468           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5469      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5470           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5471   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5472   "ldm%?ia\\t%1, {%2, %3}"
5473   [(set_attr "type" "load2")
5474    (set_attr "predicable" "yes")]
5477 (define_expand "store_multiple"
5478   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5479                           (match_operand:SI 1 "" ""))
5480                      (use (match_operand:SI 2 "" ""))])]
5481   "TARGET_ARM"
5483   HOST_WIDE_INT offset = 0;
5485   /* Support only fixed point registers.  */
5486   if (GET_CODE (operands[2]) != CONST_INT
5487       || INTVAL (operands[2]) > 14
5488       || INTVAL (operands[2]) < 2
5489       || GET_CODE (operands[1]) != REG
5490       || GET_CODE (operands[0]) != MEM
5491       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5492       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5493     FAIL;
5495   operands[3]
5496     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5497                               force_reg (SImode, XEXP (operands[0], 0)),
5498                               TRUE, FALSE, operands[0], &offset);
5501 ;; Store multiple with write-back
5503 (define_insn "*stmsi_postinc4"
5504   [(match_parallel 0 "store_multiple_operation"
5505     [(set (match_operand:SI 1 "s_register_operand" "=r")
5506           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5507                    (const_int 16)))
5508      (set (mem:SI (match_dup 2))
5509           (match_operand:SI 3 "arm_hard_register_operand" ""))
5510      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5511           (match_operand:SI 4 "arm_hard_register_operand" ""))
5512      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5513           (match_operand:SI 5 "arm_hard_register_operand" ""))
5514      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5515           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5516   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5517   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5518   [(set_attr "predicable" "yes")
5519    (set_attr "type" "store4")]
5522 (define_insn "*stmsi_postinc4_thumb"
5523   [(match_parallel 0 "store_multiple_operation"
5524     [(set (match_operand:SI 1 "s_register_operand" "=l")
5525           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5526                    (const_int 16)))
5527      (set (mem:SI (match_dup 2))
5528           (match_operand:SI 3 "arm_hard_register_operand" ""))
5529      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5530           (match_operand:SI 4 "arm_hard_register_operand" ""))
5531      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5532           (match_operand:SI 5 "arm_hard_register_operand" ""))
5533      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5534           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5535   "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5536   "stmia\\t%1!, {%3, %4, %5, %6}"
5537   [(set_attr "type" "store4")]
5540 (define_insn "*stmsi_postinc3"
5541   [(match_parallel 0 "store_multiple_operation"
5542     [(set (match_operand:SI 1 "s_register_operand" "=r")
5543           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5544                    (const_int 12)))
5545      (set (mem:SI (match_dup 2))
5546           (match_operand:SI 3 "arm_hard_register_operand" ""))
5547      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5548           (match_operand:SI 4 "arm_hard_register_operand" ""))
5549      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5550           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5551   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5552   "stm%?ia\\t%1!, {%3, %4, %5}"
5553   [(set_attr "predicable" "yes")
5554    (set_attr "type" "store3")]
5557 (define_insn "*stmsi_postinc2"
5558   [(match_parallel 0 "store_multiple_operation"
5559     [(set (match_operand:SI 1 "s_register_operand" "=r")
5560           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5561                    (const_int 8)))
5562      (set (mem:SI (match_dup 2))
5563           (match_operand:SI 3 "arm_hard_register_operand" ""))
5564      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5565           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5566   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5567   "stm%?ia\\t%1!, {%3, %4}"
5568   [(set_attr "predicable" "yes")
5569    (set_attr "type" "store2")]
5572 ;; Ordinary store multiple
5574 (define_insn "*stmsi4"
5575   [(match_parallel 0 "store_multiple_operation"
5576     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5577           (match_operand:SI 2 "arm_hard_register_operand" ""))
5578      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5579           (match_operand:SI 3 "arm_hard_register_operand" ""))
5580      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5581           (match_operand:SI 4 "arm_hard_register_operand" ""))
5582      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5583           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5584   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5585   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5586   [(set_attr "predicable" "yes")
5587    (set_attr "type" "store4")]
5590 (define_insn "*stmsi3"
5591   [(match_parallel 0 "store_multiple_operation"
5592     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5593           (match_operand:SI 2 "arm_hard_register_operand" ""))
5594      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5595           (match_operand:SI 3 "arm_hard_register_operand" ""))
5596      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5597           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5598   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5599   "stm%?ia\\t%1, {%2, %3, %4}"
5600   [(set_attr "predicable" "yes")
5601    (set_attr "type" "store3")]
5604 (define_insn "*stmsi2"
5605   [(match_parallel 0 "store_multiple_operation"
5606     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5607           (match_operand:SI 2 "arm_hard_register_operand" ""))
5608      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5609           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5610   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5611   "stm%?ia\\t%1, {%2, %3}"
5612   [(set_attr "predicable" "yes")
5613    (set_attr "type" "store2")]
5616 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5617 ;; We could let this apply for blocks of less than this, but it clobbers so
5618 ;; many registers that there is then probably a better way.
5620 (define_expand "movmemqi"
5621   [(match_operand:BLK 0 "general_operand" "")
5622    (match_operand:BLK 1 "general_operand" "")
5623    (match_operand:SI 2 "const_int_operand" "")
5624    (match_operand:SI 3 "const_int_operand" "")]
5625   "TARGET_EITHER"
5626   "
5627   if (TARGET_ARM)
5628     {
5629       if (arm_gen_movmemqi (operands))
5630         DONE;
5631       FAIL;
5632     }
5633   else /* TARGET_THUMB */
5634     {
5635       if (   INTVAL (operands[3]) != 4
5636           || INTVAL (operands[2]) > 48)
5637         FAIL;
5639       thumb_expand_movmemqi (operands);
5640       DONE;
5641     }
5642   "
5645 ;; Thumb block-move insns
5647 (define_insn "movmem12b"
5648   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5649         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5650    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5651         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5652    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5653         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5654    (set (match_operand:SI 0 "register_operand" "=l")
5655         (plus:SI (match_dup 2) (const_int 12)))
5656    (set (match_operand:SI 1 "register_operand" "=l")
5657         (plus:SI (match_dup 3) (const_int 12)))
5658    (clobber (match_scratch:SI 4 "=&l"))
5659    (clobber (match_scratch:SI 5 "=&l"))
5660    (clobber (match_scratch:SI 6 "=&l"))]
5661   "TARGET_THUMB"
5662   "* return thumb_output_move_mem_multiple (3, operands);"
5663   [(set_attr "length" "4")
5664    ; This isn't entirely accurate...  It loads as well, but in terms of
5665    ; scheduling the following insn it is better to consider it as a store
5666    (set_attr "type" "store3")]
5669 (define_insn "movmem8b"
5670   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5671         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5672    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5673         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5674    (set (match_operand:SI 0 "register_operand" "=l")
5675         (plus:SI (match_dup 2) (const_int 8)))
5676    (set (match_operand:SI 1 "register_operand" "=l")
5677         (plus:SI (match_dup 3) (const_int 8)))
5678    (clobber (match_scratch:SI 4 "=&l"))
5679    (clobber (match_scratch:SI 5 "=&l"))]
5680   "TARGET_THUMB"
5681   "* return thumb_output_move_mem_multiple (2, operands);"
5682   [(set_attr "length" "4")
5683    ; This isn't entirely accurate...  It loads as well, but in terms of
5684    ; scheduling the following insn it is better to consider it as a store
5685    (set_attr "type" "store2")]
5690 ;; Compare & branch insns
5691 ;; The range calculations are based as follows:
5692 ;; For forward branches, the address calculation returns the address of
5693 ;; the next instruction.  This is 2 beyond the branch instruction.
5694 ;; For backward branches, the address calculation returns the address of
5695 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5696 ;; instruction for the shortest sequence, and 4 before the branch instruction
5697 ;; if we have to jump around an unconditional branch.
5698 ;; To the basic branch range the PC offset must be added (this is +4).
5699 ;; So for forward branches we have 
5700 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5701 ;; And for backward branches we have 
5702 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5704 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5705 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5707 (define_expand "cbranchsi4"
5708   [(set (pc) (if_then_else
5709               (match_operator 0 "arm_comparison_operator"
5710                [(match_operand:SI 1 "s_register_operand" "")
5711                 (match_operand:SI 2 "nonmemory_operand" "")])
5712               (label_ref (match_operand 3 "" ""))
5713               (pc)))]
5714   "TARGET_THUMB"
5715   "
5716   if (thumb_cmpneg_operand (operands[2], SImode))
5717     {
5718       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5719                                               operands[3], operands[0]));
5720       DONE;
5721     }
5722   if (!thumb_cmp_operand (operands[2], SImode))
5723     operands[2] = force_reg (SImode, operands[2]);
5724   ")
5726 (define_insn "*cbranchsi4_insn"
5727   [(set (pc) (if_then_else
5728               (match_operator 0 "arm_comparison_operator"
5729                [(match_operand:SI 1 "s_register_operand" "l,*h")
5730                 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5731               (label_ref (match_operand 3 "" ""))
5732               (pc)))]
5733   "TARGET_THUMB"
5734   "*
5735   output_asm_insn (\"cmp\\t%1, %2\", operands);
5737   switch (get_attr_length (insn))
5738     {
5739     case 4:  return \"b%d0\\t%l3\";
5740     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5741     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5742     }
5743   "
5744   [(set (attr "far_jump")
5745         (if_then_else
5746             (eq_attr "length" "8")
5747             (const_string "yes")
5748             (const_string "no")))
5749    (set (attr "length") 
5750         (if_then_else
5751             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5752                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5753             (const_int 4)
5754             (if_then_else
5755                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5756                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5757                 (const_int 6)
5758                 (const_int 8))))]
5761 (define_insn "cbranchsi4_scratch"
5762   [(set (pc) (if_then_else
5763               (match_operator 4 "arm_comparison_operator"
5764                [(match_operand:SI 1 "s_register_operand" "l,0")
5765                 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5766               (label_ref (match_operand 3 "" ""))
5767               (pc)))
5768    (clobber (match_scratch:SI 0 "=l,l"))]
5769   "TARGET_THUMB"
5770   "*
5771   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5773   switch (get_attr_length (insn))
5774     {
5775     case 4:  return \"b%d4\\t%l3\";
5776     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5777     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5778     }
5779   "
5780   [(set (attr "far_jump")
5781         (if_then_else
5782             (eq_attr "length" "8")
5783             (const_string "yes")
5784             (const_string "no")))
5785    (set (attr "length") 
5786         (if_then_else
5787             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5788                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5789             (const_int 4)
5790             (if_then_else
5791                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5792                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5793                 (const_int 6)
5794                 (const_int 8))))]
5796 (define_insn "*movsi_cbranchsi4"
5797   [(set (pc)
5798         (if_then_else
5799          (match_operator 3 "arm_comparison_operator"
5800           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5801            (const_int 0)])
5802          (label_ref (match_operand 2 "" ""))
5803          (pc)))
5804    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5805         (match_dup 1))]
5806   "TARGET_THUMB"
5807   "*{
5808   if (which_alternative == 0)
5809     output_asm_insn (\"cmp\t%0, #0\", operands);
5810   else if (which_alternative == 1)
5811     output_asm_insn (\"sub\t%0, %1, #0\", operands);
5812   else
5813     {
5814       output_asm_insn (\"cmp\t%1, #0\", operands);
5815       if (which_alternative == 2)
5816         output_asm_insn (\"mov\t%0, %1\", operands);
5817       else
5818         output_asm_insn (\"str\t%1, %0\", operands);
5819     }
5820   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5821     {
5822     case 4:  return \"b%d3\\t%l2\";
5823     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5824     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5825     }
5826   }"
5827   [(set (attr "far_jump")
5828         (if_then_else
5829             (ior (and (gt (symbol_ref ("which_alternative"))
5830                           (const_int 1))
5831                       (eq_attr "length" "8"))
5832                  (eq_attr "length" "10"))
5833             (const_string "yes")
5834             (const_string "no")))
5835    (set (attr "length")
5836      (if_then_else
5837        (le (symbol_ref ("which_alternative"))
5838                        (const_int 1))
5839        (if_then_else
5840          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5841               (le (minus (match_dup 2) (pc)) (const_int 256)))
5842          (const_int 4)
5843          (if_then_else
5844            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5845                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5846            (const_int 6)
5847            (const_int 8)))
5848        (if_then_else
5849          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5850               (le (minus (match_dup 2) (pc)) (const_int 256)))
5851          (const_int 6)
5852          (if_then_else
5853            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5854                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5855            (const_int 8)
5856            (const_int 10)))))]
5859 (define_insn "*negated_cbranchsi4"
5860   [(set (pc)
5861         (if_then_else
5862          (match_operator 0 "equality_operator"
5863           [(match_operand:SI 1 "s_register_operand" "l")
5864            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5865          (label_ref (match_operand 3 "" ""))
5866          (pc)))]
5867   "TARGET_THUMB"
5868   "*
5869   output_asm_insn (\"cmn\\t%1, %2\", operands);
5870   switch (get_attr_length (insn))
5871     {
5872     case 4:  return \"b%d0\\t%l3\";
5873     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5874     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5875     }
5876   "
5877   [(set (attr "far_jump")
5878         (if_then_else
5879             (eq_attr "length" "8")
5880             (const_string "yes")
5881             (const_string "no")))
5882    (set (attr "length") 
5883         (if_then_else
5884             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5885                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5886             (const_int 4)
5887             (if_then_else
5888                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5889                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5890                 (const_int 6)
5891                 (const_int 8))))]
5894 (define_insn "*tbit_cbranch"
5895   [(set (pc)
5896         (if_then_else
5897          (match_operator 0 "equality_operator"
5898           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5899                             (const_int 1)
5900                             (match_operand:SI 2 "const_int_operand" "i"))
5901            (const_int 0)])
5902          (label_ref (match_operand 3 "" ""))
5903          (pc)))
5904    (clobber (match_scratch:SI 4 "=l"))]
5905   "TARGET_THUMB"
5906   "*
5907   {
5908   rtx op[3];
5909   op[0] = operands[4];
5910   op[1] = operands[1];
5911   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5913   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5914   switch (get_attr_length (insn))
5915     {
5916     case 4:  return \"b%d0\\t%l3\";
5917     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5918     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5919     }
5920   }"
5921   [(set (attr "far_jump")
5922         (if_then_else
5923             (eq_attr "length" "8")
5924             (const_string "yes")
5925             (const_string "no")))
5926    (set (attr "length") 
5927         (if_then_else
5928             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5929                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5930             (const_int 4)
5931             (if_then_else
5932                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5933                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5934                 (const_int 6)
5935                 (const_int 8))))]
5937   
5938 (define_insn "*tstsi3_cbranch"
5939   [(set (pc)
5940         (if_then_else
5941          (match_operator 3 "equality_operator"
5942           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5943                    (match_operand:SI 1 "s_register_operand" "l"))
5944            (const_int 0)])
5945          (label_ref (match_operand 2 "" ""))
5946          (pc)))]
5947   "TARGET_THUMB"
5948   "*
5949   {
5950   output_asm_insn (\"tst\\t%0, %1\", operands);
5951   switch (get_attr_length (insn))
5952     {
5953     case 4:  return \"b%d3\\t%l2\";
5954     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5955     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5956     }
5957   }"
5958   [(set (attr "far_jump")
5959         (if_then_else
5960             (eq_attr "length" "8")
5961             (const_string "yes")
5962             (const_string "no")))
5963    (set (attr "length") 
5964         (if_then_else
5965             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5966                  (le (minus (match_dup 2) (pc)) (const_int 256)))
5967             (const_int 4)
5968             (if_then_else
5969                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5970                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
5971                 (const_int 6)
5972                 (const_int 8))))]
5974   
5975 (define_insn "*andsi3_cbranch"
5976   [(set (pc)
5977         (if_then_else
5978          (match_operator 5 "equality_operator"
5979           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5980                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5981            (const_int 0)])
5982          (label_ref (match_operand 4 "" ""))
5983          (pc)))
5984    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5985         (and:SI (match_dup 2) (match_dup 3)))
5986    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5987   "TARGET_THUMB"
5988   "*
5989   {
5990   if (which_alternative == 0)
5991     output_asm_insn (\"and\\t%0, %3\", operands);
5992   else if (which_alternative == 1)
5993     {
5994       output_asm_insn (\"and\\t%1, %3\", operands);
5995       output_asm_insn (\"mov\\t%0, %1\", operands);
5996     }
5997   else
5998     {
5999       output_asm_insn (\"and\\t%1, %3\", operands);
6000       output_asm_insn (\"str\\t%1, %0\", operands);
6001     }
6003   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6004     {
6005     case 4:  return \"b%d5\\t%l4\";
6006     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6007     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6008     }
6009   }"
6010   [(set (attr "far_jump")
6011         (if_then_else
6012             (ior (and (eq (symbol_ref ("which_alternative"))
6013                           (const_int 0))
6014                       (eq_attr "length" "8"))
6015                  (eq_attr "length" "10"))
6016             (const_string "yes")
6017             (const_string "no")))
6018    (set (attr "length")
6019      (if_then_else
6020        (eq (symbol_ref ("which_alternative"))
6021                        (const_int 0))
6022        (if_then_else
6023          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6024               (le (minus (match_dup 4) (pc)) (const_int 256)))
6025          (const_int 4)
6026          (if_then_else
6027            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6028                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6029            (const_int 6)
6030            (const_int 8)))
6031        (if_then_else
6032          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6033               (le (minus (match_dup 4) (pc)) (const_int 256)))
6034          (const_int 6)
6035          (if_then_else
6036            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6037                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6038            (const_int 8)
6039            (const_int 10)))))]
6042 (define_insn "*orrsi3_cbranch_scratch"
6043   [(set (pc)
6044         (if_then_else
6045          (match_operator 4 "equality_operator"
6046           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6047                    (match_operand:SI 2 "s_register_operand" "l"))
6048            (const_int 0)])
6049          (label_ref (match_operand 3 "" ""))
6050          (pc)))
6051    (clobber (match_scratch:SI 0 "=l"))]
6052   "TARGET_THUMB"
6053   "*
6054   {
6055   output_asm_insn (\"orr\\t%0, %2\", operands);
6056   switch (get_attr_length (insn))
6057     {
6058     case 4:  return \"b%d4\\t%l3\";
6059     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6060     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6061     }
6062   }"
6063   [(set (attr "far_jump")
6064         (if_then_else
6065             (eq_attr "length" "8")
6066             (const_string "yes")
6067             (const_string "no")))
6068    (set (attr "length") 
6069         (if_then_else
6070             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6071                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6072             (const_int 4)
6073             (if_then_else
6074                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6075                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6076                 (const_int 6)
6077                 (const_int 8))))]
6079   
6080 (define_insn "*orrsi3_cbranch"
6081   [(set (pc)
6082         (if_then_else
6083          (match_operator 5 "equality_operator"
6084           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6085                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6086            (const_int 0)])
6087          (label_ref (match_operand 4 "" ""))
6088          (pc)))
6089    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6090         (ior:SI (match_dup 2) (match_dup 3)))
6091    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6092   "TARGET_THUMB"
6093   "*
6094   {
6095   if (which_alternative == 0)
6096     output_asm_insn (\"orr\\t%0, %3\", operands);
6097   else if (which_alternative == 1)
6098     {
6099       output_asm_insn (\"orr\\t%1, %3\", operands);
6100       output_asm_insn (\"mov\\t%0, %1\", operands);
6101     }
6102   else
6103     {
6104       output_asm_insn (\"orr\\t%1, %3\", operands);
6105       output_asm_insn (\"str\\t%1, %0\", operands);
6106     }
6108   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6109     {
6110     case 4:  return \"b%d5\\t%l4\";
6111     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6112     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6113     }
6114   }"
6115   [(set (attr "far_jump")
6116         (if_then_else
6117             (ior (and (eq (symbol_ref ("which_alternative"))
6118                           (const_int 0))
6119                       (eq_attr "length" "8"))
6120                  (eq_attr "length" "10"))
6121             (const_string "yes")
6122             (const_string "no")))
6123    (set (attr "length")
6124      (if_then_else
6125        (eq (symbol_ref ("which_alternative"))
6126                        (const_int 0))
6127        (if_then_else
6128          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6129               (le (minus (match_dup 4) (pc)) (const_int 256)))
6130          (const_int 4)
6131          (if_then_else
6132            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6133                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6134            (const_int 6)
6135            (const_int 8)))
6136        (if_then_else
6137          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6138               (le (minus (match_dup 4) (pc)) (const_int 256)))
6139          (const_int 6)
6140          (if_then_else
6141            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6142                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6143            (const_int 8)
6144            (const_int 10)))))]
6147 (define_insn "*xorsi3_cbranch_scratch"
6148   [(set (pc)
6149         (if_then_else
6150          (match_operator 4 "equality_operator"
6151           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6152                    (match_operand:SI 2 "s_register_operand" "l"))
6153            (const_int 0)])
6154          (label_ref (match_operand 3 "" ""))
6155          (pc)))
6156    (clobber (match_scratch:SI 0 "=l"))]
6157   "TARGET_THUMB"
6158   "*
6159   {
6160   output_asm_insn (\"eor\\t%0, %2\", operands);
6161   switch (get_attr_length (insn))
6162     {
6163     case 4:  return \"b%d4\\t%l3\";
6164     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6165     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6166     }
6167   }"
6168   [(set (attr "far_jump")
6169         (if_then_else
6170             (eq_attr "length" "8")
6171             (const_string "yes")
6172             (const_string "no")))
6173    (set (attr "length") 
6174         (if_then_else
6175             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6176                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6177             (const_int 4)
6178             (if_then_else
6179                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6180                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6181                 (const_int 6)
6182                 (const_int 8))))]
6184   
6185 (define_insn "*xorsi3_cbranch"
6186   [(set (pc)
6187         (if_then_else
6188          (match_operator 5 "equality_operator"
6189           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6190                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6191            (const_int 0)])
6192          (label_ref (match_operand 4 "" ""))
6193          (pc)))
6194    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6195         (xor:SI (match_dup 2) (match_dup 3)))
6196    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6197   "TARGET_THUMB"
6198   "*
6199   {
6200   if (which_alternative == 0)
6201     output_asm_insn (\"eor\\t%0, %3\", operands);
6202   else if (which_alternative == 1)
6203     {
6204       output_asm_insn (\"eor\\t%1, %3\", operands);
6205       output_asm_insn (\"mov\\t%0, %1\", operands);
6206     }
6207   else
6208     {
6209       output_asm_insn (\"eor\\t%1, %3\", operands);
6210       output_asm_insn (\"str\\t%1, %0\", operands);
6211     }
6213   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6214     {
6215     case 4:  return \"b%d5\\t%l4\";
6216     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6217     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6218     }
6219   }"
6220   [(set (attr "far_jump")
6221         (if_then_else
6222             (ior (and (eq (symbol_ref ("which_alternative"))
6223                           (const_int 0))
6224                       (eq_attr "length" "8"))
6225                  (eq_attr "length" "10"))
6226             (const_string "yes")
6227             (const_string "no")))
6228    (set (attr "length")
6229      (if_then_else
6230        (eq (symbol_ref ("which_alternative"))
6231                        (const_int 0))
6232        (if_then_else
6233          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6234               (le (minus (match_dup 4) (pc)) (const_int 256)))
6235          (const_int 4)
6236          (if_then_else
6237            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6238                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6239            (const_int 6)
6240            (const_int 8)))
6241        (if_then_else
6242          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6243               (le (minus (match_dup 4) (pc)) (const_int 256)))
6244          (const_int 6)
6245          (if_then_else
6246            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6247                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6248            (const_int 8)
6249            (const_int 10)))))]
6252 (define_insn "*bicsi3_cbranch_scratch"
6253   [(set (pc)
6254         (if_then_else
6255          (match_operator 4 "equality_operator"
6256           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6257                    (match_operand:SI 1 "s_register_operand" "0"))
6258            (const_int 0)])
6259          (label_ref (match_operand 3 "" ""))
6260          (pc)))
6261    (clobber (match_scratch:SI 0 "=l"))]
6262   "TARGET_THUMB"
6263   "*
6264   {
6265   output_asm_insn (\"bic\\t%0, %2\", operands);
6266   switch (get_attr_length (insn))
6267     {
6268     case 4:  return \"b%d4\\t%l3\";
6269     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6270     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6271     }
6272   }"
6273   [(set (attr "far_jump")
6274         (if_then_else
6275             (eq_attr "length" "8")
6276             (const_string "yes")
6277             (const_string "no")))
6278    (set (attr "length") 
6279         (if_then_else
6280             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6281                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6282             (const_int 4)
6283             (if_then_else
6284                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6285                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6286                 (const_int 6)
6287                 (const_int 8))))]
6289   
6290 (define_insn "*bicsi3_cbranch"
6291   [(set (pc)
6292         (if_then_else
6293          (match_operator 5 "equality_operator"
6294           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6295                    (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6296            (const_int 0)])
6297          (label_ref (match_operand 4 "" ""))
6298          (pc)))
6299    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6300         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6301    (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6302   "TARGET_THUMB"
6303   "*
6304   {
6305   if (which_alternative == 0)
6306     output_asm_insn (\"bic\\t%0, %3\", operands);
6307   else if (which_alternative <= 2)
6308     {
6309       output_asm_insn (\"bic\\t%1, %3\", operands);
6310       /* It's ok if OP0 is a lo-reg, even though the mov will set the
6311          conditions again, since we're only testing for equality.  */
6312       output_asm_insn (\"mov\\t%0, %1\", operands);
6313     }
6314   else
6315     {
6316       output_asm_insn (\"bic\\t%1, %3\", operands);
6317       output_asm_insn (\"str\\t%1, %0\", operands);
6318     }
6320   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6321     {
6322     case 4:  return \"b%d5\\t%l4\";
6323     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6324     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6325     }
6326   }"
6327   [(set (attr "far_jump")
6328         (if_then_else
6329             (ior (and (eq (symbol_ref ("which_alternative"))
6330                           (const_int 0))
6331                       (eq_attr "length" "8"))
6332                  (eq_attr "length" "10"))
6333             (const_string "yes")
6334             (const_string "no")))
6335    (set (attr "length")
6336      (if_then_else
6337        (eq (symbol_ref ("which_alternative"))
6338                        (const_int 0))
6339        (if_then_else
6340          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6341               (le (minus (match_dup 4) (pc)) (const_int 256)))
6342          (const_int 4)
6343          (if_then_else
6344            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6345                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6346            (const_int 6)
6347            (const_int 8)))
6348        (if_then_else
6349          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6350               (le (minus (match_dup 4) (pc)) (const_int 256)))
6351          (const_int 6)
6352          (if_then_else
6353            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6354                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6355            (const_int 8)
6356            (const_int 10)))))]
6359 (define_insn "*cbranchne_decr1"
6360   [(set (pc)
6361         (if_then_else (match_operator 3 "equality_operator"
6362                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6363                         (const_int 0)])
6364                       (label_ref (match_operand 4 "" ""))
6365                       (pc)))
6366    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6367         (plus:SI (match_dup 2) (const_int -1)))
6368    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6369   "TARGET_THUMB"
6370   "*
6371    {
6372      rtx cond[2];
6373      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6374                                 ? GEU : LTU),
6375                                VOIDmode, operands[2], const1_rtx);
6376      cond[1] = operands[4];
6378      if (which_alternative == 0)
6379        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6380      else if (which_alternative == 1)
6381        {
6382          /* We must provide an alternative for a hi reg because reload 
6383             cannot handle output reloads on a jump instruction, but we
6384             can't subtract into that.  Fortunately a mov from lo to hi
6385             does not clobber the condition codes.  */
6386          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6387          output_asm_insn (\"mov\\t%0, %1\", operands);
6388        }
6389      else
6390        {
6391          /* Similarly, but the target is memory.  */
6392          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6393          output_asm_insn (\"str\\t%1, %0\", operands);
6394        }
6396      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6397        {
6398          case 4:
6399            output_asm_insn (\"b%d0\\t%l1\", cond);
6400            return \"\";
6401          case 6:
6402            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6403            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6404          default:
6405            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6406            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6407        }
6408    }
6409   "
6410   [(set (attr "far_jump")
6411         (if_then_else
6412             (ior (and (eq (symbol_ref ("which_alternative"))
6413                           (const_int 0))
6414                       (eq_attr "length" "8"))
6415                  (eq_attr "length" "10"))
6416             (const_string "yes")
6417             (const_string "no")))
6418    (set_attr_alternative "length"
6419       [
6420        ;; Alternative 0
6421        (if_then_else
6422          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6423               (le (minus (match_dup 4) (pc)) (const_int 256)))
6424          (const_int 4)
6425          (if_then_else
6426            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6427                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6428            (const_int 6)
6429            (const_int 8)))
6430        ;; Alternative 1
6431        (if_then_else
6432          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6433               (le (minus (match_dup 4) (pc)) (const_int 256)))
6434          (const_int 6)
6435          (if_then_else
6436            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6437                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6438            (const_int 8)
6439            (const_int 10)))
6440        ;; Alternative 2
6441        (if_then_else
6442          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6443               (le (minus (match_dup 4) (pc)) (const_int 256)))
6444          (const_int 6)
6445          (if_then_else
6446            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6447                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6448            (const_int 8)
6449            (const_int 10)))
6450        ;; Alternative 3
6451        (if_then_else
6452          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6453               (le (minus (match_dup 4) (pc)) (const_int 256)))
6454          (const_int 6)
6455          (if_then_else
6456            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6457                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6458            (const_int 8)
6459            (const_int 10)))])]
6462 (define_insn "*addsi3_cbranch"
6463   [(set (pc)
6464         (if_then_else
6465          (match_operator 4 "comparison_operator"
6466           [(plus:SI
6467             (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6468             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6469            (const_int 0)])
6470          (label_ref (match_operand 5 "" ""))
6471          (pc)))
6472    (set
6473     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6474     (plus:SI (match_dup 2) (match_dup 3)))
6475    (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6476   "TARGET_THUMB
6477    && (GET_CODE (operands[4]) == EQ
6478        || GET_CODE (operands[4]) == NE
6479        || GET_CODE (operands[4]) == GE
6480        || GET_CODE (operands[4]) == LT)"
6481   "*
6482    {
6483      rtx cond[3];
6485      
6486      cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6487      cond[1] = operands[2];
6488      cond[2] = operands[3];
6490      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6491        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6492      else
6493        output_asm_insn (\"add\\t%0, %1, %2\", cond);
6495      if (which_alternative >= 3
6496          && which_alternative < 4)
6497        output_asm_insn (\"mov\\t%0, %1\", operands);
6498      else if (which_alternative >= 4)
6499        output_asm_insn (\"str\\t%1, %0\", operands);
6501      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6502        {
6503          case 4:
6504            return \"b%d4\\t%l5\";
6505          case 6:
6506            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6507          default:
6508            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6509        }
6510    }
6511   "
6512   [(set (attr "far_jump")
6513         (if_then_else
6514             (ior (and (lt (symbol_ref ("which_alternative"))
6515                           (const_int 3))
6516                       (eq_attr "length" "8"))
6517                  (eq_attr "length" "10"))
6518             (const_string "yes")
6519             (const_string "no")))
6520    (set (attr "length")
6521      (if_then_else
6522        (lt (symbol_ref ("which_alternative"))
6523                        (const_int 3))
6524        (if_then_else
6525          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6526               (le (minus (match_dup 5) (pc)) (const_int 256)))
6527          (const_int 4)
6528          (if_then_else
6529            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6530                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6531            (const_int 6)
6532            (const_int 8)))
6533        (if_then_else
6534          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6535               (le (minus (match_dup 5) (pc)) (const_int 256)))
6536          (const_int 6)
6537          (if_then_else
6538            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6539                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6540            (const_int 8)
6541            (const_int 10)))))]
6544 (define_insn "*addsi3_cbranch_scratch"
6545   [(set (pc)
6546         (if_then_else
6547          (match_operator 3 "comparison_operator"
6548           [(plus:SI
6549             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6550             (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
6551            (const_int 0)])
6552          (label_ref (match_operand 4 "" ""))
6553          (pc)))
6554    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6555   "TARGET_THUMB
6556    && (GET_CODE (operands[3]) == EQ
6557        || GET_CODE (operands[3]) == NE
6558        || GET_CODE (operands[3]) == GE
6559        || GET_CODE (operands[3]) == LT)"
6560   "*
6561    {
6562      switch (which_alternative)
6563        {
6564        case 0:
6565          output_asm_insn (\"cmp\t%1, #%n2\", operands);
6566          break;
6567        case 1:
6568          output_asm_insn (\"cmn\t%1, %2\", operands);
6569          break;
6570        case 2:
6571          if (INTVAL (operands[2]) < 0)
6572            output_asm_insn (\"sub\t%0, %1, %2\", operands);
6573          else
6574            output_asm_insn (\"add\t%0, %1, %2\", operands);
6575          break;
6576        case 3:
6577          if (INTVAL (operands[2]) < 0)
6578            output_asm_insn (\"sub\t%0, %0, %2\", operands);
6579          else
6580            output_asm_insn (\"add\t%0, %0, %2\", operands);
6581          break;
6582        }
6584      switch (get_attr_length (insn))
6585        {
6586          case 4:
6587            return \"b%d3\\t%l4\";
6588          case 6:
6589            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6590          default:
6591            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6592        }
6593    }
6594   "
6595   [(set (attr "far_jump")
6596         (if_then_else
6597             (eq_attr "length" "8")
6598             (const_string "yes")
6599             (const_string "no")))
6600    (set (attr "length")
6601        (if_then_else
6602          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6603               (le (minus (match_dup 4) (pc)) (const_int 256)))
6604          (const_int 4)
6605          (if_then_else
6606            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6607                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6608            (const_int 6)
6609            (const_int 8))))]
6612 (define_insn "*subsi3_cbranch"
6613   [(set (pc)
6614         (if_then_else
6615          (match_operator 4 "comparison_operator"
6616           [(minus:SI
6617             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6618             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6619            (const_int 0)])
6620          (label_ref (match_operand 5 "" ""))
6621          (pc)))
6622    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6623         (minus:SI (match_dup 2) (match_dup 3)))
6624    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6625   "TARGET_THUMB
6626    && (GET_CODE (operands[4]) == EQ
6627        || GET_CODE (operands[4]) == NE
6628        || GET_CODE (operands[4]) == GE
6629        || GET_CODE (operands[4]) == LT)"
6630   "*
6631    {
6632      if (which_alternative == 0)
6633        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6634      else if (which_alternative == 1)
6635        {
6636          /* We must provide an alternative for a hi reg because reload 
6637             cannot handle output reloads on a jump instruction, but we
6638             can't subtract into that.  Fortunately a mov from lo to hi
6639             does not clobber the condition codes.  */
6640          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6641          output_asm_insn (\"mov\\t%0, %1\", operands);
6642        }
6643      else
6644        {
6645          /* Similarly, but the target is memory.  */
6646          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6647          output_asm_insn (\"str\\t%1, %0\", operands);
6648        }
6650      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6651        {
6652          case 4:
6653            return \"b%d4\\t%l5\";
6654          case 6:
6655            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6656          default:
6657            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6658        }
6659    }
6660   "
6661   [(set (attr "far_jump")
6662         (if_then_else
6663             (ior (and (eq (symbol_ref ("which_alternative"))
6664                           (const_int 0))
6665                       (eq_attr "length" "8"))
6666                  (eq_attr "length" "10"))
6667             (const_string "yes")
6668             (const_string "no")))
6669    (set (attr "length")
6670      (if_then_else
6671        (eq (symbol_ref ("which_alternative"))
6672                        (const_int 0))
6673        (if_then_else
6674          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6675               (le (minus (match_dup 5) (pc)) (const_int 256)))
6676          (const_int 4)
6677          (if_then_else
6678            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6679                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6680            (const_int 6)
6681            (const_int 8)))
6682        (if_then_else
6683          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6684               (le (minus (match_dup 5) (pc)) (const_int 256)))
6685          (const_int 6)
6686          (if_then_else
6687            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6688                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6689            (const_int 8)
6690            (const_int 10)))))]
6693 (define_insn "*subsi3_cbranch_scratch"
6694   [(set (pc)
6695         (if_then_else
6696          (match_operator 0 "arm_comparison_operator"
6697           [(minus:SI (match_operand:SI 1 "register_operand" "l")
6698                      (match_operand:SI 2 "nonmemory_operand" "l"))
6699            (const_int 0)])
6700          (label_ref (match_operand 3 "" ""))
6701          (pc)))]
6702   "TARGET_THUMB
6703    && (GET_CODE (operands[0]) == EQ
6704        || GET_CODE (operands[0]) == NE
6705        || GET_CODE (operands[0]) == GE
6706        || GET_CODE (operands[0]) == LT)"
6707   "*
6708   output_asm_insn (\"cmp\\t%1, %2\", operands);
6709   switch (get_attr_length (insn))
6710     {
6711     case 4:  return \"b%d0\\t%l3\";
6712     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6713     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6714     }
6715   "
6716   [(set (attr "far_jump")
6717         (if_then_else
6718             (eq_attr "length" "8")
6719             (const_string "yes")
6720             (const_string "no")))
6721    (set (attr "length") 
6722         (if_then_else
6723             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6724                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6725             (const_int 4)
6726             (if_then_else
6727                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6728                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6729                 (const_int 6)
6730                 (const_int 8))))]
6733 ;; Comparison and test insns
6735 (define_expand "cmpsi"
6736   [(match_operand:SI 0 "s_register_operand" "")
6737    (match_operand:SI 1 "arm_add_operand" "")]
6738   "TARGET_ARM"
6739   "{
6740     arm_compare_op0 = operands[0];
6741     arm_compare_op1 = operands[1];
6742     DONE;
6743   }"
6746 (define_expand "cmpsf"
6747   [(match_operand:SF 0 "s_register_operand" "")
6748    (match_operand:SF 1 "arm_float_compare_operand" "")]
6749   "TARGET_ARM && TARGET_HARD_FLOAT"
6750   "
6751   arm_compare_op0 = operands[0];
6752   arm_compare_op1 = operands[1];
6753   DONE;
6754   "
6757 (define_expand "cmpdf"
6758   [(match_operand:DF 0 "s_register_operand" "")
6759    (match_operand:DF 1 "arm_float_compare_operand" "")]
6760   "TARGET_ARM && TARGET_HARD_FLOAT"
6761   "
6762   arm_compare_op0 = operands[0];
6763   arm_compare_op1 = operands[1];
6764   DONE;
6765   "
6768 (define_insn "*arm_cmpsi_insn"
6769   [(set (reg:CC CC_REGNUM)
6770         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6771                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
6772   "TARGET_ARM"
6773   "@
6774    cmp%?\\t%0, %1
6775    cmn%?\\t%0, #%n1"
6776   [(set_attr "conds" "set")]
6779 (define_insn "*cmpsi_shiftsi"
6780   [(set (reg:CC CC_REGNUM)
6781         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
6782                     (match_operator:SI  3 "shift_operator"
6783                      [(match_operand:SI 1 "s_register_operand" "r")
6784                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
6785   "TARGET_ARM"
6786   "cmp%?\\t%0, %1%S3"
6787   [(set_attr "conds" "set")
6788    (set_attr "shift" "1")
6789    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6790                       (const_string "alu_shift")
6791                       (const_string "alu_shift_reg")))]
6794 (define_insn "*cmpsi_shiftsi_swp"
6795   [(set (reg:CC_SWP CC_REGNUM)
6796         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6797                          [(match_operand:SI 1 "s_register_operand" "r")
6798                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
6799                         (match_operand:SI 0 "s_register_operand" "r")))]
6800   "TARGET_ARM"
6801   "cmp%?\\t%0, %1%S3"
6802   [(set_attr "conds" "set")
6803    (set_attr "shift" "1")
6804    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6805                       (const_string "alu_shift")
6806                       (const_string "alu_shift_reg")))]
6809 (define_insn "*cmpsi_negshiftsi_si"
6810   [(set (reg:CC_Z CC_REGNUM)
6811         (compare:CC_Z
6812          (neg:SI (match_operator:SI 1 "shift_operator"
6813                     [(match_operand:SI 2 "s_register_operand" "r")
6814                      (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6815          (match_operand:SI 0 "s_register_operand" "r")))]
6816   "TARGET_ARM"
6817   "cmn%?\\t%0, %2%S1"
6818   [(set_attr "conds" "set")
6819    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
6820                                     (const_string "alu_shift")
6821                                     (const_string "alu_shift_reg")))]
6824 ;; Cirrus SF compare instruction
6825 (define_insn "*cirrus_cmpsf"
6826   [(set (reg:CCFP CC_REGNUM)
6827         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6828                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
6829   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6830   "cfcmps%?\\tr15, %V0, %V1"
6831   [(set_attr "type"   "mav_farith")
6832    (set_attr "cirrus" "compare")]
6835 ;; Cirrus DF compare instruction
6836 (define_insn "*cirrus_cmpdf"
6837   [(set (reg:CCFP CC_REGNUM)
6838         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6839                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
6840   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6841   "cfcmpd%?\\tr15, %V0, %V1"
6842   [(set_attr "type"   "mav_farith")
6843    (set_attr "cirrus" "compare")]
6846 ;; Cirrus DI compare instruction
6847 (define_expand "cmpdi"
6848   [(match_operand:DI 0 "cirrus_fp_register" "")
6849    (match_operand:DI 1 "cirrus_fp_register" "")]
6850   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6851   "{
6852      arm_compare_op0 = operands[0];
6853      arm_compare_op1 = operands[1];
6854      DONE;
6855    }")
6857 (define_insn "*cirrus_cmpdi"
6858   [(set (reg:CC CC_REGNUM)
6859         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6860                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
6861   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6862   "cfcmp64%?\\tr15, %V0, %V1"
6863   [(set_attr "type"   "mav_farith")
6864    (set_attr "cirrus" "compare")]
6867 ; This insn allows redundant compares to be removed by cse, nothing should
6868 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6869 ; is deleted later on. The match_dup will match the mode here, so that
6870 ; mode changes of the condition codes aren't lost by this even though we don't
6871 ; specify what they are.
6873 (define_insn "*deleted_compare"
6874   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6875   "TARGET_ARM"
6876   "\\t%@ deleted compare"
6877   [(set_attr "conds" "set")
6878    (set_attr "length" "0")]
6882 ;; Conditional branch insns
6884 (define_expand "beq"
6885   [(set (pc)
6886         (if_then_else (eq (match_dup 1) (const_int 0))
6887                       (label_ref (match_operand 0 "" ""))
6888                       (pc)))]
6889   "TARGET_ARM"
6890   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6893 (define_expand "bne"
6894   [(set (pc)
6895         (if_then_else (ne (match_dup 1) (const_int 0))
6896                       (label_ref (match_operand 0 "" ""))
6897                       (pc)))]
6898   "TARGET_ARM"
6899   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6902 (define_expand "bgt"
6903   [(set (pc)
6904         (if_then_else (gt (match_dup 1) (const_int 0))
6905                       (label_ref (match_operand 0 "" ""))
6906                       (pc)))]
6907   "TARGET_ARM"
6908   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6911 (define_expand "ble"
6912   [(set (pc)
6913         (if_then_else (le (match_dup 1) (const_int 0))
6914                       (label_ref (match_operand 0 "" ""))
6915                       (pc)))]
6916   "TARGET_ARM"
6917   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6920 (define_expand "bge"
6921   [(set (pc)
6922         (if_then_else (ge (match_dup 1) (const_int 0))
6923                       (label_ref (match_operand 0 "" ""))
6924                       (pc)))]
6925   "TARGET_ARM"
6926   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6929 (define_expand "blt"
6930   [(set (pc)
6931         (if_then_else (lt (match_dup 1) (const_int 0))
6932                       (label_ref (match_operand 0 "" ""))
6933                       (pc)))]
6934   "TARGET_ARM"
6935   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6938 (define_expand "bgtu"
6939   [(set (pc)
6940         (if_then_else (gtu (match_dup 1) (const_int 0))
6941                       (label_ref (match_operand 0 "" ""))
6942                       (pc)))]
6943   "TARGET_ARM"
6944   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6947 (define_expand "bleu"
6948   [(set (pc)
6949         (if_then_else (leu (match_dup 1) (const_int 0))
6950                       (label_ref (match_operand 0 "" ""))
6951                       (pc)))]
6952   "TARGET_ARM"
6953   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6956 (define_expand "bgeu"
6957   [(set (pc)
6958         (if_then_else (geu (match_dup 1) (const_int 0))
6959                       (label_ref (match_operand 0 "" ""))
6960                       (pc)))]
6961   "TARGET_ARM"
6962   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6965 (define_expand "bltu"
6966   [(set (pc)
6967         (if_then_else (ltu (match_dup 1) (const_int 0))
6968                       (label_ref (match_operand 0 "" ""))
6969                       (pc)))]
6970   "TARGET_ARM"
6971   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6974 (define_expand "bunordered"
6975   [(set (pc)
6976         (if_then_else (unordered (match_dup 1) (const_int 0))
6977                       (label_ref (match_operand 0 "" ""))
6978                       (pc)))]
6979   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6980   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6981                                       arm_compare_op1);"
6984 (define_expand "bordered"
6985   [(set (pc)
6986         (if_then_else (ordered (match_dup 1) (const_int 0))
6987                       (label_ref (match_operand 0 "" ""))
6988                       (pc)))]
6989   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6990   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6991                                       arm_compare_op1);"
6994 (define_expand "bungt"
6995   [(set (pc)
6996         (if_then_else (ungt (match_dup 1) (const_int 0))
6997                       (label_ref (match_operand 0 "" ""))
6998                       (pc)))]
6999   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7000   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
7003 (define_expand "bunlt"
7004   [(set (pc)
7005         (if_then_else (unlt (match_dup 1) (const_int 0))
7006                       (label_ref (match_operand 0 "" ""))
7007                       (pc)))]
7008   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7009   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
7012 (define_expand "bunge"
7013   [(set (pc)
7014         (if_then_else (unge (match_dup 1) (const_int 0))
7015                       (label_ref (match_operand 0 "" ""))
7016                       (pc)))]
7017   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7018   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
7021 (define_expand "bunle"
7022   [(set (pc)
7023         (if_then_else (unle (match_dup 1) (const_int 0))
7024                       (label_ref (match_operand 0 "" ""))
7025                       (pc)))]
7026   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7027   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
7030 ;; The following two patterns need two branch instructions, since there is
7031 ;; no single instruction that will handle all cases.
7032 (define_expand "buneq"
7033   [(set (pc)
7034         (if_then_else (uneq (match_dup 1) (const_int 0))
7035                       (label_ref (match_operand 0 "" ""))
7036                       (pc)))]
7037   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7038   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
7041 (define_expand "bltgt"
7042   [(set (pc)
7043         (if_then_else (ltgt (match_dup 1) (const_int 0))
7044                       (label_ref (match_operand 0 "" ""))
7045                       (pc)))]
7046   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7047   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
7051 ;; Patterns to match conditional branch insns.
7054 ; Special pattern to match UNEQ.
7055 (define_insn "*arm_buneq"
7056   [(set (pc)
7057         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7058                       (label_ref (match_operand 0 "" ""))
7059                       (pc)))]
7060   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7061   "*
7062   if (arm_ccfsm_state != 0)
7063     abort ();
7065   return \"bvs\\t%l0\;beq\\t%l0\";
7066   "
7067   [(set_attr "conds" "jump_clob")
7068    (set_attr "length" "8")]
7071 ; Special pattern to match LTGT.
7072 (define_insn "*arm_bltgt"
7073   [(set (pc)
7074         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7075                       (label_ref (match_operand 0 "" ""))
7076                       (pc)))]
7077   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7078   "*
7079   if (arm_ccfsm_state != 0)
7080     abort ();
7082   return \"bmi\\t%l0\;bgt\\t%l0\";
7083   "
7084   [(set_attr "conds" "jump_clob")
7085    (set_attr "length" "8")]
7088 (define_insn "*arm_cond_branch"
7089   [(set (pc)
7090         (if_then_else (match_operator 1 "arm_comparison_operator"
7091                        [(match_operand 2 "cc_register" "") (const_int 0)])
7092                       (label_ref (match_operand 0 "" ""))
7093                       (pc)))]
7094   "TARGET_ARM"
7095   "*
7096   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7097     {
7098       arm_ccfsm_state += 2;
7099       return \"\";
7100     }
7101   return \"b%d1\\t%l0\";
7102   "
7103   [(set_attr "conds" "use")
7104    (set_attr "type" "branch")]
7107 ; Special pattern to match reversed UNEQ.
7108 (define_insn "*arm_buneq_reversed"
7109   [(set (pc)
7110         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7111                       (pc)
7112                       (label_ref (match_operand 0 "" ""))))]
7113   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7114   "*
7115   if (arm_ccfsm_state != 0)
7116     abort ();
7118   return \"bmi\\t%l0\;bgt\\t%l0\";
7119   "
7120   [(set_attr "conds" "jump_clob")
7121    (set_attr "length" "8")]
7124 ; Special pattern to match reversed LTGT.
7125 (define_insn "*arm_bltgt_reversed"
7126   [(set (pc)
7127         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7128                       (pc)
7129                       (label_ref (match_operand 0 "" ""))))]
7130   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7131   "*
7132   if (arm_ccfsm_state != 0)
7133     abort ();
7135   return \"bvs\\t%l0\;beq\\t%l0\";
7136   "
7137   [(set_attr "conds" "jump_clob")
7138    (set_attr "length" "8")]
7141 (define_insn "*arm_cond_branch_reversed"
7142   [(set (pc)
7143         (if_then_else (match_operator 1 "arm_comparison_operator"
7144                        [(match_operand 2 "cc_register" "") (const_int 0)])
7145                       (pc)
7146                       (label_ref (match_operand 0 "" ""))))]
7147   "TARGET_ARM"
7148   "*
7149   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7150     {
7151       arm_ccfsm_state += 2;
7152       return \"\";
7153     }
7154   return \"b%D1\\t%l0\";
7155   "
7156   [(set_attr "conds" "use")
7157    (set_attr "type" "branch")]
7162 ; scc insns
7164 (define_expand "seq"
7165   [(set (match_operand:SI 0 "s_register_operand" "")
7166         (eq:SI (match_dup 1) (const_int 0)))]
7167   "TARGET_ARM"
7168   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7171 (define_expand "sne"
7172   [(set (match_operand:SI 0 "s_register_operand" "")
7173         (ne:SI (match_dup 1) (const_int 0)))]
7174   "TARGET_ARM"
7175   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7178 (define_expand "sgt"
7179   [(set (match_operand:SI 0 "s_register_operand" "")
7180         (gt:SI (match_dup 1) (const_int 0)))]
7181   "TARGET_ARM"
7182   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7185 (define_expand "sle"
7186   [(set (match_operand:SI 0 "s_register_operand" "")
7187         (le:SI (match_dup 1) (const_int 0)))]
7188   "TARGET_ARM"
7189   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7192 (define_expand "sge"
7193   [(set (match_operand:SI 0 "s_register_operand" "")
7194         (ge:SI (match_dup 1) (const_int 0)))]
7195   "TARGET_ARM"
7196   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7199 (define_expand "slt"
7200   [(set (match_operand:SI 0 "s_register_operand" "")
7201         (lt:SI (match_dup 1) (const_int 0)))]
7202   "TARGET_ARM"
7203   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7206 (define_expand "sgtu"
7207   [(set (match_operand:SI 0 "s_register_operand" "")
7208         (gtu:SI (match_dup 1) (const_int 0)))]
7209   "TARGET_ARM"
7210   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7213 (define_expand "sleu"
7214   [(set (match_operand:SI 0 "s_register_operand" "")
7215         (leu:SI (match_dup 1) (const_int 0)))]
7216   "TARGET_ARM"
7217   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7220 (define_expand "sgeu"
7221   [(set (match_operand:SI 0 "s_register_operand" "")
7222         (geu:SI (match_dup 1) (const_int 0)))]
7223   "TARGET_ARM"
7224   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7227 (define_expand "sltu"
7228   [(set (match_operand:SI 0 "s_register_operand" "")
7229         (ltu:SI (match_dup 1) (const_int 0)))]
7230   "TARGET_ARM"
7231   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7234 (define_expand "sunordered"
7235   [(set (match_operand:SI 0 "s_register_operand" "")
7236         (unordered:SI (match_dup 1) (const_int 0)))]
7237   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7238   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7239                                       arm_compare_op1);"
7242 (define_expand "sordered"
7243   [(set (match_operand:SI 0 "s_register_operand" "")
7244         (ordered:SI (match_dup 1) (const_int 0)))]
7245   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7246   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7247                                       arm_compare_op1);"
7250 (define_expand "sungt"
7251   [(set (match_operand:SI 0 "s_register_operand" "")
7252         (ungt:SI (match_dup 1) (const_int 0)))]
7253   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7254   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7255                                       arm_compare_op1);"
7258 (define_expand "sunge"
7259   [(set (match_operand:SI 0 "s_register_operand" "")
7260         (unge:SI (match_dup 1) (const_int 0)))]
7261   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7262   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7263                                       arm_compare_op1);"
7266 (define_expand "sunlt"
7267   [(set (match_operand:SI 0 "s_register_operand" "")
7268         (unlt:SI (match_dup 1) (const_int 0)))]
7269   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7270   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7271                                       arm_compare_op1);"
7274 (define_expand "sunle"
7275   [(set (match_operand:SI 0 "s_register_operand" "")
7276         (unle:SI (match_dup 1) (const_int 0)))]
7277   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7278   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7279                                       arm_compare_op1);"
7282 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7283 ;;; simple ARM instructions. 
7285 ; (define_expand "suneq"
7286 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7287 ;       (uneq:SI (match_dup 1) (const_int 0)))]
7288 ;   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7289 ;   "abort ();"
7290 ; )
7292 ; (define_expand "sltgt"
7293 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7294 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
7295 ;   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7296 ;   "abort ();"
7297 ; )
7299 (define_insn "*mov_scc"
7300   [(set (match_operand:SI 0 "s_register_operand" "=r")
7301         (match_operator:SI 1 "arm_comparison_operator"
7302          [(match_operand 2 "cc_register" "") (const_int 0)]))]
7303   "TARGET_ARM"
7304   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7305   [(set_attr "conds" "use")
7306    (set_attr "length" "8")]
7309 (define_insn "*mov_negscc"
7310   [(set (match_operand:SI 0 "s_register_operand" "=r")
7311         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7312                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7313   "TARGET_ARM"
7314   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7315   [(set_attr "conds" "use")
7316    (set_attr "length" "8")]
7319 (define_insn "*mov_notscc"
7320   [(set (match_operand:SI 0 "s_register_operand" "=r")
7321         (not:SI (match_operator:SI 1 "arm_comparison_operator"
7322                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7323   "TARGET_ARM"
7324   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7325   [(set_attr "conds" "use")
7326    (set_attr "length" "8")]
7330 ;; Conditional move insns
7332 (define_expand "movsicc"
7333   [(set (match_operand:SI 0 "s_register_operand" "")
7334         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7335                          (match_operand:SI 2 "arm_not_operand" "")
7336                          (match_operand:SI 3 "arm_not_operand" "")))]
7337   "TARGET_ARM"
7338   "
7339   {
7340     enum rtx_code code = GET_CODE (operands[1]);
7341     rtx ccreg;
7343     if (code == UNEQ || code == LTGT)
7344       FAIL;
7346     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7347     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7348   }"
7351 (define_expand "movsfcc"
7352   [(set (match_operand:SF 0 "s_register_operand" "")
7353         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7354                          (match_operand:SF 2 "s_register_operand" "")
7355                          (match_operand:SF 3 "nonmemory_operand" "")))]
7356   "TARGET_ARM"
7357   "
7358   {
7359     enum rtx_code code = GET_CODE (operands[1]);
7360     rtx ccreg;
7362     if (code == UNEQ || code == LTGT)
7363       FAIL;
7365     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
7366        Otherwise, ensure it is a valid FP add operand */
7367     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7368         || (!arm_float_add_operand (operands[3], SFmode)))
7369       operands[3] = force_reg (SFmode, operands[3]);
7371     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7372     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7373   }"
7376 (define_expand "movdfcc"
7377   [(set (match_operand:DF 0 "s_register_operand" "")
7378         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7379                          (match_operand:DF 2 "s_register_operand" "")
7380                          (match_operand:DF 3 "arm_float_add_operand" "")))]
7381   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7382   "
7383   {
7384     enum rtx_code code = GET_CODE (operands[1]);
7385     rtx ccreg;
7387     if (code == UNEQ || code == LTGT)
7388       FAIL;
7390     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7391     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7392   }"
7395 (define_insn "*movsicc_insn"
7396   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7397         (if_then_else:SI
7398          (match_operator 3 "arm_comparison_operator"
7399           [(match_operand 4 "cc_register" "") (const_int 0)])
7400          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7401          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7402   "TARGET_ARM"
7403   "@
7404    mov%D3\\t%0, %2
7405    mvn%D3\\t%0, #%B2
7406    mov%d3\\t%0, %1
7407    mvn%d3\\t%0, #%B1
7408    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7409    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7410    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7411    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7412   [(set_attr "length" "4,4,4,4,8,8,8,8")
7413    (set_attr "conds" "use")]
7416 (define_insn "*movsfcc_soft_insn"
7417   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7418         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7419                           [(match_operand 4 "cc_register" "") (const_int 0)])
7420                          (match_operand:SF 1 "s_register_operand" "0,r")
7421                          (match_operand:SF 2 "s_register_operand" "r,0")))]
7422   "TARGET_ARM && TARGET_SOFT_FLOAT"
7423   "@
7424    mov%D3\\t%0, %2
7425    mov%d3\\t%0, %1"
7426   [(set_attr "conds" "use")]
7430 ;; Jump and linkage insns
7432 (define_expand "jump"
7433   [(set (pc)
7434         (label_ref (match_operand 0 "" "")))]
7435   "TARGET_EITHER"
7436   ""
7439 (define_insn "*arm_jump"
7440   [(set (pc)
7441         (label_ref (match_operand 0 "" "")))]
7442   "TARGET_ARM"
7443   "*
7444   {
7445     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7446       {
7447         arm_ccfsm_state += 2;
7448         return \"\";
7449       }
7450     return \"b%?\\t%l0\";
7451   }
7452   "
7453   [(set_attr "predicable" "yes")]
7456 (define_insn "*thumb_jump"
7457   [(set (pc)
7458         (label_ref (match_operand 0 "" "")))]
7459   "TARGET_THUMB"
7460   "*
7461   if (get_attr_length (insn) == 2)
7462     return \"b\\t%l0\";
7463   return \"bl\\t%l0\\t%@ far jump\";
7464   "
7465   [(set (attr "far_jump")
7466         (if_then_else
7467             (eq_attr "length" "4")
7468             (const_string "yes")
7469             (const_string "no")))
7470    (set (attr "length") 
7471         (if_then_else
7472             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7473                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
7474             (const_int 2)
7475             (const_int 4)))]
7478 (define_expand "call"
7479   [(parallel [(call (match_operand 0 "memory_operand" "")
7480                     (match_operand 1 "general_operand" ""))
7481               (use (match_operand 2 "" ""))
7482               (clobber (reg:SI LR_REGNUM))])]
7483   "TARGET_EITHER"
7484   "
7485   {
7486     rtx callee;
7487     
7488     /* In an untyped call, we can get NULL for operand 2.  */
7489     if (operands[2] == NULL_RTX)
7490       operands[2] = const0_rtx;
7491       
7492     /* This is to decide if we should generate indirect calls by loading the
7493        32 bit address of the callee into a register before performing the
7494        branch and link.  operand[2] encodes the long_call/short_call
7495        attribute of the function being called.  This attribute is set whenever
7496        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7497        is used, and the short_call attribute can also be set if function is
7498        declared as static or if it has already been defined in the current
7499        compilation unit.  See arm.c and arm.h for info about this.  The third
7500        parameter to arm_is_longcall_p is used to tell it which pattern
7501        invoked it.  */
7502     callee  = XEXP (operands[0], 0);
7503     
7504     if (GET_CODE (callee) != REG
7505        && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7506       XEXP (operands[0], 0) = force_reg (Pmode, callee);
7507   }"
7510 (define_insn "*call_reg_armv5"
7511   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7512          (match_operand 1 "" ""))
7513    (use (match_operand 2 "" ""))
7514    (clobber (reg:SI LR_REGNUM))]
7515   "TARGET_ARM && arm_arch5"
7516   "blx%?\\t%0"
7517   [(set_attr "type" "call")]
7520 (define_insn "*call_reg_arm"
7521   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7522          (match_operand 1 "" ""))
7523    (use (match_operand 2 "" ""))
7524    (clobber (reg:SI LR_REGNUM))]
7525   "TARGET_ARM && !arm_arch5"
7526   "*
7527   return output_call (operands);
7528   "
7529   ;; length is worst case, normally it is only two
7530   [(set_attr "length" "12")
7531    (set_attr "type" "call")]
7534 (define_insn "*call_mem"
7535   [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7536          (match_operand 1 "" ""))
7537    (use (match_operand 2 "" ""))
7538    (clobber (reg:SI LR_REGNUM))]
7539   "TARGET_ARM"
7540   "*
7541   return output_call_mem (operands);
7542   "
7543   [(set_attr "length" "12")
7544    (set_attr "type" "call")]
7547 (define_insn "*call_reg_thumb_v5"
7548   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7549          (match_operand 1 "" ""))
7550    (use (match_operand 2 "" ""))
7551    (clobber (reg:SI LR_REGNUM))]
7552   "TARGET_THUMB && arm_arch5"
7553   "blx\\t%0"
7554   [(set_attr "length" "2")
7555    (set_attr "type" "call")]
7558 (define_insn "*call_reg_thumb"
7559   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7560          (match_operand 1 "" ""))
7561    (use (match_operand 2 "" ""))
7562    (clobber (reg:SI LR_REGNUM))]
7563   "TARGET_THUMB && !arm_arch5"
7564   "*
7565   {
7566     if (!TARGET_CALLER_INTERWORKING)
7567       return thumb_call_via_reg (operands[0]);
7568     else if (operands[1] == const0_rtx)
7569       return \"bl\\t%__interwork_call_via_%0\";
7570     else if (frame_pointer_needed)
7571       return \"bl\\t%__interwork_r7_call_via_%0\";
7572     else
7573       return \"bl\\t%__interwork_r11_call_via_%0\";
7574   }"
7575   [(set_attr "type" "call")]
7578 (define_expand "call_value"
7579   [(parallel [(set (match_operand       0 "" "")
7580                    (call (match_operand 1 "memory_operand" "")
7581                          (match_operand 2 "general_operand" "")))
7582               (use (match_operand 3 "" ""))
7583               (clobber (reg:SI LR_REGNUM))])]
7584   "TARGET_EITHER"
7585   "
7586   {
7587     rtx callee = XEXP (operands[1], 0);
7588     
7589     /* In an untyped call, we can get NULL for operand 2.  */
7590     if (operands[3] == 0)
7591       operands[3] = const0_rtx;
7592       
7593     /* See the comment in define_expand \"call\".  */
7594     if (GET_CODE (callee) != REG
7595         && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7596       XEXP (operands[1], 0) = force_reg (Pmode, callee);
7597   }"
7600 (define_insn "*call_value_reg_armv5"
7601   [(set (match_operand 0 "" "")
7602         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7603               (match_operand 2 "" "")))
7604    (use (match_operand 3 "" ""))
7605    (clobber (reg:SI LR_REGNUM))]
7606   "TARGET_ARM && arm_arch5"
7607   "blx%?\\t%1"
7608   [(set_attr "type" "call")]
7611 (define_insn "*call_value_reg_arm"
7612   [(set (match_operand 0 "" "")
7613         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7614               (match_operand 2 "" "")))
7615    (use (match_operand 3 "" ""))
7616    (clobber (reg:SI LR_REGNUM))]
7617   "TARGET_ARM && !arm_arch5"
7618   "*
7619   return output_call (&operands[1]);
7620   "
7621   [(set_attr "length" "12")
7622    (set_attr "type" "call")]
7625 (define_insn "*call_value_mem"
7626   [(set (match_operand 0 "" "")
7627         (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7628               (match_operand 2 "" "")))
7629    (use (match_operand 3 "" ""))
7630    (clobber (reg:SI LR_REGNUM))]
7631   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7632   "*
7633   return output_call_mem (&operands[1]);
7634   "
7635   [(set_attr "length" "12")
7636    (set_attr "type" "call")]
7639 (define_insn "*call_value_reg_thumb_v5"
7640   [(set (match_operand 0 "" "")
7641         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7642               (match_operand 2 "" "")))
7643    (use (match_operand 3 "" ""))
7644    (clobber (reg:SI LR_REGNUM))]
7645   "TARGET_THUMB && arm_arch5"
7646   "blx\\t%1"
7647   [(set_attr "length" "2")
7648    (set_attr "type" "call")]
7651 (define_insn "*call_value_reg_thumb"
7652   [(set (match_operand 0 "" "")
7653         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7654               (match_operand 2 "" "")))
7655    (use (match_operand 3 "" ""))
7656    (clobber (reg:SI LR_REGNUM))]
7657   "TARGET_THUMB && !arm_arch5"
7658   "*
7659   {
7660     if (!TARGET_CALLER_INTERWORKING)
7661       return thumb_call_via_reg (operands[1]);
7662     else if (operands[2] == const0_rtx)
7663       return \"bl\\t%__interwork_call_via_%1\";
7664     else if (frame_pointer_needed)
7665       return \"bl\\t%__interwork_r7_call_via_%1\";
7666     else
7667       return \"bl\\t%__interwork_r11_call_via_%1\";
7668   }"
7669   [(set_attr "type" "call")]
7672 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7673 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7675 (define_insn "*call_symbol"
7676   [(call (mem:SI (match_operand:SI 0 "" ""))
7677          (match_operand 1 "" ""))
7678    (use (match_operand 2 "" ""))
7679    (clobber (reg:SI LR_REGNUM))]
7680   "TARGET_ARM
7681    && (GET_CODE (operands[0]) == SYMBOL_REF)
7682    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7683   "*
7684   {
7685     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7686   }"
7687   [(set_attr "type" "call")]
7690 (define_insn "*call_value_symbol"
7691   [(set (match_operand 0 "" "")
7692         (call (mem:SI (match_operand:SI 1 "" ""))
7693         (match_operand:SI 2 "" "")))
7694    (use (match_operand 3 "" ""))
7695    (clobber (reg:SI LR_REGNUM))]
7696   "TARGET_ARM
7697    && (GET_CODE (operands[1]) == SYMBOL_REF)
7698    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7699   "*
7700   {
7701     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7702   }"
7703   [(set_attr "type" "call")]
7706 (define_insn "*call_insn"
7707   [(call (mem:SI (match_operand:SI 0 "" ""))
7708          (match_operand:SI 1 "" ""))
7709    (use (match_operand 2 "" ""))
7710    (clobber (reg:SI LR_REGNUM))]
7711   "TARGET_THUMB
7712    && GET_CODE (operands[0]) == SYMBOL_REF
7713    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7714   "bl\\t%a0"
7715   [(set_attr "length" "4")
7716    (set_attr "type" "call")]
7719 (define_insn "*call_value_insn"
7720   [(set (match_operand 0 "" "")
7721         (call (mem:SI (match_operand 1 "" ""))
7722               (match_operand 2 "" "")))
7723    (use (match_operand 3 "" ""))
7724    (clobber (reg:SI LR_REGNUM))]
7725   "TARGET_THUMB
7726    && GET_CODE (operands[1]) == SYMBOL_REF
7727    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7728   "bl\\t%a1"
7729   [(set_attr "length" "4")
7730    (set_attr "type" "call")]
7733 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7734 (define_expand "sibcall"
7735   [(parallel [(call (match_operand 0 "memory_operand" "")
7736                     (match_operand 1 "general_operand" ""))
7737               (return)
7738               (use (match_operand 2 "" ""))])]
7739   "TARGET_ARM"
7740   "
7741   {
7742     if (operands[2] == NULL_RTX)
7743       operands[2] = const0_rtx;
7744   }"
7747 (define_expand "sibcall_value"
7748   [(parallel [(set (match_operand 0 "" "")
7749                    (call (match_operand 1 "memory_operand" "")
7750                          (match_operand 2 "general_operand" "")))
7751               (return)
7752               (use (match_operand 3 "" ""))])]
7753   "TARGET_ARM"
7754   "
7755   {
7756     if (operands[3] == NULL_RTX)
7757       operands[3] = const0_rtx;
7758   }"
7761 (define_insn "*sibcall_insn"
7762  [(call (mem:SI (match_operand:SI 0 "" "X"))
7763         (match_operand 1 "" ""))
7764   (return)
7765   (use (match_operand 2 "" ""))]
7766   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7767   "*
7768   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7769   "
7770   [(set_attr "type" "call")]
7773 (define_insn "*sibcall_value_insn"
7774  [(set (match_operand 0 "" "")
7775        (call (mem:SI (match_operand:SI 1 "" "X"))
7776              (match_operand 2 "" "")))
7777   (return)
7778   (use (match_operand 3 "" ""))]
7779   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7780   "*
7781   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7782   "
7783   [(set_attr "type" "call")]
7786 ;; Often the return insn will be the same as loading from memory, so set attr
7787 (define_insn "return"
7788   [(return)]
7789   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7790   "*
7791   {
7792     if (arm_ccfsm_state == 2)
7793       {
7794         arm_ccfsm_state += 2;
7795         return \"\";
7796       }
7797     return output_return_instruction (const_true_rtx, TRUE, FALSE);
7798   }"
7799   [(set_attr "type" "load1")
7800    (set_attr "length" "12")
7801    (set_attr "predicable" "yes")]
7804 (define_insn "*cond_return"
7805   [(set (pc)
7806         (if_then_else (match_operator 0 "arm_comparison_operator"
7807                        [(match_operand 1 "cc_register" "") (const_int 0)])
7808                       (return)
7809                       (pc)))]
7810   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7811   "*
7812   {
7813     if (arm_ccfsm_state == 2)
7814       {
7815         arm_ccfsm_state += 2;
7816         return \"\";
7817       }
7818     return output_return_instruction (operands[0], TRUE, FALSE);
7819   }"
7820   [(set_attr "conds" "use")
7821    (set_attr "length" "12")
7822    (set_attr "type" "load1")]
7825 (define_insn "*cond_return_inverted"
7826   [(set (pc)
7827         (if_then_else (match_operator 0 "arm_comparison_operator"
7828                        [(match_operand 1 "cc_register" "") (const_int 0)])
7829                       (pc)
7830                       (return)))]
7831   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7832   "*
7833   {
7834     if (arm_ccfsm_state == 2)
7835       {
7836         arm_ccfsm_state += 2;
7837         return \"\";
7838       }
7839     return output_return_instruction (operands[0], TRUE, TRUE);
7840   }"
7841   [(set_attr "conds" "use")
7842    (set_attr "length" "12")
7843    (set_attr "type" "load1")]
7846 ;; Generate a sequence of instructions to determine if the processor is
7847 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7848 ;; mask.
7850 (define_expand "return_addr_mask"
7851   [(set (match_dup 1)
7852       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7853                        (const_int 0)))
7854    (set (match_operand:SI 0 "s_register_operand" "")
7855       (if_then_else:SI (eq (match_dup 1) (const_int 0))
7856                        (const_int -1)
7857                        (const_int 67108860)))] ; 0x03fffffc
7858   "TARGET_ARM"
7859   "
7860   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7861   ")
7863 (define_insn "*check_arch2"
7864   [(set (match_operand:CC_NOOV 0 "cc_register" "")
7865       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7866                        (const_int 0)))]
7867   "TARGET_ARM"
7868   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7869   [(set_attr "length" "8")
7870    (set_attr "conds" "set")]
7873 ;; Call subroutine returning any type.
7875 (define_expand "untyped_call"
7876   [(parallel [(call (match_operand 0 "" "")
7877                     (const_int 0))
7878               (match_operand 1 "" "")
7879               (match_operand 2 "" "")])]
7880   "TARGET_EITHER"
7881   "
7882   {
7883     int i;
7884     rtx par = gen_rtx_PARALLEL (VOIDmode,
7885                                 rtvec_alloc (XVECLEN (operands[2], 0)));
7886     rtx addr = gen_reg_rtx (Pmode);
7887     rtx mem;
7888     int size = 0;
7890     emit_move_insn (addr, XEXP (operands[1], 0));
7891     mem = change_address (operands[1], BLKmode, addr);
7893     for (i = 0; i < XVECLEN (operands[2], 0); i++)
7894       {
7895         rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
7897         /* Default code only uses r0 as a return value, but we could
7898            be using anything up to 4 registers.  */
7899         if (REGNO (src) == R0_REGNUM)
7900           src = gen_rtx_REG (TImode, R0_REGNUM);
7902         XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
7903                                                  GEN_INT (size));
7904         size += GET_MODE_SIZE (GET_MODE (src));
7905       }
7907     emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
7908                                     const0_rtx));
7910     size = 0;
7912     for (i = 0; i < XVECLEN (par, 0); i++)
7913       {
7914         HOST_WIDE_INT offset = 0;
7915         rtx reg = XEXP (XVECEXP (par, 0, i), 0);
7917         if (size != 0)
7918           emit_move_insn (addr, plus_constant (addr, size));
7920         mem = change_address (mem, GET_MODE (reg), NULL);
7921         if (REGNO (reg) == R0_REGNUM)
7922           {
7923             /* On thumb we have to use a write-back instruction.  */
7924             emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
7925                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7926             size = TARGET_ARM ? 16 : 0;
7927           }
7928         else
7929           {
7930             emit_move_insn (mem, reg);
7931             size = GET_MODE_SIZE (GET_MODE (reg));
7932           }
7933       }
7935     /* The optimizer does not know that the call sets the function value
7936        registers we stored in the result block.  We avoid problems by
7937        claiming that all hard registers are used and clobbered at this
7938        point.  */
7939     emit_insn (gen_blockage ());
7941     DONE;
7942   }"
7945 (define_expand "untyped_return"
7946   [(match_operand:BLK 0 "memory_operand" "")
7947    (match_operand 1 "" "")]
7948   "TARGET_EITHER"
7949   "
7950   {
7951     int i;
7952     rtx addr = gen_reg_rtx (Pmode);
7953     rtx mem;
7954     int size = 0;
7956     emit_move_insn (addr, XEXP (operands[0], 0));
7957     mem = change_address (operands[0], BLKmode, addr);
7959     for (i = 0; i < XVECLEN (operands[1], 0); i++)
7960       {
7961         HOST_WIDE_INT offset = 0;
7962         rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
7964         if (size != 0)
7965           emit_move_insn (addr, plus_constant (addr, size));
7967         mem = change_address (mem, GET_MODE (reg), NULL);
7968         if (REGNO (reg) == R0_REGNUM)
7969           {
7970             /* On thumb we have to use a write-back instruction.  */
7971             emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
7972                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7973             size = TARGET_ARM ? 16 : 0;
7974           }
7975         else
7976           {
7977             emit_move_insn (reg, mem);
7978             size = GET_MODE_SIZE (GET_MODE (reg));
7979           }
7980       }
7982     /* Emit USE insns before the return.  */
7983     for (i = 0; i < XVECLEN (operands[1], 0); i++)
7984       emit_insn (gen_rtx_USE (VOIDmode,
7985                               SET_DEST (XVECEXP (operands[1], 0, i))));
7987     /* Construct the return.  */
7988     expand_naked_return ();
7990     DONE;
7991   }"
7994 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7995 ;; all of memory.  This blocks insns from being moved across this point.
7997 (define_insn "blockage"
7998   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
7999   "TARGET_EITHER"
8000   ""
8001   [(set_attr "length" "0")
8002    (set_attr "type" "block")]
8005 (define_expand "casesi"
8006   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
8007    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
8008    (match_operand:SI 2 "const_int_operand" "")  ; total range
8009    (match_operand:SI 3 "" "")                   ; table label
8010    (match_operand:SI 4 "" "")]                  ; Out of range label
8011   "TARGET_ARM"
8012   "
8013   {
8014     rtx reg;
8015     if (operands[1] != const0_rtx)
8016       {
8017         reg = gen_reg_rtx (SImode);
8019         emit_insn (gen_addsi3 (reg, operands[0],
8020                                GEN_INT (-INTVAL (operands[1]))));
8021         operands[0] = reg;
8022       }
8024     if (!const_ok_for_arm (INTVAL (operands[2])))
8025       operands[2] = force_reg (SImode, operands[2]);
8027     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
8028                                          operands[4]));
8029     DONE;
8030   }"
8033 ;; The USE in this pattern is needed to tell flow analysis that this is
8034 ;; a CASESI insn.  It has no other purpose.
8035 (define_insn "casesi_internal"
8036   [(parallel [(set (pc)
8037                (if_then_else
8038                 (leu (match_operand:SI 0 "s_register_operand" "r")
8039                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
8040                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8041                                  (label_ref (match_operand 2 "" ""))))
8042                 (label_ref (match_operand 3 "" ""))))
8043               (clobber (reg:CC CC_REGNUM))
8044               (use (label_ref (match_dup 2)))])]
8045   "TARGET_ARM"
8046   "*
8047     if (flag_pic)
8048       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8049     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8050   "
8051   [(set_attr "conds" "clob")
8052    (set_attr "length" "12")]
8055 (define_expand "indirect_jump"
8056   [(set (pc)
8057         (match_operand:SI 0 "s_register_operand" ""))]
8058   "TARGET_EITHER"
8059   ""
8062 ;; NB Never uses BX.
8063 (define_insn "*arm_indirect_jump"
8064   [(set (pc)
8065         (match_operand:SI 0 "s_register_operand" "r"))]
8066   "TARGET_ARM"
8067   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
8068   [(set_attr "predicable" "yes")]
8071 (define_insn "*load_indirect_jump"
8072   [(set (pc)
8073         (match_operand:SI 0 "memory_operand" "m"))]
8074   "TARGET_ARM"
8075   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
8076   [(set_attr "type" "load1")
8077    (set_attr "pool_range" "4096")
8078    (set_attr "neg_pool_range" "4084")
8079    (set_attr "predicable" "yes")]
8082 ;; NB Never uses BX.
8083 (define_insn "*thumb_indirect_jump"
8084   [(set (pc)
8085         (match_operand:SI 0 "register_operand" "l*r"))]
8086   "TARGET_THUMB"
8087   "mov\\tpc, %0"
8088   [(set_attr "conds" "clob")
8089    (set_attr "length" "2")]
8093 ;; Misc insns
8095 (define_insn "nop"
8096   [(const_int 0)]
8097   "TARGET_EITHER"
8098   "*
8099   if (TARGET_ARM)
8100     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8101   return  \"mov\\tr8, r8\";
8102   "
8103   [(set (attr "length")
8104         (if_then_else (eq_attr "is_thumb" "yes")
8105                       (const_int 2)
8106                       (const_int 4)))]
8110 ;; Patterns to allow combination of arithmetic, cond code and shifts
8112 (define_insn "*arith_shiftsi"
8113   [(set (match_operand:SI 0 "s_register_operand" "=r")
8114         (match_operator:SI 1 "shiftable_operator"
8115           [(match_operator:SI 3 "shift_operator"
8116              [(match_operand:SI 4 "s_register_operand" "r")
8117               (match_operand:SI 5 "reg_or_int_operand" "rI")])
8118            (match_operand:SI 2 "s_register_operand" "r")]))]
8119   "TARGET_ARM"
8120   "%i1%?\\t%0, %2, %4%S3"
8121   [(set_attr "predicable" "yes")
8122    (set_attr "shift" "4")
8123    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8124                       (const_string "alu_shift")
8125                       (const_string "alu_shift_reg")))]
8128 (define_split
8129   [(set (match_operand:SI 0 "s_register_operand" "")
8130         (match_operator:SI 1 "shiftable_operator"
8131          [(match_operator:SI 2 "shiftable_operator"
8132            [(match_operator:SI 3 "shift_operator"
8133              [(match_operand:SI 4 "s_register_operand" "")
8134               (match_operand:SI 5 "reg_or_int_operand" "")])
8135             (match_operand:SI 6 "s_register_operand" "")])
8136           (match_operand:SI 7 "arm_rhs_operand" "")]))
8137    (clobber (match_operand:SI 8 "s_register_operand" ""))]
8138   "TARGET_ARM"
8139   [(set (match_dup 8)
8140         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8141                          (match_dup 6)]))
8142    (set (match_dup 0)
8143         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8144   "")
8146 (define_insn "*arith_shiftsi_compare0"
8147   [(set (reg:CC_NOOV CC_REGNUM)
8148         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8149                           [(match_operator:SI 3 "shift_operator"
8150                             [(match_operand:SI 4 "s_register_operand" "r")
8151                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8152                            (match_operand:SI 2 "s_register_operand" "r")])
8153                          (const_int 0)))
8154    (set (match_operand:SI 0 "s_register_operand" "=r")
8155         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8156                          (match_dup 2)]))]
8157   "TARGET_ARM"
8158   "%i1%?s\\t%0, %2, %4%S3"
8159   [(set_attr "conds" "set")
8160    (set_attr "shift" "4")
8161    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8162                       (const_string "alu_shift")
8163                       (const_string "alu_shift_reg")))]
8166 (define_insn "*arith_shiftsi_compare0_scratch"
8167   [(set (reg:CC_NOOV CC_REGNUM)
8168         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8169                           [(match_operator:SI 3 "shift_operator"
8170                             [(match_operand:SI 4 "s_register_operand" "r")
8171                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8172                            (match_operand:SI 2 "s_register_operand" "r")])
8173                          (const_int 0)))
8174    (clobber (match_scratch:SI 0 "=r"))]
8175   "TARGET_ARM"
8176   "%i1%?s\\t%0, %2, %4%S3"
8177   [(set_attr "conds" "set")
8178    (set_attr "shift" "4")
8179    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8180                       (const_string "alu_shift")
8181                       (const_string "alu_shift_reg")))]
8184 (define_insn "*sub_shiftsi"
8185   [(set (match_operand:SI 0 "s_register_operand" "=r")
8186         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8187                   (match_operator:SI 2 "shift_operator"
8188                    [(match_operand:SI 3 "s_register_operand" "r")
8189                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
8190   "TARGET_ARM"
8191   "sub%?\\t%0, %1, %3%S2"
8192   [(set_attr "predicable" "yes")
8193    (set_attr "shift" "3")
8194    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8195                       (const_string "alu_shift")
8196                       (const_string "alu_shift_reg")))]
8199 (define_insn "*sub_shiftsi_compare0"
8200   [(set (reg:CC_NOOV CC_REGNUM)
8201         (compare:CC_NOOV
8202          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8203                    (match_operator:SI 2 "shift_operator"
8204                     [(match_operand:SI 3 "s_register_operand" "r")
8205                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8206          (const_int 0)))
8207    (set (match_operand:SI 0 "s_register_operand" "=r")
8208         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8209                                                  (match_dup 4)])))]
8210   "TARGET_ARM"
8211   "sub%?s\\t%0, %1, %3%S2"
8212   [(set_attr "conds" "set")
8213    (set_attr "shift" "3")
8214    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8215                       (const_string "alu_shift")
8216                       (const_string "alu_shift_reg")))]
8219 (define_insn "*sub_shiftsi_compare0_scratch"
8220   [(set (reg:CC_NOOV CC_REGNUM)
8221         (compare:CC_NOOV
8222          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8223                    (match_operator:SI 2 "shift_operator"
8224                     [(match_operand:SI 3 "s_register_operand" "r")
8225                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8226          (const_int 0)))
8227    (clobber (match_scratch:SI 0 "=r"))]
8228   "TARGET_ARM"
8229   "sub%?s\\t%0, %1, %3%S2"
8230   [(set_attr "conds" "set")
8231    (set_attr "shift" "3")
8232    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8233                       (const_string "alu_shift")
8234                       (const_string "alu_shift_reg")))]
8239 (define_insn "*and_scc"
8240   [(set (match_operand:SI 0 "s_register_operand" "=r")
8241         (and:SI (match_operator:SI 1 "arm_comparison_operator"
8242                  [(match_operand 3 "cc_register" "") (const_int 0)])
8243                 (match_operand:SI 2 "s_register_operand" "r")))]
8244   "TARGET_ARM"
8245   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8246   [(set_attr "conds" "use")
8247    (set_attr "length" "8")]
8250 (define_insn "*ior_scc"
8251   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8252         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8253                  [(match_operand 3 "cc_register" "") (const_int 0)])
8254                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8255   "TARGET_ARM"
8256   "@
8257    orr%d2\\t%0, %1, #1
8258    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8259   [(set_attr "conds" "use")
8260    (set_attr "length" "4,8")]
8263 (define_insn "*compare_scc"
8264   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8265         (match_operator:SI 1 "arm_comparison_operator"
8266          [(match_operand:SI 2 "s_register_operand" "r,r")
8267           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8268    (clobber (reg:CC CC_REGNUM))]
8269   "TARGET_ARM"
8270   "*
8271     if (operands[3] == const0_rtx)
8272       {
8273         if (GET_CODE (operands[1]) == LT)
8274           return \"mov\\t%0, %2, lsr #31\";
8276         if (GET_CODE (operands[1]) == GE)
8277           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8279         if (GET_CODE (operands[1]) == EQ)
8280           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8281       }
8283     if (GET_CODE (operands[1]) == NE)
8284       {
8285         if (which_alternative == 1)
8286           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8287         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8288       }
8289     if (which_alternative == 1)
8290       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8291     else
8292       output_asm_insn (\"cmp\\t%2, %3\", operands);
8293     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8294   "
8295   [(set_attr "conds" "clob")
8296    (set_attr "length" "12")]
8299 (define_insn "*cond_move"
8300   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8301         (if_then_else:SI (match_operator 3 "equality_operator"
8302                           [(match_operator 4 "arm_comparison_operator"
8303                             [(match_operand 5 "cc_register" "") (const_int 0)])
8304                            (const_int 0)])
8305                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8306                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8307   "TARGET_ARM"
8308   "*
8309     if (GET_CODE (operands[3]) == NE)
8310       {
8311         if (which_alternative != 1)
8312           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8313         if (which_alternative != 0)
8314           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8315         return \"\";
8316       }
8317     if (which_alternative != 0)
8318       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8319     if (which_alternative != 1)
8320       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8321     return \"\";
8322   "
8323   [(set_attr "conds" "use")
8324    (set_attr "length" "4,4,8")]
8327 (define_insn "*cond_arith"
8328   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8329         (match_operator:SI 5 "shiftable_operator" 
8330          [(match_operator:SI 4 "arm_comparison_operator"
8331            [(match_operand:SI 2 "s_register_operand" "r,r")
8332             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8333           (match_operand:SI 1 "s_register_operand" "0,?r")]))
8334    (clobber (reg:CC CC_REGNUM))]
8335   "TARGET_ARM"
8336   "*
8337     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8338       return \"%i5\\t%0, %1, %2, lsr #31\";
8340     output_asm_insn (\"cmp\\t%2, %3\", operands);
8341     if (GET_CODE (operands[5]) == AND)
8342       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8343     else if (GET_CODE (operands[5]) == MINUS)
8344       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8345     else if (which_alternative != 0)
8346       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8347     return \"%i5%d4\\t%0, %1, #1\";
8348   "
8349   [(set_attr "conds" "clob")
8350    (set_attr "length" "12")]
8353 (define_insn "*cond_sub"
8354   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8355         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8356                   (match_operator:SI 4 "arm_comparison_operator"
8357                    [(match_operand:SI 2 "s_register_operand" "r,r")
8358                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8359    (clobber (reg:CC CC_REGNUM))]
8360   "TARGET_ARM"
8361   "*
8362     output_asm_insn (\"cmp\\t%2, %3\", operands);
8363     if (which_alternative != 0)
8364       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8365     return \"sub%d4\\t%0, %1, #1\";
8366   "
8367   [(set_attr "conds" "clob")
8368    (set_attr "length" "8,12")]
8371 (define_insn "*cmp_ite0"
8372   [(set (match_operand 6 "dominant_cc_register" "")
8373         (compare
8374          (if_then_else:SI
8375           (match_operator 4 "arm_comparison_operator"
8376            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8377             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8378           (match_operator:SI 5 "arm_comparison_operator"
8379            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8380             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8381           (const_int 0))
8382          (const_int 0)))]
8383   "TARGET_ARM"
8384   "*
8385   {
8386     static const char * const opcodes[4][2] =
8387     {
8388       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8389        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8390       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8391        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8392       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8393        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8394       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8395        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8396     };
8397     int swap =
8398       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8400     return opcodes[which_alternative][swap];
8401   }"
8402   [(set_attr "conds" "set")
8403    (set_attr "length" "8")]
8406 (define_insn "*cmp_ite1"
8407   [(set (match_operand 6 "dominant_cc_register" "")
8408         (compare
8409          (if_then_else:SI
8410           (match_operator 4 "arm_comparison_operator"
8411            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8412             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8413           (match_operator:SI 5 "arm_comparison_operator"
8414            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8415             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8416           (const_int 1))
8417          (const_int 0)))]
8418   "TARGET_ARM"
8419   "*
8420   {
8421     static const char * const opcodes[4][2] =
8422     {
8423       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8424        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8425       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8426        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8427       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8428        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8429       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8430        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8431     };
8432     int swap =
8433       comparison_dominates_p (GET_CODE (operands[5]),
8434                               reverse_condition (GET_CODE (operands[4])));
8436     return opcodes[which_alternative][swap];
8437   }"
8438   [(set_attr "conds" "set")
8439    (set_attr "length" "8")]
8442 (define_insn "*cmp_and"
8443   [(set (match_operand 6 "dominant_cc_register" "")
8444         (compare
8445          (and:SI
8446           (match_operator 4 "arm_comparison_operator"
8447            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8448             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8449           (match_operator:SI 5 "arm_comparison_operator"
8450            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8451             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8452          (const_int 0)))]
8453   "TARGET_ARM"
8454   "*
8455   {
8456     static const char *const opcodes[4][2] =
8457     {
8458       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8459        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8460       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8461        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8462       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8463        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8464       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8465        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8466     };
8467     int swap =
8468       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8470     return opcodes[which_alternative][swap];
8471   }"
8472   [(set_attr "conds" "set")
8473    (set_attr "predicable" "no")
8474    (set_attr "length" "8")]
8477 (define_insn "*cmp_ior"
8478   [(set (match_operand 6 "dominant_cc_register" "")
8479         (compare
8480          (ior:SI
8481           (match_operator 4 "arm_comparison_operator"
8482            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8483             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8484           (match_operator:SI 5 "arm_comparison_operator"
8485            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8486             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8487          (const_int 0)))]
8488   "TARGET_ARM"
8489   "*
8491   static const char *const opcodes[4][2] =
8492   {
8493     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8494      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8495     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8496      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8497     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8498      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8499     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8500      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8501   };
8502   int swap =
8503     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8505   return opcodes[which_alternative][swap];
8508   [(set_attr "conds" "set")
8509    (set_attr "length" "8")]
8512 (define_insn_and_split "*ior_scc_scc"
8513   [(set (match_operand:SI 0 "s_register_operand" "=r")
8514         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8515                  [(match_operand:SI 1 "s_register_operand" "r")
8516                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8517                 (match_operator:SI 6 "arm_comparison_operator"
8518                  [(match_operand:SI 4 "s_register_operand" "r")
8519                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8520    (clobber (reg:CC CC_REGNUM))]
8521   "TARGET_ARM
8522    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8523        != CCmode)"
8524   "#"
8525   "TARGET_ARM && reload_completed"
8526   [(set (match_dup 7)
8527         (compare
8528          (ior:SI
8529           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8530           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8531          (const_int 0)))
8532    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8533   "operands[7]
8534      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8535                                                   DOM_CC_X_OR_Y),
8536                     CC_REGNUM);"
8537   [(set_attr "conds" "clob")
8538    (set_attr "length" "16")])
8540 ; If the above pattern is followed by a CMP insn, then the compare is 
8541 ; redundant, since we can rework the conditional instruction that follows.
8542 (define_insn_and_split "*ior_scc_scc_cmp"
8543   [(set (match_operand 0 "dominant_cc_register" "")
8544         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8545                           [(match_operand:SI 1 "s_register_operand" "r")
8546                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8547                          (match_operator:SI 6 "arm_comparison_operator"
8548                           [(match_operand:SI 4 "s_register_operand" "r")
8549                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8550                  (const_int 0)))
8551    (set (match_operand:SI 7 "s_register_operand" "=r")
8552         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8553                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8554   "TARGET_ARM"
8555   "#"
8556   "TARGET_ARM && reload_completed"
8557   [(set (match_dup 0)
8558         (compare
8559          (ior:SI
8560           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8561           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8562          (const_int 0)))
8563    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8564   ""
8565   [(set_attr "conds" "set")
8566    (set_attr "length" "16")])
8568 (define_insn_and_split "*and_scc_scc"
8569   [(set (match_operand:SI 0 "s_register_operand" "=r")
8570         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8571                  [(match_operand:SI 1 "s_register_operand" "r")
8572                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8573                 (match_operator:SI 6 "arm_comparison_operator"
8574                  [(match_operand:SI 4 "s_register_operand" "r")
8575                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8576    (clobber (reg:CC CC_REGNUM))]
8577   "TARGET_ARM
8578    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8579        != CCmode)"
8580   "#"
8581   "TARGET_ARM && reload_completed
8582    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8583        != CCmode)"
8584   [(set (match_dup 7)
8585         (compare
8586          (and:SI
8587           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8588           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8589          (const_int 0)))
8590    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8591   "operands[7]
8592      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8593                                                   DOM_CC_X_AND_Y),
8594                     CC_REGNUM);"
8595   [(set_attr "conds" "clob")
8596    (set_attr "length" "16")])
8598 ; If the above pattern is followed by a CMP insn, then the compare is 
8599 ; redundant, since we can rework the conditional instruction that follows.
8600 (define_insn_and_split "*and_scc_scc_cmp"
8601   [(set (match_operand 0 "dominant_cc_register" "")
8602         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8603                           [(match_operand:SI 1 "s_register_operand" "r")
8604                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8605                          (match_operator:SI 6 "arm_comparison_operator"
8606                           [(match_operand:SI 4 "s_register_operand" "r")
8607                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8608                  (const_int 0)))
8609    (set (match_operand:SI 7 "s_register_operand" "=r")
8610         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8611                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8612   "TARGET_ARM"
8613   "#"
8614   "TARGET_ARM && reload_completed"
8615   [(set (match_dup 0)
8616         (compare
8617          (and:SI
8618           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8619           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8620          (const_int 0)))
8621    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8622   ""
8623   [(set_attr "conds" "set")
8624    (set_attr "length" "16")])
8626 ;; If there is no dominance in the comparison, then we can still save an
8627 ;; instruction in the AND case, since we can know that the second compare
8628 ;; need only zero the value if false (if true, then the value is already
8629 ;; correct).
8630 (define_insn_and_split "*and_scc_scc_nodom"
8631   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8632         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8633                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
8634                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8635                 (match_operator:SI 6 "arm_comparison_operator"
8636                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
8637                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8638    (clobber (reg:CC CC_REGNUM))]
8639   "TARGET_ARM
8640    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8641        == CCmode)"
8642   "#"
8643   "TARGET_ARM && reload_completed"
8644   [(parallel [(set (match_dup 0)
8645                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8646               (clobber (reg:CC CC_REGNUM))])
8647    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8648    (set (match_dup 0)
8649         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8650                          (match_dup 0)
8651                          (const_int 0)))]
8652   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8653                                               operands[4], operands[5]),
8654                               CC_REGNUM);
8655    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8656                                   operands[5]);"
8657   [(set_attr "conds" "clob")
8658    (set_attr "length" "20")])
8660 (define_split
8661   [(set (reg:CC_NOOV CC_REGNUM)
8662         (compare:CC_NOOV (ior:SI
8663                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8664                                   (const_int 1))
8665                           (match_operator:SI 1 "comparison_operator"
8666                            [(match_operand:SI 2 "s_register_operand" "")
8667                             (match_operand:SI 3 "arm_add_operand" "")]))
8668                          (const_int 0)))
8669    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8670   "TARGET_ARM"
8671   [(set (match_dup 4)
8672         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8673                 (match_dup 0)))
8674    (set (reg:CC_NOOV CC_REGNUM)
8675         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8676                          (const_int 0)))]
8677   "")
8679 (define_split
8680   [(set (reg:CC_NOOV CC_REGNUM)
8681         (compare:CC_NOOV (ior:SI
8682                           (match_operator:SI 1 "comparison_operator"
8683                            [(match_operand:SI 2 "s_register_operand" "")
8684                             (match_operand:SI 3 "arm_add_operand" "")])
8685                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8686                                   (const_int 1)))
8687                          (const_int 0)))
8688    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8689   "TARGET_ARM"
8690   [(set (match_dup 4)
8691         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8692                 (match_dup 0)))
8693    (set (reg:CC_NOOV CC_REGNUM)
8694         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8695                          (const_int 0)))]
8696   "")
8698 (define_insn "*negscc"
8699   [(set (match_operand:SI 0 "s_register_operand" "=r")
8700         (neg:SI (match_operator 3 "arm_comparison_operator"
8701                  [(match_operand:SI 1 "s_register_operand" "r")
8702                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8703    (clobber (reg:CC CC_REGNUM))]
8704   "TARGET_ARM"
8705   "*
8706   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8707     return \"mov\\t%0, %1, asr #31\";
8709   if (GET_CODE (operands[3]) == NE)
8710     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8712   if (GET_CODE (operands[3]) == GT)
8713     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8715   output_asm_insn (\"cmp\\t%1, %2\", operands);
8716   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8717   return \"mvn%d3\\t%0, #0\";
8718   "
8719   [(set_attr "conds" "clob")
8720    (set_attr "length" "12")]
8723 (define_insn "movcond"
8724   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8725         (if_then_else:SI
8726          (match_operator 5 "arm_comparison_operator"
8727           [(match_operand:SI 3 "s_register_operand" "r,r,r")
8728            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8729          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8730          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8731    (clobber (reg:CC CC_REGNUM))]
8732   "TARGET_ARM"
8733   "*
8734   if (GET_CODE (operands[5]) == LT
8735       && (operands[4] == const0_rtx))
8736     {
8737       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8738         {
8739           if (operands[2] == const0_rtx)
8740             return \"and\\t%0, %1, %3, asr #31\";
8741           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8742         }
8743       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8744         {
8745           if (operands[1] == const0_rtx)
8746             return \"bic\\t%0, %2, %3, asr #31\";
8747           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8748         }
8749       /* The only case that falls through to here is when both ops 1 & 2
8750          are constants.  */
8751     }
8753   if (GET_CODE (operands[5]) == GE
8754       && (operands[4] == const0_rtx))
8755     {
8756       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8757         {
8758           if (operands[2] == const0_rtx)
8759             return \"bic\\t%0, %1, %3, asr #31\";
8760           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8761         }
8762       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8763         {
8764           if (operands[1] == const0_rtx)
8765             return \"and\\t%0, %2, %3, asr #31\";
8766           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8767         }
8768       /* The only case that falls through to here is when both ops 1 & 2
8769          are constants.  */
8770     }
8771   if (GET_CODE (operands[4]) == CONST_INT
8772       && !const_ok_for_arm (INTVAL (operands[4])))
8773     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8774   else
8775     output_asm_insn (\"cmp\\t%3, %4\", operands);
8776   if (which_alternative != 0)
8777     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8778   if (which_alternative != 1)
8779     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8780   return \"\";
8781   "
8782   [(set_attr "conds" "clob")
8783    (set_attr "length" "8,8,12")]
8786 (define_insn "*ifcompare_plus_move"
8787   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8788         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8789                           [(match_operand:SI 4 "s_register_operand" "r,r")
8790                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8791                          (plus:SI
8792                           (match_operand:SI 2 "s_register_operand" "r,r")
8793                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8794                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8795    (clobber (reg:CC CC_REGNUM))]
8796   "TARGET_ARM"
8797   "#"
8798   [(set_attr "conds" "clob")
8799    (set_attr "length" "8,12")]
8802 (define_insn "*if_plus_move"
8803   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8804         (if_then_else:SI
8805          (match_operator 4 "arm_comparison_operator"
8806           [(match_operand 5 "cc_register" "") (const_int 0)])
8807          (plus:SI
8808           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8809           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8810          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8811   "TARGET_ARM"
8812   "@
8813    add%d4\\t%0, %2, %3
8814    sub%d4\\t%0, %2, #%n3
8815    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8816    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8817   [(set_attr "conds" "use")
8818    (set_attr "length" "4,4,8,8")
8819    (set_attr "type" "*,*,*,*")]
8822 (define_insn "*ifcompare_move_plus"
8823   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8824         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8825                           [(match_operand:SI 4 "s_register_operand" "r,r")
8826                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8827                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8828                          (plus:SI
8829                           (match_operand:SI 2 "s_register_operand" "r,r")
8830                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8831    (clobber (reg:CC CC_REGNUM))]
8832   "TARGET_ARM"
8833   "#"
8834   [(set_attr "conds" "clob")
8835    (set_attr "length" "8,12")]
8838 (define_insn "*if_move_plus"
8839   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8840         (if_then_else:SI
8841          (match_operator 4 "arm_comparison_operator"
8842           [(match_operand 5 "cc_register" "") (const_int 0)])
8843          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8844          (plus:SI
8845           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8846           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8847   "TARGET_ARM"
8848   "@
8849    add%D4\\t%0, %2, %3
8850    sub%D4\\t%0, %2, #%n3
8851    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8852    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8853   [(set_attr "conds" "use")
8854    (set_attr "length" "4,4,8,8")
8855    (set_attr "type" "*,*,*,*")]
8858 (define_insn "*ifcompare_arith_arith"
8859   [(set (match_operand:SI 0 "s_register_operand" "=r")
8860         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8861                           [(match_operand:SI 5 "s_register_operand" "r")
8862                            (match_operand:SI 6 "arm_add_operand" "rIL")])
8863                          (match_operator:SI 8 "shiftable_operator"
8864                           [(match_operand:SI 1 "s_register_operand" "r")
8865                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8866                          (match_operator:SI 7 "shiftable_operator"
8867                           [(match_operand:SI 3 "s_register_operand" "r")
8868                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8869    (clobber (reg:CC CC_REGNUM))]
8870   "TARGET_ARM"
8871   "#"
8872   [(set_attr "conds" "clob")
8873    (set_attr "length" "12")]
8876 (define_insn "*if_arith_arith"
8877   [(set (match_operand:SI 0 "s_register_operand" "=r")
8878         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8879                           [(match_operand 8 "cc_register" "") (const_int 0)])
8880                          (match_operator:SI 6 "shiftable_operator"
8881                           [(match_operand:SI 1 "s_register_operand" "r")
8882                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8883                          (match_operator:SI 7 "shiftable_operator"
8884                           [(match_operand:SI 3 "s_register_operand" "r")
8885                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8886   "TARGET_ARM"
8887   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8888   [(set_attr "conds" "use")
8889    (set_attr "length" "8")]
8892 (define_insn "*ifcompare_arith_move"
8893   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8894         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8895                           [(match_operand:SI 2 "s_register_operand" "r,r")
8896                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8897                          (match_operator:SI 7 "shiftable_operator"
8898                           [(match_operand:SI 4 "s_register_operand" "r,r")
8899                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8900                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8901    (clobber (reg:CC CC_REGNUM))]
8902   "TARGET_ARM"
8903   "*
8904   /* If we have an operation where (op x 0) is the identity operation and
8905      the conditional operator is LT or GE and we are comparing against zero and
8906      everything is in registers then we can do this in two instructions.  */
8907   if (operands[3] == const0_rtx
8908       && GET_CODE (operands[7]) != AND
8909       && GET_CODE (operands[5]) == REG
8910       && GET_CODE (operands[1]) == REG 
8911       && REGNO (operands[1]) == REGNO (operands[4])
8912       && REGNO (operands[4]) != REGNO (operands[0]))
8913     {
8914       if (GET_CODE (operands[6]) == LT)
8915         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8916       else if (GET_CODE (operands[6]) == GE)
8917         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8918     }
8919   if (GET_CODE (operands[3]) == CONST_INT
8920       && !const_ok_for_arm (INTVAL (operands[3])))
8921     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8922   else
8923     output_asm_insn (\"cmp\\t%2, %3\", operands);
8924   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8925   if (which_alternative != 0)
8926     return \"mov%D6\\t%0, %1\";
8927   return \"\";
8928   "
8929   [(set_attr "conds" "clob")
8930    (set_attr "length" "8,12")]
8933 (define_insn "*if_arith_move"
8934   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8935         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8936                           [(match_operand 6 "cc_register" "") (const_int 0)])
8937                          (match_operator:SI 5 "shiftable_operator"
8938                           [(match_operand:SI 2 "s_register_operand" "r,r")
8939                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8940                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8941   "TARGET_ARM"
8942   "@
8943    %I5%d4\\t%0, %2, %3
8944    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8945   [(set_attr "conds" "use")
8946    (set_attr "length" "4,8")
8947    (set_attr "type" "*,*")]
8950 (define_insn "*ifcompare_move_arith"
8951   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8952         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8953                           [(match_operand:SI 4 "s_register_operand" "r,r")
8954                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8955                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8956                          (match_operator:SI 7 "shiftable_operator"
8957                           [(match_operand:SI 2 "s_register_operand" "r,r")
8958                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8959    (clobber (reg:CC CC_REGNUM))]
8960   "TARGET_ARM"
8961   "*
8962   /* If we have an operation where (op x 0) is the identity operation and
8963      the conditional operator is LT or GE and we are comparing against zero and
8964      everything is in registers then we can do this in two instructions */
8965   if (operands[5] == const0_rtx
8966       && GET_CODE (operands[7]) != AND
8967       && GET_CODE (operands[3]) == REG
8968       && GET_CODE (operands[1]) == REG 
8969       && REGNO (operands[1]) == REGNO (operands[2])
8970       && REGNO (operands[2]) != REGNO (operands[0]))
8971     {
8972       if (GET_CODE (operands[6]) == GE)
8973         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8974       else if (GET_CODE (operands[6]) == LT)
8975         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8976     }
8978   if (GET_CODE (operands[5]) == CONST_INT
8979       && !const_ok_for_arm (INTVAL (operands[5])))
8980     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
8981   else
8982     output_asm_insn (\"cmp\\t%4, %5\", operands);
8984   if (which_alternative != 0)
8985     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
8986   return \"%I7%D6\\t%0, %2, %3\";
8987   "
8988   [(set_attr "conds" "clob")
8989    (set_attr "length" "8,12")]
8992 (define_insn "*if_move_arith"
8993   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8994         (if_then_else:SI
8995          (match_operator 4 "arm_comparison_operator"
8996           [(match_operand 6 "cc_register" "") (const_int 0)])
8997          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8998          (match_operator:SI 5 "shiftable_operator"
8999           [(match_operand:SI 2 "s_register_operand" "r,r")
9000            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
9001   "TARGET_ARM"
9002   "@
9003    %I5%D4\\t%0, %2, %3
9004    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
9005   [(set_attr "conds" "use")
9006    (set_attr "length" "4,8")
9007    (set_attr "type" "*,*")]
9010 (define_insn "*ifcompare_move_not"
9011   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9012         (if_then_else:SI
9013          (match_operator 5 "arm_comparison_operator"
9014           [(match_operand:SI 3 "s_register_operand" "r,r")
9015            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9016          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9017          (not:SI
9018           (match_operand:SI 2 "s_register_operand" "r,r"))))
9019    (clobber (reg:CC CC_REGNUM))]
9020   "TARGET_ARM"
9021   "#"
9022   [(set_attr "conds" "clob")
9023    (set_attr "length" "8,12")]
9026 (define_insn "*if_move_not"
9027   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9028         (if_then_else:SI
9029          (match_operator 4 "arm_comparison_operator"
9030           [(match_operand 3 "cc_register" "") (const_int 0)])
9031          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9032          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9033   "TARGET_ARM"
9034   "@
9035    mvn%D4\\t%0, %2
9036    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9037    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
9038   [(set_attr "conds" "use")
9039    (set_attr "length" "4,8,8")]
9042 (define_insn "*ifcompare_not_move"
9043   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9044         (if_then_else:SI 
9045          (match_operator 5 "arm_comparison_operator"
9046           [(match_operand:SI 3 "s_register_operand" "r,r")
9047            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9048          (not:SI
9049           (match_operand:SI 2 "s_register_operand" "r,r"))
9050          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9051    (clobber (reg:CC CC_REGNUM))]
9052   "TARGET_ARM"
9053   "#"
9054   [(set_attr "conds" "clob")
9055    (set_attr "length" "8,12")]
9058 (define_insn "*if_not_move"
9059   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9060         (if_then_else:SI
9061          (match_operator 4 "arm_comparison_operator"
9062           [(match_operand 3 "cc_register" "") (const_int 0)])
9063          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9064          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9065   "TARGET_ARM"
9066   "@
9067    mvn%d4\\t%0, %2
9068    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9069    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
9070   [(set_attr "conds" "use")
9071    (set_attr "length" "4,8,8")]
9074 (define_insn "*ifcompare_shift_move"
9075   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9076         (if_then_else:SI
9077          (match_operator 6 "arm_comparison_operator"
9078           [(match_operand:SI 4 "s_register_operand" "r,r")
9079            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9080          (match_operator:SI 7 "shift_operator"
9081           [(match_operand:SI 2 "s_register_operand" "r,r")
9082            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9083          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9084    (clobber (reg:CC CC_REGNUM))]
9085   "TARGET_ARM"
9086   "#"
9087   [(set_attr "conds" "clob")
9088    (set_attr "length" "8,12")]
9091 (define_insn "*if_shift_move"
9092   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9093         (if_then_else:SI
9094          (match_operator 5 "arm_comparison_operator"
9095           [(match_operand 6 "cc_register" "") (const_int 0)])
9096          (match_operator:SI 4 "shift_operator"
9097           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9098            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9099          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9100   "TARGET_ARM"
9101   "@
9102    mov%d5\\t%0, %2%S4
9103    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9104    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
9105   [(set_attr "conds" "use")
9106    (set_attr "shift" "2")
9107    (set_attr "length" "4,8,8")
9108    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9109                       (const_string "alu_shift")
9110                       (const_string "alu_shift_reg")))]
9113 (define_insn "*ifcompare_move_shift"
9114   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9115         (if_then_else:SI
9116          (match_operator 6 "arm_comparison_operator"
9117           [(match_operand:SI 4 "s_register_operand" "r,r")
9118            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9119          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9120          (match_operator:SI 7 "shift_operator"
9121           [(match_operand:SI 2 "s_register_operand" "r,r")
9122            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
9123    (clobber (reg:CC CC_REGNUM))]
9124   "TARGET_ARM"
9125   "#"
9126   [(set_attr "conds" "clob")
9127    (set_attr "length" "8,12")]
9130 (define_insn "*if_move_shift"
9131   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9132         (if_then_else:SI
9133          (match_operator 5 "arm_comparison_operator"
9134           [(match_operand 6 "cc_register" "") (const_int 0)])
9135          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9136          (match_operator:SI 4 "shift_operator"
9137           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9138            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
9139   "TARGET_ARM"
9140   "@
9141    mov%D5\\t%0, %2%S4
9142    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9143    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
9144   [(set_attr "conds" "use")
9145    (set_attr "shift" "2")
9146    (set_attr "length" "4,8,8")
9147    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9148                       (const_string "alu_shift")
9149                       (const_string "alu_shift_reg")))]
9152 (define_insn "*ifcompare_shift_shift"
9153   [(set (match_operand:SI 0 "s_register_operand" "=r")
9154         (if_then_else:SI
9155          (match_operator 7 "arm_comparison_operator"
9156           [(match_operand:SI 5 "s_register_operand" "r")
9157            (match_operand:SI 6 "arm_add_operand" "rIL")])
9158          (match_operator:SI 8 "shift_operator"
9159           [(match_operand:SI 1 "s_register_operand" "r")
9160            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9161          (match_operator:SI 9 "shift_operator"
9162           [(match_operand:SI 3 "s_register_operand" "r")
9163            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
9164    (clobber (reg:CC CC_REGNUM))]
9165   "TARGET_ARM"
9166   "#"
9167   [(set_attr "conds" "clob")
9168    (set_attr "length" "12")]
9171 (define_insn "*if_shift_shift"
9172   [(set (match_operand:SI 0 "s_register_operand" "=r")
9173         (if_then_else:SI
9174          (match_operator 5 "arm_comparison_operator"
9175           [(match_operand 8 "cc_register" "") (const_int 0)])
9176          (match_operator:SI 6 "shift_operator"
9177           [(match_operand:SI 1 "s_register_operand" "r")
9178            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9179          (match_operator:SI 7 "shift_operator"
9180           [(match_operand:SI 3 "s_register_operand" "r")
9181            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
9182   "TARGET_ARM"
9183   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
9184   [(set_attr "conds" "use")
9185    (set_attr "shift" "1")
9186    (set_attr "length" "8")
9187    (set (attr "type") (if_then_else
9188                         (and (match_operand 2 "const_int_operand" "")
9189                              (match_operand 4 "const_int_operand" ""))
9190                       (const_string "alu_shift")
9191                       (const_string "alu_shift_reg")))]
9194 (define_insn "*ifcompare_not_arith"
9195   [(set (match_operand:SI 0 "s_register_operand" "=r")
9196         (if_then_else:SI
9197          (match_operator 6 "arm_comparison_operator"
9198           [(match_operand:SI 4 "s_register_operand" "r")
9199            (match_operand:SI 5 "arm_add_operand" "rIL")])
9200          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9201          (match_operator:SI 7 "shiftable_operator"
9202           [(match_operand:SI 2 "s_register_operand" "r")
9203            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
9204    (clobber (reg:CC CC_REGNUM))]
9205   "TARGET_ARM"
9206   "#"
9207   [(set_attr "conds" "clob")
9208    (set_attr "length" "12")]
9211 (define_insn "*if_not_arith"
9212   [(set (match_operand:SI 0 "s_register_operand" "=r")
9213         (if_then_else:SI
9214          (match_operator 5 "arm_comparison_operator"
9215           [(match_operand 4 "cc_register" "") (const_int 0)])
9216          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9217          (match_operator:SI 6 "shiftable_operator"
9218           [(match_operand:SI 2 "s_register_operand" "r")
9219            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
9220   "TARGET_ARM"
9221   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
9222   [(set_attr "conds" "use")
9223    (set_attr "length" "8")]
9226 (define_insn "*ifcompare_arith_not"
9227   [(set (match_operand:SI 0 "s_register_operand" "=r")
9228         (if_then_else:SI
9229          (match_operator 6 "arm_comparison_operator"
9230           [(match_operand:SI 4 "s_register_operand" "r")
9231            (match_operand:SI 5 "arm_add_operand" "rIL")])
9232          (match_operator:SI 7 "shiftable_operator"
9233           [(match_operand:SI 2 "s_register_operand" "r")
9234            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9235          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9236    (clobber (reg:CC CC_REGNUM))]
9237   "TARGET_ARM"
9238   "#"
9239   [(set_attr "conds" "clob")
9240    (set_attr "length" "12")]
9243 (define_insn "*if_arith_not"
9244   [(set (match_operand:SI 0 "s_register_operand" "=r")
9245         (if_then_else:SI
9246          (match_operator 5 "arm_comparison_operator"
9247           [(match_operand 4 "cc_register" "") (const_int 0)])
9248          (match_operator:SI 6 "shiftable_operator"
9249           [(match_operand:SI 2 "s_register_operand" "r")
9250            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9251          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9252   "TARGET_ARM"
9253   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9254   [(set_attr "conds" "use")
9255    (set_attr "length" "8")]
9258 (define_insn "*ifcompare_neg_move"
9259   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9260         (if_then_else:SI
9261          (match_operator 5 "arm_comparison_operator"
9262           [(match_operand:SI 3 "s_register_operand" "r,r")
9263            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9264          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9265          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9266    (clobber (reg:CC CC_REGNUM))]
9267   "TARGET_ARM"
9268   "#"
9269   [(set_attr "conds" "clob")
9270    (set_attr "length" "8,12")]
9273 (define_insn "*if_neg_move"
9274   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9275         (if_then_else:SI
9276          (match_operator 4 "arm_comparison_operator"
9277           [(match_operand 3 "cc_register" "") (const_int 0)])
9278          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9279          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9280   "TARGET_ARM"
9281   "@
9282    rsb%d4\\t%0, %2, #0
9283    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9284    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9285   [(set_attr "conds" "use")
9286    (set_attr "length" "4,8,8")]
9289 (define_insn "*ifcompare_move_neg"
9290   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9291         (if_then_else:SI
9292          (match_operator 5 "arm_comparison_operator"
9293           [(match_operand:SI 3 "s_register_operand" "r,r")
9294            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9295          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9296          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9297    (clobber (reg:CC CC_REGNUM))]
9298   "TARGET_ARM"
9299   "#"
9300   [(set_attr "conds" "clob")
9301    (set_attr "length" "8,12")]
9304 (define_insn "*if_move_neg"
9305   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9306         (if_then_else:SI
9307          (match_operator 4 "arm_comparison_operator"
9308           [(match_operand 3 "cc_register" "") (const_int 0)])
9309          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9310          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9311   "TARGET_ARM"
9312   "@
9313    rsb%D4\\t%0, %2, #0
9314    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9315    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9316   [(set_attr "conds" "use")
9317    (set_attr "length" "4,8,8")]
9320 (define_insn "*arith_adjacentmem"
9321   [(set (match_operand:SI 0 "s_register_operand" "=r")
9322         (match_operator:SI 1 "shiftable_operator"
9323          [(match_operand:SI 2 "memory_operand" "m")
9324           (match_operand:SI 3 "memory_operand" "m")]))
9325    (clobber (match_scratch:SI 4 "=r"))]
9326   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9327   "*
9328   {
9329     rtx ldm[3];
9330     rtx arith[4];
9331     rtx base_reg;
9332     HOST_WIDE_INT val1 = 0, val2 = 0;
9334     if (REGNO (operands[0]) > REGNO (operands[4]))
9335       {
9336         ldm[1] = operands[4];
9337         ldm[2] = operands[0];
9338       }
9339     else
9340       {
9341         ldm[1] = operands[0];
9342         ldm[2] = operands[4];
9343       }
9345     base_reg = XEXP (operands[2], 0);
9347     if (!REG_P (base_reg))
9348       {
9349         val1 = INTVAL (XEXP (base_reg, 1));
9350         base_reg = XEXP (base_reg, 0);
9351       }
9353     if (!REG_P (XEXP (operands[3], 0)))
9354       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9356     arith[0] = operands[0];
9357     arith[3] = operands[1];
9359     if (val1 < val2)
9360       {
9361         arith[1] = ldm[1];
9362         arith[2] = ldm[2];
9363       }
9364     else
9365       {
9366         arith[1] = ldm[2];
9367         arith[2] = ldm[1];
9368       }
9370     ldm[0] = base_reg;
9371     if (val1 !=0 && val2 != 0)
9372       {
9373         if (val1 == 4 || val2 == 4)
9374           /* Other val must be 8, since we know they are adjacent and neither
9375              is zero.  */
9376           output_asm_insn (\"ldm%?ib\\t%0, {%1, %2}\", ldm);
9377         else
9378           {
9379             rtx ops[3];
9381             ldm[0] = ops[0] = operands[4];
9382             ops[1] = base_reg;
9383             ops[2] = GEN_INT (val1);
9384             output_add_immediate (ops);
9385             if (val1 < val2)
9386               output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9387             else
9388               output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9389           }
9390       }
9391     else if (val1 != 0)
9392       {
9393         if (val1 < val2)
9394           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9395         else
9396           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9397       }
9398     else
9399       {
9400         if (val1 < val2)
9401           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9402         else
9403           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9404       }
9405     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9406     return \"\";
9407   }"
9408   [(set_attr "length" "12")
9409    (set_attr "predicable" "yes")
9410    (set_attr "type" "load1")]
9413 ;; the arm can support extended pre-inc instructions
9415 ;; In all these cases, we use operands 0 and 1 for the register being
9416 ;; incremented because those are the operands that local-alloc will
9417 ;; tie and these are the pair most likely to be tieable (and the ones
9418 ;; that will benefit the most).
9420 ;; We reject the frame pointer if it occurs anywhere in these patterns since
9421 ;; elimination will cause too many headaches.
9423 (define_insn "*strqi_preinc"
9424   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9425                          (match_operand:SI 2 "index_operand" "rJ")))
9426         (match_operand:QI 3 "s_register_operand" "r"))
9427    (set (match_operand:SI 0 "s_register_operand" "=r")
9428         (plus:SI (match_dup 1) (match_dup 2)))]
9429   "TARGET_ARM
9430    && !arm_eliminable_register (operands[0])
9431    && !arm_eliminable_register (operands[1])
9432    && !arm_eliminable_register (operands[2])"
9433   "str%?b\\t%3, [%0, %2]!"
9434   [(set_attr "type" "store1")
9435    (set_attr "predicable" "yes")]
9438 (define_insn "*strqi_predec"
9439   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9440                           (match_operand:SI 2 "s_register_operand" "r")))
9441         (match_operand:QI 3 "s_register_operand" "r"))
9442    (set (match_operand:SI 0 "s_register_operand" "=r")
9443         (minus:SI (match_dup 1) (match_dup 2)))]
9444   "TARGET_ARM
9445    && !arm_eliminable_register (operands[0])
9446    && !arm_eliminable_register (operands[1])
9447    && !arm_eliminable_register (operands[2])"
9448   "str%?b\\t%3, [%0, -%2]!"
9449   [(set_attr "type" "store1")
9450    (set_attr "predicable" "yes")]
9453 (define_insn "*loadqi_preinc"
9454   [(set (match_operand:QI 3 "s_register_operand" "=r")
9455         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9456                          (match_operand:SI 2 "index_operand" "rJ"))))
9457    (set (match_operand:SI 0 "s_register_operand" "=r")
9458         (plus:SI (match_dup 1) (match_dup 2)))]
9459   "TARGET_ARM
9460    && !arm_eliminable_register (operands[0])
9461    && !arm_eliminable_register (operands[1])
9462    && !arm_eliminable_register (operands[2])"
9463   "ldr%?b\\t%3, [%0, %2]!"
9464   [(set_attr "type" "load_byte")
9465    (set_attr "predicable" "yes")]
9468 (define_insn "*loadqi_predec"
9469   [(set (match_operand:QI 3 "s_register_operand" "=r")
9470         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9471                           (match_operand:SI 2 "s_register_operand" "r"))))
9472    (set (match_operand:SI 0 "s_register_operand" "=r")
9473         (minus:SI (match_dup 1) (match_dup 2)))]
9474   "TARGET_ARM
9475    && !arm_eliminable_register (operands[0])
9476    && !arm_eliminable_register (operands[1])
9477    && !arm_eliminable_register (operands[2])"
9478   "ldr%?b\\t%3, [%0, -%2]!"
9479   [(set_attr "type" "load_byte")
9480    (set_attr "predicable" "yes")]
9483 (define_insn "*loadqisi_preinc"
9484   [(set (match_operand:SI 3 "s_register_operand" "=r")
9485         (zero_extend:SI
9486          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9487                           (match_operand:SI 2 "index_operand" "rJ")))))
9488    (set (match_operand:SI 0 "s_register_operand" "=r")
9489         (plus:SI (match_dup 1) (match_dup 2)))]
9490   "TARGET_ARM
9491    && !arm_eliminable_register (operands[0])
9492    && !arm_eliminable_register (operands[1])
9493    && !arm_eliminable_register (operands[2])"
9494   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
9495   [(set_attr "type" "load_byte")
9496    (set_attr "predicable" "yes")]
9499 (define_insn "*loadqisi_predec"
9500   [(set (match_operand:SI 3 "s_register_operand" "=r")
9501         (zero_extend:SI
9502          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9503                            (match_operand:SI 2 "s_register_operand" "r")))))
9504    (set (match_operand:SI 0 "s_register_operand" "=r")
9505         (minus:SI (match_dup 1) (match_dup 2)))]
9506   "TARGET_ARM
9507    && !arm_eliminable_register (operands[0])
9508    && !arm_eliminable_register (operands[1])
9509    && !arm_eliminable_register (operands[2])"
9510   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
9511   [(set_attr "type" "load_byte")
9512    (set_attr "predicable" "yes")]
9515 (define_insn "*strsi_preinc"
9516   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9517                          (match_operand:SI 2 "index_operand" "rJ")))
9518         (match_operand:SI 3 "s_register_operand" "r"))
9519    (set (match_operand:SI 0 "s_register_operand" "=r")
9520         (plus:SI (match_dup 1) (match_dup 2)))]
9521   "TARGET_ARM
9522    && !arm_eliminable_register (operands[0])
9523    && !arm_eliminable_register (operands[1])
9524    && !arm_eliminable_register (operands[2])"
9525   "str%?\\t%3, [%0, %2]!"
9526   [(set_attr "type" "store1")
9527    (set_attr "predicable" "yes")]
9530 (define_insn "*strsi_predec"
9531   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9532                           (match_operand:SI 2 "s_register_operand" "r")))
9533         (match_operand:SI 3 "s_register_operand" "r"))
9534    (set (match_operand:SI 0 "s_register_operand" "=r")
9535         (minus:SI (match_dup 1) (match_dup 2)))]
9536   "TARGET_ARM
9537    && !arm_eliminable_register (operands[0])
9538    && !arm_eliminable_register (operands[1])
9539    && !arm_eliminable_register (operands[2])"
9540   "str%?\\t%3, [%0, -%2]!"
9541   [(set_attr "type" "store1")
9542    (set_attr "predicable" "yes")]
9545 (define_insn "*loadsi_preinc"
9546   [(set (match_operand:SI 3 "s_register_operand" "=r")
9547         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9548                          (match_operand:SI 2 "index_operand" "rJ"))))
9549    (set (match_operand:SI 0 "s_register_operand" "=r")
9550         (plus:SI (match_dup 1) (match_dup 2)))]
9551   "TARGET_ARM
9552    && !arm_eliminable_register (operands[0])
9553    && !arm_eliminable_register (operands[1])
9554    && !arm_eliminable_register (operands[2])"
9555   "ldr%?\\t%3, [%0, %2]!"
9556   [(set_attr "type" "load1")
9557    (set_attr "predicable" "yes")]
9560 (define_insn "*loadsi_predec"
9561   [(set (match_operand:SI 3 "s_register_operand" "=r")
9562         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9563                           (match_operand:SI 2 "s_register_operand" "r"))))
9564    (set (match_operand:SI 0 "s_register_operand" "=r")
9565         (minus:SI (match_dup 1) (match_dup 2)))]
9566   "TARGET_ARM
9567    && !arm_eliminable_register (operands[0])
9568    && !arm_eliminable_register (operands[1])
9569    && !arm_eliminable_register (operands[2])"
9570   "ldr%?\\t%3, [%0, -%2]!"
9571   [(set_attr "type" "load1")
9572    (set_attr "predicable" "yes")]
9575 (define_insn "*strqi_shiftpreinc"
9576   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9577                           [(match_operand:SI 3 "s_register_operand" "r")
9578                            (match_operand:SI 4 "const_shift_operand" "n")])
9579                          (match_operand:SI 1 "s_register_operand" "0")))
9580         (match_operand:QI 5 "s_register_operand" "r"))
9581    (set (match_operand:SI 0 "s_register_operand" "=r")
9582         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9583                  (match_dup 1)))]
9584   "TARGET_ARM
9585    && !arm_eliminable_register (operands[0])
9586    && !arm_eliminable_register (operands[1])
9587    && !arm_eliminable_register (operands[3])"
9588   "str%?b\\t%5, [%0, %3%S2]!"
9589   [(set_attr "type" "store1")
9590    (set_attr "predicable" "yes")]
9593 (define_insn "*strqi_shiftpredec"
9594   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9595                           (match_operator:SI 2 "shift_operator"
9596                            [(match_operand:SI 3 "s_register_operand" "r")
9597                             (match_operand:SI 4 "const_shift_operand" "n")])))
9598         (match_operand:QI 5 "s_register_operand" "r"))
9599    (set (match_operand:SI 0 "s_register_operand" "=r")
9600         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9601                                                  (match_dup 4)])))]
9602   "TARGET_ARM
9603    && !arm_eliminable_register (operands[0])
9604    && !arm_eliminable_register (operands[1])
9605    && !arm_eliminable_register (operands[3])"
9606   "str%?b\\t%5, [%0, -%3%S2]!"
9607   [(set_attr "type" "store1")
9608    (set_attr "predicable" "yes")]
9611 (define_insn "*loadqi_shiftpreinc"
9612   [(set (match_operand:QI 5 "s_register_operand" "=r")
9613         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9614                           [(match_operand:SI 3 "s_register_operand" "r")
9615                            (match_operand:SI 4 "const_shift_operand" "n")])
9616                          (match_operand:SI 1 "s_register_operand" "0"))))
9617    (set (match_operand:SI 0 "s_register_operand" "=r")
9618         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9619                  (match_dup 1)))]
9620   "TARGET_ARM
9621    && !arm_eliminable_register (operands[0])
9622    && !arm_eliminable_register (operands[1])
9623    && !arm_eliminable_register (operands[3])"
9624   "ldr%?b\\t%5, [%0, %3%S2]!"
9625   [(set_attr "type" "load_byte")
9626    (set_attr "predicable" "yes")]
9629 (define_insn "*loadqi_shiftpredec"
9630   [(set (match_operand:QI 5 "s_register_operand" "=r")
9631         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9632                           (match_operator:SI 2 "shift_operator"
9633                            [(match_operand:SI 3 "s_register_operand" "r")
9634                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9635    (set (match_operand:SI 0 "s_register_operand" "=r")
9636         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9637                                                  (match_dup 4)])))]
9638   "TARGET_ARM
9639    && !arm_eliminable_register (operands[0])
9640    && !arm_eliminable_register (operands[1])
9641    && !arm_eliminable_register (operands[3])"
9642   "ldr%?b\\t%5, [%0, -%3%S2]!"
9643   [(set_attr "type" "load_byte")
9644    (set_attr "predicable" "yes")]
9647 (define_insn "*strsi_shiftpreinc"
9648   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9649                           [(match_operand:SI 3 "s_register_operand" "r")
9650                            (match_operand:SI 4 "const_shift_operand" "n")])
9651                          (match_operand:SI 1 "s_register_operand" "0")))
9652         (match_operand:SI 5 "s_register_operand" "r"))
9653    (set (match_operand:SI 0 "s_register_operand" "=r")
9654         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9655                  (match_dup 1)))]
9656   "TARGET_ARM
9657    && !arm_eliminable_register (operands[0])
9658    && !arm_eliminable_register (operands[1])
9659    && !arm_eliminable_register (operands[3])"
9660   "str%?\\t%5, [%0, %3%S2]!"
9661   [(set_attr "type" "store1")
9662    (set_attr "predicable" "yes")]
9665 (define_insn "*strsi_shiftpredec"
9666   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9667                           (match_operator:SI 2 "shift_operator"
9668                            [(match_operand:SI 3 "s_register_operand" "r")
9669                             (match_operand:SI 4 "const_shift_operand" "n")])))
9670         (match_operand:SI 5 "s_register_operand" "r"))
9671    (set (match_operand:SI 0 "s_register_operand" "=r")
9672         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9673                                                  (match_dup 4)])))]
9674   "TARGET_ARM
9675    && !arm_eliminable_register (operands[0])
9676    && !arm_eliminable_register (operands[1])
9677    && !arm_eliminable_register (operands[3])"
9678   "str%?\\t%5, [%0, -%3%S2]!"
9679   [(set_attr "type" "store1")
9680    (set_attr "predicable" "yes")]
9683 (define_insn "*loadsi_shiftpreinc"
9684   [(set (match_operand:SI 5 "s_register_operand" "=r")
9685         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9686                           [(match_operand:SI 3 "s_register_operand" "r")
9687                            (match_operand:SI 4 "const_shift_operand" "n")])
9688                          (match_operand:SI 1 "s_register_operand" "0"))))
9689    (set (match_operand:SI 0 "s_register_operand" "=r")
9690         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9691                  (match_dup 1)))]
9692   "TARGET_ARM
9693    && !arm_eliminable_register (operands[0])
9694    && !arm_eliminable_register (operands[1])
9695    && !arm_eliminable_register (operands[3])"
9696   "ldr%?\\t%5, [%0, %3%S2]!"
9697   [(set_attr "type" "load1")
9698    (set_attr "predicable" "yes")]
9701 (define_insn "*loadsi_shiftpredec"
9702   [(set (match_operand:SI 5 "s_register_operand" "=r")
9703         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9704                           (match_operator:SI 2 "shift_operator"
9705                            [(match_operand:SI 3 "s_register_operand" "r")
9706                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9707    (set (match_operand:SI 0 "s_register_operand" "=r")
9708         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9709                                                  (match_dup 4)])))]
9710   "TARGET_ARM
9711    && !arm_eliminable_register (operands[0])
9712    && !arm_eliminable_register (operands[1])
9713    && !arm_eliminable_register (operands[3])"
9714   "ldr%?\\t%5, [%0, -%3%S2]!"
9715   [(set_attr "type" "load1")
9716    (set_attr "predicable" "yes")])
9718 ; It can also support extended post-inc expressions, but combine doesn't
9719 ; try these....
9720 ; It doesn't seem worth adding peepholes for anything but the most common
9721 ; cases since, unlike combine, the increment must immediately follow the load
9722 ; for this pattern to match.
9723 ; We must watch to see that the source/destination register isn't also the
9724 ; same as the base address register, and that if the index is a register,
9725 ; that it is not the same as the base address register.  In such cases the
9726 ; instruction that we would generate would have UNPREDICTABLE behavior so 
9727 ; we cannot use it.
9729 (define_peephole
9730   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9731         (match_operand:QI 2 "s_register_operand" "r"))
9732    (set (match_dup 0)
9733         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9734   "TARGET_ARM
9735    && (REGNO (operands[2]) != REGNO (operands[0]))
9736    && (GET_CODE (operands[1]) != REG
9737        || (REGNO (operands[1]) != REGNO (operands[0])))"
9738   "str%?b\\t%2, [%0], %1"
9741 (define_peephole
9742   [(set (match_operand:QI 0 "s_register_operand" "=r")
9743         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9744    (set (match_dup 1)
9745         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9746   "TARGET_ARM
9747    && REGNO (operands[0]) != REGNO(operands[1])
9748    && (GET_CODE (operands[2]) != REG
9749        || REGNO(operands[0]) != REGNO (operands[2]))"
9750   "ldr%?b\\t%0, [%1], %2"
9753 (define_peephole
9754   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9755         (match_operand:SI 2 "s_register_operand" "r"))
9756    (set (match_dup 0)
9757         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9758   "TARGET_ARM
9759    && (REGNO (operands[2]) != REGNO (operands[0]))
9760    && (GET_CODE (operands[1]) != REG
9761        || (REGNO (operands[1]) != REGNO (operands[0])))"
9762   "str%?\\t%2, [%0], %1"
9765 (define_peephole
9766   [(set (match_operand:SI 0 "s_register_operand" "=r")
9767         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9768    (set (match_dup 1)
9769         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9770   "TARGET_ARM
9771    && REGNO (operands[0]) != REGNO(operands[1])
9772    && (GET_CODE (operands[2]) != REG
9773        || REGNO(operands[0]) != REGNO (operands[2]))"
9774   "ldr%?\\t%0, [%1], %2"
9777 (define_peephole
9778   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9779                          (match_operand:SI 1 "index_operand" "rJ")))
9780         (match_operand:QI 2 "s_register_operand" "r"))
9781    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
9782   "TARGET_ARM
9783    && (REGNO (operands[2]) != REGNO (operands[0]))
9784    && (GET_CODE (operands[1]) != REG
9785        || (REGNO (operands[1]) != REGNO (operands[0])))"
9786   "str%?b\\t%2, [%0, %1]!"
9789 (define_peephole
9790   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9791                           [(match_operand:SI 0 "s_register_operand" "r")
9792                            (match_operand:SI 1 "const_int_operand" "n")])
9793                          (match_operand:SI 2 "s_register_operand" "+r")))
9794         (match_operand:QI 3 "s_register_operand" "r"))
9795    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9796                                (match_dup 2)))]
9797   "TARGET_ARM
9798    && (REGNO (operands[3]) != REGNO (operands[2]))
9799    && (REGNO (operands[0]) != REGNO (operands[2]))"
9800   "str%?b\\t%3, [%2, %0%S4]!"
9803 ; This pattern is never tried by combine, so do it as a peephole
9805 (define_peephole2
9806   [(set (match_operand:SI 0 "arm_general_register_operand" "")
9807         (match_operand:SI 1 "arm_general_register_operand" ""))
9808    (set (reg:CC CC_REGNUM)
9809         (compare:CC (match_dup 1) (const_int 0)))]
9810   "TARGET_ARM"
9811   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9812               (set (match_dup 0) (match_dup 1))])]
9813   ""
9816 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9817 ; reversed, check that the memory references aren't volatile.
9819 (define_peephole
9820   [(set (match_operand:SI 0 "s_register_operand" "=r")
9821         (match_operand:SI 4 "memory_operand" "m"))
9822    (set (match_operand:SI 1 "s_register_operand" "=r")
9823         (match_operand:SI 5 "memory_operand" "m"))
9824    (set (match_operand:SI 2 "s_register_operand" "=r")
9825         (match_operand:SI 6 "memory_operand" "m"))
9826    (set (match_operand:SI 3 "s_register_operand" "=r")
9827         (match_operand:SI 7 "memory_operand" "m"))]
9828   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9829   "*
9830   return emit_ldm_seq (operands, 4);
9831   "
9834 (define_peephole
9835   [(set (match_operand:SI 0 "s_register_operand" "=r")
9836         (match_operand:SI 3 "memory_operand" "m"))
9837    (set (match_operand:SI 1 "s_register_operand" "=r")
9838         (match_operand:SI 4 "memory_operand" "m"))
9839    (set (match_operand:SI 2 "s_register_operand" "=r")
9840         (match_operand:SI 5 "memory_operand" "m"))]
9841   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9842   "*
9843   return emit_ldm_seq (operands, 3);
9844   "
9847 (define_peephole
9848   [(set (match_operand:SI 0 "s_register_operand" "=r")
9849         (match_operand:SI 2 "memory_operand" "m"))
9850    (set (match_operand:SI 1 "s_register_operand" "=r")
9851         (match_operand:SI 3 "memory_operand" "m"))]
9852   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9853   "*
9854   return emit_ldm_seq (operands, 2);
9855   "
9858 (define_peephole
9859   [(set (match_operand:SI 4 "memory_operand" "=m")
9860         (match_operand:SI 0 "s_register_operand" "r"))
9861    (set (match_operand:SI 5 "memory_operand" "=m")
9862         (match_operand:SI 1 "s_register_operand" "r"))
9863    (set (match_operand:SI 6 "memory_operand" "=m")
9864         (match_operand:SI 2 "s_register_operand" "r"))
9865    (set (match_operand:SI 7 "memory_operand" "=m")
9866         (match_operand:SI 3 "s_register_operand" "r"))]
9867   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9868   "*
9869   return emit_stm_seq (operands, 4);
9870   "
9873 (define_peephole
9874   [(set (match_operand:SI 3 "memory_operand" "=m")
9875         (match_operand:SI 0 "s_register_operand" "r"))
9876    (set (match_operand:SI 4 "memory_operand" "=m")
9877         (match_operand:SI 1 "s_register_operand" "r"))
9878    (set (match_operand:SI 5 "memory_operand" "=m")
9879         (match_operand:SI 2 "s_register_operand" "r"))]
9880   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9881   "*
9882   return emit_stm_seq (operands, 3);
9883   "
9886 (define_peephole
9887   [(set (match_operand:SI 2 "memory_operand" "=m")
9888         (match_operand:SI 0 "s_register_operand" "r"))
9889    (set (match_operand:SI 3 "memory_operand" "=m")
9890         (match_operand:SI 1 "s_register_operand" "r"))]
9891   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9892   "*
9893   return emit_stm_seq (operands, 2);
9894   "
9897 (define_split
9898   [(set (match_operand:SI 0 "s_register_operand" "")
9899         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9900                        (const_int 0))
9901                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9902                          [(match_operand:SI 3 "s_register_operand" "")
9903                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
9904    (clobber (match_operand:SI 5 "s_register_operand" ""))]
9905   "TARGET_ARM"
9906   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9907    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9908                               (match_dup 5)))]
9909   ""
9912 ;; This split can be used because CC_Z mode implies that the following
9913 ;; branch will be an equality, or an unsigned inequality, so the sign
9914 ;; extension is not needed.
9916 (define_split
9917   [(set (reg:CC_Z CC_REGNUM)
9918         (compare:CC_Z
9919          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9920                     (const_int 24))
9921          (match_operand 1 "const_int_operand" "")))
9922    (clobber (match_scratch:SI 2 ""))]
9923   "TARGET_ARM
9924    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9925        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9926   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9927    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9928   "
9929   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9930   "
9933 (define_expand "prologue"
9934   [(clobber (const_int 0))]
9935   "TARGET_EITHER"
9936   "if (TARGET_ARM)
9937      arm_expand_prologue ();
9938    else
9939      thumb_expand_prologue ();
9940   DONE;
9941   "
9944 (define_expand "epilogue"
9945   [(clobber (const_int 0))]
9946   "TARGET_EITHER"
9947   "
9948   if (current_function_calls_eh_return)
9949     emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
9950   if (TARGET_THUMB)
9951     thumb_expand_epilogue ();
9952   else if (USE_RETURN_INSN (FALSE))
9953     {
9954       emit_jump_insn (gen_return ());
9955       DONE;
9956     }
9957   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9958         gen_rtvec (1,
9959                 gen_rtx_RETURN (VOIDmode)),
9960         VUNSPEC_EPILOGUE));
9961   DONE;
9962   "
9965 ;; Note - although unspec_volatile's USE all hard registers,
9966 ;; USEs are ignored after relaod has completed.  Thus we need
9967 ;; to add an unspec of the link register to ensure that flow
9968 ;; does not think that it is unused by the sibcall branch that
9969 ;; will replace the standard function epilogue.
9970 (define_insn "sibcall_epilogue"
9971   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9972               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9973   "TARGET_ARM"
9974   "*
9975   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9976     return output_return_instruction (const_true_rtx, FALSE, FALSE);
9977   return arm_output_epilogue (next_nonnote_insn (insn));
9978   "
9979 ;; Length is absolute worst case
9980   [(set_attr "length" "44")
9981    (set_attr "type" "block")
9982    ;; We don't clobber the conditions, but the potential length of this
9983    ;; operation is sufficient to make conditionalizing the sequence 
9984    ;; unlikely to be profitable.
9985    (set_attr "conds" "clob")]
9988 (define_insn "*epilogue_insns"
9989   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9990   "TARGET_EITHER"
9991   "*
9992   if (TARGET_ARM)
9993     return arm_output_epilogue (NULL);
9994   else /* TARGET_THUMB */
9995     return thumb_unexpanded_epilogue ();
9996   "
9997   ; Length is absolute worst case
9998   [(set_attr "length" "44")
9999    (set_attr "type" "block")
10000    ;; We don't clobber the conditions, but the potential length of this
10001    ;; operation is sufficient to make conditionalizing the sequence 
10002    ;; unlikely to be profitable.
10003    (set_attr "conds" "clob")]
10006 (define_expand "eh_epilogue"
10007   [(use (match_operand:SI 0 "register_operand" ""))
10008    (use (match_operand:SI 1 "register_operand" ""))
10009    (use (match_operand:SI 2 "register_operand" ""))]
10010   "TARGET_EITHER"
10011   "
10012   {
10013     cfun->machine->eh_epilogue_sp_ofs = operands[1];
10014     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10015       {
10016         rtx ra = gen_rtx_REG (Pmode, 2);
10018         emit_move_insn (ra, operands[2]);
10019         operands[2] = ra;
10020       }
10021     /* This is a hack -- we may have crystalized the function type too
10022        early.  */
10023     cfun->machine->func_type = 0;
10024   }"
10027 ;; This split is only used during output to reduce the number of patterns
10028 ;; that need assembler instructions adding to them.  We allowed the setting
10029 ;; of the conditions to be implicit during rtl generation so that
10030 ;; the conditional compare patterns would work.  However this conflicts to
10031 ;; some extent with the conditional data operations, so we have to split them
10032 ;; up again here.
10034 (define_split
10035   [(set (match_operand:SI 0 "s_register_operand" "")
10036         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10037                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10038                          (match_dup 0)
10039                          (match_operand 4 "" "")))
10040    (clobber (reg:CC CC_REGNUM))]
10041   "TARGET_ARM && reload_completed"
10042   [(set (match_dup 5) (match_dup 6))
10043    (cond_exec (match_dup 7)
10044               (set (match_dup 0) (match_dup 4)))]
10045   "
10046   {
10047     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10048                                              operands[2], operands[3]);
10049     enum rtx_code rc = GET_CODE (operands[1]);
10051     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10052     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10053     if (mode == CCFPmode || mode == CCFPEmode)
10054       rc = reverse_condition_maybe_unordered (rc);
10055     else
10056       rc = reverse_condition (rc);
10058     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10059   }"
10062 (define_split
10063   [(set (match_operand:SI 0 "s_register_operand" "")
10064         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10065                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10066                          (match_operand 4 "" "")
10067                          (match_dup 0)))
10068    (clobber (reg:CC CC_REGNUM))]
10069   "TARGET_ARM && reload_completed"
10070   [(set (match_dup 5) (match_dup 6))
10071    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10072               (set (match_dup 0) (match_dup 4)))]
10073   "
10074   {
10075     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10076                                              operands[2], operands[3]);
10078     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10079     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10080   }"
10083 (define_split
10084   [(set (match_operand:SI 0 "s_register_operand" "")
10085         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10086                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10087                          (match_operand 4 "" "")
10088                          (match_operand 5 "" "")))
10089    (clobber (reg:CC CC_REGNUM))]
10090   "TARGET_ARM && reload_completed"
10091   [(set (match_dup 6) (match_dup 7))
10092    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10093               (set (match_dup 0) (match_dup 4)))
10094    (cond_exec (match_dup 8)
10095               (set (match_dup 0) (match_dup 5)))]
10096   "
10097   {
10098     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10099                                              operands[2], operands[3]);
10100     enum rtx_code rc = GET_CODE (operands[1]);
10102     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10103     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10104     if (mode == CCFPmode || mode == CCFPEmode)
10105       rc = reverse_condition_maybe_unordered (rc);
10106     else
10107       rc = reverse_condition (rc);
10109     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10110   }"
10113 (define_split
10114   [(set (match_operand:SI 0 "s_register_operand" "")
10115         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10116                           [(match_operand:SI 2 "s_register_operand" "")
10117                            (match_operand:SI 3 "arm_add_operand" "")])
10118                          (match_operand:SI 4 "arm_rhs_operand" "")
10119                          (not:SI
10120                           (match_operand:SI 5 "s_register_operand" ""))))
10121    (clobber (reg:CC CC_REGNUM))]
10122   "TARGET_ARM && reload_completed"
10123   [(set (match_dup 6) (match_dup 7))
10124    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10125               (set (match_dup 0) (match_dup 4)))
10126    (cond_exec (match_dup 8)
10127               (set (match_dup 0) (not:SI (match_dup 5))))]
10128   "
10129   {
10130     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10131                                              operands[2], operands[3]);
10132     enum rtx_code rc = GET_CODE (operands[1]);
10134     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10135     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10136     if (mode == CCFPmode || mode == CCFPEmode)
10137       rc = reverse_condition_maybe_unordered (rc);
10138     else
10139       rc = reverse_condition (rc);
10141     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10142   }"
10145 (define_insn "*cond_move_not"
10146   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10147         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10148                           [(match_operand 3 "cc_register" "") (const_int 0)])
10149                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10150                          (not:SI
10151                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
10152   "TARGET_ARM"
10153   "@
10154    mvn%D4\\t%0, %2
10155    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
10156   [(set_attr "conds" "use")
10157    (set_attr "length" "4,8")]
10160 ;; The next two patterns occur when an AND operation is followed by a
10161 ;; scc insn sequence 
10163 (define_insn "*sign_extract_onebit"
10164   [(set (match_operand:SI 0 "s_register_operand" "=r")
10165         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10166                          (const_int 1)
10167                          (match_operand:SI 2 "const_int_operand" "n")))
10168     (clobber (reg:CC CC_REGNUM))]
10169   "TARGET_ARM"
10170   "*
10171     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10172     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10173     return \"mvnne\\t%0, #0\";
10174   "
10175   [(set_attr "conds" "clob")
10176    (set_attr "length" "8")]
10179 (define_insn "*not_signextract_onebit"
10180   [(set (match_operand:SI 0 "s_register_operand" "=r")
10181         (not:SI
10182          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10183                           (const_int 1)
10184                           (match_operand:SI 2 "const_int_operand" "n"))))
10185    (clobber (reg:CC CC_REGNUM))]
10186   "TARGET_ARM"
10187   "*
10188     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10189     output_asm_insn (\"tst\\t%1, %2\", operands);
10190     output_asm_insn (\"mvneq\\t%0, #0\", operands);
10191     return \"movne\\t%0, #0\";
10192   "
10193   [(set_attr "conds" "clob")
10194    (set_attr "length" "12")]
10197 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
10198 ;; expressions.  For simplicity, the first register is also in the unspec
10199 ;; part.
10200 (define_insn "*push_multi"
10201   [(match_parallel 2 "multi_register_push"
10202     [(set (match_operand:BLK 0 "memory_operand" "=m")
10203           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
10204                       UNSPEC_PUSH_MULT))])]
10205   "TARGET_ARM"
10206   "*
10207   {
10208     int num_saves = XVECLEN (operands[2], 0);
10209      
10210     /* For the StrongARM at least it is faster to
10211        use STR to store only a single register.  */
10212     if (num_saves == 1)
10213       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10214     else
10215       {
10216         int i;
10217         char pattern[100];
10219         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10221         for (i = 1; i < num_saves; i++)
10222           {
10223             strcat (pattern, \", %|\");
10224             strcat (pattern,
10225                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10226           }
10228         strcat (pattern, \"}\");
10229         output_asm_insn (pattern, operands);
10230       }
10232     return \"\";
10233   }"
10234   [(set_attr "type" "store4")]
10237 (define_insn "stack_tie"
10238   [(set (mem:BLK (scratch))
10239         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
10240                      (match_operand:SI 1 "s_register_operand" "r")]
10241                     UNSPEC_PRLG_STK))]
10242   ""
10243   ""
10244   [(set_attr "length" "0")]
10247 ;; Similarly for the floating point registers
10248 (define_insn "*push_fp_multi"
10249   [(match_parallel 2 "multi_register_push"
10250     [(set (match_operand:BLK 0 "memory_operand" "=m")
10251           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10252                       UNSPEC_PUSH_MULT))])]
10253   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
10254   "*
10255   {
10256     char pattern[100];
10258     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10259     output_asm_insn (pattern, operands);
10260     return \"\";
10261   }"
10262   [(set_attr "type" "f_store")]
10265 ;; Special patterns for dealing with the constant pool
10267 (define_insn "align_4"
10268   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10269   "TARGET_EITHER"
10270   "*
10271   assemble_align (32);
10272   return \"\";
10273   "
10276 (define_insn "align_8"
10277   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10278   "TARGET_EITHER"
10279   "*
10280   assemble_align (64);
10281   return \"\";
10282   "
10285 (define_insn "consttable_end"
10286   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10287   "TARGET_EITHER"
10288   "*
10289   making_const_table = FALSE;
10290   return \"\";
10291   "
10294 (define_insn "consttable_1"
10295   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10296   "TARGET_THUMB"
10297   "*
10298   making_const_table = TRUE;
10299   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10300   assemble_zeros (3);
10301   return \"\";
10302   "
10303   [(set_attr "length" "4")]
10306 (define_insn "consttable_2"
10307   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10308   "TARGET_THUMB"
10309   "*
10310   making_const_table = TRUE;
10311   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10312   assemble_zeros (2);
10313   return \"\";
10314   "
10315   [(set_attr "length" "4")]
10318 (define_insn "consttable_4"
10319   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10320   "TARGET_EITHER"
10321   "*
10322   {
10323     making_const_table = TRUE;
10324     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10325       {
10326       case MODE_FLOAT:
10327       {
10328         REAL_VALUE_TYPE r;
10329         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10330         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10331         break;
10332       }
10333       default:
10334         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
10335         break;
10336       }
10337     return \"\";
10338   }"
10339   [(set_attr "length" "4")]
10342 (define_insn "consttable_8"
10343   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10344   "TARGET_EITHER"
10345   "*
10346   {
10347     making_const_table = TRUE;
10348     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10349       {
10350        case MODE_FLOAT:
10351         {
10352           REAL_VALUE_TYPE r;
10353           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10354           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10355           break;
10356         }
10357       default:
10358         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10359         break;
10360       }
10361     return \"\";
10362   }"
10363   [(set_attr "length" "8")]
10366 ;; Miscellaneous Thumb patterns
10368 (define_expand "tablejump"
10369   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10370               (use (label_ref (match_operand 1 "" "")))])]
10371   "TARGET_THUMB"
10372   "
10373   if (flag_pic)
10374     {
10375       /* Hopefully, CSE will eliminate this copy.  */
10376       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10377       rtx reg2 = gen_reg_rtx (SImode);
10379       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10380       operands[0] = reg2;
10381     }
10382   "
10385 ;; NB never uses BX.
10386 (define_insn "*thumb_tablejump"
10387   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10388    (use (label_ref (match_operand 1 "" "")))]
10389   "TARGET_THUMB"
10390   "mov\\t%|pc, %0"
10391   [(set_attr "length" "2")]
10394 ;; V5 Instructions,
10396 (define_insn "clzsi2"
10397   [(set (match_operand:SI 0 "s_register_operand" "=r")
10398         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10399   "TARGET_ARM && arm_arch5"
10400   "clz%?\\t%0, %1"
10401   [(set_attr "predicable" "yes")])
10403 (define_expand "ffssi2"
10404   [(set (match_operand:SI 0 "s_register_operand" "")
10405         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10406   "TARGET_ARM && arm_arch5"
10407   "
10408   {
10409     rtx t1, t2, t3;
10411     t1 = gen_reg_rtx (SImode);
10412     t2 = gen_reg_rtx (SImode);
10413     t3 = gen_reg_rtx (SImode);
10415     emit_insn (gen_negsi2 (t1, operands[1]));
10416     emit_insn (gen_andsi3 (t2, operands[1], t1));
10417     emit_insn (gen_clzsi2 (t3, t2));
10418     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10419     DONE;
10420   }"
10423 (define_expand "ctzsi2"
10424   [(set (match_operand:SI 0 "s_register_operand" "")
10425         (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10426   "TARGET_ARM && arm_arch5"
10427   "
10428   {
10429     rtx t1, t2, t3;
10431     t1 = gen_reg_rtx (SImode);
10432     t2 = gen_reg_rtx (SImode);
10433     t3 = gen_reg_rtx (SImode);
10435     emit_insn (gen_negsi2 (t1, operands[1]));
10436     emit_insn (gen_andsi3 (t2, operands[1], t1));
10437     emit_insn (gen_clzsi2 (t3, t2));
10438     emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10439     DONE;
10440   }"
10443 ;; V5E instructions.
10445 (define_insn "prefetch"
10446   [(prefetch (match_operand:SI 0 "address_operand" "p")
10447              (match_operand:SI 1 "" "")
10448              (match_operand:SI 2 "" ""))]
10449   "TARGET_ARM && arm_arch5e"
10450   "pld\\t%a0")
10452 ;; General predication pattern
10454 (define_cond_exec
10455   [(match_operator 0 "arm_comparison_operator"
10456     [(match_operand 1 "cc_register" "")
10457      (const_int 0)])]
10458   "TARGET_ARM"
10459   ""
10462 (define_insn "prologue_use"
10463   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10464   ""
10465   "%@ %0 needed for prologue"
10469 ;; Patterns for exception handling
10471 (define_expand "eh_return"
10472   [(use (match_operand 0 "general_operand" ""))]
10473   "TARGET_EITHER"
10474   "
10475   {
10476     if (TARGET_ARM)
10477       emit_insn (gen_arm_eh_return (operands[0]));
10478     else
10479       emit_insn (gen_thumb_eh_return (operands[0]));
10480     DONE;
10481   }"
10483                                    
10484 ;; We can't expand this before we know where the link register is stored.
10485 (define_insn_and_split "arm_eh_return"
10486   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10487                     VUNSPEC_EH_RETURN)
10488    (clobber (match_scratch:SI 1 "=&r"))]
10489   "TARGET_ARM"
10490   "#"
10491   "&& reload_completed"
10492   [(const_int 0)]
10493   "
10494   {
10495     arm_set_return_address (operands[0], operands[1]);
10496     DONE;
10497   }"
10500 (define_insn_and_split "thumb_eh_return"
10501   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10502                     VUNSPEC_EH_RETURN)
10503    (clobber (match_scratch:SI 1 "=&l"))]
10504   "TARGET_THUMB"
10505   "#"
10506   "&& reload_completed"
10507   [(const_int 0)]
10508   "
10509   {
10510     thumb_set_return_address (operands[0], operands[1]);
10511     DONE;
10512   }"
10515 ;; Load the FPA co-processor patterns
10516 (include "fpa.md")
10517 ;; Load the Maverick co-processor patterns
10518 (include "cirrus.md")
10519 ;; Load the Intel Wireless Multimedia Extension patterns
10520 (include "iwmmxt.md")
10521 ;; Load the VFP co-processor patterns
10522 (include "vfp.md")