Merge reload-branch up to revision 101000
[official-gcc.git] / gcc / config / arm / arm.md
blob2aadfea671ba24b7c0e16797ef676fc0f66e9e5c
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_tune_strongarm")))
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_load[sd]    single/double load from memory
206 ; f_store[sd]   single/double store to memory
207 ; f_flag        a transfer of co-processor flags to the CPSR
208 ; f_mem_r       a transfer of a floating point register to a real reg via mem
209 ; r_mem_f       the reverse of f_mem_r
210 ; f_2_r         fast transfer float to arm (no memory needed)
211 ; r_2_f         fast transfer arm to float
212 ; f_cvt         convert floating<->integral
213 ; branch        a branch
214 ; call          a subroutine call
215 ; load_byte     load byte(s) from memory to arm registers
216 ; load1         load 1 word from memory to arm registers
217 ; load2         load 2 words from memory to arm registers
218 ; load3         load 3 words from memory to arm registers
219 ; load4         load 4 words from memory to arm registers
220 ; store         store 1 word to memory from arm registers
221 ; store2        store 2 words
222 ; store3        store 3 words
223 ; store4        store 4 (or more) words
224 ;  Additions for Cirrus Maverick co-processor:
225 ; mav_farith    Floating point arithmetic (4 cycle)
226 ; mav_dmult     Double multiplies (7 cycle)
228 (define_attr "type"
229         "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,f_flag,float_em,f_load,f_store,f_loads,f_loadd,f_stores,f_stored,f_mem_r,r_mem_f,f_2_r,r_2_f,f_cvt,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult" 
230         (if_then_else 
231          (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
232          (const_string "mult")
233          (const_string "alu")))
235 ; Load scheduling, set from the arm_ld_sched variable
236 ; initialized by arm_override_options() 
237 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
239 ; condition codes: this one is used by final_prescan_insn to speed up
240 ; conditionalizing instructions.  It saves having to scan the rtl to see if
241 ; it uses or alters the condition codes.
243 ; USE means that the condition codes are used by the insn in the process of
244 ;   outputting code, this means (at present) that we can't use the insn in
245 ;   inlined branches
247 ; SET means that the purpose of the insn is to set the condition codes in a
248 ;   well defined manner.
250 ; CLOB means that the condition codes are altered in an undefined manner, if
251 ;   they are altered at all
253 ; JUMP_CLOB is used when the condition cannot be represented by a single
254 ;   instruction (UNEQ and LTGT).  These cannot be predicated.
256 ; NOCOND means that the condition codes are neither altered nor affect the
257 ;   output of this insn
259 (define_attr "conds" "use,set,clob,jump_clob,nocond"
260         (if_then_else (eq_attr "type" "call")
261          (const_string "clob")
262          (const_string "nocond")))
264 ; Predicable means that the insn can be conditionally executed based on
265 ; an automatically added predicate (additional patterns are generated by 
266 ; gen...).  We default to 'no' because no Thumb patterns match this rule
267 ; and not all ARM patterns do.
268 (define_attr "predicable" "no,yes" (const_string "no"))
270 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
271 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
272 ; suffer blockages enough to warrant modelling this (and it can adversely
273 ; affect the schedule).
274 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
276 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
277 ; to stall the processor.  Used with model_wbuf above.
278 (define_attr "write_conflict" "no,yes"
279   (if_then_else (eq_attr "type"
280                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
281                 (const_string "yes")
282                 (const_string "no")))
284 ; Classify the insns into those that take one cycle and those that take more
285 ; than one on the main cpu execution unit.
286 (define_attr "core_cycles" "single,multi"
287   (if_then_else (eq_attr "type"
288                  "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
289                 (const_string "single")
290                 (const_string "multi")))
292 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
293 ;; distant label.  Only applicable to Thumb code.
294 (define_attr "far_jump" "yes,no" (const_string "no"))
297 ;;---------------------------------------------------------------------------
298 ;; Mode macros
300 ; A list of modes that are exactly 64 bits in size.  We use this to expand
301 ; some splits that are the same for all modes when operating on ARM 
302 ; registers.
303 (define_mode_macro ANY64 [DI DF V8QI V4HI V2SI V2SF])
305 ;;---------------------------------------------------------------------------
306 ;; Predicates
308 (include "predicates.md")
310 ;;---------------------------------------------------------------------------
311 ;; Pipeline descriptions
313 ;; Processor type.  This is created automatically from arm-cores.def.
314 (include "arm-tune.md")
316 ;; True if the generic scheduling description should be used.
318 (define_attr "generic_sched" "yes,no"
319   (const (if_then_else 
320           (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs") 
321           (const_string "no")
322           (const_string "yes"))))
324 (define_attr "generic_vfp" "yes,no"
325   (const (if_then_else
326           (and (eq_attr "fpu" "vfp")
327                (eq_attr "tune" "!arm1020e,arm1022e"))
328           (const_string "yes")
329           (const_string "no"))))
331 (include "arm-generic.md")
332 (include "arm926ejs.md")
333 (include "arm1020e.md")
334 (include "arm1026ejs.md")
335 (include "arm1136jfs.md")
338 ;;---------------------------------------------------------------------------
339 ;; Insn patterns
341 ;; Addition insns.
343 ;; Note: For DImode insns, there is normally no reason why operands should
344 ;; not be in the same register, what we don't want is for something being
345 ;; written to partially overlap something that is an input.
346 ;; Cirrus 64bit additions should not be split because we have a native
347 ;; 64bit addition instructions.
349 (define_expand "adddi3"
350  [(parallel
351    [(set (match_operand:DI           0 "s_register_operand" "")
352           (plus:DI (match_operand:DI 1 "s_register_operand" "")
353                    (match_operand:DI 2 "s_register_operand" "")))
354     (clobber (reg:CC CC_REGNUM))])]
355   "TARGET_EITHER"
356   "
357   if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
358     {
359       if (!cirrus_fp_register (operands[0], DImode))
360         operands[0] = force_reg (DImode, operands[0]);
361       if (!cirrus_fp_register (operands[1], DImode))
362         operands[1] = force_reg (DImode, operands[1]);
363       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
364       DONE;
365     }
367   if (TARGET_THUMB)
368     {
369       if (GET_CODE (operands[1]) != REG)
370         operands[1] = force_reg (SImode, operands[1]);
371       if (GET_CODE (operands[2]) != REG)
372         operands[2] = force_reg (SImode, operands[2]);
373      }
374   "
377 (define_insn "*thumb_adddi3"
378   [(set (match_operand:DI          0 "register_operand" "=l")
379         (plus:DI (match_operand:DI 1 "register_operand" "%0")
380                  (match_operand:DI 2 "register_operand" "l")))
381    (clobber (reg:CC CC_REGNUM))
382   ]
383   "TARGET_THUMB"
384   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
385   [(set_attr "length" "4")]
388 (define_insn_and_split "*arm_adddi3"
389   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
390         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
391                  (match_operand:DI 2 "s_register_operand" "r,  0")))
392    (clobber (reg:CC CC_REGNUM))]
393   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
394   "#"
395   "TARGET_ARM && reload_completed"
396   [(parallel [(set (reg:CC_C CC_REGNUM)
397                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
398                                  (match_dup 1)))
399               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
400    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
401                                (plus:SI (match_dup 4) (match_dup 5))))]
402   "
403   {
404     operands[3] = gen_highpart (SImode, operands[0]);
405     operands[0] = gen_lowpart (SImode, operands[0]);
406     operands[4] = gen_highpart (SImode, operands[1]);
407     operands[1] = gen_lowpart (SImode, operands[1]);
408     operands[5] = gen_highpart (SImode, operands[2]);
409     operands[2] = gen_lowpart (SImode, operands[2]);
410   }"
411   [(set_attr "conds" "clob")
412    (set_attr "length" "8")]
415 (define_insn_and_split "*adddi_sesidi_di"
416   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
417         (plus:DI (sign_extend:DI
418                   (match_operand:SI 2 "s_register_operand" "r,r"))
419                  (match_operand:DI 1 "s_register_operand" "r,0")))
420    (clobber (reg:CC CC_REGNUM))]
421   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
422   "#"
423   "TARGET_ARM && reload_completed"
424   [(parallel [(set (reg:CC_C CC_REGNUM)
425                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
426                                  (match_dup 1)))
427               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
428    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
429                                (plus:SI (ashiftrt:SI (match_dup 2)
430                                                      (const_int 31))
431                                         (match_dup 4))))]
432   "
433   {
434     operands[3] = gen_highpart (SImode, operands[0]);
435     operands[0] = gen_lowpart (SImode, operands[0]);
436     operands[4] = gen_highpart (SImode, operands[1]);
437     operands[1] = gen_lowpart (SImode, operands[1]);
438     operands[2] = gen_lowpart (SImode, operands[2]);
439   }"
440   [(set_attr "conds" "clob")
441    (set_attr "length" "8")]
444 (define_insn_and_split "*adddi_zesidi_di"
445   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
446         (plus:DI (zero_extend:DI
447                   (match_operand:SI 2 "s_register_operand" "r,r"))
448                  (match_operand:DI 1 "s_register_operand" "r,0")))
449    (clobber (reg:CC CC_REGNUM))]
450   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
451   "#"
452   "TARGET_ARM && reload_completed"
453   [(parallel [(set (reg:CC_C CC_REGNUM)
454                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
455                                  (match_dup 1)))
456               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
457    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
458                                (plus:SI (match_dup 4) (const_int 0))))]
459   "
460   {
461     operands[3] = gen_highpart (SImode, operands[0]);
462     operands[0] = gen_lowpart (SImode, operands[0]);
463     operands[4] = gen_highpart (SImode, operands[1]);
464     operands[1] = gen_lowpart (SImode, operands[1]);
465     operands[2] = gen_lowpart (SImode, operands[2]);
466   }"
467   [(set_attr "conds" "clob")
468    (set_attr "length" "8")]
471 (define_expand "addsi3"
472   [(set (match_operand:SI          0 "s_register_operand" "")
473         (plus:SI (match_operand:SI 1 "s_register_operand" "")
474                  (match_operand:SI 2 "reg_or_int_operand" "")))]
475   "TARGET_EITHER"
476   "
477   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
478     {
479       arm_split_constant (PLUS, SImode, NULL_RTX,
480                           INTVAL (operands[2]), operands[0], operands[1],
481                           optimize && !no_new_pseudos);
482       DONE;
483     }
484   "
487 ; If there is a scratch available, this will be faster than synthesizing the
488 ; addition.
489 (define_peephole2
490   [(match_scratch:SI 3 "r")
491    (set (match_operand:SI          0 "arm_general_register_operand" "")
492         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
493                  (match_operand:SI 2 "const_int_operand"  "")))]
494   "TARGET_ARM &&
495    !(const_ok_for_arm (INTVAL (operands[2]))
496      || const_ok_for_arm (-INTVAL (operands[2])))
497     && const_ok_for_arm (~INTVAL (operands[2]))"
498   [(set (match_dup 3) (match_dup 2))
499    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
500   ""
503 (define_insn_and_split "*arm_addsi3"
504   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
505         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
506                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
507   "TARGET_ARM"
508   "@
509    add%?\\t%0, %1, %2
510    sub%?\\t%0, %1, #%n2
511    #"
512   "TARGET_ARM &&
513    GET_CODE (operands[2]) == CONST_INT
514    && !(const_ok_for_arm (INTVAL (operands[2]))
515         || const_ok_for_arm (-INTVAL (operands[2])))"
516   [(clobber (const_int 0))]
517   "
518   arm_split_constant (PLUS, SImode, curr_insn,
519                       INTVAL (operands[2]), operands[0],
520                       operands[1], 0);
521   DONE;
522   "
523   [(set_attr "length" "4,4,16")
524    (set_attr "predicable" "yes")]
527 ;; Register group 'k' is a single register group containing only the stack
528 ;; register.  Trying to reload it will always fail catastrophically,
529 ;; so never allow those alternatives to match if reloading is needed.
531 (define_insn "*thumb_addsi3"
532   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
533         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
534                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
535   "TARGET_THUMB"
536   "*
537    static const char * const asms[] = 
538    {
539      \"add\\t%0, %0, %2\",
540      \"sub\\t%0, %0, #%n2\",
541      \"add\\t%0, %1, %2\",
542      \"add\\t%0, %0, %2\",
543      \"add\\t%0, %0, %2\",
544      \"add\\t%0, %1, %2\",
545      \"add\\t%0, %1, %2\"
546    };
547    if ((which_alternative == 2 || which_alternative == 6)
548        && GET_CODE (operands[2]) == CONST_INT
549        && INTVAL (operands[2]) < 0)
550      return \"sub\\t%0, %1, #%n2\";
551    return asms[which_alternative];
552   "
553   [(set_attr "length" "2")]
556 ;; Reloading and elimination of the frame pointer can
557 ;; sometimes cause this optimization to be missed.
558 (define_peephole2
559   [(set (match_operand:SI 0 "arm_general_register_operand" "")
560         (match_operand:SI 1 "const_int_operand" ""))
561    (set (match_dup 0)
562         (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
563   "TARGET_THUMB
564    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
565    && (INTVAL (operands[1]) & 3) == 0"
566   [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
567   ""
570 (define_insn "*addsi3_compare0"
571   [(set (reg:CC_NOOV CC_REGNUM)
572         (compare:CC_NOOV
573          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
574                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
575          (const_int 0)))
576    (set (match_operand:SI 0 "s_register_operand" "=r,r")
577         (plus:SI (match_dup 1) (match_dup 2)))]
578   "TARGET_ARM"
579   "@
580    add%?s\\t%0, %1, %2
581    sub%?s\\t%0, %1, #%n2"
582   [(set_attr "conds" "set")]
585 (define_insn "*addsi3_compare0_scratch"
586   [(set (reg:CC_NOOV CC_REGNUM)
587         (compare:CC_NOOV
588          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
589                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
590          (const_int 0)))]
591   "TARGET_ARM"
592   "@
593    cmn%?\\t%0, %1
594    cmp%?\\t%0, #%n1"
595   [(set_attr "conds" "set")]
598 (define_insn "*compare_negsi_si"
599   [(set (reg:CC_Z CC_REGNUM)
600         (compare:CC_Z
601          (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
602          (match_operand:SI 1 "s_register_operand" "r")))]
603   "TARGET_ARM"
604   "cmn%?\\t%1, %0"
605   [(set_attr "conds" "set")]
608 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
609 ;; addend is a constant.
610 (define_insn "*cmpsi2_addneg"
611   [(set (reg:CC CC_REGNUM)
612         (compare:CC
613          (match_operand:SI 1 "s_register_operand" "r,r")
614          (match_operand:SI 2 "arm_addimm_operand" "I,L")))
615    (set (match_operand:SI 0 "s_register_operand" "=r,r")
616         (plus:SI (match_dup 1)
617                  (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
618   "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
619   "@
620    sub%?s\\t%0, %1, %2
621    add%?s\\t%0, %1, #%n2"
622   [(set_attr "conds" "set")]
625 ;; Convert the sequence
626 ;;  sub  rd, rn, #1
627 ;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
628 ;;  bne  dest
629 ;; into
630 ;;  subs rd, rn, #1
631 ;;  bcs  dest   ((unsigned)rn >= 1)
632 ;; similarly for the beq variant using bcc.
633 ;; This is a common looping idiom (while (n--))
634 (define_peephole2
635   [(set (match_operand:SI 0 "arm_general_register_operand" "")
636         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
637                  (const_int -1)))
638    (set (match_operand 2 "cc_register" "")
639         (compare (match_dup 0) (const_int -1)))
640    (set (pc)
641         (if_then_else (match_operator 3 "equality_operator"
642                        [(match_dup 2) (const_int 0)])
643                       (match_operand 4 "" "")
644                       (match_operand 5 "" "")))]
645   "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
646   [(parallel[
647     (set (match_dup 2)
648          (compare:CC
649           (match_dup 1) (const_int 1)))
650     (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
651    (set (pc)
652         (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
653                       (match_dup 4)
654                       (match_dup 5)))]
655   "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
656    operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
657                                   ? GEU : LTU),
658                                  VOIDmode, 
659                                  operands[2], const0_rtx);"
662 ;; The next four insns work because they compare the result with one of
663 ;; the operands, and we know that the use of the condition code is
664 ;; either GEU or LTU, so we can use the carry flag from the addition
665 ;; instead of doing the compare a second time.
666 (define_insn "*addsi3_compare_op1"
667   [(set (reg:CC_C CC_REGNUM)
668         (compare:CC_C
669          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
670                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
671          (match_dup 1)))
672    (set (match_operand:SI 0 "s_register_operand" "=r,r")
673         (plus:SI (match_dup 1) (match_dup 2)))]
674   "TARGET_ARM"
675   "@
676    add%?s\\t%0, %1, %2
677    sub%?s\\t%0, %1, #%n2"
678   [(set_attr "conds" "set")]
681 (define_insn "*addsi3_compare_op2"
682   [(set (reg:CC_C CC_REGNUM)
683         (compare:CC_C
684          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
685                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
686          (match_dup 2)))
687    (set (match_operand:SI 0 "s_register_operand" "=r,r")
688         (plus:SI (match_dup 1) (match_dup 2)))]
689   "TARGET_ARM"
690   "@
691    add%?s\\t%0, %1, %2
692    sub%?s\\t%0, %1, #%n2"
693   [(set_attr "conds" "set")]
696 (define_insn "*compare_addsi2_op0"
697   [(set (reg:CC_C CC_REGNUM)
698         (compare:CC_C
699          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
700                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
701          (match_dup 0)))]
702   "TARGET_ARM"
703   "@
704    cmn%?\\t%0, %1
705    cmp%?\\t%0, #%n1"
706   [(set_attr "conds" "set")]
709 (define_insn "*compare_addsi2_op1"
710   [(set (reg:CC_C CC_REGNUM)
711         (compare:CC_C
712          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
713                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
714          (match_dup 1)))]
715   "TARGET_ARM"
716   "@
717    cmn%?\\t%0, %1
718    cmp%?\\t%0, #%n1"
719   [(set_attr "conds" "set")]
722 (define_insn "*addsi3_carryin"
723   [(set (match_operand:SI 0 "s_register_operand" "=r")
724         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
725                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
726                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
727   "TARGET_ARM"
728   "adc%?\\t%0, %1, %2"
729   [(set_attr "conds" "use")]
732 (define_insn "*addsi3_carryin_shift"
733   [(set (match_operand:SI 0 "s_register_operand" "=r")
734         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
735                  (plus:SI
736                    (match_operator:SI 2 "shift_operator"
737                       [(match_operand:SI 3 "s_register_operand" "r")
738                        (match_operand:SI 4 "reg_or_int_operand" "rM")])
739                     (match_operand:SI 1 "s_register_operand" "r"))))]
740   "TARGET_ARM"
741   "adc%?\\t%0, %1, %3%S2"
742   [(set_attr "conds" "use")
743    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
744                       (const_string "alu_shift")
745                       (const_string "alu_shift_reg")))]
748 (define_insn "*addsi3_carryin_alt1"
749   [(set (match_operand:SI 0 "s_register_operand" "=r")
750         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
751                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
752                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
753   "TARGET_ARM"
754   "adc%?\\t%0, %1, %2"
755   [(set_attr "conds" "use")]
758 (define_insn "*addsi3_carryin_alt2"
759   [(set (match_operand:SI 0 "s_register_operand" "=r")
760         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
761                           (match_operand:SI 1 "s_register_operand" "r"))
762                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
763   "TARGET_ARM"
764   "adc%?\\t%0, %1, %2"
765   [(set_attr "conds" "use")]
768 (define_insn "*addsi3_carryin_alt3"
769   [(set (match_operand:SI 0 "s_register_operand" "=r")
770         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
771                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
772                  (match_operand:SI 1 "s_register_operand" "r")))]
773   "TARGET_ARM"
774   "adc%?\\t%0, %1, %2"
775   [(set_attr "conds" "use")]
778 (define_insn "incscc"
779   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
780         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
781                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
782                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
783   "TARGET_ARM"
784   "@
785   add%d2\\t%0, %1, #1
786   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
787   [(set_attr "conds" "use")
788    (set_attr "length" "4,8")]
791 ; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
792 (define_split
793   [(set (match_operand:SI 0 "s_register_operand" "")
794         (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
795                             (match_operand:SI 2 "s_register_operand" ""))
796                  (const_int -1)))
797    (clobber (match_operand:SI 3 "s_register_operand" ""))]
798   "TARGET_ARM"
799   [(set (match_dup 3) (match_dup 1))
800    (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
801   "
802   operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
805 (define_expand "addsf3"
806   [(set (match_operand:SF          0 "s_register_operand" "")
807         (plus:SF (match_operand:SF 1 "s_register_operand" "")
808                  (match_operand:SF 2 "arm_float_add_operand" "")))]
809   "TARGET_ARM && TARGET_HARD_FLOAT"
810   "
811   if (TARGET_MAVERICK
812       && !cirrus_fp_register (operands[2], SFmode))
813     operands[2] = force_reg (SFmode, operands[2]);
816 (define_expand "adddf3"
817   [(set (match_operand:DF          0 "s_register_operand" "")
818         (plus:DF (match_operand:DF 1 "s_register_operand" "")
819                  (match_operand:DF 2 "arm_float_add_operand" "")))]
820   "TARGET_ARM && TARGET_HARD_FLOAT"
821   "
822   if (TARGET_MAVERICK
823       && !cirrus_fp_register (operands[2], DFmode))
824     operands[2] = force_reg (DFmode, operands[2]);
827 (define_expand "subdi3"
828  [(parallel
829    [(set (match_operand:DI            0 "s_register_operand" "")
830           (minus:DI (match_operand:DI 1 "s_register_operand" "")
831                     (match_operand:DI 2 "s_register_operand" "")))
832     (clobber (reg:CC CC_REGNUM))])]
833   "TARGET_EITHER"
834   "
835   if (TARGET_HARD_FLOAT && TARGET_MAVERICK
836       && TARGET_ARM
837       && cirrus_fp_register (operands[0], DImode)
838       && cirrus_fp_register (operands[1], DImode))
839     {
840       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
841       DONE;
842     }
844   if (TARGET_THUMB)
845     {
846       if (GET_CODE (operands[1]) != REG)
847         operands[1] = force_reg (SImode, operands[1]);
848       if (GET_CODE (operands[2]) != REG)
849         operands[2] = force_reg (SImode, operands[2]);
850      }  
851   "
854 (define_insn "*arm_subdi3"
855   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
856         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
857                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
858    (clobber (reg:CC CC_REGNUM))]
859   "TARGET_ARM"
860   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
861   [(set_attr "conds" "clob")
862    (set_attr "length" "8")]
865 (define_insn "*thumb_subdi3"
866   [(set (match_operand:DI           0 "register_operand" "=l")
867         (minus:DI (match_operand:DI 1 "register_operand"  "0")
868                   (match_operand:DI 2 "register_operand"  "l")))
869    (clobber (reg:CC CC_REGNUM))]
870   "TARGET_THUMB"
871   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
872   [(set_attr "length" "4")]
875 (define_insn "*subdi_di_zesidi"
876   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
877         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
878                   (zero_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, #0"
883   [(set_attr "conds" "clob")
884    (set_attr "length" "8")]
887 (define_insn "*subdi_di_sesidi"
888   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
889         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
890                   (sign_extend:DI
891                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
892    (clobber (reg:CC CC_REGNUM))]
893   "TARGET_ARM"
894   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
895   [(set_attr "conds" "clob")
896    (set_attr "length" "8")]
899 (define_insn "*subdi_zesidi_di"
900   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
901         (minus:DI (zero_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, #0"
907   [(set_attr "conds" "clob")
908    (set_attr "length" "8")]
911 (define_insn "*subdi_sesidi_di"
912   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
913         (minus:DI (sign_extend:DI
914                    (match_operand:SI 2 "s_register_operand"   "r,r"))
915                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
916    (clobber (reg:CC CC_REGNUM))]
917   "TARGET_ARM"
918   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
919   [(set_attr "conds" "clob")
920    (set_attr "length" "8")]
923 (define_insn "*subdi_zesidi_zesidi"
924   [(set (match_operand:DI            0 "s_register_operand" "=r")
925         (minus:DI (zero_extend:DI
926                    (match_operand:SI 1 "s_register_operand"  "r"))
927                   (zero_extend:DI
928                    (match_operand:SI 2 "s_register_operand"  "r"))))
929    (clobber (reg:CC CC_REGNUM))]
930   "TARGET_ARM"
931   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
932   [(set_attr "conds" "clob")
933    (set_attr "length" "8")]
936 (define_expand "subsi3"
937   [(set (match_operand:SI           0 "s_register_operand" "")
938         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
939                   (match_operand:SI 2 "s_register_operand" "")))]
940   "TARGET_EITHER"
941   "
942   if (GET_CODE (operands[1]) == CONST_INT)
943     {
944       if (TARGET_ARM)
945         {
946           arm_split_constant (MINUS, SImode, NULL_RTX,
947                               INTVAL (operands[1]), operands[0],
948                               operands[2], optimize && !no_new_pseudos);
949           DONE;
950         }
951       else /* TARGET_THUMB */
952         operands[1] = force_reg (SImode, operands[1]);
953     }
954   "
957 (define_insn "*thumb_subsi3_insn"
958   [(set (match_operand:SI           0 "register_operand" "=l")
959         (minus:SI (match_operand:SI 1 "register_operand" "l")
960                   (match_operand:SI 2 "register_operand" "l")))]
961   "TARGET_THUMB"
962   "sub\\t%0, %1, %2"
963   [(set_attr "length" "2")]
966 (define_insn_and_split "*arm_subsi3_insn"
967   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
968         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
969                   (match_operand:SI 2 "s_register_operand" "r,r")))]
970   "TARGET_ARM"
971   "@
972    rsb%?\\t%0, %2, %1
973    #"
974   "TARGET_ARM
975    && GET_CODE (operands[1]) == CONST_INT
976    && !const_ok_for_arm (INTVAL (operands[1]))"
977   [(clobber (const_int 0))]
978   "
979   arm_split_constant (MINUS, SImode, curr_insn,
980                       INTVAL (operands[1]), operands[0], operands[2], 0);
981   DONE;
982   "
983   [(set_attr "length" "4,16")
984    (set_attr "predicable" "yes")]
987 (define_peephole2
988   [(match_scratch:SI 3 "r")
989    (set (match_operand:SI 0 "arm_general_register_operand" "")
990         (minus:SI (match_operand:SI 1 "const_int_operand" "")
991                   (match_operand:SI 2 "arm_general_register_operand" "")))]
992   "TARGET_ARM
993    && !const_ok_for_arm (INTVAL (operands[1]))
994    && const_ok_for_arm (~INTVAL (operands[1]))"
995   [(set (match_dup 3) (match_dup 1))
996    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
997   ""
1000 (define_insn "*subsi3_compare0"
1001   [(set (reg:CC_NOOV CC_REGNUM)
1002         (compare:CC_NOOV
1003          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1004                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1005          (const_int 0)))
1006    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1007         (minus:SI (match_dup 1) (match_dup 2)))]
1008   "TARGET_ARM"
1009   "@
1010    sub%?s\\t%0, %1, %2
1011    rsb%?s\\t%0, %2, %1"
1012   [(set_attr "conds" "set")]
1015 (define_insn "decscc"
1016   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1017         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1018                   (match_operator:SI 2 "arm_comparison_operator"
1019                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1020   "TARGET_ARM"
1021   "@
1022    sub%d2\\t%0, %1, #1
1023    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1024   [(set_attr "conds" "use")
1025    (set_attr "length" "*,8")]
1028 (define_expand "subsf3"
1029   [(set (match_operand:SF           0 "s_register_operand" "")
1030         (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1031                   (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1032   "TARGET_ARM && TARGET_HARD_FLOAT"
1033   "
1034   if (TARGET_MAVERICK)
1035     {
1036       if (!cirrus_fp_register (operands[1], SFmode))
1037         operands[1] = force_reg (SFmode, operands[1]);
1038       if (!cirrus_fp_register (operands[2], SFmode))
1039         operands[2] = force_reg (SFmode, operands[2]);
1040     }
1043 (define_expand "subdf3"
1044   [(set (match_operand:DF           0 "s_register_operand" "")
1045         (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1046                   (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1047   "TARGET_ARM && TARGET_HARD_FLOAT"
1048   "
1049   if (TARGET_MAVERICK)
1050     {
1051        if (!cirrus_fp_register (operands[1], DFmode))
1052          operands[1] = force_reg (DFmode, operands[1]);
1053        if (!cirrus_fp_register (operands[2], DFmode))
1054          operands[2] = force_reg (DFmode, operands[2]);
1055     }
1059 ;; Multiplication insns
1061 (define_expand "mulsi3"
1062   [(set (match_operand:SI          0 "s_register_operand" "")
1063         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1064                  (match_operand:SI 1 "s_register_operand" "")))]
1065   "TARGET_EITHER"
1066   ""
1069 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1070 (define_insn "*arm_mulsi3"
1071   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1072         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1073                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1074   "TARGET_ARM"
1075   "mul%?\\t%0, %2, %1"
1076   [(set_attr "insn" "mul")
1077    (set_attr "predicable" "yes")]
1080 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1081 ; 1 and 2; are the same, because reload will make operand 0 match 
1082 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1083 ; this by adding another alternative to match this case, and then `reload' 
1084 ; it ourselves.  This alternative must come first.
1085 (define_insn "*thumb_mulsi3"
1086   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1087         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1088                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1089   "TARGET_THUMB"
1090   "*
1091   if (which_alternative < 2)
1092     return \"mov\\t%0, %1\;mul\\t%0, %2\";
1093   else
1094     return \"mul\\t%0, %2\";
1095   "
1096   [(set_attr "length" "4,4,2")
1097    (set_attr "insn" "mul")]
1100 (define_insn "*mulsi3_compare0"
1101   [(set (reg:CC_NOOV CC_REGNUM)
1102         (compare:CC_NOOV (mult:SI
1103                           (match_operand:SI 2 "s_register_operand" "r,r")
1104                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1105                          (const_int 0)))
1106    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1107         (mult:SI (match_dup 2) (match_dup 1)))]
1108   "TARGET_ARM"
1109   "mul%?s\\t%0, %2, %1"
1110   [(set_attr "conds" "set")
1111    (set_attr "insn" "muls")]
1114 (define_insn "*mulsi_compare0_scratch"
1115   [(set (reg:CC_NOOV CC_REGNUM)
1116         (compare:CC_NOOV (mult:SI
1117                           (match_operand:SI 2 "s_register_operand" "r,r")
1118                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1119                          (const_int 0)))
1120    (clobber (match_scratch:SI 0 "=&r,&r"))]
1121   "TARGET_ARM"
1122   "mul%?s\\t%0, %2, %1"
1123   [(set_attr "conds" "set")
1124    (set_attr "insn" "muls")]
1127 ;; Unnamed templates to match MLA instruction.
1129 (define_insn "*mulsi3addsi"
1130   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1131         (plus:SI
1132           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1133                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1134           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1135   "TARGET_ARM"
1136   "mla%?\\t%0, %2, %1, %3"
1137   [(set_attr "insn" "mla")
1138    (set_attr "predicable" "yes")]
1141 (define_insn "*mulsi3addsi_compare0"
1142   [(set (reg:CC_NOOV CC_REGNUM)
1143         (compare:CC_NOOV
1144          (plus:SI (mult:SI
1145                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1146                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1147                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1148          (const_int 0)))
1149    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1150         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1151                  (match_dup 3)))]
1152   "TARGET_ARM"
1153   "mla%?s\\t%0, %2, %1, %3"
1154   [(set_attr "conds" "set")
1155    (set_attr "insn" "mlas")]
1158 (define_insn "*mulsi3addsi_compare0_scratch"
1159   [(set (reg:CC_NOOV CC_REGNUM)
1160         (compare:CC_NOOV
1161          (plus:SI (mult:SI
1162                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1163                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1164                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1165          (const_int 0)))
1166    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1167   "TARGET_ARM"
1168   "mla%?s\\t%0, %2, %1, %3"
1169   [(set_attr "conds" "set")
1170    (set_attr "insn" "mlas")]
1173 ;; Unnamed template to match long long multiply-accumulate (smlal)
1175 (define_insn "*mulsidi3adddi"
1176   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1177         (plus:DI
1178          (mult:DI
1179           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1180           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1181          (match_operand:DI 1 "s_register_operand" "0")))]
1182   "TARGET_ARM && arm_arch3m"
1183   "smlal%?\\t%Q0, %R0, %3, %2"
1184   [(set_attr "insn" "smlal")
1185    (set_attr "predicable" "yes")]
1188 (define_insn "mulsidi3"
1189   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1190         (mult:DI
1191          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1192          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1193   "TARGET_ARM && arm_arch3m"
1194   "smull%?\\t%Q0, %R0, %1, %2"
1195   [(set_attr "insn" "smull")
1196    (set_attr "predicable" "yes")]
1199 (define_insn "umulsidi3"
1200   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1201         (mult:DI
1202          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1203          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1204   "TARGET_ARM && arm_arch3m"
1205   "umull%?\\t%Q0, %R0, %1, %2"
1206   [(set_attr "insn" "umull")
1207    (set_attr "predicable" "yes")]
1210 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1212 (define_insn "*umulsidi3adddi"
1213   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1214         (plus:DI
1215          (mult:DI
1216           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1217           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1218          (match_operand:DI 1 "s_register_operand" "0")))]
1219   "TARGET_ARM && arm_arch3m"
1220   "umlal%?\\t%Q0, %R0, %3, %2"
1221   [(set_attr "insn" "umlal")
1222    (set_attr "predicable" "yes")]
1225 (define_insn "smulsi3_highpart"
1226   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1227         (truncate:SI
1228          (lshiftrt:DI
1229           (mult:DI
1230            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1231            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1232           (const_int 32))))
1233    (clobber (match_scratch:SI 3 "=&r,&r"))]
1234   "TARGET_ARM && arm_arch3m"
1235   "smull%?\\t%3, %0, %2, %1"
1236   [(set_attr "insn" "smull")
1237    (set_attr "predicable" "yes")]
1240 (define_insn "umulsi3_highpart"
1241   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1242         (truncate:SI
1243          (lshiftrt:DI
1244           (mult:DI
1245            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1246            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1247           (const_int 32))))
1248    (clobber (match_scratch:SI 3 "=&r,&r"))]
1249   "TARGET_ARM && arm_arch3m"
1250   "umull%?\\t%3, %0, %2, %1"
1251   [(set_attr "insn" "umull")
1252    (set_attr "predicable" "yes")]
1255 (define_insn "mulhisi3"
1256   [(set (match_operand:SI 0 "s_register_operand" "=r")
1257         (mult:SI (sign_extend:SI
1258                   (match_operand:HI 1 "s_register_operand" "%r"))
1259                  (sign_extend:SI
1260                   (match_operand:HI 2 "s_register_operand" "r"))))]
1261   "TARGET_ARM && arm_arch5e"
1262   "smulbb%?\\t%0, %1, %2"
1263   [(set_attr "insn" "smulxy")
1264    (set_attr "predicable" "yes")]
1267 (define_insn "*mulhisi3tb"
1268   [(set (match_operand:SI 0 "s_register_operand" "=r")
1269         (mult:SI (ashiftrt:SI
1270                   (match_operand:SI 1 "s_register_operand" "r")
1271                   (const_int 16))
1272                  (sign_extend:SI
1273                   (match_operand:HI 2 "s_register_operand" "r"))))]
1274   "TARGET_ARM && arm_arch5e"
1275   "smultb%?\\t%0, %1, %2"
1276   [(set_attr "insn" "smulxy")
1277    (set_attr "predicable" "yes")]
1280 (define_insn "*mulhisi3bt"
1281   [(set (match_operand:SI 0 "s_register_operand" "=r")
1282         (mult:SI (sign_extend:SI
1283                   (match_operand:HI 1 "s_register_operand" "r"))
1284                  (ashiftrt:SI
1285                   (match_operand:SI 2 "s_register_operand" "r")
1286                   (const_int 16))))]
1287   "TARGET_ARM && arm_arch5e"
1288   "smulbt%?\\t%0, %1, %2"
1289   [(set_attr "insn" "smulxy")
1290    (set_attr "predicable" "yes")]
1293 (define_insn "*mulhisi3tt"
1294   [(set (match_operand:SI 0 "s_register_operand" "=r")
1295         (mult:SI (ashiftrt:SI
1296                   (match_operand:SI 1 "s_register_operand" "r")
1297                   (const_int 16))
1298                  (ashiftrt:SI
1299                   (match_operand:SI 2 "s_register_operand" "r")
1300                   (const_int 16))))]
1301   "TARGET_ARM && arm_arch5e"
1302   "smultt%?\\t%0, %1, %2"
1303   [(set_attr "insn" "smulxy")
1304    (set_attr "predicable" "yes")]
1307 (define_insn "*mulhisi3addsi"
1308   [(set (match_operand:SI 0 "s_register_operand" "=r")
1309         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1310                  (mult:SI (sign_extend:SI
1311                            (match_operand:HI 2 "s_register_operand" "%r"))
1312                           (sign_extend:SI
1313                            (match_operand:HI 3 "s_register_operand" "r")))))]
1314   "TARGET_ARM && arm_arch5e"
1315   "smlabb%?\\t%0, %2, %3, %1"
1316   [(set_attr "insn" "smlaxy")
1317    (set_attr "predicable" "yes")]
1320 (define_insn "*mulhidi3adddi"
1321   [(set (match_operand:DI 0 "s_register_operand" "=r")
1322         (plus:DI
1323           (match_operand:DI 1 "s_register_operand" "0")
1324           (mult:DI (sign_extend:DI
1325                     (match_operand:HI 2 "s_register_operand" "%r"))
1326                    (sign_extend:DI
1327                     (match_operand:HI 3 "s_register_operand" "r")))))]
1328   "TARGET_ARM && arm_arch5e"
1329   "smlalbb%?\\t%Q0, %R0, %2, %3"
1330   [(set_attr "insn" "smlalxy")
1331    (set_attr "predicable" "yes")])
1333 (define_expand "mulsf3"
1334   [(set (match_operand:SF          0 "s_register_operand" "")
1335         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1336                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1337   "TARGET_ARM && TARGET_HARD_FLOAT"
1338   "
1339   if (TARGET_MAVERICK
1340       && !cirrus_fp_register (operands[2], SFmode))
1341     operands[2] = force_reg (SFmode, operands[2]);
1344 (define_expand "muldf3"
1345   [(set (match_operand:DF          0 "s_register_operand" "")
1346         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1347                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1348   "TARGET_ARM && TARGET_HARD_FLOAT"
1349   "
1350   if (TARGET_MAVERICK
1351       && !cirrus_fp_register (operands[2], DFmode))
1352     operands[2] = force_reg (DFmode, operands[2]);
1355 ;; Division insns
1357 (define_expand "divsf3"
1358   [(set (match_operand:SF 0 "s_register_operand" "")
1359         (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1360                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1361   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1362   "")
1364 (define_expand "divdf3"
1365   [(set (match_operand:DF 0 "s_register_operand" "")
1366         (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1367                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1368   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1369   "")
1371 ;; Modulo insns
1373 (define_expand "modsf3"
1374   [(set (match_operand:SF 0 "s_register_operand" "")
1375         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1376                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1377   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1378   "")
1380 (define_expand "moddf3"
1381   [(set (match_operand:DF 0 "s_register_operand" "")
1382         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1383                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1384   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1385   "")
1387 ;; Boolean and,ior,xor insns
1389 ;; Split up double word logical operations
1391 ;; Split up simple DImode logical operations.  Simply perform the logical
1392 ;; operation on the upper and lower halves of the registers.
1393 (define_split
1394   [(set (match_operand:DI 0 "s_register_operand" "")
1395         (match_operator:DI 6 "logical_binary_operator"
1396           [(match_operand:DI 1 "s_register_operand" "")
1397            (match_operand:DI 2 "s_register_operand" "")]))]
1398   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1399   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1400    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1401   "
1402   {
1403     operands[3] = gen_highpart (SImode, operands[0]);
1404     operands[0] = gen_lowpart (SImode, operands[0]);
1405     operands[4] = gen_highpart (SImode, operands[1]);
1406     operands[1] = gen_lowpart (SImode, operands[1]);
1407     operands[5] = gen_highpart (SImode, operands[2]);
1408     operands[2] = gen_lowpart (SImode, operands[2]);
1409   }"
1412 (define_split
1413   [(set (match_operand:DI 0 "s_register_operand" "")
1414         (match_operator:DI 6 "logical_binary_operator"
1415           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1416            (match_operand:DI 1 "s_register_operand" "")]))]
1417   "TARGET_ARM && reload_completed"
1418   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1419    (set (match_dup 3) (match_op_dup:SI 6
1420                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1421                          (match_dup 4)]))]
1422   "
1423   {
1424     operands[3] = gen_highpart (SImode, operands[0]);
1425     operands[0] = gen_lowpart (SImode, operands[0]);
1426     operands[4] = gen_highpart (SImode, operands[1]);
1427     operands[1] = gen_lowpart (SImode, operands[1]);
1428     operands[5] = gen_highpart (SImode, operands[2]);
1429     operands[2] = gen_lowpart (SImode, operands[2]);
1430   }"
1433 ;; The zero extend of operand 2 means we can just copy the high part of
1434 ;; operand1 into operand0.
1435 (define_split
1436   [(set (match_operand:DI 0 "s_register_operand" "")
1437         (ior:DI
1438           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1439           (match_operand:DI 1 "s_register_operand" "")))]
1440   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1441   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1442    (set (match_dup 3) (match_dup 4))]
1443   "
1444   {
1445     operands[4] = gen_highpart (SImode, operands[1]);
1446     operands[3] = gen_highpart (SImode, operands[0]);
1447     operands[0] = gen_lowpart (SImode, operands[0]);
1448     operands[1] = gen_lowpart (SImode, operands[1]);
1449   }"
1452 ;; The zero extend of operand 2 means we can just copy the high part of
1453 ;; operand1 into operand0.
1454 (define_split
1455   [(set (match_operand:DI 0 "s_register_operand" "")
1456         (xor:DI
1457           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1458           (match_operand:DI 1 "s_register_operand" "")))]
1459   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1460   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1461    (set (match_dup 3) (match_dup 4))]
1462   "
1463   {
1464     operands[4] = gen_highpart (SImode, operands[1]);
1465     operands[3] = gen_highpart (SImode, operands[0]);
1466     operands[0] = gen_lowpart (SImode, operands[0]);
1467     operands[1] = gen_lowpart (SImode, operands[1]);
1468   }"
1471 (define_insn "anddi3"
1472   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1473         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1474                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1475   "TARGET_ARM && ! TARGET_IWMMXT"
1476   "#"
1477   [(set_attr "length" "8")]
1480 (define_insn_and_split "*anddi_zesidi_di"
1481   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1482         (and:DI (zero_extend:DI
1483                  (match_operand:SI 2 "s_register_operand" "r,r"))
1484                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1485   "TARGET_ARM"
1486   "#"
1487   "TARGET_ARM && reload_completed"
1488   ; The zero extend of operand 2 clears the high word of the output
1489   ; operand.
1490   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1491    (set (match_dup 3) (const_int 0))]
1492   "
1493   {
1494     operands[3] = gen_highpart (SImode, operands[0]);
1495     operands[0] = gen_lowpart (SImode, operands[0]);
1496     operands[1] = gen_lowpart (SImode, operands[1]);
1497   }"
1498   [(set_attr "length" "8")]
1501 (define_insn "*anddi_sesdi_di"
1502   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1503         (and:DI (sign_extend:DI
1504                  (match_operand:SI 2 "s_register_operand" "r,r"))
1505                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1506   "TARGET_ARM"
1507   "#"
1508   [(set_attr "length" "8")]
1511 (define_expand "andsi3"
1512   [(set (match_operand:SI         0 "s_register_operand" "")
1513         (and:SI (match_operand:SI 1 "s_register_operand" "")
1514                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1515   "TARGET_EITHER"
1516   "
1517   if (TARGET_ARM)
1518     {
1519       if (GET_CODE (operands[2]) == CONST_INT)
1520         {
1521           arm_split_constant (AND, SImode, NULL_RTX,
1522                               INTVAL (operands[2]), operands[0],
1523                               operands[1], optimize && !no_new_pseudos);
1525           DONE;
1526         }
1527     }
1528   else /* TARGET_THUMB */
1529     {
1530       if (GET_CODE (operands[2]) != CONST_INT)
1531         operands[2] = force_reg (SImode, operands[2]);
1532       else
1533         {
1534           int i;
1535           
1536           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1537             {
1538               operands[2] = force_reg (SImode,
1539                                        GEN_INT (~INTVAL (operands[2])));
1540               
1541               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1542               
1543               DONE;
1544             }
1546           for (i = 9; i <= 31; i++)
1547             {
1548               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1549                 {
1550                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1551                                         const0_rtx));
1552                   DONE;
1553                 }
1554               else if ((((HOST_WIDE_INT) 1) << i) - 1
1555                        == ~INTVAL (operands[2]))
1556                 {
1557                   rtx shift = GEN_INT (i);
1558                   rtx reg = gen_reg_rtx (SImode);
1559                 
1560                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1561                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1562                   
1563                   DONE;
1564                 }
1565             }
1567           operands[2] = force_reg (SImode, operands[2]);
1568         }
1569     }
1570   "
1573 (define_insn_and_split "*arm_andsi3_insn"
1574   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1575         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1576                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1577   "TARGET_ARM"
1578   "@
1579    and%?\\t%0, %1, %2
1580    bic%?\\t%0, %1, #%B2
1581    #"
1582   "TARGET_ARM
1583    && GET_CODE (operands[2]) == CONST_INT
1584    && !(const_ok_for_arm (INTVAL (operands[2]))
1585         || const_ok_for_arm (~INTVAL (operands[2])))"
1586   [(clobber (const_int 0))]
1587   "
1588   arm_split_constant  (AND, SImode, curr_insn, 
1589                        INTVAL (operands[2]), operands[0], operands[1], 0);
1590   DONE;
1591   "
1592   [(set_attr "length" "4,4,16")
1593    (set_attr "predicable" "yes")]
1596 (define_insn "*thumb_andsi3_insn"
1597   [(set (match_operand:SI         0 "register_operand" "=l")
1598         (and:SI (match_operand:SI 1 "register_operand" "%0")
1599                 (match_operand:SI 2 "register_operand" "l")))]
1600   "TARGET_THUMB"
1601   "and\\t%0, %0, %2"
1602   [(set_attr "length" "2")]
1605 (define_insn "*andsi3_compare0"
1606   [(set (reg:CC_NOOV CC_REGNUM)
1607         (compare:CC_NOOV
1608          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1609                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1610          (const_int 0)))
1611    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1612         (and:SI (match_dup 1) (match_dup 2)))]
1613   "TARGET_ARM"
1614   "@
1615    and%?s\\t%0, %1, %2
1616    bic%?s\\t%0, %1, #%B2"
1617   [(set_attr "conds" "set")]
1620 (define_insn "*andsi3_compare0_scratch"
1621   [(set (reg:CC_NOOV CC_REGNUM)
1622         (compare:CC_NOOV
1623          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1624                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1625          (const_int 0)))
1626    (clobber (match_scratch:SI 2 "=X,r"))]
1627   "TARGET_ARM"
1628   "@
1629    tst%?\\t%0, %1
1630    bic%?s\\t%2, %0, #%B1"
1631   [(set_attr "conds" "set")]
1634 (define_insn "*zeroextractsi_compare0_scratch"
1635   [(set (reg:CC_NOOV CC_REGNUM)
1636         (compare:CC_NOOV (zero_extract:SI
1637                           (match_operand:SI 0 "s_register_operand" "r")
1638                           (match_operand 1 "const_int_operand" "n")
1639                           (match_operand 2 "const_int_operand" "n"))
1640                          (const_int 0)))]
1641   "TARGET_ARM
1642   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1643       && INTVAL (operands[1]) > 0 
1644       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1645       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1646   "*
1647   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1648                          << INTVAL (operands[2]));
1649   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1650   return \"\";
1651   "
1652   [(set_attr "conds" "set")]
1655 (define_insn_and_split "*ne_zeroextractsi"
1656   [(set (match_operand:SI 0 "s_register_operand" "=r")
1657         (ne:SI (zero_extract:SI
1658                 (match_operand:SI 1 "s_register_operand" "r")
1659                 (match_operand:SI 2 "const_int_operand" "n")
1660                 (match_operand:SI 3 "const_int_operand" "n"))
1661                (const_int 0)))
1662    (clobber (reg:CC CC_REGNUM))]
1663   "TARGET_ARM
1664    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1665        && INTVAL (operands[2]) > 0 
1666        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1667        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1668   "#"
1669   "TARGET_ARM
1670    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1671        && INTVAL (operands[2]) > 0 
1672        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1673        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1674   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1675                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1676                                     (const_int 0)))
1677               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1678    (set (match_dup 0)
1679         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1680                          (match_dup 0) (const_int 1)))]
1681   "
1682   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1683                          << INTVAL (operands[3])); 
1684   "
1685   [(set_attr "conds" "clob")
1686    (set_attr "length" "8")]
1689 (define_insn_and_split "*ne_zeroextractsi_shifted"
1690   [(set (match_operand:SI 0 "s_register_operand" "=r")
1691         (ne:SI (zero_extract:SI
1692                 (match_operand:SI 1 "s_register_operand" "r")
1693                 (match_operand:SI 2 "const_int_operand" "n")
1694                 (const_int 0))
1695                (const_int 0)))
1696    (clobber (reg:CC CC_REGNUM))]
1697   "TARGET_ARM"
1698   "#"
1699   "TARGET_ARM"
1700   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1701                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1702                                     (const_int 0)))
1703               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1704    (set (match_dup 0)
1705         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1706                          (match_dup 0) (const_int 1)))]
1707   "
1708   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1709   "
1710   [(set_attr "conds" "clob")
1711    (set_attr "length" "8")]
1714 (define_insn_and_split "*ite_ne_zeroextractsi"
1715   [(set (match_operand:SI 0 "s_register_operand" "=r")
1716         (if_then_else:SI (ne (zero_extract:SI
1717                               (match_operand:SI 1 "s_register_operand" "r")
1718                               (match_operand:SI 2 "const_int_operand" "n")
1719                               (match_operand:SI 3 "const_int_operand" "n"))
1720                              (const_int 0))
1721                          (match_operand:SI 4 "arm_not_operand" "rIK")
1722                          (const_int 0)))
1723    (clobber (reg:CC CC_REGNUM))]
1724   "TARGET_ARM
1725    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1726        && INTVAL (operands[2]) > 0 
1727        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1728        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1729    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1730   "#"
1731   "TARGET_ARM
1732    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1733        && INTVAL (operands[2]) > 0 
1734        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1735        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1736    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1737   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1738                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1739                                     (const_int 0)))
1740               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1741    (set (match_dup 0)
1742         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1743                          (match_dup 0) (match_dup 4)))]
1744   "
1745   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1746                          << INTVAL (operands[3])); 
1747   "
1748   [(set_attr "conds" "clob")
1749    (set_attr "length" "8")]
1752 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1753   [(set (match_operand:SI 0 "s_register_operand" "=r")
1754         (if_then_else:SI (ne (zero_extract:SI
1755                               (match_operand:SI 1 "s_register_operand" "r")
1756                               (match_operand:SI 2 "const_int_operand" "n")
1757                               (const_int 0))
1758                              (const_int 0))
1759                          (match_operand:SI 3 "arm_not_operand" "rIK")
1760                          (const_int 0)))
1761    (clobber (reg:CC CC_REGNUM))]
1762   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1763   "#"
1764   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1765   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1766                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1767                                     (const_int 0)))
1768               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1769    (set (match_dup 0)
1770         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1771                          (match_dup 0) (match_dup 3)))]
1772   "
1773   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1774   "
1775   [(set_attr "conds" "clob")
1776    (set_attr "length" "8")]
1779 (define_split
1780   [(set (match_operand:SI 0 "s_register_operand" "")
1781         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1782                          (match_operand:SI 2 "const_int_operand" "")
1783                          (match_operand:SI 3 "const_int_operand" "")))
1784    (clobber (match_operand:SI 4 "s_register_operand" ""))]
1785   "TARGET_THUMB"
1786   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1787    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1788   "{
1789      HOST_WIDE_INT temp = INTVAL (operands[2]);
1791      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1792      operands[3] = GEN_INT (32 - temp);
1793    }"
1796 (define_split
1797   [(set (match_operand:SI 0 "s_register_operand" "")
1798         (match_operator:SI 1 "shiftable_operator"
1799          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1800                            (match_operand:SI 3 "const_int_operand" "")
1801                            (match_operand:SI 4 "const_int_operand" ""))
1802           (match_operand:SI 5 "s_register_operand" "")]))
1803    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1804   "TARGET_ARM"
1805   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1806    (set (match_dup 0)
1807         (match_op_dup 1
1808          [(lshiftrt:SI (match_dup 6) (match_dup 4))
1809           (match_dup 5)]))]
1810   "{
1811      HOST_WIDE_INT temp = INTVAL (operands[3]);
1813      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1814      operands[4] = GEN_INT (32 - temp);
1815    }"
1817   
1818 (define_split
1819   [(set (match_operand:SI 0 "s_register_operand" "")
1820         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1821                          (match_operand:SI 2 "const_int_operand" "")
1822                          (match_operand:SI 3 "const_int_operand" "")))]
1823   "TARGET_THUMB"
1824   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1825    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1826   "{
1827      HOST_WIDE_INT temp = INTVAL (operands[2]);
1829      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1830      operands[3] = GEN_INT (32 - temp);
1831    }"
1834 (define_split
1835   [(set (match_operand:SI 0 "s_register_operand" "")
1836         (match_operator:SI 1 "shiftable_operator"
1837          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1838                            (match_operand:SI 3 "const_int_operand" "")
1839                            (match_operand:SI 4 "const_int_operand" ""))
1840           (match_operand:SI 5 "s_register_operand" "")]))
1841    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1842   "TARGET_ARM"
1843   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1844    (set (match_dup 0)
1845         (match_op_dup 1
1846          [(ashiftrt:SI (match_dup 6) (match_dup 4))
1847           (match_dup 5)]))]
1848   "{
1849      HOST_WIDE_INT temp = INTVAL (operands[3]);
1851      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1852      operands[4] = GEN_INT (32 - temp);
1853    }"
1855   
1856 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1857 ;;; represented by the bitfield, then this will produce incorrect results.
1858 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1859 ;;; which have a real bit-field insert instruction, the truncation happens
1860 ;;; in the bit-field insert instruction itself.  Since arm does not have a
1861 ;;; bit-field insert instruction, we would have to emit code here to truncate
1862 ;;; the value before we insert.  This loses some of the advantage of having
1863 ;;; this insv pattern, so this pattern needs to be reevalutated.
1865 (define_expand "insv"
1866   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1867                          (match_operand:SI 1 "general_operand" "")
1868                          (match_operand:SI 2 "general_operand" ""))
1869         (match_operand:SI 3 "reg_or_int_operand" ""))]
1870   "TARGET_ARM"
1871   "
1872   {
1873     int start_bit = INTVAL (operands[2]);
1874     int width = INTVAL (operands[1]);
1875     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1876     rtx target, subtarget;
1878     target = operands[0];
1879     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1880        subreg as the final target.  */
1881     if (GET_CODE (target) == SUBREG)
1882       {
1883         subtarget = gen_reg_rtx (SImode);
1884         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1885             < GET_MODE_SIZE (SImode))
1886           target = SUBREG_REG (target);
1887       }
1888     else
1889       subtarget = target;    
1891     if (GET_CODE (operands[3]) == CONST_INT)
1892       {
1893         /* Since we are inserting a known constant, we may be able to
1894            reduce the number of bits that we have to clear so that
1895            the mask becomes simple.  */
1896         /* ??? This code does not check to see if the new mask is actually
1897            simpler.  It may not be.  */
1898         rtx op1 = gen_reg_rtx (SImode);
1899         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1900            start of this pattern.  */
1901         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1902         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1904         emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1905         emit_insn (gen_iorsi3 (subtarget, op1,
1906                                gen_int_mode (op3_value << start_bit, SImode)));
1907       }
1908     else if (start_bit == 0
1909              && !(const_ok_for_arm (mask)
1910                   || const_ok_for_arm (~mask)))
1911       {
1912         /* A Trick, since we are setting the bottom bits in the word,
1913            we can shift operand[3] up, operand[0] down, OR them together
1914            and rotate the result back again.  This takes 3 insns, and
1915            the third might be mergeable into another op.  */
1916         /* The shift up copes with the possibility that operand[3] is
1917            wider than the bitfield.  */
1918         rtx op0 = gen_reg_rtx (SImode);
1919         rtx op1 = gen_reg_rtx (SImode);
1921         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1922         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1923         emit_insn (gen_iorsi3  (op1, op1, op0));
1924         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1925       }
1926     else if ((width + start_bit == 32)
1927              && !(const_ok_for_arm (mask)
1928                   || const_ok_for_arm (~mask)))
1929       {
1930         /* Similar trick, but slightly less efficient.  */
1932         rtx op0 = gen_reg_rtx (SImode);
1933         rtx op1 = gen_reg_rtx (SImode);
1935         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1936         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1937         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1938         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1939       }
1940     else
1941       {
1942         rtx op0 = GEN_INT (mask);
1943         rtx op1 = gen_reg_rtx (SImode);
1944         rtx op2 = gen_reg_rtx (SImode);
1946         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1947           {
1948             rtx tmp = gen_reg_rtx (SImode);
1950             emit_insn (gen_movsi (tmp, op0));
1951             op0 = tmp;
1952           }
1954         /* Mask out any bits in operand[3] that are not needed.  */
1955            emit_insn (gen_andsi3 (op1, operands[3], op0));
1957         if (GET_CODE (op0) == CONST_INT
1958             && (const_ok_for_arm (mask << start_bit)
1959                 || const_ok_for_arm (~(mask << start_bit))))
1960           {
1961             op0 = GEN_INT (~(mask << start_bit));
1962             emit_insn (gen_andsi3 (op2, operands[0], op0));
1963           }
1964         else
1965           {
1966             if (GET_CODE (op0) == CONST_INT)
1967               {
1968                 rtx tmp = gen_reg_rtx (SImode);
1970                 emit_insn (gen_movsi (tmp, op0));
1971                 op0 = tmp;
1972               }
1974             if (start_bit != 0)
1975               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1976             
1977             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1978           }
1980         if (start_bit != 0)
1981           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1983         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1984       }
1986     if (subtarget != target)
1987       {
1988         /* If TARGET is still a SUBREG, then it must be wider than a word,
1989            so we must be careful only to set the subword we were asked to.  */
1990         if (GET_CODE (target) == SUBREG)
1991           emit_move_insn (target, subtarget);
1992         else
1993           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1994       }
1996     DONE;
1997   }"
2000 ; constants for op 2 will never be given to these patterns.
2001 (define_insn_and_split "*anddi_notdi_di"
2002   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2003         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2004                 (match_operand:DI 2 "s_register_operand" "0,r")))]
2005   "TARGET_ARM"
2006   "#"
2007   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2008   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2009    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2010   "
2011   {
2012     operands[3] = gen_highpart (SImode, operands[0]);
2013     operands[0] = gen_lowpart (SImode, operands[0]);
2014     operands[4] = gen_highpart (SImode, operands[1]);
2015     operands[1] = gen_lowpart (SImode, operands[1]);
2016     operands[5] = gen_highpart (SImode, operands[2]);
2017     operands[2] = gen_lowpart (SImode, operands[2]);
2018   }"
2019   [(set_attr "length" "8")
2020    (set_attr "predicable" "yes")]
2022   
2023 (define_insn_and_split "*anddi_notzesidi_di"
2024   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2025         (and:DI (not:DI (zero_extend:DI
2026                          (match_operand:SI 2 "s_register_operand" "r,r")))
2027                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2028   "TARGET_ARM"
2029   "@
2030    bic%?\\t%Q0, %Q1, %2
2031    #"
2032   ; (not (zero_extend ...)) allows us to just copy the high word from
2033   ; operand1 to operand0.
2034   "TARGET_ARM
2035    && reload_completed
2036    && operands[0] != operands[1]"
2037   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2038    (set (match_dup 3) (match_dup 4))]
2039   "
2040   {
2041     operands[3] = gen_highpart (SImode, operands[0]);
2042     operands[0] = gen_lowpart (SImode, operands[0]);
2043     operands[4] = gen_highpart (SImode, operands[1]);
2044     operands[1] = gen_lowpart (SImode, operands[1]);
2045   }"
2046   [(set_attr "length" "4,8")
2047    (set_attr "predicable" "yes")]
2049   
2050 (define_insn_and_split "*anddi_notsesidi_di"
2051   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2052         (and:DI (not:DI (sign_extend:DI
2053                          (match_operand:SI 2 "s_register_operand" "r,r")))
2054                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2055   "TARGET_ARM"
2056   "#"
2057   "TARGET_ARM && reload_completed"
2058   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2059    (set (match_dup 3) (and:SI (not:SI
2060                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2061                                (match_dup 4)))]
2062   "
2063   {
2064     operands[3] = gen_highpart (SImode, operands[0]);
2065     operands[0] = gen_lowpart (SImode, operands[0]);
2066     operands[4] = gen_highpart (SImode, operands[1]);
2067     operands[1] = gen_lowpart (SImode, operands[1]);
2068   }"
2069   [(set_attr "length" "8")
2070    (set_attr "predicable" "yes")]
2072   
2073 (define_insn "andsi_notsi_si"
2074   [(set (match_operand:SI 0 "s_register_operand" "=r")
2075         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2076                 (match_operand:SI 1 "s_register_operand" "r")))]
2077   "TARGET_ARM"
2078   "bic%?\\t%0, %1, %2"
2079   [(set_attr "predicable" "yes")]
2082 (define_insn "bicsi3"
2083   [(set (match_operand:SI                 0 "register_operand" "=l")
2084         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2085                 (match_operand:SI         2 "register_operand" "0")))]
2086   "TARGET_THUMB"
2087   "bic\\t%0, %0, %1"
2088   [(set_attr "length" "2")]
2091 (define_insn "andsi_not_shiftsi_si"
2092   [(set (match_operand:SI 0 "s_register_operand" "=r")
2093         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2094                          [(match_operand:SI 2 "s_register_operand" "r")
2095                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2096                 (match_operand:SI 1 "s_register_operand" "r")))]
2097   "TARGET_ARM"
2098   "bic%?\\t%0, %1, %2%S4"
2099   [(set_attr "predicable" "yes")
2100    (set_attr "shift" "2")
2101    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2102                       (const_string "alu_shift")
2103                       (const_string "alu_shift_reg")))]
2106 (define_insn "*andsi_notsi_si_compare0"
2107   [(set (reg:CC_NOOV CC_REGNUM)
2108         (compare:CC_NOOV
2109          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2110                  (match_operand:SI 1 "s_register_operand" "r"))
2111          (const_int 0)))
2112    (set (match_operand:SI 0 "s_register_operand" "=r")
2113         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2114   "TARGET_ARM"
2115   "bic%?s\\t%0, %1, %2"
2116   [(set_attr "conds" "set")]
2119 (define_insn "*andsi_notsi_si_compare0_scratch"
2120   [(set (reg:CC_NOOV CC_REGNUM)
2121         (compare:CC_NOOV
2122          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2123                  (match_operand:SI 1 "s_register_operand" "r"))
2124          (const_int 0)))
2125    (clobber (match_scratch:SI 0 "=r"))]
2126   "TARGET_ARM"
2127   "bic%?s\\t%0, %1, %2"
2128   [(set_attr "conds" "set")]
2131 (define_insn "iordi3"
2132   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2133         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2134                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2135   "TARGET_ARM && ! TARGET_IWMMXT"
2136   "#"
2137   [(set_attr "length" "8")
2138    (set_attr "predicable" "yes")]
2141 (define_insn "*iordi_zesidi_di"
2142   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2143         (ior:DI (zero_extend:DI
2144                  (match_operand:SI 2 "s_register_operand" "r,r"))
2145                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2146   "TARGET_ARM"
2147   "@
2148    orr%?\\t%Q0, %Q1, %2
2149    #"
2150   [(set_attr "length" "4,8")
2151    (set_attr "predicable" "yes")]
2154 (define_insn "*iordi_sesidi_di"
2155   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2156         (ior:DI (sign_extend:DI
2157                  (match_operand:SI 2 "s_register_operand" "r,r"))
2158                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2159   "TARGET_ARM"
2160   "#"
2161   [(set_attr "length" "8")
2162    (set_attr "predicable" "yes")]
2165 (define_expand "iorsi3"
2166   [(set (match_operand:SI         0 "s_register_operand" "")
2167         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2168                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2169   "TARGET_EITHER"
2170   "
2171   if (GET_CODE (operands[2]) == CONST_INT)
2172     {
2173       if (TARGET_ARM)
2174         {
2175           arm_split_constant (IOR, SImode, NULL_RTX,
2176                               INTVAL (operands[2]), operands[0], operands[1],
2177                               optimize && !no_new_pseudos);
2178           DONE;
2179         }
2180       else /* TARGET_THUMB */
2181         operands [2] = force_reg (SImode, operands [2]);
2182     }
2183   "
2186 (define_insn_and_split "*arm_iorsi3"
2187   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2188         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2189                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2190   "TARGET_ARM"
2191   "@
2192    orr%?\\t%0, %1, %2
2193    #"
2194   "TARGET_ARM
2195    && GET_CODE (operands[2]) == CONST_INT
2196    && !const_ok_for_arm (INTVAL (operands[2]))"
2197   [(clobber (const_int 0))]
2198   "
2199   arm_split_constant (IOR, SImode, curr_insn, 
2200                       INTVAL (operands[2]), operands[0], operands[1], 0);
2201   DONE;
2202   "
2203   [(set_attr "length" "4,16")
2204    (set_attr "predicable" "yes")]
2207 (define_insn "*thumb_iorsi3"
2208   [(set (match_operand:SI         0 "register_operand" "=l")
2209         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2210                 (match_operand:SI 2 "register_operand" "l")))]
2211   "TARGET_THUMB"
2212   "orr\\t%0, %0, %2"
2213   [(set_attr "length" "2")]
2216 (define_peephole2
2217   [(match_scratch:SI 3 "r")
2218    (set (match_operand:SI 0 "arm_general_register_operand" "")
2219         (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2220                 (match_operand:SI 2 "const_int_operand" "")))]
2221   "TARGET_ARM
2222    && !const_ok_for_arm (INTVAL (operands[2]))
2223    && const_ok_for_arm (~INTVAL (operands[2]))"
2224   [(set (match_dup 3) (match_dup 2))
2225    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2226   ""
2229 (define_insn "*iorsi3_compare0"
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    (set (match_operand:SI 0 "s_register_operand" "=r")
2235         (ior:SI (match_dup 1) (match_dup 2)))]
2236   "TARGET_ARM"
2237   "orr%?s\\t%0, %1, %2"
2238   [(set_attr "conds" "set")]
2241 (define_insn "*iorsi3_compare0_scratch"
2242   [(set (reg:CC_NOOV CC_REGNUM)
2243         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2244                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2245                          (const_int 0)))
2246    (clobber (match_scratch:SI 0 "=r"))]
2247   "TARGET_ARM"
2248   "orr%?s\\t%0, %1, %2"
2249   [(set_attr "conds" "set")]
2252 (define_insn "xordi3"
2253   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2254         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2255                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2256   "TARGET_ARM && !TARGET_IWMMXT"
2257   "#"
2258   [(set_attr "length" "8")
2259    (set_attr "predicable" "yes")]
2262 (define_insn "*xordi_zesidi_di"
2263   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2264         (xor:DI (zero_extend:DI
2265                  (match_operand:SI 2 "s_register_operand" "r,r"))
2266                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2267   "TARGET_ARM"
2268   "@
2269    eor%?\\t%Q0, %Q1, %2
2270    #"
2271   [(set_attr "length" "4,8")
2272    (set_attr "predicable" "yes")]
2275 (define_insn "*xordi_sesidi_di"
2276   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2277         (xor:DI (sign_extend:DI
2278                  (match_operand:SI 2 "s_register_operand" "r,r"))
2279                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2280   "TARGET_ARM"
2281   "#"
2282   [(set_attr "length" "8")
2283    (set_attr "predicable" "yes")]
2286 (define_expand "xorsi3"
2287   [(set (match_operand:SI         0 "s_register_operand" "")
2288         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2289                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2290   "TARGET_EITHER"
2291   "if (TARGET_THUMB)
2292      if (GET_CODE (operands[2]) == CONST_INT)
2293        operands[2] = force_reg (SImode, operands[2]);
2294   "
2297 (define_insn "*arm_xorsi3"
2298   [(set (match_operand:SI         0 "s_register_operand" "=r")
2299         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2300                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2301   "TARGET_ARM"
2302   "eor%?\\t%0, %1, %2"
2303   [(set_attr "predicable" "yes")]
2306 (define_insn "*thumb_xorsi3"
2307   [(set (match_operand:SI         0 "register_operand" "=l")
2308         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2309                 (match_operand:SI 2 "register_operand" "l")))]
2310   "TARGET_THUMB"
2311   "eor\\t%0, %0, %2"
2312   [(set_attr "length" "2")]
2315 (define_insn "*xorsi3_compare0"
2316   [(set (reg:CC_NOOV CC_REGNUM)
2317         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2318                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2319                          (const_int 0)))
2320    (set (match_operand:SI 0 "s_register_operand" "=r")
2321         (xor:SI (match_dup 1) (match_dup 2)))]
2322   "TARGET_ARM"
2323   "eor%?s\\t%0, %1, %2"
2324   [(set_attr "conds" "set")]
2327 (define_insn "*xorsi3_compare0_scratch"
2328   [(set (reg:CC_NOOV CC_REGNUM)
2329         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2330                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2331                          (const_int 0)))]
2332   "TARGET_ARM"
2333   "teq%?\\t%0, %1"
2334   [(set_attr "conds" "set")]
2337 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2338 ; (NOT D) we can sometimes merge the final NOT into one of the following
2339 ; insns.
2341 (define_split
2342   [(set (match_operand:SI 0 "s_register_operand" "")
2343         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2344                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2345                 (match_operand:SI 3 "arm_rhs_operand" "")))
2346    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2347   "TARGET_ARM"
2348   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2349                               (not:SI (match_dup 3))))
2350    (set (match_dup 0) (not:SI (match_dup 4)))]
2351   ""
2354 (define_insn "*andsi_iorsi3_notsi"
2355   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2356         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2357                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2358                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2359   "TARGET_ARM"
2360   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2361   [(set_attr "length" "8")
2362    (set_attr "predicable" "yes")]
2365 (define_split
2366   [(set (match_operand:SI 0 "s_register_operand" "")
2367         (match_operator:SI 1 "logical_binary_operator"
2368          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2369                            (match_operand:SI 3 "const_int_operand" "")
2370                            (match_operand:SI 4 "const_int_operand" ""))
2371           (match_operator:SI 9 "logical_binary_operator"
2372            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2373                          (match_operand:SI 6 "const_int_operand" ""))
2374             (match_operand:SI 7 "s_register_operand" "")])]))
2375    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2376   "TARGET_ARM
2377    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2378    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2379   [(set (match_dup 8)
2380         (match_op_dup 1
2381          [(ashift:SI (match_dup 2) (match_dup 4))
2382           (match_dup 5)]))
2383    (set (match_dup 0)
2384         (match_op_dup 1
2385          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2386           (match_dup 7)]))]
2387   "
2388   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2391 (define_split
2392   [(set (match_operand:SI 0 "s_register_operand" "")
2393         (match_operator:SI 1 "logical_binary_operator"
2394          [(match_operator:SI 9 "logical_binary_operator"
2395            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2396                          (match_operand:SI 6 "const_int_operand" ""))
2397             (match_operand:SI 7 "s_register_operand" "")])
2398           (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2399                            (match_operand:SI 3 "const_int_operand" "")
2400                            (match_operand:SI 4 "const_int_operand" ""))]))
2401    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2402   "TARGET_ARM
2403    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2404    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2405   [(set (match_dup 8)
2406         (match_op_dup 1
2407          [(ashift:SI (match_dup 2) (match_dup 4))
2408           (match_dup 5)]))
2409    (set (match_dup 0)
2410         (match_op_dup 1
2411          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2412           (match_dup 7)]))]
2413   "
2414   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2417 (define_split
2418   [(set (match_operand:SI 0 "s_register_operand" "")
2419         (match_operator:SI 1 "logical_binary_operator"
2420          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2421                            (match_operand:SI 3 "const_int_operand" "")
2422                            (match_operand:SI 4 "const_int_operand" ""))
2423           (match_operator:SI 9 "logical_binary_operator"
2424            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2425                          (match_operand:SI 6 "const_int_operand" ""))
2426             (match_operand:SI 7 "s_register_operand" "")])]))
2427    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2428   "TARGET_ARM
2429    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2430    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2431   [(set (match_dup 8)
2432         (match_op_dup 1
2433          [(ashift:SI (match_dup 2) (match_dup 4))
2434           (match_dup 5)]))
2435    (set (match_dup 0)
2436         (match_op_dup 1
2437          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2438           (match_dup 7)]))]
2439   "
2440   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2443 (define_split
2444   [(set (match_operand:SI 0 "s_register_operand" "")
2445         (match_operator:SI 1 "logical_binary_operator"
2446          [(match_operator:SI 9 "logical_binary_operator"
2447            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2448                          (match_operand:SI 6 "const_int_operand" ""))
2449             (match_operand:SI 7 "s_register_operand" "")])
2450           (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2451                            (match_operand:SI 3 "const_int_operand" "")
2452                            (match_operand:SI 4 "const_int_operand" ""))]))
2453    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2454   "TARGET_ARM
2455    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2456    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2457   [(set (match_dup 8)
2458         (match_op_dup 1
2459          [(ashift:SI (match_dup 2) (match_dup 4))
2460           (match_dup 5)]))
2461    (set (match_dup 0)
2462         (match_op_dup 1
2463          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2464           (match_dup 7)]))]
2465   "
2466   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2470 ;; Minimum and maximum insns
2472 (define_insn "smaxsi3"
2473   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2474         (smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2475                  (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2476    (clobber (reg:CC CC_REGNUM))]
2477   "TARGET_ARM"
2478   "@
2479    cmp\\t%1, %2\;movlt\\t%0, %2
2480    cmp\\t%1, %2\;movge\\t%0, %1
2481    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2482   [(set_attr "conds" "clob")
2483    (set_attr "length" "8,8,12")]
2486 (define_insn "sminsi3"
2487   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2488         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2489                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2490    (clobber (reg:CC CC_REGNUM))]
2491   "TARGET_ARM"
2492   "@
2493    cmp\\t%1, %2\;movge\\t%0, %2
2494    cmp\\t%1, %2\;movlt\\t%0, %1
2495    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2496   [(set_attr "conds" "clob")
2497    (set_attr "length" "8,8,12")]
2500 (define_insn "umaxsi3"
2501   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2502         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2503                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2504    (clobber (reg:CC CC_REGNUM))]
2505   "TARGET_ARM"
2506   "@
2507    cmp\\t%1, %2\;movcc\\t%0, %2
2508    cmp\\t%1, %2\;movcs\\t%0, %1
2509    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2510   [(set_attr "conds" "clob")
2511    (set_attr "length" "8,8,12")]
2514 (define_insn "uminsi3"
2515   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2516         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2517                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2518    (clobber (reg:CC CC_REGNUM))]
2519   "TARGET_ARM"
2520   "@
2521    cmp\\t%1, %2\;movcs\\t%0, %2
2522    cmp\\t%1, %2\;movcc\\t%0, %1
2523    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2524   [(set_attr "conds" "clob")
2525    (set_attr "length" "8,8,12")]
2528 (define_insn "*store_minmaxsi"
2529   [(set (match_operand:SI 0 "memory_operand" "=m")
2530         (match_operator:SI 3 "minmax_operator"
2531          [(match_operand:SI 1 "s_register_operand" "r")
2532           (match_operand:SI 2 "s_register_operand" "r")]))
2533    (clobber (reg:CC CC_REGNUM))]
2534   "TARGET_ARM"
2535   "*
2536   operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2537                                 operands[1], operands[2]);
2538   output_asm_insn (\"cmp\\t%1, %2\", operands);
2539   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2540   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2541   return \"\";
2542   "
2543   [(set_attr "conds" "clob")
2544    (set_attr "length" "12")
2545    (set_attr "type" "store1")]
2548 ; Reject the frame pointer in operand[1], since reloading this after
2549 ; it has been eliminated can cause carnage.
2550 (define_insn "*minmax_arithsi"
2551   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2552         (match_operator:SI 4 "shiftable_operator"
2553          [(match_operator:SI 5 "minmax_operator"
2554            [(match_operand:SI 2 "s_register_operand" "r,r")
2555             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2556           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2557    (clobber (reg:CC CC_REGNUM))]
2558   "TARGET_ARM && !arm_eliminable_register (operands[1])"
2559   "*
2560   {
2561     enum rtx_code code = GET_CODE (operands[4]);
2563     operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2564                                   operands[2], operands[3]);
2565     output_asm_insn (\"cmp\\t%2, %3\", operands);
2566     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2567     if (which_alternative != 0 || operands[3] != const0_rtx
2568         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2569       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2570     return \"\";
2571   }"
2572   [(set_attr "conds" "clob")
2573    (set_attr "length" "12")]
2577 ;; Shift and rotation insns
2579 (define_expand "ashldi3"
2580   [(set (match_operand:DI            0 "s_register_operand" "")
2581         (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2582                    (match_operand:SI 2 "reg_or_int_operand" "")))]
2583   "TARGET_ARM"
2584   "
2585   if (GET_CODE (operands[2]) == CONST_INT)
2586     {
2587       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2588         {
2589           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2590           DONE;
2591         }
2592         /* Ideally we shouldn't fail here if we could know that operands[1] 
2593            ends up already living in an iwmmxt register. Otherwise it's
2594            cheaper to have the alternate code being generated than moving
2595            values to iwmmxt regs and back.  */
2596         FAIL;
2597     }
2598   else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2599     FAIL;
2600   "
2603 (define_insn "arm_ashldi3_1bit"
2604   [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
2605         (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2606                    (const_int 1)))
2607    (clobber (reg:CC CC_REGNUM))]
2608   "TARGET_ARM"
2609   "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2610   [(set_attr "conds" "clob")
2611    (set_attr "length" "8")]
2614 (define_expand "ashlsi3"
2615   [(set (match_operand:SI            0 "s_register_operand" "")
2616         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2617                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2618   "TARGET_EITHER"
2619   "
2620   if (GET_CODE (operands[2]) == CONST_INT
2621       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2622     {
2623       emit_insn (gen_movsi (operands[0], const0_rtx));
2624       DONE;
2625     }
2626   "
2629 (define_insn "*thumb_ashlsi3"
2630   [(set (match_operand:SI            0 "register_operand" "=l,l")
2631         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2632                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2633   "TARGET_THUMB"
2634   "lsl\\t%0, %1, %2"
2635   [(set_attr "length" "2")]
2638 (define_expand "ashrdi3"
2639   [(set (match_operand:DI              0 "s_register_operand" "")
2640         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2641                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2642   "TARGET_ARM"
2643   "
2644   if (GET_CODE (operands[2]) == CONST_INT)
2645     {
2646       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2647         {
2648           emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2649           DONE;
2650         }
2651         /* Ideally we shouldn't fail here if we could know that operands[1] 
2652            ends up already living in an iwmmxt register. Otherwise it's
2653            cheaper to have the alternate code being generated than moving
2654            values to iwmmxt regs and back.  */
2655         FAIL;
2656     }
2657   else if (!TARGET_REALLY_IWMMXT)
2658     FAIL;
2659   "
2662 (define_insn "arm_ashrdi3_1bit"
2663   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2664         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2665                      (const_int 1)))
2666    (clobber (reg:CC CC_REGNUM))]
2667   "TARGET_ARM"
2668   "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2669   [(set_attr "conds" "clob")
2670    (set_attr "length" "8")]
2673 (define_expand "ashrsi3"
2674   [(set (match_operand:SI              0 "s_register_operand" "")
2675         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2676                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2677   "TARGET_EITHER"
2678   "
2679   if (GET_CODE (operands[2]) == CONST_INT
2680       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2681     operands[2] = GEN_INT (31);
2682   "
2685 (define_insn "*thumb_ashrsi3"
2686   [(set (match_operand:SI              0 "register_operand" "=l,l")
2687         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2688                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2689   "TARGET_THUMB"
2690   "asr\\t%0, %1, %2"
2691   [(set_attr "length" "2")]
2694 (define_expand "lshrdi3"
2695   [(set (match_operand:DI              0 "s_register_operand" "")
2696         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2697                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2698   "TARGET_ARM"
2699   "
2700   if (GET_CODE (operands[2]) == CONST_INT)
2701     {
2702       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2703         {
2704           emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2705           DONE;
2706         }
2707         /* Ideally we shouldn't fail here if we could know that operands[1] 
2708            ends up already living in an iwmmxt register. Otherwise it's
2709            cheaper to have the alternate code being generated than moving
2710            values to iwmmxt regs and back.  */
2711         FAIL;
2712     }
2713   else if (!TARGET_REALLY_IWMMXT)
2714     FAIL;
2715   "
2718 (define_insn "arm_lshrdi3_1bit"
2719   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2720         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2721                      (const_int 1)))
2722    (clobber (reg:CC CC_REGNUM))]
2723   "TARGET_ARM"
2724   "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2725   [(set_attr "conds" "clob")
2726    (set_attr "length" "8")]
2729 (define_expand "lshrsi3"
2730   [(set (match_operand:SI              0 "s_register_operand" "")
2731         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2732                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2733   "TARGET_EITHER"
2734   "
2735   if (GET_CODE (operands[2]) == CONST_INT
2736       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2737     {
2738       emit_insn (gen_movsi (operands[0], const0_rtx));
2739       DONE;
2740     }
2741   "
2744 (define_insn "*thumb_lshrsi3"
2745   [(set (match_operand:SI              0 "register_operand" "=l,l")
2746         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2747                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2748   "TARGET_THUMB"
2749   "lsr\\t%0, %1, %2"
2750   [(set_attr "length" "2")]
2753 (define_expand "rotlsi3"
2754   [(set (match_operand:SI              0 "s_register_operand" "")
2755         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2756                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2757   "TARGET_ARM"
2758   "
2759   if (GET_CODE (operands[2]) == CONST_INT)
2760     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2761   else
2762     {
2763       rtx reg = gen_reg_rtx (SImode);
2764       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2765       operands[2] = reg;
2766     }
2767   "
2770 (define_expand "rotrsi3"
2771   [(set (match_operand:SI              0 "s_register_operand" "")
2772         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2773                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2774   "TARGET_EITHER"
2775   "
2776   if (TARGET_ARM)
2777     {
2778       if (GET_CODE (operands[2]) == CONST_INT
2779           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2780         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2781     }
2782   else /* TARGET_THUMB */
2783     {
2784       if (GET_CODE (operands [2]) == CONST_INT)
2785         operands [2] = force_reg (SImode, operands[2]);
2786     }
2787   "
2790 (define_insn "*thumb_rotrsi3"
2791   [(set (match_operand:SI              0 "register_operand" "=l")
2792         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2793                      (match_operand:SI 2 "register_operand" "l")))]
2794   "TARGET_THUMB"
2795   "ror\\t%0, %0, %2"
2796   [(set_attr "length" "2")]
2799 (define_insn "*arm_shiftsi3"
2800   [(set (match_operand:SI   0 "s_register_operand" "=r")
2801         (match_operator:SI  3 "shift_operator"
2802          [(match_operand:SI 1 "s_register_operand"  "r")
2803           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2804   "TARGET_ARM"
2805   "mov%?\\t%0, %1%S3"
2806   [(set_attr "predicable" "yes")
2807    (set_attr "shift" "1")
2808    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2809                       (const_string "alu_shift")
2810                       (const_string "alu_shift_reg")))]
2813 (define_insn "*shiftsi3_compare0"
2814   [(set (reg:CC_NOOV CC_REGNUM)
2815         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2816                           [(match_operand:SI 1 "s_register_operand" "r")
2817                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2818                          (const_int 0)))
2819    (set (match_operand:SI 0 "s_register_operand" "=r")
2820         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2821   "TARGET_ARM"
2822   "mov%?s\\t%0, %1%S3"
2823   [(set_attr "conds" "set")
2824    (set_attr "shift" "1")
2825    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2826                       (const_string "alu_shift")
2827                       (const_string "alu_shift_reg")))]
2830 (define_insn "*shiftsi3_compare0_scratch"
2831   [(set (reg:CC_NOOV CC_REGNUM)
2832         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2833                           [(match_operand:SI 1 "s_register_operand" "r")
2834                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2835                          (const_int 0)))
2836    (clobber (match_scratch:SI 0 "=r"))]
2837   "TARGET_ARM"
2838   "mov%?s\\t%0, %1%S3"
2839   [(set_attr "conds" "set")
2840    (set_attr "shift" "1")]
2843 (define_insn "*notsi_shiftsi"
2844   [(set (match_operand:SI 0 "s_register_operand" "=r")
2845         (not:SI (match_operator:SI 3 "shift_operator"
2846                  [(match_operand:SI 1 "s_register_operand" "r")
2847                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2848   "TARGET_ARM"
2849   "mvn%?\\t%0, %1%S3"
2850   [(set_attr "predicable" "yes")
2851    (set_attr "shift" "1")
2852    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2853                       (const_string "alu_shift")
2854                       (const_string "alu_shift_reg")))]
2857 (define_insn "*notsi_shiftsi_compare0"
2858   [(set (reg:CC_NOOV CC_REGNUM)
2859         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2860                           [(match_operand:SI 1 "s_register_operand" "r")
2861                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2862                          (const_int 0)))
2863    (set (match_operand:SI 0 "s_register_operand" "=r")
2864         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2865   "TARGET_ARM"
2866   "mvn%?s\\t%0, %1%S3"
2867   [(set_attr "conds" "set")
2868    (set_attr "shift" "1")
2869    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2870                       (const_string "alu_shift")
2871                       (const_string "alu_shift_reg")))]
2874 (define_insn "*not_shiftsi_compare0_scratch"
2875   [(set (reg:CC_NOOV CC_REGNUM)
2876         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2877                           [(match_operand:SI 1 "s_register_operand" "r")
2878                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2879                          (const_int 0)))
2880    (clobber (match_scratch:SI 0 "=r"))]
2881   "TARGET_ARM"
2882   "mvn%?s\\t%0, %1%S3"
2883   [(set_attr "conds" "set")
2884    (set_attr "shift" "1")
2885    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2886                       (const_string "alu_shift")
2887                       (const_string "alu_shift_reg")))]
2890 ;; We don't really have extzv, but defining this using shifts helps
2891 ;; to reduce register pressure later on.
2893 (define_expand "extzv"
2894   [(set (match_dup 4)
2895         (ashift:SI (match_operand:SI   1 "register_operand" "")
2896                    (match_operand:SI   2 "const_int_operand" "")))
2897    (set (match_operand:SI              0 "register_operand" "")
2898         (lshiftrt:SI (match_dup 4)
2899                      (match_operand:SI 3 "const_int_operand" "")))]
2900   "TARGET_THUMB"
2901   "
2902   {
2903     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2904     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2905     
2906     operands[3] = GEN_INT (rshift);
2907     
2908     if (lshift == 0)
2909       {
2910         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2911         DONE;
2912       }
2913       
2914     operands[2] = GEN_INT (lshift);
2915     operands[4] = gen_reg_rtx (SImode);
2916   }"
2920 ;; Unary arithmetic insns
2922 (define_expand "negdi2"
2923  [(parallel
2924    [(set (match_operand:DI          0 "s_register_operand" "")
2925           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2926     (clobber (reg:CC CC_REGNUM))])]
2927   "TARGET_EITHER"
2928   "
2929   if (TARGET_THUMB)
2930     {
2931       if (GET_CODE (operands[1]) != REG)
2932         operands[1] = force_reg (SImode, operands[1]);
2933      }
2934   "
2937 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2938 ;; The second alternative is to allow the common case of a *full* overlap.
2939 (define_insn "*arm_negdi2"
2940   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2941         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2942    (clobber (reg:CC CC_REGNUM))]
2943   "TARGET_ARM"
2944   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2945   [(set_attr "conds" "clob")
2946    (set_attr "length" "8")]
2949 (define_insn "*thumb_negdi2"
2950   [(set (match_operand:DI         0 "register_operand" "=&l")
2951         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
2952    (clobber (reg:CC CC_REGNUM))]
2953   "TARGET_THUMB"
2954   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2955   [(set_attr "length" "6")]
2958 (define_expand "negsi2"
2959   [(set (match_operand:SI         0 "s_register_operand" "")
2960         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2961   "TARGET_EITHER"
2962   ""
2965 (define_insn "*arm_negsi2"
2966   [(set (match_operand:SI         0 "s_register_operand" "=r")
2967         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2968   "TARGET_ARM"
2969   "rsb%?\\t%0, %1, #0"
2970   [(set_attr "predicable" "yes")]
2973 (define_insn "*thumb_negsi2"
2974   [(set (match_operand:SI         0 "register_operand" "=l")
2975         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2976   "TARGET_THUMB"
2977   "neg\\t%0, %1"
2978   [(set_attr "length" "2")]
2981 (define_expand "negsf2"
2982   [(set (match_operand:SF         0 "s_register_operand" "")
2983         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2984   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
2985   ""
2988 (define_expand "negdf2"
2989   [(set (match_operand:DF         0 "s_register_operand" "")
2990         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2991   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
2992   "")
2994 ;; abssi2 doesn't really clobber the condition codes if a different register
2995 ;; is being set.  To keep things simple, assume during rtl manipulations that
2996 ;; it does, but tell the final scan operator the truth.  Similarly for
2997 ;; (neg (abs...))
2999 (define_expand "abssi2"
3000   [(parallel
3001     [(set (match_operand:SI         0 "s_register_operand" "")
3002           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3003      (clobber (reg:CC CC_REGNUM))])]
3004   "TARGET_ARM"
3005   "")
3007 (define_insn "*arm_abssi2"
3008   [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
3009         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3010    (clobber (reg:CC CC_REGNUM))]
3011   "TARGET_ARM"
3012   "@
3013    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3014    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3015   [(set_attr "conds" "clob,*")
3016    (set_attr "shift" "1")
3017    ;; predicable can't be set based on the variant, so left as no
3018    (set_attr "length" "8")]
3021 (define_insn "*neg_abssi2"
3022   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3023         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3024    (clobber (reg:CC CC_REGNUM))]
3025   "TARGET_ARM"
3026   "@
3027    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3028    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3029   [(set_attr "conds" "clob,*")
3030    (set_attr "shift" "1")
3031    ;; predicable can't be set based on the variant, so left as no
3032    (set_attr "length" "8")]
3035 (define_expand "abssf2"
3036   [(set (match_operand:SF         0 "s_register_operand" "")
3037         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3038   "TARGET_ARM && TARGET_HARD_FLOAT"
3039   "")
3041 (define_expand "absdf2"
3042   [(set (match_operand:DF         0 "s_register_operand" "")
3043         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3044   "TARGET_ARM && TARGET_HARD_FLOAT"
3045   "")
3047 (define_expand "sqrtsf2"
3048   [(set (match_operand:SF 0 "s_register_operand" "")
3049         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3050   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3051   "")
3053 (define_expand "sqrtdf2"
3054   [(set (match_operand:DF 0 "s_register_operand" "")
3055         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3056   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3057   "")
3059 (define_insn_and_split "one_cmpldi2"
3060   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3061         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3062   "TARGET_ARM"
3063   "#"
3064   "TARGET_ARM && reload_completed"
3065   [(set (match_dup 0) (not:SI (match_dup 1)))
3066    (set (match_dup 2) (not:SI (match_dup 3)))]
3067   "
3068   {
3069     operands[2] = gen_highpart (SImode, operands[0]);
3070     operands[0] = gen_lowpart (SImode, operands[0]);
3071     operands[3] = gen_highpart (SImode, operands[1]);
3072     operands[1] = gen_lowpart (SImode, operands[1]);
3073   }"
3074   [(set_attr "length" "8")
3075    (set_attr "predicable" "yes")]
3078 (define_expand "one_cmplsi2"
3079   [(set (match_operand:SI         0 "s_register_operand" "")
3080         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3081   "TARGET_EITHER"
3082   ""
3085 (define_insn "*arm_one_cmplsi2"
3086   [(set (match_operand:SI         0 "s_register_operand" "=r")
3087         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3088   "TARGET_ARM"
3089   "mvn%?\\t%0, %1"
3090   [(set_attr "predicable" "yes")]
3093 (define_insn "*thumb_one_cmplsi2"
3094   [(set (match_operand:SI         0 "register_operand" "=l")
3095         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3096   "TARGET_THUMB"
3097   "mvn\\t%0, %1"
3098   [(set_attr "length" "2")]
3101 (define_insn "*notsi_compare0"
3102   [(set (reg:CC_NOOV CC_REGNUM)
3103         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3104                          (const_int 0)))
3105    (set (match_operand:SI 0 "s_register_operand" "=r")
3106         (not:SI (match_dup 1)))]
3107   "TARGET_ARM"
3108   "mvn%?s\\t%0, %1"
3109   [(set_attr "conds" "set")]
3112 (define_insn "*notsi_compare0_scratch"
3113   [(set (reg:CC_NOOV CC_REGNUM)
3114         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3115                          (const_int 0)))
3116    (clobber (match_scratch:SI 0 "=r"))]
3117   "TARGET_ARM"
3118   "mvn%?s\\t%0, %1"
3119   [(set_attr "conds" "set")]
3122 ;; Fixed <--> Floating conversion insns
3124 (define_expand "floatsisf2"
3125   [(set (match_operand:SF           0 "s_register_operand" "")
3126         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3127   "TARGET_ARM && TARGET_HARD_FLOAT"
3128   "
3129   if (TARGET_MAVERICK)
3130     {
3131       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3132       DONE;
3133     }
3136 (define_expand "floatsidf2"
3137   [(set (match_operand:DF           0 "s_register_operand" "")
3138         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3139   "TARGET_ARM && TARGET_HARD_FLOAT"
3140   "
3141   if (TARGET_MAVERICK)
3142     {
3143       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3144       DONE;
3145     }
3148 (define_expand "fix_truncsfsi2"
3149   [(set (match_operand:SI         0 "s_register_operand" "")
3150         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3151   "TARGET_ARM && TARGET_HARD_FLOAT"
3152   "
3153   if (TARGET_MAVERICK)
3154     {
3155       if (!cirrus_fp_register (operands[0], SImode))
3156         operands[0] = force_reg (SImode, operands[0]);
3157       if (!cirrus_fp_register (operands[1], SFmode))
3158         operands[1] = force_reg (SFmode, operands[0]);
3159       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3160       DONE;
3161     }
3164 (define_expand "fix_truncdfsi2"
3165   [(set (match_operand:SI         0 "s_register_operand" "")
3166         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3167   "TARGET_ARM && TARGET_HARD_FLOAT"
3168   "
3169   if (TARGET_MAVERICK)
3170     {
3171       if (!cirrus_fp_register (operands[1], DFmode))
3172         operands[1] = force_reg (DFmode, operands[0]);
3173       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3174       DONE;
3175     }
3178 ;; Truncation insns
3180 (define_expand "truncdfsf2"
3181   [(set (match_operand:SF  0 "s_register_operand" "")
3182         (float_truncate:SF
3183          (match_operand:DF 1 "s_register_operand" "")))]
3184   "TARGET_ARM && TARGET_HARD_FLOAT"
3185   ""
3188 ;; Zero and sign extension instructions.
3190 (define_insn "zero_extendsidi2"
3191   [(set (match_operand:DI 0 "s_register_operand" "=r")
3192         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3193   "TARGET_ARM"
3194   "*
3195     if (REGNO (operands[1])
3196         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3197       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3198     return \"mov%?\\t%R0, #0\";
3199   "
3200   [(set_attr "length" "8")
3201    (set_attr "predicable" "yes")]
3204 (define_insn "zero_extendqidi2"
3205   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3206         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3207   "TARGET_ARM"
3208   "@
3209    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3210    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3211   [(set_attr "length" "8")
3212    (set_attr "predicable" "yes")
3213    (set_attr "type" "*,load_byte")
3214    (set_attr "pool_range" "*,4092")
3215    (set_attr "neg_pool_range" "*,4084")]
3218 (define_insn "extendsidi2"
3219   [(set (match_operand:DI 0 "s_register_operand" "=r")
3220         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3221   "TARGET_ARM"
3222   "*
3223     if (REGNO (operands[1])
3224         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3225       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3226     return \"mov%?\\t%R0, %Q0, asr #31\";
3227   "
3228   [(set_attr "length" "8")
3229    (set_attr "shift" "1")
3230    (set_attr "predicable" "yes")]
3233 (define_expand "zero_extendhisi2"
3234   [(set (match_dup 2)
3235         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3236                    (const_int 16)))
3237    (set (match_operand:SI 0 "s_register_operand" "")
3238         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3239   "TARGET_EITHER"
3240   "
3241   {
3242     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3243       {
3244         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3245                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3246         DONE;
3247       }
3249     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3250       {
3251         emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3252         DONE;
3253       }
3255     if (!s_register_operand (operands[1], HImode))
3256       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3258     if (arm_arch6)
3259       {
3260         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3261                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3262         DONE;
3263       }
3265     operands[1] = gen_lowpart (SImode, operands[1]);
3266     operands[2] = gen_reg_rtx (SImode);
3267   }"
3270 (define_insn "*thumb_zero_extendhisi2"
3271   [(set (match_operand:SI 0 "register_operand" "=l")
3272         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3273   "TARGET_THUMB && !arm_arch6"
3274   "*
3275   rtx mem = XEXP (operands[1], 0);
3277   if (GET_CODE (mem) == CONST)
3278     mem = XEXP (mem, 0);
3279     
3280   if (GET_CODE (mem) == LABEL_REF)
3281     return \"ldr\\t%0, %1\";
3282     
3283   if (GET_CODE (mem) == PLUS)
3284     {
3285       rtx a = XEXP (mem, 0);
3286       rtx b = XEXP (mem, 1);
3288       /* This can happen due to bugs in reload.  */
3289       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3290         {
3291           rtx ops[2];
3292           ops[0] = operands[0];
3293           ops[1] = a;
3294       
3295           output_asm_insn (\"mov        %0, %1\", ops);
3297           XEXP (mem, 0) = operands[0];
3298        }
3300       else if (   GET_CODE (a) == LABEL_REF
3301                && GET_CODE (b) == CONST_INT)
3302         return \"ldr\\t%0, %1\";
3303     }
3304     
3305   return \"ldrh\\t%0, %1\";
3306   "
3307   [(set_attr "length" "4")
3308    (set_attr "type" "load_byte")
3309    (set_attr "pool_range" "60")]
3312 (define_insn "*thumb_zero_extendhisi2_v6"
3313   [(set (match_operand:SI 0 "register_operand" "=l,l")
3314         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3315   "TARGET_THUMB && arm_arch6"
3316   "*
3317   rtx mem;
3319   if (which_alternative == 0)
3320     return \"uxth\\t%0, %1\";
3322   mem = XEXP (operands[1], 0);
3324   if (GET_CODE (mem) == CONST)
3325     mem = XEXP (mem, 0);
3326     
3327   if (GET_CODE (mem) == LABEL_REF)
3328     return \"ldr\\t%0, %1\";
3329     
3330   if (GET_CODE (mem) == PLUS)
3331     {
3332       rtx a = XEXP (mem, 0);
3333       rtx b = XEXP (mem, 1);
3335       /* This can happen due to bugs in reload.  */
3336       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3337         {
3338           rtx ops[2];
3339           ops[0] = operands[0];
3340           ops[1] = a;
3341       
3342           output_asm_insn (\"mov        %0, %1\", ops);
3344           XEXP (mem, 0) = operands[0];
3345        }
3347       else if (   GET_CODE (a) == LABEL_REF
3348                && GET_CODE (b) == CONST_INT)
3349         return \"ldr\\t%0, %1\";
3350     }
3351     
3352   return \"ldrh\\t%0, %1\";
3353   "
3354   [(set_attr "length" "2,4")
3355    (set_attr "type" "alu_shift,load_byte")
3356    (set_attr "pool_range" "*,60")]
3359 (define_insn "*arm_zero_extendhisi2"
3360   [(set (match_operand:SI 0 "s_register_operand" "=r")
3361         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3362   "TARGET_ARM && arm_arch4 && !arm_arch6"
3363   "ldr%?h\\t%0, %1"
3364   [(set_attr "type" "load_byte")
3365    (set_attr "predicable" "yes")
3366    (set_attr "pool_range" "256")
3367    (set_attr "neg_pool_range" "244")]
3370 (define_insn "*arm_zero_extendhisi2_v6"
3371   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3372         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3373   "TARGET_ARM && arm_arch6"
3374   "@
3375    uxth%?\\t%0, %1
3376    ldr%?h\\t%0, %1"
3377   [(set_attr "type" "alu_shift,load_byte")
3378    (set_attr "predicable" "yes")
3379    (set_attr "pool_range" "*,256")
3380    (set_attr "neg_pool_range" "*,244")]
3383 (define_insn "*arm_zero_extendhisi2addsi"
3384   [(set (match_operand:SI 0 "s_register_operand" "=r")
3385         (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3386                  (match_operand:SI 2 "s_register_operand" "r")))]
3387   "TARGET_ARM && arm_arch6"
3388   "uxtah%?\\t%0, %2, %1"
3389   [(set_attr "type" "alu_shift")
3390    (set_attr "predicable" "yes")]
3393 (define_split
3394   [(set (match_operand:SI 0 "s_register_operand" "")
3395         (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3396    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3397   "TARGET_ARM && (!arm_arch4)"
3398   [(set (match_dup 2) (match_dup 1))
3399    (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3400   "
3401   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3402     FAIL;
3403   "
3406 (define_split
3407   [(set (match_operand:SI 0 "s_register_operand" "")
3408         (match_operator:SI 3 "shiftable_operator"
3409          [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3410           (match_operand:SI 4 "s_register_operand" "")]))
3411    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3412   "TARGET_ARM && (!arm_arch4)"
3413   [(set (match_dup 2) (match_dup 1))
3414    (set (match_dup 0)
3415         (match_op_dup 3
3416          [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3417   "
3418   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3419     FAIL;
3420   "
3423 (define_expand "zero_extendqisi2"
3424   [(set (match_operand:SI 0 "s_register_operand" "")
3425         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3426   "TARGET_EITHER"
3427   "
3428   if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3429     {
3430       if (TARGET_ARM)
3431         {
3432           emit_insn (gen_andsi3 (operands[0],
3433                                  gen_lowpart (SImode, operands[1]),
3434                                  GEN_INT (255)));
3435         }
3436       else /* TARGET_THUMB */
3437         {
3438           rtx temp = gen_reg_rtx (SImode);
3439           rtx ops[3];
3440           
3441           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3442           operands[1] = gen_lowpart (SImode, operands[1]);
3444           ops[0] = temp;
3445           ops[1] = operands[1];
3446           ops[2] = GEN_INT (24);
3448           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3449                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3450           
3451           ops[0] = operands[0];
3452           ops[1] = temp;
3453           ops[2] = GEN_INT (24);
3455           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3456                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3457         }
3458       DONE;
3459     }
3460   "
3463 (define_insn "*thumb_zero_extendqisi2"
3464   [(set (match_operand:SI 0 "register_operand" "=l")
3465         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3466   "TARGET_THUMB && !arm_arch6"
3467   "ldrb\\t%0, %1"
3468   [(set_attr "length" "2")
3469    (set_attr "type" "load_byte")
3470    (set_attr "pool_range" "32")]
3473 (define_insn "*thumb_zero_extendqisi2_v6"
3474   [(set (match_operand:SI 0 "register_operand" "=l,l")
3475         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3476   "TARGET_THUMB && arm_arch6"
3477   "@
3478    uxtb\\t%0, %1
3479    ldrb\\t%0, %1"
3480   [(set_attr "length" "2,2")
3481    (set_attr "type" "alu_shift,load_byte")
3482    (set_attr "pool_range" "*,32")]
3485 (define_insn "*arm_zero_extendqisi2"
3486   [(set (match_operand:SI 0 "s_register_operand" "=r")
3487         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3488   "TARGET_ARM && !arm_arch6"
3489   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3490   [(set_attr "type" "load_byte")
3491    (set_attr "predicable" "yes")
3492    (set_attr "pool_range" "4096")
3493    (set_attr "neg_pool_range" "4084")]
3496 (define_insn "*arm_zero_extendqisi2_v6"
3497   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3498         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3499   "TARGET_ARM && arm_arch6"
3500   "@
3501    uxtb%?\\t%0, %1
3502    ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3503   [(set_attr "type" "alu_shift,load_byte")
3504    (set_attr "predicable" "yes")
3505    (set_attr "pool_range" "*,4096")
3506    (set_attr "neg_pool_range" "*,4084")]
3509 (define_insn "*arm_zero_extendqisi2addsi"
3510   [(set (match_operand:SI 0 "s_register_operand" "=r")
3511         (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3512                  (match_operand:SI 2 "s_register_operand" "r")))]
3513   "TARGET_ARM && arm_arch6"
3514   "uxtab%?\\t%0, %2, %1"
3515   [(set_attr "predicable" "yes")
3516    (set_attr "type" "alu_shift")]
3519 (define_split
3520   [(set (match_operand:SI 0 "s_register_operand" "")
3521         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3522    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3523   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3524   [(set (match_dup 2) (match_dup 1))
3525    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3526   ""
3529 (define_insn "*compareqi_eq0"
3530   [(set (reg:CC_Z CC_REGNUM)
3531         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3532                          (const_int 0)))]
3533   "TARGET_ARM"
3534   "tst\\t%0, #255"
3535   [(set_attr "conds" "set")]
3538 (define_expand "extendhisi2"
3539   [(set (match_dup 2)
3540         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3541                    (const_int 16)))
3542    (set (match_operand:SI 0 "s_register_operand" "")
3543         (ashiftrt:SI (match_dup 2)
3544                      (const_int 16)))]
3545   "TARGET_EITHER"
3546   "
3547   {
3548     if (GET_CODE (operands[1]) == MEM)
3549       {
3550         if (TARGET_THUMB)
3551           {
3552             emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3553             DONE;
3554           }
3555         else if (arm_arch4)
3556           {
3557             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3558                        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3559             DONE;
3560           }
3561       }
3563     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3564       {
3565         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3566         DONE;
3567       }
3569     if (!s_register_operand (operands[1], HImode))
3570       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3572     if (arm_arch6)
3573       {
3574         if (TARGET_THUMB)
3575           emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3576         else
3577           emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3578                      gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3580         DONE;
3581       }
3583     operands[1] = gen_lowpart (SImode, operands[1]);
3584     operands[2] = gen_reg_rtx (SImode);
3585   }"
3588 (define_insn "thumb_extendhisi2"
3589   [(set (match_operand:SI 0 "register_operand" "=l")
3590         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3591    (clobber (match_scratch:SI 2 "=&l"))]
3592   "TARGET_THUMB && !arm_arch6"
3593   "*
3594   {
3595     rtx ops[4];
3596     rtx mem = XEXP (operands[1], 0);
3598     /* This code used to try to use 'V', and fix the address only if it was
3599        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3600        range of QImode offsets, and offsettable_address_p does a QImode
3601        address check.  */
3602        
3603     if (GET_CODE (mem) == CONST)
3604       mem = XEXP (mem, 0);
3605     
3606     if (GET_CODE (mem) == LABEL_REF)
3607       return \"ldr\\t%0, %1\";
3608     
3609     if (GET_CODE (mem) == PLUS)
3610       {
3611         rtx a = XEXP (mem, 0);
3612         rtx b = XEXP (mem, 1);
3614         if (GET_CODE (a) == LABEL_REF
3615             && GET_CODE (b) == CONST_INT)
3616           return \"ldr\\t%0, %1\";
3618         if (GET_CODE (b) == REG)
3619           return \"ldrsh\\t%0, %1\";
3620           
3621         ops[1] = a;
3622         ops[2] = b;
3623       }
3624     else
3625       {
3626         ops[1] = mem;
3627         ops[2] = const0_rtx;
3628       }
3630     gcc_assert (GET_CODE (ops[1]) == REG);
3632     ops[0] = operands[0];
3633     ops[3] = operands[2];
3634     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3635     return \"\";
3636   }"
3637   [(set_attr "length" "4")
3638    (set_attr "type" "load_byte")
3639    (set_attr "pool_range" "1020")]
3642 ;; We used to have an early-clobber on the scratch register here.
3643 ;; However, there's a bug somewhere in reload which means that this
3644 ;; can be partially ignored during spill allocation if the memory
3645 ;; address also needs reloading; this causes us to die later on when
3646 ;; we try to verify the operands.  Fortunately, we don't really need
3647 ;; the early-clobber: we can always use operand 0 if operand 2
3648 ;; overlaps the address.
3649 (define_insn "*thumb_extendhisi2_insn_v6"
3650   [(set (match_operand:SI 0 "register_operand" "=l,l")
3651         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3652    (clobber (match_scratch:SI 2 "=X,l"))]
3653   "TARGET_THUMB && arm_arch6"
3654   "*
3655   {
3656     rtx ops[4];
3657     rtx mem;
3659     if (which_alternative == 0)
3660       return \"sxth\\t%0, %1\";
3662     mem = XEXP (operands[1], 0);
3664     /* This code used to try to use 'V', and fix the address only if it was
3665        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3666        range of QImode offsets, and offsettable_address_p does a QImode
3667        address check.  */
3668        
3669     if (GET_CODE (mem) == CONST)
3670       mem = XEXP (mem, 0);
3671     
3672     if (GET_CODE (mem) == LABEL_REF)
3673       return \"ldr\\t%0, %1\";
3674     
3675     if (GET_CODE (mem) == PLUS)
3676       {
3677         rtx a = XEXP (mem, 0);
3678         rtx b = XEXP (mem, 1);
3680         if (GET_CODE (a) == LABEL_REF
3681             && GET_CODE (b) == CONST_INT)
3682           return \"ldr\\t%0, %1\";
3684         if (GET_CODE (b) == REG)
3685           return \"ldrsh\\t%0, %1\";
3686           
3687         ops[1] = a;
3688         ops[2] = b;
3689       }
3690     else
3691       {
3692         ops[1] = mem;
3693         ops[2] = const0_rtx;
3694       }
3695       
3696     gcc_assert (GET_CODE (ops[1]) == REG);
3698     ops[0] = operands[0];
3699     if (reg_mentioned_p (operands[2], ops[1]))
3700       ops[3] = ops[0];
3701     else
3702       ops[3] = operands[2];
3703     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3704     return \"\";
3705   }"
3706   [(set_attr "length" "2,4")
3707    (set_attr "type" "alu_shift,load_byte")
3708    (set_attr "pool_range" "*,1020")]
3711 (define_expand "extendhisi2_mem"
3712   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3713    (set (match_dup 3)
3714         (zero_extend:SI (match_dup 7)))
3715    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3716    (set (match_operand:SI 0 "" "")
3717         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3718   "TARGET_ARM"
3719   "
3720   {
3721     rtx mem1, mem2;
3722     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3724     mem1 = gen_rtx_MEM (QImode, addr);
3725     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3726     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3727     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3728     operands[0] = gen_lowpart (SImode, operands[0]);
3729     operands[1] = mem1;
3730     operands[2] = gen_reg_rtx (SImode);
3731     operands[3] = gen_reg_rtx (SImode);
3732     operands[6] = gen_reg_rtx (SImode);
3733     operands[7] = mem2;
3735     if (BYTES_BIG_ENDIAN)
3736       {
3737         operands[4] = operands[2];
3738         operands[5] = operands[3];
3739       }
3740     else
3741       {
3742         operands[4] = operands[3];
3743         operands[5] = operands[2];
3744       }
3745   }"
3748 (define_insn "*arm_extendhisi2"
3749   [(set (match_operand:SI 0 "s_register_operand" "=r")
3750         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3751   "TARGET_ARM && arm_arch4 && !arm_arch6"
3752   "ldr%?sh\\t%0, %1"
3753   [(set_attr "type" "load_byte")
3754    (set_attr "predicable" "yes")
3755    (set_attr "pool_range" "256")
3756    (set_attr "neg_pool_range" "244")]
3759 (define_insn "*arm_extendhisi2_v6"
3760   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3761         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3762   "TARGET_ARM && arm_arch6"
3763   "@
3764    sxth%?\\t%0, %1
3765    ldr%?sh\\t%0, %1"
3766   [(set_attr "type" "alu_shift,load_byte")
3767    (set_attr "predicable" "yes")
3768    (set_attr "pool_range" "*,256")
3769    (set_attr "neg_pool_range" "*,244")]
3772 (define_insn "*arm_extendhisi2addsi"
3773   [(set (match_operand:SI 0 "s_register_operand" "=r")
3774         (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3775                  (match_operand:SI 2 "s_register_operand" "r")))]
3776   "TARGET_ARM && arm_arch6"
3777   "sxtah%?\\t%0, %2, %1"
3780 (define_split
3781   [(set (match_operand:SI                 0 "s_register_operand" "")
3782         (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3783    (clobber (match_operand:SI             2 "s_register_operand" ""))]
3784   "TARGET_ARM && (!arm_arch4)"
3785   [(set (match_dup 2) (match_dup 1))
3786    (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3787   "
3788   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3789     FAIL;
3790   "
3793 (define_split
3794   [(set (match_operand:SI                   0 "s_register_operand" "")
3795         (match_operator:SI                  3 "shiftable_operator"
3796          [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3797           (match_operand:SI                 4 "s_register_operand" "")]))
3798    (clobber (match_operand:SI               2 "s_register_operand" ""))]
3799   "TARGET_ARM && (!arm_arch4)"
3800   [(set (match_dup 2) (match_dup 1))
3801    (set (match_dup 0)
3802         (match_op_dup 3
3803          [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3804   "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3805      FAIL;
3806   "
3809 (define_expand "extendqihi2"
3810   [(set (match_dup 2)
3811         (ashift:SI (match_operand:QI 1 "general_operand" "")
3812                    (const_int 24)))
3813    (set (match_operand:HI 0 "s_register_operand" "")
3814         (ashiftrt:SI (match_dup 2)
3815                      (const_int 24)))]
3816   "TARGET_ARM"
3817   "
3818   {
3819     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3820       {
3821         emit_insn (gen_rtx_SET (VOIDmode,
3822                                 operands[0],
3823                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3824         DONE;
3825       }
3826     if (!s_register_operand (operands[1], QImode))
3827       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3828     operands[0] = gen_lowpart (SImode, operands[0]);
3829     operands[1] = gen_lowpart (SImode, operands[1]);
3830     operands[2] = gen_reg_rtx (SImode);
3831   }"
3834 (define_insn "*extendqihi_insn"
3835   [(set (match_operand:HI 0 "s_register_operand" "=r")
3836         (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3837   "TARGET_ARM && arm_arch4"
3838   "ldr%?sb\\t%0, %1"
3839   [(set_attr "type" "load_byte")
3840    (set_attr "predicable" "yes")
3841    (set_attr "pool_range" "256")
3842    (set_attr "neg_pool_range" "244")]
3845 (define_expand "extendqisi2"
3846   [(set (match_dup 2)
3847         (ashift:SI (match_operand:QI 1 "general_operand" "")
3848                    (const_int 24)))
3849    (set (match_operand:SI 0 "s_register_operand" "")
3850         (ashiftrt:SI (match_dup 2)
3851                      (const_int 24)))]
3852   "TARGET_EITHER"
3853   "
3854   {
3855     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3856       {
3857         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3858                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3859         DONE;
3860       }
3862     if (!s_register_operand (operands[1], QImode))
3863       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3865     if (arm_arch6)
3866       {
3867         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3868                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3869         DONE;
3870       }
3872     operands[1] = gen_lowpart (SImode, operands[1]);
3873     operands[2] = gen_reg_rtx (SImode);
3874   }"
3877 (define_insn "*arm_extendqisi"
3878   [(set (match_operand:SI 0 "s_register_operand" "=r")
3879         (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3880   "TARGET_ARM && arm_arch4 && !arm_arch6"
3881   "ldr%?sb\\t%0, %1"
3882   [(set_attr "type" "load_byte")
3883    (set_attr "predicable" "yes")
3884    (set_attr "pool_range" "256")
3885    (set_attr "neg_pool_range" "244")]
3888 (define_insn "*arm_extendqisi_v6"
3889   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3890         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3891   "TARGET_ARM && arm_arch6"
3892   "@
3893    sxtb%?\\t%0, %1
3894    ldr%?sb\\t%0, %1"
3895   [(set_attr "type" "alu_shift,load_byte")
3896    (set_attr "predicable" "yes")
3897    (set_attr "pool_range" "*,256")
3898    (set_attr "neg_pool_range" "*,244")]
3901 (define_insn "*arm_extendqisi2addsi"
3902   [(set (match_operand:SI 0 "s_register_operand" "=r")
3903         (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3904                  (match_operand:SI 2 "s_register_operand" "r")))]
3905   "TARGET_ARM && arm_arch6"
3906   "sxtab%?\\t%0, %2, %1"
3907   [(set_attr "type" "alu_shift")
3908    (set_attr "predicable" "yes")]
3911 (define_insn "*thumb_extendqisi2"
3912   [(set (match_operand:SI 0 "register_operand" "=l,l")
3913         (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3914   "TARGET_THUMB && !arm_arch6"
3915   "*
3916   {
3917     rtx ops[3];
3918     rtx mem = XEXP (operands[1], 0);
3919     
3920     if (GET_CODE (mem) == CONST)
3921       mem = XEXP (mem, 0);
3922     
3923     if (GET_CODE (mem) == LABEL_REF)
3924       return \"ldr\\t%0, %1\";
3926     if (GET_CODE (mem) == PLUS
3927         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3928       return \"ldr\\t%0, %1\";
3929       
3930     if (which_alternative == 0)
3931       return \"ldrsb\\t%0, %1\";
3932       
3933     ops[0] = operands[0];
3934     
3935     if (GET_CODE (mem) == PLUS)
3936       {
3937         rtx a = XEXP (mem, 0);
3938         rtx b = XEXP (mem, 1);
3939         
3940         ops[1] = a;
3941         ops[2] = b;
3943         if (GET_CODE (a) == REG)
3944           {
3945             if (GET_CODE (b) == REG)
3946               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3947             else if (REGNO (a) == REGNO (ops[0]))
3948               {
3949                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3950                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3951                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3952               }
3953             else
3954               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3955           }
3956         else
3957           {
3958             gcc_assert (GET_CODE (b) == REG);
3959             if (REGNO (b) == REGNO (ops[0]))
3960               {
3961                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3962                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3963                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3964               }
3965             else
3966               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3967           }
3968       }
3969     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3970       {
3971         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3972         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3973         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3974       }
3975     else
3976       {
3977         ops[1] = mem;
3978         ops[2] = const0_rtx;
3979         
3980         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3981       }
3982     return \"\";
3983   }"
3984   [(set_attr "length" "2,6")
3985    (set_attr "type" "load_byte,load_byte")
3986    (set_attr "pool_range" "32,32")]
3989 (define_insn "*thumb_extendqisi2_v6"
3990   [(set (match_operand:SI 0 "register_operand" "=l,l,l")
3991         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
3992   "TARGET_THUMB && arm_arch6"
3993   "*
3994   {
3995     rtx ops[3];
3996     rtx mem;
3998     if (which_alternative == 0)
3999       return \"sxtb\\t%0, %1\";
4001     mem = XEXP (operands[1], 0);
4002     
4003     if (GET_CODE (mem) == CONST)
4004       mem = XEXP (mem, 0);
4005     
4006     if (GET_CODE (mem) == LABEL_REF)
4007       return \"ldr\\t%0, %1\";
4009     if (GET_CODE (mem) == PLUS
4010         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4011       return \"ldr\\t%0, %1\";
4012       
4013     if (which_alternative == 0)
4014       return \"ldrsb\\t%0, %1\";
4015       
4016     ops[0] = operands[0];
4017     
4018     if (GET_CODE (mem) == PLUS)
4019       {
4020         rtx a = XEXP (mem, 0);
4021         rtx b = XEXP (mem, 1);
4022         
4023         ops[1] = a;
4024         ops[2] = b;
4026         if (GET_CODE (a) == REG)
4027           {
4028             if (GET_CODE (b) == REG)
4029               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4030             else if (REGNO (a) == REGNO (ops[0]))
4031               {
4032                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4033                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4034               }
4035             else
4036               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4037           }
4038         else
4039           {
4040             gcc_assert (GET_CODE (b) == REG);
4041             if (REGNO (b) == REGNO (ops[0]))
4042               {
4043                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4044                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4045               }
4046             else
4047               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4048           }
4049       }
4050     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4051       {
4052         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4053         output_asm_insn (\"sxtb\\t%0, %0\", ops);
4054       }
4055     else
4056       {
4057         ops[1] = mem;
4058         ops[2] = const0_rtx;
4059         
4060         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4061       }
4062     return \"\";
4063   }"
4064   [(set_attr "length" "2,2,4")
4065    (set_attr "type" "alu_shift,load_byte,load_byte")
4066    (set_attr "pool_range" "*,32,32")]
4069 (define_expand "extendsfdf2"
4070   [(set (match_operand:DF                  0 "s_register_operand" "")
4071         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
4072   "TARGET_ARM && TARGET_HARD_FLOAT"
4073   ""
4076 ;; Move insns (including loads and stores)
4078 ;; XXX Just some ideas about movti.
4079 ;; I don't think these are a good idea on the arm, there just aren't enough
4080 ;; registers
4081 ;;(define_expand "loadti"
4082 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
4083 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
4084 ;;  "" "")
4086 ;;(define_expand "storeti"
4087 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4088 ;;      (match_operand:TI 1 "s_register_operand" ""))]
4089 ;;  "" "")
4091 ;;(define_expand "movti"
4092 ;;  [(set (match_operand:TI 0 "general_operand" "")
4093 ;;      (match_operand:TI 1 "general_operand" ""))]
4094 ;;  ""
4095 ;;  "
4097 ;;  rtx insn;
4099 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4100 ;;    operands[1] = copy_to_reg (operands[1]);
4101 ;;  if (GET_CODE (operands[0]) == MEM)
4102 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4103 ;;  else if (GET_CODE (operands[1]) == MEM)
4104 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4105 ;;  else
4106 ;;    FAIL;
4108 ;;  emit_insn (insn);
4109 ;;  DONE;
4110 ;;}")
4112 ;; Recognize garbage generated above.
4114 ;;(define_insn ""
4115 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4116 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4117 ;;  ""
4118 ;;  "*
4119 ;;  {
4120 ;;    register mem = (which_alternative < 3);
4121 ;;    register const char *template;
4123 ;;    operands[mem] = XEXP (operands[mem], 0);
4124 ;;    switch (which_alternative)
4125 ;;      {
4126 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4127 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
4128 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
4129 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
4130 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
4131 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
4132 ;;      }
4133 ;;    output_asm_insn (template, operands);
4134 ;;    return \"\";
4135 ;;  }")
4137 (define_expand "movdi"
4138   [(set (match_operand:DI 0 "general_operand" "")
4139         (match_operand:DI 1 "general_operand" ""))]
4140   "TARGET_EITHER"
4141   "
4142   if (TARGET_THUMB)
4143     {
4144       if (!no_new_pseudos)
4145         {
4146           if (GET_CODE (operands[0]) != REG)
4147             operands[1] = force_reg (DImode, operands[1]);
4148         }
4149     }
4150   "
4153 (define_insn "*arm_movdi"
4154   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4155         (match_operand:DI 1 "di_operand"              "rDa,Db,Dc,mi,r"))]
4156   "TARGET_ARM
4157   && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4158   && !TARGET_IWMMXT"
4159   "*
4160   switch (which_alternative)
4161     {
4162     case 0:
4163     case 1:
4164     case 2:
4165       return \"#\";
4166     default:
4167       return output_move_double (operands);
4168     }
4169   "
4170   [(set_attr "length" "8,12,16,8,8")
4171    (set_attr "type" "*,*,*,load2,store2")
4172    (set_attr "pool_range" "*,*,*,1020,*")
4173    (set_attr "neg_pool_range" "*,*,*,1008,*")]
4176 (define_split
4177   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4178         (match_operand:ANY64 1 "const_double_operand" ""))]
4179   "TARGET_ARM
4180    && reload_completed
4181    && (arm_const_double_inline_cost (operands[1])
4182        <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4183   [(const_int 0)]
4184   "
4185   arm_split_constant (SET, SImode, curr_insn,
4186                       INTVAL (gen_lowpart (SImode, operands[1])),
4187                       gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4188   arm_split_constant (SET, SImode, curr_insn,
4189                       INTVAL (gen_highpart_mode (SImode,
4190                                                  GET_MODE (operands[0]),
4191                                                  operands[1])),
4192                       gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4193   DONE;
4194   "
4197 ; If optimizing for size, or if we have load delay slots, then 
4198 ; we want to split the constant into two separate operations. 
4199 ; In both cases this may split a trivial part into a single data op
4200 ; leaving a single complex constant to load.  We can also get longer
4201 ; offsets in a LDR which means we get better chances of sharing the pool
4202 ; entries.  Finally, we can normally do a better job of scheduling
4203 ; LDR instructions than we can with LDM.
4204 ; This pattern will only match if the one above did not.
4205 (define_split
4206   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4207         (match_operand:ANY64 1 "const_double_operand" ""))]
4208   "TARGET_ARM && reload_completed
4209    && arm_const_double_by_parts (operands[1])"
4210   [(set (match_dup 0) (match_dup 1))
4211    (set (match_dup 2) (match_dup 3))]
4212   "
4213   operands[2] = gen_highpart (SImode, operands[0]);
4214   operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4215                                    operands[1]);
4216   operands[0] = gen_lowpart (SImode, operands[0]);
4217   operands[1] = gen_lowpart (SImode, operands[1]);
4218   "
4221 (define_split
4222   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4223         (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4224   "TARGET_EITHER && reload_completed"
4225   [(set (match_dup 0) (match_dup 1))
4226    (set (match_dup 2) (match_dup 3))]
4227   "
4228   operands[2] = gen_highpart (SImode, operands[0]);
4229   operands[3] = gen_highpart (SImode, operands[1]);
4230   operands[0] = gen_lowpart (SImode, operands[0]);
4231   operands[1] = gen_lowpart (SImode, operands[1]);
4233   /* Handle a partial overlap.  */
4234   if (rtx_equal_p (operands[0], operands[3]))
4235     {
4236       rtx tmp0 = operands[0];
4237       rtx tmp1 = operands[1];
4239       operands[0] = operands[2];
4240       operands[1] = operands[3];
4241       operands[2] = tmp0;
4242       operands[3] = tmp1;
4243     }
4244   "
4247 ;; We can't actually do base+index doubleword loads if the index and
4248 ;; destination overlap.  Split here so that we at least have chance to
4249 ;; schedule.
4250 (define_split
4251   [(set (match_operand:DI 0 "s_register_operand" "")
4252         (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4253                          (match_operand:SI 2 "s_register_operand" ""))))]
4254   "TARGET_LDRD
4255   && reg_overlap_mentioned_p (operands[0], operands[1])
4256   && reg_overlap_mentioned_p (operands[0], operands[2])"
4257   [(set (match_dup 4)
4258         (plus:SI (match_dup 1)
4259                  (match_dup 2)))
4260    (set (match_dup 0)
4261         (mem:DI (match_dup 4)))]
4262   "
4263   operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4264   "
4267 ;;; ??? This should have alternatives for constants.
4268 ;;; ??? This was originally identical to the movdf_insn pattern.
4269 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4270 ;;; thumb_reorg with a memory reference.
4271 (define_insn "*thumb_movdi_insn"
4272   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4273         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
4274   "TARGET_THUMB
4275    && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4276    && (   register_operand (operands[0], DImode)
4277        || register_operand (operands[1], DImode))"
4278   "*
4279   {
4280   switch (which_alternative)
4281     {
4282     default:
4283     case 0:
4284       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4285         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
4286       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
4287     case 1:
4288       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4289     case 2:
4290       operands[1] = GEN_INT (- INTVAL (operands[1]));
4291       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4292     case 3:
4293       return \"ldmia\\t%1, {%0, %H0}\";
4294     case 4:
4295       return \"stmia\\t%0, {%1, %H1}\";
4296     case 5:
4297       return thumb_load_double_from_address (operands);
4298     case 6:
4299       operands[2] = gen_rtx_MEM (SImode,
4300                              plus_constant (XEXP (operands[0], 0), 4));
4301       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4302       return \"\";
4303     case 7:
4304       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4305         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4306       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4307     }
4308   }"
4309   [(set_attr "length" "4,4,6,2,2,6,4,4")
4310    (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4311    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4314 (define_expand "movsi"
4315   [(set (match_operand:SI 0 "general_operand" "")
4316         (match_operand:SI 1 "general_operand" ""))]
4317   "TARGET_EITHER"
4318   "
4319   if (TARGET_ARM)
4320     {
4321       /* Everything except mem = const or mem = mem can be done easily.  */
4322       if (GET_CODE (operands[0]) == MEM)
4323         operands[1] = force_reg (SImode, operands[1]);
4324       if (arm_general_register_operand (operands[0], SImode)
4325           && GET_CODE (operands[1]) == CONST_INT
4326           && !(const_ok_for_arm (INTVAL (operands[1]))
4327                || const_ok_for_arm (~INTVAL (operands[1]))))
4328         {
4329            arm_split_constant (SET, SImode, NULL_RTX,
4330                                INTVAL (operands[1]), operands[0], NULL_RTX,
4331                                optimize && !no_new_pseudos);
4332           DONE;
4333         }
4334     }
4335   else /* TARGET_THUMB....  */
4336     {
4337       if (!no_new_pseudos)
4338         {
4339           if (GET_CODE (operands[0]) != REG)
4340             operands[1] = force_reg (SImode, operands[1]);
4341         }
4342     }
4343     
4344   if (flag_pic
4345       && (CONSTANT_P (operands[1])
4346          || symbol_mentioned_p (operands[1])
4347          || label_mentioned_p (operands[1])))
4348     operands[1] = legitimize_pic_address (operands[1], SImode,
4349                                           (no_new_pseudos ? operands[0] : 0));
4350   "
4353 (define_insn "*arm_movsi_insn"
4354   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4355         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
4356   "TARGET_ARM && ! TARGET_IWMMXT
4357    && !(TARGET_HARD_FLOAT && TARGET_VFP)
4358    && (   register_operand (operands[0], SImode)
4359        || register_operand (operands[1], SImode))"
4360   "@
4361    mov%?\\t%0, %1
4362    mvn%?\\t%0, #%B1
4363    ldr%?\\t%0, %1
4364    str%?\\t%1, %0"
4365   [(set_attr "type" "*,*,load1,store1")
4366    (set_attr "predicable" "yes")
4367    (set_attr "pool_range" "*,*,4096,*")
4368    (set_attr "neg_pool_range" "*,*,4084,*")]
4371 (define_split
4372   [(set (match_operand:SI 0 "arm_general_register_operand" "")
4373         (match_operand:SI 1 "const_int_operand" ""))]
4374   "TARGET_ARM
4375   && (!(const_ok_for_arm (INTVAL (operands[1]))
4376         || const_ok_for_arm (~INTVAL (operands[1]))))"
4377   [(clobber (const_int 0))]
4378   "
4379   arm_split_constant (SET, SImode, NULL_RTX, 
4380                       INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4381   DONE;
4382   "
4385 (define_insn "*thumb_movsi_insn"
4386   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4387         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4388   "TARGET_THUMB
4389    && (   register_operand (operands[0], SImode) 
4390        || register_operand (operands[1], SImode))"
4391   "@
4392    mov  %0, %1
4393    mov  %0, %1
4394    #
4395    #
4396    ldmia\\t%1, {%0}
4397    stmia\\t%0, {%1}
4398    ldr\\t%0, %1
4399    str\\t%1, %0
4400    mov\\t%0, %1"
4401   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4402    (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4403    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4406 (define_split 
4407   [(set (match_operand:SI 0 "register_operand" "")
4408         (match_operand:SI 1 "const_int_operand" ""))]
4409   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4410   [(set (match_dup 0) (match_dup 1))
4411    (set (match_dup 0) (neg:SI (match_dup 0)))]
4412   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4415 (define_split 
4416   [(set (match_operand:SI 0 "register_operand" "")
4417         (match_operand:SI 1 "const_int_operand" ""))]
4418   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4419   [(set (match_dup 0) (match_dup 1))
4420    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4421   "
4422   {
4423     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4424     unsigned HOST_WIDE_INT mask = 0xff;
4425     int i;
4426     
4427     for (i = 0; i < 25; i++)
4428       if ((val & (mask << i)) == val)
4429         break;
4431     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4432     if (i == 0)
4433       FAIL;
4435     operands[1] = GEN_INT (val >> i);
4436     operands[2] = GEN_INT (i);
4437   }"
4440 ;; When generating pic, we need to load the symbol offset into a register.
4441 ;; So that the optimizer does not confuse this with a normal symbol load
4442 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
4443 ;; since that is the only type of relocation we can use.
4445 ;; The rather odd constraints on the following are to force reload to leave
4446 ;; the insn alone, and to force the minipool generation pass to then move
4447 ;; the GOT symbol to memory.
4449 (define_insn "pic_load_addr_arm"
4450   [(set (match_operand:SI 0 "s_register_operand" "=r")
4451         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4452   "TARGET_ARM && flag_pic"
4453   "ldr%?\\t%0, %1"
4454   [(set_attr "type" "load1")
4455    (set (attr "pool_range")     (const_int 4096))
4456    (set (attr "neg_pool_range") (const_int 4084))]
4459 (define_insn "pic_load_addr_thumb"
4460   [(set (match_operand:SI 0 "s_register_operand" "=l")
4461         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4462   "TARGET_THUMB && flag_pic"
4463   "ldr\\t%0, %1"
4464   [(set_attr "type" "load1")
4465    (set (attr "pool_range") (const_int 1024))]
4468 ;; This variant is used for AOF assembly, since it needs to mention the
4469 ;; pic register in the rtl.
4470 (define_expand "pic_load_addr_based"
4471   [(set (match_operand:SI 0 "s_register_operand" "")
4472         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4473   "TARGET_ARM && flag_pic"
4474   "operands[2] = pic_offset_table_rtx;"
4477 (define_insn "*pic_load_addr_based_insn"
4478   [(set (match_operand:SI 0 "s_register_operand" "=r")
4479         (unspec:SI [(match_operand 1 "" "")
4480                     (match_operand 2 "s_register_operand" "r")]
4481                    UNSPEC_PIC_SYM))]
4482   "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4483   "*
4484 #ifdef AOF_ASSEMBLER
4485   operands[1] = aof_pic_entry (operands[1]);
4486 #endif
4487   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4488   return \"\";
4489   "
4490   [(set_attr "type" "load1")
4491    (set (attr "pool_range")
4492         (if_then_else (eq_attr "is_thumb" "yes")
4493                       (const_int 1024)
4494                       (const_int 4096)))
4495    (set (attr "neg_pool_range")
4496         (if_then_else (eq_attr "is_thumb" "yes")
4497                       (const_int 0)
4498                       (const_int 4084)))]
4501 (define_insn "pic_add_dot_plus_four"
4502   [(set (match_operand:SI 0 "register_operand" "+r")
4503         (unspec:SI [(plus:SI (match_dup 0)
4504                              (const (plus:SI (pc) (const_int 4))))]
4505                    UNSPEC_PIC_BASE))
4506    (use (label_ref (match_operand 1 "" "")))]
4507   "TARGET_THUMB && flag_pic"
4508   "*
4509   (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4510                              CODE_LABEL_NUMBER (operands[1]));
4511   return \"add\\t%0, %|pc\";
4512   "
4513   [(set_attr "length" "2")]
4516 (define_insn "pic_add_dot_plus_eight"
4517   [(set (match_operand:SI 0 "register_operand" "+r")
4518         (unspec:SI [(plus:SI (match_dup 0)
4519                              (const (plus:SI (pc) (const_int 8))))]
4520                    UNSPEC_PIC_BASE))
4521    (use (label_ref (match_operand 1 "" "")))]
4522   "TARGET_ARM && flag_pic"
4523   "*
4524     (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4525                                CODE_LABEL_NUMBER (operands[1]));
4526     return \"add%?\\t%0, %|pc, %0\";
4527   "
4528   [(set_attr "predicable" "yes")]
4531 (define_expand "builtin_setjmp_receiver"
4532   [(label_ref (match_operand 0 "" ""))]
4533   "flag_pic"
4534   "
4536   /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4537      register.  */
4538   arm_load_pic_register (3);
4539   DONE;
4542 ;; If copying one reg to another we can set the condition codes according to
4543 ;; its value.  Such a move is common after a return from subroutine and the
4544 ;; result is being tested against zero.
4546 (define_insn "*movsi_compare0"
4547   [(set (reg:CC CC_REGNUM)
4548         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4549                     (const_int 0)))
4550    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4551         (match_dup 1))]
4552   "TARGET_ARM"
4553   "@
4554    cmp%?\\t%0, #0
4555    sub%?s\\t%0, %1, #0"
4556   [(set_attr "conds" "set")]
4559 ;; Subroutine to store a half word from a register into memory.
4560 ;; Operand 0 is the source register (HImode)
4561 ;; Operand 1 is the destination address in a register (SImode)
4563 ;; In both this routine and the next, we must be careful not to spill
4564 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4565 ;; can generate unrecognizable rtl.
4567 (define_expand "storehi"
4568   [;; store the low byte
4569    (set (match_operand 1 "" "") (match_dup 3))
4570    ;; extract the high byte
4571    (set (match_dup 2)
4572         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4573    ;; store the high byte
4574    (set (match_dup 4) (match_dup 5))]
4575   "TARGET_ARM"
4576   "
4577   {
4578     rtx op1 = operands[1];
4579     rtx addr = XEXP (op1, 0);
4580     enum rtx_code code = GET_CODE (addr);
4582     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4583         || code == MINUS)
4584       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4586     operands[4] = adjust_address (op1, QImode, 1);
4587     operands[1] = adjust_address (operands[1], QImode, 0);
4588     operands[3] = gen_lowpart (QImode, operands[0]);
4589     operands[0] = gen_lowpart (SImode, operands[0]);
4590     operands[2] = gen_reg_rtx (SImode);
4591     operands[5] = gen_lowpart (QImode, operands[2]);
4592   }"
4595 (define_expand "storehi_bigend"
4596   [(set (match_dup 4) (match_dup 3))
4597    (set (match_dup 2)
4598         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4599    (set (match_operand 1 "" "") (match_dup 5))]
4600   "TARGET_ARM"
4601   "
4602   {
4603     rtx op1 = operands[1];
4604     rtx addr = XEXP (op1, 0);
4605     enum rtx_code code = GET_CODE (addr);
4607     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4608         || code == MINUS)
4609       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4611     operands[4] = adjust_address (op1, QImode, 1);
4612     operands[1] = adjust_address (operands[1], QImode, 0);
4613     operands[3] = gen_lowpart (QImode, operands[0]);
4614     operands[0] = gen_lowpart (SImode, operands[0]);
4615     operands[2] = gen_reg_rtx (SImode);
4616     operands[5] = gen_lowpart (QImode, operands[2]);
4617   }"
4620 ;; Subroutine to store a half word integer constant into memory.
4621 (define_expand "storeinthi"
4622   [(set (match_operand 0 "" "")
4623         (match_operand 1 "" ""))
4624    (set (match_dup 3) (match_dup 2))]
4625   "TARGET_ARM"
4626   "
4627   {
4628     HOST_WIDE_INT value = INTVAL (operands[1]);
4629     rtx addr = XEXP (operands[0], 0);
4630     rtx op0 = operands[0];
4631     enum rtx_code code = GET_CODE (addr);
4633     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4634         || code == MINUS)
4635       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4637     operands[1] = gen_reg_rtx (SImode);
4638     if (BYTES_BIG_ENDIAN)
4639       {
4640         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4641         if ((value & 255) == ((value >> 8) & 255))
4642           operands[2] = operands[1];
4643         else
4644           {
4645             operands[2] = gen_reg_rtx (SImode);
4646             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4647           }
4648       }
4649     else
4650       {
4651         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4652         if ((value & 255) == ((value >> 8) & 255))
4653           operands[2] = operands[1];
4654         else
4655           {
4656             operands[2] = gen_reg_rtx (SImode);
4657             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4658           }
4659       }
4661     operands[3] = adjust_address (op0, QImode, 1);
4662     operands[0] = adjust_address (operands[0], QImode, 0);
4663     operands[2] = gen_lowpart (QImode, operands[2]);
4664     operands[1] = gen_lowpart (QImode, operands[1]);
4665   }"
4668 (define_expand "storehi_single_op"
4669   [(set (match_operand:HI 0 "memory_operand" "")
4670         (match_operand:HI 1 "general_operand" ""))]
4671   "TARGET_ARM && arm_arch4"
4672   "
4673   if (!s_register_operand (operands[1], HImode))
4674     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4675   "
4678 (define_expand "movhi"
4679   [(set (match_operand:HI 0 "general_operand" "")
4680         (match_operand:HI 1 "general_operand" ""))]
4681   "TARGET_EITHER"
4682   "
4683   if (TARGET_ARM)
4684     {
4685       if (!no_new_pseudos)
4686         {
4687           if (GET_CODE (operands[0]) == MEM)
4688             {
4689               if (arm_arch4)
4690                 {
4691                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4692                   DONE;
4693                 }
4694               if (GET_CODE (operands[1]) == CONST_INT)
4695                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4696               else
4697                 {
4698                   if (GET_CODE (operands[1]) == MEM)
4699                     operands[1] = force_reg (HImode, operands[1]);
4700                   if (BYTES_BIG_ENDIAN)
4701                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4702                   else
4703                    emit_insn (gen_storehi (operands[1], operands[0]));
4704                 }
4705               DONE;
4706             }
4707           /* Sign extend a constant, and keep it in an SImode reg.  */
4708           else if (GET_CODE (operands[1]) == CONST_INT)
4709             {
4710               rtx reg = gen_reg_rtx (SImode);
4711               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4713               /* If the constant is already valid, leave it alone.  */
4714               if (!const_ok_for_arm (val))
4715                 {
4716                   /* If setting all the top bits will make the constant 
4717                      loadable in a single instruction, then set them.  
4718                      Otherwise, sign extend the number.  */
4720                   if (const_ok_for_arm (~(val | ~0xffff)))
4721                     val |= ~0xffff;
4722                   else if (val & 0x8000)
4723                     val |= ~0xffff;
4724                 }
4726               emit_insn (gen_movsi (reg, GEN_INT (val)));
4727               operands[1] = gen_lowpart (HImode, reg);
4728             }
4729           else if (arm_arch4 && optimize && !no_new_pseudos
4730                    && GET_CODE (operands[1]) == MEM)
4731             {
4732               rtx reg = gen_reg_rtx (SImode);
4734               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4735               operands[1] = gen_lowpart (HImode, reg);
4736             }
4737           else if (!arm_arch4)
4738             {
4739               if (GET_CODE (operands[1]) == MEM)
4740                 {
4741                   rtx base;
4742                   rtx offset = const0_rtx;
4743                   rtx reg = gen_reg_rtx (SImode);
4745                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4746                        || (GET_CODE (base) == PLUS
4747                            && (GET_CODE (offset = XEXP (base, 1))
4748                                == CONST_INT)
4749                            && ((INTVAL(offset) & 1) != 1)
4750                            && GET_CODE (base = XEXP (base, 0)) == REG))
4751                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4752                     {
4753                       HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4754                       rtx new;
4756                       new = gen_rtx_MEM (SImode,
4757                                          plus_constant (base, new_offset));
4758                       MEM_COPY_ATTRIBUTES (new, operands[1]);
4759                       emit_insn (gen_movsi (reg, new));
4760                       if (((INTVAL (offset) & 2) != 0)
4761                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4762                         {
4763                           rtx reg2 = gen_reg_rtx (SImode);
4765                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4766                           reg = reg2;
4767                         }
4768                     }
4769                   else
4770                     emit_insn (gen_movhi_bytes (reg, operands[1]));
4772                   operands[1] = gen_lowpart (HImode, reg);
4773                }
4774            }
4775         }
4776       /* Handle loading a large integer during reload.  */
4777       else if (GET_CODE (operands[1]) == CONST_INT
4778                && !const_ok_for_arm (INTVAL (operands[1]))
4779                && !const_ok_for_arm (~INTVAL (operands[1])))
4780         {
4781           /* Writing a constant to memory needs a scratch, which should
4782              be handled with SECONDARY_RELOADs.  */
4783           gcc_assert (GET_CODE (operands[0]) == REG);
4785           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4786           emit_insn (gen_movsi (operands[0], operands[1]));
4787           DONE;
4788        }
4789     }
4790   else /* TARGET_THUMB */
4791     {
4792       if (!no_new_pseudos)
4793         {
4794           if (GET_CODE (operands[0]) != REG)
4795             operands[1] = force_reg (HImode, operands[1]);
4797           /* ??? We shouldn't really get invalid addresses here, but this can
4798              happen if we are passed a SP (never OK for HImode/QImode) or 
4799              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4800              HImode/QImode) relative address.  */
4801           /* ??? This should perhaps be fixed elsewhere, for instance, in
4802              fixup_stack_1, by checking for other kinds of invalid addresses,
4803              e.g. a bare reference to a virtual register.  This may confuse the
4804              alpha though, which must handle this case differently.  */
4805           if (GET_CODE (operands[0]) == MEM
4806               && !memory_address_p (GET_MODE (operands[0]),
4807                                     XEXP (operands[0], 0)))
4808             operands[0]
4809               = replace_equiv_address (operands[0],
4810                                        copy_to_reg (XEXP (operands[0], 0)));
4811    
4812           if (GET_CODE (operands[1]) == MEM
4813               && !memory_address_p (GET_MODE (operands[1]),
4814                                     XEXP (operands[1], 0)))
4815             operands[1]
4816               = replace_equiv_address (operands[1],
4817                                        copy_to_reg (XEXP (operands[1], 0)));
4818         }
4819       /* Handle loading a large integer during reload.  */
4820       else if (GET_CODE (operands[1]) == CONST_INT
4821                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4822         {
4823           /* Writing a constant to memory needs a scratch, which should
4824              be handled with SECONDARY_RELOADs.  */
4825           gcc_assert (GET_CODE (operands[0]) == REG);
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: gcc_unreachable ();
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   gcc_unreachable ();"
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           gcc_assert (GET_CODE (operands[0]) == REG);
5057           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5058           emit_insn (gen_movsi (operands[0], operands[1]));
5059           DONE;
5060        }
5061     }
5062   "
5066 (define_insn "*arm_movqi_insn"
5067   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5068         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5069   "TARGET_ARM
5070    && (   register_operand (operands[0], QImode)
5071        || register_operand (operands[1], QImode))"
5072   "@
5073    mov%?\\t%0, %1
5074    mvn%?\\t%0, #%B1
5075    ldr%?b\\t%0, %1
5076    str%?b\\t%1, %0"
5077   [(set_attr "type" "*,*,load1,store1")
5078    (set_attr "predicable" "yes")]
5081 (define_insn "*thumb_movqi_insn"
5082   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5083         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
5084   "TARGET_THUMB
5085    && (   register_operand (operands[0], QImode)
5086        || register_operand (operands[1], QImode))"
5087   "@
5088    add\\t%0, %1, #0
5089    ldrb\\t%0, %1
5090    strb\\t%1, %0
5091    mov\\t%0, %1
5092    mov\\t%0, %1
5093    mov\\t%0, %1"
5094   [(set_attr "length" "2")
5095    (set_attr "type" "*,load1,store1,*,*,*")
5096    (set_attr "pool_range" "*,32,*,*,*,*")]
5099 (define_expand "movsf"
5100   [(set (match_operand:SF 0 "general_operand" "")
5101         (match_operand:SF 1 "general_operand" ""))]
5102   "TARGET_EITHER"
5103   "
5104   if (TARGET_ARM)
5105     {
5106       if (GET_CODE (operands[0]) == MEM)
5107         operands[1] = force_reg (SFmode, operands[1]);
5108     }
5109   else /* TARGET_THUMB */
5110     {
5111       if (!no_new_pseudos)
5112         {
5113            if (GET_CODE (operands[0]) != REG)
5114              operands[1] = force_reg (SFmode, operands[1]);
5115         }
5116     }
5117   "
5120 (define_split
5121   [(set (match_operand:SF 0 "nonimmediate_operand" "")
5122         (match_operand:SF 1 "immediate_operand" ""))]
5123   "TARGET_ARM
5124    && !(TARGET_HARD_FLOAT && TARGET_FPA)
5125    && reload_completed
5126    && GET_CODE (operands[1]) == CONST_DOUBLE"
5127   [(set (match_dup 2) (match_dup 3))]
5128   "
5129   operands[2] = gen_lowpart (SImode, operands[0]);
5130   operands[3] = gen_lowpart (SImode, operands[1]);
5131   if (operands[2] == 0 || operands[3] == 0)
5132     FAIL;
5133   "
5136 (define_insn "*arm_movsf_soft_insn"
5137   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5138         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
5139   "TARGET_ARM
5140    && TARGET_SOFT_FLOAT
5141    && (GET_CODE (operands[0]) != MEM
5142        || register_operand (operands[1], SFmode))"
5143   "@
5144    mov%?\\t%0, %1
5145    ldr%?\\t%0, %1\\t%@ float
5146    str%?\\t%1, %0\\t%@ float"
5147   [(set_attr "length" "4,4,4")
5148    (set_attr "predicable" "yes")
5149    (set_attr "type" "*,load1,store1")
5150    (set_attr "pool_range" "*,4096,*")
5151    (set_attr "neg_pool_range" "*,4084,*")]
5154 ;;; ??? This should have alternatives for constants.
5155 (define_insn "*thumb_movsf_insn"
5156   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5157         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5158   "TARGET_THUMB
5159    && (   register_operand (operands[0], SFmode) 
5160        || register_operand (operands[1], SFmode))"
5161   "@
5162    add\\t%0, %1, #0
5163    ldmia\\t%1, {%0}
5164    stmia\\t%0, {%1}
5165    ldr\\t%0, %1
5166    str\\t%1, %0
5167    mov\\t%0, %1
5168    mov\\t%0, %1"
5169   [(set_attr "length" "2")
5170    (set_attr "type" "*,load1,store1,load1,store1,*,*")
5171    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5174 (define_expand "movdf"
5175   [(set (match_operand:DF 0 "general_operand" "")
5176         (match_operand:DF 1 "general_operand" ""))]
5177   "TARGET_EITHER"
5178   "
5179   if (TARGET_ARM)
5180     {
5181       if (GET_CODE (operands[0]) == MEM)
5182         operands[1] = force_reg (DFmode, operands[1]);
5183     }
5184   else /* TARGET_THUMB */
5185     {
5186       if (!no_new_pseudos)
5187         {
5188           if (GET_CODE (operands[0]) != REG)
5189             operands[1] = force_reg (DFmode, operands[1]);
5190         }
5191     }
5192   "
5195 ;; Reloading a df mode value stored in integer regs to memory can require a
5196 ;; scratch reg.
5197 (define_expand "reload_outdf"
5198   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5199    (match_operand:DF 1 "s_register_operand" "r")
5200    (match_operand:SI 2 "s_register_operand" "=&r")]
5201   "TARGET_ARM"
5202   "
5203   {
5204     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5206     if (code == REG)
5207       operands[2] = XEXP (operands[0], 0);
5208     else if (code == POST_INC || code == PRE_DEC)
5209       {
5210         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5211         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5212         emit_insn (gen_movdi (operands[0], operands[1]));
5213         DONE;
5214       }
5215     else if (code == PRE_INC)
5216       {
5217         rtx reg = XEXP (XEXP (operands[0], 0), 0);
5219         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5220         operands[2] = reg;
5221       }
5222     else if (code == POST_DEC)
5223       operands[2] = XEXP (XEXP (operands[0], 0), 0);
5224     else
5225       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5226                              XEXP (XEXP (operands[0], 0), 1)));
5228     emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5229                             operands[1]));
5231     if (code == POST_DEC)
5232       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5234     DONE;
5235   }"
5238 (define_insn "*movdf_soft_insn"
5239   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5240         (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
5241   "TARGET_ARM && TARGET_SOFT_FLOAT
5242   "
5243   "*
5244   switch (which_alternative)
5245     {
5246     case 0:
5247     case 1:
5248     case 2:
5249       return \"#\";
5250     default:
5251       return output_move_double (operands);
5252     }
5253   "
5254   [(set_attr "length" "8,12,16,8,8")
5255    (set_attr "type" "*,*,*,load2,store2")
5256    (set_attr "pool_range" "1020")
5257    (set_attr "neg_pool_range" "1008")]
5260 ;;; ??? This should have alternatives for constants.
5261 ;;; ??? This was originally identical to the movdi_insn pattern.
5262 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5263 ;;; thumb_reorg with a memory reference.
5264 (define_insn "*thumb_movdf_insn"
5265   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5266         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5267   "TARGET_THUMB
5268    && (   register_operand (operands[0], DFmode)
5269        || register_operand (operands[1], DFmode))"
5270   "*
5271   switch (which_alternative)
5272     {
5273     default:
5274     case 0:
5275       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5276         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5277       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5278     case 1:
5279       return \"ldmia\\t%1, {%0, %H0}\";
5280     case 2:
5281       return \"stmia\\t%0, {%1, %H1}\";
5282     case 3:
5283       return thumb_load_double_from_address (operands);
5284     case 4:
5285       operands[2] = gen_rtx_MEM (SImode,
5286                                  plus_constant (XEXP (operands[0], 0), 4));
5287       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5288       return \"\";
5289     case 5:
5290       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5291         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5292       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5293     }
5294   "
5295   [(set_attr "length" "4,2,2,6,4,4")
5296    (set_attr "type" "*,load2,store2,load2,store2,*")
5297    (set_attr "pool_range" "*,*,*,1020,*,*")]
5300 (define_expand "movxf"
5301   [(set (match_operand:XF 0 "general_operand" "")
5302         (match_operand:XF 1 "general_operand" ""))]
5303   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
5304   "
5305   if (GET_CODE (operands[0]) == MEM)
5306     operands[1] = force_reg (XFmode, operands[1]);
5307   "
5310 ;; Vector Moves
5311 (define_expand "movv2si"
5312   [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5313         (match_operand:V2SI 1 "general_operand" ""))]
5314   "TARGET_REALLY_IWMMXT"
5318 (define_expand "movv4hi"
5319   [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5320         (match_operand:V4HI 1 "general_operand" ""))]
5321   "TARGET_REALLY_IWMMXT"
5325 (define_expand "movv8qi"
5326   [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5327         (match_operand:V8QI 1 "general_operand" ""))]
5328   "TARGET_REALLY_IWMMXT"
5333 ;; load- and store-multiple insns
5334 ;; The arm can load/store any set of registers, provided that they are in
5335 ;; ascending order; but that is beyond GCC so stick with what it knows.
5337 (define_expand "load_multiple"
5338   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5339                           (match_operand:SI 1 "" ""))
5340                      (use (match_operand:SI 2 "" ""))])]
5341   "TARGET_ARM"
5343   HOST_WIDE_INT offset = 0;
5345   /* Support only fixed point registers.  */
5346   if (GET_CODE (operands[2]) != CONST_INT
5347       || INTVAL (operands[2]) > 14
5348       || INTVAL (operands[2]) < 2
5349       || GET_CODE (operands[1]) != MEM
5350       || GET_CODE (operands[0]) != REG
5351       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5352       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5353     FAIL;
5355   operands[3]
5356     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5357                              force_reg (SImode, XEXP (operands[1], 0)),
5358                              TRUE, FALSE, operands[1], &offset);
5361 ;; Load multiple with write-back
5363 (define_insn "*ldmsi_postinc4"
5364   [(match_parallel 0 "load_multiple_operation"
5365     [(set (match_operand:SI 1 "s_register_operand" "=r")
5366           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5367                    (const_int 16)))
5368      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5369           (mem:SI (match_dup 2)))
5370      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5371           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5372      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5373           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5374      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5375           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5376   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5377   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5378   [(set_attr "type" "load4")
5379    (set_attr "predicable" "yes")]
5382 (define_insn "*ldmsi_postinc4_thumb"
5383   [(match_parallel 0 "load_multiple_operation"
5384     [(set (match_operand:SI 1 "s_register_operand" "=l")
5385           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5386                    (const_int 16)))
5387      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5388           (mem:SI (match_dup 2)))
5389      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5390           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5391      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5392           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5393      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5394           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5395   "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5396   "ldmia\\t%1!, {%3, %4, %5, %6}"
5397   [(set_attr "type" "load4")]
5400 (define_insn "*ldmsi_postinc3"
5401   [(match_parallel 0 "load_multiple_operation"
5402     [(set (match_operand:SI 1 "s_register_operand" "=r")
5403           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5404                    (const_int 12)))
5405      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5406           (mem:SI (match_dup 2)))
5407      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5408           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5409      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5410           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5411   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5412   "ldm%?ia\\t%1!, {%3, %4, %5}"
5413   [(set_attr "type" "load3")
5414    (set_attr "predicable" "yes")]
5417 (define_insn "*ldmsi_postinc2"
5418   [(match_parallel 0 "load_multiple_operation"
5419     [(set (match_operand:SI 1 "s_register_operand" "=r")
5420           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5421                    (const_int 8)))
5422      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5423           (mem:SI (match_dup 2)))
5424      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5425           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5426   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5427   "ldm%?ia\\t%1!, {%3, %4}"
5428   [(set_attr "type" "load2")
5429    (set_attr "predicable" "yes")]
5432 ;; Ordinary load multiple
5434 (define_insn "*ldmsi4"
5435   [(match_parallel 0 "load_multiple_operation"
5436     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5437           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5438      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5439           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5440      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5441           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5442      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5443           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5444   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5445   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5446   [(set_attr "type" "load4")
5447    (set_attr "predicable" "yes")]
5450 (define_insn "*ldmsi3"
5451   [(match_parallel 0 "load_multiple_operation"
5452     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5453           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5454      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5455           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5456      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5457           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5458   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5459   "ldm%?ia\\t%1, {%2, %3, %4}"
5460   [(set_attr "type" "load3")
5461    (set_attr "predicable" "yes")]
5464 (define_insn "*ldmsi2"
5465   [(match_parallel 0 "load_multiple_operation"
5466     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5467           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5468      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5469           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5470   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5471   "ldm%?ia\\t%1, {%2, %3}"
5472   [(set_attr "type" "load2")
5473    (set_attr "predicable" "yes")]
5476 (define_expand "store_multiple"
5477   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5478                           (match_operand:SI 1 "" ""))
5479                      (use (match_operand:SI 2 "" ""))])]
5480   "TARGET_ARM"
5482   HOST_WIDE_INT offset = 0;
5484   /* Support only fixed point registers.  */
5485   if (GET_CODE (operands[2]) != CONST_INT
5486       || INTVAL (operands[2]) > 14
5487       || INTVAL (operands[2]) < 2
5488       || GET_CODE (operands[1]) != REG
5489       || GET_CODE (operands[0]) != MEM
5490       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5491       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5492     FAIL;
5494   operands[3]
5495     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5496                               force_reg (SImode, XEXP (operands[0], 0)),
5497                               TRUE, FALSE, operands[0], &offset);
5500 ;; Store multiple with write-back
5502 (define_insn "*stmsi_postinc4"
5503   [(match_parallel 0 "store_multiple_operation"
5504     [(set (match_operand:SI 1 "s_register_operand" "=r")
5505           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5506                    (const_int 16)))
5507      (set (mem:SI (match_dup 2))
5508           (match_operand:SI 3 "arm_hard_register_operand" ""))
5509      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5510           (match_operand:SI 4 "arm_hard_register_operand" ""))
5511      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5512           (match_operand:SI 5 "arm_hard_register_operand" ""))
5513      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5514           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5515   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5516   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5517   [(set_attr "predicable" "yes")
5518    (set_attr "type" "store4")]
5521 (define_insn "*stmsi_postinc4_thumb"
5522   [(match_parallel 0 "store_multiple_operation"
5523     [(set (match_operand:SI 1 "s_register_operand" "=l")
5524           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5525                    (const_int 16)))
5526      (set (mem:SI (match_dup 2))
5527           (match_operand:SI 3 "arm_hard_register_operand" ""))
5528      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5529           (match_operand:SI 4 "arm_hard_register_operand" ""))
5530      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5531           (match_operand:SI 5 "arm_hard_register_operand" ""))
5532      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5533           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5534   "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5535   "stmia\\t%1!, {%3, %4, %5, %6}"
5536   [(set_attr "type" "store4")]
5539 (define_insn "*stmsi_postinc3"
5540   [(match_parallel 0 "store_multiple_operation"
5541     [(set (match_operand:SI 1 "s_register_operand" "=r")
5542           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5543                    (const_int 12)))
5544      (set (mem:SI (match_dup 2))
5545           (match_operand:SI 3 "arm_hard_register_operand" ""))
5546      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5547           (match_operand:SI 4 "arm_hard_register_operand" ""))
5548      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5549           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5550   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5551   "stm%?ia\\t%1!, {%3, %4, %5}"
5552   [(set_attr "predicable" "yes")
5553    (set_attr "type" "store3")]
5556 (define_insn "*stmsi_postinc2"
5557   [(match_parallel 0 "store_multiple_operation"
5558     [(set (match_operand:SI 1 "s_register_operand" "=r")
5559           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5560                    (const_int 8)))
5561      (set (mem:SI (match_dup 2))
5562           (match_operand:SI 3 "arm_hard_register_operand" ""))
5563      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5564           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5565   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5566   "stm%?ia\\t%1!, {%3, %4}"
5567   [(set_attr "predicable" "yes")
5568    (set_attr "type" "store2")]
5571 ;; Ordinary store multiple
5573 (define_insn "*stmsi4"
5574   [(match_parallel 0 "store_multiple_operation"
5575     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5576           (match_operand:SI 2 "arm_hard_register_operand" ""))
5577      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5578           (match_operand:SI 3 "arm_hard_register_operand" ""))
5579      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5580           (match_operand:SI 4 "arm_hard_register_operand" ""))
5581      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5582           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5583   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5584   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5585   [(set_attr "predicable" "yes")
5586    (set_attr "type" "store4")]
5589 (define_insn "*stmsi3"
5590   [(match_parallel 0 "store_multiple_operation"
5591     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5592           (match_operand:SI 2 "arm_hard_register_operand" ""))
5593      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5594           (match_operand:SI 3 "arm_hard_register_operand" ""))
5595      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5596           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5597   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5598   "stm%?ia\\t%1, {%2, %3, %4}"
5599   [(set_attr "predicable" "yes")
5600    (set_attr "type" "store3")]
5603 (define_insn "*stmsi2"
5604   [(match_parallel 0 "store_multiple_operation"
5605     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5606           (match_operand:SI 2 "arm_hard_register_operand" ""))
5607      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5608           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5609   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5610   "stm%?ia\\t%1, {%2, %3}"
5611   [(set_attr "predicable" "yes")
5612    (set_attr "type" "store2")]
5615 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5616 ;; We could let this apply for blocks of less than this, but it clobbers so
5617 ;; many registers that there is then probably a better way.
5619 (define_expand "movmemqi"
5620   [(match_operand:BLK 0 "general_operand" "")
5621    (match_operand:BLK 1 "general_operand" "")
5622    (match_operand:SI 2 "const_int_operand" "")
5623    (match_operand:SI 3 "const_int_operand" "")]
5624   "TARGET_EITHER"
5625   "
5626   if (TARGET_ARM)
5627     {
5628       if (arm_gen_movmemqi (operands))
5629         DONE;
5630       FAIL;
5631     }
5632   else /* TARGET_THUMB */
5633     {
5634       if (   INTVAL (operands[3]) != 4
5635           || INTVAL (operands[2]) > 48)
5636         FAIL;
5638       thumb_expand_movmemqi (operands);
5639       DONE;
5640     }
5641   "
5644 ;; Thumb block-move insns
5646 (define_insn "movmem12b"
5647   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5648         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5649    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5650         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5651    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5652         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5653    (set (match_operand:SI 0 "register_operand" "=l")
5654         (plus:SI (match_dup 2) (const_int 12)))
5655    (set (match_operand:SI 1 "register_operand" "=l")
5656         (plus:SI (match_dup 3) (const_int 12)))
5657    (clobber (match_scratch:SI 4 "=&l"))
5658    (clobber (match_scratch:SI 5 "=&l"))
5659    (clobber (match_scratch:SI 6 "=&l"))]
5660   "TARGET_THUMB"
5661   "* return thumb_output_move_mem_multiple (3, operands);"
5662   [(set_attr "length" "4")
5663    ; This isn't entirely accurate...  It loads as well, but in terms of
5664    ; scheduling the following insn it is better to consider it as a store
5665    (set_attr "type" "store3")]
5668 (define_insn "movmem8b"
5669   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5670         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5671    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5672         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5673    (set (match_operand:SI 0 "register_operand" "=l")
5674         (plus:SI (match_dup 2) (const_int 8)))
5675    (set (match_operand:SI 1 "register_operand" "=l")
5676         (plus:SI (match_dup 3) (const_int 8)))
5677    (clobber (match_scratch:SI 4 "=&l"))
5678    (clobber (match_scratch:SI 5 "=&l"))]
5679   "TARGET_THUMB"
5680   "* return thumb_output_move_mem_multiple (2, operands);"
5681   [(set_attr "length" "4")
5682    ; This isn't entirely accurate...  It loads as well, but in terms of
5683    ; scheduling the following insn it is better to consider it as a store
5684    (set_attr "type" "store2")]
5689 ;; Compare & branch insns
5690 ;; The range calculations are based as follows:
5691 ;; For forward branches, the address calculation returns the address of
5692 ;; the next instruction.  This is 2 beyond the branch instruction.
5693 ;; For backward branches, the address calculation returns the address of
5694 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5695 ;; instruction for the shortest sequence, and 4 before the branch instruction
5696 ;; if we have to jump around an unconditional branch.
5697 ;; To the basic branch range the PC offset must be added (this is +4).
5698 ;; So for forward branches we have 
5699 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5700 ;; And for backward branches we have 
5701 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5703 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5704 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5706 (define_expand "cbranchsi4"
5707   [(set (pc) (if_then_else
5708               (match_operator 0 "arm_comparison_operator"
5709                [(match_operand:SI 1 "s_register_operand" "")
5710                 (match_operand:SI 2 "nonmemory_operand" "")])
5711               (label_ref (match_operand 3 "" ""))
5712               (pc)))]
5713   "TARGET_THUMB"
5714   "
5715   if (thumb_cmpneg_operand (operands[2], SImode))
5716     {
5717       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5718                                               operands[3], operands[0]));
5719       DONE;
5720     }
5721   if (!thumb_cmp_operand (operands[2], SImode))
5722     operands[2] = force_reg (SImode, operands[2]);
5723   ")
5725 (define_insn "*cbranchsi4_insn"
5726   [(set (pc) (if_then_else
5727               (match_operator 0 "arm_comparison_operator"
5728                [(match_operand:SI 1 "s_register_operand" "l,*h")
5729                 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5730               (label_ref (match_operand 3 "" ""))
5731               (pc)))]
5732   "TARGET_THUMB"
5733   "*
5734   output_asm_insn (\"cmp\\t%1, %2\", operands);
5736   switch (get_attr_length (insn))
5737     {
5738     case 4:  return \"b%d0\\t%l3\";
5739     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5740     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5741     }
5742   "
5743   [(set (attr "far_jump")
5744         (if_then_else
5745             (eq_attr "length" "8")
5746             (const_string "yes")
5747             (const_string "no")))
5748    (set (attr "length") 
5749         (if_then_else
5750             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5751                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5752             (const_int 4)
5753             (if_then_else
5754                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5755                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5756                 (const_int 6)
5757                 (const_int 8))))]
5760 (define_insn "cbranchsi4_scratch"
5761   [(set (pc) (if_then_else
5762               (match_operator 4 "arm_comparison_operator"
5763                [(match_operand:SI 1 "s_register_operand" "l,0")
5764                 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5765               (label_ref (match_operand 3 "" ""))
5766               (pc)))
5767    (clobber (match_scratch:SI 0 "=l,l"))]
5768   "TARGET_THUMB"
5769   "*
5770   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5772   switch (get_attr_length (insn))
5773     {
5774     case 4:  return \"b%d4\\t%l3\";
5775     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5776     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5777     }
5778   "
5779   [(set (attr "far_jump")
5780         (if_then_else
5781             (eq_attr "length" "8")
5782             (const_string "yes")
5783             (const_string "no")))
5784    (set (attr "length") 
5785         (if_then_else
5786             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5787                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5788             (const_int 4)
5789             (if_then_else
5790                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5791                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5792                 (const_int 6)
5793                 (const_int 8))))]
5795 (define_insn "*movsi_cbranchsi4"
5796   [(set (pc)
5797         (if_then_else
5798          (match_operator 3 "arm_comparison_operator"
5799           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5800            (const_int 0)])
5801          (label_ref (match_operand 2 "" ""))
5802          (pc)))
5803    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5804         (match_dup 1))]
5805   "TARGET_THUMB"
5806   "*{
5807   if (which_alternative == 0)
5808     output_asm_insn (\"cmp\t%0, #0\", operands);
5809   else if (which_alternative == 1)
5810     output_asm_insn (\"sub\t%0, %1, #0\", operands);
5811   else
5812     {
5813       output_asm_insn (\"cmp\t%1, #0\", operands);
5814       if (which_alternative == 2)
5815         output_asm_insn (\"mov\t%0, %1\", operands);
5816       else
5817         output_asm_insn (\"str\t%1, %0\", operands);
5818     }
5819   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5820     {
5821     case 4:  return \"b%d3\\t%l2\";
5822     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5823     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5824     }
5825   }"
5826   [(set (attr "far_jump")
5827         (if_then_else
5828             (ior (and (gt (symbol_ref ("which_alternative"))
5829                           (const_int 1))
5830                       (eq_attr "length" "8"))
5831                  (eq_attr "length" "10"))
5832             (const_string "yes")
5833             (const_string "no")))
5834    (set (attr "length")
5835      (if_then_else
5836        (le (symbol_ref ("which_alternative"))
5837                        (const_int 1))
5838        (if_then_else
5839          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5840               (le (minus (match_dup 2) (pc)) (const_int 256)))
5841          (const_int 4)
5842          (if_then_else
5843            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5844                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5845            (const_int 6)
5846            (const_int 8)))
5847        (if_then_else
5848          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5849               (le (minus (match_dup 2) (pc)) (const_int 256)))
5850          (const_int 6)
5851          (if_then_else
5852            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5853                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5854            (const_int 8)
5855            (const_int 10)))))]
5858 (define_insn "*negated_cbranchsi4"
5859   [(set (pc)
5860         (if_then_else
5861          (match_operator 0 "equality_operator"
5862           [(match_operand:SI 1 "s_register_operand" "l")
5863            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5864          (label_ref (match_operand 3 "" ""))
5865          (pc)))]
5866   "TARGET_THUMB"
5867   "*
5868   output_asm_insn (\"cmn\\t%1, %2\", operands);
5869   switch (get_attr_length (insn))
5870     {
5871     case 4:  return \"b%d0\\t%l3\";
5872     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5873     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5874     }
5875   "
5876   [(set (attr "far_jump")
5877         (if_then_else
5878             (eq_attr "length" "8")
5879             (const_string "yes")
5880             (const_string "no")))
5881    (set (attr "length") 
5882         (if_then_else
5883             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5884                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5885             (const_int 4)
5886             (if_then_else
5887                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5888                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5889                 (const_int 6)
5890                 (const_int 8))))]
5893 (define_insn "*tbit_cbranch"
5894   [(set (pc)
5895         (if_then_else
5896          (match_operator 0 "equality_operator"
5897           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5898                             (const_int 1)
5899                             (match_operand:SI 2 "const_int_operand" "i"))
5900            (const_int 0)])
5901          (label_ref (match_operand 3 "" ""))
5902          (pc)))
5903    (clobber (match_scratch:SI 4 "=l"))]
5904   "TARGET_THUMB"
5905   "*
5906   {
5907   rtx op[3];
5908   op[0] = operands[4];
5909   op[1] = operands[1];
5910   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5912   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5913   switch (get_attr_length (insn))
5914     {
5915     case 4:  return \"b%d0\\t%l3\";
5916     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5917     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5918     }
5919   }"
5920   [(set (attr "far_jump")
5921         (if_then_else
5922             (eq_attr "length" "8")
5923             (const_string "yes")
5924             (const_string "no")))
5925    (set (attr "length") 
5926         (if_then_else
5927             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5928                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5929             (const_int 4)
5930             (if_then_else
5931                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5932                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5933                 (const_int 6)
5934                 (const_int 8))))]
5936   
5937 (define_insn "*tstsi3_cbranch"
5938   [(set (pc)
5939         (if_then_else
5940          (match_operator 3 "equality_operator"
5941           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5942                    (match_operand:SI 1 "s_register_operand" "l"))
5943            (const_int 0)])
5944          (label_ref (match_operand 2 "" ""))
5945          (pc)))]
5946   "TARGET_THUMB"
5947   "*
5948   {
5949   output_asm_insn (\"tst\\t%0, %1\", operands);
5950   switch (get_attr_length (insn))
5951     {
5952     case 4:  return \"b%d3\\t%l2\";
5953     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5954     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5955     }
5956   }"
5957   [(set (attr "far_jump")
5958         (if_then_else
5959             (eq_attr "length" "8")
5960             (const_string "yes")
5961             (const_string "no")))
5962    (set (attr "length") 
5963         (if_then_else
5964             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5965                  (le (minus (match_dup 2) (pc)) (const_int 256)))
5966             (const_int 4)
5967             (if_then_else
5968                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5969                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
5970                 (const_int 6)
5971                 (const_int 8))))]
5973   
5974 (define_insn "*andsi3_cbranch"
5975   [(set (pc)
5976         (if_then_else
5977          (match_operator 5 "equality_operator"
5978           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5979                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5980            (const_int 0)])
5981          (label_ref (match_operand 4 "" ""))
5982          (pc)))
5983    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5984         (and:SI (match_dup 2) (match_dup 3)))
5985    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5986   "TARGET_THUMB"
5987   "*
5988   {
5989   if (which_alternative == 0)
5990     output_asm_insn (\"and\\t%0, %3\", operands);
5991   else if (which_alternative == 1)
5992     {
5993       output_asm_insn (\"and\\t%1, %3\", operands);
5994       output_asm_insn (\"mov\\t%0, %1\", operands);
5995     }
5996   else
5997     {
5998       output_asm_insn (\"and\\t%1, %3\", operands);
5999       output_asm_insn (\"str\\t%1, %0\", operands);
6000     }
6002   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6003     {
6004     case 4:  return \"b%d5\\t%l4\";
6005     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6006     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6007     }
6008   }"
6009   [(set (attr "far_jump")
6010         (if_then_else
6011             (ior (and (eq (symbol_ref ("which_alternative"))
6012                           (const_int 0))
6013                       (eq_attr "length" "8"))
6014                  (eq_attr "length" "10"))
6015             (const_string "yes")
6016             (const_string "no")))
6017    (set (attr "length")
6018      (if_then_else
6019        (eq (symbol_ref ("which_alternative"))
6020                        (const_int 0))
6021        (if_then_else
6022          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6023               (le (minus (match_dup 4) (pc)) (const_int 256)))
6024          (const_int 4)
6025          (if_then_else
6026            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6027                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6028            (const_int 6)
6029            (const_int 8)))
6030        (if_then_else
6031          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6032               (le (minus (match_dup 4) (pc)) (const_int 256)))
6033          (const_int 6)
6034          (if_then_else
6035            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6036                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6037            (const_int 8)
6038            (const_int 10)))))]
6041 (define_insn "*orrsi3_cbranch_scratch"
6042   [(set (pc)
6043         (if_then_else
6044          (match_operator 4 "equality_operator"
6045           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6046                    (match_operand:SI 2 "s_register_operand" "l"))
6047            (const_int 0)])
6048          (label_ref (match_operand 3 "" ""))
6049          (pc)))
6050    (clobber (match_scratch:SI 0 "=l"))]
6051   "TARGET_THUMB"
6052   "*
6053   {
6054   output_asm_insn (\"orr\\t%0, %2\", operands);
6055   switch (get_attr_length (insn))
6056     {
6057     case 4:  return \"b%d4\\t%l3\";
6058     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6059     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6060     }
6061   }"
6062   [(set (attr "far_jump")
6063         (if_then_else
6064             (eq_attr "length" "8")
6065             (const_string "yes")
6066             (const_string "no")))
6067    (set (attr "length") 
6068         (if_then_else
6069             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6070                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6071             (const_int 4)
6072             (if_then_else
6073                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6074                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6075                 (const_int 6)
6076                 (const_int 8))))]
6078   
6079 (define_insn "*orrsi3_cbranch"
6080   [(set (pc)
6081         (if_then_else
6082          (match_operator 5 "equality_operator"
6083           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6084                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6085            (const_int 0)])
6086          (label_ref (match_operand 4 "" ""))
6087          (pc)))
6088    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6089         (ior:SI (match_dup 2) (match_dup 3)))
6090    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6091   "TARGET_THUMB"
6092   "*
6093   {
6094   if (which_alternative == 0)
6095     output_asm_insn (\"orr\\t%0, %3\", operands);
6096   else if (which_alternative == 1)
6097     {
6098       output_asm_insn (\"orr\\t%1, %3\", operands);
6099       output_asm_insn (\"mov\\t%0, %1\", operands);
6100     }
6101   else
6102     {
6103       output_asm_insn (\"orr\\t%1, %3\", operands);
6104       output_asm_insn (\"str\\t%1, %0\", operands);
6105     }
6107   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6108     {
6109     case 4:  return \"b%d5\\t%l4\";
6110     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6111     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6112     }
6113   }"
6114   [(set (attr "far_jump")
6115         (if_then_else
6116             (ior (and (eq (symbol_ref ("which_alternative"))
6117                           (const_int 0))
6118                       (eq_attr "length" "8"))
6119                  (eq_attr "length" "10"))
6120             (const_string "yes")
6121             (const_string "no")))
6122    (set (attr "length")
6123      (if_then_else
6124        (eq (symbol_ref ("which_alternative"))
6125                        (const_int 0))
6126        (if_then_else
6127          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6128               (le (minus (match_dup 4) (pc)) (const_int 256)))
6129          (const_int 4)
6130          (if_then_else
6131            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6132                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6133            (const_int 6)
6134            (const_int 8)))
6135        (if_then_else
6136          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6137               (le (minus (match_dup 4) (pc)) (const_int 256)))
6138          (const_int 6)
6139          (if_then_else
6140            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6141                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6142            (const_int 8)
6143            (const_int 10)))))]
6146 (define_insn "*xorsi3_cbranch_scratch"
6147   [(set (pc)
6148         (if_then_else
6149          (match_operator 4 "equality_operator"
6150           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6151                    (match_operand:SI 2 "s_register_operand" "l"))
6152            (const_int 0)])
6153          (label_ref (match_operand 3 "" ""))
6154          (pc)))
6155    (clobber (match_scratch:SI 0 "=l"))]
6156   "TARGET_THUMB"
6157   "*
6158   {
6159   output_asm_insn (\"eor\\t%0, %2\", operands);
6160   switch (get_attr_length (insn))
6161     {
6162     case 4:  return \"b%d4\\t%l3\";
6163     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6164     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6165     }
6166   }"
6167   [(set (attr "far_jump")
6168         (if_then_else
6169             (eq_attr "length" "8")
6170             (const_string "yes")
6171             (const_string "no")))
6172    (set (attr "length") 
6173         (if_then_else
6174             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6175                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6176             (const_int 4)
6177             (if_then_else
6178                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6179                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6180                 (const_int 6)
6181                 (const_int 8))))]
6183   
6184 (define_insn "*xorsi3_cbranch"
6185   [(set (pc)
6186         (if_then_else
6187          (match_operator 5 "equality_operator"
6188           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6189                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6190            (const_int 0)])
6191          (label_ref (match_operand 4 "" ""))
6192          (pc)))
6193    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6194         (xor:SI (match_dup 2) (match_dup 3)))
6195    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6196   "TARGET_THUMB"
6197   "*
6198   {
6199   if (which_alternative == 0)
6200     output_asm_insn (\"eor\\t%0, %3\", operands);
6201   else if (which_alternative == 1)
6202     {
6203       output_asm_insn (\"eor\\t%1, %3\", operands);
6204       output_asm_insn (\"mov\\t%0, %1\", operands);
6205     }
6206   else
6207     {
6208       output_asm_insn (\"eor\\t%1, %3\", operands);
6209       output_asm_insn (\"str\\t%1, %0\", operands);
6210     }
6212   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6213     {
6214     case 4:  return \"b%d5\\t%l4\";
6215     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6216     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6217     }
6218   }"
6219   [(set (attr "far_jump")
6220         (if_then_else
6221             (ior (and (eq (symbol_ref ("which_alternative"))
6222                           (const_int 0))
6223                       (eq_attr "length" "8"))
6224                  (eq_attr "length" "10"))
6225             (const_string "yes")
6226             (const_string "no")))
6227    (set (attr "length")
6228      (if_then_else
6229        (eq (symbol_ref ("which_alternative"))
6230                        (const_int 0))
6231        (if_then_else
6232          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6233               (le (minus (match_dup 4) (pc)) (const_int 256)))
6234          (const_int 4)
6235          (if_then_else
6236            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6237                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6238            (const_int 6)
6239            (const_int 8)))
6240        (if_then_else
6241          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6242               (le (minus (match_dup 4) (pc)) (const_int 256)))
6243          (const_int 6)
6244          (if_then_else
6245            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6246                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6247            (const_int 8)
6248            (const_int 10)))))]
6251 (define_insn "*bicsi3_cbranch_scratch"
6252   [(set (pc)
6253         (if_then_else
6254          (match_operator 4 "equality_operator"
6255           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6256                    (match_operand:SI 1 "s_register_operand" "0"))
6257            (const_int 0)])
6258          (label_ref (match_operand 3 "" ""))
6259          (pc)))
6260    (clobber (match_scratch:SI 0 "=l"))]
6261   "TARGET_THUMB"
6262   "*
6263   {
6264   output_asm_insn (\"bic\\t%0, %2\", operands);
6265   switch (get_attr_length (insn))
6266     {
6267     case 4:  return \"b%d4\\t%l3\";
6268     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6269     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6270     }
6271   }"
6272   [(set (attr "far_jump")
6273         (if_then_else
6274             (eq_attr "length" "8")
6275             (const_string "yes")
6276             (const_string "no")))
6277    (set (attr "length") 
6278         (if_then_else
6279             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6280                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6281             (const_int 4)
6282             (if_then_else
6283                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6284                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6285                 (const_int 6)
6286                 (const_int 8))))]
6288   
6289 (define_insn "*bicsi3_cbranch"
6290   [(set (pc)
6291         (if_then_else
6292          (match_operator 5 "equality_operator"
6293           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6294                    (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6295            (const_int 0)])
6296          (label_ref (match_operand 4 "" ""))
6297          (pc)))
6298    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6299         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6300    (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6301   "TARGET_THUMB"
6302   "*
6303   {
6304   if (which_alternative == 0)
6305     output_asm_insn (\"bic\\t%0, %3\", operands);
6306   else if (which_alternative <= 2)
6307     {
6308       output_asm_insn (\"bic\\t%1, %3\", operands);
6309       /* It's ok if OP0 is a lo-reg, even though the mov will set the
6310          conditions again, since we're only testing for equality.  */
6311       output_asm_insn (\"mov\\t%0, %1\", operands);
6312     }
6313   else
6314     {
6315       output_asm_insn (\"bic\\t%1, %3\", operands);
6316       output_asm_insn (\"str\\t%1, %0\", operands);
6317     }
6319   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6320     {
6321     case 4:  return \"b%d5\\t%l4\";
6322     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6323     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6324     }
6325   }"
6326   [(set (attr "far_jump")
6327         (if_then_else
6328             (ior (and (eq (symbol_ref ("which_alternative"))
6329                           (const_int 0))
6330                       (eq_attr "length" "8"))
6331                  (eq_attr "length" "10"))
6332             (const_string "yes")
6333             (const_string "no")))
6334    (set (attr "length")
6335      (if_then_else
6336        (eq (symbol_ref ("which_alternative"))
6337                        (const_int 0))
6338        (if_then_else
6339          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6340               (le (minus (match_dup 4) (pc)) (const_int 256)))
6341          (const_int 4)
6342          (if_then_else
6343            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6344                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6345            (const_int 6)
6346            (const_int 8)))
6347        (if_then_else
6348          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6349               (le (minus (match_dup 4) (pc)) (const_int 256)))
6350          (const_int 6)
6351          (if_then_else
6352            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6353                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6354            (const_int 8)
6355            (const_int 10)))))]
6358 (define_insn "*cbranchne_decr1"
6359   [(set (pc)
6360         (if_then_else (match_operator 3 "equality_operator"
6361                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6362                         (const_int 0)])
6363                       (label_ref (match_operand 4 "" ""))
6364                       (pc)))
6365    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6366         (plus:SI (match_dup 2) (const_int -1)))
6367    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6368   "TARGET_THUMB"
6369   "*
6370    {
6371      rtx cond[2];
6372      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6373                                 ? GEU : LTU),
6374                                VOIDmode, operands[2], const1_rtx);
6375      cond[1] = operands[4];
6377      if (which_alternative == 0)
6378        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6379      else if (which_alternative == 1)
6380        {
6381          /* We must provide an alternative for a hi reg because reload 
6382             cannot handle output reloads on a jump instruction, but we
6383             can't subtract into that.  Fortunately a mov from lo to hi
6384             does not clobber the condition codes.  */
6385          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6386          output_asm_insn (\"mov\\t%0, %1\", operands);
6387        }
6388      else
6389        {
6390          /* Similarly, but the target is memory.  */
6391          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6392          output_asm_insn (\"str\\t%1, %0\", operands);
6393        }
6395      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6396        {
6397          case 4:
6398            output_asm_insn (\"b%d0\\t%l1\", cond);
6399            return \"\";
6400          case 6:
6401            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6402            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6403          default:
6404            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6405            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6406        }
6407    }
6408   "
6409   [(set (attr "far_jump")
6410         (if_then_else
6411             (ior (and (eq (symbol_ref ("which_alternative"))
6412                           (const_int 0))
6413                       (eq_attr "length" "8"))
6414                  (eq_attr "length" "10"))
6415             (const_string "yes")
6416             (const_string "no")))
6417    (set_attr_alternative "length"
6418       [
6419        ;; Alternative 0
6420        (if_then_else
6421          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6422               (le (minus (match_dup 4) (pc)) (const_int 256)))
6423          (const_int 4)
6424          (if_then_else
6425            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6426                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6427            (const_int 6)
6428            (const_int 8)))
6429        ;; Alternative 1
6430        (if_then_else
6431          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6432               (le (minus (match_dup 4) (pc)) (const_int 256)))
6433          (const_int 6)
6434          (if_then_else
6435            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6436                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6437            (const_int 8)
6438            (const_int 10)))
6439        ;; Alternative 2
6440        (if_then_else
6441          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6442               (le (minus (match_dup 4) (pc)) (const_int 256)))
6443          (const_int 6)
6444          (if_then_else
6445            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6446                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6447            (const_int 8)
6448            (const_int 10)))
6449        ;; Alternative 3
6450        (if_then_else
6451          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6452               (le (minus (match_dup 4) (pc)) (const_int 256)))
6453          (const_int 6)
6454          (if_then_else
6455            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6456                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6457            (const_int 8)
6458            (const_int 10)))])]
6461 (define_insn "*addsi3_cbranch"
6462   [(set (pc)
6463         (if_then_else
6464          (match_operator 4 "comparison_operator"
6465           [(plus:SI
6466             (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6467             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6468            (const_int 0)])
6469          (label_ref (match_operand 5 "" ""))
6470          (pc)))
6471    (set
6472     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6473     (plus:SI (match_dup 2) (match_dup 3)))
6474    (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6475   "TARGET_THUMB
6476    && (GET_CODE (operands[4]) == EQ
6477        || GET_CODE (operands[4]) == NE
6478        || GET_CODE (operands[4]) == GE
6479        || GET_CODE (operands[4]) == LT)"
6480   "*
6481    {
6482      rtx cond[3];
6484      
6485      cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6486      cond[1] = operands[2];
6487      cond[2] = operands[3];
6489      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6490        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6491      else
6492        output_asm_insn (\"add\\t%0, %1, %2\", cond);
6494      if (which_alternative >= 3
6495          && which_alternative < 4)
6496        output_asm_insn (\"mov\\t%0, %1\", operands);
6497      else if (which_alternative >= 4)
6498        output_asm_insn (\"str\\t%1, %0\", operands);
6500      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6501        {
6502          case 4:
6503            return \"b%d4\\t%l5\";
6504          case 6:
6505            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6506          default:
6507            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6508        }
6509    }
6510   "
6511   [(set (attr "far_jump")
6512         (if_then_else
6513             (ior (and (lt (symbol_ref ("which_alternative"))
6514                           (const_int 3))
6515                       (eq_attr "length" "8"))
6516                  (eq_attr "length" "10"))
6517             (const_string "yes")
6518             (const_string "no")))
6519    (set (attr "length")
6520      (if_then_else
6521        (lt (symbol_ref ("which_alternative"))
6522                        (const_int 3))
6523        (if_then_else
6524          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6525               (le (minus (match_dup 5) (pc)) (const_int 256)))
6526          (const_int 4)
6527          (if_then_else
6528            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6529                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6530            (const_int 6)
6531            (const_int 8)))
6532        (if_then_else
6533          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6534               (le (minus (match_dup 5) (pc)) (const_int 256)))
6535          (const_int 6)
6536          (if_then_else
6537            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6538                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6539            (const_int 8)
6540            (const_int 10)))))]
6543 (define_insn "*addsi3_cbranch_scratch"
6544   [(set (pc)
6545         (if_then_else
6546          (match_operator 3 "comparison_operator"
6547           [(plus:SI
6548             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6549             (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
6550            (const_int 0)])
6551          (label_ref (match_operand 4 "" ""))
6552          (pc)))
6553    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6554   "TARGET_THUMB
6555    && (GET_CODE (operands[3]) == EQ
6556        || GET_CODE (operands[3]) == NE
6557        || GET_CODE (operands[3]) == GE
6558        || GET_CODE (operands[3]) == LT)"
6559   "*
6560    {
6561      switch (which_alternative)
6562        {
6563        case 0:
6564          output_asm_insn (\"cmp\t%1, #%n2\", operands);
6565          break;
6566        case 1:
6567          output_asm_insn (\"cmn\t%1, %2\", operands);
6568          break;
6569        case 2:
6570          if (INTVAL (operands[2]) < 0)
6571            output_asm_insn (\"sub\t%0, %1, %2\", operands);
6572          else
6573            output_asm_insn (\"add\t%0, %1, %2\", operands);
6574          break;
6575        case 3:
6576          if (INTVAL (operands[2]) < 0)
6577            output_asm_insn (\"sub\t%0, %0, %2\", operands);
6578          else
6579            output_asm_insn (\"add\t%0, %0, %2\", operands);
6580          break;
6581        }
6583      switch (get_attr_length (insn))
6584        {
6585          case 4:
6586            return \"b%d3\\t%l4\";
6587          case 6:
6588            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6589          default:
6590            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6591        }
6592    }
6593   "
6594   [(set (attr "far_jump")
6595         (if_then_else
6596             (eq_attr "length" "8")
6597             (const_string "yes")
6598             (const_string "no")))
6599    (set (attr "length")
6600        (if_then_else
6601          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6602               (le (minus (match_dup 4) (pc)) (const_int 256)))
6603          (const_int 4)
6604          (if_then_else
6605            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6606                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6607            (const_int 6)
6608            (const_int 8))))]
6611 (define_insn "*subsi3_cbranch"
6612   [(set (pc)
6613         (if_then_else
6614          (match_operator 4 "comparison_operator"
6615           [(minus:SI
6616             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6617             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6618            (const_int 0)])
6619          (label_ref (match_operand 5 "" ""))
6620          (pc)))
6621    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6622         (minus:SI (match_dup 2) (match_dup 3)))
6623    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6624   "TARGET_THUMB
6625    && (GET_CODE (operands[4]) == EQ
6626        || GET_CODE (operands[4]) == NE
6627        || GET_CODE (operands[4]) == GE
6628        || GET_CODE (operands[4]) == LT)"
6629   "*
6630    {
6631      if (which_alternative == 0)
6632        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6633      else if (which_alternative == 1)
6634        {
6635          /* We must provide an alternative for a hi reg because reload 
6636             cannot handle output reloads on a jump instruction, but we
6637             can't subtract into that.  Fortunately a mov from lo to hi
6638             does not clobber the condition codes.  */
6639          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6640          output_asm_insn (\"mov\\t%0, %1\", operands);
6641        }
6642      else
6643        {
6644          /* Similarly, but the target is memory.  */
6645          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6646          output_asm_insn (\"str\\t%1, %0\", operands);
6647        }
6649      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6650        {
6651          case 4:
6652            return \"b%d4\\t%l5\";
6653          case 6:
6654            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6655          default:
6656            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6657        }
6658    }
6659   "
6660   [(set (attr "far_jump")
6661         (if_then_else
6662             (ior (and (eq (symbol_ref ("which_alternative"))
6663                           (const_int 0))
6664                       (eq_attr "length" "8"))
6665                  (eq_attr "length" "10"))
6666             (const_string "yes")
6667             (const_string "no")))
6668    (set (attr "length")
6669      (if_then_else
6670        (eq (symbol_ref ("which_alternative"))
6671                        (const_int 0))
6672        (if_then_else
6673          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6674               (le (minus (match_dup 5) (pc)) (const_int 256)))
6675          (const_int 4)
6676          (if_then_else
6677            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6678                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6679            (const_int 6)
6680            (const_int 8)))
6681        (if_then_else
6682          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6683               (le (minus (match_dup 5) (pc)) (const_int 256)))
6684          (const_int 6)
6685          (if_then_else
6686            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6687                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6688            (const_int 8)
6689            (const_int 10)))))]
6692 (define_insn "*subsi3_cbranch_scratch"
6693   [(set (pc)
6694         (if_then_else
6695          (match_operator 0 "arm_comparison_operator"
6696           [(minus:SI (match_operand:SI 1 "register_operand" "l")
6697                      (match_operand:SI 2 "nonmemory_operand" "l"))
6698            (const_int 0)])
6699          (label_ref (match_operand 3 "" ""))
6700          (pc)))]
6701   "TARGET_THUMB
6702    && (GET_CODE (operands[0]) == EQ
6703        || GET_CODE (operands[0]) == NE
6704        || GET_CODE (operands[0]) == GE
6705        || GET_CODE (operands[0]) == LT)"
6706   "*
6707   output_asm_insn (\"cmp\\t%1, %2\", operands);
6708   switch (get_attr_length (insn))
6709     {
6710     case 4:  return \"b%d0\\t%l3\";
6711     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6712     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6713     }
6714   "
6715   [(set (attr "far_jump")
6716         (if_then_else
6717             (eq_attr "length" "8")
6718             (const_string "yes")
6719             (const_string "no")))
6720    (set (attr "length") 
6721         (if_then_else
6722             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6723                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6724             (const_int 4)
6725             (if_then_else
6726                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6727                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6728                 (const_int 6)
6729                 (const_int 8))))]
6732 ;; Comparison and test insns
6734 (define_expand "cmpsi"
6735   [(match_operand:SI 0 "s_register_operand" "")
6736    (match_operand:SI 1 "arm_add_operand" "")]
6737   "TARGET_ARM"
6738   "{
6739     arm_compare_op0 = operands[0];
6740     arm_compare_op1 = operands[1];
6741     DONE;
6742   }"
6745 (define_expand "cmpsf"
6746   [(match_operand:SF 0 "s_register_operand" "")
6747    (match_operand:SF 1 "arm_float_compare_operand" "")]
6748   "TARGET_ARM && TARGET_HARD_FLOAT"
6749   "
6750   arm_compare_op0 = operands[0];
6751   arm_compare_op1 = operands[1];
6752   DONE;
6753   "
6756 (define_expand "cmpdf"
6757   [(match_operand:DF 0 "s_register_operand" "")
6758    (match_operand:DF 1 "arm_float_compare_operand" "")]
6759   "TARGET_ARM && TARGET_HARD_FLOAT"
6760   "
6761   arm_compare_op0 = operands[0];
6762   arm_compare_op1 = operands[1];
6763   DONE;
6764   "
6767 (define_insn "*arm_cmpsi_insn"
6768   [(set (reg:CC CC_REGNUM)
6769         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6770                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
6771   "TARGET_ARM"
6772   "@
6773    cmp%?\\t%0, %1
6774    cmn%?\\t%0, #%n1"
6775   [(set_attr "conds" "set")]
6778 (define_insn "*cmpsi_shiftsi"
6779   [(set (reg:CC CC_REGNUM)
6780         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
6781                     (match_operator:SI  3 "shift_operator"
6782                      [(match_operand:SI 1 "s_register_operand" "r")
6783                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
6784   "TARGET_ARM"
6785   "cmp%?\\t%0, %1%S3"
6786   [(set_attr "conds" "set")
6787    (set_attr "shift" "1")
6788    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6789                       (const_string "alu_shift")
6790                       (const_string "alu_shift_reg")))]
6793 (define_insn "*cmpsi_shiftsi_swp"
6794   [(set (reg:CC_SWP CC_REGNUM)
6795         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6796                          [(match_operand:SI 1 "s_register_operand" "r")
6797                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
6798                         (match_operand:SI 0 "s_register_operand" "r")))]
6799   "TARGET_ARM"
6800   "cmp%?\\t%0, %1%S3"
6801   [(set_attr "conds" "set")
6802    (set_attr "shift" "1")
6803    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6804                       (const_string "alu_shift")
6805                       (const_string "alu_shift_reg")))]
6808 (define_insn "*cmpsi_negshiftsi_si"
6809   [(set (reg:CC_Z CC_REGNUM)
6810         (compare:CC_Z
6811          (neg:SI (match_operator:SI 1 "shift_operator"
6812                     [(match_operand:SI 2 "s_register_operand" "r")
6813                      (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6814          (match_operand:SI 0 "s_register_operand" "r")))]
6815   "TARGET_ARM"
6816   "cmn%?\\t%0, %2%S1"
6817   [(set_attr "conds" "set")
6818    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
6819                                     (const_string "alu_shift")
6820                                     (const_string "alu_shift_reg")))]
6823 ;; Cirrus SF compare instruction
6824 (define_insn "*cirrus_cmpsf"
6825   [(set (reg:CCFP CC_REGNUM)
6826         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6827                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
6828   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6829   "cfcmps%?\\tr15, %V0, %V1"
6830   [(set_attr "type"   "mav_farith")
6831    (set_attr "cirrus" "compare")]
6834 ;; Cirrus DF compare instruction
6835 (define_insn "*cirrus_cmpdf"
6836   [(set (reg:CCFP CC_REGNUM)
6837         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6838                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
6839   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6840   "cfcmpd%?\\tr15, %V0, %V1"
6841   [(set_attr "type"   "mav_farith")
6842    (set_attr "cirrus" "compare")]
6845 ;; Cirrus DI compare instruction
6846 (define_expand "cmpdi"
6847   [(match_operand:DI 0 "cirrus_fp_register" "")
6848    (match_operand:DI 1 "cirrus_fp_register" "")]
6849   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6850   "{
6851      arm_compare_op0 = operands[0];
6852      arm_compare_op1 = operands[1];
6853      DONE;
6854    }")
6856 (define_insn "*cirrus_cmpdi"
6857   [(set (reg:CC CC_REGNUM)
6858         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6859                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
6860   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6861   "cfcmp64%?\\tr15, %V0, %V1"
6862   [(set_attr "type"   "mav_farith")
6863    (set_attr "cirrus" "compare")]
6866 ; This insn allows redundant compares to be removed by cse, nothing should
6867 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6868 ; is deleted later on. The match_dup will match the mode here, so that
6869 ; mode changes of the condition codes aren't lost by this even though we don't
6870 ; specify what they are.
6872 (define_insn "*deleted_compare"
6873   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6874   "TARGET_ARM"
6875   "\\t%@ deleted compare"
6876   [(set_attr "conds" "set")
6877    (set_attr "length" "0")]
6881 ;; Conditional branch insns
6883 (define_expand "beq"
6884   [(set (pc)
6885         (if_then_else (eq (match_dup 1) (const_int 0))
6886                       (label_ref (match_operand 0 "" ""))
6887                       (pc)))]
6888   "TARGET_ARM"
6889   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6892 (define_expand "bne"
6893   [(set (pc)
6894         (if_then_else (ne (match_dup 1) (const_int 0))
6895                       (label_ref (match_operand 0 "" ""))
6896                       (pc)))]
6897   "TARGET_ARM"
6898   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6901 (define_expand "bgt"
6902   [(set (pc)
6903         (if_then_else (gt (match_dup 1) (const_int 0))
6904                       (label_ref (match_operand 0 "" ""))
6905                       (pc)))]
6906   "TARGET_ARM"
6907   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6910 (define_expand "ble"
6911   [(set (pc)
6912         (if_then_else (le (match_dup 1) (const_int 0))
6913                       (label_ref (match_operand 0 "" ""))
6914                       (pc)))]
6915   "TARGET_ARM"
6916   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6919 (define_expand "bge"
6920   [(set (pc)
6921         (if_then_else (ge (match_dup 1) (const_int 0))
6922                       (label_ref (match_operand 0 "" ""))
6923                       (pc)))]
6924   "TARGET_ARM"
6925   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6928 (define_expand "blt"
6929   [(set (pc)
6930         (if_then_else (lt (match_dup 1) (const_int 0))
6931                       (label_ref (match_operand 0 "" ""))
6932                       (pc)))]
6933   "TARGET_ARM"
6934   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6937 (define_expand "bgtu"
6938   [(set (pc)
6939         (if_then_else (gtu (match_dup 1) (const_int 0))
6940                       (label_ref (match_operand 0 "" ""))
6941                       (pc)))]
6942   "TARGET_ARM"
6943   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6946 (define_expand "bleu"
6947   [(set (pc)
6948         (if_then_else (leu (match_dup 1) (const_int 0))
6949                       (label_ref (match_operand 0 "" ""))
6950                       (pc)))]
6951   "TARGET_ARM"
6952   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6955 (define_expand "bgeu"
6956   [(set (pc)
6957         (if_then_else (geu (match_dup 1) (const_int 0))
6958                       (label_ref (match_operand 0 "" ""))
6959                       (pc)))]
6960   "TARGET_ARM"
6961   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6964 (define_expand "bltu"
6965   [(set (pc)
6966         (if_then_else (ltu (match_dup 1) (const_int 0))
6967                       (label_ref (match_operand 0 "" ""))
6968                       (pc)))]
6969   "TARGET_ARM"
6970   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6973 (define_expand "bunordered"
6974   [(set (pc)
6975         (if_then_else (unordered (match_dup 1) (const_int 0))
6976                       (label_ref (match_operand 0 "" ""))
6977                       (pc)))]
6978   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
6979   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6980                                       arm_compare_op1);"
6983 (define_expand "bordered"
6984   [(set (pc)
6985         (if_then_else (ordered (match_dup 1) (const_int 0))
6986                       (label_ref (match_operand 0 "" ""))
6987                       (pc)))]
6988   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
6989   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6990                                       arm_compare_op1);"
6993 (define_expand "bungt"
6994   [(set (pc)
6995         (if_then_else (ungt (match_dup 1) (const_int 0))
6996                       (label_ref (match_operand 0 "" ""))
6997                       (pc)))]
6998   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
6999   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
7002 (define_expand "bunlt"
7003   [(set (pc)
7004         (if_then_else (unlt (match_dup 1) (const_int 0))
7005                       (label_ref (match_operand 0 "" ""))
7006                       (pc)))]
7007   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7008   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
7011 (define_expand "bunge"
7012   [(set (pc)
7013         (if_then_else (unge (match_dup 1) (const_int 0))
7014                       (label_ref (match_operand 0 "" ""))
7015                       (pc)))]
7016   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7017   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
7020 (define_expand "bunle"
7021   [(set (pc)
7022         (if_then_else (unle (match_dup 1) (const_int 0))
7023                       (label_ref (match_operand 0 "" ""))
7024                       (pc)))]
7025   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7026   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
7029 ;; The following two patterns need two branch instructions, since there is
7030 ;; no single instruction that will handle all cases.
7031 (define_expand "buneq"
7032   [(set (pc)
7033         (if_then_else (uneq (match_dup 1) (const_int 0))
7034                       (label_ref (match_operand 0 "" ""))
7035                       (pc)))]
7036   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7037   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
7040 (define_expand "bltgt"
7041   [(set (pc)
7042         (if_then_else (ltgt (match_dup 1) (const_int 0))
7043                       (label_ref (match_operand 0 "" ""))
7044                       (pc)))]
7045   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7046   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
7050 ;; Patterns to match conditional branch insns.
7053 ; Special pattern to match UNEQ.
7054 (define_insn "*arm_buneq"
7055   [(set (pc)
7056         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7057                       (label_ref (match_operand 0 "" ""))
7058                       (pc)))]
7059   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7060   "*
7061   gcc_assert (!arm_ccfsm_state);
7063   return \"bvs\\t%l0\;beq\\t%l0\";
7064   "
7065   [(set_attr "conds" "jump_clob")
7066    (set_attr "length" "8")]
7069 ; Special pattern to match LTGT.
7070 (define_insn "*arm_bltgt"
7071   [(set (pc)
7072         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7073                       (label_ref (match_operand 0 "" ""))
7074                       (pc)))]
7075   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7076   "*
7077   gcc_assert (!arm_ccfsm_state);
7079   return \"bmi\\t%l0\;bgt\\t%l0\";
7080   "
7081   [(set_attr "conds" "jump_clob")
7082    (set_attr "length" "8")]
7085 (define_insn "*arm_cond_branch"
7086   [(set (pc)
7087         (if_then_else (match_operator 1 "arm_comparison_operator"
7088                        [(match_operand 2 "cc_register" "") (const_int 0)])
7089                       (label_ref (match_operand 0 "" ""))
7090                       (pc)))]
7091   "TARGET_ARM"
7092   "*
7093   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7094     {
7095       arm_ccfsm_state += 2;
7096       return \"\";
7097     }
7098   return \"b%d1\\t%l0\";
7099   "
7100   [(set_attr "conds" "use")
7101    (set_attr "type" "branch")]
7104 ; Special pattern to match reversed UNEQ.
7105 (define_insn "*arm_buneq_reversed"
7106   [(set (pc)
7107         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7108                       (pc)
7109                       (label_ref (match_operand 0 "" ""))))]
7110   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7111   "*
7112   gcc_assert (!arm_ccfsm_state);
7114   return \"bmi\\t%l0\;bgt\\t%l0\";
7115   "
7116   [(set_attr "conds" "jump_clob")
7117    (set_attr "length" "8")]
7120 ; Special pattern to match reversed LTGT.
7121 (define_insn "*arm_bltgt_reversed"
7122   [(set (pc)
7123         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7124                       (pc)
7125                       (label_ref (match_operand 0 "" ""))))]
7126   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7127   "*
7128   gcc_assert (!arm_ccfsm_state);
7130   return \"bvs\\t%l0\;beq\\t%l0\";
7131   "
7132   [(set_attr "conds" "jump_clob")
7133    (set_attr "length" "8")]
7136 (define_insn "*arm_cond_branch_reversed"
7137   [(set (pc)
7138         (if_then_else (match_operator 1 "arm_comparison_operator"
7139                        [(match_operand 2 "cc_register" "") (const_int 0)])
7140                       (pc)
7141                       (label_ref (match_operand 0 "" ""))))]
7142   "TARGET_ARM"
7143   "*
7144   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7145     {
7146       arm_ccfsm_state += 2;
7147       return \"\";
7148     }
7149   return \"b%D1\\t%l0\";
7150   "
7151   [(set_attr "conds" "use")
7152    (set_attr "type" "branch")]
7157 ; scc insns
7159 (define_expand "seq"
7160   [(set (match_operand:SI 0 "s_register_operand" "")
7161         (eq:SI (match_dup 1) (const_int 0)))]
7162   "TARGET_ARM"
7163   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7166 (define_expand "sne"
7167   [(set (match_operand:SI 0 "s_register_operand" "")
7168         (ne:SI (match_dup 1) (const_int 0)))]
7169   "TARGET_ARM"
7170   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7173 (define_expand "sgt"
7174   [(set (match_operand:SI 0 "s_register_operand" "")
7175         (gt:SI (match_dup 1) (const_int 0)))]
7176   "TARGET_ARM"
7177   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7180 (define_expand "sle"
7181   [(set (match_operand:SI 0 "s_register_operand" "")
7182         (le:SI (match_dup 1) (const_int 0)))]
7183   "TARGET_ARM"
7184   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7187 (define_expand "sge"
7188   [(set (match_operand:SI 0 "s_register_operand" "")
7189         (ge:SI (match_dup 1) (const_int 0)))]
7190   "TARGET_ARM"
7191   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7194 (define_expand "slt"
7195   [(set (match_operand:SI 0 "s_register_operand" "")
7196         (lt:SI (match_dup 1) (const_int 0)))]
7197   "TARGET_ARM"
7198   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7201 (define_expand "sgtu"
7202   [(set (match_operand:SI 0 "s_register_operand" "")
7203         (gtu:SI (match_dup 1) (const_int 0)))]
7204   "TARGET_ARM"
7205   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7208 (define_expand "sleu"
7209   [(set (match_operand:SI 0 "s_register_operand" "")
7210         (leu:SI (match_dup 1) (const_int 0)))]
7211   "TARGET_ARM"
7212   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7215 (define_expand "sgeu"
7216   [(set (match_operand:SI 0 "s_register_operand" "")
7217         (geu:SI (match_dup 1) (const_int 0)))]
7218   "TARGET_ARM"
7219   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7222 (define_expand "sltu"
7223   [(set (match_operand:SI 0 "s_register_operand" "")
7224         (ltu:SI (match_dup 1) (const_int 0)))]
7225   "TARGET_ARM"
7226   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7229 (define_expand "sunordered"
7230   [(set (match_operand:SI 0 "s_register_operand" "")
7231         (unordered:SI (match_dup 1) (const_int 0)))]
7232   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7233   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7234                                       arm_compare_op1);"
7237 (define_expand "sordered"
7238   [(set (match_operand:SI 0 "s_register_operand" "")
7239         (ordered:SI (match_dup 1) (const_int 0)))]
7240   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7241   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7242                                       arm_compare_op1);"
7245 (define_expand "sungt"
7246   [(set (match_operand:SI 0 "s_register_operand" "")
7247         (ungt:SI (match_dup 1) (const_int 0)))]
7248   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7249   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7250                                       arm_compare_op1);"
7253 (define_expand "sunge"
7254   [(set (match_operand:SI 0 "s_register_operand" "")
7255         (unge:SI (match_dup 1) (const_int 0)))]
7256   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7257   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7258                                       arm_compare_op1);"
7261 (define_expand "sunlt"
7262   [(set (match_operand:SI 0 "s_register_operand" "")
7263         (unlt:SI (match_dup 1) (const_int 0)))]
7264   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7265   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7266                                       arm_compare_op1);"
7269 (define_expand "sunle"
7270   [(set (match_operand:SI 0 "s_register_operand" "")
7271         (unle:SI (match_dup 1) (const_int 0)))]
7272   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7273   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7274                                       arm_compare_op1);"
7277 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7278 ;;; simple ARM instructions. 
7280 ; (define_expand "suneq"
7281 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7282 ;       (uneq:SI (match_dup 1) (const_int 0)))]
7283 ;   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7284 ;   "gcc_unreachable ();"
7285 ; )
7287 ; (define_expand "sltgt"
7288 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7289 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
7290 ;   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7291 ;   "gcc_unreachable ();"
7292 ; )
7294 (define_insn "*mov_scc"
7295   [(set (match_operand:SI 0 "s_register_operand" "=r")
7296         (match_operator:SI 1 "arm_comparison_operator"
7297          [(match_operand 2 "cc_register" "") (const_int 0)]))]
7298   "TARGET_ARM"
7299   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7300   [(set_attr "conds" "use")
7301    (set_attr "length" "8")]
7304 (define_insn "*mov_negscc"
7305   [(set (match_operand:SI 0 "s_register_operand" "=r")
7306         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7307                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7308   "TARGET_ARM"
7309   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7310   [(set_attr "conds" "use")
7311    (set_attr "length" "8")]
7314 (define_insn "*mov_notscc"
7315   [(set (match_operand:SI 0 "s_register_operand" "=r")
7316         (not:SI (match_operator:SI 1 "arm_comparison_operator"
7317                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7318   "TARGET_ARM"
7319   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7320   [(set_attr "conds" "use")
7321    (set_attr "length" "8")]
7325 ;; Conditional move insns
7327 (define_expand "movsicc"
7328   [(set (match_operand:SI 0 "s_register_operand" "")
7329         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7330                          (match_operand:SI 2 "arm_not_operand" "")
7331                          (match_operand:SI 3 "arm_not_operand" "")))]
7332   "TARGET_ARM"
7333   "
7334   {
7335     enum rtx_code code = GET_CODE (operands[1]);
7336     rtx ccreg;
7338     if (code == UNEQ || code == LTGT)
7339       FAIL;
7341     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7342     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7343   }"
7346 (define_expand "movsfcc"
7347   [(set (match_operand:SF 0 "s_register_operand" "")
7348         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7349                          (match_operand:SF 2 "s_register_operand" "")
7350                          (match_operand:SF 3 "nonmemory_operand" "")))]
7351   "TARGET_ARM"
7352   "
7353   {
7354     enum rtx_code code = GET_CODE (operands[1]);
7355     rtx ccreg;
7357     if (code == UNEQ || code == LTGT)
7358       FAIL;
7360     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
7361        Otherwise, ensure it is a valid FP add operand */
7362     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7363         || (!arm_float_add_operand (operands[3], SFmode)))
7364       operands[3] = force_reg (SFmode, operands[3]);
7366     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7367     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7368   }"
7371 (define_expand "movdfcc"
7372   [(set (match_operand:DF 0 "s_register_operand" "")
7373         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7374                          (match_operand:DF 2 "s_register_operand" "")
7375                          (match_operand:DF 3 "arm_float_add_operand" "")))]
7376   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7377   "
7378   {
7379     enum rtx_code code = GET_CODE (operands[1]);
7380     rtx ccreg;
7382     if (code == UNEQ || code == LTGT)
7383       FAIL;
7385     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7386     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7387   }"
7390 (define_insn "*movsicc_insn"
7391   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7392         (if_then_else:SI
7393          (match_operator 3 "arm_comparison_operator"
7394           [(match_operand 4 "cc_register" "") (const_int 0)])
7395          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7396          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7397   "TARGET_ARM"
7398   "@
7399    mov%D3\\t%0, %2
7400    mvn%D3\\t%0, #%B2
7401    mov%d3\\t%0, %1
7402    mvn%d3\\t%0, #%B1
7403    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7404    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7405    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7406    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7407   [(set_attr "length" "4,4,4,4,8,8,8,8")
7408    (set_attr "conds" "use")]
7411 (define_insn "*movsfcc_soft_insn"
7412   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7413         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7414                           [(match_operand 4 "cc_register" "") (const_int 0)])
7415                          (match_operand:SF 1 "s_register_operand" "0,r")
7416                          (match_operand:SF 2 "s_register_operand" "r,0")))]
7417   "TARGET_ARM && TARGET_SOFT_FLOAT"
7418   "@
7419    mov%D3\\t%0, %2
7420    mov%d3\\t%0, %1"
7421   [(set_attr "conds" "use")]
7425 ;; Jump and linkage insns
7427 (define_expand "jump"
7428   [(set (pc)
7429         (label_ref (match_operand 0 "" "")))]
7430   "TARGET_EITHER"
7431   ""
7434 (define_insn "*arm_jump"
7435   [(set (pc)
7436         (label_ref (match_operand 0 "" "")))]
7437   "TARGET_ARM"
7438   "*
7439   {
7440     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7441       {
7442         arm_ccfsm_state += 2;
7443         return \"\";
7444       }
7445     return \"b%?\\t%l0\";
7446   }
7447   "
7448   [(set_attr "predicable" "yes")]
7451 (define_insn "*thumb_jump"
7452   [(set (pc)
7453         (label_ref (match_operand 0 "" "")))]
7454   "TARGET_THUMB"
7455   "*
7456   if (get_attr_length (insn) == 2)
7457     return \"b\\t%l0\";
7458   return \"bl\\t%l0\\t%@ far jump\";
7459   "
7460   [(set (attr "far_jump")
7461         (if_then_else
7462             (eq_attr "length" "4")
7463             (const_string "yes")
7464             (const_string "no")))
7465    (set (attr "length") 
7466         (if_then_else
7467             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7468                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
7469             (const_int 2)
7470             (const_int 4)))]
7473 (define_expand "call"
7474   [(parallel [(call (match_operand 0 "memory_operand" "")
7475                     (match_operand 1 "general_operand" ""))
7476               (use (match_operand 2 "" ""))
7477               (clobber (reg:SI LR_REGNUM))])]
7478   "TARGET_EITHER"
7479   "
7480   {
7481     rtx callee;
7482     
7483     /* In an untyped call, we can get NULL for operand 2.  */
7484     if (operands[2] == NULL_RTX)
7485       operands[2] = const0_rtx;
7486       
7487     /* This is to decide if we should generate indirect calls by loading the
7488        32 bit address of the callee into a register before performing the
7489        branch and link.  operand[2] encodes the long_call/short_call
7490        attribute of the function being called.  This attribute is set whenever
7491        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7492        is used, and the short_call attribute can also be set if function is
7493        declared as static or if it has already been defined in the current
7494        compilation unit.  See arm.c and arm.h for info about this.  The third
7495        parameter to arm_is_longcall_p is used to tell it which pattern
7496        invoked it.  */
7497     callee  = XEXP (operands[0], 0);
7498     
7499     if (GET_CODE (callee) != REG
7500        && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7501       XEXP (operands[0], 0) = force_reg (Pmode, callee);
7502   }"
7505 (define_insn "*call_reg_armv5"
7506   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7507          (match_operand 1 "" ""))
7508    (use (match_operand 2 "" ""))
7509    (clobber (reg:SI LR_REGNUM))]
7510   "TARGET_ARM && arm_arch5"
7511   "blx%?\\t%0"
7512   [(set_attr "type" "call")]
7515 (define_insn "*call_reg_arm"
7516   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7517          (match_operand 1 "" ""))
7518    (use (match_operand 2 "" ""))
7519    (clobber (reg:SI LR_REGNUM))]
7520   "TARGET_ARM && !arm_arch5"
7521   "*
7522   return output_call (operands);
7523   "
7524   ;; length is worst case, normally it is only two
7525   [(set_attr "length" "12")
7526    (set_attr "type" "call")]
7529 (define_insn "*call_mem"
7530   [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7531          (match_operand 1 "" ""))
7532    (use (match_operand 2 "" ""))
7533    (clobber (reg:SI LR_REGNUM))]
7534   "TARGET_ARM"
7535   "*
7536   return output_call_mem (operands);
7537   "
7538   [(set_attr "length" "12")
7539    (set_attr "type" "call")]
7542 (define_insn "*call_reg_thumb_v5"
7543   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7544          (match_operand 1 "" ""))
7545    (use (match_operand 2 "" ""))
7546    (clobber (reg:SI LR_REGNUM))]
7547   "TARGET_THUMB && arm_arch5"
7548   "blx\\t%0"
7549   [(set_attr "length" "2")
7550    (set_attr "type" "call")]
7553 (define_insn "*call_reg_thumb"
7554   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7555          (match_operand 1 "" ""))
7556    (use (match_operand 2 "" ""))
7557    (clobber (reg:SI LR_REGNUM))]
7558   "TARGET_THUMB && !arm_arch5"
7559   "*
7560   {
7561     if (!TARGET_CALLER_INTERWORKING)
7562       return thumb_call_via_reg (operands[0]);
7563     else if (operands[1] == const0_rtx)
7564       return \"bl\\t%__interwork_call_via_%0\";
7565     else if (frame_pointer_needed)
7566       return \"bl\\t%__interwork_r7_call_via_%0\";
7567     else
7568       return \"bl\\t%__interwork_r11_call_via_%0\";
7569   }"
7570   [(set_attr "type" "call")]
7573 (define_expand "call_value"
7574   [(parallel [(set (match_operand       0 "" "")
7575                    (call (match_operand 1 "memory_operand" "")
7576                          (match_operand 2 "general_operand" "")))
7577               (use (match_operand 3 "" ""))
7578               (clobber (reg:SI LR_REGNUM))])]
7579   "TARGET_EITHER"
7580   "
7581   {
7582     rtx callee = XEXP (operands[1], 0);
7583     
7584     /* In an untyped call, we can get NULL for operand 2.  */
7585     if (operands[3] == 0)
7586       operands[3] = const0_rtx;
7587       
7588     /* See the comment in define_expand \"call\".  */
7589     if (GET_CODE (callee) != REG
7590         && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7591       XEXP (operands[1], 0) = force_reg (Pmode, callee);
7592   }"
7595 (define_insn "*call_value_reg_armv5"
7596   [(set (match_operand 0 "" "")
7597         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7598               (match_operand 2 "" "")))
7599    (use (match_operand 3 "" ""))
7600    (clobber (reg:SI LR_REGNUM))]
7601   "TARGET_ARM && arm_arch5"
7602   "blx%?\\t%1"
7603   [(set_attr "type" "call")]
7606 (define_insn "*call_value_reg_arm"
7607   [(set (match_operand 0 "" "")
7608         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7609               (match_operand 2 "" "")))
7610    (use (match_operand 3 "" ""))
7611    (clobber (reg:SI LR_REGNUM))]
7612   "TARGET_ARM && !arm_arch5"
7613   "*
7614   return output_call (&operands[1]);
7615   "
7616   [(set_attr "length" "12")
7617    (set_attr "type" "call")]
7620 (define_insn "*call_value_mem"
7621   [(set (match_operand 0 "" "")
7622         (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7623               (match_operand 2 "" "")))
7624    (use (match_operand 3 "" ""))
7625    (clobber (reg:SI LR_REGNUM))]
7626   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7627   "*
7628   return output_call_mem (&operands[1]);
7629   "
7630   [(set_attr "length" "12")
7631    (set_attr "type" "call")]
7634 (define_insn "*call_value_reg_thumb_v5"
7635   [(set (match_operand 0 "" "")
7636         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7637               (match_operand 2 "" "")))
7638    (use (match_operand 3 "" ""))
7639    (clobber (reg:SI LR_REGNUM))]
7640   "TARGET_THUMB && arm_arch5"
7641   "blx\\t%1"
7642   [(set_attr "length" "2")
7643    (set_attr "type" "call")]
7646 (define_insn "*call_value_reg_thumb"
7647   [(set (match_operand 0 "" "")
7648         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7649               (match_operand 2 "" "")))
7650    (use (match_operand 3 "" ""))
7651    (clobber (reg:SI LR_REGNUM))]
7652   "TARGET_THUMB && !arm_arch5"
7653   "*
7654   {
7655     if (!TARGET_CALLER_INTERWORKING)
7656       return thumb_call_via_reg (operands[1]);
7657     else if (operands[2] == const0_rtx)
7658       return \"bl\\t%__interwork_call_via_%1\";
7659     else if (frame_pointer_needed)
7660       return \"bl\\t%__interwork_r7_call_via_%1\";
7661     else
7662       return \"bl\\t%__interwork_r11_call_via_%1\";
7663   }"
7664   [(set_attr "type" "call")]
7667 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7668 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7670 (define_insn "*call_symbol"
7671   [(call (mem:SI (match_operand:SI 0 "" ""))
7672          (match_operand 1 "" ""))
7673    (use (match_operand 2 "" ""))
7674    (clobber (reg:SI LR_REGNUM))]
7675   "TARGET_ARM
7676    && (GET_CODE (operands[0]) == SYMBOL_REF)
7677    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7678   "*
7679   {
7680     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7681   }"
7682   [(set_attr "type" "call")]
7685 (define_insn "*call_value_symbol"
7686   [(set (match_operand 0 "" "")
7687         (call (mem:SI (match_operand:SI 1 "" ""))
7688         (match_operand:SI 2 "" "")))
7689    (use (match_operand 3 "" ""))
7690    (clobber (reg:SI LR_REGNUM))]
7691   "TARGET_ARM
7692    && (GET_CODE (operands[1]) == SYMBOL_REF)
7693    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7694   "*
7695   {
7696     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7697   }"
7698   [(set_attr "type" "call")]
7701 (define_insn "*call_insn"
7702   [(call (mem:SI (match_operand:SI 0 "" ""))
7703          (match_operand:SI 1 "" ""))
7704    (use (match_operand 2 "" ""))
7705    (clobber (reg:SI LR_REGNUM))]
7706   "TARGET_THUMB
7707    && GET_CODE (operands[0]) == SYMBOL_REF
7708    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7709   "bl\\t%a0"
7710   [(set_attr "length" "4")
7711    (set_attr "type" "call")]
7714 (define_insn "*call_value_insn"
7715   [(set (match_operand 0 "" "")
7716         (call (mem:SI (match_operand 1 "" ""))
7717               (match_operand 2 "" "")))
7718    (use (match_operand 3 "" ""))
7719    (clobber (reg:SI LR_REGNUM))]
7720   "TARGET_THUMB
7721    && GET_CODE (operands[1]) == SYMBOL_REF
7722    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7723   "bl\\t%a1"
7724   [(set_attr "length" "4")
7725    (set_attr "type" "call")]
7728 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7729 (define_expand "sibcall"
7730   [(parallel [(call (match_operand 0 "memory_operand" "")
7731                     (match_operand 1 "general_operand" ""))
7732               (return)
7733               (use (match_operand 2 "" ""))])]
7734   "TARGET_ARM"
7735   "
7736   {
7737     if (operands[2] == NULL_RTX)
7738       operands[2] = const0_rtx;
7739   }"
7742 (define_expand "sibcall_value"
7743   [(parallel [(set (match_operand 0 "" "")
7744                    (call (match_operand 1 "memory_operand" "")
7745                          (match_operand 2 "general_operand" "")))
7746               (return)
7747               (use (match_operand 3 "" ""))])]
7748   "TARGET_ARM"
7749   "
7750   {
7751     if (operands[3] == NULL_RTX)
7752       operands[3] = const0_rtx;
7753   }"
7756 (define_insn "*sibcall_insn"
7757  [(call (mem:SI (match_operand:SI 0 "" "X"))
7758         (match_operand 1 "" ""))
7759   (return)
7760   (use (match_operand 2 "" ""))]
7761   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7762   "*
7763   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7764   "
7765   [(set_attr "type" "call")]
7768 (define_insn "*sibcall_value_insn"
7769  [(set (match_operand 0 "" "")
7770        (call (mem:SI (match_operand:SI 1 "" "X"))
7771              (match_operand 2 "" "")))
7772   (return)
7773   (use (match_operand 3 "" ""))]
7774   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7775   "*
7776   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7777   "
7778   [(set_attr "type" "call")]
7781 ;; Often the return insn will be the same as loading from memory, so set attr
7782 (define_insn "return"
7783   [(return)]
7784   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7785   "*
7786   {
7787     if (arm_ccfsm_state == 2)
7788       {
7789         arm_ccfsm_state += 2;
7790         return \"\";
7791       }
7792     return output_return_instruction (const_true_rtx, TRUE, FALSE);
7793   }"
7794   [(set_attr "type" "load1")
7795    (set_attr "length" "12")
7796    (set_attr "predicable" "yes")]
7799 (define_insn "*cond_return"
7800   [(set (pc)
7801         (if_then_else (match_operator 0 "arm_comparison_operator"
7802                        [(match_operand 1 "cc_register" "") (const_int 0)])
7803                       (return)
7804                       (pc)))]
7805   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7806   "*
7807   {
7808     if (arm_ccfsm_state == 2)
7809       {
7810         arm_ccfsm_state += 2;
7811         return \"\";
7812       }
7813     return output_return_instruction (operands[0], TRUE, FALSE);
7814   }"
7815   [(set_attr "conds" "use")
7816    (set_attr "length" "12")
7817    (set_attr "type" "load1")]
7820 (define_insn "*cond_return_inverted"
7821   [(set (pc)
7822         (if_then_else (match_operator 0 "arm_comparison_operator"
7823                        [(match_operand 1 "cc_register" "") (const_int 0)])
7824                       (pc)
7825                       (return)))]
7826   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7827   "*
7828   {
7829     if (arm_ccfsm_state == 2)
7830       {
7831         arm_ccfsm_state += 2;
7832         return \"\";
7833       }
7834     return output_return_instruction (operands[0], TRUE, TRUE);
7835   }"
7836   [(set_attr "conds" "use")
7837    (set_attr "length" "12")
7838    (set_attr "type" "load1")]
7841 ;; Generate a sequence of instructions to determine if the processor is
7842 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7843 ;; mask.
7845 (define_expand "return_addr_mask"
7846   [(set (match_dup 1)
7847       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7848                        (const_int 0)))
7849    (set (match_operand:SI 0 "s_register_operand" "")
7850       (if_then_else:SI (eq (match_dup 1) (const_int 0))
7851                        (const_int -1)
7852                        (const_int 67108860)))] ; 0x03fffffc
7853   "TARGET_ARM"
7854   "
7855   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7856   ")
7858 (define_insn "*check_arch2"
7859   [(set (match_operand:CC_NOOV 0 "cc_register" "")
7860       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7861                        (const_int 0)))]
7862   "TARGET_ARM"
7863   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7864   [(set_attr "length" "8")
7865    (set_attr "conds" "set")]
7868 ;; Call subroutine returning any type.
7870 (define_expand "untyped_call"
7871   [(parallel [(call (match_operand 0 "" "")
7872                     (const_int 0))
7873               (match_operand 1 "" "")
7874               (match_operand 2 "" "")])]
7875   "TARGET_EITHER"
7876   "
7877   {
7878     int i;
7879     rtx par = gen_rtx_PARALLEL (VOIDmode,
7880                                 rtvec_alloc (XVECLEN (operands[2], 0)));
7881     rtx addr = gen_reg_rtx (Pmode);
7882     rtx mem;
7883     int size = 0;
7885     emit_move_insn (addr, XEXP (operands[1], 0));
7886     mem = change_address (operands[1], BLKmode, addr);
7888     for (i = 0; i < XVECLEN (operands[2], 0); i++)
7889       {
7890         rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
7892         /* Default code only uses r0 as a return value, but we could
7893            be using anything up to 4 registers.  */
7894         if (REGNO (src) == R0_REGNUM)
7895           src = gen_rtx_REG (TImode, R0_REGNUM);
7897         XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
7898                                                  GEN_INT (size));
7899         size += GET_MODE_SIZE (GET_MODE (src));
7900       }
7902     emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
7903                                     const0_rtx));
7905     size = 0;
7907     for (i = 0; i < XVECLEN (par, 0); i++)
7908       {
7909         HOST_WIDE_INT offset = 0;
7910         rtx reg = XEXP (XVECEXP (par, 0, i), 0);
7912         if (size != 0)
7913           emit_move_insn (addr, plus_constant (addr, size));
7915         mem = change_address (mem, GET_MODE (reg), NULL);
7916         if (REGNO (reg) == R0_REGNUM)
7917           {
7918             /* On thumb we have to use a write-back instruction.  */
7919             emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
7920                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7921             size = TARGET_ARM ? 16 : 0;
7922           }
7923         else
7924           {
7925             emit_move_insn (mem, reg);
7926             size = GET_MODE_SIZE (GET_MODE (reg));
7927           }
7928       }
7930     /* The optimizer does not know that the call sets the function value
7931        registers we stored in the result block.  We avoid problems by
7932        claiming that all hard registers are used and clobbered at this
7933        point.  */
7934     emit_insn (gen_blockage ());
7936     DONE;
7937   }"
7940 (define_expand "untyped_return"
7941   [(match_operand:BLK 0 "memory_operand" "")
7942    (match_operand 1 "" "")]
7943   "TARGET_EITHER"
7944   "
7945   {
7946     int i;
7947     rtx addr = gen_reg_rtx (Pmode);
7948     rtx mem;
7949     int size = 0;
7951     emit_move_insn (addr, XEXP (operands[0], 0));
7952     mem = change_address (operands[0], BLKmode, addr);
7954     for (i = 0; i < XVECLEN (operands[1], 0); i++)
7955       {
7956         HOST_WIDE_INT offset = 0;
7957         rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
7959         if (size != 0)
7960           emit_move_insn (addr, plus_constant (addr, size));
7962         mem = change_address (mem, GET_MODE (reg), NULL);
7963         if (REGNO (reg) == R0_REGNUM)
7964           {
7965             /* On thumb we have to use a write-back instruction.  */
7966             emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
7967                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7968             size = TARGET_ARM ? 16 : 0;
7969           }
7970         else
7971           {
7972             emit_move_insn (reg, mem);
7973             size = GET_MODE_SIZE (GET_MODE (reg));
7974           }
7975       }
7977     /* Emit USE insns before the return.  */
7978     for (i = 0; i < XVECLEN (operands[1], 0); i++)
7979       emit_insn (gen_rtx_USE (VOIDmode,
7980                               SET_DEST (XVECEXP (operands[1], 0, i))));
7982     /* Construct the return.  */
7983     expand_naked_return ();
7985     DONE;
7986   }"
7989 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7990 ;; all of memory.  This blocks insns from being moved across this point.
7992 (define_insn "blockage"
7993   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
7994   "TARGET_EITHER"
7995   ""
7996   [(set_attr "length" "0")
7997    (set_attr "type" "block")]
8000 (define_expand "casesi"
8001   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
8002    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
8003    (match_operand:SI 2 "const_int_operand" "")  ; total range
8004    (match_operand:SI 3 "" "")                   ; table label
8005    (match_operand:SI 4 "" "")]                  ; Out of range label
8006   "TARGET_ARM"
8007   "
8008   {
8009     rtx reg;
8010     if (operands[1] != const0_rtx)
8011       {
8012         reg = gen_reg_rtx (SImode);
8014         emit_insn (gen_addsi3 (reg, operands[0],
8015                                GEN_INT (-INTVAL (operands[1]))));
8016         operands[0] = reg;
8017       }
8019     if (!const_ok_for_arm (INTVAL (operands[2])))
8020       operands[2] = force_reg (SImode, operands[2]);
8022     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
8023                                          operands[4]));
8024     DONE;
8025   }"
8028 ;; The USE in this pattern is needed to tell flow analysis that this is
8029 ;; a CASESI insn.  It has no other purpose.
8030 (define_insn "casesi_internal"
8031   [(parallel [(set (pc)
8032                (if_then_else
8033                 (leu (match_operand:SI 0 "s_register_operand" "r")
8034                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
8035                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8036                                  (label_ref (match_operand 2 "" ""))))
8037                 (label_ref (match_operand 3 "" ""))))
8038               (clobber (reg:CC CC_REGNUM))
8039               (use (label_ref (match_dup 2)))])]
8040   "TARGET_ARM"
8041   "*
8042     if (flag_pic)
8043       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8044     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8045   "
8046   [(set_attr "conds" "clob")
8047    (set_attr "length" "12")]
8050 (define_expand "indirect_jump"
8051   [(set (pc)
8052         (match_operand:SI 0 "s_register_operand" ""))]
8053   "TARGET_EITHER"
8054   ""
8057 ;; NB Never uses BX.
8058 (define_insn "*arm_indirect_jump"
8059   [(set (pc)
8060         (match_operand:SI 0 "s_register_operand" "r"))]
8061   "TARGET_ARM"
8062   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
8063   [(set_attr "predicable" "yes")]
8066 (define_insn "*load_indirect_jump"
8067   [(set (pc)
8068         (match_operand:SI 0 "memory_operand" "m"))]
8069   "TARGET_ARM"
8070   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
8071   [(set_attr "type" "load1")
8072    (set_attr "pool_range" "4096")
8073    (set_attr "neg_pool_range" "4084")
8074    (set_attr "predicable" "yes")]
8077 ;; NB Never uses BX.
8078 (define_insn "*thumb_indirect_jump"
8079   [(set (pc)
8080         (match_operand:SI 0 "register_operand" "l*r"))]
8081   "TARGET_THUMB"
8082   "mov\\tpc, %0"
8083   [(set_attr "conds" "clob")
8084    (set_attr "length" "2")]
8088 ;; Misc insns
8090 (define_insn "nop"
8091   [(const_int 0)]
8092   "TARGET_EITHER"
8093   "*
8094   if (TARGET_ARM)
8095     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8096   return  \"mov\\tr8, r8\";
8097   "
8098   [(set (attr "length")
8099         (if_then_else (eq_attr "is_thumb" "yes")
8100                       (const_int 2)
8101                       (const_int 4)))]
8105 ;; Patterns to allow combination of arithmetic, cond code and shifts
8107 (define_insn "*arith_shiftsi"
8108   [(set (match_operand:SI 0 "s_register_operand" "=r")
8109         (match_operator:SI 1 "shiftable_operator"
8110           [(match_operator:SI 3 "shift_operator"
8111              [(match_operand:SI 4 "s_register_operand" "r")
8112               (match_operand:SI 5 "reg_or_int_operand" "rI")])
8113            (match_operand:SI 2 "s_register_operand" "r")]))]
8114   "TARGET_ARM"
8115   "%i1%?\\t%0, %2, %4%S3"
8116   [(set_attr "predicable" "yes")
8117    (set_attr "shift" "4")
8118    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8119                       (const_string "alu_shift")
8120                       (const_string "alu_shift_reg")))]
8123 (define_split
8124   [(set (match_operand:SI 0 "s_register_operand" "")
8125         (match_operator:SI 1 "shiftable_operator"
8126          [(match_operator:SI 2 "shiftable_operator"
8127            [(match_operator:SI 3 "shift_operator"
8128              [(match_operand:SI 4 "s_register_operand" "")
8129               (match_operand:SI 5 "reg_or_int_operand" "")])
8130             (match_operand:SI 6 "s_register_operand" "")])
8131           (match_operand:SI 7 "arm_rhs_operand" "")]))
8132    (clobber (match_operand:SI 8 "s_register_operand" ""))]
8133   "TARGET_ARM"
8134   [(set (match_dup 8)
8135         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8136                          (match_dup 6)]))
8137    (set (match_dup 0)
8138         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8139   "")
8141 (define_insn "*arith_shiftsi_compare0"
8142   [(set (reg:CC_NOOV CC_REGNUM)
8143         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8144                           [(match_operator:SI 3 "shift_operator"
8145                             [(match_operand:SI 4 "s_register_operand" "r")
8146                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8147                            (match_operand:SI 2 "s_register_operand" "r")])
8148                          (const_int 0)))
8149    (set (match_operand:SI 0 "s_register_operand" "=r")
8150         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8151                          (match_dup 2)]))]
8152   "TARGET_ARM"
8153   "%i1%?s\\t%0, %2, %4%S3"
8154   [(set_attr "conds" "set")
8155    (set_attr "shift" "4")
8156    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8157                       (const_string "alu_shift")
8158                       (const_string "alu_shift_reg")))]
8161 (define_insn "*arith_shiftsi_compare0_scratch"
8162   [(set (reg:CC_NOOV CC_REGNUM)
8163         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8164                           [(match_operator:SI 3 "shift_operator"
8165                             [(match_operand:SI 4 "s_register_operand" "r")
8166                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8167                            (match_operand:SI 2 "s_register_operand" "r")])
8168                          (const_int 0)))
8169    (clobber (match_scratch:SI 0 "=r"))]
8170   "TARGET_ARM"
8171   "%i1%?s\\t%0, %2, %4%S3"
8172   [(set_attr "conds" "set")
8173    (set_attr "shift" "4")
8174    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8175                       (const_string "alu_shift")
8176                       (const_string "alu_shift_reg")))]
8179 (define_insn "*sub_shiftsi"
8180   [(set (match_operand:SI 0 "s_register_operand" "=r")
8181         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8182                   (match_operator:SI 2 "shift_operator"
8183                    [(match_operand:SI 3 "s_register_operand" "r")
8184                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
8185   "TARGET_ARM"
8186   "sub%?\\t%0, %1, %3%S2"
8187   [(set_attr "predicable" "yes")
8188    (set_attr "shift" "3")
8189    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8190                       (const_string "alu_shift")
8191                       (const_string "alu_shift_reg")))]
8194 (define_insn "*sub_shiftsi_compare0"
8195   [(set (reg:CC_NOOV CC_REGNUM)
8196         (compare:CC_NOOV
8197          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8198                    (match_operator:SI 2 "shift_operator"
8199                     [(match_operand:SI 3 "s_register_operand" "r")
8200                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8201          (const_int 0)))
8202    (set (match_operand:SI 0 "s_register_operand" "=r")
8203         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8204                                                  (match_dup 4)])))]
8205   "TARGET_ARM"
8206   "sub%?s\\t%0, %1, %3%S2"
8207   [(set_attr "conds" "set")
8208    (set_attr "shift" "3")
8209    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8210                       (const_string "alu_shift")
8211                       (const_string "alu_shift_reg")))]
8214 (define_insn "*sub_shiftsi_compare0_scratch"
8215   [(set (reg:CC_NOOV CC_REGNUM)
8216         (compare:CC_NOOV
8217          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8218                    (match_operator:SI 2 "shift_operator"
8219                     [(match_operand:SI 3 "s_register_operand" "r")
8220                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8221          (const_int 0)))
8222    (clobber (match_scratch:SI 0 "=r"))]
8223   "TARGET_ARM"
8224   "sub%?s\\t%0, %1, %3%S2"
8225   [(set_attr "conds" "set")
8226    (set_attr "shift" "3")
8227    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8228                       (const_string "alu_shift")
8229                       (const_string "alu_shift_reg")))]
8234 (define_insn "*and_scc"
8235   [(set (match_operand:SI 0 "s_register_operand" "=r")
8236         (and:SI (match_operator:SI 1 "arm_comparison_operator"
8237                  [(match_operand 3 "cc_register" "") (const_int 0)])
8238                 (match_operand:SI 2 "s_register_operand" "r")))]
8239   "TARGET_ARM"
8240   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8241   [(set_attr "conds" "use")
8242    (set_attr "length" "8")]
8245 (define_insn "*ior_scc"
8246   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8247         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8248                  [(match_operand 3 "cc_register" "") (const_int 0)])
8249                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8250   "TARGET_ARM"
8251   "@
8252    orr%d2\\t%0, %1, #1
8253    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8254   [(set_attr "conds" "use")
8255    (set_attr "length" "4,8")]
8258 (define_insn "*compare_scc"
8259   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8260         (match_operator:SI 1 "arm_comparison_operator"
8261          [(match_operand:SI 2 "s_register_operand" "r,r")
8262           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8263    (clobber (reg:CC CC_REGNUM))]
8264   "TARGET_ARM"
8265   "*
8266     if (operands[3] == const0_rtx)
8267       {
8268         if (GET_CODE (operands[1]) == LT)
8269           return \"mov\\t%0, %2, lsr #31\";
8271         if (GET_CODE (operands[1]) == GE)
8272           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8274         if (GET_CODE (operands[1]) == EQ)
8275           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8276       }
8278     if (GET_CODE (operands[1]) == NE)
8279       {
8280         if (which_alternative == 1)
8281           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8282         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8283       }
8284     if (which_alternative == 1)
8285       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8286     else
8287       output_asm_insn (\"cmp\\t%2, %3\", operands);
8288     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8289   "
8290   [(set_attr "conds" "clob")
8291    (set_attr "length" "12")]
8294 (define_insn "*cond_move"
8295   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8296         (if_then_else:SI (match_operator 3 "equality_operator"
8297                           [(match_operator 4 "arm_comparison_operator"
8298                             [(match_operand 5 "cc_register" "") (const_int 0)])
8299                            (const_int 0)])
8300                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8301                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8302   "TARGET_ARM"
8303   "*
8304     if (GET_CODE (operands[3]) == NE)
8305       {
8306         if (which_alternative != 1)
8307           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8308         if (which_alternative != 0)
8309           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8310         return \"\";
8311       }
8312     if (which_alternative != 0)
8313       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8314     if (which_alternative != 1)
8315       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8316     return \"\";
8317   "
8318   [(set_attr "conds" "use")
8319    (set_attr "length" "4,4,8")]
8322 (define_insn "*cond_arith"
8323   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8324         (match_operator:SI 5 "shiftable_operator" 
8325          [(match_operator:SI 4 "arm_comparison_operator"
8326            [(match_operand:SI 2 "s_register_operand" "r,r")
8327             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8328           (match_operand:SI 1 "s_register_operand" "0,?r")]))
8329    (clobber (reg:CC CC_REGNUM))]
8330   "TARGET_ARM"
8331   "*
8332     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8333       return \"%i5\\t%0, %1, %2, lsr #31\";
8335     output_asm_insn (\"cmp\\t%2, %3\", operands);
8336     if (GET_CODE (operands[5]) == AND)
8337       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8338     else if (GET_CODE (operands[5]) == MINUS)
8339       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8340     else if (which_alternative != 0)
8341       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8342     return \"%i5%d4\\t%0, %1, #1\";
8343   "
8344   [(set_attr "conds" "clob")
8345    (set_attr "length" "12")]
8348 (define_insn "*cond_sub"
8349   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8350         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8351                   (match_operator:SI 4 "arm_comparison_operator"
8352                    [(match_operand:SI 2 "s_register_operand" "r,r")
8353                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8354    (clobber (reg:CC CC_REGNUM))]
8355   "TARGET_ARM"
8356   "*
8357     output_asm_insn (\"cmp\\t%2, %3\", operands);
8358     if (which_alternative != 0)
8359       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8360     return \"sub%d4\\t%0, %1, #1\";
8361   "
8362   [(set_attr "conds" "clob")
8363    (set_attr "length" "8,12")]
8366 (define_insn "*cmp_ite0"
8367   [(set (match_operand 6 "dominant_cc_register" "")
8368         (compare
8369          (if_then_else:SI
8370           (match_operator 4 "arm_comparison_operator"
8371            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8372             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8373           (match_operator:SI 5 "arm_comparison_operator"
8374            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8375             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8376           (const_int 0))
8377          (const_int 0)))]
8378   "TARGET_ARM"
8379   "*
8380   {
8381     static const char * const opcodes[4][2] =
8382     {
8383       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8384        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8385       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8386        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8387       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8388        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8389       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8390        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8391     };
8392     int swap =
8393       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8395     return opcodes[which_alternative][swap];
8396   }"
8397   [(set_attr "conds" "set")
8398    (set_attr "length" "8")]
8401 (define_insn "*cmp_ite1"
8402   [(set (match_operand 6 "dominant_cc_register" "")
8403         (compare
8404          (if_then_else:SI
8405           (match_operator 4 "arm_comparison_operator"
8406            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8407             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8408           (match_operator:SI 5 "arm_comparison_operator"
8409            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8410             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8411           (const_int 1))
8412          (const_int 0)))]
8413   "TARGET_ARM"
8414   "*
8415   {
8416     static const char * const opcodes[4][2] =
8417     {
8418       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8419        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8420       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8421        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8422       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8423        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8424       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8425        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8426     };
8427     int swap =
8428       comparison_dominates_p (GET_CODE (operands[5]),
8429                               reverse_condition (GET_CODE (operands[4])));
8431     return opcodes[which_alternative][swap];
8432   }"
8433   [(set_attr "conds" "set")
8434    (set_attr "length" "8")]
8437 (define_insn "*cmp_and"
8438   [(set (match_operand 6 "dominant_cc_register" "")
8439         (compare
8440          (and:SI
8441           (match_operator 4 "arm_comparison_operator"
8442            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8443             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8444           (match_operator:SI 5 "arm_comparison_operator"
8445            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8446             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8447          (const_int 0)))]
8448   "TARGET_ARM"
8449   "*
8450   {
8451     static const char *const opcodes[4][2] =
8452     {
8453       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8454        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8455       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8456        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8457       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8458        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8459       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8460        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8461     };
8462     int swap =
8463       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8465     return opcodes[which_alternative][swap];
8466   }"
8467   [(set_attr "conds" "set")
8468    (set_attr "predicable" "no")
8469    (set_attr "length" "8")]
8472 (define_insn "*cmp_ior"
8473   [(set (match_operand 6 "dominant_cc_register" "")
8474         (compare
8475          (ior:SI
8476           (match_operator 4 "arm_comparison_operator"
8477            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8478             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8479           (match_operator:SI 5 "arm_comparison_operator"
8480            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8481             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8482          (const_int 0)))]
8483   "TARGET_ARM"
8484   "*
8486   static const char *const opcodes[4][2] =
8487   {
8488     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8489      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8490     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8491      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8492     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8493      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8494     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8495      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8496   };
8497   int swap =
8498     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8500   return opcodes[which_alternative][swap];
8503   [(set_attr "conds" "set")
8504    (set_attr "length" "8")]
8507 (define_insn_and_split "*ior_scc_scc"
8508   [(set (match_operand:SI 0 "s_register_operand" "=r")
8509         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8510                  [(match_operand:SI 1 "s_register_operand" "r")
8511                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8512                 (match_operator:SI 6 "arm_comparison_operator"
8513                  [(match_operand:SI 4 "s_register_operand" "r")
8514                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8515    (clobber (reg:CC CC_REGNUM))]
8516   "TARGET_ARM
8517    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8518        != CCmode)"
8519   "#"
8520   "TARGET_ARM && reload_completed"
8521   [(set (match_dup 7)
8522         (compare
8523          (ior:SI
8524           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8525           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8526          (const_int 0)))
8527    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8528   "operands[7]
8529      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8530                                                   DOM_CC_X_OR_Y),
8531                     CC_REGNUM);"
8532   [(set_attr "conds" "clob")
8533    (set_attr "length" "16")])
8535 ; If the above pattern is followed by a CMP insn, then the compare is 
8536 ; redundant, since we can rework the conditional instruction that follows.
8537 (define_insn_and_split "*ior_scc_scc_cmp"
8538   [(set (match_operand 0 "dominant_cc_register" "")
8539         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8540                           [(match_operand:SI 1 "s_register_operand" "r")
8541                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8542                          (match_operator:SI 6 "arm_comparison_operator"
8543                           [(match_operand:SI 4 "s_register_operand" "r")
8544                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8545                  (const_int 0)))
8546    (set (match_operand:SI 7 "s_register_operand" "=r")
8547         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8548                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8549   "TARGET_ARM"
8550   "#"
8551   "TARGET_ARM && reload_completed"
8552   [(set (match_dup 0)
8553         (compare
8554          (ior:SI
8555           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8556           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8557          (const_int 0)))
8558    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8559   ""
8560   [(set_attr "conds" "set")
8561    (set_attr "length" "16")])
8563 (define_insn_and_split "*and_scc_scc"
8564   [(set (match_operand:SI 0 "s_register_operand" "=r")
8565         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8566                  [(match_operand:SI 1 "s_register_operand" "r")
8567                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8568                 (match_operator:SI 6 "arm_comparison_operator"
8569                  [(match_operand:SI 4 "s_register_operand" "r")
8570                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8571    (clobber (reg:CC CC_REGNUM))]
8572   "TARGET_ARM
8573    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8574        != CCmode)"
8575   "#"
8576   "TARGET_ARM && reload_completed
8577    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8578        != CCmode)"
8579   [(set (match_dup 7)
8580         (compare
8581          (and:SI
8582           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8583           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8584          (const_int 0)))
8585    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8586   "operands[7]
8587      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8588                                                   DOM_CC_X_AND_Y),
8589                     CC_REGNUM);"
8590   [(set_attr "conds" "clob")
8591    (set_attr "length" "16")])
8593 ; If the above pattern is followed by a CMP insn, then the compare is 
8594 ; redundant, since we can rework the conditional instruction that follows.
8595 (define_insn_and_split "*and_scc_scc_cmp"
8596   [(set (match_operand 0 "dominant_cc_register" "")
8597         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8598                           [(match_operand:SI 1 "s_register_operand" "r")
8599                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8600                          (match_operator:SI 6 "arm_comparison_operator"
8601                           [(match_operand:SI 4 "s_register_operand" "r")
8602                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8603                  (const_int 0)))
8604    (set (match_operand:SI 7 "s_register_operand" "=r")
8605         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8606                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8607   "TARGET_ARM"
8608   "#"
8609   "TARGET_ARM && reload_completed"
8610   [(set (match_dup 0)
8611         (compare
8612          (and:SI
8613           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8614           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8615          (const_int 0)))
8616    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8617   ""
8618   [(set_attr "conds" "set")
8619    (set_attr "length" "16")])
8621 ;; If there is no dominance in the comparison, then we can still save an
8622 ;; instruction in the AND case, since we can know that the second compare
8623 ;; need only zero the value if false (if true, then the value is already
8624 ;; correct).
8625 (define_insn_and_split "*and_scc_scc_nodom"
8626   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8627         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8628                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
8629                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8630                 (match_operator:SI 6 "arm_comparison_operator"
8631                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
8632                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8633    (clobber (reg:CC CC_REGNUM))]
8634   "TARGET_ARM
8635    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8636        == CCmode)"
8637   "#"
8638   "TARGET_ARM && reload_completed"
8639   [(parallel [(set (match_dup 0)
8640                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8641               (clobber (reg:CC CC_REGNUM))])
8642    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8643    (set (match_dup 0)
8644         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8645                          (match_dup 0)
8646                          (const_int 0)))]
8647   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8648                                               operands[4], operands[5]),
8649                               CC_REGNUM);
8650    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8651                                   operands[5]);"
8652   [(set_attr "conds" "clob")
8653    (set_attr "length" "20")])
8655 (define_split
8656   [(set (reg:CC_NOOV CC_REGNUM)
8657         (compare:CC_NOOV (ior:SI
8658                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8659                                   (const_int 1))
8660                           (match_operator:SI 1 "comparison_operator"
8661                            [(match_operand:SI 2 "s_register_operand" "")
8662                             (match_operand:SI 3 "arm_add_operand" "")]))
8663                          (const_int 0)))
8664    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8665   "TARGET_ARM"
8666   [(set (match_dup 4)
8667         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8668                 (match_dup 0)))
8669    (set (reg:CC_NOOV CC_REGNUM)
8670         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8671                          (const_int 0)))]
8672   "")
8674 (define_split
8675   [(set (reg:CC_NOOV CC_REGNUM)
8676         (compare:CC_NOOV (ior:SI
8677                           (match_operator:SI 1 "comparison_operator"
8678                            [(match_operand:SI 2 "s_register_operand" "")
8679                             (match_operand:SI 3 "arm_add_operand" "")])
8680                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8681                                   (const_int 1)))
8682                          (const_int 0)))
8683    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8684   "TARGET_ARM"
8685   [(set (match_dup 4)
8686         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8687                 (match_dup 0)))
8688    (set (reg:CC_NOOV CC_REGNUM)
8689         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8690                          (const_int 0)))]
8691   "")
8693 (define_insn "*negscc"
8694   [(set (match_operand:SI 0 "s_register_operand" "=r")
8695         (neg:SI (match_operator 3 "arm_comparison_operator"
8696                  [(match_operand:SI 1 "s_register_operand" "r")
8697                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8698    (clobber (reg:CC CC_REGNUM))]
8699   "TARGET_ARM"
8700   "*
8701   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8702     return \"mov\\t%0, %1, asr #31\";
8704   if (GET_CODE (operands[3]) == NE)
8705     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8707   if (GET_CODE (operands[3]) == GT)
8708     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8710   output_asm_insn (\"cmp\\t%1, %2\", operands);
8711   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8712   return \"mvn%d3\\t%0, #0\";
8713   "
8714   [(set_attr "conds" "clob")
8715    (set_attr "length" "12")]
8718 (define_insn "movcond"
8719   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8720         (if_then_else:SI
8721          (match_operator 5 "arm_comparison_operator"
8722           [(match_operand:SI 3 "s_register_operand" "r,r,r")
8723            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8724          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8725          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8726    (clobber (reg:CC CC_REGNUM))]
8727   "TARGET_ARM"
8728   "*
8729   if (GET_CODE (operands[5]) == LT
8730       && (operands[4] == const0_rtx))
8731     {
8732       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8733         {
8734           if (operands[2] == const0_rtx)
8735             return \"and\\t%0, %1, %3, asr #31\";
8736           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8737         }
8738       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8739         {
8740           if (operands[1] == const0_rtx)
8741             return \"bic\\t%0, %2, %3, asr #31\";
8742           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8743         }
8744       /* The only case that falls through to here is when both ops 1 & 2
8745          are constants.  */
8746     }
8748   if (GET_CODE (operands[5]) == GE
8749       && (operands[4] == const0_rtx))
8750     {
8751       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8752         {
8753           if (operands[2] == const0_rtx)
8754             return \"bic\\t%0, %1, %3, asr #31\";
8755           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8756         }
8757       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8758         {
8759           if (operands[1] == const0_rtx)
8760             return \"and\\t%0, %2, %3, asr #31\";
8761           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8762         }
8763       /* The only case that falls through to here is when both ops 1 & 2
8764          are constants.  */
8765     }
8766   if (GET_CODE (operands[4]) == CONST_INT
8767       && !const_ok_for_arm (INTVAL (operands[4])))
8768     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8769   else
8770     output_asm_insn (\"cmp\\t%3, %4\", operands);
8771   if (which_alternative != 0)
8772     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8773   if (which_alternative != 1)
8774     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8775   return \"\";
8776   "
8777   [(set_attr "conds" "clob")
8778    (set_attr "length" "8,8,12")]
8781 (define_insn "*ifcompare_plus_move"
8782   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8783         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8784                           [(match_operand:SI 4 "s_register_operand" "r,r")
8785                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8786                          (plus:SI
8787                           (match_operand:SI 2 "s_register_operand" "r,r")
8788                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8789                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8790    (clobber (reg:CC CC_REGNUM))]
8791   "TARGET_ARM"
8792   "#"
8793   [(set_attr "conds" "clob")
8794    (set_attr "length" "8,12")]
8797 (define_insn "*if_plus_move"
8798   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8799         (if_then_else:SI
8800          (match_operator 4 "arm_comparison_operator"
8801           [(match_operand 5 "cc_register" "") (const_int 0)])
8802          (plus:SI
8803           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8804           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8805          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8806   "TARGET_ARM"
8807   "@
8808    add%d4\\t%0, %2, %3
8809    sub%d4\\t%0, %2, #%n3
8810    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8811    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8812   [(set_attr "conds" "use")
8813    (set_attr "length" "4,4,8,8")
8814    (set_attr "type" "*,*,*,*")]
8817 (define_insn "*ifcompare_move_plus"
8818   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8819         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8820                           [(match_operand:SI 4 "s_register_operand" "r,r")
8821                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8822                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8823                          (plus:SI
8824                           (match_operand:SI 2 "s_register_operand" "r,r")
8825                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8826    (clobber (reg:CC CC_REGNUM))]
8827   "TARGET_ARM"
8828   "#"
8829   [(set_attr "conds" "clob")
8830    (set_attr "length" "8,12")]
8833 (define_insn "*if_move_plus"
8834   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8835         (if_then_else:SI
8836          (match_operator 4 "arm_comparison_operator"
8837           [(match_operand 5 "cc_register" "") (const_int 0)])
8838          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8839          (plus:SI
8840           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8841           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8842   "TARGET_ARM"
8843   "@
8844    add%D4\\t%0, %2, %3
8845    sub%D4\\t%0, %2, #%n3
8846    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8847    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8848   [(set_attr "conds" "use")
8849    (set_attr "length" "4,4,8,8")
8850    (set_attr "type" "*,*,*,*")]
8853 (define_insn "*ifcompare_arith_arith"
8854   [(set (match_operand:SI 0 "s_register_operand" "=r")
8855         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8856                           [(match_operand:SI 5 "s_register_operand" "r")
8857                            (match_operand:SI 6 "arm_add_operand" "rIL")])
8858                          (match_operator:SI 8 "shiftable_operator"
8859                           [(match_operand:SI 1 "s_register_operand" "r")
8860                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8861                          (match_operator:SI 7 "shiftable_operator"
8862                           [(match_operand:SI 3 "s_register_operand" "r")
8863                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8864    (clobber (reg:CC CC_REGNUM))]
8865   "TARGET_ARM"
8866   "#"
8867   [(set_attr "conds" "clob")
8868    (set_attr "length" "12")]
8871 (define_insn "*if_arith_arith"
8872   [(set (match_operand:SI 0 "s_register_operand" "=r")
8873         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8874                           [(match_operand 8 "cc_register" "") (const_int 0)])
8875                          (match_operator:SI 6 "shiftable_operator"
8876                           [(match_operand:SI 1 "s_register_operand" "r")
8877                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8878                          (match_operator:SI 7 "shiftable_operator"
8879                           [(match_operand:SI 3 "s_register_operand" "r")
8880                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8881   "TARGET_ARM"
8882   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8883   [(set_attr "conds" "use")
8884    (set_attr "length" "8")]
8887 (define_insn "*ifcompare_arith_move"
8888   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8889         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8890                           [(match_operand:SI 2 "s_register_operand" "r,r")
8891                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8892                          (match_operator:SI 7 "shiftable_operator"
8893                           [(match_operand:SI 4 "s_register_operand" "r,r")
8894                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8895                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8896    (clobber (reg:CC CC_REGNUM))]
8897   "TARGET_ARM"
8898   "*
8899   /* If we have an operation where (op x 0) is the identity operation and
8900      the conditional operator is LT or GE and we are comparing against zero and
8901      everything is in registers then we can do this in two instructions.  */
8902   if (operands[3] == const0_rtx
8903       && GET_CODE (operands[7]) != AND
8904       && GET_CODE (operands[5]) == REG
8905       && GET_CODE (operands[1]) == REG 
8906       && REGNO (operands[1]) == REGNO (operands[4])
8907       && REGNO (operands[4]) != REGNO (operands[0]))
8908     {
8909       if (GET_CODE (operands[6]) == LT)
8910         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8911       else if (GET_CODE (operands[6]) == GE)
8912         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8913     }
8914   if (GET_CODE (operands[3]) == CONST_INT
8915       && !const_ok_for_arm (INTVAL (operands[3])))
8916     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8917   else
8918     output_asm_insn (\"cmp\\t%2, %3\", operands);
8919   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8920   if (which_alternative != 0)
8921     return \"mov%D6\\t%0, %1\";
8922   return \"\";
8923   "
8924   [(set_attr "conds" "clob")
8925    (set_attr "length" "8,12")]
8928 (define_insn "*if_arith_move"
8929   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8930         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8931                           [(match_operand 6 "cc_register" "") (const_int 0)])
8932                          (match_operator:SI 5 "shiftable_operator"
8933                           [(match_operand:SI 2 "s_register_operand" "r,r")
8934                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8935                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8936   "TARGET_ARM"
8937   "@
8938    %I5%d4\\t%0, %2, %3
8939    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8940   [(set_attr "conds" "use")
8941    (set_attr "length" "4,8")
8942    (set_attr "type" "*,*")]
8945 (define_insn "*ifcompare_move_arith"
8946   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8947         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8948                           [(match_operand:SI 4 "s_register_operand" "r,r")
8949                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8950                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8951                          (match_operator:SI 7 "shiftable_operator"
8952                           [(match_operand:SI 2 "s_register_operand" "r,r")
8953                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8954    (clobber (reg:CC CC_REGNUM))]
8955   "TARGET_ARM"
8956   "*
8957   /* If we have an operation where (op x 0) is the identity operation and
8958      the conditional operator is LT or GE and we are comparing against zero and
8959      everything is in registers then we can do this in two instructions */
8960   if (operands[5] == const0_rtx
8961       && GET_CODE (operands[7]) != AND
8962       && GET_CODE (operands[3]) == REG
8963       && GET_CODE (operands[1]) == REG 
8964       && REGNO (operands[1]) == REGNO (operands[2])
8965       && REGNO (operands[2]) != REGNO (operands[0]))
8966     {
8967       if (GET_CODE (operands[6]) == GE)
8968         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8969       else if (GET_CODE (operands[6]) == LT)
8970         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8971     }
8973   if (GET_CODE (operands[5]) == CONST_INT
8974       && !const_ok_for_arm (INTVAL (operands[5])))
8975     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
8976   else
8977     output_asm_insn (\"cmp\\t%4, %5\", operands);
8979   if (which_alternative != 0)
8980     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
8981   return \"%I7%D6\\t%0, %2, %3\";
8982   "
8983   [(set_attr "conds" "clob")
8984    (set_attr "length" "8,12")]
8987 (define_insn "*if_move_arith"
8988   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8989         (if_then_else:SI
8990          (match_operator 4 "arm_comparison_operator"
8991           [(match_operand 6 "cc_register" "") (const_int 0)])
8992          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8993          (match_operator:SI 5 "shiftable_operator"
8994           [(match_operand:SI 2 "s_register_operand" "r,r")
8995            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
8996   "TARGET_ARM"
8997   "@
8998    %I5%D4\\t%0, %2, %3
8999    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
9000   [(set_attr "conds" "use")
9001    (set_attr "length" "4,8")
9002    (set_attr "type" "*,*")]
9005 (define_insn "*ifcompare_move_not"
9006   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9007         (if_then_else:SI
9008          (match_operator 5 "arm_comparison_operator"
9009           [(match_operand:SI 3 "s_register_operand" "r,r")
9010            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9011          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9012          (not:SI
9013           (match_operand:SI 2 "s_register_operand" "r,r"))))
9014    (clobber (reg:CC CC_REGNUM))]
9015   "TARGET_ARM"
9016   "#"
9017   [(set_attr "conds" "clob")
9018    (set_attr "length" "8,12")]
9021 (define_insn "*if_move_not"
9022   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9023         (if_then_else:SI
9024          (match_operator 4 "arm_comparison_operator"
9025           [(match_operand 3 "cc_register" "") (const_int 0)])
9026          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9027          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9028   "TARGET_ARM"
9029   "@
9030    mvn%D4\\t%0, %2
9031    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9032    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
9033   [(set_attr "conds" "use")
9034    (set_attr "length" "4,8,8")]
9037 (define_insn "*ifcompare_not_move"
9038   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9039         (if_then_else:SI 
9040          (match_operator 5 "arm_comparison_operator"
9041           [(match_operand:SI 3 "s_register_operand" "r,r")
9042            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9043          (not:SI
9044           (match_operand:SI 2 "s_register_operand" "r,r"))
9045          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9046    (clobber (reg:CC CC_REGNUM))]
9047   "TARGET_ARM"
9048   "#"
9049   [(set_attr "conds" "clob")
9050    (set_attr "length" "8,12")]
9053 (define_insn "*if_not_move"
9054   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9055         (if_then_else:SI
9056          (match_operator 4 "arm_comparison_operator"
9057           [(match_operand 3 "cc_register" "") (const_int 0)])
9058          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9059          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9060   "TARGET_ARM"
9061   "@
9062    mvn%d4\\t%0, %2
9063    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9064    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
9065   [(set_attr "conds" "use")
9066    (set_attr "length" "4,8,8")]
9069 (define_insn "*ifcompare_shift_move"
9070   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9071         (if_then_else:SI
9072          (match_operator 6 "arm_comparison_operator"
9073           [(match_operand:SI 4 "s_register_operand" "r,r")
9074            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9075          (match_operator:SI 7 "shift_operator"
9076           [(match_operand:SI 2 "s_register_operand" "r,r")
9077            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9078          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9079    (clobber (reg:CC CC_REGNUM))]
9080   "TARGET_ARM"
9081   "#"
9082   [(set_attr "conds" "clob")
9083    (set_attr "length" "8,12")]
9086 (define_insn "*if_shift_move"
9087   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9088         (if_then_else:SI
9089          (match_operator 5 "arm_comparison_operator"
9090           [(match_operand 6 "cc_register" "") (const_int 0)])
9091          (match_operator:SI 4 "shift_operator"
9092           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9093            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9094          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9095   "TARGET_ARM"
9096   "@
9097    mov%d5\\t%0, %2%S4
9098    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9099    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
9100   [(set_attr "conds" "use")
9101    (set_attr "shift" "2")
9102    (set_attr "length" "4,8,8")
9103    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9104                       (const_string "alu_shift")
9105                       (const_string "alu_shift_reg")))]
9108 (define_insn "*ifcompare_move_shift"
9109   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9110         (if_then_else:SI
9111          (match_operator 6 "arm_comparison_operator"
9112           [(match_operand:SI 4 "s_register_operand" "r,r")
9113            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9114          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9115          (match_operator:SI 7 "shift_operator"
9116           [(match_operand:SI 2 "s_register_operand" "r,r")
9117            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
9118    (clobber (reg:CC CC_REGNUM))]
9119   "TARGET_ARM"
9120   "#"
9121   [(set_attr "conds" "clob")
9122    (set_attr "length" "8,12")]
9125 (define_insn "*if_move_shift"
9126   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9127         (if_then_else:SI
9128          (match_operator 5 "arm_comparison_operator"
9129           [(match_operand 6 "cc_register" "") (const_int 0)])
9130          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9131          (match_operator:SI 4 "shift_operator"
9132           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9133            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
9134   "TARGET_ARM"
9135   "@
9136    mov%D5\\t%0, %2%S4
9137    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9138    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
9139   [(set_attr "conds" "use")
9140    (set_attr "shift" "2")
9141    (set_attr "length" "4,8,8")
9142    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9143                       (const_string "alu_shift")
9144                       (const_string "alu_shift_reg")))]
9147 (define_insn "*ifcompare_shift_shift"
9148   [(set (match_operand:SI 0 "s_register_operand" "=r")
9149         (if_then_else:SI
9150          (match_operator 7 "arm_comparison_operator"
9151           [(match_operand:SI 5 "s_register_operand" "r")
9152            (match_operand:SI 6 "arm_add_operand" "rIL")])
9153          (match_operator:SI 8 "shift_operator"
9154           [(match_operand:SI 1 "s_register_operand" "r")
9155            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9156          (match_operator:SI 9 "shift_operator"
9157           [(match_operand:SI 3 "s_register_operand" "r")
9158            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
9159    (clobber (reg:CC CC_REGNUM))]
9160   "TARGET_ARM"
9161   "#"
9162   [(set_attr "conds" "clob")
9163    (set_attr "length" "12")]
9166 (define_insn "*if_shift_shift"
9167   [(set (match_operand:SI 0 "s_register_operand" "=r")
9168         (if_then_else:SI
9169          (match_operator 5 "arm_comparison_operator"
9170           [(match_operand 8 "cc_register" "") (const_int 0)])
9171          (match_operator:SI 6 "shift_operator"
9172           [(match_operand:SI 1 "s_register_operand" "r")
9173            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9174          (match_operator:SI 7 "shift_operator"
9175           [(match_operand:SI 3 "s_register_operand" "r")
9176            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
9177   "TARGET_ARM"
9178   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
9179   [(set_attr "conds" "use")
9180    (set_attr "shift" "1")
9181    (set_attr "length" "8")
9182    (set (attr "type") (if_then_else
9183                         (and (match_operand 2 "const_int_operand" "")
9184                              (match_operand 4 "const_int_operand" ""))
9185                       (const_string "alu_shift")
9186                       (const_string "alu_shift_reg")))]
9189 (define_insn "*ifcompare_not_arith"
9190   [(set (match_operand:SI 0 "s_register_operand" "=r")
9191         (if_then_else:SI
9192          (match_operator 6 "arm_comparison_operator"
9193           [(match_operand:SI 4 "s_register_operand" "r")
9194            (match_operand:SI 5 "arm_add_operand" "rIL")])
9195          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9196          (match_operator:SI 7 "shiftable_operator"
9197           [(match_operand:SI 2 "s_register_operand" "r")
9198            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
9199    (clobber (reg:CC CC_REGNUM))]
9200   "TARGET_ARM"
9201   "#"
9202   [(set_attr "conds" "clob")
9203    (set_attr "length" "12")]
9206 (define_insn "*if_not_arith"
9207   [(set (match_operand:SI 0 "s_register_operand" "=r")
9208         (if_then_else:SI
9209          (match_operator 5 "arm_comparison_operator"
9210           [(match_operand 4 "cc_register" "") (const_int 0)])
9211          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9212          (match_operator:SI 6 "shiftable_operator"
9213           [(match_operand:SI 2 "s_register_operand" "r")
9214            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
9215   "TARGET_ARM"
9216   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
9217   [(set_attr "conds" "use")
9218    (set_attr "length" "8")]
9221 (define_insn "*ifcompare_arith_not"
9222   [(set (match_operand:SI 0 "s_register_operand" "=r")
9223         (if_then_else:SI
9224          (match_operator 6 "arm_comparison_operator"
9225           [(match_operand:SI 4 "s_register_operand" "r")
9226            (match_operand:SI 5 "arm_add_operand" "rIL")])
9227          (match_operator:SI 7 "shiftable_operator"
9228           [(match_operand:SI 2 "s_register_operand" "r")
9229            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9230          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9231    (clobber (reg:CC CC_REGNUM))]
9232   "TARGET_ARM"
9233   "#"
9234   [(set_attr "conds" "clob")
9235    (set_attr "length" "12")]
9238 (define_insn "*if_arith_not"
9239   [(set (match_operand:SI 0 "s_register_operand" "=r")
9240         (if_then_else:SI
9241          (match_operator 5 "arm_comparison_operator"
9242           [(match_operand 4 "cc_register" "") (const_int 0)])
9243          (match_operator:SI 6 "shiftable_operator"
9244           [(match_operand:SI 2 "s_register_operand" "r")
9245            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9246          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9247   "TARGET_ARM"
9248   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9249   [(set_attr "conds" "use")
9250    (set_attr "length" "8")]
9253 (define_insn "*ifcompare_neg_move"
9254   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9255         (if_then_else:SI
9256          (match_operator 5 "arm_comparison_operator"
9257           [(match_operand:SI 3 "s_register_operand" "r,r")
9258            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9259          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9260          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9261    (clobber (reg:CC CC_REGNUM))]
9262   "TARGET_ARM"
9263   "#"
9264   [(set_attr "conds" "clob")
9265    (set_attr "length" "8,12")]
9268 (define_insn "*if_neg_move"
9269   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9270         (if_then_else:SI
9271          (match_operator 4 "arm_comparison_operator"
9272           [(match_operand 3 "cc_register" "") (const_int 0)])
9273          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9274          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9275   "TARGET_ARM"
9276   "@
9277    rsb%d4\\t%0, %2, #0
9278    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9279    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9280   [(set_attr "conds" "use")
9281    (set_attr "length" "4,8,8")]
9284 (define_insn "*ifcompare_move_neg"
9285   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9286         (if_then_else:SI
9287          (match_operator 5 "arm_comparison_operator"
9288           [(match_operand:SI 3 "s_register_operand" "r,r")
9289            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9290          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9291          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9292    (clobber (reg:CC CC_REGNUM))]
9293   "TARGET_ARM"
9294   "#"
9295   [(set_attr "conds" "clob")
9296    (set_attr "length" "8,12")]
9299 (define_insn "*if_move_neg"
9300   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9301         (if_then_else:SI
9302          (match_operator 4 "arm_comparison_operator"
9303           [(match_operand 3 "cc_register" "") (const_int 0)])
9304          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9305          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9306   "TARGET_ARM"
9307   "@
9308    rsb%D4\\t%0, %2, #0
9309    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9310    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9311   [(set_attr "conds" "use")
9312    (set_attr "length" "4,8,8")]
9315 (define_insn "*arith_adjacentmem"
9316   [(set (match_operand:SI 0 "s_register_operand" "=r")
9317         (match_operator:SI 1 "shiftable_operator"
9318          [(match_operand:SI 2 "memory_operand" "m")
9319           (match_operand:SI 3 "memory_operand" "m")]))
9320    (clobber (match_scratch:SI 4 "=r"))]
9321   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9322   "*
9323   {
9324     rtx ldm[3];
9325     rtx arith[4];
9326     rtx base_reg;
9327     HOST_WIDE_INT val1 = 0, val2 = 0;
9329     if (REGNO (operands[0]) > REGNO (operands[4]))
9330       {
9331         ldm[1] = operands[4];
9332         ldm[2] = operands[0];
9333       }
9334     else
9335       {
9336         ldm[1] = operands[0];
9337         ldm[2] = operands[4];
9338       }
9340     base_reg = XEXP (operands[2], 0);
9342     if (!REG_P (base_reg))
9343       {
9344         val1 = INTVAL (XEXP (base_reg, 1));
9345         base_reg = XEXP (base_reg, 0);
9346       }
9348     if (!REG_P (XEXP (operands[3], 0)))
9349       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9351     arith[0] = operands[0];
9352     arith[3] = operands[1];
9354     if (val1 < val2)
9355       {
9356         arith[1] = ldm[1];
9357         arith[2] = ldm[2];
9358       }
9359     else
9360       {
9361         arith[1] = ldm[2];
9362         arith[2] = ldm[1];
9363       }
9365     ldm[0] = base_reg;
9366     if (val1 !=0 && val2 != 0)
9367       {
9368         if (val1 == 4 || val2 == 4)
9369           /* Other val must be 8, since we know they are adjacent and neither
9370              is zero.  */
9371           output_asm_insn (\"ldm%?ib\\t%0, {%1, %2}\", ldm);
9372         else
9373           {
9374             rtx ops[3];
9376             ldm[0] = ops[0] = operands[4];
9377             ops[1] = base_reg;
9378             ops[2] = GEN_INT (val1);
9379             output_add_immediate (ops);
9380             if (val1 < val2)
9381               output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9382             else
9383               output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9384           }
9385       }
9386     else if (val1 != 0)
9387       {
9388         if (val1 < val2)
9389           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9390         else
9391           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9392       }
9393     else
9394       {
9395         if (val1 < val2)
9396           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9397         else
9398           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9399       }
9400     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9401     return \"\";
9402   }"
9403   [(set_attr "length" "12")
9404    (set_attr "predicable" "yes")
9405    (set_attr "type" "load1")]
9408 ;; the arm can support extended pre-inc instructions
9410 ;; In all these cases, we use operands 0 and 1 for the register being
9411 ;; incremented because those are the operands that local-alloc will
9412 ;; tie and these are the pair most likely to be tieable (and the ones
9413 ;; that will benefit the most).
9415 ;; We reject the frame pointer if it occurs anywhere in these patterns since
9416 ;; elimination will cause too many headaches.
9418 (define_insn "*strqi_preinc"
9419   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9420                          (match_operand:SI 2 "index_operand" "rJ")))
9421         (match_operand:QI 3 "s_register_operand" "r"))
9422    (set (match_operand:SI 0 "s_register_operand" "=r")
9423         (plus:SI (match_dup 1) (match_dup 2)))]
9424   "TARGET_ARM
9425    && !arm_eliminable_register (operands[0])
9426    && !arm_eliminable_register (operands[1])
9427    && !arm_eliminable_register (operands[2])"
9428   "str%?b\\t%3, [%0, %2]!"
9429   [(set_attr "type" "store1")
9430    (set_attr "predicable" "yes")]
9433 (define_insn "*strqi_predec"
9434   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9435                           (match_operand:SI 2 "s_register_operand" "r")))
9436         (match_operand:QI 3 "s_register_operand" "r"))
9437    (set (match_operand:SI 0 "s_register_operand" "=r")
9438         (minus:SI (match_dup 1) (match_dup 2)))]
9439   "TARGET_ARM
9440    && !arm_eliminable_register (operands[0])
9441    && !arm_eliminable_register (operands[1])
9442    && !arm_eliminable_register (operands[2])"
9443   "str%?b\\t%3, [%0, -%2]!"
9444   [(set_attr "type" "store1")
9445    (set_attr "predicable" "yes")]
9448 (define_insn "*loadqi_preinc"
9449   [(set (match_operand:QI 3 "s_register_operand" "=r")
9450         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9451                          (match_operand:SI 2 "index_operand" "rJ"))))
9452    (set (match_operand:SI 0 "s_register_operand" "=r")
9453         (plus:SI (match_dup 1) (match_dup 2)))]
9454   "TARGET_ARM
9455    && !arm_eliminable_register (operands[0])
9456    && !arm_eliminable_register (operands[1])
9457    && !arm_eliminable_register (operands[2])"
9458   "ldr%?b\\t%3, [%0, %2]!"
9459   [(set_attr "type" "load_byte")
9460    (set_attr "predicable" "yes")]
9463 (define_insn "*loadqi_predec"
9464   [(set (match_operand:QI 3 "s_register_operand" "=r")
9465         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9466                           (match_operand:SI 2 "s_register_operand" "r"))))
9467    (set (match_operand:SI 0 "s_register_operand" "=r")
9468         (minus:SI (match_dup 1) (match_dup 2)))]
9469   "TARGET_ARM
9470    && !arm_eliminable_register (operands[0])
9471    && !arm_eliminable_register (operands[1])
9472    && !arm_eliminable_register (operands[2])"
9473   "ldr%?b\\t%3, [%0, -%2]!"
9474   [(set_attr "type" "load_byte")
9475    (set_attr "predicable" "yes")]
9478 (define_insn "*loadqisi_preinc"
9479   [(set (match_operand:SI 3 "s_register_operand" "=r")
9480         (zero_extend:SI
9481          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9482                           (match_operand:SI 2 "index_operand" "rJ")))))
9483    (set (match_operand:SI 0 "s_register_operand" "=r")
9484         (plus:SI (match_dup 1) (match_dup 2)))]
9485   "TARGET_ARM
9486    && !arm_eliminable_register (operands[0])
9487    && !arm_eliminable_register (operands[1])
9488    && !arm_eliminable_register (operands[2])"
9489   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
9490   [(set_attr "type" "load_byte")
9491    (set_attr "predicable" "yes")]
9494 (define_insn "*loadqisi_predec"
9495   [(set (match_operand:SI 3 "s_register_operand" "=r")
9496         (zero_extend:SI
9497          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9498                            (match_operand:SI 2 "s_register_operand" "r")))))
9499    (set (match_operand:SI 0 "s_register_operand" "=r")
9500         (minus:SI (match_dup 1) (match_dup 2)))]
9501   "TARGET_ARM
9502    && !arm_eliminable_register (operands[0])
9503    && !arm_eliminable_register (operands[1])
9504    && !arm_eliminable_register (operands[2])"
9505   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
9506   [(set_attr "type" "load_byte")
9507    (set_attr "predicable" "yes")]
9510 (define_insn "*strsi_preinc"
9511   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9512                          (match_operand:SI 2 "index_operand" "rJ")))
9513         (match_operand:SI 3 "s_register_operand" "r"))
9514    (set (match_operand:SI 0 "s_register_operand" "=r")
9515         (plus:SI (match_dup 1) (match_dup 2)))]
9516   "TARGET_ARM
9517    && !arm_eliminable_register (operands[0])
9518    && !arm_eliminable_register (operands[1])
9519    && !arm_eliminable_register (operands[2])"
9520   "str%?\\t%3, [%0, %2]!"
9521   [(set_attr "type" "store1")
9522    (set_attr "predicable" "yes")]
9525 (define_insn "*strsi_predec"
9526   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9527                           (match_operand:SI 2 "s_register_operand" "r")))
9528         (match_operand:SI 3 "s_register_operand" "r"))
9529    (set (match_operand:SI 0 "s_register_operand" "=r")
9530         (minus:SI (match_dup 1) (match_dup 2)))]
9531   "TARGET_ARM
9532    && !arm_eliminable_register (operands[0])
9533    && !arm_eliminable_register (operands[1])
9534    && !arm_eliminable_register (operands[2])"
9535   "str%?\\t%3, [%0, -%2]!"
9536   [(set_attr "type" "store1")
9537    (set_attr "predicable" "yes")]
9540 (define_insn "*loadsi_preinc"
9541   [(set (match_operand:SI 3 "s_register_operand" "=r")
9542         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9543                          (match_operand:SI 2 "index_operand" "rJ"))))
9544    (set (match_operand:SI 0 "s_register_operand" "=r")
9545         (plus:SI (match_dup 1) (match_dup 2)))]
9546   "TARGET_ARM
9547    && !arm_eliminable_register (operands[0])
9548    && !arm_eliminable_register (operands[1])
9549    && !arm_eliminable_register (operands[2])"
9550   "ldr%?\\t%3, [%0, %2]!"
9551   [(set_attr "type" "load1")
9552    (set_attr "predicable" "yes")]
9555 (define_insn "*loadsi_predec"
9556   [(set (match_operand:SI 3 "s_register_operand" "=r")
9557         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9558                           (match_operand:SI 2 "s_register_operand" "r"))))
9559    (set (match_operand:SI 0 "s_register_operand" "=r")
9560         (minus:SI (match_dup 1) (match_dup 2)))]
9561   "TARGET_ARM
9562    && !arm_eliminable_register (operands[0])
9563    && !arm_eliminable_register (operands[1])
9564    && !arm_eliminable_register (operands[2])"
9565   "ldr%?\\t%3, [%0, -%2]!"
9566   [(set_attr "type" "load1")
9567    (set_attr "predicable" "yes")]
9570 (define_insn "*strqi_shiftpreinc"
9571   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9572                           [(match_operand:SI 3 "s_register_operand" "r")
9573                            (match_operand:SI 4 "const_shift_operand" "n")])
9574                          (match_operand:SI 1 "s_register_operand" "0")))
9575         (match_operand:QI 5 "s_register_operand" "r"))
9576    (set (match_operand:SI 0 "s_register_operand" "=r")
9577         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9578                  (match_dup 1)))]
9579   "TARGET_ARM
9580    && !arm_eliminable_register (operands[0])
9581    && !arm_eliminable_register (operands[1])
9582    && !arm_eliminable_register (operands[3])"
9583   "str%?b\\t%5, [%0, %3%S2]!"
9584   [(set_attr "type" "store1")
9585    (set_attr "predicable" "yes")]
9588 (define_insn "*strqi_shiftpredec"
9589   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9590                           (match_operator:SI 2 "shift_operator"
9591                            [(match_operand:SI 3 "s_register_operand" "r")
9592                             (match_operand:SI 4 "const_shift_operand" "n")])))
9593         (match_operand:QI 5 "s_register_operand" "r"))
9594    (set (match_operand:SI 0 "s_register_operand" "=r")
9595         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9596                                                  (match_dup 4)])))]
9597   "TARGET_ARM
9598    && !arm_eliminable_register (operands[0])
9599    && !arm_eliminable_register (operands[1])
9600    && !arm_eliminable_register (operands[3])"
9601   "str%?b\\t%5, [%0, -%3%S2]!"
9602   [(set_attr "type" "store1")
9603    (set_attr "predicable" "yes")]
9606 (define_insn "*loadqi_shiftpreinc"
9607   [(set (match_operand:QI 5 "s_register_operand" "=r")
9608         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9609                           [(match_operand:SI 3 "s_register_operand" "r")
9610                            (match_operand:SI 4 "const_shift_operand" "n")])
9611                          (match_operand:SI 1 "s_register_operand" "0"))))
9612    (set (match_operand:SI 0 "s_register_operand" "=r")
9613         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9614                  (match_dup 1)))]
9615   "TARGET_ARM
9616    && !arm_eliminable_register (operands[0])
9617    && !arm_eliminable_register (operands[1])
9618    && !arm_eliminable_register (operands[3])"
9619   "ldr%?b\\t%5, [%0, %3%S2]!"
9620   [(set_attr "type" "load_byte")
9621    (set_attr "predicable" "yes")]
9624 (define_insn "*loadqi_shiftpredec"
9625   [(set (match_operand:QI 5 "s_register_operand" "=r")
9626         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9627                           (match_operator:SI 2 "shift_operator"
9628                            [(match_operand:SI 3 "s_register_operand" "r")
9629                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9630    (set (match_operand:SI 0 "s_register_operand" "=r")
9631         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9632                                                  (match_dup 4)])))]
9633   "TARGET_ARM
9634    && !arm_eliminable_register (operands[0])
9635    && !arm_eliminable_register (operands[1])
9636    && !arm_eliminable_register (operands[3])"
9637   "ldr%?b\\t%5, [%0, -%3%S2]!"
9638   [(set_attr "type" "load_byte")
9639    (set_attr "predicable" "yes")]
9642 (define_insn "*strsi_shiftpreinc"
9643   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9644                           [(match_operand:SI 3 "s_register_operand" "r")
9645                            (match_operand:SI 4 "const_shift_operand" "n")])
9646                          (match_operand:SI 1 "s_register_operand" "0")))
9647         (match_operand:SI 5 "s_register_operand" "r"))
9648    (set (match_operand:SI 0 "s_register_operand" "=r")
9649         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9650                  (match_dup 1)))]
9651   "TARGET_ARM
9652    && !arm_eliminable_register (operands[0])
9653    && !arm_eliminable_register (operands[1])
9654    && !arm_eliminable_register (operands[3])"
9655   "str%?\\t%5, [%0, %3%S2]!"
9656   [(set_attr "type" "store1")
9657    (set_attr "predicable" "yes")]
9660 (define_insn "*strsi_shiftpredec"
9661   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9662                           (match_operator:SI 2 "shift_operator"
9663                            [(match_operand:SI 3 "s_register_operand" "r")
9664                             (match_operand:SI 4 "const_shift_operand" "n")])))
9665         (match_operand:SI 5 "s_register_operand" "r"))
9666    (set (match_operand:SI 0 "s_register_operand" "=r")
9667         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9668                                                  (match_dup 4)])))]
9669   "TARGET_ARM
9670    && !arm_eliminable_register (operands[0])
9671    && !arm_eliminable_register (operands[1])
9672    && !arm_eliminable_register (operands[3])"
9673   "str%?\\t%5, [%0, -%3%S2]!"
9674   [(set_attr "type" "store1")
9675    (set_attr "predicable" "yes")]
9678 (define_insn "*loadsi_shiftpreinc"
9679   [(set (match_operand:SI 5 "s_register_operand" "=r")
9680         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9681                           [(match_operand:SI 3 "s_register_operand" "r")
9682                            (match_operand:SI 4 "const_shift_operand" "n")])
9683                          (match_operand:SI 1 "s_register_operand" "0"))))
9684    (set (match_operand:SI 0 "s_register_operand" "=r")
9685         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9686                  (match_dup 1)))]
9687   "TARGET_ARM
9688    && !arm_eliminable_register (operands[0])
9689    && !arm_eliminable_register (operands[1])
9690    && !arm_eliminable_register (operands[3])"
9691   "ldr%?\\t%5, [%0, %3%S2]!"
9692   [(set_attr "type" "load1")
9693    (set_attr "predicable" "yes")]
9696 (define_insn "*loadsi_shiftpredec"
9697   [(set (match_operand:SI 5 "s_register_operand" "=r")
9698         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9699                           (match_operator:SI 2 "shift_operator"
9700                            [(match_operand:SI 3 "s_register_operand" "r")
9701                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9702    (set (match_operand:SI 0 "s_register_operand" "=r")
9703         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9704                                                  (match_dup 4)])))]
9705   "TARGET_ARM
9706    && !arm_eliminable_register (operands[0])
9707    && !arm_eliminable_register (operands[1])
9708    && !arm_eliminable_register (operands[3])"
9709   "ldr%?\\t%5, [%0, -%3%S2]!"
9710   [(set_attr "type" "load1")
9711    (set_attr "predicable" "yes")])
9713 ; It can also support extended post-inc expressions, but combine doesn't
9714 ; try these....
9715 ; It doesn't seem worth adding peepholes for anything but the most common
9716 ; cases since, unlike combine, the increment must immediately follow the load
9717 ; for this pattern to match.
9718 ; We must watch to see that the source/destination register isn't also the
9719 ; same as the base address register, and that if the index is a register,
9720 ; that it is not the same as the base address register.  In such cases the
9721 ; instruction that we would generate would have UNPREDICTABLE behavior so 
9722 ; we cannot use it.
9724 (define_peephole
9725   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9726         (match_operand:QI 2 "s_register_operand" "r"))
9727    (set (match_dup 0)
9728         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9729   "TARGET_ARM
9730    && (REGNO (operands[2]) != REGNO (operands[0]))
9731    && (GET_CODE (operands[1]) != REG
9732        || (REGNO (operands[1]) != REGNO (operands[0])))"
9733   "str%?b\\t%2, [%0], %1"
9736 (define_peephole
9737   [(set (match_operand:QI 0 "s_register_operand" "=r")
9738         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9739    (set (match_dup 1)
9740         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9741   "TARGET_ARM
9742    && REGNO (operands[0]) != REGNO(operands[1])
9743    && (GET_CODE (operands[2]) != REG
9744        || REGNO(operands[0]) != REGNO (operands[2]))"
9745   "ldr%?b\\t%0, [%1], %2"
9748 (define_peephole
9749   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9750         (match_operand:SI 2 "s_register_operand" "r"))
9751    (set (match_dup 0)
9752         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9753   "TARGET_ARM
9754    && (REGNO (operands[2]) != REGNO (operands[0]))
9755    && (GET_CODE (operands[1]) != REG
9756        || (REGNO (operands[1]) != REGNO (operands[0])))"
9757   "str%?\\t%2, [%0], %1"
9760 (define_peephole
9761   [(set (match_operand:SI 0 "s_register_operand" "=r")
9762         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9763    (set (match_dup 1)
9764         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9765   "TARGET_ARM
9766    && REGNO (operands[0]) != REGNO(operands[1])
9767    && (GET_CODE (operands[2]) != REG
9768        || REGNO(operands[0]) != REGNO (operands[2]))"
9769   "ldr%?\\t%0, [%1], %2"
9772 (define_peephole
9773   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9774                          (match_operand:SI 1 "index_operand" "rJ")))
9775         (match_operand:QI 2 "s_register_operand" "r"))
9776    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
9777   "TARGET_ARM
9778    && (REGNO (operands[2]) != REGNO (operands[0]))
9779    && (GET_CODE (operands[1]) != REG
9780        || (REGNO (operands[1]) != REGNO (operands[0])))"
9781   "str%?b\\t%2, [%0, %1]!"
9784 (define_peephole
9785   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9786                           [(match_operand:SI 0 "s_register_operand" "r")
9787                            (match_operand:SI 1 "const_int_operand" "n")])
9788                          (match_operand:SI 2 "s_register_operand" "+r")))
9789         (match_operand:QI 3 "s_register_operand" "r"))
9790    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9791                                (match_dup 2)))]
9792   "TARGET_ARM
9793    && (REGNO (operands[3]) != REGNO (operands[2]))
9794    && (REGNO (operands[0]) != REGNO (operands[2]))"
9795   "str%?b\\t%3, [%2, %0%S4]!"
9798 ; This pattern is never tried by combine, so do it as a peephole
9800 (define_peephole2
9801   [(set (match_operand:SI 0 "arm_general_register_operand" "")
9802         (match_operand:SI 1 "arm_general_register_operand" ""))
9803    (set (reg:CC CC_REGNUM)
9804         (compare:CC (match_dup 1) (const_int 0)))]
9805   "TARGET_ARM"
9806   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9807               (set (match_dup 0) (match_dup 1))])]
9808   ""
9811 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9812 ; reversed, check that the memory references aren't volatile.
9814 (define_peephole
9815   [(set (match_operand:SI 0 "s_register_operand" "=r")
9816         (match_operand:SI 4 "memory_operand" "m"))
9817    (set (match_operand:SI 1 "s_register_operand" "=r")
9818         (match_operand:SI 5 "memory_operand" "m"))
9819    (set (match_operand:SI 2 "s_register_operand" "=r")
9820         (match_operand:SI 6 "memory_operand" "m"))
9821    (set (match_operand:SI 3 "s_register_operand" "=r")
9822         (match_operand:SI 7 "memory_operand" "m"))]
9823   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9824   "*
9825   return emit_ldm_seq (operands, 4);
9826   "
9829 (define_peephole
9830   [(set (match_operand:SI 0 "s_register_operand" "=r")
9831         (match_operand:SI 3 "memory_operand" "m"))
9832    (set (match_operand:SI 1 "s_register_operand" "=r")
9833         (match_operand:SI 4 "memory_operand" "m"))
9834    (set (match_operand:SI 2 "s_register_operand" "=r")
9835         (match_operand:SI 5 "memory_operand" "m"))]
9836   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9837   "*
9838   return emit_ldm_seq (operands, 3);
9839   "
9842 (define_peephole
9843   [(set (match_operand:SI 0 "s_register_operand" "=r")
9844         (match_operand:SI 2 "memory_operand" "m"))
9845    (set (match_operand:SI 1 "s_register_operand" "=r")
9846         (match_operand:SI 3 "memory_operand" "m"))]
9847   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9848   "*
9849   return emit_ldm_seq (operands, 2);
9850   "
9853 (define_peephole
9854   [(set (match_operand:SI 4 "memory_operand" "=m")
9855         (match_operand:SI 0 "s_register_operand" "r"))
9856    (set (match_operand:SI 5 "memory_operand" "=m")
9857         (match_operand:SI 1 "s_register_operand" "r"))
9858    (set (match_operand:SI 6 "memory_operand" "=m")
9859         (match_operand:SI 2 "s_register_operand" "r"))
9860    (set (match_operand:SI 7 "memory_operand" "=m")
9861         (match_operand:SI 3 "s_register_operand" "r"))]
9862   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9863   "*
9864   return emit_stm_seq (operands, 4);
9865   "
9868 (define_peephole
9869   [(set (match_operand:SI 3 "memory_operand" "=m")
9870         (match_operand:SI 0 "s_register_operand" "r"))
9871    (set (match_operand:SI 4 "memory_operand" "=m")
9872         (match_operand:SI 1 "s_register_operand" "r"))
9873    (set (match_operand:SI 5 "memory_operand" "=m")
9874         (match_operand:SI 2 "s_register_operand" "r"))]
9875   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9876   "*
9877   return emit_stm_seq (operands, 3);
9878   "
9881 (define_peephole
9882   [(set (match_operand:SI 2 "memory_operand" "=m")
9883         (match_operand:SI 0 "s_register_operand" "r"))
9884    (set (match_operand:SI 3 "memory_operand" "=m")
9885         (match_operand:SI 1 "s_register_operand" "r"))]
9886   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9887   "*
9888   return emit_stm_seq (operands, 2);
9889   "
9892 (define_split
9893   [(set (match_operand:SI 0 "s_register_operand" "")
9894         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9895                        (const_int 0))
9896                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9897                          [(match_operand:SI 3 "s_register_operand" "")
9898                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
9899    (clobber (match_operand:SI 5 "s_register_operand" ""))]
9900   "TARGET_ARM"
9901   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9902    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9903                               (match_dup 5)))]
9904   ""
9907 ;; This split can be used because CC_Z mode implies that the following
9908 ;; branch will be an equality, or an unsigned inequality, so the sign
9909 ;; extension is not needed.
9911 (define_split
9912   [(set (reg:CC_Z CC_REGNUM)
9913         (compare:CC_Z
9914          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9915                     (const_int 24))
9916          (match_operand 1 "const_int_operand" "")))
9917    (clobber (match_scratch:SI 2 ""))]
9918   "TARGET_ARM
9919    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9920        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9921   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9922    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9923   "
9924   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9925   "
9928 (define_expand "prologue"
9929   [(clobber (const_int 0))]
9930   "TARGET_EITHER"
9931   "if (TARGET_ARM)
9932      arm_expand_prologue ();
9933    else
9934      thumb_expand_prologue ();
9935   DONE;
9936   "
9939 (define_expand "epilogue"
9940   [(clobber (const_int 0))]
9941   "TARGET_EITHER"
9942   "
9943   if (current_function_calls_eh_return)
9944     emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
9945   if (TARGET_THUMB)
9946     thumb_expand_epilogue ();
9947   else if (USE_RETURN_INSN (FALSE))
9948     {
9949       emit_jump_insn (gen_return ());
9950       DONE;
9951     }
9952   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9953         gen_rtvec (1,
9954                 gen_rtx_RETURN (VOIDmode)),
9955         VUNSPEC_EPILOGUE));
9956   DONE;
9957   "
9960 ;; Note - although unspec_volatile's USE all hard registers,
9961 ;; USEs are ignored after relaod has completed.  Thus we need
9962 ;; to add an unspec of the link register to ensure that flow
9963 ;; does not think that it is unused by the sibcall branch that
9964 ;; will replace the standard function epilogue.
9965 (define_insn "sibcall_epilogue"
9966   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9967               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9968   "TARGET_ARM"
9969   "*
9970   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9971     return output_return_instruction (const_true_rtx, FALSE, FALSE);
9972   return arm_output_epilogue (next_nonnote_insn (insn));
9973   "
9974 ;; Length is absolute worst case
9975   [(set_attr "length" "44")
9976    (set_attr "type" "block")
9977    ;; We don't clobber the conditions, but the potential length of this
9978    ;; operation is sufficient to make conditionalizing the sequence 
9979    ;; unlikely to be profitable.
9980    (set_attr "conds" "clob")]
9983 (define_insn "*epilogue_insns"
9984   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9985   "TARGET_EITHER"
9986   "*
9987   if (TARGET_ARM)
9988     return arm_output_epilogue (NULL);
9989   else /* TARGET_THUMB */
9990     return thumb_unexpanded_epilogue ();
9991   "
9992   ; Length is absolute worst case
9993   [(set_attr "length" "44")
9994    (set_attr "type" "block")
9995    ;; We don't clobber the conditions, but the potential length of this
9996    ;; operation is sufficient to make conditionalizing the sequence 
9997    ;; unlikely to be profitable.
9998    (set_attr "conds" "clob")]
10001 (define_expand "eh_epilogue"
10002   [(use (match_operand:SI 0 "register_operand" ""))
10003    (use (match_operand:SI 1 "register_operand" ""))
10004    (use (match_operand:SI 2 "register_operand" ""))]
10005   "TARGET_EITHER"
10006   "
10007   {
10008     cfun->machine->eh_epilogue_sp_ofs = operands[1];
10009     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10010       {
10011         rtx ra = gen_rtx_REG (Pmode, 2);
10013         emit_move_insn (ra, operands[2]);
10014         operands[2] = ra;
10015       }
10016     /* This is a hack -- we may have crystalized the function type too
10017        early.  */
10018     cfun->machine->func_type = 0;
10019   }"
10022 ;; This split is only used during output to reduce the number of patterns
10023 ;; that need assembler instructions adding to them.  We allowed the setting
10024 ;; of the conditions to be implicit during rtl generation so that
10025 ;; the conditional compare patterns would work.  However this conflicts to
10026 ;; some extent with the conditional data operations, so we have to split them
10027 ;; up again here.
10029 (define_split
10030   [(set (match_operand:SI 0 "s_register_operand" "")
10031         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10032                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10033                          (match_dup 0)
10034                          (match_operand 4 "" "")))
10035    (clobber (reg:CC CC_REGNUM))]
10036   "TARGET_ARM && reload_completed"
10037   [(set (match_dup 5) (match_dup 6))
10038    (cond_exec (match_dup 7)
10039               (set (match_dup 0) (match_dup 4)))]
10040   "
10041   {
10042     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10043                                              operands[2], operands[3]);
10044     enum rtx_code rc = GET_CODE (operands[1]);
10046     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10047     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10048     if (mode == CCFPmode || mode == CCFPEmode)
10049       rc = reverse_condition_maybe_unordered (rc);
10050     else
10051       rc = reverse_condition (rc);
10053     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10054   }"
10057 (define_split
10058   [(set (match_operand:SI 0 "s_register_operand" "")
10059         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10060                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10061                          (match_operand 4 "" "")
10062                          (match_dup 0)))
10063    (clobber (reg:CC CC_REGNUM))]
10064   "TARGET_ARM && reload_completed"
10065   [(set (match_dup 5) (match_dup 6))
10066    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10067               (set (match_dup 0) (match_dup 4)))]
10068   "
10069   {
10070     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10071                                              operands[2], operands[3]);
10073     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10074     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10075   }"
10078 (define_split
10079   [(set (match_operand:SI 0 "s_register_operand" "")
10080         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10081                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10082                          (match_operand 4 "" "")
10083                          (match_operand 5 "" "")))
10084    (clobber (reg:CC CC_REGNUM))]
10085   "TARGET_ARM && reload_completed"
10086   [(set (match_dup 6) (match_dup 7))
10087    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10088               (set (match_dup 0) (match_dup 4)))
10089    (cond_exec (match_dup 8)
10090               (set (match_dup 0) (match_dup 5)))]
10091   "
10092   {
10093     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10094                                              operands[2], operands[3]);
10095     enum rtx_code rc = GET_CODE (operands[1]);
10097     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10098     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10099     if (mode == CCFPmode || mode == CCFPEmode)
10100       rc = reverse_condition_maybe_unordered (rc);
10101     else
10102       rc = reverse_condition (rc);
10104     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10105   }"
10108 (define_split
10109   [(set (match_operand:SI 0 "s_register_operand" "")
10110         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10111                           [(match_operand:SI 2 "s_register_operand" "")
10112                            (match_operand:SI 3 "arm_add_operand" "")])
10113                          (match_operand:SI 4 "arm_rhs_operand" "")
10114                          (not:SI
10115                           (match_operand:SI 5 "s_register_operand" ""))))
10116    (clobber (reg:CC CC_REGNUM))]
10117   "TARGET_ARM && reload_completed"
10118   [(set (match_dup 6) (match_dup 7))
10119    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10120               (set (match_dup 0) (match_dup 4)))
10121    (cond_exec (match_dup 8)
10122               (set (match_dup 0) (not:SI (match_dup 5))))]
10123   "
10124   {
10125     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10126                                              operands[2], operands[3]);
10127     enum rtx_code rc = GET_CODE (operands[1]);
10129     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10130     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10131     if (mode == CCFPmode || mode == CCFPEmode)
10132       rc = reverse_condition_maybe_unordered (rc);
10133     else
10134       rc = reverse_condition (rc);
10136     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10137   }"
10140 (define_insn "*cond_move_not"
10141   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10142         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10143                           [(match_operand 3 "cc_register" "") (const_int 0)])
10144                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10145                          (not:SI
10146                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
10147   "TARGET_ARM"
10148   "@
10149    mvn%D4\\t%0, %2
10150    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
10151   [(set_attr "conds" "use")
10152    (set_attr "length" "4,8")]
10155 ;; The next two patterns occur when an AND operation is followed by a
10156 ;; scc insn sequence 
10158 (define_insn "*sign_extract_onebit"
10159   [(set (match_operand:SI 0 "s_register_operand" "=r")
10160         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10161                          (const_int 1)
10162                          (match_operand:SI 2 "const_int_operand" "n")))
10163     (clobber (reg:CC CC_REGNUM))]
10164   "TARGET_ARM"
10165   "*
10166     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10167     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10168     return \"mvnne\\t%0, #0\";
10169   "
10170   [(set_attr "conds" "clob")
10171    (set_attr "length" "8")]
10174 (define_insn "*not_signextract_onebit"
10175   [(set (match_operand:SI 0 "s_register_operand" "=r")
10176         (not:SI
10177          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10178                           (const_int 1)
10179                           (match_operand:SI 2 "const_int_operand" "n"))))
10180    (clobber (reg:CC CC_REGNUM))]
10181   "TARGET_ARM"
10182   "*
10183     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10184     output_asm_insn (\"tst\\t%1, %2\", operands);
10185     output_asm_insn (\"mvneq\\t%0, #0\", operands);
10186     return \"movne\\t%0, #0\";
10187   "
10188   [(set_attr "conds" "clob")
10189    (set_attr "length" "12")]
10192 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
10193 ;; expressions.  For simplicity, the first register is also in the unspec
10194 ;; part.
10195 (define_insn "*push_multi"
10196   [(match_parallel 2 "multi_register_push"
10197     [(set (match_operand:BLK 0 "memory_operand" "=m")
10198           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
10199                       UNSPEC_PUSH_MULT))])]
10200   "TARGET_ARM"
10201   "*
10202   {
10203     int num_saves = XVECLEN (operands[2], 0);
10204      
10205     /* For the StrongARM at least it is faster to
10206        use STR to store only a single register.  */
10207     if (num_saves == 1)
10208       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10209     else
10210       {
10211         int i;
10212         char pattern[100];
10214         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10216         for (i = 1; i < num_saves; i++)
10217           {
10218             strcat (pattern, \", %|\");
10219             strcat (pattern,
10220                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10221           }
10223         strcat (pattern, \"}\");
10224         output_asm_insn (pattern, operands);
10225       }
10227     return \"\";
10228   }"
10229   [(set_attr "type" "store4")]
10232 (define_insn "stack_tie"
10233   [(set (mem:BLK (scratch))
10234         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
10235                      (match_operand:SI 1 "s_register_operand" "r")]
10236                     UNSPEC_PRLG_STK))]
10237   ""
10238   ""
10239   [(set_attr "length" "0")]
10242 ;; Similarly for the floating point registers
10243 (define_insn "*push_fp_multi"
10244   [(match_parallel 2 "multi_register_push"
10245     [(set (match_operand:BLK 0 "memory_operand" "=m")
10246           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10247                       UNSPEC_PUSH_MULT))])]
10248   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
10249   "*
10250   {
10251     char pattern[100];
10253     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10254     output_asm_insn (pattern, operands);
10255     return \"\";
10256   }"
10257   [(set_attr "type" "f_store")]
10260 ;; Special patterns for dealing with the constant pool
10262 (define_insn "align_4"
10263   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10264   "TARGET_EITHER"
10265   "*
10266   assemble_align (32);
10267   return \"\";
10268   "
10271 (define_insn "align_8"
10272   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10273   "TARGET_EITHER"
10274   "*
10275   assemble_align (64);
10276   return \"\";
10277   "
10280 (define_insn "consttable_end"
10281   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10282   "TARGET_EITHER"
10283   "*
10284   making_const_table = FALSE;
10285   return \"\";
10286   "
10289 (define_insn "consttable_1"
10290   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10291   "TARGET_THUMB"
10292   "*
10293   making_const_table = TRUE;
10294   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10295   assemble_zeros (3);
10296   return \"\";
10297   "
10298   [(set_attr "length" "4")]
10301 (define_insn "consttable_2"
10302   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10303   "TARGET_THUMB"
10304   "*
10305   making_const_table = TRUE;
10306   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10307   assemble_zeros (2);
10308   return \"\";
10309   "
10310   [(set_attr "length" "4")]
10313 (define_insn "consttable_4"
10314   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10315   "TARGET_EITHER"
10316   "*
10317   {
10318     making_const_table = TRUE;
10319     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10320       {
10321       case MODE_FLOAT:
10322       {
10323         REAL_VALUE_TYPE r;
10324         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10325         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10326         break;
10327       }
10328       default:
10329         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
10330         break;
10331       }
10332     return \"\";
10333   }"
10334   [(set_attr "length" "4")]
10337 (define_insn "consttable_8"
10338   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10339   "TARGET_EITHER"
10340   "*
10341   {
10342     making_const_table = TRUE;
10343     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10344       {
10345        case MODE_FLOAT:
10346         {
10347           REAL_VALUE_TYPE r;
10348           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10349           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10350           break;
10351         }
10352       default:
10353         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10354         break;
10355       }
10356     return \"\";
10357   }"
10358   [(set_attr "length" "8")]
10361 ;; Miscellaneous Thumb patterns
10363 (define_expand "tablejump"
10364   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10365               (use (label_ref (match_operand 1 "" "")))])]
10366   "TARGET_THUMB"
10367   "
10368   if (flag_pic)
10369     {
10370       /* Hopefully, CSE will eliminate this copy.  */
10371       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10372       rtx reg2 = gen_reg_rtx (SImode);
10374       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10375       operands[0] = reg2;
10376     }
10377   "
10380 ;; NB never uses BX.
10381 (define_insn "*thumb_tablejump"
10382   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10383    (use (label_ref (match_operand 1 "" "")))]
10384   "TARGET_THUMB"
10385   "mov\\t%|pc, %0"
10386   [(set_attr "length" "2")]
10389 ;; V5 Instructions,
10391 (define_insn "clzsi2"
10392   [(set (match_operand:SI 0 "s_register_operand" "=r")
10393         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10394   "TARGET_ARM && arm_arch5"
10395   "clz%?\\t%0, %1"
10396   [(set_attr "predicable" "yes")])
10398 (define_expand "ffssi2"
10399   [(set (match_operand:SI 0 "s_register_operand" "")
10400         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10401   "TARGET_ARM && arm_arch5"
10402   "
10403   {
10404     rtx t1, t2, t3;
10406     t1 = gen_reg_rtx (SImode);
10407     t2 = gen_reg_rtx (SImode);
10408     t3 = gen_reg_rtx (SImode);
10410     emit_insn (gen_negsi2 (t1, operands[1]));
10411     emit_insn (gen_andsi3 (t2, operands[1], t1));
10412     emit_insn (gen_clzsi2 (t3, t2));
10413     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10414     DONE;
10415   }"
10418 (define_expand "ctzsi2"
10419   [(set (match_operand:SI 0 "s_register_operand" "")
10420         (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10421   "TARGET_ARM && arm_arch5"
10422   "
10423   {
10424     rtx t1, t2, t3;
10426     t1 = gen_reg_rtx (SImode);
10427     t2 = gen_reg_rtx (SImode);
10428     t3 = gen_reg_rtx (SImode);
10430     emit_insn (gen_negsi2 (t1, operands[1]));
10431     emit_insn (gen_andsi3 (t2, operands[1], t1));
10432     emit_insn (gen_clzsi2 (t3, t2));
10433     emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10434     DONE;
10435   }"
10438 ;; V5E instructions.
10440 (define_insn "prefetch"
10441   [(prefetch (match_operand:SI 0 "address_operand" "p")
10442              (match_operand:SI 1 "" "")
10443              (match_operand:SI 2 "" ""))]
10444   "TARGET_ARM && arm_arch5e"
10445   "pld\\t%a0")
10447 ;; General predication pattern
10449 (define_cond_exec
10450   [(match_operator 0 "arm_comparison_operator"
10451     [(match_operand 1 "cc_register" "")
10452      (const_int 0)])]
10453   "TARGET_ARM"
10454   ""
10457 (define_insn "prologue_use"
10458   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10459   ""
10460   "%@ %0 needed for prologue"
10464 ;; Patterns for exception handling
10466 (define_expand "eh_return"
10467   [(use (match_operand 0 "general_operand" ""))]
10468   "TARGET_EITHER"
10469   "
10470   {
10471     if (TARGET_ARM)
10472       emit_insn (gen_arm_eh_return (operands[0]));
10473     else
10474       emit_insn (gen_thumb_eh_return (operands[0]));
10475     DONE;
10476   }"
10478                                    
10479 ;; We can't expand this before we know where the link register is stored.
10480 (define_insn_and_split "arm_eh_return"
10481   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10482                     VUNSPEC_EH_RETURN)
10483    (clobber (match_scratch:SI 1 "=&r"))]
10484   "TARGET_ARM"
10485   "#"
10486   "&& reload_completed"
10487   [(const_int 0)]
10488   "
10489   {
10490     arm_set_return_address (operands[0], operands[1]);
10491     DONE;
10492   }"
10495 (define_insn_and_split "thumb_eh_return"
10496   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10497                     VUNSPEC_EH_RETURN)
10498    (clobber (match_scratch:SI 1 "=&l"))]
10499   "TARGET_THUMB"
10500   "#"
10501   "&& reload_completed"
10502   [(const_int 0)]
10503   "
10504   {
10505     thumb_set_return_address (operands[0], operands[1]);
10506     DONE;
10507   }"
10510 ;; Load the FPA co-processor patterns
10511 (include "fpa.md")
10512 ;; Load the Maverick co-processor patterns
10513 (include "cirrus.md")
10514 ;; Load the Intel Wireless Multimedia Extension patterns
10515 (include "iwmmxt.md")
10516 ;; Load the VFP co-processor patterns
10517 (include "vfp.md")