Merged with mainline at revision 128810.
[official-gcc.git] / gcc / config / arm / arm.md
blob04ca8ac37f53c7386c7bd0348c02c71430778d9d
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, 2006, 2007 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 3, 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 COPYING3.  If not see
22 ;; <http://www.gnu.org/licenses/>.
24 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
27 ;;---------------------------------------------------------------------------
28 ;; Constants
30 ;; Register numbers
31 (define_constants
32   [(R0_REGNUM        0)         ; First CORE register
33    (IP_REGNUM       12)         ; Scratch register
34    (SP_REGNUM       13)         ; Stack pointer
35    (LR_REGNUM       14)         ; Return address register
36    (PC_REGNUM       15)         ; Program counter
37    (CC_REGNUM       24)         ; Condition code pseudo register
38    (LAST_ARM_REGNUM 15)         ;
39    (FPA_F0_REGNUM   16)         ; FIRST_FPA_REGNUM
40    (FPA_F7_REGNUM   23)         ; LAST_FPA_REGNUM
41   ]
43 ;; 3rd operand to select_dominance_cc_mode
44 (define_constants
45   [(DOM_CC_X_AND_Y  0)
46    (DOM_CC_NX_OR_Y  1)
47    (DOM_CC_X_OR_Y   2)
48   ]
51 ;; UNSPEC Usage:
52 ;; Note: sin and cos are no-longer used.
53 ;; Unspec constants for Neon are defined in neon.md.
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    (UNSPEC_TLS      20) ; A symbol that has been treated properly for TLS usage.
94    (UNSPEC_PIC_LABEL 21) ; A label used for PIC access that does not appear in the
95                          ; instruction stream.
96    (UNSPEC_STACK_ALIGN 20) ; Doubleword aligned stack pointer.  Used to
97                            ; generate correct unwind information.
98    (UNSPEC_PIC_OFFSET 22) ; A symbolic 12-bit OFFSET that has been treated
99                           ; correctly for PIC usage.
100   ]
103 ;; UNSPEC_VOLATILE Usage:
105 (define_constants
106   [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
107                         ;   insn in the code.
108    (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
109                         ;   instruction epilogue sequence that isn't expanded
110                         ;   into normal RTL.  Used for both normal and sibcall
111                         ;   epilogues.
112    (VUNSPEC_ALIGN    2) ; `align' insn.  Used at the head of a minipool table 
113                         ;   for inlined constants.
114    (VUNSPEC_POOL_END 3) ; `end-of-table'.  Used to mark the end of a minipool
115                         ;   table.
116    (VUNSPEC_POOL_1   4) ; `pool-entry(1)'.  An entry in the constant pool for
117                         ;   an 8-bit object.
118    (VUNSPEC_POOL_2   5) ; `pool-entry(2)'.  An entry in the constant pool for
119                         ;   a 16-bit object.
120    (VUNSPEC_POOL_4   6) ; `pool-entry(4)'.  An entry in the constant pool for
121                         ;   a 32-bit object.
122    (VUNSPEC_POOL_8   7) ; `pool-entry(8)'.  An entry in the constant pool for
123                         ;   a 64-bit object.
124    (VUNSPEC_POOL_16  8) ; `pool-entry(16)'.  An entry in the constant pool for
125                         ;   a 128-bit object.
126    (VUNSPEC_TMRC     9) ; Used by the iWMMXt TMRC instruction.
127    (VUNSPEC_TMCR     10) ; Used by the iWMMXt TMCR instruction.
128    (VUNSPEC_ALIGN8   11) ; 8-byte alignment version of VUNSPEC_ALIGN
129    (VUNSPEC_WCMP_EQ  12) ; Used by the iWMMXt WCMPEQ instructions
130    (VUNSPEC_WCMP_GTU 13) ; Used by the iWMMXt WCMPGTU instructions
131    (VUNSPEC_WCMP_GT  14) ; Used by the iwMMXT WCMPGT instructions
132    (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
133                          ; handling.
134   ]
137 ;;---------------------------------------------------------------------------
138 ;; Attributes
140 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
141 ; generating ARM code.  This is used to control the length of some insn
142 ; patterns that share the same RTL in both ARM and Thumb code.
143 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
145 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
146 ; scheduling decisions for the load unit and the multiplier.
147 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_tune_strongarm")))
149 ; IS_XSCALE is set to 'yes' when compiling for XScale.
150 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
152 ;; Operand number of an input operand that is shifted.  Zero if the
153 ;; given instruction does not shift one of its input operands.
154 (define_attr "shift" "" (const_int 0))
156 ; Floating Point Unit.  If we only have floating point emulation, then there
157 ; is no point in scheduling the floating point insns.  (Well, for best
158 ; performance we should try and group them together).
159 (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
160   (const (symbol_ref "arm_fpu_attr")))
162 ; LENGTH of an instruction (in bytes)
163 (define_attr "length" "" (const_int 4))
165 ; POOL_RANGE is how far away from a constant pool entry that this insn
166 ; can be placed.  If the distance is zero, then this insn will never
167 ; reference the pool.
168 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
169 ; before its address.
170 (define_attr "pool_range" "" (const_int 0))
171 (define_attr "neg_pool_range" "" (const_int 0))
173 ; An assembler sequence may clobber the condition codes without us knowing.
174 ; If such an insn references the pool, then we have no way of knowing how,
175 ; so use the most conservative value for pool_range.
176 (define_asm_attributes
177  [(set_attr "conds" "clob")
178   (set_attr "length" "4")
179   (set_attr "pool_range" "250")])
181 ;; The instruction used to implement a particular pattern.  This
182 ;; information is used by pipeline descriptions to provide accurate
183 ;; scheduling information.
185 (define_attr "insn"
186         "mov,mvn,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,smmla,umaal,smlald,smlsld,clz,mrs,msr,xtab,other"
187         (const_string "other"))
189 ; TYPE attribute is used to detect floating point instructions which, if
190 ; running on a co-processor can run in parallel with other, basic instructions
191 ; If write-buffer scheduling is enabled then it can also be used in the
192 ; scheduling of writes.
194 ; Classification of each insn
195 ; alu           any alu  instruction that doesn't hit memory or fp
196 ;               regs or have a shifted source operand
197 ; alu_shift     any data instruction that doesn't hit memory or fp
198 ;               regs, but has a source operand shifted by a constant
199 ; alu_shift_reg any data instruction that doesn't hit memory or fp
200 ;               regs, but has a source operand shifted by a register value
201 ; mult          a multiply instruction
202 ; block         blockage insn, this blocks all functional units
203 ; float         a floating point arithmetic operation (subject to expansion)
204 ; fdivd         DFmode floating point division
205 ; fdivs         SFmode floating point division
206 ; fmul          Floating point multiply
207 ; ffmul         Fast floating point multiply
208 ; farith        Floating point arithmetic (4 cycle)
209 ; ffarith       Fast floating point arithmetic (2 cycle)
210 ; float_em      a floating point arithmetic operation that is normally emulated
211 ;               even on a machine with an fpa.
212 ; f_load        a floating point load from memory
213 ; f_store       a floating point store to memory
214 ; f_load[sd]    single/double load from memory
215 ; f_store[sd]   single/double store to memory
216 ; f_flag        a transfer of co-processor flags to the CPSR
217 ; f_mem_r       a transfer of a floating point register to a real reg via mem
218 ; r_mem_f       the reverse of f_mem_r
219 ; f_2_r         fast transfer float to arm (no memory needed)
220 ; r_2_f         fast transfer arm to float
221 ; f_cvt         convert floating<->integral
222 ; branch        a branch
223 ; call          a subroutine call
224 ; load_byte     load byte(s) from memory to arm registers
225 ; load1         load 1 word from memory to arm registers
226 ; load2         load 2 words from memory to arm registers
227 ; load3         load 3 words from memory to arm registers
228 ; load4         load 4 words from memory to arm registers
229 ; store         store 1 word to memory from arm registers
230 ; store2        store 2 words
231 ; store3        store 3 words
232 ; store4        store 4 (or more) words
233 ;  Additions for Cirrus Maverick co-processor:
234 ; mav_farith    Floating point arithmetic (4 cycle)
235 ; mav_dmult     Double multiplies (7 cycle)
238 (define_attr "type"
239         "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,fmuls,fmuld,fmacs,fmacd,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"
240         (if_then_else 
241          (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
242          (const_string "mult")
243          (const_string "alu")))
245 ; Load scheduling, set from the arm_ld_sched variable
246 ; initialized by arm_override_options() 
247 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
249 ; condition codes: this one is used by final_prescan_insn to speed up
250 ; conditionalizing instructions.  It saves having to scan the rtl to see if
251 ; it uses or alters the condition codes.
253 ; USE means that the condition codes are used by the insn in the process of
254 ;   outputting code, this means (at present) that we can't use the insn in
255 ;   inlined branches
257 ; SET means that the purpose of the insn is to set the condition codes in a
258 ;   well defined manner.
260 ; CLOB means that the condition codes are altered in an undefined manner, if
261 ;   they are altered at all
263 ; JUMP_CLOB is used when the condition cannot be represented by a single
264 ;   instruction (UNEQ and LTGT).  These cannot be predicated.
266 ; NOCOND means that the condition codes are neither altered nor affect the
267 ;   output of this insn
269 (define_attr "conds" "use,set,clob,jump_clob,nocond"
270         (if_then_else (eq_attr "type" "call")
271          (const_string "clob")
272          (const_string "nocond")))
274 ; Predicable means that the insn can be conditionally executed based on
275 ; an automatically added predicate (additional patterns are generated by 
276 ; gen...).  We default to 'no' because no Thumb patterns match this rule
277 ; and not all ARM patterns do.
278 (define_attr "predicable" "no,yes" (const_string "no"))
280 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
281 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
282 ; suffer blockages enough to warrant modelling this (and it can adversely
283 ; affect the schedule).
284 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
286 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
287 ; to stall the processor.  Used with model_wbuf above.
288 (define_attr "write_conflict" "no,yes"
289   (if_then_else (eq_attr "type"
290                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
291                 (const_string "yes")
292                 (const_string "no")))
294 ; Classify the insns into those that take one cycle and those that take more
295 ; than one on the main cpu execution unit.
296 (define_attr "core_cycles" "single,multi"
297   (if_then_else (eq_attr "type"
298                  "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
299                 (const_string "single")
300                 (const_string "multi")))
302 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
303 ;; distant label.  Only applicable to Thumb code.
304 (define_attr "far_jump" "yes,no" (const_string "no"))
307 ;; The number of machine instructions this pattern expands to.
308 ;; Used for Thumb-2 conditional execution.
309 (define_attr "ce_count" "" (const_int 1))
311 ;;---------------------------------------------------------------------------
312 ;; Mode iterators
314 ; A list of modes that are exactly 64 bits in size.  We use this to expand
315 ; some splits that are the same for all modes when operating on ARM 
316 ; registers.
317 (define_mode_iterator ANY64 [DI DF V8QI V4HI V2SI V2SF])
319 ;;---------------------------------------------------------------------------
320 ;; Predicates
322 (include "predicates.md")
323 (include "constraints.md")
325 ;;---------------------------------------------------------------------------
326 ;; Pipeline descriptions
328 ;; Processor type.  This is created automatically from arm-cores.def.
329 (include "arm-tune.md")
331 ;; True if the generic scheduling description should be used.
333 (define_attr "generic_sched" "yes,no"
334   (const (if_then_else 
335           (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa8")
336           (const_string "no")
337           (const_string "yes"))))
339 (define_attr "generic_vfp" "yes,no"
340   (const (if_then_else
341           (and (eq_attr "fpu" "vfp")
342                (eq_attr "tune" "!arm1020e,arm1022e,cortexa8"))
343           (const_string "yes")
344           (const_string "no"))))
346 (include "arm-generic.md")
347 (include "arm926ejs.md")
348 (include "arm1020e.md")
349 (include "arm1026ejs.md")
350 (include "arm1136jfs.md")
351 (include "cortex-a8.md")
354 ;;---------------------------------------------------------------------------
355 ;; Insn patterns
357 ;; Addition insns.
359 ;; Note: For DImode insns, there is normally no reason why operands should
360 ;; not be in the same register, what we don't want is for something being
361 ;; written to partially overlap something that is an input.
362 ;; Cirrus 64bit additions should not be split because we have a native
363 ;; 64bit addition instructions.
365 (define_expand "adddi3"
366  [(parallel
367    [(set (match_operand:DI           0 "s_register_operand" "")
368           (plus:DI (match_operand:DI 1 "s_register_operand" "")
369                    (match_operand:DI 2 "s_register_operand" "")))
370     (clobber (reg:CC CC_REGNUM))])]
371   "TARGET_EITHER"
372   "
373   if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
374     {
375       if (!cirrus_fp_register (operands[0], DImode))
376         operands[0] = force_reg (DImode, operands[0]);
377       if (!cirrus_fp_register (operands[1], DImode))
378         operands[1] = force_reg (DImode, operands[1]);
379       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
380       DONE;
381     }
383   if (TARGET_THUMB1)
384     {
385       if (GET_CODE (operands[1]) != REG)
386         operands[1] = force_reg (SImode, operands[1]);
387       if (GET_CODE (operands[2]) != REG)
388         operands[2] = force_reg (SImode, operands[2]);
389      }
390   "
393 (define_insn "*thumb1_adddi3"
394   [(set (match_operand:DI          0 "register_operand" "=l")
395         (plus:DI (match_operand:DI 1 "register_operand" "%0")
396                  (match_operand:DI 2 "register_operand" "l")))
397    (clobber (reg:CC CC_REGNUM))
398   ]
399   "TARGET_THUMB1"
400   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
401   [(set_attr "length" "4")]
404 (define_insn_and_split "*arm_adddi3"
405   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
406         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
407                  (match_operand:DI 2 "s_register_operand" "r,  0")))
408    (clobber (reg:CC CC_REGNUM))]
409   "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
410   "#"
411   "TARGET_32BIT && reload_completed"
412   [(parallel [(set (reg:CC_C CC_REGNUM)
413                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
414                                  (match_dup 1)))
415               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
416    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
417                                (plus:SI (match_dup 4) (match_dup 5))))]
418   "
419   {
420     operands[3] = gen_highpart (SImode, operands[0]);
421     operands[0] = gen_lowpart (SImode, operands[0]);
422     operands[4] = gen_highpart (SImode, operands[1]);
423     operands[1] = gen_lowpart (SImode, operands[1]);
424     operands[5] = gen_highpart (SImode, operands[2]);
425     operands[2] = gen_lowpart (SImode, operands[2]);
426   }"
427   [(set_attr "conds" "clob")
428    (set_attr "length" "8")]
431 (define_insn_and_split "*adddi_sesidi_di"
432   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
433         (plus:DI (sign_extend:DI
434                   (match_operand:SI 2 "s_register_operand" "r,r"))
435                  (match_operand:DI 1 "s_register_operand" "r,0")))
436    (clobber (reg:CC CC_REGNUM))]
437   "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
438   "#"
439   "TARGET_32BIT && reload_completed"
440   [(parallel [(set (reg:CC_C CC_REGNUM)
441                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
442                                  (match_dup 1)))
443               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
444    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
445                                (plus:SI (ashiftrt:SI (match_dup 2)
446                                                      (const_int 31))
447                                         (match_dup 4))))]
448   "
449   {
450     operands[3] = gen_highpart (SImode, operands[0]);
451     operands[0] = gen_lowpart (SImode, operands[0]);
452     operands[4] = gen_highpart (SImode, operands[1]);
453     operands[1] = gen_lowpart (SImode, operands[1]);
454     operands[2] = gen_lowpart (SImode, operands[2]);
455   }"
456   [(set_attr "conds" "clob")
457    (set_attr "length" "8")]
460 (define_insn_and_split "*adddi_zesidi_di"
461   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
462         (plus:DI (zero_extend:DI
463                   (match_operand:SI 2 "s_register_operand" "r,r"))
464                  (match_operand:DI 1 "s_register_operand" "r,0")))
465    (clobber (reg:CC CC_REGNUM))]
466   "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
467   "#"
468   "TARGET_32BIT && reload_completed"
469   [(parallel [(set (reg:CC_C CC_REGNUM)
470                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
471                                  (match_dup 1)))
472               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
473    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
474                                (plus:SI (match_dup 4) (const_int 0))))]
475   "
476   {
477     operands[3] = gen_highpart (SImode, operands[0]);
478     operands[0] = gen_lowpart (SImode, operands[0]);
479     operands[4] = gen_highpart (SImode, operands[1]);
480     operands[1] = gen_lowpart (SImode, operands[1]);
481     operands[2] = gen_lowpart (SImode, operands[2]);
482   }"
483   [(set_attr "conds" "clob")
484    (set_attr "length" "8")]
487 (define_expand "addsi3"
488   [(set (match_operand:SI          0 "s_register_operand" "")
489         (plus:SI (match_operand:SI 1 "s_register_operand" "")
490                  (match_operand:SI 2 "reg_or_int_operand" "")))]
491   "TARGET_EITHER"
492   "
493   if (TARGET_32BIT && GET_CODE (operands[2]) == CONST_INT)
494     {
495       arm_split_constant (PLUS, SImode, NULL_RTX,
496                           INTVAL (operands[2]), operands[0], operands[1],
497                           optimize && can_create_pseudo_p ());
498       DONE;
499     }
500   "
503 ; If there is a scratch available, this will be faster than synthesizing the
504 ; addition.
505 (define_peephole2
506   [(match_scratch:SI 3 "r")
507    (set (match_operand:SI          0 "arm_general_register_operand" "")
508         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
509                  (match_operand:SI 2 "const_int_operand"  "")))]
510   "TARGET_32BIT &&
511    !(const_ok_for_arm (INTVAL (operands[2]))
512      || const_ok_for_arm (-INTVAL (operands[2])))
513     && const_ok_for_arm (~INTVAL (operands[2]))"
514   [(set (match_dup 3) (match_dup 2))
515    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
516   ""
519 (define_insn_and_split "*arm_addsi3"
520   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
521         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
522                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
523   "TARGET_32BIT"
524   "@
525    add%?\\t%0, %1, %2
526    sub%?\\t%0, %1, #%n2
527    #"
528   "TARGET_32BIT &&
529    GET_CODE (operands[2]) == CONST_INT
530    && !(const_ok_for_arm (INTVAL (operands[2]))
531         || const_ok_for_arm (-INTVAL (operands[2])))"
532   [(clobber (const_int 0))]
533   "
534   arm_split_constant (PLUS, SImode, curr_insn,
535                       INTVAL (operands[2]), operands[0],
536                       operands[1], 0);
537   DONE;
538   "
539   [(set_attr "length" "4,4,16")
540    (set_attr "predicable" "yes")]
543 ;; Register group 'k' is a single register group containing only the stack
544 ;; register.  Trying to reload it will always fail catastrophically,
545 ;; so never allow those alternatives to match if reloading is needed.
547 (define_insn "*thumb1_addsi3"
548   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
549         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
550                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
551   "TARGET_THUMB1"
552   "*
553    static const char * const asms[] = 
554    {
555      \"add\\t%0, %0, %2\",
556      \"sub\\t%0, %0, #%n2\",
557      \"add\\t%0, %1, %2\",
558      \"add\\t%0, %0, %2\",
559      \"add\\t%0, %0, %2\",
560      \"add\\t%0, %1, %2\",
561      \"add\\t%0, %1, %2\"
562    };
563    if ((which_alternative == 2 || which_alternative == 6)
564        && GET_CODE (operands[2]) == CONST_INT
565        && INTVAL (operands[2]) < 0)
566      return \"sub\\t%0, %1, #%n2\";
567    return asms[which_alternative];
568   "
569   [(set_attr "length" "2")]
572 ;; Reloading and elimination of the frame pointer can
573 ;; sometimes cause this optimization to be missed.
574 (define_peephole2
575   [(set (match_operand:SI 0 "arm_general_register_operand" "")
576         (match_operand:SI 1 "const_int_operand" ""))
577    (set (match_dup 0)
578         (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
579   "TARGET_THUMB1
580    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
581    && (INTVAL (operands[1]) & 3) == 0"
582   [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
583   ""
586 ;; ??? Make Thumb-2 variants which prefer low regs
587 (define_insn "*addsi3_compare0"
588   [(set (reg:CC_NOOV CC_REGNUM)
589         (compare:CC_NOOV
590          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
591                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
592          (const_int 0)))
593    (set (match_operand:SI 0 "s_register_operand" "=r,r")
594         (plus:SI (match_dup 1) (match_dup 2)))]
595   "TARGET_32BIT"
596   "@
597    add%.\\t%0, %1, %2
598    sub%.\\t%0, %1, #%n2"
599   [(set_attr "conds" "set")]
602 (define_insn "*addsi3_compare0_scratch"
603   [(set (reg:CC_NOOV CC_REGNUM)
604         (compare:CC_NOOV
605          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
606                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
607          (const_int 0)))]
608   "TARGET_32BIT"
609   "@
610    cmn%?\\t%0, %1
611    cmp%?\\t%0, #%n1"
612   [(set_attr "conds" "set")]
615 (define_insn "*compare_negsi_si"
616   [(set (reg:CC_Z CC_REGNUM)
617         (compare:CC_Z
618          (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
619          (match_operand:SI 1 "s_register_operand" "r")))]
620   "TARGET_32BIT"
621   "cmn%?\\t%1, %0"
622   [(set_attr "conds" "set")]
625 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
626 ;; addend is a constant.
627 (define_insn "*cmpsi2_addneg"
628   [(set (reg:CC CC_REGNUM)
629         (compare:CC
630          (match_operand:SI 1 "s_register_operand" "r,r")
631          (match_operand:SI 2 "arm_addimm_operand" "I,L")))
632    (set (match_operand:SI 0 "s_register_operand" "=r,r")
633         (plus:SI (match_dup 1)
634                  (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
635   "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
636   "@
637    sub%.\\t%0, %1, %2
638    add%.\\t%0, %1, #%n2"
639   [(set_attr "conds" "set")]
642 ;; Convert the sequence
643 ;;  sub  rd, rn, #1
644 ;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
645 ;;  bne  dest
646 ;; into
647 ;;  subs rd, rn, #1
648 ;;  bcs  dest   ((unsigned)rn >= 1)
649 ;; similarly for the beq variant using bcc.
650 ;; This is a common looping idiom (while (n--))
651 (define_peephole2
652   [(set (match_operand:SI 0 "arm_general_register_operand" "")
653         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
654                  (const_int -1)))
655    (set (match_operand 2 "cc_register" "")
656         (compare (match_dup 0) (const_int -1)))
657    (set (pc)
658         (if_then_else (match_operator 3 "equality_operator"
659                        [(match_dup 2) (const_int 0)])
660                       (match_operand 4 "" "")
661                       (match_operand 5 "" "")))]
662   "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
663   [(parallel[
664     (set (match_dup 2)
665          (compare:CC
666           (match_dup 1) (const_int 1)))
667     (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
668    (set (pc)
669         (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
670                       (match_dup 4)
671                       (match_dup 5)))]
672   "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
673    operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
674                                   ? GEU : LTU),
675                                  VOIDmode, 
676                                  operands[2], const0_rtx);"
679 ;; The next four insns work because they compare the result with one of
680 ;; the operands, and we know that the use of the condition code is
681 ;; either GEU or LTU, so we can use the carry flag from the addition
682 ;; instead of doing the compare a second time.
683 (define_insn "*addsi3_compare_op1"
684   [(set (reg:CC_C CC_REGNUM)
685         (compare:CC_C
686          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
687                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
688          (match_dup 1)))
689    (set (match_operand:SI 0 "s_register_operand" "=r,r")
690         (plus:SI (match_dup 1) (match_dup 2)))]
691   "TARGET_32BIT"
692   "@
693    add%.\\t%0, %1, %2
694    sub%.\\t%0, %1, #%n2"
695   [(set_attr "conds" "set")]
698 (define_insn "*addsi3_compare_op2"
699   [(set (reg:CC_C CC_REGNUM)
700         (compare:CC_C
701          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
702                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
703          (match_dup 2)))
704    (set (match_operand:SI 0 "s_register_operand" "=r,r")
705         (plus:SI (match_dup 1) (match_dup 2)))]
706   "TARGET_32BIT"
707   "@
708    add%.\\t%0, %1, %2
709    sub%.\\t%0, %1, #%n2"
710   [(set_attr "conds" "set")]
713 (define_insn "*compare_addsi2_op0"
714   [(set (reg:CC_C CC_REGNUM)
715         (compare:CC_C
716          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
717                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
718          (match_dup 0)))]
719   "TARGET_32BIT"
720   "@
721    cmn%?\\t%0, %1
722    cmp%?\\t%0, #%n1"
723   [(set_attr "conds" "set")]
726 (define_insn "*compare_addsi2_op1"
727   [(set (reg:CC_C CC_REGNUM)
728         (compare:CC_C
729          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
730                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
731          (match_dup 1)))]
732   "TARGET_32BIT"
733   "@
734    cmn%?\\t%0, %1
735    cmp%?\\t%0, #%n1"
736   [(set_attr "conds" "set")]
739 (define_insn "*addsi3_carryin"
740   [(set (match_operand:SI 0 "s_register_operand" "=r")
741         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
742                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
743                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
744   "TARGET_32BIT"
745   "adc%?\\t%0, %1, %2"
746   [(set_attr "conds" "use")]
749 (define_insn "*addsi3_carryin_shift"
750   [(set (match_operand:SI 0 "s_register_operand" "=r")
751         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
752                  (plus:SI
753                    (match_operator:SI 2 "shift_operator"
754                       [(match_operand:SI 3 "s_register_operand" "r")
755                        (match_operand:SI 4 "reg_or_int_operand" "rM")])
756                     (match_operand:SI 1 "s_register_operand" "r"))))]
757   "TARGET_32BIT"
758   "adc%?\\t%0, %1, %3%S2"
759   [(set_attr "conds" "use")
760    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
761                       (const_string "alu_shift")
762                       (const_string "alu_shift_reg")))]
765 (define_insn "*addsi3_carryin_alt1"
766   [(set (match_operand:SI 0 "s_register_operand" "=r")
767         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
768                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
769                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
770   "TARGET_32BIT"
771   "adc%?\\t%0, %1, %2"
772   [(set_attr "conds" "use")]
775 (define_insn "*addsi3_carryin_alt2"
776   [(set (match_operand:SI 0 "s_register_operand" "=r")
777         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
778                           (match_operand:SI 1 "s_register_operand" "r"))
779                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
780   "TARGET_32BIT"
781   "adc%?\\t%0, %1, %2"
782   [(set_attr "conds" "use")]
785 (define_insn "*addsi3_carryin_alt3"
786   [(set (match_operand:SI 0 "s_register_operand" "=r")
787         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
788                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
789                  (match_operand:SI 1 "s_register_operand" "r")))]
790   "TARGET_32BIT"
791   "adc%?\\t%0, %1, %2"
792   [(set_attr "conds" "use")]
795 (define_expand "incscc"
796   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
797         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
798                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
799                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
800   "TARGET_32BIT"
801   ""
804 (define_insn "*arm_incscc"
805   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
806         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
807                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
808                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
809   "TARGET_ARM"
810   "@
811   add%d2\\t%0, %1, #1
812   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
813   [(set_attr "conds" "use")
814    (set_attr "length" "4,8")]
817 ; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
818 (define_split
819   [(set (match_operand:SI 0 "s_register_operand" "")
820         (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
821                             (match_operand:SI 2 "s_register_operand" ""))
822                  (const_int -1)))
823    (clobber (match_operand:SI 3 "s_register_operand" ""))]
824   "TARGET_32BIT"
825   [(set (match_dup 3) (match_dup 1))
826    (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
827   "
828   operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
831 (define_expand "addsf3"
832   [(set (match_operand:SF          0 "s_register_operand" "")
833         (plus:SF (match_operand:SF 1 "s_register_operand" "")
834                  (match_operand:SF 2 "arm_float_add_operand" "")))]
835   "TARGET_32BIT && TARGET_HARD_FLOAT"
836   "
837   if (TARGET_MAVERICK
838       && !cirrus_fp_register (operands[2], SFmode))
839     operands[2] = force_reg (SFmode, operands[2]);
842 (define_expand "adddf3"
843   [(set (match_operand:DF          0 "s_register_operand" "")
844         (plus:DF (match_operand:DF 1 "s_register_operand" "")
845                  (match_operand:DF 2 "arm_float_add_operand" "")))]
846   "TARGET_32BIT && TARGET_HARD_FLOAT"
847   "
848   if (TARGET_MAVERICK
849       && !cirrus_fp_register (operands[2], DFmode))
850     operands[2] = force_reg (DFmode, operands[2]);
853 (define_expand "subdi3"
854  [(parallel
855    [(set (match_operand:DI            0 "s_register_operand" "")
856           (minus:DI (match_operand:DI 1 "s_register_operand" "")
857                     (match_operand:DI 2 "s_register_operand" "")))
858     (clobber (reg:CC CC_REGNUM))])]
859   "TARGET_EITHER"
860   "
861   if (TARGET_HARD_FLOAT && TARGET_MAVERICK
862       && TARGET_32BIT
863       && cirrus_fp_register (operands[0], DImode)
864       && cirrus_fp_register (operands[1], DImode))
865     {
866       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
867       DONE;
868     }
870   if (TARGET_THUMB1)
871     {
872       if (GET_CODE (operands[1]) != REG)
873         operands[1] = force_reg (SImode, operands[1]);
874       if (GET_CODE (operands[2]) != REG)
875         operands[2] = force_reg (SImode, operands[2]);
876      }  
877   "
880 (define_insn "*arm_subdi3"
881   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
882         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
883                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
884    (clobber (reg:CC CC_REGNUM))]
885   "TARGET_32BIT"
886   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
887   [(set_attr "conds" "clob")
888    (set_attr "length" "8")]
891 (define_insn "*thumb_subdi3"
892   [(set (match_operand:DI           0 "register_operand" "=l")
893         (minus:DI (match_operand:DI 1 "register_operand"  "0")
894                   (match_operand:DI 2 "register_operand"  "l")))
895    (clobber (reg:CC CC_REGNUM))]
896   "TARGET_THUMB1"
897   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
898   [(set_attr "length" "4")]
901 (define_insn "*subdi_di_zesidi"
902   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
903         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
904                   (zero_extend:DI
905                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
906    (clobber (reg:CC CC_REGNUM))]
907   "TARGET_32BIT"
908   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
909   [(set_attr "conds" "clob")
910    (set_attr "length" "8")]
913 (define_insn "*subdi_di_sesidi"
914   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
915         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
916                   (sign_extend:DI
917                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
918    (clobber (reg:CC CC_REGNUM))]
919   "TARGET_32BIT"
920   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
921   [(set_attr "conds" "clob")
922    (set_attr "length" "8")]
925 (define_insn "*subdi_zesidi_di"
926   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
927         (minus:DI (zero_extend:DI
928                    (match_operand:SI 2 "s_register_operand"  "r,r"))
929                   (match_operand:DI  1 "s_register_operand" "?r,0")))
930    (clobber (reg:CC CC_REGNUM))]
931   "TARGET_ARM"
932   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
933   [(set_attr "conds" "clob")
934    (set_attr "length" "8")]
937 (define_insn "*subdi_sesidi_di"
938   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
939         (minus:DI (sign_extend:DI
940                    (match_operand:SI 2 "s_register_operand"   "r,r"))
941                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
942    (clobber (reg:CC CC_REGNUM))]
943   "TARGET_ARM"
944   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
945   [(set_attr "conds" "clob")
946    (set_attr "length" "8")]
949 (define_insn "*subdi_zesidi_zesidi"
950   [(set (match_operand:DI            0 "s_register_operand" "=r")
951         (minus:DI (zero_extend:DI
952                    (match_operand:SI 1 "s_register_operand"  "r"))
953                   (zero_extend:DI
954                    (match_operand:SI 2 "s_register_operand"  "r"))))
955    (clobber (reg:CC CC_REGNUM))]
956   "TARGET_32BIT"
957   "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
958   [(set_attr "conds" "clob")
959    (set_attr "length" "8")]
962 (define_expand "subsi3"
963   [(set (match_operand:SI           0 "s_register_operand" "")
964         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
965                   (match_operand:SI 2 "s_register_operand" "")))]
966   "TARGET_EITHER"
967   "
968   if (GET_CODE (operands[1]) == CONST_INT)
969     {
970       if (TARGET_32BIT)
971         {
972           arm_split_constant (MINUS, SImode, NULL_RTX,
973                               INTVAL (operands[1]), operands[0],
974                               operands[2], optimize && can_create_pseudo_p ());
975           DONE;
976         }
977       else /* TARGET_THUMB1 */
978         operands[1] = force_reg (SImode, operands[1]);
979     }
980   "
983 (define_insn "*thumb1_subsi3_insn"
984   [(set (match_operand:SI           0 "register_operand" "=l")
985         (minus:SI (match_operand:SI 1 "register_operand" "l")
986                   (match_operand:SI 2 "register_operand" "l")))]
987   "TARGET_THUMB1"
988   "sub\\t%0, %1, %2"
989   [(set_attr "length" "2")]
992 ; ??? Check Thumb-2 split length
993 (define_insn_and_split "*arm_subsi3_insn"
994   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
995         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
996                   (match_operand:SI 2 "s_register_operand" "r,r")))]
997   "TARGET_32BIT"
998   "@
999    rsb%?\\t%0, %2, %1
1000    #"
1001   "TARGET_32BIT
1002    && GET_CODE (operands[1]) == CONST_INT
1003    && !const_ok_for_arm (INTVAL (operands[1]))"
1004   [(clobber (const_int 0))]
1005   "
1006   arm_split_constant (MINUS, SImode, curr_insn,
1007                       INTVAL (operands[1]), operands[0], operands[2], 0);
1008   DONE;
1009   "
1010   [(set_attr "length" "4,16")
1011    (set_attr "predicable" "yes")]
1014 (define_peephole2
1015   [(match_scratch:SI 3 "r")
1016    (set (match_operand:SI 0 "arm_general_register_operand" "")
1017         (minus:SI (match_operand:SI 1 "const_int_operand" "")
1018                   (match_operand:SI 2 "arm_general_register_operand" "")))]
1019   "TARGET_32BIT
1020    && !const_ok_for_arm (INTVAL (operands[1]))
1021    && const_ok_for_arm (~INTVAL (operands[1]))"
1022   [(set (match_dup 3) (match_dup 1))
1023    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1024   ""
1027 (define_insn "*subsi3_compare0"
1028   [(set (reg:CC_NOOV CC_REGNUM)
1029         (compare:CC_NOOV
1030          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1031                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1032          (const_int 0)))
1033    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1034         (minus:SI (match_dup 1) (match_dup 2)))]
1035   "TARGET_32BIT"
1036   "@
1037    sub%.\\t%0, %1, %2
1038    rsb%.\\t%0, %2, %1"
1039   [(set_attr "conds" "set")]
1042 (define_expand "decscc"
1043   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1044         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1045                   (match_operator:SI 2 "arm_comparison_operator"
1046                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1047   "TARGET_32BIT"
1048   ""
1051 (define_insn "*arm_decscc"
1052   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1053         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1054                   (match_operator:SI 2 "arm_comparison_operator"
1055                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1056   "TARGET_ARM"
1057   "@
1058    sub%d2\\t%0, %1, #1
1059    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1060   [(set_attr "conds" "use")
1061    (set_attr "length" "*,8")]
1064 (define_expand "subsf3"
1065   [(set (match_operand:SF           0 "s_register_operand" "")
1066         (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1067                   (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1068   "TARGET_32BIT && TARGET_HARD_FLOAT"
1069   "
1070   if (TARGET_MAVERICK)
1071     {
1072       if (!cirrus_fp_register (operands[1], SFmode))
1073         operands[1] = force_reg (SFmode, operands[1]);
1074       if (!cirrus_fp_register (operands[2], SFmode))
1075         operands[2] = force_reg (SFmode, operands[2]);
1076     }
1079 (define_expand "subdf3"
1080   [(set (match_operand:DF           0 "s_register_operand" "")
1081         (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1082                   (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1083   "TARGET_32BIT && TARGET_HARD_FLOAT"
1084   "
1085   if (TARGET_MAVERICK)
1086     {
1087        if (!cirrus_fp_register (operands[1], DFmode))
1088          operands[1] = force_reg (DFmode, operands[1]);
1089        if (!cirrus_fp_register (operands[2], DFmode))
1090          operands[2] = force_reg (DFmode, operands[2]);
1091     }
1095 ;; Multiplication insns
1097 (define_expand "mulsi3"
1098   [(set (match_operand:SI          0 "s_register_operand" "")
1099         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1100                  (match_operand:SI 1 "s_register_operand" "")))]
1101   "TARGET_EITHER"
1102   ""
1105 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1106 (define_insn "*arm_mulsi3"
1107   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1108         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1109                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1110   "TARGET_32BIT && !arm_arch6"
1111   "mul%?\\t%0, %2, %1"
1112   [(set_attr "insn" "mul")
1113    (set_attr "predicable" "yes")]
1116 (define_insn "*arm_mulsi3_v6"
1117   [(set (match_operand:SI          0 "s_register_operand" "=r")
1118         (mult:SI (match_operand:SI 1 "s_register_operand" "r")
1119                  (match_operand:SI 2 "s_register_operand" "r")))]
1120   "TARGET_32BIT && arm_arch6"
1121   "mul%?\\t%0, %1, %2"
1122   [(set_attr "insn" "mul")
1123    (set_attr "predicable" "yes")]
1126 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1127 ; 1 and 2; are the same, because reload will make operand 0 match 
1128 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1129 ; this by adding another alternative to match this case, and then `reload' 
1130 ; it ourselves.  This alternative must come first.
1131 (define_insn "*thumb_mulsi3"
1132   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1133         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1134                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1135   "TARGET_THUMB1 && !arm_arch6"
1136   "*
1137   if (which_alternative < 2)
1138     return \"mov\\t%0, %1\;mul\\t%0, %2\";
1139   else
1140     return \"mul\\t%0, %2\";
1141   "
1142   [(set_attr "length" "4,4,2")
1143    (set_attr "insn" "mul")]
1146 (define_insn "*thumb_mulsi3_v6"
1147   [(set (match_operand:SI          0 "register_operand" "=l,l,l")
1148         (mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
1149                  (match_operand:SI 2 "register_operand" "l,0,0")))]
1150   "TARGET_THUMB1 && arm_arch6"
1151   "@
1152    mul\\t%0, %2 
1153    mul\\t%0, %1 
1154    mul\\t%0, %1"
1155   [(set_attr "length" "2")
1156    (set_attr "insn" "mul")]
1159 (define_insn "*mulsi3_compare0"
1160   [(set (reg:CC_NOOV CC_REGNUM)
1161         (compare:CC_NOOV (mult:SI
1162                           (match_operand:SI 2 "s_register_operand" "r,r")
1163                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1164                          (const_int 0)))
1165    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1166         (mult:SI (match_dup 2) (match_dup 1)))]
1167   "TARGET_ARM && !arm_arch6"
1168   "mul%.\\t%0, %2, %1"
1169   [(set_attr "conds" "set")
1170    (set_attr "insn" "muls")]
1173 (define_insn "*mulsi3_compare0_v6"
1174   [(set (reg:CC_NOOV CC_REGNUM)
1175         (compare:CC_NOOV (mult:SI
1176                           (match_operand:SI 2 "s_register_operand" "r")
1177                           (match_operand:SI 1 "s_register_operand" "r"))
1178                          (const_int 0)))
1179    (set (match_operand:SI 0 "s_register_operand" "=r")
1180         (mult:SI (match_dup 2) (match_dup 1)))]
1181   "TARGET_ARM && arm_arch6 && optimize_size"
1182   "mul%.\\t%0, %2, %1"
1183   [(set_attr "conds" "set")
1184    (set_attr "insn" "muls")]
1187 (define_insn "*mulsi_compare0_scratch"
1188   [(set (reg:CC_NOOV CC_REGNUM)
1189         (compare:CC_NOOV (mult:SI
1190                           (match_operand:SI 2 "s_register_operand" "r,r")
1191                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1192                          (const_int 0)))
1193    (clobber (match_scratch:SI 0 "=&r,&r"))]
1194   "TARGET_ARM && !arm_arch6"
1195   "mul%.\\t%0, %2, %1"
1196   [(set_attr "conds" "set")
1197    (set_attr "insn" "muls")]
1200 (define_insn "*mulsi_compare0_scratch_v6"
1201   [(set (reg:CC_NOOV CC_REGNUM)
1202         (compare:CC_NOOV (mult:SI
1203                           (match_operand:SI 2 "s_register_operand" "r")
1204                           (match_operand:SI 1 "s_register_operand" "r"))
1205                          (const_int 0)))
1206    (clobber (match_scratch:SI 0 "=r"))]
1207   "TARGET_ARM && arm_arch6 && optimize_size"
1208   "mul%.\\t%0, %2, %1"
1209   [(set_attr "conds" "set")
1210    (set_attr "insn" "muls")]
1213 ;; Unnamed templates to match MLA instruction.
1215 (define_insn "*mulsi3addsi"
1216   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1217         (plus:SI
1218           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1219                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1220           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1221   "TARGET_32BIT && !arm_arch6"
1222   "mla%?\\t%0, %2, %1, %3"
1223   [(set_attr "insn" "mla")
1224    (set_attr "predicable" "yes")]
1227 (define_insn "*mulsi3addsi_v6"
1228   [(set (match_operand:SI 0 "s_register_operand" "=r")
1229         (plus:SI
1230           (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1231                    (match_operand:SI 1 "s_register_operand" "r"))
1232           (match_operand:SI 3 "s_register_operand" "r")))]
1233   "TARGET_32BIT && arm_arch6"
1234   "mla%?\\t%0, %2, %1, %3"
1235   [(set_attr "insn" "mla")
1236    (set_attr "predicable" "yes")]
1239 (define_insn "*mulsi3addsi_compare0"
1240   [(set (reg:CC_NOOV CC_REGNUM)
1241         (compare:CC_NOOV
1242          (plus:SI (mult:SI
1243                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1244                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1245                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1246          (const_int 0)))
1247    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1248         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1249                  (match_dup 3)))]
1250   "TARGET_ARM && arm_arch6"
1251   "mla%.\\t%0, %2, %1, %3"
1252   [(set_attr "conds" "set")
1253    (set_attr "insn" "mlas")]
1256 (define_insn "*mulsi3addsi_compare0_v6"
1257   [(set (reg:CC_NOOV CC_REGNUM)
1258         (compare:CC_NOOV
1259          (plus:SI (mult:SI
1260                    (match_operand:SI 2 "s_register_operand" "r")
1261                    (match_operand:SI 1 "s_register_operand" "r"))
1262                   (match_operand:SI 3 "s_register_operand" "r"))
1263          (const_int 0)))
1264    (set (match_operand:SI 0 "s_register_operand" "=r")
1265         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1266                  (match_dup 3)))]
1267   "TARGET_ARM && arm_arch6 && optimize_size"
1268   "mla%.\\t%0, %2, %1, %3"
1269   [(set_attr "conds" "set")
1270    (set_attr "insn" "mlas")]
1273 (define_insn "*mulsi3addsi_compare0_scratch"
1274   [(set (reg:CC_NOOV CC_REGNUM)
1275         (compare:CC_NOOV
1276          (plus:SI (mult:SI
1277                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1278                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1279                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1280          (const_int 0)))
1281    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1282   "TARGET_ARM && !arm_arch6"
1283   "mla%.\\t%0, %2, %1, %3"
1284   [(set_attr "conds" "set")
1285    (set_attr "insn" "mlas")]
1288 (define_insn "*mulsi3addsi_compare0_scratch_v6"
1289   [(set (reg:CC_NOOV CC_REGNUM)
1290         (compare:CC_NOOV
1291          (plus:SI (mult:SI
1292                    (match_operand:SI 2 "s_register_operand" "r")
1293                    (match_operand:SI 1 "s_register_operand" "r"))
1294                   (match_operand:SI 3 "s_register_operand" "r"))
1295          (const_int 0)))
1296    (clobber (match_scratch:SI 0 "=r"))]
1297   "TARGET_ARM && arm_arch6 && optimize_size"
1298   "mla%.\\t%0, %2, %1, %3"
1299   [(set_attr "conds" "set")
1300    (set_attr "insn" "mlas")]
1303 (define_insn "*mulsi3subsi"
1304   [(set (match_operand:SI 0 "s_register_operand" "=r")
1305         (minus:SI
1306           (match_operand:SI 3 "s_register_operand" "r")
1307           (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1308                    (match_operand:SI 1 "s_register_operand" "r"))))]
1309   "TARGET_32BIT && arm_arch_thumb2"
1310   "mls%?\\t%0, %2, %1, %3"
1311   [(set_attr "insn" "mla")
1312    (set_attr "predicable" "yes")]
1315 ;; Unnamed template to match long long multiply-accumulate (smlal)
1317 (define_insn "*mulsidi3adddi"
1318   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1319         (plus:DI
1320          (mult:DI
1321           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1322           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1323          (match_operand:DI 1 "s_register_operand" "0")))]
1324   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1325   "smlal%?\\t%Q0, %R0, %3, %2"
1326   [(set_attr "insn" "smlal")
1327    (set_attr "predicable" "yes")]
1330 (define_insn "*mulsidi3adddi_v6"
1331   [(set (match_operand:DI 0 "s_register_operand" "=r")
1332         (plus:DI
1333          (mult:DI
1334           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1335           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1336          (match_operand:DI 1 "s_register_operand" "0")))]
1337   "TARGET_32BIT && arm_arch6"
1338   "smlal%?\\t%Q0, %R0, %3, %2"
1339   [(set_attr "insn" "smlal")
1340    (set_attr "predicable" "yes")]
1343 ;; 32x32->64 widening multiply.
1344 ;; As with mulsi3, the only difference between the v3-5 and v6+
1345 ;; versions of these patterns is the requirement that the output not
1346 ;; overlap the inputs, but that still means we have to have a named
1347 ;; expander and two different starred insns.
1349 (define_expand "mulsidi3"
1350   [(set (match_operand:DI 0 "s_register_operand" "")
1351         (mult:DI
1352          (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1353          (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1354   "TARGET_32BIT && arm_arch3m"
1355   ""
1358 (define_insn "*mulsidi3_nov6"
1359   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1360         (mult:DI
1361          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1362          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1363   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1364   "smull%?\\t%Q0, %R0, %1, %2"
1365   [(set_attr "insn" "smull")
1366    (set_attr "predicable" "yes")]
1369 (define_insn "*mulsidi3_v6"
1370   [(set (match_operand:DI 0 "s_register_operand" "=r")
1371         (mult:DI
1372          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1373          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1374   "TARGET_32BIT && arm_arch6"
1375   "smull%?\\t%Q0, %R0, %1, %2"
1376   [(set_attr "insn" "smull")
1377    (set_attr "predicable" "yes")]
1380 (define_expand "umulsidi3"
1381   [(set (match_operand:DI 0 "s_register_operand" "")
1382         (mult:DI
1383          (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1384          (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1385   "TARGET_32BIT && arm_arch3m"
1386   ""
1389 (define_insn "*umulsidi3_nov6"
1390   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1391         (mult:DI
1392          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1393          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1394   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1395   "umull%?\\t%Q0, %R0, %1, %2"
1396   [(set_attr "insn" "umull")
1397    (set_attr "predicable" "yes")]
1400 (define_insn "*umulsidi3_v6"
1401   [(set (match_operand:DI 0 "s_register_operand" "=r")
1402         (mult:DI
1403          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1404          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1405   "TARGET_32BIT && arm_arch6"
1406   "umull%?\\t%Q0, %R0, %1, %2"
1407   [(set_attr "insn" "umull")
1408    (set_attr "predicable" "yes")]
1411 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1413 (define_insn "*umulsidi3adddi"
1414   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1415         (plus:DI
1416          (mult:DI
1417           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1418           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1419          (match_operand:DI 1 "s_register_operand" "0")))]
1420   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1421   "umlal%?\\t%Q0, %R0, %3, %2"
1422   [(set_attr "insn" "umlal")
1423    (set_attr "predicable" "yes")]
1426 (define_insn "*umulsidi3adddi_v6"
1427   [(set (match_operand:DI 0 "s_register_operand" "=r")
1428         (plus:DI
1429          (mult:DI
1430           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1431           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1432          (match_operand:DI 1 "s_register_operand" "0")))]
1433   "TARGET_32BIT && arm_arch6"
1434   "umlal%?\\t%Q0, %R0, %3, %2"
1435   [(set_attr "insn" "umlal")
1436    (set_attr "predicable" "yes")]
1439 (define_expand "smulsi3_highpart"
1440   [(parallel
1441     [(set (match_operand:SI 0 "s_register_operand" "")
1442           (truncate:SI
1443            (lshiftrt:DI
1444             (mult:DI
1445              (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1446              (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1447             (const_int 32))))
1448      (clobber (match_scratch:SI 3 ""))])]
1449   "TARGET_32BIT && arm_arch3m"
1450   ""
1453 (define_insn "*smulsi3_highpart_nov6"
1454   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1455         (truncate:SI
1456          (lshiftrt:DI
1457           (mult:DI
1458            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1459            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1460           (const_int 32))))
1461    (clobber (match_scratch:SI 3 "=&r,&r"))]
1462   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1463   "smull%?\\t%3, %0, %2, %1"
1464   [(set_attr "insn" "smull")
1465    (set_attr "predicable" "yes")]
1468 (define_insn "*smulsi3_highpart_v6"
1469   [(set (match_operand:SI 0 "s_register_operand" "=r")
1470         (truncate:SI
1471          (lshiftrt:DI
1472           (mult:DI
1473            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1474            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1475           (const_int 32))))
1476    (clobber (match_scratch:SI 3 "=r"))]
1477   "TARGET_32BIT && arm_arch6"
1478   "smull%?\\t%3, %0, %2, %1"
1479   [(set_attr "insn" "smull")
1480    (set_attr "predicable" "yes")]
1483 (define_expand "umulsi3_highpart"
1484   [(parallel
1485     [(set (match_operand:SI 0 "s_register_operand" "")
1486           (truncate:SI
1487            (lshiftrt:DI
1488             (mult:DI
1489              (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1490               (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1491             (const_int 32))))
1492      (clobber (match_scratch:SI 3 ""))])]
1493   "TARGET_32BIT && arm_arch3m"
1494   ""
1497 (define_insn "*umulsi3_highpart_nov6"
1498   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1499         (truncate:SI
1500          (lshiftrt:DI
1501           (mult:DI
1502            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1503            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1504           (const_int 32))))
1505    (clobber (match_scratch:SI 3 "=&r,&r"))]
1506   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1507   "umull%?\\t%3, %0, %2, %1"
1508   [(set_attr "insn" "umull")
1509    (set_attr "predicable" "yes")]
1512 (define_insn "*umulsi3_highpart_v6"
1513   [(set (match_operand:SI 0 "s_register_operand" "=r")
1514         (truncate:SI
1515          (lshiftrt:DI
1516           (mult:DI
1517            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1518            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1519           (const_int 32))))
1520    (clobber (match_scratch:SI 3 "=r"))]
1521   "TARGET_32BIT && arm_arch6"
1522   "umull%?\\t%3, %0, %2, %1"
1523   [(set_attr "insn" "umull")
1524    (set_attr "predicable" "yes")]
1527 (define_insn "mulhisi3"
1528   [(set (match_operand:SI 0 "s_register_operand" "=r")
1529         (mult:SI (sign_extend:SI
1530                   (match_operand:HI 1 "s_register_operand" "%r"))
1531                  (sign_extend:SI
1532                   (match_operand:HI 2 "s_register_operand" "r"))))]
1533   "TARGET_DSP_MULTIPLY"
1534   "smulbb%?\\t%0, %1, %2"
1535   [(set_attr "insn" "smulxy")
1536    (set_attr "predicable" "yes")]
1539 (define_insn "*mulhisi3tb"
1540   [(set (match_operand:SI 0 "s_register_operand" "=r")
1541         (mult:SI (ashiftrt:SI
1542                   (match_operand:SI 1 "s_register_operand" "r")
1543                   (const_int 16))
1544                  (sign_extend:SI
1545                   (match_operand:HI 2 "s_register_operand" "r"))))]
1546   "TARGET_DSP_MULTIPLY"
1547   "smultb%?\\t%0, %1, %2"
1548   [(set_attr "insn" "smulxy")
1549    (set_attr "predicable" "yes")]
1552 (define_insn "*mulhisi3bt"
1553   [(set (match_operand:SI 0 "s_register_operand" "=r")
1554         (mult:SI (sign_extend:SI
1555                   (match_operand:HI 1 "s_register_operand" "r"))
1556                  (ashiftrt:SI
1557                   (match_operand:SI 2 "s_register_operand" "r")
1558                   (const_int 16))))]
1559   "TARGET_DSP_MULTIPLY"
1560   "smulbt%?\\t%0, %1, %2"
1561   [(set_attr "insn" "smulxy")
1562    (set_attr "predicable" "yes")]
1565 (define_insn "*mulhisi3tt"
1566   [(set (match_operand:SI 0 "s_register_operand" "=r")
1567         (mult:SI (ashiftrt:SI
1568                   (match_operand:SI 1 "s_register_operand" "r")
1569                   (const_int 16))
1570                  (ashiftrt:SI
1571                   (match_operand:SI 2 "s_register_operand" "r")
1572                   (const_int 16))))]
1573   "TARGET_DSP_MULTIPLY"
1574   "smultt%?\\t%0, %1, %2"
1575   [(set_attr "insn" "smulxy")
1576    (set_attr "predicable" "yes")]
1579 (define_insn "*mulhisi3addsi"
1580   [(set (match_operand:SI 0 "s_register_operand" "=r")
1581         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1582                  (mult:SI (sign_extend:SI
1583                            (match_operand:HI 2 "s_register_operand" "%r"))
1584                           (sign_extend:SI
1585                            (match_operand:HI 3 "s_register_operand" "r")))))]
1586   "TARGET_DSP_MULTIPLY"
1587   "smlabb%?\\t%0, %2, %3, %1"
1588   [(set_attr "insn" "smlaxy")
1589    (set_attr "predicable" "yes")]
1592 (define_insn "*mulhidi3adddi"
1593   [(set (match_operand:DI 0 "s_register_operand" "=r")
1594         (plus:DI
1595           (match_operand:DI 1 "s_register_operand" "0")
1596           (mult:DI (sign_extend:DI
1597                     (match_operand:HI 2 "s_register_operand" "%r"))
1598                    (sign_extend:DI
1599                     (match_operand:HI 3 "s_register_operand" "r")))))]
1600   "TARGET_DSP_MULTIPLY"
1601   "smlalbb%?\\t%Q0, %R0, %2, %3"
1602   [(set_attr "insn" "smlalxy")
1603    (set_attr "predicable" "yes")])
1605 (define_expand "mulsf3"
1606   [(set (match_operand:SF          0 "s_register_operand" "")
1607         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1608                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1609   "TARGET_32BIT && TARGET_HARD_FLOAT"
1610   "
1611   if (TARGET_MAVERICK
1612       && !cirrus_fp_register (operands[2], SFmode))
1613     operands[2] = force_reg (SFmode, operands[2]);
1616 (define_expand "muldf3"
1617   [(set (match_operand:DF          0 "s_register_operand" "")
1618         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1619                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1620   "TARGET_32BIT && TARGET_HARD_FLOAT"
1621   "
1622   if (TARGET_MAVERICK
1623       && !cirrus_fp_register (operands[2], DFmode))
1624     operands[2] = force_reg (DFmode, operands[2]);
1627 ;; Division insns
1629 (define_expand "divsf3"
1630   [(set (match_operand:SF 0 "s_register_operand" "")
1631         (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1632                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1633   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1634   "")
1636 (define_expand "divdf3"
1637   [(set (match_operand:DF 0 "s_register_operand" "")
1638         (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1639                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1640   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1641   "")
1643 ;; Modulo insns
1645 (define_expand "modsf3"
1646   [(set (match_operand:SF 0 "s_register_operand" "")
1647         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1648                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1649   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
1650   "")
1652 (define_expand "moddf3"
1653   [(set (match_operand:DF 0 "s_register_operand" "")
1654         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1655                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1656   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
1657   "")
1659 ;; Boolean and,ior,xor insns
1661 ;; Split up double word logical operations
1663 ;; Split up simple DImode logical operations.  Simply perform the logical
1664 ;; operation on the upper and lower halves of the registers.
1665 (define_split
1666   [(set (match_operand:DI 0 "s_register_operand" "")
1667         (match_operator:DI 6 "logical_binary_operator"
1668           [(match_operand:DI 1 "s_register_operand" "")
1669            (match_operand:DI 2 "s_register_operand" "")]))]
1670   "TARGET_32BIT && reload_completed
1671    && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1672   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1673    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1674   "
1675   {
1676     operands[3] = gen_highpart (SImode, operands[0]);
1677     operands[0] = gen_lowpart (SImode, operands[0]);
1678     operands[4] = gen_highpart (SImode, operands[1]);
1679     operands[1] = gen_lowpart (SImode, operands[1]);
1680     operands[5] = gen_highpart (SImode, operands[2]);
1681     operands[2] = gen_lowpart (SImode, operands[2]);
1682   }"
1685 (define_split
1686   [(set (match_operand:DI 0 "s_register_operand" "")
1687         (match_operator:DI 6 "logical_binary_operator"
1688           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1689            (match_operand:DI 1 "s_register_operand" "")]))]
1690   "TARGET_32BIT && reload_completed"
1691   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1692    (set (match_dup 3) (match_op_dup:SI 6
1693                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1694                          (match_dup 4)]))]
1695   "
1696   {
1697     operands[3] = gen_highpart (SImode, operands[0]);
1698     operands[0] = gen_lowpart (SImode, operands[0]);
1699     operands[4] = gen_highpart (SImode, operands[1]);
1700     operands[1] = gen_lowpart (SImode, operands[1]);
1701     operands[5] = gen_highpart (SImode, operands[2]);
1702     operands[2] = gen_lowpart (SImode, operands[2]);
1703   }"
1706 ;; The zero extend of operand 2 means we can just copy the high part of
1707 ;; operand1 into operand0.
1708 (define_split
1709   [(set (match_operand:DI 0 "s_register_operand" "")
1710         (ior:DI
1711           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1712           (match_operand:DI 1 "s_register_operand" "")))]
1713   "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
1714   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1715    (set (match_dup 3) (match_dup 4))]
1716   "
1717   {
1718     operands[4] = gen_highpart (SImode, operands[1]);
1719     operands[3] = gen_highpart (SImode, operands[0]);
1720     operands[0] = gen_lowpart (SImode, operands[0]);
1721     operands[1] = gen_lowpart (SImode, operands[1]);
1722   }"
1725 ;; The zero extend of operand 2 means we can just copy the high part of
1726 ;; operand1 into operand0.
1727 (define_split
1728   [(set (match_operand:DI 0 "s_register_operand" "")
1729         (xor:DI
1730           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1731           (match_operand:DI 1 "s_register_operand" "")))]
1732   "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
1733   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1734    (set (match_dup 3) (match_dup 4))]
1735   "
1736   {
1737     operands[4] = gen_highpart (SImode, operands[1]);
1738     operands[3] = gen_highpart (SImode, operands[0]);
1739     operands[0] = gen_lowpart (SImode, operands[0]);
1740     operands[1] = gen_lowpart (SImode, operands[1]);
1741   }"
1744 (define_insn "anddi3"
1745   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1746         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1747                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1748   "TARGET_32BIT && ! TARGET_IWMMXT"
1749   "#"
1750   [(set_attr "length" "8")]
1753 (define_insn_and_split "*anddi_zesidi_di"
1754   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1755         (and:DI (zero_extend:DI
1756                  (match_operand:SI 2 "s_register_operand" "r,r"))
1757                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1758   "TARGET_32BIT"
1759   "#"
1760   "TARGET_32BIT && reload_completed"
1761   ; The zero extend of operand 2 clears the high word of the output
1762   ; operand.
1763   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1764    (set (match_dup 3) (const_int 0))]
1765   "
1766   {
1767     operands[3] = gen_highpart (SImode, operands[0]);
1768     operands[0] = gen_lowpart (SImode, operands[0]);
1769     operands[1] = gen_lowpart (SImode, operands[1]);
1770   }"
1771   [(set_attr "length" "8")]
1774 (define_insn "*anddi_sesdi_di"
1775   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1776         (and:DI (sign_extend:DI
1777                  (match_operand:SI 2 "s_register_operand" "r,r"))
1778                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1779   "TARGET_32BIT"
1780   "#"
1781   [(set_attr "length" "8")]
1784 (define_expand "andsi3"
1785   [(set (match_operand:SI         0 "s_register_operand" "")
1786         (and:SI (match_operand:SI 1 "s_register_operand" "")
1787                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1788   "TARGET_EITHER"
1789   "
1790   if (TARGET_32BIT)
1791     {
1792       if (GET_CODE (operands[2]) == CONST_INT)
1793         {
1794           arm_split_constant (AND, SImode, NULL_RTX,
1795                               INTVAL (operands[2]), operands[0],
1796                               operands[1], optimize && can_create_pseudo_p ());
1798           DONE;
1799         }
1800     }
1801   else /* TARGET_THUMB1 */
1802     {
1803       if (GET_CODE (operands[2]) != CONST_INT)
1804         operands[2] = force_reg (SImode, operands[2]);
1805       else
1806         {
1807           int i;
1808           
1809           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1810             {
1811               operands[2] = force_reg (SImode,
1812                                        GEN_INT (~INTVAL (operands[2])));
1813               
1814               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1815               
1816               DONE;
1817             }
1819           for (i = 9; i <= 31; i++)
1820             {
1821               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1822                 {
1823                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1824                                         const0_rtx));
1825                   DONE;
1826                 }
1827               else if ((((HOST_WIDE_INT) 1) << i) - 1
1828                        == ~INTVAL (operands[2]))
1829                 {
1830                   rtx shift = GEN_INT (i);
1831                   rtx reg = gen_reg_rtx (SImode);
1832                 
1833                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1834                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1835                   
1836                   DONE;
1837                 }
1838             }
1840           operands[2] = force_reg (SImode, operands[2]);
1841         }
1842     }
1843   "
1846 ; ??? Check split length for Thumb-2
1847 (define_insn_and_split "*arm_andsi3_insn"
1848   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1849         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1850                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1851   "TARGET_32BIT"
1852   "@
1853    and%?\\t%0, %1, %2
1854    bic%?\\t%0, %1, #%B2
1855    #"
1856   "TARGET_32BIT
1857    && GET_CODE (operands[2]) == CONST_INT
1858    && !(const_ok_for_arm (INTVAL (operands[2]))
1859         || const_ok_for_arm (~INTVAL (operands[2])))"
1860   [(clobber (const_int 0))]
1861   "
1862   arm_split_constant  (AND, SImode, curr_insn, 
1863                        INTVAL (operands[2]), operands[0], operands[1], 0);
1864   DONE;
1865   "
1866   [(set_attr "length" "4,4,16")
1867    (set_attr "predicable" "yes")]
1870 (define_insn "*thumb1_andsi3_insn"
1871   [(set (match_operand:SI         0 "register_operand" "=l")
1872         (and:SI (match_operand:SI 1 "register_operand" "%0")
1873                 (match_operand:SI 2 "register_operand" "l")))]
1874   "TARGET_THUMB1"
1875   "and\\t%0, %0, %2"
1876   [(set_attr "length" "2")]
1879 (define_insn "*andsi3_compare0"
1880   [(set (reg:CC_NOOV CC_REGNUM)
1881         (compare:CC_NOOV
1882          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1883                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1884          (const_int 0)))
1885    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1886         (and:SI (match_dup 1) (match_dup 2)))]
1887   "TARGET_32BIT"
1888   "@
1889    and%.\\t%0, %1, %2
1890    bic%.\\t%0, %1, #%B2"
1891   [(set_attr "conds" "set")]
1894 (define_insn "*andsi3_compare0_scratch"
1895   [(set (reg:CC_NOOV CC_REGNUM)
1896         (compare:CC_NOOV
1897          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1898                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1899          (const_int 0)))
1900    (clobber (match_scratch:SI 2 "=X,r"))]
1901   "TARGET_32BIT"
1902   "@
1903    tst%?\\t%0, %1
1904    bic%.\\t%2, %0, #%B1"
1905   [(set_attr "conds" "set")]
1908 (define_insn "*zeroextractsi_compare0_scratch"
1909   [(set (reg:CC_NOOV CC_REGNUM)
1910         (compare:CC_NOOV (zero_extract:SI
1911                           (match_operand:SI 0 "s_register_operand" "r")
1912                           (match_operand 1 "const_int_operand" "n")
1913                           (match_operand 2 "const_int_operand" "n"))
1914                          (const_int 0)))]
1915   "TARGET_32BIT
1916   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1917       && INTVAL (operands[1]) > 0 
1918       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1919       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1920   "*
1921   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1922                          << INTVAL (operands[2]));
1923   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1924   return \"\";
1925   "
1926   [(set_attr "conds" "set")]
1929 (define_insn_and_split "*ne_zeroextractsi"
1930   [(set (match_operand:SI 0 "s_register_operand" "=r")
1931         (ne:SI (zero_extract:SI
1932                 (match_operand:SI 1 "s_register_operand" "r")
1933                 (match_operand:SI 2 "const_int_operand" "n")
1934                 (match_operand:SI 3 "const_int_operand" "n"))
1935                (const_int 0)))
1936    (clobber (reg:CC CC_REGNUM))]
1937   "TARGET_32BIT
1938    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1939        && INTVAL (operands[2]) > 0 
1940        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1941        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1942   "#"
1943   "TARGET_32BIT
1944    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1945        && INTVAL (operands[2]) > 0 
1946        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1947        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1948   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1949                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1950                                     (const_int 0)))
1951               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1952    (set (match_dup 0)
1953         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1954                          (match_dup 0) (const_int 1)))]
1955   "
1956   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1957                          << INTVAL (operands[3])); 
1958   "
1959   [(set_attr "conds" "clob")
1960    (set (attr "length")
1961         (if_then_else (eq_attr "is_thumb" "yes")
1962                       (const_int 12)
1963                       (const_int 8)))]
1966 (define_insn_and_split "*ne_zeroextractsi_shifted"
1967   [(set (match_operand:SI 0 "s_register_operand" "=r")
1968         (ne:SI (zero_extract:SI
1969                 (match_operand:SI 1 "s_register_operand" "r")
1970                 (match_operand:SI 2 "const_int_operand" "n")
1971                 (const_int 0))
1972                (const_int 0)))
1973    (clobber (reg:CC CC_REGNUM))]
1974   "TARGET_ARM"
1975   "#"
1976   "TARGET_ARM"
1977   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1978                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1979                                     (const_int 0)))
1980               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1981    (set (match_dup 0)
1982         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1983                          (match_dup 0) (const_int 1)))]
1984   "
1985   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1986   "
1987   [(set_attr "conds" "clob")
1988    (set_attr "length" "8")]
1991 (define_insn_and_split "*ite_ne_zeroextractsi"
1992   [(set (match_operand:SI 0 "s_register_operand" "=r")
1993         (if_then_else:SI (ne (zero_extract:SI
1994                               (match_operand:SI 1 "s_register_operand" "r")
1995                               (match_operand:SI 2 "const_int_operand" "n")
1996                               (match_operand:SI 3 "const_int_operand" "n"))
1997                              (const_int 0))
1998                          (match_operand:SI 4 "arm_not_operand" "rIK")
1999                          (const_int 0)))
2000    (clobber (reg:CC CC_REGNUM))]
2001   "TARGET_ARM
2002    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2003        && INTVAL (operands[2]) > 0 
2004        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2005        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2006    && !reg_overlap_mentioned_p (operands[0], operands[4])"
2007   "#"
2008   "TARGET_ARM
2009    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2010        && INTVAL (operands[2]) > 0 
2011        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2012        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2013    && !reg_overlap_mentioned_p (operands[0], operands[4])"
2014   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2015                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2016                                     (const_int 0)))
2017               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2018    (set (match_dup 0)
2019         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2020                          (match_dup 0) (match_dup 4)))]
2021   "
2022   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2023                          << INTVAL (operands[3])); 
2024   "
2025   [(set_attr "conds" "clob")
2026    (set_attr "length" "8")]
2029 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2030   [(set (match_operand:SI 0 "s_register_operand" "=r")
2031         (if_then_else:SI (ne (zero_extract:SI
2032                               (match_operand:SI 1 "s_register_operand" "r")
2033                               (match_operand:SI 2 "const_int_operand" "n")
2034                               (const_int 0))
2035                              (const_int 0))
2036                          (match_operand:SI 3 "arm_not_operand" "rIK")
2037                          (const_int 0)))
2038    (clobber (reg:CC CC_REGNUM))]
2039   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2040   "#"
2041   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2042   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2043                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2044                                     (const_int 0)))
2045               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2046    (set (match_dup 0)
2047         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2048                          (match_dup 0) (match_dup 3)))]
2049   "
2050   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2051   "
2052   [(set_attr "conds" "clob")
2053    (set_attr "length" "8")]
2056 (define_split
2057   [(set (match_operand:SI 0 "s_register_operand" "")
2058         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
2059                          (match_operand:SI 2 "const_int_operand" "")
2060                          (match_operand:SI 3 "const_int_operand" "")))
2061    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2062   "TARGET_THUMB1"
2063   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
2064    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
2065   "{
2066      HOST_WIDE_INT temp = INTVAL (operands[2]);
2068      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2069      operands[3] = GEN_INT (32 - temp);
2070    }"
2073 ;; ??? Use Thumb-2 has bitfield insert/extract instructions.
2074 (define_split
2075   [(set (match_operand:SI 0 "s_register_operand" "")
2076         (match_operator:SI 1 "shiftable_operator"
2077          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2078                            (match_operand:SI 3 "const_int_operand" "")
2079                            (match_operand:SI 4 "const_int_operand" ""))
2080           (match_operand:SI 5 "s_register_operand" "")]))
2081    (clobber (match_operand:SI 6 "s_register_operand" ""))]
2082   "TARGET_ARM"
2083   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2084    (set (match_dup 0)
2085         (match_op_dup 1
2086          [(lshiftrt:SI (match_dup 6) (match_dup 4))
2087           (match_dup 5)]))]
2088   "{
2089      HOST_WIDE_INT temp = INTVAL (operands[3]);
2091      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2092      operands[4] = GEN_INT (32 - temp);
2093    }"
2095   
2096 (define_split
2097   [(set (match_operand:SI 0 "s_register_operand" "")
2098         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2099                          (match_operand:SI 2 "const_int_operand" "")
2100                          (match_operand:SI 3 "const_int_operand" "")))]
2101   "TARGET_THUMB1"
2102   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2103    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2104   "{
2105      HOST_WIDE_INT temp = INTVAL (operands[2]);
2107      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2108      operands[3] = GEN_INT (32 - temp);
2109    }"
2112 (define_split
2113   [(set (match_operand:SI 0 "s_register_operand" "")
2114         (match_operator:SI 1 "shiftable_operator"
2115          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2116                            (match_operand:SI 3 "const_int_operand" "")
2117                            (match_operand:SI 4 "const_int_operand" ""))
2118           (match_operand:SI 5 "s_register_operand" "")]))
2119    (clobber (match_operand:SI 6 "s_register_operand" ""))]
2120   "TARGET_ARM"
2121   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2122    (set (match_dup 0)
2123         (match_op_dup 1
2124          [(ashiftrt:SI (match_dup 6) (match_dup 4))
2125           (match_dup 5)]))]
2126   "{
2127      HOST_WIDE_INT temp = INTVAL (operands[3]);
2129      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2130      operands[4] = GEN_INT (32 - temp);
2131    }"
2133   
2134 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
2135 ;;; represented by the bitfield, then this will produce incorrect results.
2136 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
2137 ;;; which have a real bit-field insert instruction, the truncation happens
2138 ;;; in the bit-field insert instruction itself.  Since arm does not have a
2139 ;;; bit-field insert instruction, we would have to emit code here to truncate
2140 ;;; the value before we insert.  This loses some of the advantage of having
2141 ;;; this insv pattern, so this pattern needs to be reevalutated.
2143 ; ??? Use Thumb-2 bitfield insert/extract instructions
2144 (define_expand "insv"
2145   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
2146                          (match_operand:SI 1 "general_operand" "")
2147                          (match_operand:SI 2 "general_operand" ""))
2148         (match_operand:SI 3 "reg_or_int_operand" ""))]
2149   "TARGET_ARM"
2150   "
2151   {
2152     int start_bit = INTVAL (operands[2]);
2153     int width = INTVAL (operands[1]);
2154     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2155     rtx target, subtarget;
2157     target = operands[0];
2158     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
2159        subreg as the final target.  */
2160     if (GET_CODE (target) == SUBREG)
2161       {
2162         subtarget = gen_reg_rtx (SImode);
2163         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2164             < GET_MODE_SIZE (SImode))
2165           target = SUBREG_REG (target);
2166       }
2167     else
2168       subtarget = target;    
2170     if (GET_CODE (operands[3]) == CONST_INT)
2171       {
2172         /* Since we are inserting a known constant, we may be able to
2173            reduce the number of bits that we have to clear so that
2174            the mask becomes simple.  */
2175         /* ??? This code does not check to see if the new mask is actually
2176            simpler.  It may not be.  */
2177         rtx op1 = gen_reg_rtx (SImode);
2178         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
2179            start of this pattern.  */
2180         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2181         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2183         emit_insn (gen_andsi3 (op1, operands[0],
2184                                gen_int_mode (~mask2, SImode)));
2185         emit_insn (gen_iorsi3 (subtarget, op1,
2186                                gen_int_mode (op3_value << start_bit, SImode)));
2187       }
2188     else if (start_bit == 0
2189              && !(const_ok_for_arm (mask)
2190                   || const_ok_for_arm (~mask)))
2191       {
2192         /* A Trick, since we are setting the bottom bits in the word,
2193            we can shift operand[3] up, operand[0] down, OR them together
2194            and rotate the result back again.  This takes 3 insns, and
2195            the third might be mergeable into another op.  */
2196         /* The shift up copes with the possibility that operand[3] is
2197            wider than the bitfield.  */
2198         rtx op0 = gen_reg_rtx (SImode);
2199         rtx op1 = gen_reg_rtx (SImode);
2201         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2202         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2203         emit_insn (gen_iorsi3  (op1, op1, op0));
2204         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2205       }
2206     else if ((width + start_bit == 32)
2207              && !(const_ok_for_arm (mask)
2208                   || const_ok_for_arm (~mask)))
2209       {
2210         /* Similar trick, but slightly less efficient.  */
2212         rtx op0 = gen_reg_rtx (SImode);
2213         rtx op1 = gen_reg_rtx (SImode);
2215         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2216         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2217         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2218         emit_insn (gen_iorsi3 (subtarget, op1, op0));
2219       }
2220     else
2221       {
2222         rtx op0 = gen_int_mode (mask, SImode);
2223         rtx op1 = gen_reg_rtx (SImode);
2224         rtx op2 = gen_reg_rtx (SImode);
2226         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2227           {
2228             rtx tmp = gen_reg_rtx (SImode);
2230             emit_insn (gen_movsi (tmp, op0));
2231             op0 = tmp;
2232           }
2234         /* Mask out any bits in operand[3] that are not needed.  */
2235            emit_insn (gen_andsi3 (op1, operands[3], op0));
2237         if (GET_CODE (op0) == CONST_INT
2238             && (const_ok_for_arm (mask << start_bit)
2239                 || const_ok_for_arm (~(mask << start_bit))))
2240           {
2241             op0 = gen_int_mode (~(mask << start_bit), SImode);
2242             emit_insn (gen_andsi3 (op2, operands[0], op0));
2243           }
2244         else
2245           {
2246             if (GET_CODE (op0) == CONST_INT)
2247               {
2248                 rtx tmp = gen_reg_rtx (SImode);
2250                 emit_insn (gen_movsi (tmp, op0));
2251                 op0 = tmp;
2252               }
2254             if (start_bit != 0)
2255               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
2256             
2257             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2258           }
2260         if (start_bit != 0)
2261           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
2263         emit_insn (gen_iorsi3 (subtarget, op1, op2));
2264       }
2266     if (subtarget != target)
2267       {
2268         /* If TARGET is still a SUBREG, then it must be wider than a word,
2269            so we must be careful only to set the subword we were asked to.  */
2270         if (GET_CODE (target) == SUBREG)
2271           emit_move_insn (target, subtarget);
2272         else
2273           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2274       }
2276     DONE;
2277   }"
2280 ; constants for op 2 will never be given to these patterns.
2281 (define_insn_and_split "*anddi_notdi_di"
2282   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2283         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2284                 (match_operand:DI 2 "s_register_operand" "0,r")))]
2285   "TARGET_32BIT"
2286   "#"
2287   "TARGET_32BIT && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2288   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2289    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2290   "
2291   {
2292     operands[3] = gen_highpart (SImode, operands[0]);
2293     operands[0] = gen_lowpart (SImode, operands[0]);
2294     operands[4] = gen_highpart (SImode, operands[1]);
2295     operands[1] = gen_lowpart (SImode, operands[1]);
2296     operands[5] = gen_highpart (SImode, operands[2]);
2297     operands[2] = gen_lowpart (SImode, operands[2]);
2298   }"
2299   [(set_attr "length" "8")
2300    (set_attr "predicable" "yes")]
2302   
2303 (define_insn_and_split "*anddi_notzesidi_di"
2304   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2305         (and:DI (not:DI (zero_extend:DI
2306                          (match_operand:SI 2 "s_register_operand" "r,r")))
2307                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2308   "TARGET_32BIT"
2309   "@
2310    bic%?\\t%Q0, %Q1, %2
2311    #"
2312   ; (not (zero_extend ...)) allows us to just copy the high word from
2313   ; operand1 to operand0.
2314   "TARGET_32BIT
2315    && reload_completed
2316    && operands[0] != operands[1]"
2317   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2318    (set (match_dup 3) (match_dup 4))]
2319   "
2320   {
2321     operands[3] = gen_highpart (SImode, operands[0]);
2322     operands[0] = gen_lowpart (SImode, operands[0]);
2323     operands[4] = gen_highpart (SImode, operands[1]);
2324     operands[1] = gen_lowpart (SImode, operands[1]);
2325   }"
2326   [(set_attr "length" "4,8")
2327    (set_attr "predicable" "yes")]
2329   
2330 (define_insn_and_split "*anddi_notsesidi_di"
2331   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2332         (and:DI (not:DI (sign_extend:DI
2333                          (match_operand:SI 2 "s_register_operand" "r,r")))
2334                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2335   "TARGET_32BIT"
2336   "#"
2337   "TARGET_32BIT && reload_completed"
2338   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2339    (set (match_dup 3) (and:SI (not:SI
2340                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2341                                (match_dup 4)))]
2342   "
2343   {
2344     operands[3] = gen_highpart (SImode, operands[0]);
2345     operands[0] = gen_lowpart (SImode, operands[0]);
2346     operands[4] = gen_highpart (SImode, operands[1]);
2347     operands[1] = gen_lowpart (SImode, operands[1]);
2348   }"
2349   [(set_attr "length" "8")
2350    (set_attr "predicable" "yes")]
2352   
2353 (define_insn "andsi_notsi_si"
2354   [(set (match_operand:SI 0 "s_register_operand" "=r")
2355         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2356                 (match_operand:SI 1 "s_register_operand" "r")))]
2357   "TARGET_32BIT"
2358   "bic%?\\t%0, %1, %2"
2359   [(set_attr "predicable" "yes")]
2362 (define_insn "bicsi3"
2363   [(set (match_operand:SI                 0 "register_operand" "=l")
2364         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2365                 (match_operand:SI         2 "register_operand" "0")))]
2366   "TARGET_THUMB1"
2367   "bic\\t%0, %0, %1"
2368   [(set_attr "length" "2")]
2371 (define_insn "andsi_not_shiftsi_si"
2372   [(set (match_operand:SI 0 "s_register_operand" "=r")
2373         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2374                          [(match_operand:SI 2 "s_register_operand" "r")
2375                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2376                 (match_operand:SI 1 "s_register_operand" "r")))]
2377   "TARGET_ARM"
2378   "bic%?\\t%0, %1, %2%S4"
2379   [(set_attr "predicable" "yes")
2380    (set_attr "shift" "2")
2381    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2382                       (const_string "alu_shift")
2383                       (const_string "alu_shift_reg")))]
2386 (define_insn "*andsi_notsi_si_compare0"
2387   [(set (reg:CC_NOOV CC_REGNUM)
2388         (compare:CC_NOOV
2389          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2390                  (match_operand:SI 1 "s_register_operand" "r"))
2391          (const_int 0)))
2392    (set (match_operand:SI 0 "s_register_operand" "=r")
2393         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2394   "TARGET_32BIT"
2395   "bic%.\\t%0, %1, %2"
2396   [(set_attr "conds" "set")]
2399 (define_insn "*andsi_notsi_si_compare0_scratch"
2400   [(set (reg:CC_NOOV CC_REGNUM)
2401         (compare:CC_NOOV
2402          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2403                  (match_operand:SI 1 "s_register_operand" "r"))
2404          (const_int 0)))
2405    (clobber (match_scratch:SI 0 "=r"))]
2406   "TARGET_32BIT"
2407   "bic%.\\t%0, %1, %2"
2408   [(set_attr "conds" "set")]
2411 (define_insn "iordi3"
2412   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2413         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2414                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2415   "TARGET_32BIT && ! TARGET_IWMMXT"
2416   "#"
2417   [(set_attr "length" "8")
2418    (set_attr "predicable" "yes")]
2421 (define_insn "*iordi_zesidi_di"
2422   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2423         (ior:DI (zero_extend:DI
2424                  (match_operand:SI 2 "s_register_operand" "r,r"))
2425                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2426   "TARGET_32BIT"
2427   "@
2428    orr%?\\t%Q0, %Q1, %2
2429    #"
2430   [(set_attr "length" "4,8")
2431    (set_attr "predicable" "yes")]
2434 (define_insn "*iordi_sesidi_di"
2435   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2436         (ior:DI (sign_extend:DI
2437                  (match_operand:SI 2 "s_register_operand" "r,r"))
2438                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2439   "TARGET_32BIT"
2440   "#"
2441   [(set_attr "length" "8")
2442    (set_attr "predicable" "yes")]
2445 (define_expand "iorsi3"
2446   [(set (match_operand:SI         0 "s_register_operand" "")
2447         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2448                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2449   "TARGET_EITHER"
2450   "
2451   if (GET_CODE (operands[2]) == CONST_INT)
2452     {
2453       if (TARGET_32BIT)
2454         {
2455           arm_split_constant (IOR, SImode, NULL_RTX,
2456                               INTVAL (operands[2]), operands[0], operands[1],
2457                               optimize && can_create_pseudo_p ());
2458           DONE;
2459         }
2460       else /* TARGET_THUMB1 */
2461         operands [2] = force_reg (SImode, operands [2]);
2462     }
2463   "
2466 (define_insn_and_split "*arm_iorsi3"
2467   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2468         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2469                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2470   "TARGET_32BIT"
2471   "@
2472    orr%?\\t%0, %1, %2
2473    #"
2474   "TARGET_32BIT
2475    && GET_CODE (operands[2]) == CONST_INT
2476    && !const_ok_for_arm (INTVAL (operands[2]))"
2477   [(clobber (const_int 0))]
2478   "
2479   arm_split_constant (IOR, SImode, curr_insn, 
2480                       INTVAL (operands[2]), operands[0], operands[1], 0);
2481   DONE;
2482   "
2483   [(set_attr "length" "4,16")
2484    (set_attr "predicable" "yes")]
2487 (define_insn "*thumb1_iorsi3"
2488   [(set (match_operand:SI         0 "register_operand" "=l")
2489         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2490                 (match_operand:SI 2 "register_operand" "l")))]
2491   "TARGET_THUMB1"
2492   "orr\\t%0, %0, %2"
2493   [(set_attr "length" "2")]
2496 (define_peephole2
2497   [(match_scratch:SI 3 "r")
2498    (set (match_operand:SI 0 "arm_general_register_operand" "")
2499         (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2500                 (match_operand:SI 2 "const_int_operand" "")))]
2501   "TARGET_32BIT
2502    && !const_ok_for_arm (INTVAL (operands[2]))
2503    && const_ok_for_arm (~INTVAL (operands[2]))"
2504   [(set (match_dup 3) (match_dup 2))
2505    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2506   ""
2509 (define_insn "*iorsi3_compare0"
2510   [(set (reg:CC_NOOV CC_REGNUM)
2511         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2512                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2513                          (const_int 0)))
2514    (set (match_operand:SI 0 "s_register_operand" "=r")
2515         (ior:SI (match_dup 1) (match_dup 2)))]
2516   "TARGET_32BIT"
2517   "orr%.\\t%0, %1, %2"
2518   [(set_attr "conds" "set")]
2521 (define_insn "*iorsi3_compare0_scratch"
2522   [(set (reg:CC_NOOV CC_REGNUM)
2523         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2524                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2525                          (const_int 0)))
2526    (clobber (match_scratch:SI 0 "=r"))]
2527   "TARGET_32BIT"
2528   "orr%.\\t%0, %1, %2"
2529   [(set_attr "conds" "set")]
2532 (define_insn "xordi3"
2533   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2534         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2535                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2536   "TARGET_32BIT && !TARGET_IWMMXT"
2537   "#"
2538   [(set_attr "length" "8")
2539    (set_attr "predicable" "yes")]
2542 (define_insn "*xordi_zesidi_di"
2543   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2544         (xor:DI (zero_extend:DI
2545                  (match_operand:SI 2 "s_register_operand" "r,r"))
2546                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2547   "TARGET_32BIT"
2548   "@
2549    eor%?\\t%Q0, %Q1, %2
2550    #"
2551   [(set_attr "length" "4,8")
2552    (set_attr "predicable" "yes")]
2555 (define_insn "*xordi_sesidi_di"
2556   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2557         (xor:DI (sign_extend:DI
2558                  (match_operand:SI 2 "s_register_operand" "r,r"))
2559                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2560   "TARGET_32BIT"
2561   "#"
2562   [(set_attr "length" "8")
2563    (set_attr "predicable" "yes")]
2566 (define_expand "xorsi3"
2567   [(set (match_operand:SI         0 "s_register_operand" "")
2568         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2569                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2570   "TARGET_EITHER"
2571   "if (TARGET_THUMB1)
2572      if (GET_CODE (operands[2]) == CONST_INT)
2573        operands[2] = force_reg (SImode, operands[2]);
2574   "
2577 (define_insn "*arm_xorsi3"
2578   [(set (match_operand:SI         0 "s_register_operand" "=r")
2579         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2580                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2581   "TARGET_32BIT"
2582   "eor%?\\t%0, %1, %2"
2583   [(set_attr "predicable" "yes")]
2586 (define_insn "*thumb1_xorsi3"
2587   [(set (match_operand:SI         0 "register_operand" "=l")
2588         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2589                 (match_operand:SI 2 "register_operand" "l")))]
2590   "TARGET_THUMB1"
2591   "eor\\t%0, %0, %2"
2592   [(set_attr "length" "2")]
2595 (define_insn "*xorsi3_compare0"
2596   [(set (reg:CC_NOOV CC_REGNUM)
2597         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2598                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2599                          (const_int 0)))
2600    (set (match_operand:SI 0 "s_register_operand" "=r")
2601         (xor:SI (match_dup 1) (match_dup 2)))]
2602   "TARGET_32BIT"
2603   "eor%.\\t%0, %1, %2"
2604   [(set_attr "conds" "set")]
2607 (define_insn "*xorsi3_compare0_scratch"
2608   [(set (reg:CC_NOOV CC_REGNUM)
2609         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2610                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2611                          (const_int 0)))]
2612   "TARGET_32BIT"
2613   "teq%?\\t%0, %1"
2614   [(set_attr "conds" "set")]
2617 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2618 ; (NOT D) we can sometimes merge the final NOT into one of the following
2619 ; insns.
2621 (define_split
2622   [(set (match_operand:SI 0 "s_register_operand" "")
2623         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2624                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2625                 (match_operand:SI 3 "arm_rhs_operand" "")))
2626    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2627   "TARGET_32BIT"
2628   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2629                               (not:SI (match_dup 3))))
2630    (set (match_dup 0) (not:SI (match_dup 4)))]
2631   ""
2634 (define_insn "*andsi_iorsi3_notsi"
2635   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2636         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2637                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2638                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2639   "TARGET_32BIT"
2640   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2641   [(set_attr "length" "8")
2642    (set_attr "ce_count" "2")
2643    (set_attr "predicable" "yes")]
2646 ; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
2647 ; insns are available?
2648 (define_split
2649   [(set (match_operand:SI 0 "s_register_operand" "")
2650         (match_operator:SI 1 "logical_binary_operator"
2651          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2652                            (match_operand:SI 3 "const_int_operand" "")
2653                            (match_operand:SI 4 "const_int_operand" ""))
2654           (match_operator:SI 9 "logical_binary_operator"
2655            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2656                          (match_operand:SI 6 "const_int_operand" ""))
2657             (match_operand:SI 7 "s_register_operand" "")])]))
2658    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2659   "TARGET_32BIT
2660    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2661    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2662   [(set (match_dup 8)
2663         (match_op_dup 1
2664          [(ashift:SI (match_dup 2) (match_dup 4))
2665           (match_dup 5)]))
2666    (set (match_dup 0)
2667         (match_op_dup 1
2668          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2669           (match_dup 7)]))]
2670   "
2671   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2674 (define_split
2675   [(set (match_operand:SI 0 "s_register_operand" "")
2676         (match_operator:SI 1 "logical_binary_operator"
2677          [(match_operator:SI 9 "logical_binary_operator"
2678            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2679                          (match_operand:SI 6 "const_int_operand" ""))
2680             (match_operand:SI 7 "s_register_operand" "")])
2681           (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2682                            (match_operand:SI 3 "const_int_operand" "")
2683                            (match_operand:SI 4 "const_int_operand" ""))]))
2684    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2685   "TARGET_32BIT
2686    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2687    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2688   [(set (match_dup 8)
2689         (match_op_dup 1
2690          [(ashift:SI (match_dup 2) (match_dup 4))
2691           (match_dup 5)]))
2692    (set (match_dup 0)
2693         (match_op_dup 1
2694          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2695           (match_dup 7)]))]
2696   "
2697   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2700 (define_split
2701   [(set (match_operand:SI 0 "s_register_operand" "")
2702         (match_operator:SI 1 "logical_binary_operator"
2703          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2704                            (match_operand:SI 3 "const_int_operand" "")
2705                            (match_operand:SI 4 "const_int_operand" ""))
2706           (match_operator:SI 9 "logical_binary_operator"
2707            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2708                          (match_operand:SI 6 "const_int_operand" ""))
2709             (match_operand:SI 7 "s_register_operand" "")])]))
2710    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2711   "TARGET_32BIT
2712    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2713    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2714   [(set (match_dup 8)
2715         (match_op_dup 1
2716          [(ashift:SI (match_dup 2) (match_dup 4))
2717           (match_dup 5)]))
2718    (set (match_dup 0)
2719         (match_op_dup 1
2720          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2721           (match_dup 7)]))]
2722   "
2723   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2726 (define_split
2727   [(set (match_operand:SI 0 "s_register_operand" "")
2728         (match_operator:SI 1 "logical_binary_operator"
2729          [(match_operator:SI 9 "logical_binary_operator"
2730            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2731                          (match_operand:SI 6 "const_int_operand" ""))
2732             (match_operand:SI 7 "s_register_operand" "")])
2733           (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2734                            (match_operand:SI 3 "const_int_operand" "")
2735                            (match_operand:SI 4 "const_int_operand" ""))]))
2736    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2737   "TARGET_32BIT
2738    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2739    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2740   [(set (match_dup 8)
2741         (match_op_dup 1
2742          [(ashift:SI (match_dup 2) (match_dup 4))
2743           (match_dup 5)]))
2744    (set (match_dup 0)
2745         (match_op_dup 1
2746          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2747           (match_dup 7)]))]
2748   "
2749   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2753 ;; Minimum and maximum insns
2755 (define_expand "smaxsi3"
2756   [(parallel [
2757     (set (match_operand:SI 0 "s_register_operand" "")
2758          (smax:SI (match_operand:SI 1 "s_register_operand" "")
2759                   (match_operand:SI 2 "arm_rhs_operand" "")))
2760     (clobber (reg:CC CC_REGNUM))])]
2761   "TARGET_32BIT"
2762   "
2763   if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
2764     {
2765       /* No need for a clobber of the condition code register here.  */
2766       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2767                               gen_rtx_SMAX (SImode, operands[1],
2768                                             operands[2])));
2769       DONE;
2770     }
2773 (define_insn "*smax_0"
2774   [(set (match_operand:SI 0 "s_register_operand" "=r")
2775         (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2776                  (const_int 0)))]
2777   "TARGET_32BIT"
2778   "bic%?\\t%0, %1, %1, asr #31"
2779   [(set_attr "predicable" "yes")]
2782 (define_insn "*smax_m1"
2783   [(set (match_operand:SI 0 "s_register_operand" "=r")
2784         (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2785                  (const_int -1)))]
2786   "TARGET_32BIT"
2787   "orr%?\\t%0, %1, %1, asr #31"
2788   [(set_attr "predicable" "yes")]
2791 (define_insn "*arm_smax_insn"
2792   [(set (match_operand:SI          0 "s_register_operand" "=r,r")
2793         (smax:SI (match_operand:SI 1 "s_register_operand"  "%0,?r")
2794                  (match_operand:SI 2 "arm_rhs_operand"    "rI,rI")))
2795    (clobber (reg:CC CC_REGNUM))]
2796   "TARGET_ARM"
2797   "@
2798    cmp\\t%1, %2\;movlt\\t%0, %2
2799    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2800   [(set_attr "conds" "clob")
2801    (set_attr "length" "8,12")]
2804 (define_expand "sminsi3"
2805   [(parallel [
2806     (set (match_operand:SI 0 "s_register_operand" "")
2807          (smin:SI (match_operand:SI 1 "s_register_operand" "")
2808                   (match_operand:SI 2 "arm_rhs_operand" "")))
2809     (clobber (reg:CC CC_REGNUM))])]
2810   "TARGET_32BIT"
2811   "
2812   if (operands[2] == const0_rtx)
2813     {
2814       /* No need for a clobber of the condition code register here.  */
2815       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2816                               gen_rtx_SMIN (SImode, operands[1],
2817                                             operands[2])));
2818       DONE;
2819     }
2822 (define_insn "*smin_0"
2823   [(set (match_operand:SI 0 "s_register_operand" "=r")
2824         (smin:SI (match_operand:SI 1 "s_register_operand" "r")
2825                  (const_int 0)))]
2826   "TARGET_32BIT"
2827   "and%?\\t%0, %1, %1, asr #31"
2828   [(set_attr "predicable" "yes")]
2831 (define_insn "*arm_smin_insn"
2832   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2833         (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
2834                  (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
2835    (clobber (reg:CC CC_REGNUM))]
2836   "TARGET_ARM"
2837   "@
2838    cmp\\t%1, %2\;movge\\t%0, %2
2839    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2840   [(set_attr "conds" "clob")
2841    (set_attr "length" "8,12")]
2844 (define_expand "umaxsi3"
2845   [(parallel [
2846     (set (match_operand:SI 0 "s_register_operand" "")
2847          (umax:SI (match_operand:SI 1 "s_register_operand" "")
2848                   (match_operand:SI 2 "arm_rhs_operand" "")))
2849     (clobber (reg:CC CC_REGNUM))])]
2850   "TARGET_32BIT"
2851   ""
2854 (define_insn "*arm_umaxsi3"
2855   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2856         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2857                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2858    (clobber (reg:CC CC_REGNUM))]
2859   "TARGET_ARM"
2860   "@
2861    cmp\\t%1, %2\;movcc\\t%0, %2
2862    cmp\\t%1, %2\;movcs\\t%0, %1
2863    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2864   [(set_attr "conds" "clob")
2865    (set_attr "length" "8,8,12")]
2868 (define_expand "uminsi3"
2869   [(parallel [
2870     (set (match_operand:SI 0 "s_register_operand" "")
2871          (umin:SI (match_operand:SI 1 "s_register_operand" "")
2872                   (match_operand:SI 2 "arm_rhs_operand" "")))
2873     (clobber (reg:CC CC_REGNUM))])]
2874   "TARGET_32BIT"
2875   ""
2878 (define_insn "*arm_uminsi3"
2879   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2880         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2881                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2882    (clobber (reg:CC CC_REGNUM))]
2883   "TARGET_ARM"
2884   "@
2885    cmp\\t%1, %2\;movcs\\t%0, %2
2886    cmp\\t%1, %2\;movcc\\t%0, %1
2887    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2888   [(set_attr "conds" "clob")
2889    (set_attr "length" "8,8,12")]
2892 (define_insn "*store_minmaxsi"
2893   [(set (match_operand:SI 0 "memory_operand" "=m")
2894         (match_operator:SI 3 "minmax_operator"
2895          [(match_operand:SI 1 "s_register_operand" "r")
2896           (match_operand:SI 2 "s_register_operand" "r")]))
2897    (clobber (reg:CC CC_REGNUM))]
2898   "TARGET_32BIT"
2899   "*
2900   operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2901                                 operands[1], operands[2]);
2902   output_asm_insn (\"cmp\\t%1, %2\", operands);
2903   if (TARGET_THUMB2)
2904     output_asm_insn (\"ite\t%d3\", operands);
2905   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2906   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2907   return \"\";
2908   "
2909   [(set_attr "conds" "clob")
2910    (set (attr "length")
2911         (if_then_else (eq_attr "is_thumb" "yes")
2912                       (const_int 14)
2913                       (const_int 12)))
2914    (set_attr "type" "store1")]
2917 ; Reject the frame pointer in operand[1], since reloading this after
2918 ; it has been eliminated can cause carnage.
2919 (define_insn "*minmax_arithsi"
2920   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2921         (match_operator:SI 4 "shiftable_operator"
2922          [(match_operator:SI 5 "minmax_operator"
2923            [(match_operand:SI 2 "s_register_operand" "r,r")
2924             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2925           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2926    (clobber (reg:CC CC_REGNUM))]
2927   "TARGET_32BIT && !arm_eliminable_register (operands[1])"
2928   "*
2929   {
2930     enum rtx_code code = GET_CODE (operands[4]);
2931     bool need_else;
2933     if (which_alternative != 0 || operands[3] != const0_rtx
2934         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2935       need_else = true;
2936     else
2937       need_else = false;
2939     operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2940                                   operands[2], operands[3]);
2941     output_asm_insn (\"cmp\\t%2, %3\", operands);
2942     if (TARGET_THUMB2)
2943       {
2944         if (need_else)
2945           output_asm_insn (\"ite\\t%d5\", operands);
2946         else
2947           output_asm_insn (\"it\\t%d5\", operands);
2948       }
2949     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2950     if (need_else)
2951       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2952     return \"\";
2953   }"
2954   [(set_attr "conds" "clob")
2955    (set (attr "length")
2956         (if_then_else (eq_attr "is_thumb" "yes")
2957                       (const_int 14)
2958                       (const_int 12)))]
2962 ;; Shift and rotation insns
2964 (define_expand "ashldi3"
2965   [(set (match_operand:DI            0 "s_register_operand" "")
2966         (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2967                    (match_operand:SI 2 "reg_or_int_operand" "")))]
2968   "TARGET_32BIT"
2969   "
2970   if (GET_CODE (operands[2]) == CONST_INT)
2971     {
2972       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2973         {
2974           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2975           DONE;
2976         }
2977         /* Ideally we shouldn't fail here if we could know that operands[1] 
2978            ends up already living in an iwmmxt register. Otherwise it's
2979            cheaper to have the alternate code being generated than moving
2980            values to iwmmxt regs and back.  */
2981         FAIL;
2982     }
2983   else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2984     FAIL;
2985   "
2988 (define_insn "arm_ashldi3_1bit"
2989   [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
2990         (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2991                    (const_int 1)))
2992    (clobber (reg:CC CC_REGNUM))]
2993   "TARGET_32BIT"
2994   "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2995   [(set_attr "conds" "clob")
2996    (set_attr "length" "8")]
2999 (define_expand "ashlsi3"
3000   [(set (match_operand:SI            0 "s_register_operand" "")
3001         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3002                    (match_operand:SI 2 "arm_rhs_operand" "")))]
3003   "TARGET_EITHER"
3004   "
3005   if (GET_CODE (operands[2]) == CONST_INT
3006       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3007     {
3008       emit_insn (gen_movsi (operands[0], const0_rtx));
3009       DONE;
3010     }
3011   "
3014 (define_insn "*thumb1_ashlsi3"
3015   [(set (match_operand:SI            0 "register_operand" "=l,l")
3016         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
3017                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
3018   "TARGET_THUMB1"
3019   "lsl\\t%0, %1, %2"
3020   [(set_attr "length" "2")]
3023 (define_expand "ashrdi3"
3024   [(set (match_operand:DI              0 "s_register_operand" "")
3025         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3026                      (match_operand:SI 2 "reg_or_int_operand" "")))]
3027   "TARGET_32BIT"
3028   "
3029   if (GET_CODE (operands[2]) == CONST_INT)
3030     {
3031       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3032         {
3033           emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3034           DONE;
3035         }
3036         /* Ideally we shouldn't fail here if we could know that operands[1] 
3037            ends up already living in an iwmmxt register. Otherwise it's
3038            cheaper to have the alternate code being generated than moving
3039            values to iwmmxt regs and back.  */
3040         FAIL;
3041     }
3042   else if (!TARGET_REALLY_IWMMXT)
3043     FAIL;
3044   "
3047 (define_insn "arm_ashrdi3_1bit"
3048   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
3049         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
3050                      (const_int 1)))
3051    (clobber (reg:CC CC_REGNUM))]
3052   "TARGET_32BIT"
3053   "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
3054   [(set_attr "conds" "clob")
3055    (set_attr "length" "8")]
3058 (define_expand "ashrsi3"
3059   [(set (match_operand:SI              0 "s_register_operand" "")
3060         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3061                      (match_operand:SI 2 "arm_rhs_operand" "")))]
3062   "TARGET_EITHER"
3063   "
3064   if (GET_CODE (operands[2]) == CONST_INT
3065       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3066     operands[2] = GEN_INT (31);
3067   "
3070 (define_insn "*thumb1_ashrsi3"
3071   [(set (match_operand:SI              0 "register_operand" "=l,l")
3072         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3073                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
3074   "TARGET_THUMB1"
3075   "asr\\t%0, %1, %2"
3076   [(set_attr "length" "2")]
3079 (define_expand "lshrdi3"
3080   [(set (match_operand:DI              0 "s_register_operand" "")
3081         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3082                      (match_operand:SI 2 "reg_or_int_operand" "")))]
3083   "TARGET_32BIT"
3084   "
3085   if (GET_CODE (operands[2]) == CONST_INT)
3086     {
3087       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3088         {
3089           emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3090           DONE;
3091         }
3092         /* Ideally we shouldn't fail here if we could know that operands[1] 
3093            ends up already living in an iwmmxt register. Otherwise it's
3094            cheaper to have the alternate code being generated than moving
3095            values to iwmmxt regs and back.  */
3096         FAIL;
3097     }
3098   else if (!TARGET_REALLY_IWMMXT)
3099     FAIL;
3100   "
3103 (define_insn "arm_lshrdi3_1bit"
3104   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
3105         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
3106                      (const_int 1)))
3107    (clobber (reg:CC CC_REGNUM))]
3108   "TARGET_32BIT"
3109   "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
3110   [(set_attr "conds" "clob")
3111    (set_attr "length" "8")]
3114 (define_expand "lshrsi3"
3115   [(set (match_operand:SI              0 "s_register_operand" "")
3116         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3117                      (match_operand:SI 2 "arm_rhs_operand" "")))]
3118   "TARGET_EITHER"
3119   "
3120   if (GET_CODE (operands[2]) == CONST_INT
3121       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3122     {
3123       emit_insn (gen_movsi (operands[0], const0_rtx));
3124       DONE;
3125     }
3126   "
3129 (define_insn "*thumb1_lshrsi3"
3130   [(set (match_operand:SI              0 "register_operand" "=l,l")
3131         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3132                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
3133   "TARGET_THUMB1"
3134   "lsr\\t%0, %1, %2"
3135   [(set_attr "length" "2")]
3138 (define_expand "rotlsi3"
3139   [(set (match_operand:SI              0 "s_register_operand" "")
3140         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3141                      (match_operand:SI 2 "reg_or_int_operand" "")))]
3142   "TARGET_32BIT"
3143   "
3144   if (GET_CODE (operands[2]) == CONST_INT)
3145     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3146   else
3147     {
3148       rtx reg = gen_reg_rtx (SImode);
3149       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3150       operands[2] = reg;
3151     }
3152   "
3155 (define_expand "rotrsi3"
3156   [(set (match_operand:SI              0 "s_register_operand" "")
3157         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3158                      (match_operand:SI 2 "arm_rhs_operand" "")))]
3159   "TARGET_EITHER"
3160   "
3161   if (TARGET_32BIT)
3162     {
3163       if (GET_CODE (operands[2]) == CONST_INT
3164           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3165         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3166     }
3167   else /* TARGET_THUMB1 */
3168     {
3169       if (GET_CODE (operands [2]) == CONST_INT)
3170         operands [2] = force_reg (SImode, operands[2]);
3171     }
3172   "
3175 (define_insn "*thumb1_rotrsi3"
3176   [(set (match_operand:SI              0 "register_operand" "=l")
3177         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
3178                      (match_operand:SI 2 "register_operand" "l")))]
3179   "TARGET_THUMB1"
3180   "ror\\t%0, %0, %2"
3181   [(set_attr "length" "2")]
3184 (define_insn "*arm_shiftsi3"
3185   [(set (match_operand:SI   0 "s_register_operand" "=r")
3186         (match_operator:SI  3 "shift_operator"
3187          [(match_operand:SI 1 "s_register_operand"  "r")
3188           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
3189   "TARGET_32BIT"
3190   "* return arm_output_shift(operands, 0);"
3191   [(set_attr "predicable" "yes")
3192    (set_attr "shift" "1")
3193    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3194                       (const_string "alu_shift")
3195                       (const_string "alu_shift_reg")))]
3198 (define_insn "*shiftsi3_compare0"
3199   [(set (reg:CC_NOOV CC_REGNUM)
3200         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3201                           [(match_operand:SI 1 "s_register_operand" "r")
3202                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
3203                          (const_int 0)))
3204    (set (match_operand:SI 0 "s_register_operand" "=r")
3205         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
3206   "TARGET_32BIT"
3207   "* return arm_output_shift(operands, 1);"
3208   [(set_attr "conds" "set")
3209    (set_attr "shift" "1")
3210    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3211                       (const_string "alu_shift")
3212                       (const_string "alu_shift_reg")))]
3215 (define_insn "*shiftsi3_compare0_scratch"
3216   [(set (reg:CC_NOOV CC_REGNUM)
3217         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3218                           [(match_operand:SI 1 "s_register_operand" "r")
3219                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
3220                          (const_int 0)))
3221    (clobber (match_scratch:SI 0 "=r"))]
3222   "TARGET_32BIT"
3223   "* return arm_output_shift(operands, 1);"
3224   [(set_attr "conds" "set")
3225    (set_attr "shift" "1")]
3228 (define_insn "*arm_notsi_shiftsi"
3229   [(set (match_operand:SI 0 "s_register_operand" "=r")
3230         (not:SI (match_operator:SI 3 "shift_operator"
3231                  [(match_operand:SI 1 "s_register_operand" "r")
3232                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
3233   "TARGET_ARM"
3234   "mvn%?\\t%0, %1%S3"
3235   [(set_attr "predicable" "yes")
3236    (set_attr "shift" "1")
3237    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3238                       (const_string "alu_shift")
3239                       (const_string "alu_shift_reg")))]
3242 (define_insn "*arm_notsi_shiftsi_compare0"
3243   [(set (reg:CC_NOOV CC_REGNUM)
3244         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
3245                           [(match_operand:SI 1 "s_register_operand" "r")
3246                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
3247                          (const_int 0)))
3248    (set (match_operand:SI 0 "s_register_operand" "=r")
3249         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
3250   "TARGET_ARM"
3251   "mvn%.\\t%0, %1%S3"
3252   [(set_attr "conds" "set")
3253    (set_attr "shift" "1")
3254    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3255                       (const_string "alu_shift")
3256                       (const_string "alu_shift_reg")))]
3259 (define_insn "*arm_not_shiftsi_compare0_scratch"
3260   [(set (reg:CC_NOOV CC_REGNUM)
3261         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
3262                           [(match_operand:SI 1 "s_register_operand" "r")
3263                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
3264                          (const_int 0)))
3265    (clobber (match_scratch:SI 0 "=r"))]
3266   "TARGET_ARM"
3267   "mvn%.\\t%0, %1%S3"
3268   [(set_attr "conds" "set")
3269    (set_attr "shift" "1")
3270    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3271                       (const_string "alu_shift")
3272                       (const_string "alu_shift_reg")))]
3275 ;; We don't really have extzv, but defining this using shifts helps
3276 ;; to reduce register pressure later on.
3278 (define_expand "extzv"
3279   [(set (match_dup 4)
3280         (ashift:SI (match_operand:SI   1 "register_operand" "")
3281                    (match_operand:SI   2 "const_int_operand" "")))
3282    (set (match_operand:SI              0 "register_operand" "")
3283         (lshiftrt:SI (match_dup 4)
3284                      (match_operand:SI 3 "const_int_operand" "")))]
3285   "TARGET_THUMB1"
3286   "
3287   {
3288     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3289     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3290     
3291     operands[3] = GEN_INT (rshift);
3292     
3293     if (lshift == 0)
3294       {
3295         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3296         DONE;
3297       }
3298       
3299     operands[2] = GEN_INT (lshift);
3300     operands[4] = gen_reg_rtx (SImode);
3301   }"
3305 ;; Unary arithmetic insns
3307 (define_expand "negdi2"
3308  [(parallel
3309    [(set (match_operand:DI          0 "s_register_operand" "")
3310           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
3311     (clobber (reg:CC CC_REGNUM))])]
3312   "TARGET_EITHER"
3313   "
3314   if (TARGET_THUMB1)
3315     {
3316       if (GET_CODE (operands[1]) != REG)
3317         operands[1] = force_reg (SImode, operands[1]);
3318      }
3319   "
3322 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
3323 ;; The second alternative is to allow the common case of a *full* overlap.
3324 (define_insn "*arm_negdi2"
3325   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
3326         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
3327    (clobber (reg:CC CC_REGNUM))]
3328   "TARGET_ARM"
3329   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
3330   [(set_attr "conds" "clob")
3331    (set_attr "length" "8")]
3334 (define_insn "*thumb1_negdi2"
3335   [(set (match_operand:DI         0 "register_operand" "=&l")
3336         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
3337    (clobber (reg:CC CC_REGNUM))]
3338   "TARGET_THUMB1"
3339   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
3340   [(set_attr "length" "6")]
3343 (define_expand "negsi2"
3344   [(set (match_operand:SI         0 "s_register_operand" "")
3345         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
3346   "TARGET_EITHER"
3347   ""
3350 (define_insn "*arm_negsi2"
3351   [(set (match_operand:SI         0 "s_register_operand" "=r")
3352         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
3353   "TARGET_32BIT"
3354   "rsb%?\\t%0, %1, #0"
3355   [(set_attr "predicable" "yes")]
3358 (define_insn "*thumb1_negsi2"
3359   [(set (match_operand:SI         0 "register_operand" "=l")
3360         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
3361   "TARGET_THUMB1"
3362   "neg\\t%0, %1"
3363   [(set_attr "length" "2")]
3366 (define_expand "negsf2"
3367   [(set (match_operand:SF         0 "s_register_operand" "")
3368         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
3369   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3370   ""
3373 (define_expand "negdf2"
3374   [(set (match_operand:DF         0 "s_register_operand" "")
3375         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
3376   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3377   "")
3379 ;; abssi2 doesn't really clobber the condition codes if a different register
3380 ;; is being set.  To keep things simple, assume during rtl manipulations that
3381 ;; it does, but tell the final scan operator the truth.  Similarly for
3382 ;; (neg (abs...))
3384 (define_expand "abssi2"
3385   [(parallel
3386     [(set (match_operand:SI         0 "s_register_operand" "")
3387           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3388      (clobber (match_dup 2))])]
3389   "TARGET_EITHER"
3390   "
3391   if (TARGET_THUMB1)
3392     operands[2] = gen_rtx_SCRATCH (SImode);
3393   else
3394     operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
3397 (define_insn "*arm_abssi2"
3398   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3399         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3400    (clobber (reg:CC CC_REGNUM))]
3401   "TARGET_ARM"
3402   "@
3403    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3404    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3405   [(set_attr "conds" "clob,*")
3406    (set_attr "shift" "1")
3407    ;; predicable can't be set based on the variant, so left as no
3408    (set_attr "length" "8")]
3411 (define_insn_and_split "*thumb1_abssi2"
3412   [(set (match_operand:SI 0 "s_register_operand" "=l")
3413         (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
3414    (clobber (match_scratch:SI 2 "=&l"))]
3415   "TARGET_THUMB1"
3416   "#"
3417   "TARGET_THUMB1 && reload_completed"
3418   [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3419    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
3420    (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3421   ""
3422   [(set_attr "length" "6")]
3425 (define_insn "*arm_neg_abssi2"
3426   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3427         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3428    (clobber (reg:CC CC_REGNUM))]
3429   "TARGET_ARM"
3430   "@
3431    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3432    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3433   [(set_attr "conds" "clob,*")
3434    (set_attr "shift" "1")
3435    ;; predicable can't be set based on the variant, so left as no
3436    (set_attr "length" "8")]
3439 (define_insn_and_split "*thumb1_neg_abssi2"
3440   [(set (match_operand:SI 0 "s_register_operand" "=l")
3441         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
3442    (clobber (match_scratch:SI 2 "=&l"))]
3443   "TARGET_THUMB1"
3444   "#"
3445   "TARGET_THUMB1 && reload_completed"
3446   [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3447    (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
3448    (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3449   ""
3450   [(set_attr "length" "6")]
3453 (define_expand "abssf2"
3454   [(set (match_operand:SF         0 "s_register_operand" "")
3455         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3456   "TARGET_32BIT && TARGET_HARD_FLOAT"
3457   "")
3459 (define_expand "absdf2"
3460   [(set (match_operand:DF         0 "s_register_operand" "")
3461         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3462   "TARGET_32BIT && TARGET_HARD_FLOAT"
3463   "")
3465 (define_expand "sqrtsf2"
3466   [(set (match_operand:SF 0 "s_register_operand" "")
3467         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3468   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3469   "")
3471 (define_expand "sqrtdf2"
3472   [(set (match_operand:DF 0 "s_register_operand" "")
3473         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3474   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3475   "")
3477 (define_insn_and_split "one_cmpldi2"
3478   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3479         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3480   "TARGET_32BIT"
3481   "#"
3482   "TARGET_32BIT && reload_completed"
3483   [(set (match_dup 0) (not:SI (match_dup 1)))
3484    (set (match_dup 2) (not:SI (match_dup 3)))]
3485   "
3486   {
3487     operands[2] = gen_highpart (SImode, operands[0]);
3488     operands[0] = gen_lowpart (SImode, operands[0]);
3489     operands[3] = gen_highpart (SImode, operands[1]);
3490     operands[1] = gen_lowpart (SImode, operands[1]);
3491   }"
3492   [(set_attr "length" "8")
3493    (set_attr "predicable" "yes")]
3496 (define_expand "one_cmplsi2"
3497   [(set (match_operand:SI         0 "s_register_operand" "")
3498         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3499   "TARGET_EITHER"
3500   ""
3503 (define_insn "*arm_one_cmplsi2"
3504   [(set (match_operand:SI         0 "s_register_operand" "=r")
3505         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3506   "TARGET_32BIT"
3507   "mvn%?\\t%0, %1"
3508   [(set_attr "predicable" "yes")]
3511 (define_insn "*thumb1_one_cmplsi2"
3512   [(set (match_operand:SI         0 "register_operand" "=l")
3513         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3514   "TARGET_THUMB1"
3515   "mvn\\t%0, %1"
3516   [(set_attr "length" "2")]
3519 (define_insn "*notsi_compare0"
3520   [(set (reg:CC_NOOV CC_REGNUM)
3521         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3522                          (const_int 0)))
3523    (set (match_operand:SI 0 "s_register_operand" "=r")
3524         (not:SI (match_dup 1)))]
3525   "TARGET_32BIT"
3526   "mvn%.\\t%0, %1"
3527   [(set_attr "conds" "set")]
3530 (define_insn "*notsi_compare0_scratch"
3531   [(set (reg:CC_NOOV CC_REGNUM)
3532         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3533                          (const_int 0)))
3534    (clobber (match_scratch:SI 0 "=r"))]
3535   "TARGET_32BIT"
3536   "mvn%.\\t%0, %1"
3537   [(set_attr "conds" "set")]
3540 ;; Fixed <--> Floating conversion insns
3542 (define_expand "floatsisf2"
3543   [(set (match_operand:SF           0 "s_register_operand" "")
3544         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3545   "TARGET_32BIT && TARGET_HARD_FLOAT"
3546   "
3547   if (TARGET_MAVERICK)
3548     {
3549       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3550       DONE;
3551     }
3554 (define_expand "floatsidf2"
3555   [(set (match_operand:DF           0 "s_register_operand" "")
3556         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3557   "TARGET_32BIT && TARGET_HARD_FLOAT"
3558   "
3559   if (TARGET_MAVERICK)
3560     {
3561       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3562       DONE;
3563     }
3566 (define_expand "fix_truncsfsi2"
3567   [(set (match_operand:SI         0 "s_register_operand" "")
3568         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3569   "TARGET_32BIT && TARGET_HARD_FLOAT"
3570   "
3571   if (TARGET_MAVERICK)
3572     {
3573       if (!cirrus_fp_register (operands[0], SImode))
3574         operands[0] = force_reg (SImode, operands[0]);
3575       if (!cirrus_fp_register (operands[1], SFmode))
3576         operands[1] = force_reg (SFmode, operands[0]);
3577       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3578       DONE;
3579     }
3582 (define_expand "fix_truncdfsi2"
3583   [(set (match_operand:SI         0 "s_register_operand" "")
3584         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3585   "TARGET_32BIT && TARGET_HARD_FLOAT"
3586   "
3587   if (TARGET_MAVERICK)
3588     {
3589       if (!cirrus_fp_register (operands[1], DFmode))
3590         operands[1] = force_reg (DFmode, operands[0]);
3591       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3592       DONE;
3593     }
3596 ;; Truncation insns
3598 (define_expand "truncdfsf2"
3599   [(set (match_operand:SF  0 "s_register_operand" "")
3600         (float_truncate:SF
3601          (match_operand:DF 1 "s_register_operand" "")))]
3602   "TARGET_32BIT && TARGET_HARD_FLOAT"
3603   ""
3606 ;; Zero and sign extension instructions.
3608 (define_expand "zero_extendsidi2"
3609   [(set (match_operand:DI 0 "s_register_operand" "")
3610         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
3611   "TARGET_32BIT"
3612   ""
3615 (define_insn "*arm_zero_extendsidi2"
3616   [(set (match_operand:DI 0 "s_register_operand" "=r")
3617         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3618   "TARGET_ARM"
3619   "*
3620     if (REGNO (operands[1])
3621         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3622       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3623     return \"mov%?\\t%R0, #0\";
3624   "
3625   [(set_attr "length" "8")
3626    (set_attr "predicable" "yes")]
3629 (define_expand "zero_extendqidi2"
3630   [(set (match_operand:DI                 0 "s_register_operand"  "")
3631         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))]
3632   "TARGET_32BIT"
3633   ""
3636 (define_insn "*arm_zero_extendqidi2"
3637   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3638         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3639   "TARGET_ARM"
3640   "@
3641    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3642    ldr%(b%)\\t%Q0, %1\;mov%?\\t%R0, #0"
3643   [(set_attr "length" "8")
3644    (set_attr "predicable" "yes")
3645    (set_attr "type" "*,load_byte")
3646    (set_attr "pool_range" "*,4092")
3647    (set_attr "neg_pool_range" "*,4084")]
3650 (define_expand "extendsidi2"
3651   [(set (match_operand:DI 0 "s_register_operand" "")
3652         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
3653   "TARGET_32BIT"
3654   ""
3657 (define_insn "*arm_extendsidi2"
3658   [(set (match_operand:DI 0 "s_register_operand" "=r")
3659         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3660   "TARGET_ARM"
3661   "*
3662     if (REGNO (operands[1])
3663         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3664       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3665     return \"mov%?\\t%R0, %Q0, asr #31\";
3666   "
3667   [(set_attr "length" "8")
3668    (set_attr "shift" "1")
3669    (set_attr "predicable" "yes")]
3672 (define_expand "zero_extendhisi2"
3673   [(set (match_dup 2)
3674         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3675                    (const_int 16)))
3676    (set (match_operand:SI 0 "s_register_operand" "")
3677         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3678   "TARGET_EITHER"
3679   "
3680   {
3681     if ((TARGET_THUMB1 || arm_arch4) && GET_CODE (operands[1]) == MEM)
3682       {
3683         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3684                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3685         DONE;
3686       }
3688     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3689       {
3690         emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3691         DONE;
3692       }
3694     if (!s_register_operand (operands[1], HImode))
3695       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3697     if (arm_arch6)
3698       {
3699         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3700                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3701         DONE;
3702       }
3704     operands[1] = gen_lowpart (SImode, operands[1]);
3705     operands[2] = gen_reg_rtx (SImode);
3706   }"
3709 (define_insn "*thumb1_zero_extendhisi2"
3710   [(set (match_operand:SI 0 "register_operand" "=l")
3711         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3712   "TARGET_THUMB1 && !arm_arch6"
3713   "*
3714   rtx mem = XEXP (operands[1], 0);
3716   if (GET_CODE (mem) == CONST)
3717     mem = XEXP (mem, 0);
3718     
3719   if (GET_CODE (mem) == LABEL_REF)
3720     return \"ldr\\t%0, %1\";
3721     
3722   if (GET_CODE (mem) == PLUS)
3723     {
3724       rtx a = XEXP (mem, 0);
3725       rtx b = XEXP (mem, 1);
3727       /* This can happen due to bugs in reload.  */
3728       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3729         {
3730           rtx ops[2];
3731           ops[0] = operands[0];
3732           ops[1] = a;
3733       
3734           output_asm_insn (\"mov        %0, %1\", ops);
3736           XEXP (mem, 0) = operands[0];
3737        }
3739       else if (   GET_CODE (a) == LABEL_REF
3740                && GET_CODE (b) == CONST_INT)
3741         return \"ldr\\t%0, %1\";
3742     }
3743     
3744   return \"ldrh\\t%0, %1\";
3745   "
3746   [(set_attr "length" "4")
3747    (set_attr "type" "load_byte")
3748    (set_attr "pool_range" "60")]
3751 (define_insn "*thumb1_zero_extendhisi2_v6"
3752   [(set (match_operand:SI 0 "register_operand" "=l,l")
3753         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3754   "TARGET_THUMB1 && arm_arch6"
3755   "*
3756   rtx mem;
3758   if (which_alternative == 0)
3759     return \"uxth\\t%0, %1\";
3761   mem = XEXP (operands[1], 0);
3763   if (GET_CODE (mem) == CONST)
3764     mem = XEXP (mem, 0);
3765     
3766   if (GET_CODE (mem) == LABEL_REF)
3767     return \"ldr\\t%0, %1\";
3768     
3769   if (GET_CODE (mem) == PLUS)
3770     {
3771       rtx a = XEXP (mem, 0);
3772       rtx b = XEXP (mem, 1);
3774       /* This can happen due to bugs in reload.  */
3775       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3776         {
3777           rtx ops[2];
3778           ops[0] = operands[0];
3779           ops[1] = a;
3780       
3781           output_asm_insn (\"mov        %0, %1\", ops);
3783           XEXP (mem, 0) = operands[0];
3784        }
3786       else if (   GET_CODE (a) == LABEL_REF
3787                && GET_CODE (b) == CONST_INT)
3788         return \"ldr\\t%0, %1\";
3789     }
3790     
3791   return \"ldrh\\t%0, %1\";
3792   "
3793   [(set_attr "length" "2,4")
3794    (set_attr "type" "alu_shift,load_byte")
3795    (set_attr "pool_range" "*,60")]
3798 (define_insn "*arm_zero_extendhisi2"
3799   [(set (match_operand:SI 0 "s_register_operand" "=r")
3800         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3801   "TARGET_ARM && arm_arch4 && !arm_arch6"
3802   "ldr%(h%)\\t%0, %1"
3803   [(set_attr "type" "load_byte")
3804    (set_attr "predicable" "yes")
3805    (set_attr "pool_range" "256")
3806    (set_attr "neg_pool_range" "244")]
3809 (define_insn "*arm_zero_extendhisi2_v6"
3810   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3811         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3812   "TARGET_ARM && arm_arch6"
3813   "@
3814    uxth%?\\t%0, %1
3815    ldr%(h%)\\t%0, %1"
3816   [(set_attr "type" "alu_shift,load_byte")
3817    (set_attr "predicable" "yes")
3818    (set_attr "pool_range" "*,256")
3819    (set_attr "neg_pool_range" "*,244")]
3822 (define_insn "*arm_zero_extendhisi2addsi"
3823   [(set (match_operand:SI 0 "s_register_operand" "=r")
3824         (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3825                  (match_operand:SI 2 "s_register_operand" "r")))]
3826   "TARGET_INT_SIMD"
3827   "uxtah%?\\t%0, %2, %1"
3828   [(set_attr "type" "alu_shift")
3829    (set_attr "predicable" "yes")]
3832 (define_expand "zero_extendqisi2"
3833   [(set (match_operand:SI 0 "s_register_operand" "")
3834         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3835   "TARGET_EITHER"
3836   "
3837   if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3838     {
3839       if (TARGET_ARM)
3840         {
3841           emit_insn (gen_andsi3 (operands[0],
3842                                  gen_lowpart (SImode, operands[1]),
3843                                  GEN_INT (255)));
3844         }
3845       else /* TARGET_THUMB */
3846         {
3847           rtx temp = gen_reg_rtx (SImode);
3848           rtx ops[3];
3849           
3850           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3851           operands[1] = gen_lowpart (SImode, operands[1]);
3853           ops[0] = temp;
3854           ops[1] = operands[1];
3855           ops[2] = GEN_INT (24);
3857           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3858                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3859           
3860           ops[0] = operands[0];
3861           ops[1] = temp;
3862           ops[2] = GEN_INT (24);
3864           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3865                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3866         }
3867       DONE;
3868     }
3869   "
3872 (define_insn "*thumb1_zero_extendqisi2"
3873   [(set (match_operand:SI 0 "register_operand" "=l")
3874         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3875   "TARGET_THUMB1 && !arm_arch6"
3876   "ldrb\\t%0, %1"
3877   [(set_attr "length" "2")
3878    (set_attr "type" "load_byte")
3879    (set_attr "pool_range" "32")]
3882 (define_insn "*thumb1_zero_extendqisi2_v6"
3883   [(set (match_operand:SI 0 "register_operand" "=l,l")
3884         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3885   "TARGET_THUMB1 && arm_arch6"
3886   "@
3887    uxtb\\t%0, %1
3888    ldrb\\t%0, %1"
3889   [(set_attr "length" "2,2")
3890    (set_attr "type" "alu_shift,load_byte")
3891    (set_attr "pool_range" "*,32")]
3894 (define_insn "*arm_zero_extendqisi2"
3895   [(set (match_operand:SI 0 "s_register_operand" "=r")
3896         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3897   "TARGET_ARM && !arm_arch6"
3898   "ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
3899   [(set_attr "type" "load_byte")
3900    (set_attr "predicable" "yes")
3901    (set_attr "pool_range" "4096")
3902    (set_attr "neg_pool_range" "4084")]
3905 (define_insn "*arm_zero_extendqisi2_v6"
3906   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3907         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3908   "TARGET_ARM && arm_arch6"
3909   "@
3910    uxtb%(%)\\t%0, %1
3911    ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
3912   [(set_attr "type" "alu_shift,load_byte")
3913    (set_attr "predicable" "yes")
3914    (set_attr "pool_range" "*,4096")
3915    (set_attr "neg_pool_range" "*,4084")]
3918 (define_insn "*arm_zero_extendqisi2addsi"
3919   [(set (match_operand:SI 0 "s_register_operand" "=r")
3920         (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3921                  (match_operand:SI 2 "s_register_operand" "r")))]
3922   "TARGET_INT_SIMD"
3923   "uxtab%?\\t%0, %2, %1"
3924   [(set_attr "predicable" "yes")
3925    (set_attr "insn" "xtab")
3926    (set_attr "type" "alu_shift")]
3929 (define_split
3930   [(set (match_operand:SI 0 "s_register_operand" "")
3931         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3932    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3933   "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3934   [(set (match_dup 2) (match_dup 1))
3935    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3936   ""
3939 (define_split
3940   [(set (match_operand:SI 0 "s_register_operand" "")
3941         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
3942    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3943   "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
3944   [(set (match_dup 2) (match_dup 1))
3945    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3946   ""
3949 (define_insn "*compareqi_eq0"
3950   [(set (reg:CC_Z CC_REGNUM)
3951         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3952                          (const_int 0)))]
3953   "TARGET_32BIT"
3954   "tst\\t%0, #255"
3955   [(set_attr "conds" "set")]
3958 (define_expand "extendhisi2"
3959   [(set (match_dup 2)
3960         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3961                    (const_int 16)))
3962    (set (match_operand:SI 0 "s_register_operand" "")
3963         (ashiftrt:SI (match_dup 2)
3964                      (const_int 16)))]
3965   "TARGET_EITHER"
3966   "
3967   {
3968     if (GET_CODE (operands[1]) == MEM)
3969       {
3970         if (TARGET_THUMB1)
3971           {
3972             emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
3973             DONE;
3974           }
3975         else if (arm_arch4)
3976           {
3977             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3978                        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3979             DONE;
3980           }
3981       }
3983     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3984       {
3985         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3986         DONE;
3987       }
3989     if (!s_register_operand (operands[1], HImode))
3990       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3992     if (arm_arch6)
3993       {
3994         if (TARGET_THUMB1)
3995           emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
3996         else
3997           emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3998                      gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4000         DONE;
4001       }
4003     operands[1] = gen_lowpart (SImode, operands[1]);
4004     operands[2] = gen_reg_rtx (SImode);
4005   }"
4008 (define_insn "thumb1_extendhisi2"
4009   [(set (match_operand:SI 0 "register_operand" "=l")
4010         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
4011    (clobber (match_scratch:SI 2 "=&l"))]
4012   "TARGET_THUMB1 && !arm_arch6"
4013   "*
4014   {
4015     rtx ops[4];
4016     rtx mem = XEXP (operands[1], 0);
4018     /* This code used to try to use 'V', and fix the address only if it was
4019        offsettable, but this fails for e.g. REG+48 because 48 is outside the
4020        range of QImode offsets, and offsettable_address_p does a QImode
4021        address check.  */
4022        
4023     if (GET_CODE (mem) == CONST)
4024       mem = XEXP (mem, 0);
4025     
4026     if (GET_CODE (mem) == LABEL_REF)
4027       return \"ldr\\t%0, %1\";
4028     
4029     if (GET_CODE (mem) == PLUS)
4030       {
4031         rtx a = XEXP (mem, 0);
4032         rtx b = XEXP (mem, 1);
4034         if (GET_CODE (a) == LABEL_REF
4035             && GET_CODE (b) == CONST_INT)
4036           return \"ldr\\t%0, %1\";
4038         if (GET_CODE (b) == REG)
4039           return \"ldrsh\\t%0, %1\";
4040           
4041         ops[1] = a;
4042         ops[2] = b;
4043       }
4044     else
4045       {
4046         ops[1] = mem;
4047         ops[2] = const0_rtx;
4048       }
4050     gcc_assert (GET_CODE (ops[1]) == REG);
4052     ops[0] = operands[0];
4053     ops[3] = operands[2];
4054     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4055     return \"\";
4056   }"
4057   [(set_attr "length" "4")
4058    (set_attr "type" "load_byte")
4059    (set_attr "pool_range" "1020")]
4062 ;; We used to have an early-clobber on the scratch register here.
4063 ;; However, there's a bug somewhere in reload which means that this
4064 ;; can be partially ignored during spill allocation if the memory
4065 ;; address also needs reloading; this causes us to die later on when
4066 ;; we try to verify the operands.  Fortunately, we don't really need
4067 ;; the early-clobber: we can always use operand 0 if operand 2
4068 ;; overlaps the address.
4069 (define_insn "*thumb1_extendhisi2_insn_v6"
4070   [(set (match_operand:SI 0 "register_operand" "=l,l")
4071         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
4072    (clobber (match_scratch:SI 2 "=X,l"))]
4073   "TARGET_THUMB1 && arm_arch6"
4074   "*
4075   {
4076     rtx ops[4];
4077     rtx mem;
4079     if (which_alternative == 0)
4080       return \"sxth\\t%0, %1\";
4082     mem = XEXP (operands[1], 0);
4084     /* This code used to try to use 'V', and fix the address only if it was
4085        offsettable, but this fails for e.g. REG+48 because 48 is outside the
4086        range of QImode offsets, and offsettable_address_p does a QImode
4087        address check.  */
4088        
4089     if (GET_CODE (mem) == CONST)
4090       mem = XEXP (mem, 0);
4091     
4092     if (GET_CODE (mem) == LABEL_REF)
4093       return \"ldr\\t%0, %1\";
4094     
4095     if (GET_CODE (mem) == PLUS)
4096       {
4097         rtx a = XEXP (mem, 0);
4098         rtx b = XEXP (mem, 1);
4100         if (GET_CODE (a) == LABEL_REF
4101             && GET_CODE (b) == CONST_INT)
4102           return \"ldr\\t%0, %1\";
4104         if (GET_CODE (b) == REG)
4105           return \"ldrsh\\t%0, %1\";
4106           
4107         ops[1] = a;
4108         ops[2] = b;
4109       }
4110     else
4111       {
4112         ops[1] = mem;
4113         ops[2] = const0_rtx;
4114       }
4115       
4116     gcc_assert (GET_CODE (ops[1]) == REG);
4118     ops[0] = operands[0];
4119     if (reg_mentioned_p (operands[2], ops[1]))
4120       ops[3] = ops[0];
4121     else
4122       ops[3] = operands[2];
4123     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4124     return \"\";
4125   }"
4126   [(set_attr "length" "2,4")
4127    (set_attr "type" "alu_shift,load_byte")
4128    (set_attr "pool_range" "*,1020")]
4131 ;; This pattern will only be used when ldsh is not available
4132 (define_expand "extendhisi2_mem"
4133   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4134    (set (match_dup 3)
4135         (zero_extend:SI (match_dup 7)))
4136    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4137    (set (match_operand:SI 0 "" "")
4138         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
4139   "TARGET_ARM"
4140   "
4141   {
4142     rtx mem1, mem2;
4143     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4145     mem1 = change_address (operands[1], QImode, addr);
4146     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
4147     operands[0] = gen_lowpart (SImode, operands[0]);
4148     operands[1] = mem1;
4149     operands[2] = gen_reg_rtx (SImode);
4150     operands[3] = gen_reg_rtx (SImode);
4151     operands[6] = gen_reg_rtx (SImode);
4152     operands[7] = mem2;
4154     if (BYTES_BIG_ENDIAN)
4155       {
4156         operands[4] = operands[2];
4157         operands[5] = operands[3];
4158       }
4159     else
4160       {
4161         operands[4] = operands[3];
4162         operands[5] = operands[2];
4163       }
4164   }"
4167 (define_insn "*arm_extendhisi2"
4168   [(set (match_operand:SI 0 "s_register_operand" "=r")
4169         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
4170   "TARGET_ARM && arm_arch4 && !arm_arch6"
4171   "ldr%(sh%)\\t%0, %1"
4172   [(set_attr "type" "load_byte")
4173    (set_attr "predicable" "yes")
4174    (set_attr "pool_range" "256")
4175    (set_attr "neg_pool_range" "244")]
4178 ;; ??? Check Thumb-2 pool range
4179 (define_insn "*arm_extendhisi2_v6"
4180   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4181         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4182   "TARGET_32BIT && arm_arch6"
4183   "@
4184    sxth%?\\t%0, %1
4185    ldr%(sh%)\\t%0, %1"
4186   [(set_attr "type" "alu_shift,load_byte")
4187    (set_attr "predicable" "yes")
4188    (set_attr "pool_range" "*,256")
4189    (set_attr "neg_pool_range" "*,244")]
4192 (define_insn "*arm_extendhisi2addsi"
4193   [(set (match_operand:SI 0 "s_register_operand" "=r")
4194         (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4195                  (match_operand:SI 2 "s_register_operand" "r")))]
4196   "TARGET_INT_SIMD"
4197   "sxtah%?\\t%0, %2, %1"
4200 (define_expand "extendqihi2"
4201   [(set (match_dup 2)
4202         (ashift:SI (match_operand:QI 1 "general_operand" "")
4203                    (const_int 24)))
4204    (set (match_operand:HI 0 "s_register_operand" "")
4205         (ashiftrt:SI (match_dup 2)
4206                      (const_int 24)))]
4207   "TARGET_ARM"
4208   "
4209   {
4210     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
4211       {
4212         emit_insn (gen_rtx_SET (VOIDmode,
4213                                 operands[0],
4214                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
4215         DONE;
4216       }
4217     if (!s_register_operand (operands[1], QImode))
4218       operands[1] = copy_to_mode_reg (QImode, operands[1]);
4219     operands[0] = gen_lowpart (SImode, operands[0]);
4220     operands[1] = gen_lowpart (SImode, operands[1]);
4221     operands[2] = gen_reg_rtx (SImode);
4222   }"
4225 (define_insn "*arm_extendqihi_insn"
4226   [(set (match_operand:HI 0 "s_register_operand" "=r")
4227         (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
4228   "TARGET_ARM && arm_arch4"
4229   "ldr%(sb%)\\t%0, %1"
4230   [(set_attr "type" "load_byte")
4231    (set_attr "predicable" "yes")
4232    (set_attr "pool_range" "256")
4233    (set_attr "neg_pool_range" "244")]
4236 (define_expand "extendqisi2"
4237   [(set (match_dup 2)
4238         (ashift:SI (match_operand:QI 1 "general_operand" "")
4239                    (const_int 24)))
4240    (set (match_operand:SI 0 "s_register_operand" "")
4241         (ashiftrt:SI (match_dup 2)
4242                      (const_int 24)))]
4243   "TARGET_EITHER"
4244   "
4245   {
4246     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
4247       {
4248         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4249                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4250         DONE;
4251       }
4253     if (!s_register_operand (operands[1], QImode))
4254       operands[1] = copy_to_mode_reg (QImode, operands[1]);
4256     if (arm_arch6)
4257       {
4258         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4259                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4260         DONE;
4261       }
4263     operands[1] = gen_lowpart (SImode, operands[1]);
4264     operands[2] = gen_reg_rtx (SImode);
4265   }"
4268 (define_insn "*arm_extendqisi"
4269   [(set (match_operand:SI 0 "s_register_operand" "=r")
4270         (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
4271   "TARGET_ARM && arm_arch4 && !arm_arch6"
4272   "ldr%(sb%)\\t%0, %1"
4273   [(set_attr "type" "load_byte")
4274    (set_attr "predicable" "yes")
4275    (set_attr "pool_range" "256")
4276    (set_attr "neg_pool_range" "244")]
4279 (define_insn "*arm_extendqisi_v6"
4280   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4281         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
4282   "TARGET_ARM && arm_arch6"
4283   "@
4284    sxtb%?\\t%0, %1
4285    ldr%(sb%)\\t%0, %1"
4286   [(set_attr "type" "alu_shift,load_byte")
4287    (set_attr "predicable" "yes")
4288    (set_attr "pool_range" "*,256")
4289    (set_attr "neg_pool_range" "*,244")]
4292 (define_insn "*arm_extendqisi2addsi"
4293   [(set (match_operand:SI 0 "s_register_operand" "=r")
4294         (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4295                  (match_operand:SI 2 "s_register_operand" "r")))]
4296   "TARGET_INT_SIMD"
4297   "sxtab%?\\t%0, %2, %1"
4298   [(set_attr "type" "alu_shift")
4299    (set_attr "insn" "xtab")
4300    (set_attr "predicable" "yes")]
4303 (define_insn "*thumb1_extendqisi2"
4304   [(set (match_operand:SI 0 "register_operand" "=l,l")
4305         (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
4306   "TARGET_THUMB1 && !arm_arch6"
4307   "*
4308   {
4309     rtx ops[3];
4310     rtx mem = XEXP (operands[1], 0);
4311     
4312     if (GET_CODE (mem) == CONST)
4313       mem = XEXP (mem, 0);
4314     
4315     if (GET_CODE (mem) == LABEL_REF)
4316       return \"ldr\\t%0, %1\";
4318     if (GET_CODE (mem) == PLUS
4319         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4320       return \"ldr\\t%0, %1\";
4321       
4322     if (which_alternative == 0)
4323       return \"ldrsb\\t%0, %1\";
4324       
4325     ops[0] = operands[0];
4326     
4327     if (GET_CODE (mem) == PLUS)
4328       {
4329         rtx a = XEXP (mem, 0);
4330         rtx b = XEXP (mem, 1);
4331         
4332         ops[1] = a;
4333         ops[2] = b;
4335         if (GET_CODE (a) == REG)
4336           {
4337             if (GET_CODE (b) == REG)
4338               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4339             else if (REGNO (a) == REGNO (ops[0]))
4340               {
4341                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4342                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4343                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4344               }
4345             else
4346               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4347           }
4348         else
4349           {
4350             gcc_assert (GET_CODE (b) == REG);
4351             if (REGNO (b) == REGNO (ops[0]))
4352               {
4353                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4354                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4355                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4356               }
4357             else
4358               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4359           }
4360       }
4361     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4362       {
4363         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4364         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4365         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4366       }
4367     else
4368       {
4369         ops[1] = mem;
4370         ops[2] = const0_rtx;
4371         
4372         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4373       }
4374     return \"\";
4375   }"
4376   [(set_attr "length" "2,6")
4377    (set_attr "type" "load_byte,load_byte")
4378    (set_attr "pool_range" "32,32")]
4381 (define_insn "*thumb1_extendqisi2_v6"
4382   [(set (match_operand:SI 0 "register_operand" "=l,l,l")
4383         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
4384   "TARGET_THUMB1 && arm_arch6"
4385   "*
4386   {
4387     rtx ops[3];
4388     rtx mem;
4390     if (which_alternative == 0)
4391       return \"sxtb\\t%0, %1\";
4393     mem = XEXP (operands[1], 0);
4394     
4395     if (GET_CODE (mem) == CONST)
4396       mem = XEXP (mem, 0);
4397     
4398     if (GET_CODE (mem) == LABEL_REF)
4399       return \"ldr\\t%0, %1\";
4401     if (GET_CODE (mem) == PLUS
4402         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4403       return \"ldr\\t%0, %1\";
4404       
4405     if (which_alternative == 0)
4406       return \"ldrsb\\t%0, %1\";
4407       
4408     ops[0] = operands[0];
4409     
4410     if (GET_CODE (mem) == PLUS)
4411       {
4412         rtx a = XEXP (mem, 0);
4413         rtx b = XEXP (mem, 1);
4414         
4415         ops[1] = a;
4416         ops[2] = b;
4418         if (GET_CODE (a) == REG)
4419           {
4420             if (GET_CODE (b) == REG)
4421               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4422             else if (REGNO (a) == REGNO (ops[0]))
4423               {
4424                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4425                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4426               }
4427             else
4428               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4429           }
4430         else
4431           {
4432             gcc_assert (GET_CODE (b) == REG);
4433             if (REGNO (b) == REGNO (ops[0]))
4434               {
4435                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4436                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4437               }
4438             else
4439               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4440           }
4441       }
4442     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4443       {
4444         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4445         output_asm_insn (\"sxtb\\t%0, %0\", ops);
4446       }
4447     else
4448       {
4449         ops[1] = mem;
4450         ops[2] = const0_rtx;
4451         
4452         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4453       }
4454     return \"\";
4455   }"
4456   [(set_attr "length" "2,2,4")
4457    (set_attr "type" "alu_shift,load_byte,load_byte")
4458    (set_attr "pool_range" "*,32,32")]
4461 (define_expand "extendsfdf2"
4462   [(set (match_operand:DF                  0 "s_register_operand" "")
4463         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
4464   "TARGET_32BIT && TARGET_HARD_FLOAT"
4465   ""
4468 ;; Move insns (including loads and stores)
4470 ;; XXX Just some ideas about movti.
4471 ;; I don't think these are a good idea on the arm, there just aren't enough
4472 ;; registers
4473 ;;(define_expand "loadti"
4474 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
4475 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
4476 ;;  "" "")
4478 ;;(define_expand "storeti"
4479 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4480 ;;      (match_operand:TI 1 "s_register_operand" ""))]
4481 ;;  "" "")
4483 ;;(define_expand "movti"
4484 ;;  [(set (match_operand:TI 0 "general_operand" "")
4485 ;;      (match_operand:TI 1 "general_operand" ""))]
4486 ;;  ""
4487 ;;  "
4489 ;;  rtx insn;
4491 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4492 ;;    operands[1] = copy_to_reg (operands[1]);
4493 ;;  if (GET_CODE (operands[0]) == MEM)
4494 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4495 ;;  else if (GET_CODE (operands[1]) == MEM)
4496 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4497 ;;  else
4498 ;;    FAIL;
4500 ;;  emit_insn (insn);
4501 ;;  DONE;
4502 ;;}")
4504 ;; Recognize garbage generated above.
4506 ;;(define_insn ""
4507 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4508 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4509 ;;  ""
4510 ;;  "*
4511 ;;  {
4512 ;;    register mem = (which_alternative < 3);
4513 ;;    register const char *template;
4515 ;;    operands[mem] = XEXP (operands[mem], 0);
4516 ;;    switch (which_alternative)
4517 ;;      {
4518 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4519 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
4520 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
4521 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
4522 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
4523 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
4524 ;;      }
4525 ;;    output_asm_insn (template, operands);
4526 ;;    return \"\";
4527 ;;  }")
4529 (define_expand "movdi"
4530   [(set (match_operand:DI 0 "general_operand" "")
4531         (match_operand:DI 1 "general_operand" ""))]
4532   "TARGET_EITHER"
4533   "
4534   if (can_create_pseudo_p ())
4535     {
4536       if (GET_CODE (operands[0]) != REG)
4537         operands[1] = force_reg (DImode, operands[1]);
4538     }
4539   "
4542 (define_insn "*arm_movdi"
4543   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4544         (match_operand:DI 1 "di_operand"              "rDa,Db,Dc,mi,r"))]
4545   "TARGET_ARM
4546    && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4547    && !TARGET_IWMMXT
4548    && (   register_operand (operands[0], DImode)
4549        || register_operand (operands[1], DImode))"
4550   "*
4551   switch (which_alternative)
4552     {
4553     case 0:
4554     case 1:
4555     case 2:
4556       return \"#\";
4557     default:
4558       return output_move_double (operands);
4559     }
4560   "
4561   [(set_attr "length" "8,12,16,8,8")
4562    (set_attr "type" "*,*,*,load2,store2")
4563    (set_attr "pool_range" "*,*,*,1020,*")
4564    (set_attr "neg_pool_range" "*,*,*,1008,*")]
4567 (define_split
4568   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4569         (match_operand:ANY64 1 "const_double_operand" ""))]
4570   "TARGET_32BIT
4571    && reload_completed
4572    && (arm_const_double_inline_cost (operands[1])
4573        <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4574   [(const_int 0)]
4575   "
4576   arm_split_constant (SET, SImode, curr_insn,
4577                       INTVAL (gen_lowpart (SImode, operands[1])),
4578                       gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4579   arm_split_constant (SET, SImode, curr_insn,
4580                       INTVAL (gen_highpart_mode (SImode,
4581                                                  GET_MODE (operands[0]),
4582                                                  operands[1])),
4583                       gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4584   DONE;
4585   "
4588 ; If optimizing for size, or if we have load delay slots, then 
4589 ; we want to split the constant into two separate operations. 
4590 ; In both cases this may split a trivial part into a single data op
4591 ; leaving a single complex constant to load.  We can also get longer
4592 ; offsets in a LDR which means we get better chances of sharing the pool
4593 ; entries.  Finally, we can normally do a better job of scheduling
4594 ; LDR instructions than we can with LDM.
4595 ; This pattern will only match if the one above did not.
4596 (define_split
4597   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4598         (match_operand:ANY64 1 "const_double_operand" ""))]
4599   "TARGET_ARM && reload_completed
4600    && arm_const_double_by_parts (operands[1])"
4601   [(set (match_dup 0) (match_dup 1))
4602    (set (match_dup 2) (match_dup 3))]
4603   "
4604   operands[2] = gen_highpart (SImode, operands[0]);
4605   operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4606                                    operands[1]);
4607   operands[0] = gen_lowpart (SImode, operands[0]);
4608   operands[1] = gen_lowpart (SImode, operands[1]);
4609   "
4612 (define_split
4613   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4614         (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4615   "TARGET_EITHER && reload_completed"
4616   [(set (match_dup 0) (match_dup 1))
4617    (set (match_dup 2) (match_dup 3))]
4618   "
4619   operands[2] = gen_highpart (SImode, operands[0]);
4620   operands[3] = gen_highpart (SImode, operands[1]);
4621   operands[0] = gen_lowpart (SImode, operands[0]);
4622   operands[1] = gen_lowpart (SImode, operands[1]);
4624   /* Handle a partial overlap.  */
4625   if (rtx_equal_p (operands[0], operands[3]))
4626     {
4627       rtx tmp0 = operands[0];
4628       rtx tmp1 = operands[1];
4630       operands[0] = operands[2];
4631       operands[1] = operands[3];
4632       operands[2] = tmp0;
4633       operands[3] = tmp1;
4634     }
4635   "
4638 ;; We can't actually do base+index doubleword loads if the index and
4639 ;; destination overlap.  Split here so that we at least have chance to
4640 ;; schedule.
4641 (define_split
4642   [(set (match_operand:DI 0 "s_register_operand" "")
4643         (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4644                          (match_operand:SI 2 "s_register_operand" ""))))]
4645   "TARGET_LDRD
4646   && reg_overlap_mentioned_p (operands[0], operands[1])
4647   && reg_overlap_mentioned_p (operands[0], operands[2])"
4648   [(set (match_dup 4)
4649         (plus:SI (match_dup 1)
4650                  (match_dup 2)))
4651    (set (match_dup 0)
4652         (mem:DI (match_dup 4)))]
4653   "
4654   operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4655   "
4658 ;;; ??? This should have alternatives for constants.
4659 ;;; ??? This was originally identical to the movdf_insn pattern.
4660 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4661 ;;; thumb_reorg with a memory reference.
4662 (define_insn "*thumb1_movdi_insn"
4663   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4664         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
4665   "TARGET_THUMB1
4666    && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4667    && (   register_operand (operands[0], DImode)
4668        || register_operand (operands[1], DImode))"
4669   "*
4670   {
4671   switch (which_alternative)
4672     {
4673     default:
4674     case 0:
4675       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4676         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
4677       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
4678     case 1:
4679       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4680     case 2:
4681       operands[1] = GEN_INT (- INTVAL (operands[1]));
4682       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4683     case 3:
4684       return \"ldmia\\t%1, {%0, %H0}\";
4685     case 4:
4686       return \"stmia\\t%0, {%1, %H1}\";
4687     case 5:
4688       return thumb_load_double_from_address (operands);
4689     case 6:
4690       operands[2] = gen_rtx_MEM (SImode,
4691                              plus_constant (XEXP (operands[0], 0), 4));
4692       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4693       return \"\";
4694     case 7:
4695       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4696         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4697       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4698     }
4699   }"
4700   [(set_attr "length" "4,4,6,2,2,6,4,4")
4701    (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4702    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4705 (define_expand "movsi"
4706   [(set (match_operand:SI 0 "general_operand" "")
4707         (match_operand:SI 1 "general_operand" ""))]
4708   "TARGET_EITHER"
4709   "
4710   {
4711   rtx base, offset, tmp;
4713   if (TARGET_32BIT)
4714     {
4715       /* Everything except mem = const or mem = mem can be done easily.  */
4716       if (GET_CODE (operands[0]) == MEM)
4717         operands[1] = force_reg (SImode, operands[1]);
4718       if (arm_general_register_operand (operands[0], SImode)
4719           && GET_CODE (operands[1]) == CONST_INT
4720           && !(const_ok_for_arm (INTVAL (operands[1]))
4721                || const_ok_for_arm (~INTVAL (operands[1]))))
4722         {
4723            arm_split_constant (SET, SImode, NULL_RTX,
4724                                INTVAL (operands[1]), operands[0], NULL_RTX,
4725                                optimize && can_create_pseudo_p ());
4726           DONE;
4727         }
4728     }
4729   else /* TARGET_THUMB1...  */
4730     {
4731       if (can_create_pseudo_p ())
4732         {
4733           if (GET_CODE (operands[0]) != REG)
4734             operands[1] = force_reg (SImode, operands[1]);
4735         }
4736     }
4738   if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
4739     {
4740       split_const (operands[1], &base, &offset);
4741       if (GET_CODE (base) == SYMBOL_REF
4742           && !offset_within_block_p (base, INTVAL (offset)))
4743         {
4744           tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
4745           emit_move_insn (tmp, base);
4746           emit_insn (gen_addsi3 (operands[0], tmp, offset));
4747           DONE;
4748         }
4749     }
4751   /* Recognize the case where operand[1] is a reference to thread-local
4752      data and load its address to a register.  */
4753   if (arm_tls_referenced_p (operands[1]))
4754     {
4755       rtx tmp = operands[1];
4756       rtx addend = NULL;
4758       if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
4759         {
4760           addend = XEXP (XEXP (tmp, 0), 1);
4761           tmp = XEXP (XEXP (tmp, 0), 0);
4762         }
4764       gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
4765       gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
4767       tmp = legitimize_tls_address (tmp,
4768                                     !can_create_pseudo_p () ? operands[0] : 0);
4769       if (addend)
4770         {
4771           tmp = gen_rtx_PLUS (SImode, tmp, addend);
4772           tmp = force_operand (tmp, operands[0]);
4773         }
4774       operands[1] = tmp;
4775     }
4776   else if (flag_pic
4777            && (CONSTANT_P (operands[1])
4778                || symbol_mentioned_p (operands[1])
4779                || label_mentioned_p (operands[1])))
4780       operands[1] = legitimize_pic_address (operands[1], SImode,
4781                                             (!can_create_pseudo_p ()
4782                                              ? operands[0]
4783                                              : 0));
4784   }
4785   "
4788 (define_insn "*arm_movsi_insn"
4789   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r, m")
4790         (match_operand:SI 1 "general_operand"      "rI,K,N,mi,r"))]
4791   "TARGET_ARM && ! TARGET_IWMMXT
4792    && !(TARGET_HARD_FLOAT && TARGET_VFP)
4793    && (   register_operand (operands[0], SImode)
4794        || register_operand (operands[1], SImode))"
4795   "@
4796    mov%?\\t%0, %1
4797    mvn%?\\t%0, #%B1
4798    movw%?\\t%0, %1
4799    ldr%?\\t%0, %1
4800    str%?\\t%1, %0"
4801   [(set_attr "type" "*,*,*,load1,store1")
4802    (set_attr "predicable" "yes")
4803    (set_attr "pool_range" "*,*,*,4096,*")
4804    (set_attr "neg_pool_range" "*,*,*,4084,*")]
4807 (define_split
4808   [(set (match_operand:SI 0 "arm_general_register_operand" "")
4809         (match_operand:SI 1 "const_int_operand" ""))]
4810   "TARGET_32BIT
4811   && (!(const_ok_for_arm (INTVAL (operands[1]))
4812         || const_ok_for_arm (~INTVAL (operands[1]))))"
4813   [(clobber (const_int 0))]
4814   "
4815   arm_split_constant (SET, SImode, NULL_RTX, 
4816                       INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4817   DONE;
4818   "
4821 (define_insn "*thumb1_movsi_insn"
4822   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4823         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4824   "TARGET_THUMB1
4825    && (   register_operand (operands[0], SImode) 
4826        || register_operand (operands[1], SImode))"
4827   "@
4828    mov  %0, %1
4829    mov  %0, %1
4830    #
4831    #
4832    ldmia\\t%1, {%0}
4833    stmia\\t%0, {%1}
4834    ldr\\t%0, %1
4835    str\\t%1, %0
4836    mov\\t%0, %1"
4837   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4838    (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4839    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4842 (define_split 
4843   [(set (match_operand:SI 0 "register_operand" "")
4844         (match_operand:SI 1 "const_int_operand" ""))]
4845   "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
4846   [(set (match_dup 0) (match_dup 1))
4847    (set (match_dup 0) (neg:SI (match_dup 0)))]
4848   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4851 (define_split 
4852   [(set (match_operand:SI 0 "register_operand" "")
4853         (match_operand:SI 1 "const_int_operand" ""))]
4854   "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
4855   [(set (match_dup 0) (match_dup 1))
4856    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4857   "
4858   {
4859     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4860     unsigned HOST_WIDE_INT mask = 0xff;
4861     int i;
4862     
4863     for (i = 0; i < 25; i++)
4864       if ((val & (mask << i)) == val)
4865         break;
4867     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4868     if (i == 0)
4869       FAIL;
4871     operands[1] = GEN_INT (val >> i);
4872     operands[2] = GEN_INT (i);
4873   }"
4876 ;; When generating pic, we need to load the symbol offset into a register.
4877 ;; So that the optimizer does not confuse this with a normal symbol load
4878 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
4879 ;; since that is the only type of relocation we can use.
4881 ;; The rather odd constraints on the following are to force reload to leave
4882 ;; the insn alone, and to force the minipool generation pass to then move
4883 ;; the GOT symbol to memory.
4885 (define_insn "pic_load_addr_arm"
4886   [(set (match_operand:SI 0 "s_register_operand" "=r")
4887         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4888   "TARGET_ARM && flag_pic"
4889   "ldr%?\\t%0, %1"
4890   [(set_attr "type" "load1")
4891    (set (attr "pool_range")     (const_int 4096))
4892    (set (attr "neg_pool_range") (const_int 4084))]
4895 (define_insn "pic_load_addr_thumb1"
4896   [(set (match_operand:SI 0 "s_register_operand" "=l")
4897         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4898   "TARGET_THUMB1 && flag_pic"
4899   "ldr\\t%0, %1"
4900   [(set_attr "type" "load1")
4901    (set (attr "pool_range") (const_int 1024))]
4904 (define_insn "pic_add_dot_plus_four"
4905   [(set (match_operand:SI 0 "register_operand" "=r")
4906         (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "0")
4907                              (const (plus:SI (pc) (const_int 4))))
4908                     (match_operand 2 "" "")]
4909                    UNSPEC_PIC_BASE))]
4910   "TARGET_THUMB1"
4911   "*
4912   (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4913                                      INTVAL (operands[2]));
4914   return \"add\\t%0, %|pc\";
4915   "
4916   [(set_attr "length" "2")]
4919 (define_insn "pic_add_dot_plus_eight"
4920   [(set (match_operand:SI 0 "register_operand" "=r")
4921         (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
4922                              (const (plus:SI (pc) (const_int 8))))
4923                     (match_operand 2 "" "")]
4924                    UNSPEC_PIC_BASE))]
4925   "TARGET_ARM"
4926   "*
4927     (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4928                                        INTVAL (operands[2]));
4929     return \"add%?\\t%0, %|pc, %1\";
4930   "
4931   [(set_attr "predicable" "yes")]
4934 (define_insn "tls_load_dot_plus_eight"
4935   [(set (match_operand:SI 0 "register_operand" "+r")
4936         (mem:SI (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
4937                                      (const (plus:SI (pc) (const_int 8))))
4938                             (match_operand 2 "" "")]
4939                            UNSPEC_PIC_BASE)))]
4940   "TARGET_ARM"
4941   "*
4942     (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4943                                        INTVAL (operands[2]));
4944     return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
4945   "
4946   [(set_attr "predicable" "yes")]
4949 ;; PIC references to local variables can generate pic_add_dot_plus_eight
4950 ;; followed by a load.  These sequences can be crunched down to
4951 ;; tls_load_dot_plus_eight by a peephole.
4953 (define_peephole2
4954   [(parallel [(set (match_operand:SI 0 "register_operand" "")
4955                    (unspec:SI [(plus:SI (match_operand:SI 3 "register_operand" "")
4956                                         (const (plus:SI (pc) (const_int 8))))]
4957                               UNSPEC_PIC_BASE))
4958               (use (label_ref (match_operand 1 "" "")))])
4959    (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
4960   "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
4961   [(parallel [(set (match_dup 2)
4962                    (mem:SI (unspec:SI [(plus:SI (match_dup 3)
4963                                                 (const (plus:SI (pc) (const_int 8))))]
4964                                       UNSPEC_PIC_BASE)))
4965               (use (label_ref (match_dup 1)))])]
4966   ""
4969 (define_insn "pic_offset_arm"
4970   [(set (match_operand:SI 0 "register_operand" "=r")
4971         (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
4972                          (unspec:SI [(match_operand:SI 2 "" "X")]
4973                                     UNSPEC_PIC_OFFSET))))]
4974   "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
4975   "ldr%?\\t%0, [%1,%2]"
4976   [(set_attr "type" "load1")]
4979 (define_expand "builtin_setjmp_receiver"
4980   [(label_ref (match_operand 0 "" ""))]
4981   "flag_pic"
4982   "
4984   /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4985      register.  */
4986   if (arm_pic_register != INVALID_REGNUM)
4987     arm_load_pic_register (1UL << 3);
4988   DONE;
4991 ;; If copying one reg to another we can set the condition codes according to
4992 ;; its value.  Such a move is common after a return from subroutine and the
4993 ;; result is being tested against zero.
4995 (define_insn "*movsi_compare0"
4996   [(set (reg:CC CC_REGNUM)
4997         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4998                     (const_int 0)))
4999    (set (match_operand:SI 0 "s_register_operand" "=r,r")
5000         (match_dup 1))]
5001   "TARGET_32BIT"
5002   "@
5003    cmp%?\\t%0, #0
5004    sub%.\\t%0, %1, #0"
5005   [(set_attr "conds" "set")]
5008 ;; Subroutine to store a half word from a register into memory.
5009 ;; Operand 0 is the source register (HImode)
5010 ;; Operand 1 is the destination address in a register (SImode)
5012 ;; In both this routine and the next, we must be careful not to spill
5013 ;; a memory address of reg+large_const into a separate PLUS insn, since this
5014 ;; can generate unrecognizable rtl.
5016 (define_expand "storehi"
5017   [;; store the low byte
5018    (set (match_operand 1 "" "") (match_dup 3))
5019    ;; extract the high byte
5020    (set (match_dup 2)
5021         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
5022    ;; store the high byte
5023    (set (match_dup 4) (match_dup 5))]
5024   "TARGET_ARM"
5025   "
5026   {
5027     rtx op1 = operands[1];
5028     rtx addr = XEXP (op1, 0);
5029     enum rtx_code code = GET_CODE (addr);
5031     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5032         || code == MINUS)
5033       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
5035     operands[4] = adjust_address (op1, QImode, 1);
5036     operands[1] = adjust_address (operands[1], QImode, 0);
5037     operands[3] = gen_lowpart (QImode, operands[0]);
5038     operands[0] = gen_lowpart (SImode, operands[0]);
5039     operands[2] = gen_reg_rtx (SImode);
5040     operands[5] = gen_lowpart (QImode, operands[2]);
5041   }"
5044 (define_expand "storehi_bigend"
5045   [(set (match_dup 4) (match_dup 3))
5046    (set (match_dup 2)
5047         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
5048    (set (match_operand 1 "" "") (match_dup 5))]
5049   "TARGET_ARM"
5050   "
5051   {
5052     rtx op1 = operands[1];
5053     rtx addr = XEXP (op1, 0);
5054     enum rtx_code code = GET_CODE (addr);
5056     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5057         || code == MINUS)
5058       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
5060     operands[4] = adjust_address (op1, QImode, 1);
5061     operands[1] = adjust_address (operands[1], QImode, 0);
5062     operands[3] = gen_lowpart (QImode, operands[0]);
5063     operands[0] = gen_lowpart (SImode, operands[0]);
5064     operands[2] = gen_reg_rtx (SImode);
5065     operands[5] = gen_lowpart (QImode, operands[2]);
5066   }"
5069 ;; Subroutine to store a half word integer constant into memory.
5070 (define_expand "storeinthi"
5071   [(set (match_operand 0 "" "")
5072         (match_operand 1 "" ""))
5073    (set (match_dup 3) (match_dup 2))]
5074   "TARGET_ARM"
5075   "
5076   {
5077     HOST_WIDE_INT value = INTVAL (operands[1]);
5078     rtx addr = XEXP (operands[0], 0);
5079     rtx op0 = operands[0];
5080     enum rtx_code code = GET_CODE (addr);
5082     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5083         || code == MINUS)
5084       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
5086     operands[1] = gen_reg_rtx (SImode);
5087     if (BYTES_BIG_ENDIAN)
5088       {
5089         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5090         if ((value & 255) == ((value >> 8) & 255))
5091           operands[2] = operands[1];
5092         else
5093           {
5094             operands[2] = gen_reg_rtx (SImode);
5095             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5096           }
5097       }
5098     else
5099       {
5100         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5101         if ((value & 255) == ((value >> 8) & 255))
5102           operands[2] = operands[1];
5103         else
5104           {
5105             operands[2] = gen_reg_rtx (SImode);
5106             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5107           }
5108       }
5110     operands[3] = adjust_address (op0, QImode, 1);
5111     operands[0] = adjust_address (operands[0], QImode, 0);
5112     operands[2] = gen_lowpart (QImode, operands[2]);
5113     operands[1] = gen_lowpart (QImode, operands[1]);
5114   }"
5117 (define_expand "storehi_single_op"
5118   [(set (match_operand:HI 0 "memory_operand" "")
5119         (match_operand:HI 1 "general_operand" ""))]
5120   "TARGET_32BIT && arm_arch4"
5121   "
5122   if (!s_register_operand (operands[1], HImode))
5123     operands[1] = copy_to_mode_reg (HImode, operands[1]);
5124   "
5127 (define_expand "movhi"
5128   [(set (match_operand:HI 0 "general_operand" "")
5129         (match_operand:HI 1 "general_operand" ""))]
5130   "TARGET_EITHER"
5131   "
5132   if (TARGET_ARM)
5133     {
5134       if (can_create_pseudo_p ())
5135         {
5136           if (GET_CODE (operands[0]) == MEM)
5137             {
5138               if (arm_arch4)
5139                 {
5140                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5141                   DONE;
5142                 }
5143               if (GET_CODE (operands[1]) == CONST_INT)
5144                 emit_insn (gen_storeinthi (operands[0], operands[1]));
5145               else
5146                 {
5147                   if (GET_CODE (operands[1]) == MEM)
5148                     operands[1] = force_reg (HImode, operands[1]);
5149                   if (BYTES_BIG_ENDIAN)
5150                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
5151                   else
5152                    emit_insn (gen_storehi (operands[1], operands[0]));
5153                 }
5154               DONE;
5155             }
5156           /* Sign extend a constant, and keep it in an SImode reg.  */
5157           else if (GET_CODE (operands[1]) == CONST_INT)
5158             {
5159               rtx reg = gen_reg_rtx (SImode);
5160               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5162               /* If the constant is already valid, leave it alone.  */
5163               if (!const_ok_for_arm (val))
5164                 {
5165                   /* If setting all the top bits will make the constant 
5166                      loadable in a single instruction, then set them.  
5167                      Otherwise, sign extend the number.  */
5169                   if (const_ok_for_arm (~(val | ~0xffff)))
5170                     val |= ~0xffff;
5171                   else if (val & 0x8000)
5172                     val |= ~0xffff;
5173                 }
5175               emit_insn (gen_movsi (reg, GEN_INT (val)));
5176               operands[1] = gen_lowpart (HImode, reg);
5177             }
5178           else if (arm_arch4 && optimize && can_create_pseudo_p ()
5179                    && GET_CODE (operands[1]) == MEM)
5180             {
5181               rtx reg = gen_reg_rtx (SImode);
5183               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5184               operands[1] = gen_lowpart (HImode, reg);
5185             }
5186           else if (!arm_arch4)
5187             {
5188               if (GET_CODE (operands[1]) == MEM)
5189                 {
5190                   rtx base;
5191                   rtx offset = const0_rtx;
5192                   rtx reg = gen_reg_rtx (SImode);
5194                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
5195                        || (GET_CODE (base) == PLUS
5196                            && (GET_CODE (offset = XEXP (base, 1))
5197                                == CONST_INT)
5198                            && ((INTVAL(offset) & 1) != 1)
5199                            && GET_CODE (base = XEXP (base, 0)) == REG))
5200                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
5201                     {
5202                       rtx new;
5204                       new = widen_memory_access (operands[1], SImode,
5205                                                  ((INTVAL (offset) & ~3)
5206                                                   - INTVAL (offset)));
5207                       emit_insn (gen_movsi (reg, new));
5208                       if (((INTVAL (offset) & 2) != 0)
5209                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
5210                         {
5211                           rtx reg2 = gen_reg_rtx (SImode);
5213                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
5214                           reg = reg2;
5215                         }
5216                     }
5217                   else
5218                     emit_insn (gen_movhi_bytes (reg, operands[1]));
5220                   operands[1] = gen_lowpart (HImode, reg);
5221                }
5222            }
5223         }
5224       /* Handle loading a large integer during reload.  */
5225       else if (GET_CODE (operands[1]) == CONST_INT
5226                && !const_ok_for_arm (INTVAL (operands[1]))
5227                && !const_ok_for_arm (~INTVAL (operands[1])))
5228         {
5229           /* Writing a constant to memory needs a scratch, which should
5230              be handled with SECONDARY_RELOADs.  */
5231           gcc_assert (GET_CODE (operands[0]) == REG);
5233           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5234           emit_insn (gen_movsi (operands[0], operands[1]));
5235           DONE;
5236        }
5237     }
5238   else if (TARGET_THUMB2)
5239     {
5240       /* Thumb-2 can do everything except mem=mem and mem=const easily.  */
5241       if (can_create_pseudo_p ())
5242         {
5243           if (GET_CODE (operands[0]) != REG)
5244             operands[1] = force_reg (HImode, operands[1]);
5245           /* Zero extend a constant, and keep it in an SImode reg.  */
5246           else if (GET_CODE (operands[1]) == CONST_INT)
5247             {
5248               rtx reg = gen_reg_rtx (SImode);
5249               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5251               emit_insn (gen_movsi (reg, GEN_INT (val)));
5252               operands[1] = gen_lowpart (HImode, reg);
5253             }
5254         }
5255     }
5256   else /* TARGET_THUMB1 */
5257     {
5258       if (can_create_pseudo_p ())
5259         {
5260           if (GET_CODE (operands[1]) == CONST_INT)
5261             {
5262               rtx reg = gen_reg_rtx (SImode);
5264               emit_insn (gen_movsi (reg, operands[1]));
5265               operands[1] = gen_lowpart (HImode, reg);
5266             }
5268           /* ??? We shouldn't really get invalid addresses here, but this can
5269              happen if we are passed a SP (never OK for HImode/QImode) or 
5270              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
5271              HImode/QImode) relative address.  */
5272           /* ??? This should perhaps be fixed elsewhere, for instance, in
5273              fixup_stack_1, by checking for other kinds of invalid addresses,
5274              e.g. a bare reference to a virtual register.  This may confuse the
5275              alpha though, which must handle this case differently.  */
5276           if (GET_CODE (operands[0]) == MEM
5277               && !memory_address_p (GET_MODE (operands[0]),
5278                                     XEXP (operands[0], 0)))
5279             operands[0]
5280               = replace_equiv_address (operands[0],
5281                                        copy_to_reg (XEXP (operands[0], 0)));
5282    
5283           if (GET_CODE (operands[1]) == MEM
5284               && !memory_address_p (GET_MODE (operands[1]),
5285                                     XEXP (operands[1], 0)))
5286             operands[1]
5287               = replace_equiv_address (operands[1],
5288                                        copy_to_reg (XEXP (operands[1], 0)));
5290           if (GET_CODE (operands[1]) == MEM && optimize > 0)
5291             {
5292               rtx reg = gen_reg_rtx (SImode);
5294               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5295               operands[1] = gen_lowpart (HImode, reg);
5296             }
5298           if (GET_CODE (operands[0]) == MEM)
5299             operands[1] = force_reg (HImode, operands[1]);
5300         }
5301       else if (GET_CODE (operands[1]) == CONST_INT
5302                 && !satisfies_constraint_I (operands[1]))
5303         {
5304           /* Handle loading a large integer during reload.  */
5306           /* Writing a constant to memory needs a scratch, which should
5307              be handled with SECONDARY_RELOADs.  */
5308           gcc_assert (GET_CODE (operands[0]) == REG);
5310           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5311           emit_insn (gen_movsi (operands[0], operands[1]));
5312           DONE;
5313         }
5314     }
5315   "
5318 (define_insn "*thumb1_movhi_insn"
5319   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5320         (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
5321   "TARGET_THUMB1
5322    && (   register_operand (operands[0], HImode)
5323        || register_operand (operands[1], HImode))"
5324   "*
5325   switch (which_alternative)
5326     {
5327     case 0: return \"add        %0, %1, #0\";
5328     case 2: return \"strh       %1, %0\";
5329     case 3: return \"mov        %0, %1\";
5330     case 4: return \"mov        %0, %1\";
5331     case 5: return \"mov        %0, %1\";
5332     default: gcc_unreachable ();
5333     case 1:
5334       /* The stack pointer can end up being taken as an index register.
5335           Catch this case here and deal with it.  */
5336       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
5337           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
5338           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
5339         {
5340           rtx ops[2];
5341           ops[0] = operands[0];
5342           ops[1] = XEXP (XEXP (operands[1], 0), 0);
5343       
5344           output_asm_insn (\"mov        %0, %1\", ops);
5346           XEXP (XEXP (operands[1], 0), 0) = operands[0];
5347     
5348         }
5349       return \"ldrh     %0, %1\";
5350     }"
5351   [(set_attr "length" "2,4,2,2,2,2")
5352    (set_attr "type" "*,load1,store1,*,*,*")]
5356 (define_expand "movhi_bytes"
5357   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
5358    (set (match_dup 3)
5359         (zero_extend:SI (match_dup 6)))
5360    (set (match_operand:SI 0 "" "")
5361          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
5362   "TARGET_ARM"
5363   "
5364   {
5365     rtx mem1, mem2;
5366     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5368     mem1 = change_address (operands[1], QImode, addr);
5369     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
5370     operands[0] = gen_lowpart (SImode, operands[0]);
5371     operands[1] = mem1;
5372     operands[2] = gen_reg_rtx (SImode);
5373     operands[3] = gen_reg_rtx (SImode);
5374     operands[6] = mem2;
5376     if (BYTES_BIG_ENDIAN)
5377       {
5378         operands[4] = operands[2];
5379         operands[5] = operands[3];
5380       }
5381     else
5382       {
5383         operands[4] = operands[3];
5384         operands[5] = operands[2];
5385       }
5386   }"
5389 (define_expand "movhi_bigend"
5390   [(set (match_dup 2)
5391         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
5392                    (const_int 16)))
5393    (set (match_dup 3)
5394         (ashiftrt:SI (match_dup 2) (const_int 16)))
5395    (set (match_operand:HI 0 "s_register_operand" "")
5396         (match_dup 4))]
5397   "TARGET_ARM"
5398   "
5399   operands[2] = gen_reg_rtx (SImode);
5400   operands[3] = gen_reg_rtx (SImode);
5401   operands[4] = gen_lowpart (HImode, operands[3]);
5402   "
5405 ;; Pattern to recognize insn generated default case above
5406 (define_insn "*movhi_insn_arch4"
5407   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
5408         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
5409   "TARGET_ARM
5410    && arm_arch4
5411    && (GET_CODE (operands[1]) != CONST_INT
5412        || const_ok_for_arm (INTVAL (operands[1]))
5413        || const_ok_for_arm (~INTVAL (operands[1])))"
5414   "@
5415    mov%?\\t%0, %1\\t%@ movhi
5416    mvn%?\\t%0, #%B1\\t%@ movhi
5417    str%(h%)\\t%1, %0\\t%@ movhi
5418    ldr%(h%)\\t%0, %1\\t%@ movhi"
5419   [(set_attr "type" "*,*,store1,load1")
5420    (set_attr "predicable" "yes")
5421    (set_attr "pool_range" "*,*,*,256")
5422    (set_attr "neg_pool_range" "*,*,*,244")]
5425 (define_insn "*movhi_bytes"
5426   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
5427         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
5428   "TARGET_ARM"
5429   "@
5430    mov%?\\t%0, %1\\t%@ movhi
5431    mvn%?\\t%0, #%B1\\t%@ movhi"
5432   [(set_attr "predicable" "yes")]
5435 (define_expand "thumb_movhi_clobber"
5436   [(set (match_operand:HI     0 "memory_operand"   "")
5437         (match_operand:HI     1 "register_operand" ""))
5438    (clobber (match_operand:DI 2 "register_operand" ""))]
5439   "TARGET_THUMB1"
5440   "
5441   if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
5442       && REGNO (operands[1]) <= LAST_LO_REGNUM)
5443     {
5444       emit_insn (gen_movhi (operands[0], operands[1]));
5445       DONE;
5446     }
5447   /* XXX Fixme, need to handle other cases here as well.  */
5448   gcc_unreachable ();
5449   "
5451         
5452 ;; We use a DImode scratch because we may occasionally need an additional
5453 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
5454 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
5455 (define_expand "reload_outhi"
5456   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
5457               (match_operand:HI 1 "s_register_operand"        "r")
5458               (match_operand:DI 2 "s_register_operand"        "=&l")])]
5459   "TARGET_EITHER"
5460   "if (TARGET_ARM)
5461      arm_reload_out_hi (operands);
5462    else
5463      thumb_reload_out_hi (operands);
5464   DONE;
5465   "
5468 (define_expand "reload_inhi"
5469   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
5470               (match_operand:HI 1 "arm_reload_memory_operand" "o")
5471               (match_operand:DI 2 "s_register_operand" "=&r")])]
5472   "TARGET_EITHER"
5473   "
5474   if (TARGET_ARM)
5475     arm_reload_in_hi (operands);
5476   else
5477     thumb_reload_out_hi (operands);
5478   DONE;
5481 (define_expand "movqi"
5482   [(set (match_operand:QI 0 "general_operand" "")
5483         (match_operand:QI 1 "general_operand" ""))]
5484   "TARGET_EITHER"
5485   "
5486   /* Everything except mem = const or mem = mem can be done easily */
5488   if (can_create_pseudo_p ())
5489     {
5490       if (GET_CODE (operands[1]) == CONST_INT)
5491         {
5492           rtx reg = gen_reg_rtx (SImode);
5494           emit_insn (gen_movsi (reg, operands[1]));
5495           operands[1] = gen_lowpart (QImode, reg);
5496         }
5498       if (TARGET_THUMB)
5499         {
5500           /* ??? We shouldn't really get invalid addresses here, but this can
5501              happen if we are passed a SP (never OK for HImode/QImode) or
5502              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
5503              HImode/QImode) relative address.  */
5504           /* ??? This should perhaps be fixed elsewhere, for instance, in
5505              fixup_stack_1, by checking for other kinds of invalid addresses,
5506              e.g. a bare reference to a virtual register.  This may confuse the
5507              alpha though, which must handle this case differently.  */
5508           if (GET_CODE (operands[0]) == MEM
5509               && !memory_address_p (GET_MODE (operands[0]),
5510                                      XEXP (operands[0], 0)))
5511             operands[0]
5512               = replace_equiv_address (operands[0],
5513                                        copy_to_reg (XEXP (operands[0], 0)));
5514           if (GET_CODE (operands[1]) == MEM
5515               && !memory_address_p (GET_MODE (operands[1]),
5516                                     XEXP (operands[1], 0)))
5517              operands[1]
5518                = replace_equiv_address (operands[1],
5519                                         copy_to_reg (XEXP (operands[1], 0)));
5520         }
5522       if (GET_CODE (operands[1]) == MEM && optimize > 0)
5523         {
5524           rtx reg = gen_reg_rtx (SImode);
5526           emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5527           operands[1] = gen_lowpart (QImode, reg);
5528         }
5530       if (GET_CODE (operands[0]) == MEM)
5531         operands[1] = force_reg (QImode, operands[1]);
5532     }
5533   else if (TARGET_THUMB
5534            && GET_CODE (operands[1]) == CONST_INT
5535            && !satisfies_constraint_I (operands[1]))
5536     {
5537       /* Handle loading a large integer during reload.  */
5539       /* Writing a constant to memory needs a scratch, which should
5540          be handled with SECONDARY_RELOADs.  */
5541       gcc_assert (GET_CODE (operands[0]) == REG);
5543       operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5544       emit_insn (gen_movsi (operands[0], operands[1]));
5545       DONE;
5546     }
5547   "
5551 (define_insn "*arm_movqi_insn"
5552   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5553         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5554   "TARGET_32BIT
5555    && (   register_operand (operands[0], QImode)
5556        || register_operand (operands[1], QImode))"
5557   "@
5558    mov%?\\t%0, %1
5559    mvn%?\\t%0, #%B1
5560    ldr%(b%)\\t%0, %1
5561    str%(b%)\\t%1, %0"
5562   [(set_attr "type" "*,*,load1,store1")
5563    (set_attr "predicable" "yes")]
5566 (define_insn "*thumb1_movqi_insn"
5567   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5568         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
5569   "TARGET_THUMB1
5570    && (   register_operand (operands[0], QImode)
5571        || register_operand (operands[1], QImode))"
5572   "@
5573    add\\t%0, %1, #0
5574    ldrb\\t%0, %1
5575    strb\\t%1, %0
5576    mov\\t%0, %1
5577    mov\\t%0, %1
5578    mov\\t%0, %1"
5579   [(set_attr "length" "2")
5580    (set_attr "type" "*,load1,store1,*,*,*")
5581    (set_attr "pool_range" "*,32,*,*,*,*")]
5584 (define_expand "movsf"
5585   [(set (match_operand:SF 0 "general_operand" "")
5586         (match_operand:SF 1 "general_operand" ""))]
5587   "TARGET_EITHER"
5588   "
5589   if (TARGET_32BIT)
5590     {
5591       if (GET_CODE (operands[0]) == MEM)
5592         operands[1] = force_reg (SFmode, operands[1]);
5593     }
5594   else /* TARGET_THUMB1 */
5595     {
5596       if (can_create_pseudo_p ())
5597         {
5598            if (GET_CODE (operands[0]) != REG)
5599              operands[1] = force_reg (SFmode, operands[1]);
5600         }
5601     }
5602   "
5605 ;; Transform a floating-point move of a constant into a core register into
5606 ;; an SImode operation.
5607 (define_split
5608   [(set (match_operand:SF 0 "arm_general_register_operand" "")
5609         (match_operand:SF 1 "immediate_operand" ""))]
5610   "TARGET_32BIT
5611    && reload_completed
5612    && GET_CODE (operands[1]) == CONST_DOUBLE"
5613   [(set (match_dup 2) (match_dup 3))]
5614   "
5615   operands[2] = gen_lowpart (SImode, operands[0]);
5616   operands[3] = gen_lowpart (SImode, operands[1]);
5617   if (operands[2] == 0 || operands[3] == 0)
5618     FAIL;
5619   "
5622 (define_insn "*arm_movsf_soft_insn"
5623   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5624         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
5625   "TARGET_ARM
5626    && TARGET_SOFT_FLOAT
5627    && (GET_CODE (operands[0]) != MEM
5628        || register_operand (operands[1], SFmode))"
5629   "@
5630    mov%?\\t%0, %1
5631    ldr%?\\t%0, %1\\t%@ float
5632    str%?\\t%1, %0\\t%@ float"
5633   [(set_attr "length" "4,4,4")
5634    (set_attr "predicable" "yes")
5635    (set_attr "type" "*,load1,store1")
5636    (set_attr "pool_range" "*,4096,*")
5637    (set_attr "neg_pool_range" "*,4084,*")]
5640 ;;; ??? This should have alternatives for constants.
5641 (define_insn "*thumb1_movsf_insn"
5642   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5643         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5644   "TARGET_THUMB1
5645    && (   register_operand (operands[0], SFmode) 
5646        || register_operand (operands[1], SFmode))"
5647   "@
5648    add\\t%0, %1, #0
5649    ldmia\\t%1, {%0}
5650    stmia\\t%0, {%1}
5651    ldr\\t%0, %1
5652    str\\t%1, %0
5653    mov\\t%0, %1
5654    mov\\t%0, %1"
5655   [(set_attr "length" "2")
5656    (set_attr "type" "*,load1,store1,load1,store1,*,*")
5657    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5660 (define_expand "movdf"
5661   [(set (match_operand:DF 0 "general_operand" "")
5662         (match_operand:DF 1 "general_operand" ""))]
5663   "TARGET_EITHER"
5664   "
5665   if (TARGET_32BIT)
5666     {
5667       if (GET_CODE (operands[0]) == MEM)
5668         operands[1] = force_reg (DFmode, operands[1]);
5669     }
5670   else /* TARGET_THUMB */
5671     {
5672       if (can_create_pseudo_p ())
5673         {
5674           if (GET_CODE (operands[0]) != REG)
5675             operands[1] = force_reg (DFmode, operands[1]);
5676         }
5677     }
5678   "
5681 ;; Reloading a df mode value stored in integer regs to memory can require a
5682 ;; scratch reg.
5683 (define_expand "reload_outdf"
5684   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5685    (match_operand:DF 1 "s_register_operand" "r")
5686    (match_operand:SI 2 "s_register_operand" "=&r")]
5687   "TARGET_32BIT"
5688   "
5689   {
5690     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5692     if (code == REG)
5693       operands[2] = XEXP (operands[0], 0);
5694     else if (code == POST_INC || code == PRE_DEC)
5695       {
5696         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5697         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5698         emit_insn (gen_movdi (operands[0], operands[1]));
5699         DONE;
5700       }
5701     else if (code == PRE_INC)
5702       {
5703         rtx reg = XEXP (XEXP (operands[0], 0), 0);
5705         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5706         operands[2] = reg;
5707       }
5708     else if (code == POST_DEC)
5709       operands[2] = XEXP (XEXP (operands[0], 0), 0);
5710     else
5711       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5712                              XEXP (XEXP (operands[0], 0), 1)));
5714     emit_insn (gen_rtx_SET (VOIDmode,
5715                             replace_equiv_address (operands[0], operands[2]),
5716                             operands[1]));
5718     if (code == POST_DEC)
5719       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5721     DONE;
5722   }"
5725 (define_insn "*movdf_soft_insn"
5726   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5727         (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
5728   "TARGET_ARM && TARGET_SOFT_FLOAT
5729    && (   register_operand (operands[0], DFmode)
5730        || register_operand (operands[1], DFmode))"
5731   "*
5732   switch (which_alternative)
5733     {
5734     case 0:
5735     case 1:
5736     case 2:
5737       return \"#\";
5738     default:
5739       return output_move_double (operands);
5740     }
5741   "
5742   [(set_attr "length" "8,12,16,8,8")
5743    (set_attr "type" "*,*,*,load2,store2")
5744    (set_attr "pool_range" "1020")
5745    (set_attr "neg_pool_range" "1008")]
5748 ;;; ??? This should have alternatives for constants.
5749 ;;; ??? This was originally identical to the movdi_insn pattern.
5750 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5751 ;;; thumb_reorg with a memory reference.
5752 (define_insn "*thumb_movdf_insn"
5753   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5754         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5755   "TARGET_THUMB1
5756    && (   register_operand (operands[0], DFmode)
5757        || register_operand (operands[1], DFmode))"
5758   "*
5759   switch (which_alternative)
5760     {
5761     default:
5762     case 0:
5763       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5764         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5765       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5766     case 1:
5767       return \"ldmia\\t%1, {%0, %H0}\";
5768     case 2:
5769       return \"stmia\\t%0, {%1, %H1}\";
5770     case 3:
5771       return thumb_load_double_from_address (operands);
5772     case 4:
5773       operands[2] = gen_rtx_MEM (SImode,
5774                                  plus_constant (XEXP (operands[0], 0), 4));
5775       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5776       return \"\";
5777     case 5:
5778       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5779         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5780       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5781     }
5782   "
5783   [(set_attr "length" "4,2,2,6,4,4")
5784    (set_attr "type" "*,load2,store2,load2,store2,*")
5785    (set_attr "pool_range" "*,*,*,1020,*,*")]
5788 (define_expand "movxf"
5789   [(set (match_operand:XF 0 "general_operand" "")
5790         (match_operand:XF 1 "general_operand" ""))]
5791   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
5792   "
5793   if (GET_CODE (operands[0]) == MEM)
5794     operands[1] = force_reg (XFmode, operands[1]);
5795   "
5800 ;; load- and store-multiple insns
5801 ;; The arm can load/store any set of registers, provided that they are in
5802 ;; ascending order; but that is beyond GCC so stick with what it knows.
5804 (define_expand "load_multiple"
5805   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5806                           (match_operand:SI 1 "" ""))
5807                      (use (match_operand:SI 2 "" ""))])]
5808   "TARGET_32BIT"
5810   HOST_WIDE_INT offset = 0;
5812   /* Support only fixed point registers.  */
5813   if (GET_CODE (operands[2]) != CONST_INT
5814       || INTVAL (operands[2]) > 14
5815       || INTVAL (operands[2]) < 2
5816       || GET_CODE (operands[1]) != MEM
5817       || GET_CODE (operands[0]) != REG
5818       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5819       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5820     FAIL;
5822   operands[3]
5823     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5824                              force_reg (SImode, XEXP (operands[1], 0)),
5825                              TRUE, FALSE, operands[1], &offset);
5828 ;; Load multiple with write-back
5830 (define_insn "*ldmsi_postinc4"
5831   [(match_parallel 0 "load_multiple_operation"
5832     [(set (match_operand:SI 1 "s_register_operand" "=r")
5833           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5834                    (const_int 16)))
5835      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5836           (mem:SI (match_dup 2)))
5837      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5838           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5839      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5840           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5841      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5842           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5843   "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
5844   "ldm%(ia%)\\t%1!, {%3, %4, %5, %6}"
5845   [(set_attr "type" "load4")
5846    (set_attr "predicable" "yes")]
5849 (define_insn "*ldmsi_postinc4_thumb1"
5850   [(match_parallel 0 "load_multiple_operation"
5851     [(set (match_operand:SI 1 "s_register_operand" "=l")
5852           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5853                    (const_int 16)))
5854      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5855           (mem:SI (match_dup 2)))
5856      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5857           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5858      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5859           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5860      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5861           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5862   "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
5863   "ldmia\\t%1!, {%3, %4, %5, %6}"
5864   [(set_attr "type" "load4")]
5867 (define_insn "*ldmsi_postinc3"
5868   [(match_parallel 0 "load_multiple_operation"
5869     [(set (match_operand:SI 1 "s_register_operand" "=r")
5870           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5871                    (const_int 12)))
5872      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5873           (mem:SI (match_dup 2)))
5874      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5875           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5876      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5877           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5878   "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
5879   "ldm%(ia%)\\t%1!, {%3, %4, %5}"
5880   [(set_attr "type" "load3")
5881    (set_attr "predicable" "yes")]
5884 (define_insn "*ldmsi_postinc2"
5885   [(match_parallel 0 "load_multiple_operation"
5886     [(set (match_operand:SI 1 "s_register_operand" "=r")
5887           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5888                    (const_int 8)))
5889      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5890           (mem:SI (match_dup 2)))
5891      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5892           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5893   "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
5894   "ldm%(ia%)\\t%1!, {%3, %4}"
5895   [(set_attr "type" "load2")
5896    (set_attr "predicable" "yes")]
5899 ;; Ordinary load multiple
5901 (define_insn "*ldmsi4"
5902   [(match_parallel 0 "load_multiple_operation"
5903     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5904           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5905      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5906           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5907      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5908           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5909      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5910           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5911   "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
5912   "ldm%(ia%)\\t%1, {%2, %3, %4, %5}"
5913   [(set_attr "type" "load4")
5914    (set_attr "predicable" "yes")]
5917 (define_insn "*ldmsi3"
5918   [(match_parallel 0 "load_multiple_operation"
5919     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5920           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5921      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5922           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5923      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5924           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5925   "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
5926   "ldm%(ia%)\\t%1, {%2, %3, %4}"
5927   [(set_attr "type" "load3")
5928    (set_attr "predicable" "yes")]
5931 (define_insn "*ldmsi2"
5932   [(match_parallel 0 "load_multiple_operation"
5933     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5934           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5935      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5936           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5937   "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
5938   "ldm%(ia%)\\t%1, {%2, %3}"
5939   [(set_attr "type" "load2")
5940    (set_attr "predicable" "yes")]
5943 (define_expand "store_multiple"
5944   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5945                           (match_operand:SI 1 "" ""))
5946                      (use (match_operand:SI 2 "" ""))])]
5947   "TARGET_32BIT"
5949   HOST_WIDE_INT offset = 0;
5951   /* Support only fixed point registers.  */
5952   if (GET_CODE (operands[2]) != CONST_INT
5953       || INTVAL (operands[2]) > 14
5954       || INTVAL (operands[2]) < 2
5955       || GET_CODE (operands[1]) != REG
5956       || GET_CODE (operands[0]) != MEM
5957       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5958       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5959     FAIL;
5961   operands[3]
5962     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5963                               force_reg (SImode, XEXP (operands[0], 0)),
5964                               TRUE, FALSE, operands[0], &offset);
5967 ;; Store multiple with write-back
5969 (define_insn "*stmsi_postinc4"
5970   [(match_parallel 0 "store_multiple_operation"
5971     [(set (match_operand:SI 1 "s_register_operand" "=r")
5972           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5973                    (const_int 16)))
5974      (set (mem:SI (match_dup 2))
5975           (match_operand:SI 3 "arm_hard_register_operand" ""))
5976      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5977           (match_operand:SI 4 "arm_hard_register_operand" ""))
5978      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5979           (match_operand:SI 5 "arm_hard_register_operand" ""))
5980      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5981           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5982   "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
5983   "stm%(ia%)\\t%1!, {%3, %4, %5, %6}"
5984   [(set_attr "predicable" "yes")
5985    (set_attr "type" "store4")]
5988 (define_insn "*stmsi_postinc4_thumb1"
5989   [(match_parallel 0 "store_multiple_operation"
5990     [(set (match_operand:SI 1 "s_register_operand" "=l")
5991           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5992                    (const_int 16)))
5993      (set (mem:SI (match_dup 2))
5994           (match_operand:SI 3 "arm_hard_register_operand" ""))
5995      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5996           (match_operand:SI 4 "arm_hard_register_operand" ""))
5997      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5998           (match_operand:SI 5 "arm_hard_register_operand" ""))
5999      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
6000           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
6001   "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
6002   "stmia\\t%1!, {%3, %4, %5, %6}"
6003   [(set_attr "type" "store4")]
6006 (define_insn "*stmsi_postinc3"
6007   [(match_parallel 0 "store_multiple_operation"
6008     [(set (match_operand:SI 1 "s_register_operand" "=r")
6009           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6010                    (const_int 12)))
6011      (set (mem:SI (match_dup 2))
6012           (match_operand:SI 3 "arm_hard_register_operand" ""))
6013      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6014           (match_operand:SI 4 "arm_hard_register_operand" ""))
6015      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6016           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
6017   "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6018   "stm%(ia%)\\t%1!, {%3, %4, %5}"
6019   [(set_attr "predicable" "yes")
6020    (set_attr "type" "store3")]
6023 (define_insn "*stmsi_postinc2"
6024   [(match_parallel 0 "store_multiple_operation"
6025     [(set (match_operand:SI 1 "s_register_operand" "=r")
6026           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6027                    (const_int 8)))
6028      (set (mem:SI (match_dup 2))
6029           (match_operand:SI 3 "arm_hard_register_operand" ""))
6030      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6031           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
6032   "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6033   "stm%(ia%)\\t%1!, {%3, %4}"
6034   [(set_attr "predicable" "yes")
6035    (set_attr "type" "store2")]
6038 ;; Ordinary store multiple
6040 (define_insn "*stmsi4"
6041   [(match_parallel 0 "store_multiple_operation"
6042     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6043           (match_operand:SI 2 "arm_hard_register_operand" ""))
6044      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6045           (match_operand:SI 3 "arm_hard_register_operand" ""))
6046      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
6047           (match_operand:SI 4 "arm_hard_register_operand" ""))
6048      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
6049           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
6050   "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6051   "stm%(ia%)\\t%1, {%2, %3, %4, %5}"
6052   [(set_attr "predicable" "yes")
6053    (set_attr "type" "store4")]
6056 (define_insn "*stmsi3"
6057   [(match_parallel 0 "store_multiple_operation"
6058     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6059           (match_operand:SI 2 "arm_hard_register_operand" ""))
6060      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6061           (match_operand:SI 3 "arm_hard_register_operand" ""))
6062      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
6063           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
6064   "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6065   "stm%(ia%)\\t%1, {%2, %3, %4}"
6066   [(set_attr "predicable" "yes")
6067    (set_attr "type" "store3")]
6070 (define_insn "*stmsi2"
6071   [(match_parallel 0 "store_multiple_operation"
6072     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6073           (match_operand:SI 2 "arm_hard_register_operand" ""))
6074      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6075           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
6076   "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
6077   "stm%(ia%)\\t%1, {%2, %3}"
6078   [(set_attr "predicable" "yes")
6079    (set_attr "type" "store2")]
6082 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
6083 ;; We could let this apply for blocks of less than this, but it clobbers so
6084 ;; many registers that there is then probably a better way.
6086 (define_expand "movmemqi"
6087   [(match_operand:BLK 0 "general_operand" "")
6088    (match_operand:BLK 1 "general_operand" "")
6089    (match_operand:SI 2 "const_int_operand" "")
6090    (match_operand:SI 3 "const_int_operand" "")]
6091   "TARGET_EITHER"
6092   "
6093   if (TARGET_32BIT)
6094     {
6095       if (arm_gen_movmemqi (operands))
6096         DONE;
6097       FAIL;
6098     }
6099   else /* TARGET_THUMB1 */
6100     {
6101       if (   INTVAL (operands[3]) != 4
6102           || INTVAL (operands[2]) > 48)
6103         FAIL;
6105       thumb_expand_movmemqi (operands);
6106       DONE;
6107     }
6108   "
6111 ;; Thumb block-move insns
6113 (define_insn "movmem12b"
6114   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6115         (mem:SI (match_operand:SI 3 "register_operand" "1")))
6116    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6117         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6118    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6119         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
6120    (set (match_operand:SI 0 "register_operand" "=l")
6121         (plus:SI (match_dup 2) (const_int 12)))
6122    (set (match_operand:SI 1 "register_operand" "=l")
6123         (plus:SI (match_dup 3) (const_int 12)))
6124    (clobber (match_scratch:SI 4 "=&l"))
6125    (clobber (match_scratch:SI 5 "=&l"))
6126    (clobber (match_scratch:SI 6 "=&l"))]
6127   "TARGET_THUMB1"
6128   "* return thumb_output_move_mem_multiple (3, operands);"
6129   [(set_attr "length" "4")
6130    ; This isn't entirely accurate...  It loads as well, but in terms of
6131    ; scheduling the following insn it is better to consider it as a store
6132    (set_attr "type" "store3")]
6135 (define_insn "movmem8b"
6136   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6137         (mem:SI (match_operand:SI 3 "register_operand" "1")))
6138    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6139         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6140    (set (match_operand:SI 0 "register_operand" "=l")
6141         (plus:SI (match_dup 2) (const_int 8)))
6142    (set (match_operand:SI 1 "register_operand" "=l")
6143         (plus:SI (match_dup 3) (const_int 8)))
6144    (clobber (match_scratch:SI 4 "=&l"))
6145    (clobber (match_scratch:SI 5 "=&l"))]
6146   "TARGET_THUMB1"
6147   "* return thumb_output_move_mem_multiple (2, operands);"
6148   [(set_attr "length" "4")
6149    ; This isn't entirely accurate...  It loads as well, but in terms of
6150    ; scheduling the following insn it is better to consider it as a store
6151    (set_attr "type" "store2")]
6156 ;; Compare & branch insns
6157 ;; The range calculations are based as follows:
6158 ;; For forward branches, the address calculation returns the address of
6159 ;; the next instruction.  This is 2 beyond the branch instruction.
6160 ;; For backward branches, the address calculation returns the address of
6161 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
6162 ;; instruction for the shortest sequence, and 4 before the branch instruction
6163 ;; if we have to jump around an unconditional branch.
6164 ;; To the basic branch range the PC offset must be added (this is +4).
6165 ;; So for forward branches we have 
6166 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6167 ;; And for backward branches we have 
6168 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6170 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6171 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
6173 (define_expand "cbranchsi4"
6174   [(set (pc) (if_then_else
6175               (match_operator 0 "arm_comparison_operator"
6176                [(match_operand:SI 1 "s_register_operand" "")
6177                 (match_operand:SI 2 "nonmemory_operand" "")])
6178               (label_ref (match_operand 3 "" ""))
6179               (pc)))]
6180   "TARGET_THUMB1"
6181   "
6182   if (thumb1_cmpneg_operand (operands[2], SImode))
6183     {
6184       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6185                                               operands[3], operands[0]));
6186       DONE;
6187     }
6188   if (!thumb1_cmp_operand (operands[2], SImode))
6189     operands[2] = force_reg (SImode, operands[2]);
6190   ")
6192 (define_insn "*cbranchsi4_insn"
6193   [(set (pc) (if_then_else
6194               (match_operator 0 "arm_comparison_operator"
6195                [(match_operand:SI 1 "s_register_operand" "l,*h")
6196                 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
6197               (label_ref (match_operand 3 "" ""))
6198               (pc)))]
6199   "TARGET_THUMB1"
6200   "*
6201   output_asm_insn (\"cmp\\t%1, %2\", operands);
6203   switch (get_attr_length (insn))
6204     {
6205     case 4:  return \"b%d0\\t%l3\";
6206     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6207     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6208     }
6209   "
6210   [(set (attr "far_jump")
6211         (if_then_else
6212             (eq_attr "length" "8")
6213             (const_string "yes")
6214             (const_string "no")))
6215    (set (attr "length") 
6216         (if_then_else
6217             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6218                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6219             (const_int 4)
6220             (if_then_else
6221                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6222                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6223                 (const_int 6)
6224                 (const_int 8))))]
6227 (define_insn "cbranchsi4_scratch"
6228   [(set (pc) (if_then_else
6229               (match_operator 4 "arm_comparison_operator"
6230                [(match_operand:SI 1 "s_register_operand" "l,0")
6231                 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
6232               (label_ref (match_operand 3 "" ""))
6233               (pc)))
6234    (clobber (match_scratch:SI 0 "=l,l"))]
6235   "TARGET_THUMB1"
6236   "*
6237   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
6239   switch (get_attr_length (insn))
6240     {
6241     case 4:  return \"b%d4\\t%l3\";
6242     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6243     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6244     }
6245   "
6246   [(set (attr "far_jump")
6247         (if_then_else
6248             (eq_attr "length" "8")
6249             (const_string "yes")
6250             (const_string "no")))
6251    (set (attr "length") 
6252         (if_then_else
6253             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6254                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6255             (const_int 4)
6256             (if_then_else
6257                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6258                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6259                 (const_int 6)
6260                 (const_int 8))))]
6262 (define_insn "*movsi_cbranchsi4"
6263   [(set (pc)
6264         (if_then_else
6265          (match_operator 3 "arm_comparison_operator"
6266           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
6267            (const_int 0)])
6268          (label_ref (match_operand 2 "" ""))
6269          (pc)))
6270    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
6271         (match_dup 1))]
6272   "TARGET_THUMB1"
6273   "*{
6274   if (which_alternative == 0)
6275     output_asm_insn (\"cmp\t%0, #0\", operands);
6276   else if (which_alternative == 1)
6277     output_asm_insn (\"sub\t%0, %1, #0\", operands);
6278   else
6279     {
6280       output_asm_insn (\"cmp\t%1, #0\", operands);
6281       if (which_alternative == 2)
6282         output_asm_insn (\"mov\t%0, %1\", operands);
6283       else
6284         output_asm_insn (\"str\t%1, %0\", operands);
6285     }
6286   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
6287     {
6288     case 4:  return \"b%d3\\t%l2\";
6289     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6290     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
6291     }
6292   }"
6293   [(set (attr "far_jump")
6294         (if_then_else
6295             (ior (and (gt (symbol_ref ("which_alternative"))
6296                           (const_int 1))
6297                       (eq_attr "length" "8"))
6298                  (eq_attr "length" "10"))
6299             (const_string "yes")
6300             (const_string "no")))
6301    (set (attr "length")
6302      (if_then_else
6303        (le (symbol_ref ("which_alternative"))
6304                        (const_int 1))
6305        (if_then_else
6306          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6307               (le (minus (match_dup 2) (pc)) (const_int 256)))
6308          (const_int 4)
6309          (if_then_else
6310            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6311                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6312            (const_int 6)
6313            (const_int 8)))
6314        (if_then_else
6315          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
6316               (le (minus (match_dup 2) (pc)) (const_int 256)))
6317          (const_int 6)
6318          (if_then_else
6319            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
6320                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6321            (const_int 8)
6322            (const_int 10)))))]
6325 (define_insn "*negated_cbranchsi4"
6326   [(set (pc)
6327         (if_then_else
6328          (match_operator 0 "equality_operator"
6329           [(match_operand:SI 1 "s_register_operand" "l")
6330            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
6331          (label_ref (match_operand 3 "" ""))
6332          (pc)))]
6333   "TARGET_THUMB1"
6334   "*
6335   output_asm_insn (\"cmn\\t%1, %2\", operands);
6336   switch (get_attr_length (insn))
6337     {
6338     case 4:  return \"b%d0\\t%l3\";
6339     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6340     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6341     }
6342   "
6343   [(set (attr "far_jump")
6344         (if_then_else
6345             (eq_attr "length" "8")
6346             (const_string "yes")
6347             (const_string "no")))
6348    (set (attr "length") 
6349         (if_then_else
6350             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6351                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6352             (const_int 4)
6353             (if_then_else
6354                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6355                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6356                 (const_int 6)
6357                 (const_int 8))))]
6360 (define_insn "*tbit_cbranch"
6361   [(set (pc)
6362         (if_then_else
6363          (match_operator 0 "equality_operator"
6364           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6365                             (const_int 1)
6366                             (match_operand:SI 2 "const_int_operand" "i"))
6367            (const_int 0)])
6368          (label_ref (match_operand 3 "" ""))
6369          (pc)))
6370    (clobber (match_scratch:SI 4 "=l"))]
6371   "TARGET_THUMB1"
6372   "*
6373   {
6374   rtx op[3];
6375   op[0] = operands[4];
6376   op[1] = operands[1];
6377   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
6379   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6380   switch (get_attr_length (insn))
6381     {
6382     case 4:  return \"b%d0\\t%l3\";
6383     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6384     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6385     }
6386   }"
6387   [(set (attr "far_jump")
6388         (if_then_else
6389             (eq_attr "length" "8")
6390             (const_string "yes")
6391             (const_string "no")))
6392    (set (attr "length") 
6393         (if_then_else
6394             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6395                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6396             (const_int 4)
6397             (if_then_else
6398                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6399                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6400                 (const_int 6)
6401                 (const_int 8))))]
6403   
6404 (define_insn "*tlobits_cbranch"
6405   [(set (pc)
6406         (if_then_else
6407          (match_operator 0 "equality_operator"
6408           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6409                             (match_operand:SI 2 "const_int_operand" "i")
6410                             (const_int 0))
6411            (const_int 0)])
6412          (label_ref (match_operand 3 "" ""))
6413          (pc)))
6414    (clobber (match_scratch:SI 4 "=l"))]
6415   "TARGET_THUMB1"
6416   "*
6417   {
6418   rtx op[3];
6419   op[0] = operands[4];
6420   op[1] = operands[1];
6421   op[2] = GEN_INT (32 - INTVAL (operands[2]));
6423   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6424   switch (get_attr_length (insn))
6425     {
6426     case 4:  return \"b%d0\\t%l3\";
6427     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6428     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6429     }
6430   }"
6431   [(set (attr "far_jump")
6432         (if_then_else
6433             (eq_attr "length" "8")
6434             (const_string "yes")
6435             (const_string "no")))
6436    (set (attr "length") 
6437         (if_then_else
6438             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6439                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6440             (const_int 4)
6441             (if_then_else
6442                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6443                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6444                 (const_int 6)
6445                 (const_int 8))))]
6447   
6448 (define_insn "*tstsi3_cbranch"
6449   [(set (pc)
6450         (if_then_else
6451          (match_operator 3 "equality_operator"
6452           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
6453                    (match_operand:SI 1 "s_register_operand" "l"))
6454            (const_int 0)])
6455          (label_ref (match_operand 2 "" ""))
6456          (pc)))]
6457   "TARGET_THUMB1"
6458   "*
6459   {
6460   output_asm_insn (\"tst\\t%0, %1\", operands);
6461   switch (get_attr_length (insn))
6462     {
6463     case 4:  return \"b%d3\\t%l2\";
6464     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6465     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
6466     }
6467   }"
6468   [(set (attr "far_jump")
6469         (if_then_else
6470             (eq_attr "length" "8")
6471             (const_string "yes")
6472             (const_string "no")))
6473    (set (attr "length") 
6474         (if_then_else
6475             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6476                  (le (minus (match_dup 2) (pc)) (const_int 256)))
6477             (const_int 4)
6478             (if_then_else
6479                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6480                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
6481                 (const_int 6)
6482                 (const_int 8))))]
6484   
6485 (define_insn "*andsi3_cbranch"
6486   [(set (pc)
6487         (if_then_else
6488          (match_operator 5 "equality_operator"
6489           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6490                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6491            (const_int 0)])
6492          (label_ref (match_operand 4 "" ""))
6493          (pc)))
6494    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6495         (and:SI (match_dup 2) (match_dup 3)))
6496    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6497   "TARGET_THUMB1"
6498   "*
6499   {
6500   if (which_alternative == 0)
6501     output_asm_insn (\"and\\t%0, %3\", operands);
6502   else if (which_alternative == 1)
6503     {
6504       output_asm_insn (\"and\\t%1, %3\", operands);
6505       output_asm_insn (\"mov\\t%0, %1\", operands);
6506     }
6507   else
6508     {
6509       output_asm_insn (\"and\\t%1, %3\", operands);
6510       output_asm_insn (\"str\\t%1, %0\", operands);
6511     }
6513   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6514     {
6515     case 4:  return \"b%d5\\t%l4\";
6516     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6517     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6518     }
6519   }"
6520   [(set (attr "far_jump")
6521         (if_then_else
6522             (ior (and (eq (symbol_ref ("which_alternative"))
6523                           (const_int 0))
6524                       (eq_attr "length" "8"))
6525                  (eq_attr "length" "10"))
6526             (const_string "yes")
6527             (const_string "no")))
6528    (set (attr "length")
6529      (if_then_else
6530        (eq (symbol_ref ("which_alternative"))
6531                        (const_int 0))
6532        (if_then_else
6533          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6534               (le (minus (match_dup 4) (pc)) (const_int 256)))
6535          (const_int 4)
6536          (if_then_else
6537            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6538                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6539            (const_int 6)
6540            (const_int 8)))
6541        (if_then_else
6542          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6543               (le (minus (match_dup 4) (pc)) (const_int 256)))
6544          (const_int 6)
6545          (if_then_else
6546            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6547                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6548            (const_int 8)
6549            (const_int 10)))))]
6552 (define_insn "*orrsi3_cbranch_scratch"
6553   [(set (pc)
6554         (if_then_else
6555          (match_operator 4 "equality_operator"
6556           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6557                    (match_operand:SI 2 "s_register_operand" "l"))
6558            (const_int 0)])
6559          (label_ref (match_operand 3 "" ""))
6560          (pc)))
6561    (clobber (match_scratch:SI 0 "=l"))]
6562   "TARGET_THUMB1"
6563   "*
6564   {
6565   output_asm_insn (\"orr\\t%0, %2\", operands);
6566   switch (get_attr_length (insn))
6567     {
6568     case 4:  return \"b%d4\\t%l3\";
6569     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6570     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6571     }
6572   }"
6573   [(set (attr "far_jump")
6574         (if_then_else
6575             (eq_attr "length" "8")
6576             (const_string "yes")
6577             (const_string "no")))
6578    (set (attr "length") 
6579         (if_then_else
6580             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6581                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6582             (const_int 4)
6583             (if_then_else
6584                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6585                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6586                 (const_int 6)
6587                 (const_int 8))))]
6589   
6590 (define_insn "*orrsi3_cbranch"
6591   [(set (pc)
6592         (if_then_else
6593          (match_operator 5 "equality_operator"
6594           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6595                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6596            (const_int 0)])
6597          (label_ref (match_operand 4 "" ""))
6598          (pc)))
6599    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6600         (ior:SI (match_dup 2) (match_dup 3)))
6601    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6602   "TARGET_THUMB1"
6603   "*
6604   {
6605   if (which_alternative == 0)
6606     output_asm_insn (\"orr\\t%0, %3\", operands);
6607   else if (which_alternative == 1)
6608     {
6609       output_asm_insn (\"orr\\t%1, %3\", operands);
6610       output_asm_insn (\"mov\\t%0, %1\", operands);
6611     }
6612   else
6613     {
6614       output_asm_insn (\"orr\\t%1, %3\", operands);
6615       output_asm_insn (\"str\\t%1, %0\", operands);
6616     }
6618   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6619     {
6620     case 4:  return \"b%d5\\t%l4\";
6621     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6622     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6623     }
6624   }"
6625   [(set (attr "far_jump")
6626         (if_then_else
6627             (ior (and (eq (symbol_ref ("which_alternative"))
6628                           (const_int 0))
6629                       (eq_attr "length" "8"))
6630                  (eq_attr "length" "10"))
6631             (const_string "yes")
6632             (const_string "no")))
6633    (set (attr "length")
6634      (if_then_else
6635        (eq (symbol_ref ("which_alternative"))
6636                        (const_int 0))
6637        (if_then_else
6638          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6639               (le (minus (match_dup 4) (pc)) (const_int 256)))
6640          (const_int 4)
6641          (if_then_else
6642            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6643                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6644            (const_int 6)
6645            (const_int 8)))
6646        (if_then_else
6647          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6648               (le (minus (match_dup 4) (pc)) (const_int 256)))
6649          (const_int 6)
6650          (if_then_else
6651            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6652                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6653            (const_int 8)
6654            (const_int 10)))))]
6657 (define_insn "*xorsi3_cbranch_scratch"
6658   [(set (pc)
6659         (if_then_else
6660          (match_operator 4 "equality_operator"
6661           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6662                    (match_operand:SI 2 "s_register_operand" "l"))
6663            (const_int 0)])
6664          (label_ref (match_operand 3 "" ""))
6665          (pc)))
6666    (clobber (match_scratch:SI 0 "=l"))]
6667   "TARGET_THUMB1"
6668   "*
6669   {
6670   output_asm_insn (\"eor\\t%0, %2\", operands);
6671   switch (get_attr_length (insn))
6672     {
6673     case 4:  return \"b%d4\\t%l3\";
6674     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6675     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6676     }
6677   }"
6678   [(set (attr "far_jump")
6679         (if_then_else
6680             (eq_attr "length" "8")
6681             (const_string "yes")
6682             (const_string "no")))
6683    (set (attr "length") 
6684         (if_then_else
6685             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6686                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6687             (const_int 4)
6688             (if_then_else
6689                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6690                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6691                 (const_int 6)
6692                 (const_int 8))))]
6694   
6695 (define_insn "*xorsi3_cbranch"
6696   [(set (pc)
6697         (if_then_else
6698          (match_operator 5 "equality_operator"
6699           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6700                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6701            (const_int 0)])
6702          (label_ref (match_operand 4 "" ""))
6703          (pc)))
6704    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6705         (xor:SI (match_dup 2) (match_dup 3)))
6706    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6707   "TARGET_THUMB1"
6708   "*
6709   {
6710   if (which_alternative == 0)
6711     output_asm_insn (\"eor\\t%0, %3\", operands);
6712   else if (which_alternative == 1)
6713     {
6714       output_asm_insn (\"eor\\t%1, %3\", operands);
6715       output_asm_insn (\"mov\\t%0, %1\", operands);
6716     }
6717   else
6718     {
6719       output_asm_insn (\"eor\\t%1, %3\", operands);
6720       output_asm_insn (\"str\\t%1, %0\", operands);
6721     }
6723   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6724     {
6725     case 4:  return \"b%d5\\t%l4\";
6726     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6727     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6728     }
6729   }"
6730   [(set (attr "far_jump")
6731         (if_then_else
6732             (ior (and (eq (symbol_ref ("which_alternative"))
6733                           (const_int 0))
6734                       (eq_attr "length" "8"))
6735                  (eq_attr "length" "10"))
6736             (const_string "yes")
6737             (const_string "no")))
6738    (set (attr "length")
6739      (if_then_else
6740        (eq (symbol_ref ("which_alternative"))
6741                        (const_int 0))
6742        (if_then_else
6743          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6744               (le (minus (match_dup 4) (pc)) (const_int 256)))
6745          (const_int 4)
6746          (if_then_else
6747            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6748                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6749            (const_int 6)
6750            (const_int 8)))
6751        (if_then_else
6752          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6753               (le (minus (match_dup 4) (pc)) (const_int 256)))
6754          (const_int 6)
6755          (if_then_else
6756            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6757                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6758            (const_int 8)
6759            (const_int 10)))))]
6762 (define_insn "*bicsi3_cbranch_scratch"
6763   [(set (pc)
6764         (if_then_else
6765          (match_operator 4 "equality_operator"
6766           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6767                    (match_operand:SI 1 "s_register_operand" "0"))
6768            (const_int 0)])
6769          (label_ref (match_operand 3 "" ""))
6770          (pc)))
6771    (clobber (match_scratch:SI 0 "=l"))]
6772   "TARGET_THUMB1"
6773   "*
6774   {
6775   output_asm_insn (\"bic\\t%0, %2\", operands);
6776   switch (get_attr_length (insn))
6777     {
6778     case 4:  return \"b%d4\\t%l3\";
6779     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6780     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6781     }
6782   }"
6783   [(set (attr "far_jump")
6784         (if_then_else
6785             (eq_attr "length" "8")
6786             (const_string "yes")
6787             (const_string "no")))
6788    (set (attr "length") 
6789         (if_then_else
6790             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6791                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6792             (const_int 4)
6793             (if_then_else
6794                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6795                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6796                 (const_int 6)
6797                 (const_int 8))))]
6799   
6800 (define_insn "*bicsi3_cbranch"
6801   [(set (pc)
6802         (if_then_else
6803          (match_operator 5 "equality_operator"
6804           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6805                    (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6806            (const_int 0)])
6807          (label_ref (match_operand 4 "" ""))
6808          (pc)))
6809    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6810         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6811    (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6812   "TARGET_THUMB1"
6813   "*
6814   {
6815   if (which_alternative == 0)
6816     output_asm_insn (\"bic\\t%0, %3\", operands);
6817   else if (which_alternative <= 2)
6818     {
6819       output_asm_insn (\"bic\\t%1, %3\", operands);
6820       /* It's ok if OP0 is a lo-reg, even though the mov will set the
6821          conditions again, since we're only testing for equality.  */
6822       output_asm_insn (\"mov\\t%0, %1\", operands);
6823     }
6824   else
6825     {
6826       output_asm_insn (\"bic\\t%1, %3\", operands);
6827       output_asm_insn (\"str\\t%1, %0\", operands);
6828     }
6830   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6831     {
6832     case 4:  return \"b%d5\\t%l4\";
6833     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6834     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6835     }
6836   }"
6837   [(set (attr "far_jump")
6838         (if_then_else
6839             (ior (and (eq (symbol_ref ("which_alternative"))
6840                           (const_int 0))
6841                       (eq_attr "length" "8"))
6842                  (eq_attr "length" "10"))
6843             (const_string "yes")
6844             (const_string "no")))
6845    (set (attr "length")
6846      (if_then_else
6847        (eq (symbol_ref ("which_alternative"))
6848                        (const_int 0))
6849        (if_then_else
6850          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6851               (le (minus (match_dup 4) (pc)) (const_int 256)))
6852          (const_int 4)
6853          (if_then_else
6854            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6855                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6856            (const_int 6)
6857            (const_int 8)))
6858        (if_then_else
6859          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6860               (le (minus (match_dup 4) (pc)) (const_int 256)))
6861          (const_int 6)
6862          (if_then_else
6863            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6864                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6865            (const_int 8)
6866            (const_int 10)))))]
6869 (define_insn "*cbranchne_decr1"
6870   [(set (pc)
6871         (if_then_else (match_operator 3 "equality_operator"
6872                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6873                         (const_int 0)])
6874                       (label_ref (match_operand 4 "" ""))
6875                       (pc)))
6876    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6877         (plus:SI (match_dup 2) (const_int -1)))
6878    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6879   "TARGET_THUMB1"
6880   "*
6881    {
6882      rtx cond[2];
6883      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6884                                 ? GEU : LTU),
6885                                VOIDmode, operands[2], const1_rtx);
6886      cond[1] = operands[4];
6888      if (which_alternative == 0)
6889        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6890      else if (which_alternative == 1)
6891        {
6892          /* We must provide an alternative for a hi reg because reload 
6893             cannot handle output reloads on a jump instruction, but we
6894             can't subtract into that.  Fortunately a mov from lo to hi
6895             does not clobber the condition codes.  */
6896          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6897          output_asm_insn (\"mov\\t%0, %1\", operands);
6898        }
6899      else
6900        {
6901          /* Similarly, but the target is memory.  */
6902          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6903          output_asm_insn (\"str\\t%1, %0\", operands);
6904        }
6906      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6907        {
6908          case 4:
6909            output_asm_insn (\"b%d0\\t%l1\", cond);
6910            return \"\";
6911          case 6:
6912            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6913            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6914          default:
6915            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6916            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6917        }
6918    }
6919   "
6920   [(set (attr "far_jump")
6921         (if_then_else
6922             (ior (and (eq (symbol_ref ("which_alternative"))
6923                           (const_int 0))
6924                       (eq_attr "length" "8"))
6925                  (eq_attr "length" "10"))
6926             (const_string "yes")
6927             (const_string "no")))
6928    (set_attr_alternative "length"
6929       [
6930        ;; Alternative 0
6931        (if_then_else
6932          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6933               (le (minus (match_dup 4) (pc)) (const_int 256)))
6934          (const_int 4)
6935          (if_then_else
6936            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6937                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6938            (const_int 6)
6939            (const_int 8)))
6940        ;; Alternative 1
6941        (if_then_else
6942          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6943               (le (minus (match_dup 4) (pc)) (const_int 256)))
6944          (const_int 6)
6945          (if_then_else
6946            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6947                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6948            (const_int 8)
6949            (const_int 10)))
6950        ;; Alternative 2
6951        (if_then_else
6952          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6953               (le (minus (match_dup 4) (pc)) (const_int 256)))
6954          (const_int 6)
6955          (if_then_else
6956            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6957                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6958            (const_int 8)
6959            (const_int 10)))
6960        ;; Alternative 3
6961        (if_then_else
6962          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6963               (le (minus (match_dup 4) (pc)) (const_int 256)))
6964          (const_int 6)
6965          (if_then_else
6966            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6967                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6968            (const_int 8)
6969            (const_int 10)))])]
6972 (define_insn "*addsi3_cbranch"
6973   [(set (pc)
6974         (if_then_else
6975          (match_operator 4 "comparison_operator"
6976           [(plus:SI
6977             (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6978             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6979            (const_int 0)])
6980          (label_ref (match_operand 5 "" ""))
6981          (pc)))
6982    (set
6983     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6984     (plus:SI (match_dup 2) (match_dup 3)))
6985    (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6986   "TARGET_THUMB1
6987    && (GET_CODE (operands[4]) == EQ
6988        || GET_CODE (operands[4]) == NE
6989        || GET_CODE (operands[4]) == GE
6990        || GET_CODE (operands[4]) == LT)"
6991   "*
6992    {
6993      rtx cond[3];
6995      
6996      cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6997      cond[1] = operands[2];
6998      cond[2] = operands[3];
7000      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
7001        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
7002      else
7003        output_asm_insn (\"add\\t%0, %1, %2\", cond);
7005      if (which_alternative >= 3
7006          && which_alternative < 4)
7007        output_asm_insn (\"mov\\t%0, %1\", operands);
7008      else if (which_alternative >= 4)
7009        output_asm_insn (\"str\\t%1, %0\", operands);
7011      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
7012        {
7013          case 4:
7014            return \"b%d4\\t%l5\";
7015          case 6:
7016            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7017          default:
7018            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7019        }
7020    }
7021   "
7022   [(set (attr "far_jump")
7023         (if_then_else
7024             (ior (and (lt (symbol_ref ("which_alternative"))
7025                           (const_int 3))
7026                       (eq_attr "length" "8"))
7027                  (eq_attr "length" "10"))
7028             (const_string "yes")
7029             (const_string "no")))
7030    (set (attr "length")
7031      (if_then_else
7032        (lt (symbol_ref ("which_alternative"))
7033                        (const_int 3))
7034        (if_then_else
7035          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7036               (le (minus (match_dup 5) (pc)) (const_int 256)))
7037          (const_int 4)
7038          (if_then_else
7039            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7040                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7041            (const_int 6)
7042            (const_int 8)))
7043        (if_then_else
7044          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7045               (le (minus (match_dup 5) (pc)) (const_int 256)))
7046          (const_int 6)
7047          (if_then_else
7048            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7049                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7050            (const_int 8)
7051            (const_int 10)))))]
7054 (define_insn "*addsi3_cbranch_scratch"
7055   [(set (pc)
7056         (if_then_else
7057          (match_operator 3 "comparison_operator"
7058           [(plus:SI
7059             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
7060             (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
7061            (const_int 0)])
7062          (label_ref (match_operand 4 "" ""))
7063          (pc)))
7064    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
7065   "TARGET_THUMB1
7066    && (GET_CODE (operands[3]) == EQ
7067        || GET_CODE (operands[3]) == NE
7068        || GET_CODE (operands[3]) == GE
7069        || GET_CODE (operands[3]) == LT)"
7070   "*
7071    {
7072      switch (which_alternative)
7073        {
7074        case 0:
7075          output_asm_insn (\"cmp\t%1, #%n2\", operands);
7076          break;
7077        case 1:
7078          output_asm_insn (\"cmn\t%1, %2\", operands);
7079          break;
7080        case 2:
7081          if (INTVAL (operands[2]) < 0)
7082            output_asm_insn (\"sub\t%0, %1, %2\", operands);
7083          else
7084            output_asm_insn (\"add\t%0, %1, %2\", operands);
7085          break;
7086        case 3:
7087          if (INTVAL (operands[2]) < 0)
7088            output_asm_insn (\"sub\t%0, %0, %2\", operands);
7089          else
7090            output_asm_insn (\"add\t%0, %0, %2\", operands);
7091          break;
7092        }
7094      switch (get_attr_length (insn))
7095        {
7096          case 4:
7097            return \"b%d3\\t%l4\";
7098          case 6:
7099            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7100          default:
7101            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7102        }
7103    }
7104   "
7105   [(set (attr "far_jump")
7106         (if_then_else
7107             (eq_attr "length" "8")
7108             (const_string "yes")
7109             (const_string "no")))
7110    (set (attr "length")
7111        (if_then_else
7112          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7113               (le (minus (match_dup 4) (pc)) (const_int 256)))
7114          (const_int 4)
7115          (if_then_else
7116            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7117                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7118            (const_int 6)
7119            (const_int 8))))]
7122 (define_insn "*subsi3_cbranch"
7123   [(set (pc)
7124         (if_then_else
7125          (match_operator 4 "comparison_operator"
7126           [(minus:SI
7127             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
7128             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7129            (const_int 0)])
7130          (label_ref (match_operand 5 "" ""))
7131          (pc)))
7132    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
7133         (minus:SI (match_dup 2) (match_dup 3)))
7134    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
7135   "TARGET_THUMB1
7136    && (GET_CODE (operands[4]) == EQ
7137        || GET_CODE (operands[4]) == NE
7138        || GET_CODE (operands[4]) == GE
7139        || GET_CODE (operands[4]) == LT)"
7140   "*
7141    {
7142      if (which_alternative == 0)
7143        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
7144      else if (which_alternative == 1)
7145        {
7146          /* We must provide an alternative for a hi reg because reload 
7147             cannot handle output reloads on a jump instruction, but we
7148             can't subtract into that.  Fortunately a mov from lo to hi
7149             does not clobber the condition codes.  */
7150          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
7151          output_asm_insn (\"mov\\t%0, %1\", operands);
7152        }
7153      else
7154        {
7155          /* Similarly, but the target is memory.  */
7156          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
7157          output_asm_insn (\"str\\t%1, %0\", operands);
7158        }
7160      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
7161        {
7162          case 4:
7163            return \"b%d4\\t%l5\";
7164          case 6:
7165            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7166          default:
7167            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7168        }
7169    }
7170   "
7171   [(set (attr "far_jump")
7172         (if_then_else
7173             (ior (and (eq (symbol_ref ("which_alternative"))
7174                           (const_int 0))
7175                       (eq_attr "length" "8"))
7176                  (eq_attr "length" "10"))
7177             (const_string "yes")
7178             (const_string "no")))
7179    (set (attr "length")
7180      (if_then_else
7181        (eq (symbol_ref ("which_alternative"))
7182                        (const_int 0))
7183        (if_then_else
7184          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7185               (le (minus (match_dup 5) (pc)) (const_int 256)))
7186          (const_int 4)
7187          (if_then_else
7188            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7189                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7190            (const_int 6)
7191            (const_int 8)))
7192        (if_then_else
7193          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7194               (le (minus (match_dup 5) (pc)) (const_int 256)))
7195          (const_int 6)
7196          (if_then_else
7197            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7198                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7199            (const_int 8)
7200            (const_int 10)))))]
7203 (define_insn "*subsi3_cbranch_scratch"
7204   [(set (pc)
7205         (if_then_else
7206          (match_operator 0 "arm_comparison_operator"
7207           [(minus:SI (match_operand:SI 1 "register_operand" "l")
7208                      (match_operand:SI 2 "nonmemory_operand" "l"))
7209            (const_int 0)])
7210          (label_ref (match_operand 3 "" ""))
7211          (pc)))]
7212   "TARGET_THUMB1
7213    && (GET_CODE (operands[0]) == EQ
7214        || GET_CODE (operands[0]) == NE
7215        || GET_CODE (operands[0]) == GE
7216        || GET_CODE (operands[0]) == LT)"
7217   "*
7218   output_asm_insn (\"cmp\\t%1, %2\", operands);
7219   switch (get_attr_length (insn))
7220     {
7221     case 4:  return \"b%d0\\t%l3\";
7222     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7223     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7224     }
7225   "
7226   [(set (attr "far_jump")
7227         (if_then_else
7228             (eq_attr "length" "8")
7229             (const_string "yes")
7230             (const_string "no")))
7231    (set (attr "length") 
7232         (if_then_else
7233             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7234                  (le (minus (match_dup 3) (pc)) (const_int 256)))
7235             (const_int 4)
7236             (if_then_else
7237                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7238                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
7239                 (const_int 6)
7240                 (const_int 8))))]
7243 ;; Comparison and test insns
7245 (define_expand "cmpsi"
7246   [(match_operand:SI 0 "s_register_operand" "")
7247    (match_operand:SI 1 "arm_add_operand" "")]
7248   "TARGET_32BIT"
7249   "{
7250     arm_compare_op0 = operands[0];
7251     arm_compare_op1 = operands[1];
7252     DONE;
7253   }"
7256 (define_expand "cmpsf"
7257   [(match_operand:SF 0 "s_register_operand" "")
7258    (match_operand:SF 1 "arm_float_compare_operand" "")]
7259   "TARGET_32BIT && TARGET_HARD_FLOAT"
7260   "
7261   arm_compare_op0 = operands[0];
7262   arm_compare_op1 = operands[1];
7263   DONE;
7264   "
7267 (define_expand "cmpdf"
7268   [(match_operand:DF 0 "s_register_operand" "")
7269    (match_operand:DF 1 "arm_float_compare_operand" "")]
7270   "TARGET_32BIT && TARGET_HARD_FLOAT"
7271   "
7272   arm_compare_op0 = operands[0];
7273   arm_compare_op1 = operands[1];
7274   DONE;
7275   "
7278 (define_insn "*arm_cmpsi_insn"
7279   [(set (reg:CC CC_REGNUM)
7280         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
7281                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
7282   "TARGET_32BIT"
7283   "@
7284    cmp%?\\t%0, %1
7285    cmn%?\\t%0, #%n1"
7286   [(set_attr "conds" "set")]
7289 (define_insn "*arm_cmpsi_shiftsi"
7290   [(set (reg:CC CC_REGNUM)
7291         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
7292                     (match_operator:SI  3 "shift_operator"
7293                      [(match_operand:SI 1 "s_register_operand" "r")
7294                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
7295   "TARGET_ARM"
7296   "cmp%?\\t%0, %1%S3"
7297   [(set_attr "conds" "set")
7298    (set_attr "shift" "1")
7299    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
7300                       (const_string "alu_shift")
7301                       (const_string "alu_shift_reg")))]
7304 (define_insn "*arm_cmpsi_shiftsi_swp"
7305   [(set (reg:CC_SWP CC_REGNUM)
7306         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
7307                          [(match_operand:SI 1 "s_register_operand" "r")
7308                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
7309                         (match_operand:SI 0 "s_register_operand" "r")))]
7310   "TARGET_ARM"
7311   "cmp%?\\t%0, %1%S3"
7312   [(set_attr "conds" "set")
7313    (set_attr "shift" "1")
7314    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
7315                       (const_string "alu_shift")
7316                       (const_string "alu_shift_reg")))]
7319 (define_insn "*arm_cmpsi_negshiftsi_si"
7320   [(set (reg:CC_Z CC_REGNUM)
7321         (compare:CC_Z
7322          (neg:SI (match_operator:SI 1 "shift_operator"
7323                     [(match_operand:SI 2 "s_register_operand" "r")
7324                      (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7325          (match_operand:SI 0 "s_register_operand" "r")))]
7326   "TARGET_ARM"
7327   "cmn%?\\t%0, %2%S1"
7328   [(set_attr "conds" "set")
7329    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7330                                     (const_string "alu_shift")
7331                                     (const_string "alu_shift_reg")))]
7334 ;; Cirrus SF compare instruction
7335 (define_insn "*cirrus_cmpsf"
7336   [(set (reg:CCFP CC_REGNUM)
7337         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
7338                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
7339   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7340   "cfcmps%?\\tr15, %V0, %V1"
7341   [(set_attr "type"   "mav_farith")
7342    (set_attr "cirrus" "compare")]
7345 ;; Cirrus DF compare instruction
7346 (define_insn "*cirrus_cmpdf"
7347   [(set (reg:CCFP CC_REGNUM)
7348         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
7349                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
7350   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7351   "cfcmpd%?\\tr15, %V0, %V1"
7352   [(set_attr "type"   "mav_farith")
7353    (set_attr "cirrus" "compare")]
7356 ;; Cirrus DI compare instruction
7357 (define_expand "cmpdi"
7358   [(match_operand:DI 0 "cirrus_fp_register" "")
7359    (match_operand:DI 1 "cirrus_fp_register" "")]
7360   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7361   "{
7362      arm_compare_op0 = operands[0];
7363      arm_compare_op1 = operands[1];
7364      DONE;
7365    }")
7367 (define_insn "*cirrus_cmpdi"
7368   [(set (reg:CC CC_REGNUM)
7369         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
7370                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
7371   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7372   "cfcmp64%?\\tr15, %V0, %V1"
7373   [(set_attr "type"   "mav_farith")
7374    (set_attr "cirrus" "compare")]
7377 ; This insn allows redundant compares to be removed by cse, nothing should
7378 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7379 ; is deleted later on. The match_dup will match the mode here, so that
7380 ; mode changes of the condition codes aren't lost by this even though we don't
7381 ; specify what they are.
7383 (define_insn "*deleted_compare"
7384   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
7385   "TARGET_32BIT"
7386   "\\t%@ deleted compare"
7387   [(set_attr "conds" "set")
7388    (set_attr "length" "0")]
7392 ;; Conditional branch insns
7394 (define_expand "beq"
7395   [(set (pc)
7396         (if_then_else (eq (match_dup 1) (const_int 0))
7397                       (label_ref (match_operand 0 "" ""))
7398                       (pc)))]
7399   "TARGET_32BIT"
7400   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7403 (define_expand "bne"
7404   [(set (pc)
7405         (if_then_else (ne (match_dup 1) (const_int 0))
7406                       (label_ref (match_operand 0 "" ""))
7407                       (pc)))]
7408   "TARGET_32BIT"
7409   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7412 (define_expand "bgt"
7413   [(set (pc)
7414         (if_then_else (gt (match_dup 1) (const_int 0))
7415                       (label_ref (match_operand 0 "" ""))
7416                       (pc)))]
7417   "TARGET_32BIT"
7418   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7421 (define_expand "ble"
7422   [(set (pc)
7423         (if_then_else (le (match_dup 1) (const_int 0))
7424                       (label_ref (match_operand 0 "" ""))
7425                       (pc)))]
7426   "TARGET_32BIT"
7427   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7430 (define_expand "bge"
7431   [(set (pc)
7432         (if_then_else (ge (match_dup 1) (const_int 0))
7433                       (label_ref (match_operand 0 "" ""))
7434                       (pc)))]
7435   "TARGET_32BIT"
7436   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7439 (define_expand "blt"
7440   [(set (pc)
7441         (if_then_else (lt (match_dup 1) (const_int 0))
7442                       (label_ref (match_operand 0 "" ""))
7443                       (pc)))]
7444   "TARGET_32BIT"
7445   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7448 (define_expand "bgtu"
7449   [(set (pc)
7450         (if_then_else (gtu (match_dup 1) (const_int 0))
7451                       (label_ref (match_operand 0 "" ""))
7452                       (pc)))]
7453   "TARGET_32BIT"
7454   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7457 (define_expand "bleu"
7458   [(set (pc)
7459         (if_then_else (leu (match_dup 1) (const_int 0))
7460                       (label_ref (match_operand 0 "" ""))
7461                       (pc)))]
7462   "TARGET_32BIT"
7463   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7466 (define_expand "bgeu"
7467   [(set (pc)
7468         (if_then_else (geu (match_dup 1) (const_int 0))
7469                       (label_ref (match_operand 0 "" ""))
7470                       (pc)))]
7471   "TARGET_32BIT"
7472   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7475 (define_expand "bltu"
7476   [(set (pc)
7477         (if_then_else (ltu (match_dup 1) (const_int 0))
7478                       (label_ref (match_operand 0 "" ""))
7479                       (pc)))]
7480   "TARGET_32BIT"
7481   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7484 (define_expand "bunordered"
7485   [(set (pc)
7486         (if_then_else (unordered (match_dup 1) (const_int 0))
7487                       (label_ref (match_operand 0 "" ""))
7488                       (pc)))]
7489   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7490   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7491                                       arm_compare_op1);"
7494 (define_expand "bordered"
7495   [(set (pc)
7496         (if_then_else (ordered (match_dup 1) (const_int 0))
7497                       (label_ref (match_operand 0 "" ""))
7498                       (pc)))]
7499   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7500   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7501                                       arm_compare_op1);"
7504 (define_expand "bungt"
7505   [(set (pc)
7506         (if_then_else (ungt (match_dup 1) (const_int 0))
7507                       (label_ref (match_operand 0 "" ""))
7508                       (pc)))]
7509   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7510   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
7513 (define_expand "bunlt"
7514   [(set (pc)
7515         (if_then_else (unlt (match_dup 1) (const_int 0))
7516                       (label_ref (match_operand 0 "" ""))
7517                       (pc)))]
7518   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7519   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
7522 (define_expand "bunge"
7523   [(set (pc)
7524         (if_then_else (unge (match_dup 1) (const_int 0))
7525                       (label_ref (match_operand 0 "" ""))
7526                       (pc)))]
7527   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7528   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
7531 (define_expand "bunle"
7532   [(set (pc)
7533         (if_then_else (unle (match_dup 1) (const_int 0))
7534                       (label_ref (match_operand 0 "" ""))
7535                       (pc)))]
7536   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7537   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
7540 ;; The following two patterns need two branch instructions, since there is
7541 ;; no single instruction that will handle all cases.
7542 (define_expand "buneq"
7543   [(set (pc)
7544         (if_then_else (uneq (match_dup 1) (const_int 0))
7545                       (label_ref (match_operand 0 "" ""))
7546                       (pc)))]
7547   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7548   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
7551 (define_expand "bltgt"
7552   [(set (pc)
7553         (if_then_else (ltgt (match_dup 1) (const_int 0))
7554                       (label_ref (match_operand 0 "" ""))
7555                       (pc)))]
7556   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7557   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
7561 ;; Patterns to match conditional branch insns.
7564 ; Special pattern to match UNEQ.
7565 (define_insn "*arm_buneq"
7566   [(set (pc)
7567         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7568                       (label_ref (match_operand 0 "" ""))
7569                       (pc)))]
7570   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7571   "*
7572   gcc_assert (!arm_ccfsm_state);
7574   return \"bvs\\t%l0\;beq\\t%l0\";
7575   "
7576   [(set_attr "conds" "jump_clob")
7577    (set_attr "length" "8")]
7580 ; Special pattern to match LTGT.
7581 (define_insn "*arm_bltgt"
7582   [(set (pc)
7583         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7584                       (label_ref (match_operand 0 "" ""))
7585                       (pc)))]
7586   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7587   "*
7588   gcc_assert (!arm_ccfsm_state);
7590   return \"bmi\\t%l0\;bgt\\t%l0\";
7591   "
7592   [(set_attr "conds" "jump_clob")
7593    (set_attr "length" "8")]
7596 (define_insn "*arm_cond_branch"
7597   [(set (pc)
7598         (if_then_else (match_operator 1 "arm_comparison_operator"
7599                        [(match_operand 2 "cc_register" "") (const_int 0)])
7600                       (label_ref (match_operand 0 "" ""))
7601                       (pc)))]
7602   "TARGET_32BIT"
7603   "*
7604   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7605     {
7606       arm_ccfsm_state += 2;
7607       return \"\";
7608     }
7609   return \"b%d1\\t%l0\";
7610   "
7611   [(set_attr "conds" "use")
7612    (set_attr "type" "branch")]
7615 ; Special pattern to match reversed UNEQ.
7616 (define_insn "*arm_buneq_reversed"
7617   [(set (pc)
7618         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7619                       (pc)
7620                       (label_ref (match_operand 0 "" ""))))]
7621   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7622   "*
7623   gcc_assert (!arm_ccfsm_state);
7625   return \"bmi\\t%l0\;bgt\\t%l0\";
7626   "
7627   [(set_attr "conds" "jump_clob")
7628    (set_attr "length" "8")]
7631 ; Special pattern to match reversed LTGT.
7632 (define_insn "*arm_bltgt_reversed"
7633   [(set (pc)
7634         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7635                       (pc)
7636                       (label_ref (match_operand 0 "" ""))))]
7637   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7638   "*
7639   gcc_assert (!arm_ccfsm_state);
7641   return \"bvs\\t%l0\;beq\\t%l0\";
7642   "
7643   [(set_attr "conds" "jump_clob")
7644    (set_attr "length" "8")]
7647 (define_insn "*arm_cond_branch_reversed"
7648   [(set (pc)
7649         (if_then_else (match_operator 1 "arm_comparison_operator"
7650                        [(match_operand 2 "cc_register" "") (const_int 0)])
7651                       (pc)
7652                       (label_ref (match_operand 0 "" ""))))]
7653   "TARGET_32BIT"
7654   "*
7655   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7656     {
7657       arm_ccfsm_state += 2;
7658       return \"\";
7659     }
7660   return \"b%D1\\t%l0\";
7661   "
7662   [(set_attr "conds" "use")
7663    (set_attr "type" "branch")]
7668 ; scc insns
7670 (define_expand "seq"
7671   [(set (match_operand:SI 0 "s_register_operand" "")
7672         (eq:SI (match_dup 1) (const_int 0)))]
7673   "TARGET_32BIT"
7674   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7677 (define_expand "sne"
7678   [(set (match_operand:SI 0 "s_register_operand" "")
7679         (ne:SI (match_dup 1) (const_int 0)))]
7680   "TARGET_32BIT"
7681   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7684 (define_expand "sgt"
7685   [(set (match_operand:SI 0 "s_register_operand" "")
7686         (gt:SI (match_dup 1) (const_int 0)))]
7687   "TARGET_32BIT"
7688   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7691 (define_expand "sle"
7692   [(set (match_operand:SI 0 "s_register_operand" "")
7693         (le:SI (match_dup 1) (const_int 0)))]
7694   "TARGET_32BIT"
7695   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7698 (define_expand "sge"
7699   [(set (match_operand:SI 0 "s_register_operand" "")
7700         (ge:SI (match_dup 1) (const_int 0)))]
7701   "TARGET_32BIT"
7702   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7705 (define_expand "slt"
7706   [(set (match_operand:SI 0 "s_register_operand" "")
7707         (lt:SI (match_dup 1) (const_int 0)))]
7708   "TARGET_32BIT"
7709   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7712 (define_expand "sgtu"
7713   [(set (match_operand:SI 0 "s_register_operand" "")
7714         (gtu:SI (match_dup 1) (const_int 0)))]
7715   "TARGET_32BIT"
7716   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7719 (define_expand "sleu"
7720   [(set (match_operand:SI 0 "s_register_operand" "")
7721         (leu:SI (match_dup 1) (const_int 0)))]
7722   "TARGET_32BIT"
7723   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7726 (define_expand "sgeu"
7727   [(set (match_operand:SI 0 "s_register_operand" "")
7728         (geu:SI (match_dup 1) (const_int 0)))]
7729   "TARGET_32BIT"
7730   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7733 (define_expand "sltu"
7734   [(set (match_operand:SI 0 "s_register_operand" "")
7735         (ltu:SI (match_dup 1) (const_int 0)))]
7736   "TARGET_32BIT"
7737   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7740 (define_expand "sunordered"
7741   [(set (match_operand:SI 0 "s_register_operand" "")
7742         (unordered:SI (match_dup 1) (const_int 0)))]
7743   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7744   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7745                                       arm_compare_op1);"
7748 (define_expand "sordered"
7749   [(set (match_operand:SI 0 "s_register_operand" "")
7750         (ordered:SI (match_dup 1) (const_int 0)))]
7751   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7752   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7753                                       arm_compare_op1);"
7756 (define_expand "sungt"
7757   [(set (match_operand:SI 0 "s_register_operand" "")
7758         (ungt:SI (match_dup 1) (const_int 0)))]
7759   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7760   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7761                                       arm_compare_op1);"
7764 (define_expand "sunge"
7765   [(set (match_operand:SI 0 "s_register_operand" "")
7766         (unge:SI (match_dup 1) (const_int 0)))]
7767   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7768   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7769                                       arm_compare_op1);"
7772 (define_expand "sunlt"
7773   [(set (match_operand:SI 0 "s_register_operand" "")
7774         (unlt:SI (match_dup 1) (const_int 0)))]
7775   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7776   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7777                                       arm_compare_op1);"
7780 (define_expand "sunle"
7781   [(set (match_operand:SI 0 "s_register_operand" "")
7782         (unle:SI (match_dup 1) (const_int 0)))]
7783   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7784   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7785                                       arm_compare_op1);"
7788 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7789 ;;; simple ARM instructions. 
7791 ; (define_expand "suneq"
7792 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7793 ;       (uneq:SI (match_dup 1) (const_int 0)))]
7794 ;   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7795 ;   "gcc_unreachable ();"
7796 ; )
7798 ; (define_expand "sltgt"
7799 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7800 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
7801 ;   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7802 ;   "gcc_unreachable ();"
7803 ; )
7805 (define_insn "*mov_scc"
7806   [(set (match_operand:SI 0 "s_register_operand" "=r")
7807         (match_operator:SI 1 "arm_comparison_operator"
7808          [(match_operand 2 "cc_register" "") (const_int 0)]))]
7809   "TARGET_ARM"
7810   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7811   [(set_attr "conds" "use")
7812    (set_attr "length" "8")]
7815 (define_insn "*mov_negscc"
7816   [(set (match_operand:SI 0 "s_register_operand" "=r")
7817         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7818                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7819   "TARGET_ARM"
7820   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7821   [(set_attr "conds" "use")
7822    (set_attr "length" "8")]
7825 (define_insn "*mov_notscc"
7826   [(set (match_operand:SI 0 "s_register_operand" "=r")
7827         (not:SI (match_operator:SI 1 "arm_comparison_operator"
7828                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7829   "TARGET_ARM"
7830   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7831   [(set_attr "conds" "use")
7832    (set_attr "length" "8")]
7835 (define_expand "cstoresi4"
7836   [(set (match_operand:SI 0 "s_register_operand" "")
7837         (match_operator:SI 1 "arm_comparison_operator"
7838          [(match_operand:SI 2 "s_register_operand" "")
7839           (match_operand:SI 3 "reg_or_int_operand" "")]))]
7840   "TARGET_THUMB1"
7841   "{
7842   rtx op3, scratch, scratch2;
7844   if (operands[3] == const0_rtx)
7845     {
7846       switch (GET_CODE (operands[1]))
7847         {
7848         case EQ:
7849           emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
7850           break;
7852         case NE:
7853           emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
7854           break;
7856         case LE:
7857           scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7858                                   NULL_RTX, 0, OPTAB_WIDEN);
7859           scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7860                                   NULL_RTX, 0, OPTAB_WIDEN);
7861           expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7862                         operands[0], 1, OPTAB_WIDEN);
7863           break;
7865         case GE:
7866           scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7867                                  NULL_RTX, 1);
7868           expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7869                         NULL_RTX, 1, OPTAB_WIDEN);
7870           break;
7872         case GT:
7873           scratch = expand_binop (SImode, ashr_optab, operands[2],
7874                                   GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7875           scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7876                                   NULL_RTX, 0, OPTAB_WIDEN);
7877           expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7878                         0, OPTAB_WIDEN);
7879           break;
7881         /* LT is handled by generic code.  No need for unsigned with 0.  */
7882         default:
7883           FAIL;
7884         }
7885       DONE;
7886     }
7888   switch (GET_CODE (operands[1]))
7889     {
7890     case EQ:
7891       scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7892                               NULL_RTX, 0, OPTAB_WIDEN);
7893       emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
7894       break;
7896     case NE:
7897       scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7898                               NULL_RTX, 0, OPTAB_WIDEN);
7899       emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
7900       break;
7902     case LE:
7903       op3 = force_reg (SImode, operands[3]);
7905       scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7906                               NULL_RTX, 1, OPTAB_WIDEN);
7907       scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7908                               NULL_RTX, 0, OPTAB_WIDEN);
7909       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
7910                                           op3, operands[2]));
7911       break;
7913     case GE:
7914       op3 = operands[3];
7915       if (!thumb1_cmp_operand (op3, SImode))
7916         op3 = force_reg (SImode, op3);
7917       scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7918                               NULL_RTX, 0, OPTAB_WIDEN);
7919       scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7920                                NULL_RTX, 1, OPTAB_WIDEN);
7921       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
7922                                           operands[2], op3));
7923       break;
7925     case LEU:
7926       op3 = force_reg (SImode, operands[3]);
7927       scratch = force_reg (SImode, const0_rtx);
7928       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
7929                                           op3, operands[2]));
7930       break;
7932     case GEU:
7933       op3 = operands[3];
7934       if (!thumb1_cmp_operand (op3, SImode))
7935         op3 = force_reg (SImode, op3);
7936       scratch = force_reg (SImode, const0_rtx);
7937       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
7938                                           operands[2], op3));
7939       break;
7941     case LTU:
7942       op3 = operands[3];
7943       if (!thumb1_cmp_operand (op3, SImode))
7944         op3 = force_reg (SImode, op3);
7945       scratch = gen_reg_rtx (SImode);
7946       emit_insn (gen_cstoresi_nltu_thumb1 (scratch, operands[2], op3));
7947       emit_insn (gen_negsi2 (operands[0], scratch));
7948       break;
7950     case GTU:
7951       op3 = force_reg (SImode, operands[3]);
7952       scratch = gen_reg_rtx (SImode);
7953       emit_insn (gen_cstoresi_nltu_thumb1 (scratch, op3, operands[2]));
7954       emit_insn (gen_negsi2 (operands[0], scratch));
7955       break;
7957     /* No good sequences for GT, LT.  */
7958     default:
7959       FAIL;
7960     }
7961   DONE;
7964 (define_expand "cstoresi_eq0_thumb1"
7965   [(parallel
7966     [(set (match_operand:SI 0 "s_register_operand" "")
7967           (eq:SI (match_operand:SI 1 "s_register_operand" "")
7968                  (const_int 0)))
7969      (clobber (match_dup:SI 2))])]
7970   "TARGET_THUMB1"
7971   "operands[2] = gen_reg_rtx (SImode);"
7974 (define_expand "cstoresi_ne0_thumb1"
7975   [(parallel
7976     [(set (match_operand:SI 0 "s_register_operand" "")
7977           (ne:SI (match_operand:SI 1 "s_register_operand" "")
7978                  (const_int 0)))
7979      (clobber (match_dup:SI 2))])]
7980   "TARGET_THUMB1"
7981   "operands[2] = gen_reg_rtx (SImode);"
7984 (define_insn "*cstoresi_eq0_thumb1_insn"
7985   [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
7986         (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
7987                (const_int 0)))
7988    (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
7989   "TARGET_THUMB1"
7990   "@
7991    neg\\t%0, %1\;adc\\t%0, %0, %1
7992    neg\\t%2, %1\;adc\\t%0, %1, %2"
7993   [(set_attr "length" "4")]
7996 (define_insn "*cstoresi_ne0_thumb1_insn"
7997   [(set (match_operand:SI 0 "s_register_operand" "=l")
7998         (ne:SI (match_operand:SI 1 "s_register_operand" "0")
7999                (const_int 0)))
8000    (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
8001   "TARGET_THUMB1"
8002   "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
8003   [(set_attr "length" "4")]
8006 (define_insn "cstoresi_nltu_thumb1"
8007   [(set (match_operand:SI 0 "s_register_operand" "=l,l")
8008         (neg:SI (gtu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
8009                         (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
8010   "TARGET_THUMB1"
8011   "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
8012   [(set_attr "length" "4")]
8015 ;; Used as part of the expansion of thumb les sequence.
8016 (define_insn "thumb1_addsi3_addgeu"
8017   [(set (match_operand:SI 0 "s_register_operand" "=l")
8018         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8019                           (match_operand:SI 2 "s_register_operand" "l"))
8020                  (geu:SI (match_operand:SI 3 "s_register_operand" "l")
8021                          (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
8022   "TARGET_THUMB1"
8023   "cmp\\t%3, %4\;adc\\t%0, %1, %2"
8024   [(set_attr "length" "4")]
8028 ;; Conditional move insns
8030 (define_expand "movsicc"
8031   [(set (match_operand:SI 0 "s_register_operand" "")
8032         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
8033                          (match_operand:SI 2 "arm_not_operand" "")
8034                          (match_operand:SI 3 "arm_not_operand" "")))]
8035   "TARGET_32BIT"
8036   "
8037   {
8038     enum rtx_code code = GET_CODE (operands[1]);
8039     rtx ccreg;
8041     if (code == UNEQ || code == LTGT)
8042       FAIL;
8044     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
8045     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
8046   }"
8049 (define_expand "movsfcc"
8050   [(set (match_operand:SF 0 "s_register_operand" "")
8051         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
8052                          (match_operand:SF 2 "s_register_operand" "")
8053                          (match_operand:SF 3 "nonmemory_operand" "")))]
8054   "TARGET_32BIT"
8055   "
8056   {
8057     enum rtx_code code = GET_CODE (operands[1]);
8058     rtx ccreg;
8060     if (code == UNEQ || code == LTGT)
8061       FAIL;
8063     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
8064        Otherwise, ensure it is a valid FP add operand */
8065     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
8066         || (!arm_float_add_operand (operands[3], SFmode)))
8067       operands[3] = force_reg (SFmode, operands[3]);
8069     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
8070     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
8071   }"
8074 (define_expand "movdfcc"
8075   [(set (match_operand:DF 0 "s_register_operand" "")
8076         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
8077                          (match_operand:DF 2 "s_register_operand" "")
8078                          (match_operand:DF 3 "arm_float_add_operand" "")))]
8079   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8080   "
8081   {
8082     enum rtx_code code = GET_CODE (operands[1]);
8083     rtx ccreg;
8085     if (code == UNEQ || code == LTGT)
8086       FAIL;
8088     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
8089     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
8090   }"
8093 (define_insn "*movsicc_insn"
8094   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8095         (if_then_else:SI
8096          (match_operator 3 "arm_comparison_operator"
8097           [(match_operand 4 "cc_register" "") (const_int 0)])
8098          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
8099          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
8100   "TARGET_ARM"
8101   "@
8102    mov%D3\\t%0, %2
8103    mvn%D3\\t%0, #%B2
8104    mov%d3\\t%0, %1
8105    mvn%d3\\t%0, #%B1
8106    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
8107    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
8108    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
8109    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
8110   [(set_attr "length" "4,4,4,4,8,8,8,8")
8111    (set_attr "conds" "use")]
8114 (define_insn "*movsfcc_soft_insn"
8115   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8116         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8117                           [(match_operand 4 "cc_register" "") (const_int 0)])
8118                          (match_operand:SF 1 "s_register_operand" "0,r")
8119                          (match_operand:SF 2 "s_register_operand" "r,0")))]
8120   "TARGET_ARM && TARGET_SOFT_FLOAT"
8121   "@
8122    mov%D3\\t%0, %2
8123    mov%d3\\t%0, %1"
8124   [(set_attr "conds" "use")]
8128 ;; Jump and linkage insns
8130 (define_expand "jump"
8131   [(set (pc)
8132         (label_ref (match_operand 0 "" "")))]
8133   "TARGET_EITHER"
8134   ""
8137 (define_insn "*arm_jump"
8138   [(set (pc)
8139         (label_ref (match_operand 0 "" "")))]
8140   "TARGET_32BIT"
8141   "*
8142   {
8143     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
8144       {
8145         arm_ccfsm_state += 2;
8146         return \"\";
8147       }
8148     return \"b%?\\t%l0\";
8149   }
8150   "
8151   [(set_attr "predicable" "yes")]
8154 (define_insn "*thumb_jump"
8155   [(set (pc)
8156         (label_ref (match_operand 0 "" "")))]
8157   "TARGET_THUMB1"
8158   "*
8159   if (get_attr_length (insn) == 2)
8160     return \"b\\t%l0\";
8161   return \"bl\\t%l0\\t%@ far jump\";
8162   "
8163   [(set (attr "far_jump")
8164         (if_then_else
8165             (eq_attr "length" "4")
8166             (const_string "yes")
8167             (const_string "no")))
8168    (set (attr "length") 
8169         (if_then_else
8170             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8171                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
8172             (const_int 2)
8173             (const_int 4)))]
8176 (define_expand "call"
8177   [(parallel [(call (match_operand 0 "memory_operand" "")
8178                     (match_operand 1 "general_operand" ""))
8179               (use (match_operand 2 "" ""))
8180               (clobber (reg:SI LR_REGNUM))])]
8181   "TARGET_EITHER"
8182   "
8183   {
8184     rtx callee, pat;
8185     
8186     /* In an untyped call, we can get NULL for operand 2.  */
8187     if (operands[2] == NULL_RTX)
8188       operands[2] = const0_rtx;
8189       
8190     /* Decide if we should generate indirect calls by loading the
8191        32-bit address of the callee into a register before performing the
8192        branch and link.  */
8193     callee = XEXP (operands[0], 0);
8194     if (GET_CODE (callee) == SYMBOL_REF
8195         ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8196         : !REG_P (callee))
8197       XEXP (operands[0], 0) = force_reg (Pmode, callee);
8199     pat = gen_call_internal (operands[0], operands[1], operands[2]);
8200     arm_emit_call_insn (pat, XEXP (operands[0], 0));
8201     DONE;
8202   }"
8205 (define_expand "call_internal"
8206   [(parallel [(call (match_operand 0 "memory_operand" "")
8207                     (match_operand 1 "general_operand" ""))
8208               (use (match_operand 2 "" ""))
8209               (clobber (reg:SI LR_REGNUM))])])
8211 (define_insn "*call_reg_armv5"
8212   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8213          (match_operand 1 "" ""))
8214    (use (match_operand 2 "" ""))
8215    (clobber (reg:SI LR_REGNUM))]
8216   "TARGET_ARM && arm_arch5"
8217   "blx%?\\t%0"
8218   [(set_attr "type" "call")]
8221 (define_insn "*call_reg_arm"
8222   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8223          (match_operand 1 "" ""))
8224    (use (match_operand 2 "" ""))
8225    (clobber (reg:SI LR_REGNUM))]
8226   "TARGET_ARM && !arm_arch5"
8227   "*
8228   return output_call (operands);
8229   "
8230   ;; length is worst case, normally it is only two
8231   [(set_attr "length" "12")
8232    (set_attr "type" "call")]
8235 (define_insn "*call_mem"
8236   [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
8237          (match_operand 1 "" ""))
8238    (use (match_operand 2 "" ""))
8239    (clobber (reg:SI LR_REGNUM))]
8240   "TARGET_ARM"
8241   "*
8242   return output_call_mem (operands);
8243   "
8244   [(set_attr "length" "12")
8245    (set_attr "type" "call")]
8248 (define_insn "*call_reg_thumb1_v5"
8249   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8250          (match_operand 1 "" ""))
8251    (use (match_operand 2 "" ""))
8252    (clobber (reg:SI LR_REGNUM))]
8253   "TARGET_THUMB1 && arm_arch5"
8254   "blx\\t%0"
8255   [(set_attr "length" "2")
8256    (set_attr "type" "call")]
8259 (define_insn "*call_reg_thumb1"
8260   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8261          (match_operand 1 "" ""))
8262    (use (match_operand 2 "" ""))
8263    (clobber (reg:SI LR_REGNUM))]
8264   "TARGET_THUMB1 && !arm_arch5"
8265   "*
8266   {
8267     if (!TARGET_CALLER_INTERWORKING)
8268       return thumb_call_via_reg (operands[0]);
8269     else if (operands[1] == const0_rtx)
8270       return \"bl\\t%__interwork_call_via_%0\";
8271     else if (frame_pointer_needed)
8272       return \"bl\\t%__interwork_r7_call_via_%0\";
8273     else
8274       return \"bl\\t%__interwork_r11_call_via_%0\";
8275   }"
8276   [(set_attr "type" "call")]
8279 (define_expand "call_value"
8280   [(parallel [(set (match_operand       0 "" "")
8281                    (call (match_operand 1 "memory_operand" "")
8282                          (match_operand 2 "general_operand" "")))
8283               (use (match_operand 3 "" ""))
8284               (clobber (reg:SI LR_REGNUM))])]
8285   "TARGET_EITHER"
8286   "
8287   {
8288     rtx pat, callee;
8289     
8290     /* In an untyped call, we can get NULL for operand 2.  */
8291     if (operands[3] == 0)
8292       operands[3] = const0_rtx;
8293       
8294     /* Decide if we should generate indirect calls by loading the
8295        32-bit address of the callee into a register before performing the
8296        branch and link.  */
8297     callee = XEXP (operands[1], 0);
8298     if (GET_CODE (callee) == SYMBOL_REF
8299         ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8300         : !REG_P (callee))
8301       XEXP (operands[1], 0) = force_reg (Pmode, callee);
8303     pat = gen_call_value_internal (operands[0], operands[1],
8304                                    operands[2], operands[3]);
8305     arm_emit_call_insn (pat, XEXP (operands[1], 0));
8306     DONE;
8307   }"
8310 (define_expand "call_value_internal"
8311   [(parallel [(set (match_operand       0 "" "")
8312                    (call (match_operand 1 "memory_operand" "")
8313                          (match_operand 2 "general_operand" "")))
8314               (use (match_operand 3 "" ""))
8315               (clobber (reg:SI LR_REGNUM))])])
8317 (define_insn "*call_value_reg_armv5"
8318   [(set (match_operand 0 "" "")
8319         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8320               (match_operand 2 "" "")))
8321    (use (match_operand 3 "" ""))
8322    (clobber (reg:SI LR_REGNUM))]
8323   "TARGET_ARM && arm_arch5"
8324   "blx%?\\t%1"
8325   [(set_attr "type" "call")]
8328 (define_insn "*call_value_reg_arm"
8329   [(set (match_operand 0 "" "")
8330         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8331               (match_operand 2 "" "")))
8332    (use (match_operand 3 "" ""))
8333    (clobber (reg:SI LR_REGNUM))]
8334   "TARGET_ARM && !arm_arch5"
8335   "*
8336   return output_call (&operands[1]);
8337   "
8338   [(set_attr "length" "12")
8339    (set_attr "type" "call")]
8342 (define_insn "*call_value_mem"
8343   [(set (match_operand 0 "" "")
8344         (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
8345               (match_operand 2 "" "")))
8346    (use (match_operand 3 "" ""))
8347    (clobber (reg:SI LR_REGNUM))]
8348   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
8349   "*
8350   return output_call_mem (&operands[1]);
8351   "
8352   [(set_attr "length" "12")
8353    (set_attr "type" "call")]
8356 (define_insn "*call_value_reg_thumb1_v5"
8357   [(set (match_operand 0 "" "")
8358         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8359               (match_operand 2 "" "")))
8360    (use (match_operand 3 "" ""))
8361    (clobber (reg:SI LR_REGNUM))]
8362   "TARGET_THUMB1 && arm_arch5"
8363   "blx\\t%1"
8364   [(set_attr "length" "2")
8365    (set_attr "type" "call")]
8368 (define_insn "*call_value_reg_thumb1"
8369   [(set (match_operand 0 "" "")
8370         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8371               (match_operand 2 "" "")))
8372    (use (match_operand 3 "" ""))
8373    (clobber (reg:SI LR_REGNUM))]
8374   "TARGET_THUMB1 && !arm_arch5"
8375   "*
8376   {
8377     if (!TARGET_CALLER_INTERWORKING)
8378       return thumb_call_via_reg (operands[1]);
8379     else if (operands[2] == const0_rtx)
8380       return \"bl\\t%__interwork_call_via_%1\";
8381     else if (frame_pointer_needed)
8382       return \"bl\\t%__interwork_r7_call_via_%1\";
8383     else
8384       return \"bl\\t%__interwork_r11_call_via_%1\";
8385   }"
8386   [(set_attr "type" "call")]
8389 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8390 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8392 (define_insn "*call_symbol"
8393   [(call (mem:SI (match_operand:SI 0 "" ""))
8394          (match_operand 1 "" ""))
8395    (use (match_operand 2 "" ""))
8396    (clobber (reg:SI LR_REGNUM))]
8397   "TARGET_ARM
8398    && (GET_CODE (operands[0]) == SYMBOL_REF)
8399    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
8400   "*
8401   {
8402     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
8403   }"
8404   [(set_attr "type" "call")]
8407 (define_insn "*call_value_symbol"
8408   [(set (match_operand 0 "" "")
8409         (call (mem:SI (match_operand:SI 1 "" ""))
8410         (match_operand:SI 2 "" "")))
8411    (use (match_operand 3 "" ""))
8412    (clobber (reg:SI LR_REGNUM))]
8413   "TARGET_ARM
8414    && (GET_CODE (operands[1]) == SYMBOL_REF)
8415    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
8416   "*
8417   {
8418     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
8419   }"
8420   [(set_attr "type" "call")]
8423 (define_insn "*call_insn"
8424   [(call (mem:SI (match_operand:SI 0 "" ""))
8425          (match_operand:SI 1 "" ""))
8426    (use (match_operand 2 "" ""))
8427    (clobber (reg:SI LR_REGNUM))]
8428   "TARGET_THUMB
8429    && GET_CODE (operands[0]) == SYMBOL_REF
8430    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
8431   "bl\\t%a0"
8432   [(set_attr "length" "4")
8433    (set_attr "type" "call")]
8436 (define_insn "*call_value_insn"
8437   [(set (match_operand 0 "" "")
8438         (call (mem:SI (match_operand 1 "" ""))
8439               (match_operand 2 "" "")))
8440    (use (match_operand 3 "" ""))
8441    (clobber (reg:SI LR_REGNUM))]
8442   "TARGET_THUMB
8443    && GET_CODE (operands[1]) == SYMBOL_REF
8444    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
8445   "bl\\t%a1"
8446   [(set_attr "length" "4")
8447    (set_attr "type" "call")]
8450 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
8451 (define_expand "sibcall"
8452   [(parallel [(call (match_operand 0 "memory_operand" "")
8453                     (match_operand 1 "general_operand" ""))
8454               (return)
8455               (use (match_operand 2 "" ""))])]
8456   "TARGET_ARM"
8457   "
8458   {
8459     if (operands[2] == NULL_RTX)
8460       operands[2] = const0_rtx;
8461   }"
8464 (define_expand "sibcall_value"
8465   [(parallel [(set (match_operand 0 "" "")
8466                    (call (match_operand 1 "memory_operand" "")
8467                          (match_operand 2 "general_operand" "")))
8468               (return)
8469               (use (match_operand 3 "" ""))])]
8470   "TARGET_ARM"
8471   "
8472   {
8473     if (operands[3] == NULL_RTX)
8474       operands[3] = const0_rtx;
8475   }"
8478 (define_insn "*sibcall_insn"
8479  [(call (mem:SI (match_operand:SI 0 "" "X"))
8480         (match_operand 1 "" ""))
8481   (return)
8482   (use (match_operand 2 "" ""))]
8483   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
8484   "*
8485   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8486   "
8487   [(set_attr "type" "call")]
8490 (define_insn "*sibcall_value_insn"
8491  [(set (match_operand 0 "" "")
8492        (call (mem:SI (match_operand:SI 1 "" "X"))
8493              (match_operand 2 "" "")))
8494   (return)
8495   (use (match_operand 3 "" ""))]
8496   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
8497   "*
8498   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8499   "
8500   [(set_attr "type" "call")]
8503 ;; Often the return insn will be the same as loading from memory, so set attr
8504 (define_insn "return"
8505   [(return)]
8506   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
8507   "*
8508   {
8509     if (arm_ccfsm_state == 2)
8510       {
8511         arm_ccfsm_state += 2;
8512         return \"\";
8513       }
8514     return output_return_instruction (const_true_rtx, TRUE, FALSE);
8515   }"
8516   [(set_attr "type" "load1")
8517    (set_attr "length" "12")
8518    (set_attr "predicable" "yes")]
8521 (define_insn "*cond_return"
8522   [(set (pc)
8523         (if_then_else (match_operator 0 "arm_comparison_operator"
8524                        [(match_operand 1 "cc_register" "") (const_int 0)])
8525                       (return)
8526                       (pc)))]
8527   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
8528   "*
8529   {
8530     if (arm_ccfsm_state == 2)
8531       {
8532         arm_ccfsm_state += 2;
8533         return \"\";
8534       }
8535     return output_return_instruction (operands[0], TRUE, FALSE);
8536   }"
8537   [(set_attr "conds" "use")
8538    (set_attr "length" "12")
8539    (set_attr "type" "load1")]
8542 (define_insn "*cond_return_inverted"
8543   [(set (pc)
8544         (if_then_else (match_operator 0 "arm_comparison_operator"
8545                        [(match_operand 1 "cc_register" "") (const_int 0)])
8546                       (pc)
8547                       (return)))]
8548   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
8549   "*
8550   {
8551     if (arm_ccfsm_state == 2)
8552       {
8553         arm_ccfsm_state += 2;
8554         return \"\";
8555       }
8556     return output_return_instruction (operands[0], TRUE, TRUE);
8557   }"
8558   [(set_attr "conds" "use")
8559    (set_attr "length" "12")
8560    (set_attr "type" "load1")]
8563 ;; Generate a sequence of instructions to determine if the processor is
8564 ;; in 26-bit or 32-bit mode, and return the appropriate return address
8565 ;; mask.
8567 (define_expand "return_addr_mask"
8568   [(set (match_dup 1)
8569       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8570                        (const_int 0)))
8571    (set (match_operand:SI 0 "s_register_operand" "")
8572       (if_then_else:SI (eq (match_dup 1) (const_int 0))
8573                        (const_int -1)
8574                        (const_int 67108860)))] ; 0x03fffffc
8575   "TARGET_ARM"
8576   "
8577   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
8578   ")
8580 (define_insn "*check_arch2"
8581   [(set (match_operand:CC_NOOV 0 "cc_register" "")
8582       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8583                        (const_int 0)))]
8584   "TARGET_ARM"
8585   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8586   [(set_attr "length" "8")
8587    (set_attr "conds" "set")]
8590 ;; Call subroutine returning any type.
8592 (define_expand "untyped_call"
8593   [(parallel [(call (match_operand 0 "" "")
8594                     (const_int 0))
8595               (match_operand 1 "" "")
8596               (match_operand 2 "" "")])]
8597   "TARGET_EITHER"
8598   "
8599   {
8600     int i;
8601     rtx par = gen_rtx_PARALLEL (VOIDmode,
8602                                 rtvec_alloc (XVECLEN (operands[2], 0)));
8603     rtx addr = gen_reg_rtx (Pmode);
8604     rtx mem;
8605     int size = 0;
8607     emit_move_insn (addr, XEXP (operands[1], 0));
8608     mem = change_address (operands[1], BLKmode, addr);
8610     for (i = 0; i < XVECLEN (operands[2], 0); i++)
8611       {
8612         rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
8614         /* Default code only uses r0 as a return value, but we could
8615            be using anything up to 4 registers.  */
8616         if (REGNO (src) == R0_REGNUM)
8617           src = gen_rtx_REG (TImode, R0_REGNUM);
8619         XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8620                                                  GEN_INT (size));
8621         size += GET_MODE_SIZE (GET_MODE (src));
8622       }
8624     emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8625                                     const0_rtx));
8627     size = 0;
8629     for (i = 0; i < XVECLEN (par, 0); i++)
8630       {
8631         HOST_WIDE_INT offset = 0;
8632         rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8634         if (size != 0)
8635           emit_move_insn (addr, plus_constant (addr, size));
8637         mem = change_address (mem, GET_MODE (reg), NULL);
8638         if (REGNO (reg) == R0_REGNUM)
8639           {
8640             /* On thumb we have to use a write-back instruction.  */
8641             emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
8642                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8643             size = TARGET_ARM ? 16 : 0;
8644           }
8645         else
8646           {
8647             emit_move_insn (mem, reg);
8648             size = GET_MODE_SIZE (GET_MODE (reg));
8649           }
8650       }
8652     /* The optimizer does not know that the call sets the function value
8653        registers we stored in the result block.  We avoid problems by
8654        claiming that all hard registers are used and clobbered at this
8655        point.  */
8656     emit_insn (gen_blockage ());
8658     DONE;
8659   }"
8662 (define_expand "untyped_return"
8663   [(match_operand:BLK 0 "memory_operand" "")
8664    (match_operand 1 "" "")]
8665   "TARGET_EITHER"
8666   "
8667   {
8668     int i;
8669     rtx addr = gen_reg_rtx (Pmode);
8670     rtx mem;
8671     int size = 0;
8673     emit_move_insn (addr, XEXP (operands[0], 0));
8674     mem = change_address (operands[0], BLKmode, addr);
8676     for (i = 0; i < XVECLEN (operands[1], 0); i++)
8677       {
8678         HOST_WIDE_INT offset = 0;
8679         rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8681         if (size != 0)
8682           emit_move_insn (addr, plus_constant (addr, size));
8684         mem = change_address (mem, GET_MODE (reg), NULL);
8685         if (REGNO (reg) == R0_REGNUM)
8686           {
8687             /* On thumb we have to use a write-back instruction.  */
8688             emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
8689                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8690             size = TARGET_ARM ? 16 : 0;
8691           }
8692         else
8693           {
8694             emit_move_insn (reg, mem);
8695             size = GET_MODE_SIZE (GET_MODE (reg));
8696           }
8697       }
8699     /* Emit USE insns before the return.  */
8700     for (i = 0; i < XVECLEN (operands[1], 0); i++)
8701       emit_insn (gen_rtx_USE (VOIDmode,
8702                               SET_DEST (XVECEXP (operands[1], 0, i))));
8704     /* Construct the return.  */
8705     expand_naked_return ();
8707     DONE;
8708   }"
8711 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8712 ;; all of memory.  This blocks insns from being moved across this point.
8714 (define_insn "blockage"
8715   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
8716   "TARGET_EITHER"
8717   ""
8718   [(set_attr "length" "0")
8719    (set_attr "type" "block")]
8722 (define_expand "casesi"
8723   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
8724    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
8725    (match_operand:SI 2 "const_int_operand" "")  ; total range
8726    (match_operand:SI 3 "" "")                   ; table label
8727    (match_operand:SI 4 "" "")]                  ; Out of range label
8728   "TARGET_32BIT"
8729   "
8730   {
8731     rtx reg;
8732     if (operands[1] != const0_rtx)
8733       {
8734         reg = gen_reg_rtx (SImode);
8736         emit_insn (gen_addsi3 (reg, operands[0],
8737                                GEN_INT (-INTVAL (operands[1]))));
8738         operands[0] = reg;
8739       }
8741     if (!const_ok_for_arm (INTVAL (operands[2])))
8742       operands[2] = force_reg (SImode, operands[2]);
8744     if (TARGET_ARM)
8745       {
8746         emit_jump_insn (gen_arm_casesi_internal (operands[0], operands[2],
8747                                                  operands[3], operands[4]));
8748       }
8749     else if (flag_pic)
8750       {
8751         emit_jump_insn (gen_thumb2_casesi_internal_pic (operands[0],
8752             operands[2], operands[3], operands[4]));
8753       }
8754     else
8755       {
8756         emit_jump_insn (gen_thumb2_casesi_internal (operands[0], operands[2],
8757                                                     operands[3], operands[4]));
8758       }
8759     DONE;
8760   }"
8763 ;; The USE in this pattern is needed to tell flow analysis that this is
8764 ;; a CASESI insn.  It has no other purpose.
8765 (define_insn "arm_casesi_internal"
8766   [(parallel [(set (pc)
8767                (if_then_else
8768                 (leu (match_operand:SI 0 "s_register_operand" "r")
8769                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
8770                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8771                                  (label_ref (match_operand 2 "" ""))))
8772                 (label_ref (match_operand 3 "" ""))))
8773               (clobber (reg:CC CC_REGNUM))
8774               (use (label_ref (match_dup 2)))])]
8775   "TARGET_ARM"
8776   "*
8777     if (flag_pic)
8778       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8779     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8780   "
8781   [(set_attr "conds" "clob")
8782    (set_attr "length" "12")]
8785 (define_expand "indirect_jump"
8786   [(set (pc)
8787         (match_operand:SI 0 "s_register_operand" ""))]
8788   "TARGET_EITHER"
8789   "
8790   /* Thumb-2 doesn't have mov pc, reg.  Explicitly set the low bit of the
8791      address and use bx.  */
8792   if (TARGET_THUMB2)
8793     {
8794       rtx tmp;
8795       tmp = gen_reg_rtx (SImode);
8796       emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8797       operands[0] = tmp;
8798     }
8799   "
8802 ;; NB Never uses BX.
8803 (define_insn "*arm_indirect_jump"
8804   [(set (pc)
8805         (match_operand:SI 0 "s_register_operand" "r"))]
8806   "TARGET_ARM"
8807   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
8808   [(set_attr "predicable" "yes")]
8811 (define_insn "*load_indirect_jump"
8812   [(set (pc)
8813         (match_operand:SI 0 "memory_operand" "m"))]
8814   "TARGET_ARM"
8815   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
8816   [(set_attr "type" "load1")
8817    (set_attr "pool_range" "4096")
8818    (set_attr "neg_pool_range" "4084")
8819    (set_attr "predicable" "yes")]
8822 ;; NB Never uses BX.
8823 (define_insn "*thumb1_indirect_jump"
8824   [(set (pc)
8825         (match_operand:SI 0 "register_operand" "l*r"))]
8826   "TARGET_THUMB1"
8827   "mov\\tpc, %0"
8828   [(set_attr "conds" "clob")
8829    (set_attr "length" "2")]
8833 ;; Misc insns
8835 (define_insn "nop"
8836   [(const_int 0)]
8837   "TARGET_EITHER"
8838   "*
8839   if (TARGET_UNIFIED_ASM)
8840     return \"nop\";
8841   if (TARGET_ARM)
8842     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8843   return  \"mov\\tr8, r8\";
8844   "
8845   [(set (attr "length")
8846         (if_then_else (eq_attr "is_thumb" "yes")
8847                       (const_int 2)
8848                       (const_int 4)))]
8852 ;; Patterns to allow combination of arithmetic, cond code and shifts
8854 (define_insn "*arith_shiftsi"
8855   [(set (match_operand:SI 0 "s_register_operand" "=r")
8856         (match_operator:SI 1 "shiftable_operator"
8857           [(match_operator:SI 3 "shift_operator"
8858              [(match_operand:SI 4 "s_register_operand" "r")
8859               (match_operand:SI 5 "reg_or_int_operand" "rI")])
8860            (match_operand:SI 2 "s_register_operand" "r")]))]
8861   "TARGET_ARM"
8862   "%i1%?\\t%0, %2, %4%S3"
8863   [(set_attr "predicable" "yes")
8864    (set_attr "shift" "4")
8865    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8866                       (const_string "alu_shift")
8867                       (const_string "alu_shift_reg")))]
8870 (define_split
8871   [(set (match_operand:SI 0 "s_register_operand" "")
8872         (match_operator:SI 1 "shiftable_operator"
8873          [(match_operator:SI 2 "shiftable_operator"
8874            [(match_operator:SI 3 "shift_operator"
8875              [(match_operand:SI 4 "s_register_operand" "")
8876               (match_operand:SI 5 "reg_or_int_operand" "")])
8877             (match_operand:SI 6 "s_register_operand" "")])
8878           (match_operand:SI 7 "arm_rhs_operand" "")]))
8879    (clobber (match_operand:SI 8 "s_register_operand" ""))]
8880   "TARGET_ARM"
8881   [(set (match_dup 8)
8882         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8883                          (match_dup 6)]))
8884    (set (match_dup 0)
8885         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8886   "")
8888 (define_insn "*arith_shiftsi_compare0"
8889   [(set (reg:CC_NOOV CC_REGNUM)
8890         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8891                           [(match_operator:SI 3 "shift_operator"
8892                             [(match_operand:SI 4 "s_register_operand" "r")
8893                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8894                            (match_operand:SI 2 "s_register_operand" "r")])
8895                          (const_int 0)))
8896    (set (match_operand:SI 0 "s_register_operand" "=r")
8897         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8898                          (match_dup 2)]))]
8899   "TARGET_ARM"
8900   "%i1%.\\t%0, %2, %4%S3"
8901   [(set_attr "conds" "set")
8902    (set_attr "shift" "4")
8903    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8904                       (const_string "alu_shift")
8905                       (const_string "alu_shift_reg")))]
8908 (define_insn "*arith_shiftsi_compare0_scratch"
8909   [(set (reg:CC_NOOV CC_REGNUM)
8910         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8911                           [(match_operator:SI 3 "shift_operator"
8912                             [(match_operand:SI 4 "s_register_operand" "r")
8913                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8914                            (match_operand:SI 2 "s_register_operand" "r")])
8915                          (const_int 0)))
8916    (clobber (match_scratch:SI 0 "=r"))]
8917   "TARGET_ARM"
8918   "%i1%.\\t%0, %2, %4%S3"
8919   [(set_attr "conds" "set")
8920    (set_attr "shift" "4")
8921    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8922                       (const_string "alu_shift")
8923                       (const_string "alu_shift_reg")))]
8926 (define_insn "*sub_shiftsi"
8927   [(set (match_operand:SI 0 "s_register_operand" "=r")
8928         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8929                   (match_operator:SI 2 "shift_operator"
8930                    [(match_operand:SI 3 "s_register_operand" "r")
8931                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
8932   "TARGET_ARM"
8933   "sub%?\\t%0, %1, %3%S2"
8934   [(set_attr "predicable" "yes")
8935    (set_attr "shift" "3")
8936    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8937                       (const_string "alu_shift")
8938                       (const_string "alu_shift_reg")))]
8941 (define_insn "*sub_shiftsi_compare0"
8942   [(set (reg:CC_NOOV CC_REGNUM)
8943         (compare:CC_NOOV
8944          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8945                    (match_operator:SI 2 "shift_operator"
8946                     [(match_operand:SI 3 "s_register_operand" "r")
8947                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8948          (const_int 0)))
8949    (set (match_operand:SI 0 "s_register_operand" "=r")
8950         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8951                                                  (match_dup 4)])))]
8952   "TARGET_ARM"
8953   "sub%.\\t%0, %1, %3%S2"
8954   [(set_attr "conds" "set")
8955    (set_attr "shift" "3")
8956    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8957                       (const_string "alu_shift")
8958                       (const_string "alu_shift_reg")))]
8961 (define_insn "*sub_shiftsi_compare0_scratch"
8962   [(set (reg:CC_NOOV CC_REGNUM)
8963         (compare:CC_NOOV
8964          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8965                    (match_operator:SI 2 "shift_operator"
8966                     [(match_operand:SI 3 "s_register_operand" "r")
8967                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8968          (const_int 0)))
8969    (clobber (match_scratch:SI 0 "=r"))]
8970   "TARGET_ARM"
8971   "sub%.\\t%0, %1, %3%S2"
8972   [(set_attr "conds" "set")
8973    (set_attr "shift" "3")
8974    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8975                       (const_string "alu_shift")
8976                       (const_string "alu_shift_reg")))]
8981 (define_insn "*and_scc"
8982   [(set (match_operand:SI 0 "s_register_operand" "=r")
8983         (and:SI (match_operator:SI 1 "arm_comparison_operator"
8984                  [(match_operand 3 "cc_register" "") (const_int 0)])
8985                 (match_operand:SI 2 "s_register_operand" "r")))]
8986   "TARGET_ARM"
8987   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8988   [(set_attr "conds" "use")
8989    (set_attr "length" "8")]
8992 (define_insn "*ior_scc"
8993   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8994         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8995                  [(match_operand 3 "cc_register" "") (const_int 0)])
8996                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8997   "TARGET_ARM"
8998   "@
8999    orr%d2\\t%0, %1, #1
9000    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
9001   [(set_attr "conds" "use")
9002    (set_attr "length" "4,8")]
9005 (define_insn "*compare_scc"
9006   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9007         (match_operator:SI 1 "arm_comparison_operator"
9008          [(match_operand:SI 2 "s_register_operand" "r,r")
9009           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
9010    (clobber (reg:CC CC_REGNUM))]
9011   "TARGET_ARM"
9012   "*
9013     if (operands[3] == const0_rtx)
9014       {
9015         if (GET_CODE (operands[1]) == LT)
9016           return \"mov\\t%0, %2, lsr #31\";
9018         if (GET_CODE (operands[1]) == GE)
9019           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
9021         if (GET_CODE (operands[1]) == EQ)
9022           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
9023       }
9025     if (GET_CODE (operands[1]) == NE)
9026       {
9027         if (which_alternative == 1)
9028           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
9029         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
9030       }
9031     if (which_alternative == 1)
9032       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9033     else
9034       output_asm_insn (\"cmp\\t%2, %3\", operands);
9035     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
9036   "
9037   [(set_attr "conds" "clob")
9038    (set_attr "length" "12")]
9041 (define_insn "*cond_move"
9042   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9043         (if_then_else:SI (match_operator 3 "equality_operator"
9044                           [(match_operator 4 "arm_comparison_operator"
9045                             [(match_operand 5 "cc_register" "") (const_int 0)])
9046                            (const_int 0)])
9047                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9048                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
9049   "TARGET_ARM"
9050   "*
9051     if (GET_CODE (operands[3]) == NE)
9052       {
9053         if (which_alternative != 1)
9054           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
9055         if (which_alternative != 0)
9056           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
9057         return \"\";
9058       }
9059     if (which_alternative != 0)
9060       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9061     if (which_alternative != 1)
9062       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
9063     return \"\";
9064   "
9065   [(set_attr "conds" "use")
9066    (set_attr "length" "4,4,8")]
9069 (define_insn "*cond_arith"
9070   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9071         (match_operator:SI 5 "shiftable_operator" 
9072          [(match_operator:SI 4 "arm_comparison_operator"
9073            [(match_operand:SI 2 "s_register_operand" "r,r")
9074             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9075           (match_operand:SI 1 "s_register_operand" "0,?r")]))
9076    (clobber (reg:CC CC_REGNUM))]
9077   "TARGET_ARM"
9078   "*
9079     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
9080       return \"%i5\\t%0, %1, %2, lsr #31\";
9082     output_asm_insn (\"cmp\\t%2, %3\", operands);
9083     if (GET_CODE (operands[5]) == AND)
9084       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
9085     else if (GET_CODE (operands[5]) == MINUS)
9086       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
9087     else if (which_alternative != 0)
9088       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9089     return \"%i5%d4\\t%0, %1, #1\";
9090   "
9091   [(set_attr "conds" "clob")
9092    (set_attr "length" "12")]
9095 (define_insn "*cond_sub"
9096   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9097         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
9098                   (match_operator:SI 4 "arm_comparison_operator"
9099                    [(match_operand:SI 2 "s_register_operand" "r,r")
9100                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
9101    (clobber (reg:CC CC_REGNUM))]
9102   "TARGET_ARM"
9103   "*
9104     output_asm_insn (\"cmp\\t%2, %3\", operands);
9105     if (which_alternative != 0)
9106       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9107     return \"sub%d4\\t%0, %1, #1\";
9108   "
9109   [(set_attr "conds" "clob")
9110    (set_attr "length" "8,12")]
9113 ;; ??? Is it worth using these conditional patterns in Thumb-2 mode?
9114 (define_insn "*cmp_ite0"
9115   [(set (match_operand 6 "dominant_cc_register" "")
9116         (compare
9117          (if_then_else:SI
9118           (match_operator 4 "arm_comparison_operator"
9119            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9120             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9121           (match_operator:SI 5 "arm_comparison_operator"
9122            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9123             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
9124           (const_int 0))
9125          (const_int 0)))]
9126   "TARGET_ARM"
9127   "*
9128   {
9129     static const char * const opcodes[4][2] =
9130     {
9131       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9132        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9133       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9134        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9135       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9136        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9137       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9138        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9139     };
9140     int swap =
9141       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9143     return opcodes[which_alternative][swap];
9144   }"
9145   [(set_attr "conds" "set")
9146    (set_attr "length" "8")]
9149 (define_insn "*cmp_ite1"
9150   [(set (match_operand 6 "dominant_cc_register" "")
9151         (compare
9152          (if_then_else:SI
9153           (match_operator 4 "arm_comparison_operator"
9154            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9155             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9156           (match_operator:SI 5 "arm_comparison_operator"
9157            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9158             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
9159           (const_int 1))
9160          (const_int 0)))]
9161   "TARGET_ARM"
9162   "*
9163   {
9164     static const char * const opcodes[4][2] =
9165     {
9166       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
9167        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9168       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
9169        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9170       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
9171        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9172       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
9173        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9174     };
9175     int swap =
9176       comparison_dominates_p (GET_CODE (operands[5]),
9177                               reverse_condition (GET_CODE (operands[4])));
9179     return opcodes[which_alternative][swap];
9180   }"
9181   [(set_attr "conds" "set")
9182    (set_attr "length" "8")]
9185 (define_insn "*cmp_and"
9186   [(set (match_operand 6 "dominant_cc_register" "")
9187         (compare
9188          (and:SI
9189           (match_operator 4 "arm_comparison_operator"
9190            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9191             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9192           (match_operator:SI 5 "arm_comparison_operator"
9193            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9194             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9195          (const_int 0)))]
9196   "TARGET_ARM"
9197   "*
9198   {
9199     static const char *const opcodes[4][2] =
9200     {
9201       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9202        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9203       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9204        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9205       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9206        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9207       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9208        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9209     };
9210     int swap =
9211       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9213     return opcodes[which_alternative][swap];
9214   }"
9215   [(set_attr "conds" "set")
9216    (set_attr "predicable" "no")
9217    (set_attr "length" "8")]
9220 (define_insn "*cmp_ior"
9221   [(set (match_operand 6 "dominant_cc_register" "")
9222         (compare
9223          (ior:SI
9224           (match_operator 4 "arm_comparison_operator"
9225            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9226             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9227           (match_operator:SI 5 "arm_comparison_operator"
9228            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9229             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9230          (const_int 0)))]
9231   "TARGET_ARM"
9232   "*
9234   static const char *const opcodes[4][2] =
9235   {
9236     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
9237      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9238     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
9239      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9240     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
9241      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9242     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
9243      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9244   };
9245   int swap =
9246     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9248   return opcodes[which_alternative][swap];
9251   [(set_attr "conds" "set")
9252    (set_attr "length" "8")]
9255 (define_insn_and_split "*ior_scc_scc"
9256   [(set (match_operand:SI 0 "s_register_operand" "=r")
9257         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9258                  [(match_operand:SI 1 "s_register_operand" "r")
9259                   (match_operand:SI 2 "arm_add_operand" "rIL")])
9260                 (match_operator:SI 6 "arm_comparison_operator"
9261                  [(match_operand:SI 4 "s_register_operand" "r")
9262                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
9263    (clobber (reg:CC CC_REGNUM))]
9264   "TARGET_ARM
9265    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9266        != CCmode)"
9267   "#"
9268   "TARGET_ARM && reload_completed"
9269   [(set (match_dup 7)
9270         (compare
9271          (ior:SI
9272           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9273           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9274          (const_int 0)))
9275    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9276   "operands[7]
9277      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9278                                                   DOM_CC_X_OR_Y),
9279                     CC_REGNUM);"
9280   [(set_attr "conds" "clob")
9281    (set_attr "length" "16")])
9283 ; If the above pattern is followed by a CMP insn, then the compare is 
9284 ; redundant, since we can rework the conditional instruction that follows.
9285 (define_insn_and_split "*ior_scc_scc_cmp"
9286   [(set (match_operand 0 "dominant_cc_register" "")
9287         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9288                           [(match_operand:SI 1 "s_register_operand" "r")
9289                            (match_operand:SI 2 "arm_add_operand" "rIL")])
9290                          (match_operator:SI 6 "arm_comparison_operator"
9291                           [(match_operand:SI 4 "s_register_operand" "r")
9292                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
9293                  (const_int 0)))
9294    (set (match_operand:SI 7 "s_register_operand" "=r")
9295         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9296                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9297   "TARGET_ARM"
9298   "#"
9299   "TARGET_ARM && reload_completed"
9300   [(set (match_dup 0)
9301         (compare
9302          (ior:SI
9303           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9304           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9305          (const_int 0)))
9306    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9307   ""
9308   [(set_attr "conds" "set")
9309    (set_attr "length" "16")])
9311 (define_insn_and_split "*and_scc_scc"
9312   [(set (match_operand:SI 0 "s_register_operand" "=r")
9313         (and:SI (match_operator:SI 3 "arm_comparison_operator"
9314                  [(match_operand:SI 1 "s_register_operand" "r")
9315                   (match_operand:SI 2 "arm_add_operand" "rIL")])
9316                 (match_operator:SI 6 "arm_comparison_operator"
9317                  [(match_operand:SI 4 "s_register_operand" "r")
9318                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
9319    (clobber (reg:CC CC_REGNUM))]
9320   "TARGET_ARM
9321    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9322        != CCmode)"
9323   "#"
9324   "TARGET_ARM && reload_completed
9325    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9326        != CCmode)"
9327   [(set (match_dup 7)
9328         (compare
9329          (and:SI
9330           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9331           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9332          (const_int 0)))
9333    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9334   "operands[7]
9335      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9336                                                   DOM_CC_X_AND_Y),
9337                     CC_REGNUM);"
9338   [(set_attr "conds" "clob")
9339    (set_attr "length" "16")])
9341 ; If the above pattern is followed by a CMP insn, then the compare is 
9342 ; redundant, since we can rework the conditional instruction that follows.
9343 (define_insn_and_split "*and_scc_scc_cmp"
9344   [(set (match_operand 0 "dominant_cc_register" "")
9345         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9346                           [(match_operand:SI 1 "s_register_operand" "r")
9347                            (match_operand:SI 2 "arm_add_operand" "rIL")])
9348                          (match_operator:SI 6 "arm_comparison_operator"
9349                           [(match_operand:SI 4 "s_register_operand" "r")
9350                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
9351                  (const_int 0)))
9352    (set (match_operand:SI 7 "s_register_operand" "=r")
9353         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9354                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9355   "TARGET_ARM"
9356   "#"
9357   "TARGET_ARM && reload_completed"
9358   [(set (match_dup 0)
9359         (compare
9360          (and:SI
9361           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9362           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9363          (const_int 0)))
9364    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9365   ""
9366   [(set_attr "conds" "set")
9367    (set_attr "length" "16")])
9369 ;; If there is no dominance in the comparison, then we can still save an
9370 ;; instruction in the AND case, since we can know that the second compare
9371 ;; need only zero the value if false (if true, then the value is already
9372 ;; correct).
9373 (define_insn_and_split "*and_scc_scc_nodom"
9374   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
9375         (and:SI (match_operator:SI 3 "arm_comparison_operator"
9376                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
9377                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9378                 (match_operator:SI 6 "arm_comparison_operator"
9379                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
9380                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9381    (clobber (reg:CC CC_REGNUM))]
9382   "TARGET_ARM
9383    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9384        == CCmode)"
9385   "#"
9386   "TARGET_ARM && reload_completed"
9387   [(parallel [(set (match_dup 0)
9388                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9389               (clobber (reg:CC CC_REGNUM))])
9390    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9391    (set (match_dup 0)
9392         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9393                          (match_dup 0)
9394                          (const_int 0)))]
9395   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9396                                               operands[4], operands[5]),
9397                               CC_REGNUM);
9398    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9399                                   operands[5]);"
9400   [(set_attr "conds" "clob")
9401    (set_attr "length" "20")])
9403 (define_split
9404   [(set (reg:CC_NOOV CC_REGNUM)
9405         (compare:CC_NOOV (ior:SI
9406                           (and:SI (match_operand:SI 0 "s_register_operand" "")
9407                                   (const_int 1))
9408                           (match_operator:SI 1 "comparison_operator"
9409                            [(match_operand:SI 2 "s_register_operand" "")
9410                             (match_operand:SI 3 "arm_add_operand" "")]))
9411                          (const_int 0)))
9412    (clobber (match_operand:SI 4 "s_register_operand" ""))]
9413   "TARGET_ARM"
9414   [(set (match_dup 4)
9415         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9416                 (match_dup 0)))
9417    (set (reg:CC_NOOV CC_REGNUM)
9418         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9419                          (const_int 0)))]
9420   "")
9422 (define_split
9423   [(set (reg:CC_NOOV CC_REGNUM)
9424         (compare:CC_NOOV (ior:SI
9425                           (match_operator:SI 1 "comparison_operator"
9426                            [(match_operand:SI 2 "s_register_operand" "")
9427                             (match_operand:SI 3 "arm_add_operand" "")])
9428                           (and:SI (match_operand:SI 0 "s_register_operand" "")
9429                                   (const_int 1)))
9430                          (const_int 0)))
9431    (clobber (match_operand:SI 4 "s_register_operand" ""))]
9432   "TARGET_ARM"
9433   [(set (match_dup 4)
9434         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9435                 (match_dup 0)))
9436    (set (reg:CC_NOOV CC_REGNUM)
9437         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9438                          (const_int 0)))]
9439   "")
9440 ;; ??? The conditional patterns above need checking for Thumb-2 usefulness
9442 (define_insn "*negscc"
9443   [(set (match_operand:SI 0 "s_register_operand" "=r")
9444         (neg:SI (match_operator 3 "arm_comparison_operator"
9445                  [(match_operand:SI 1 "s_register_operand" "r")
9446                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
9447    (clobber (reg:CC CC_REGNUM))]
9448   "TARGET_ARM"
9449   "*
9450   if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
9451     return \"mov\\t%0, %1, asr #31\";
9453   if (GET_CODE (operands[3]) == NE)
9454     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9456   output_asm_insn (\"cmp\\t%1, %2\", operands);
9457   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9458   return \"mvn%d3\\t%0, #0\";
9459   "
9460   [(set_attr "conds" "clob")
9461    (set_attr "length" "12")]
9464 (define_insn "movcond"
9465   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9466         (if_then_else:SI
9467          (match_operator 5 "arm_comparison_operator"
9468           [(match_operand:SI 3 "s_register_operand" "r,r,r")
9469            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9470          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9471          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
9472    (clobber (reg:CC CC_REGNUM))]
9473   "TARGET_ARM"
9474   "*
9475   if (GET_CODE (operands[5]) == LT
9476       && (operands[4] == const0_rtx))
9477     {
9478       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9479         {
9480           if (operands[2] == const0_rtx)
9481             return \"and\\t%0, %1, %3, asr #31\";
9482           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9483         }
9484       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9485         {
9486           if (operands[1] == const0_rtx)
9487             return \"bic\\t%0, %2, %3, asr #31\";
9488           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9489         }
9490       /* The only case that falls through to here is when both ops 1 & 2
9491          are constants.  */
9492     }
9494   if (GET_CODE (operands[5]) == GE
9495       && (operands[4] == const0_rtx))
9496     {
9497       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9498         {
9499           if (operands[2] == const0_rtx)
9500             return \"bic\\t%0, %1, %3, asr #31\";
9501           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9502         }
9503       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9504         {
9505           if (operands[1] == const0_rtx)
9506             return \"and\\t%0, %2, %3, asr #31\";
9507           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9508         }
9509       /* The only case that falls through to here is when both ops 1 & 2
9510          are constants.  */
9511     }
9512   if (GET_CODE (operands[4]) == CONST_INT
9513       && !const_ok_for_arm (INTVAL (operands[4])))
9514     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9515   else
9516     output_asm_insn (\"cmp\\t%3, %4\", operands);
9517   if (which_alternative != 0)
9518     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9519   if (which_alternative != 1)
9520     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9521   return \"\";
9522   "
9523   [(set_attr "conds" "clob")
9524    (set_attr "length" "8,8,12")]
9527 ;; ??? The patterns below need checking for Thumb-2 usefulness.
9529 (define_insn "*ifcompare_plus_move"
9530   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9531         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9532                           [(match_operand:SI 4 "s_register_operand" "r,r")
9533                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9534                          (plus:SI
9535                           (match_operand:SI 2 "s_register_operand" "r,r")
9536                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
9537                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9538    (clobber (reg:CC CC_REGNUM))]
9539   "TARGET_ARM"
9540   "#"
9541   [(set_attr "conds" "clob")
9542    (set_attr "length" "8,12")]
9545 (define_insn "*if_plus_move"
9546   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9547         (if_then_else:SI
9548          (match_operator 4 "arm_comparison_operator"
9549           [(match_operand 5 "cc_register" "") (const_int 0)])
9550          (plus:SI
9551           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9552           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9553          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
9554   "TARGET_ARM"
9555   "@
9556    add%d4\\t%0, %2, %3
9557    sub%d4\\t%0, %2, #%n3
9558    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
9559    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
9560   [(set_attr "conds" "use")
9561    (set_attr "length" "4,4,8,8")
9562    (set_attr "type" "*,*,*,*")]
9565 (define_insn "*ifcompare_move_plus"
9566   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9567         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9568                           [(match_operand:SI 4 "s_register_operand" "r,r")
9569                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9570                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9571                          (plus:SI
9572                           (match_operand:SI 2 "s_register_operand" "r,r")
9573                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
9574    (clobber (reg:CC CC_REGNUM))]
9575   "TARGET_ARM"
9576   "#"
9577   [(set_attr "conds" "clob")
9578    (set_attr "length" "8,12")]
9581 (define_insn "*if_move_plus"
9582   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9583         (if_then_else:SI
9584          (match_operator 4 "arm_comparison_operator"
9585           [(match_operand 5 "cc_register" "") (const_int 0)])
9586          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
9587          (plus:SI
9588           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9589           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
9590   "TARGET_ARM"
9591   "@
9592    add%D4\\t%0, %2, %3
9593    sub%D4\\t%0, %2, #%n3
9594    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
9595    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
9596   [(set_attr "conds" "use")
9597    (set_attr "length" "4,4,8,8")
9598    (set_attr "type" "*,*,*,*")]
9601 (define_insn "*ifcompare_arith_arith"
9602   [(set (match_operand:SI 0 "s_register_operand" "=r")
9603         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
9604                           [(match_operand:SI 5 "s_register_operand" "r")
9605                            (match_operand:SI 6 "arm_add_operand" "rIL")])
9606                          (match_operator:SI 8 "shiftable_operator"
9607                           [(match_operand:SI 1 "s_register_operand" "r")
9608                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
9609                          (match_operator:SI 7 "shiftable_operator"
9610                           [(match_operand:SI 3 "s_register_operand" "r")
9611                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
9612    (clobber (reg:CC CC_REGNUM))]
9613   "TARGET_ARM"
9614   "#"
9615   [(set_attr "conds" "clob")
9616    (set_attr "length" "12")]
9619 (define_insn "*if_arith_arith"
9620   [(set (match_operand:SI 0 "s_register_operand" "=r")
9621         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
9622                           [(match_operand 8 "cc_register" "") (const_int 0)])
9623                          (match_operator:SI 6 "shiftable_operator"
9624                           [(match_operand:SI 1 "s_register_operand" "r")
9625                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
9626                          (match_operator:SI 7 "shiftable_operator"
9627                           [(match_operand:SI 3 "s_register_operand" "r")
9628                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
9629   "TARGET_ARM"
9630   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
9631   [(set_attr "conds" "use")
9632    (set_attr "length" "8")]
9635 (define_insn "*ifcompare_arith_move"
9636   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9637         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9638                           [(match_operand:SI 2 "s_register_operand" "r,r")
9639                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9640                          (match_operator:SI 7 "shiftable_operator"
9641                           [(match_operand:SI 4 "s_register_operand" "r,r")
9642                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
9643                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9644    (clobber (reg:CC CC_REGNUM))]
9645   "TARGET_ARM"
9646   "*
9647   /* If we have an operation where (op x 0) is the identity operation and
9648      the conditional operator is LT or GE and we are comparing against zero and
9649      everything is in registers then we can do this in two instructions.  */
9650   if (operands[3] == const0_rtx
9651       && GET_CODE (operands[7]) != AND
9652       && GET_CODE (operands[5]) == REG
9653       && GET_CODE (operands[1]) == REG 
9654       && REGNO (operands[1]) == REGNO (operands[4])
9655       && REGNO (operands[4]) != REGNO (operands[0]))
9656     {
9657       if (GET_CODE (operands[6]) == LT)
9658         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9659       else if (GET_CODE (operands[6]) == GE)
9660         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9661     }
9662   if (GET_CODE (operands[3]) == CONST_INT
9663       && !const_ok_for_arm (INTVAL (operands[3])))
9664     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9665   else
9666     output_asm_insn (\"cmp\\t%2, %3\", operands);
9667   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9668   if (which_alternative != 0)
9669     return \"mov%D6\\t%0, %1\";
9670   return \"\";
9671   "
9672   [(set_attr "conds" "clob")
9673    (set_attr "length" "8,12")]
9676 (define_insn "*if_arith_move"
9677   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9678         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9679                           [(match_operand 6 "cc_register" "") (const_int 0)])
9680                          (match_operator:SI 5 "shiftable_operator"
9681                           [(match_operand:SI 2 "s_register_operand" "r,r")
9682                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9683                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
9684   "TARGET_ARM"
9685   "@
9686    %I5%d4\\t%0, %2, %3
9687    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
9688   [(set_attr "conds" "use")
9689    (set_attr "length" "4,8")
9690    (set_attr "type" "*,*")]
9693 (define_insn "*ifcompare_move_arith"
9694   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9695         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9696                           [(match_operand:SI 4 "s_register_operand" "r,r")
9697                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9698                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9699                          (match_operator:SI 7 "shiftable_operator"
9700                           [(match_operand:SI 2 "s_register_operand" "r,r")
9701                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
9702    (clobber (reg:CC CC_REGNUM))]
9703   "TARGET_ARM"
9704   "*
9705   /* If we have an operation where (op x 0) is the identity operation and
9706      the conditional operator is LT or GE and we are comparing against zero and
9707      everything is in registers then we can do this in two instructions */
9708   if (operands[5] == const0_rtx
9709       && GET_CODE (operands[7]) != AND
9710       && GET_CODE (operands[3]) == REG
9711       && GET_CODE (operands[1]) == REG 
9712       && REGNO (operands[1]) == REGNO (operands[2])
9713       && REGNO (operands[2]) != REGNO (operands[0]))
9714     {
9715       if (GET_CODE (operands[6]) == GE)
9716         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9717       else if (GET_CODE (operands[6]) == LT)
9718         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9719     }
9721   if (GET_CODE (operands[5]) == CONST_INT
9722       && !const_ok_for_arm (INTVAL (operands[5])))
9723     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9724   else
9725     output_asm_insn (\"cmp\\t%4, %5\", operands);
9727   if (which_alternative != 0)
9728     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
9729   return \"%I7%D6\\t%0, %2, %3\";
9730   "
9731   [(set_attr "conds" "clob")
9732    (set_attr "length" "8,12")]
9735 (define_insn "*if_move_arith"
9736   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9737         (if_then_else:SI
9738          (match_operator 4 "arm_comparison_operator"
9739           [(match_operand 6 "cc_register" "") (const_int 0)])
9740          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9741          (match_operator:SI 5 "shiftable_operator"
9742           [(match_operand:SI 2 "s_register_operand" "r,r")
9743            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
9744   "TARGET_ARM"
9745   "@
9746    %I5%D4\\t%0, %2, %3
9747    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
9748   [(set_attr "conds" "use")
9749    (set_attr "length" "4,8")
9750    (set_attr "type" "*,*")]
9753 (define_insn "*ifcompare_move_not"
9754   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9755         (if_then_else:SI
9756          (match_operator 5 "arm_comparison_operator"
9757           [(match_operand:SI 3 "s_register_operand" "r,r")
9758            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9759          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9760          (not:SI
9761           (match_operand:SI 2 "s_register_operand" "r,r"))))
9762    (clobber (reg:CC CC_REGNUM))]
9763   "TARGET_ARM"
9764   "#"
9765   [(set_attr "conds" "clob")
9766    (set_attr "length" "8,12")]
9769 (define_insn "*if_move_not"
9770   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9771         (if_then_else:SI
9772          (match_operator 4 "arm_comparison_operator"
9773           [(match_operand 3 "cc_register" "") (const_int 0)])
9774          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9775          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9776   "TARGET_ARM"
9777   "@
9778    mvn%D4\\t%0, %2
9779    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9780    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
9781   [(set_attr "conds" "use")
9782    (set_attr "length" "4,8,8")]
9785 (define_insn "*ifcompare_not_move"
9786   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9787         (if_then_else:SI 
9788          (match_operator 5 "arm_comparison_operator"
9789           [(match_operand:SI 3 "s_register_operand" "r,r")
9790            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9791          (not:SI
9792           (match_operand:SI 2 "s_register_operand" "r,r"))
9793          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9794    (clobber (reg:CC CC_REGNUM))]
9795   "TARGET_ARM"
9796   "#"
9797   [(set_attr "conds" "clob")
9798    (set_attr "length" "8,12")]
9801 (define_insn "*if_not_move"
9802   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9803         (if_then_else:SI
9804          (match_operator 4 "arm_comparison_operator"
9805           [(match_operand 3 "cc_register" "") (const_int 0)])
9806          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9807          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9808   "TARGET_ARM"
9809   "@
9810    mvn%d4\\t%0, %2
9811    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9812    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
9813   [(set_attr "conds" "use")
9814    (set_attr "length" "4,8,8")]
9817 (define_insn "*ifcompare_shift_move"
9818   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9819         (if_then_else:SI
9820          (match_operator 6 "arm_comparison_operator"
9821           [(match_operand:SI 4 "s_register_operand" "r,r")
9822            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9823          (match_operator:SI 7 "shift_operator"
9824           [(match_operand:SI 2 "s_register_operand" "r,r")
9825            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9826          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9827    (clobber (reg:CC CC_REGNUM))]
9828   "TARGET_ARM"
9829   "#"
9830   [(set_attr "conds" "clob")
9831    (set_attr "length" "8,12")]
9834 (define_insn "*if_shift_move"
9835   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9836         (if_then_else:SI
9837          (match_operator 5 "arm_comparison_operator"
9838           [(match_operand 6 "cc_register" "") (const_int 0)])
9839          (match_operator:SI 4 "shift_operator"
9840           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9841            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9842          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9843   "TARGET_ARM"
9844   "@
9845    mov%d5\\t%0, %2%S4
9846    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9847    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
9848   [(set_attr "conds" "use")
9849    (set_attr "shift" "2")
9850    (set_attr "length" "4,8,8")
9851    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9852                       (const_string "alu_shift")
9853                       (const_string "alu_shift_reg")))]
9856 (define_insn "*ifcompare_move_shift"
9857   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9858         (if_then_else:SI
9859          (match_operator 6 "arm_comparison_operator"
9860           [(match_operand:SI 4 "s_register_operand" "r,r")
9861            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9862          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9863          (match_operator:SI 7 "shift_operator"
9864           [(match_operand:SI 2 "s_register_operand" "r,r")
9865            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
9866    (clobber (reg:CC CC_REGNUM))]
9867   "TARGET_ARM"
9868   "#"
9869   [(set_attr "conds" "clob")
9870    (set_attr "length" "8,12")]
9873 (define_insn "*if_move_shift"
9874   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9875         (if_then_else:SI
9876          (match_operator 5 "arm_comparison_operator"
9877           [(match_operand 6 "cc_register" "") (const_int 0)])
9878          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9879          (match_operator:SI 4 "shift_operator"
9880           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9881            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
9882   "TARGET_ARM"
9883   "@
9884    mov%D5\\t%0, %2%S4
9885    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9886    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
9887   [(set_attr "conds" "use")
9888    (set_attr "shift" "2")
9889    (set_attr "length" "4,8,8")
9890    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9891                       (const_string "alu_shift")
9892                       (const_string "alu_shift_reg")))]
9895 (define_insn "*ifcompare_shift_shift"
9896   [(set (match_operand:SI 0 "s_register_operand" "=r")
9897         (if_then_else:SI
9898          (match_operator 7 "arm_comparison_operator"
9899           [(match_operand:SI 5 "s_register_operand" "r")
9900            (match_operand:SI 6 "arm_add_operand" "rIL")])
9901          (match_operator:SI 8 "shift_operator"
9902           [(match_operand:SI 1 "s_register_operand" "r")
9903            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9904          (match_operator:SI 9 "shift_operator"
9905           [(match_operand:SI 3 "s_register_operand" "r")
9906            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
9907    (clobber (reg:CC CC_REGNUM))]
9908   "TARGET_ARM"
9909   "#"
9910   [(set_attr "conds" "clob")
9911    (set_attr "length" "12")]
9914 (define_insn "*if_shift_shift"
9915   [(set (match_operand:SI 0 "s_register_operand" "=r")
9916         (if_then_else:SI
9917          (match_operator 5 "arm_comparison_operator"
9918           [(match_operand 8 "cc_register" "") (const_int 0)])
9919          (match_operator:SI 6 "shift_operator"
9920           [(match_operand:SI 1 "s_register_operand" "r")
9921            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9922          (match_operator:SI 7 "shift_operator"
9923           [(match_operand:SI 3 "s_register_operand" "r")
9924            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
9925   "TARGET_ARM"
9926   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
9927   [(set_attr "conds" "use")
9928    (set_attr "shift" "1")
9929    (set_attr "length" "8")
9930    (set (attr "type") (if_then_else
9931                         (and (match_operand 2 "const_int_operand" "")
9932                              (match_operand 4 "const_int_operand" ""))
9933                       (const_string "alu_shift")
9934                       (const_string "alu_shift_reg")))]
9937 (define_insn "*ifcompare_not_arith"
9938   [(set (match_operand:SI 0 "s_register_operand" "=r")
9939         (if_then_else:SI
9940          (match_operator 6 "arm_comparison_operator"
9941           [(match_operand:SI 4 "s_register_operand" "r")
9942            (match_operand:SI 5 "arm_add_operand" "rIL")])
9943          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9944          (match_operator:SI 7 "shiftable_operator"
9945           [(match_operand:SI 2 "s_register_operand" "r")
9946            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
9947    (clobber (reg:CC CC_REGNUM))]
9948   "TARGET_ARM"
9949   "#"
9950   [(set_attr "conds" "clob")
9951    (set_attr "length" "12")]
9954 (define_insn "*if_not_arith"
9955   [(set (match_operand:SI 0 "s_register_operand" "=r")
9956         (if_then_else:SI
9957          (match_operator 5 "arm_comparison_operator"
9958           [(match_operand 4 "cc_register" "") (const_int 0)])
9959          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9960          (match_operator:SI 6 "shiftable_operator"
9961           [(match_operand:SI 2 "s_register_operand" "r")
9962            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
9963   "TARGET_ARM"
9964   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
9965   [(set_attr "conds" "use")
9966    (set_attr "length" "8")]
9969 (define_insn "*ifcompare_arith_not"
9970   [(set (match_operand:SI 0 "s_register_operand" "=r")
9971         (if_then_else:SI
9972          (match_operator 6 "arm_comparison_operator"
9973           [(match_operand:SI 4 "s_register_operand" "r")
9974            (match_operand:SI 5 "arm_add_operand" "rIL")])
9975          (match_operator:SI 7 "shiftable_operator"
9976           [(match_operand:SI 2 "s_register_operand" "r")
9977            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9978          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9979    (clobber (reg:CC CC_REGNUM))]
9980   "TARGET_ARM"
9981   "#"
9982   [(set_attr "conds" "clob")
9983    (set_attr "length" "12")]
9986 (define_insn "*if_arith_not"
9987   [(set (match_operand:SI 0 "s_register_operand" "=r")
9988         (if_then_else:SI
9989          (match_operator 5 "arm_comparison_operator"
9990           [(match_operand 4 "cc_register" "") (const_int 0)])
9991          (match_operator:SI 6 "shiftable_operator"
9992           [(match_operand:SI 2 "s_register_operand" "r")
9993            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9994          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9995   "TARGET_ARM"
9996   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9997   [(set_attr "conds" "use")
9998    (set_attr "length" "8")]
10001 (define_insn "*ifcompare_neg_move"
10002   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10003         (if_then_else:SI
10004          (match_operator 5 "arm_comparison_operator"
10005           [(match_operand:SI 3 "s_register_operand" "r,r")
10006            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10007          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10008          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
10009    (clobber (reg:CC CC_REGNUM))]
10010   "TARGET_ARM"
10011   "#"
10012   [(set_attr "conds" "clob")
10013    (set_attr "length" "8,12")]
10016 (define_insn "*if_neg_move"
10017   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10018         (if_then_else:SI
10019          (match_operator 4 "arm_comparison_operator"
10020           [(match_operand 3 "cc_register" "") (const_int 0)])
10021          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10022          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
10023   "TARGET_ARM"
10024   "@
10025    rsb%d4\\t%0, %2, #0
10026    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
10027    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
10028   [(set_attr "conds" "use")
10029    (set_attr "length" "4,8,8")]
10032 (define_insn "*ifcompare_move_neg"
10033   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10034         (if_then_else:SI
10035          (match_operator 5 "arm_comparison_operator"
10036           [(match_operand:SI 3 "s_register_operand" "r,r")
10037            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10038          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10039          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
10040    (clobber (reg:CC CC_REGNUM))]
10041   "TARGET_ARM"
10042   "#"
10043   [(set_attr "conds" "clob")
10044    (set_attr "length" "8,12")]
10047 (define_insn "*if_move_neg"
10048   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10049         (if_then_else:SI
10050          (match_operator 4 "arm_comparison_operator"
10051           [(match_operand 3 "cc_register" "") (const_int 0)])
10052          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10053          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
10054   "TARGET_ARM"
10055   "@
10056    rsb%D4\\t%0, %2, #0
10057    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
10058    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
10059   [(set_attr "conds" "use")
10060    (set_attr "length" "4,8,8")]
10063 (define_insn "*arith_adjacentmem"
10064   [(set (match_operand:SI 0 "s_register_operand" "=r")
10065         (match_operator:SI 1 "shiftable_operator"
10066          [(match_operand:SI 2 "memory_operand" "m")
10067           (match_operand:SI 3 "memory_operand" "m")]))
10068    (clobber (match_scratch:SI 4 "=r"))]
10069   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
10070   "*
10071   {
10072     rtx ldm[3];
10073     rtx arith[4];
10074     rtx base_reg;
10075     HOST_WIDE_INT val1 = 0, val2 = 0;
10077     if (REGNO (operands[0]) > REGNO (operands[4]))
10078       {
10079         ldm[1] = operands[4];
10080         ldm[2] = operands[0];
10081       }
10082     else
10083       {
10084         ldm[1] = operands[0];
10085         ldm[2] = operands[4];
10086       }
10088     base_reg = XEXP (operands[2], 0);
10090     if (!REG_P (base_reg))
10091       {
10092         val1 = INTVAL (XEXP (base_reg, 1));
10093         base_reg = XEXP (base_reg, 0);
10094       }
10096     if (!REG_P (XEXP (operands[3], 0)))
10097       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
10099     arith[0] = operands[0];
10100     arith[3] = operands[1];
10102     if (val1 < val2)
10103       {
10104         arith[1] = ldm[1];
10105         arith[2] = ldm[2];
10106       }
10107     else
10108       {
10109         arith[1] = ldm[2];
10110         arith[2] = ldm[1];
10111       }
10113     ldm[0] = base_reg;
10114     if (val1 !=0 && val2 != 0)
10115       {
10116         rtx ops[3];
10118         if (val1 == 4 || val2 == 4)
10119           /* Other val must be 8, since we know they are adjacent and neither
10120              is zero.  */
10121           output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
10122         else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
10123           {
10124             ldm[0] = ops[0] = operands[4];
10125             ops[1] = base_reg;
10126             ops[2] = GEN_INT (val1);
10127             output_add_immediate (ops);
10128             if (val1 < val2)
10129               output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
10130             else
10131               output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
10132           }
10133         else
10134           {
10135             /* Offset is out of range for a single add, so use two ldr.  */
10136             ops[0] = ldm[1];
10137             ops[1] = base_reg;
10138             ops[2] = GEN_INT (val1);
10139             output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10140             ops[0] = ldm[2];
10141             ops[2] = GEN_INT (val2);
10142             output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10143           }
10144       }
10145     else if (val1 != 0)
10146       {
10147         if (val1 < val2)
10148           output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
10149         else
10150           output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
10151       }
10152     else
10153       {
10154         if (val1 < val2)
10155           output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
10156         else
10157           output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
10158       }
10159     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10160     return \"\";
10161   }"
10162   [(set_attr "length" "12")
10163    (set_attr "predicable" "yes")
10164    (set_attr "type" "load1")]
10167 ; This pattern is never tried by combine, so do it as a peephole
10169 (define_peephole2
10170   [(set (match_operand:SI 0 "arm_general_register_operand" "")
10171         (match_operand:SI 1 "arm_general_register_operand" ""))
10172    (set (reg:CC CC_REGNUM)
10173         (compare:CC (match_dup 1) (const_int 0)))]
10174   "TARGET_ARM"
10175   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10176               (set (match_dup 0) (match_dup 1))])]
10177   ""
10180 ; Peepholes to spot possible load- and store-multiples, if the ordering is
10181 ; reversed, check that the memory references aren't volatile.
10183 (define_peephole
10184   [(set (match_operand:SI 0 "s_register_operand" "=r")
10185         (match_operand:SI 4 "memory_operand" "m"))
10186    (set (match_operand:SI 1 "s_register_operand" "=r")
10187         (match_operand:SI 5 "memory_operand" "m"))
10188    (set (match_operand:SI 2 "s_register_operand" "=r")
10189         (match_operand:SI 6 "memory_operand" "m"))
10190    (set (match_operand:SI 3 "s_register_operand" "=r")
10191         (match_operand:SI 7 "memory_operand" "m"))]
10192   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
10193   "*
10194   return emit_ldm_seq (operands, 4);
10195   "
10198 (define_peephole
10199   [(set (match_operand:SI 0 "s_register_operand" "=r")
10200         (match_operand:SI 3 "memory_operand" "m"))
10201    (set (match_operand:SI 1 "s_register_operand" "=r")
10202         (match_operand:SI 4 "memory_operand" "m"))
10203    (set (match_operand:SI 2 "s_register_operand" "=r")
10204         (match_operand:SI 5 "memory_operand" "m"))]
10205   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
10206   "*
10207   return emit_ldm_seq (operands, 3);
10208   "
10211 (define_peephole
10212   [(set (match_operand:SI 0 "s_register_operand" "=r")
10213         (match_operand:SI 2 "memory_operand" "m"))
10214    (set (match_operand:SI 1 "s_register_operand" "=r")
10215         (match_operand:SI 3 "memory_operand" "m"))]
10216   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
10217   "*
10218   return emit_ldm_seq (operands, 2);
10219   "
10222 (define_peephole
10223   [(set (match_operand:SI 4 "memory_operand" "=m")
10224         (match_operand:SI 0 "s_register_operand" "r"))
10225    (set (match_operand:SI 5 "memory_operand" "=m")
10226         (match_operand:SI 1 "s_register_operand" "r"))
10227    (set (match_operand:SI 6 "memory_operand" "=m")
10228         (match_operand:SI 2 "s_register_operand" "r"))
10229    (set (match_operand:SI 7 "memory_operand" "=m")
10230         (match_operand:SI 3 "s_register_operand" "r"))]
10231   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
10232   "*
10233   return emit_stm_seq (operands, 4);
10234   "
10237 (define_peephole
10238   [(set (match_operand:SI 3 "memory_operand" "=m")
10239         (match_operand:SI 0 "s_register_operand" "r"))
10240    (set (match_operand:SI 4 "memory_operand" "=m")
10241         (match_operand:SI 1 "s_register_operand" "r"))
10242    (set (match_operand:SI 5 "memory_operand" "=m")
10243         (match_operand:SI 2 "s_register_operand" "r"))]
10244   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
10245   "*
10246   return emit_stm_seq (operands, 3);
10247   "
10250 (define_peephole
10251   [(set (match_operand:SI 2 "memory_operand" "=m")
10252         (match_operand:SI 0 "s_register_operand" "r"))
10253    (set (match_operand:SI 3 "memory_operand" "=m")
10254         (match_operand:SI 1 "s_register_operand" "r"))]
10255   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
10256   "*
10257   return emit_stm_seq (operands, 2);
10258   "
10261 (define_split
10262   [(set (match_operand:SI 0 "s_register_operand" "")
10263         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10264                        (const_int 0))
10265                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
10266                          [(match_operand:SI 3 "s_register_operand" "")
10267                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
10268    (clobber (match_operand:SI 5 "s_register_operand" ""))]
10269   "TARGET_ARM"
10270   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10271    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10272                               (match_dup 5)))]
10273   ""
10276 ;; This split can be used because CC_Z mode implies that the following
10277 ;; branch will be an equality, or an unsigned inequality, so the sign
10278 ;; extension is not needed.
10280 (define_split
10281   [(set (reg:CC_Z CC_REGNUM)
10282         (compare:CC_Z
10283          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
10284                     (const_int 24))
10285          (match_operand 1 "const_int_operand" "")))
10286    (clobber (match_scratch:SI 2 ""))]
10287   "TARGET_ARM
10288    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10289        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
10290   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
10291    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
10292   "
10293   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
10294   "
10296 ;; ??? Check the patterns above for Thumb-2 usefulness
10298 (define_expand "prologue"
10299   [(clobber (const_int 0))]
10300   "TARGET_EITHER"
10301   "if (TARGET_32BIT)
10302      arm_expand_prologue ();
10303    else
10304      thumb1_expand_prologue ();
10305   DONE;
10306   "
10309 (define_expand "epilogue"
10310   [(clobber (const_int 0))]
10311   "TARGET_EITHER"
10312   "
10313   if (current_function_calls_eh_return)
10314     emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
10315   if (TARGET_THUMB1)
10316     thumb1_expand_epilogue ();
10317   else if (USE_RETURN_INSN (FALSE))
10318     {
10319       emit_jump_insn (gen_return ());
10320       DONE;
10321     }
10322   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10323         gen_rtvec (1,
10324                 gen_rtx_RETURN (VOIDmode)),
10325         VUNSPEC_EPILOGUE));
10326   DONE;
10327   "
10330 ;; Note - although unspec_volatile's USE all hard registers,
10331 ;; USEs are ignored after relaod has completed.  Thus we need
10332 ;; to add an unspec of the link register to ensure that flow
10333 ;; does not think that it is unused by the sibcall branch that
10334 ;; will replace the standard function epilogue.
10335 (define_insn "sibcall_epilogue"
10336   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
10337               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10338   "TARGET_32BIT"
10339   "*
10340   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
10341     return output_return_instruction (const_true_rtx, FALSE, FALSE);
10342   return arm_output_epilogue (next_nonnote_insn (insn));
10343   "
10344 ;; Length is absolute worst case
10345   [(set_attr "length" "44")
10346    (set_attr "type" "block")
10347    ;; We don't clobber the conditions, but the potential length of this
10348    ;; operation is sufficient to make conditionalizing the sequence 
10349    ;; unlikely to be profitable.
10350    (set_attr "conds" "clob")]
10353 (define_insn "*epilogue_insns"
10354   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
10355   "TARGET_EITHER"
10356   "*
10357   if (TARGET_32BIT)
10358     return arm_output_epilogue (NULL);
10359   else /* TARGET_THUMB1 */
10360     return thumb_unexpanded_epilogue ();
10361   "
10362   ; Length is absolute worst case
10363   [(set_attr "length" "44")
10364    (set_attr "type" "block")
10365    ;; We don't clobber the conditions, but the potential length of this
10366    ;; operation is sufficient to make conditionalizing the sequence 
10367    ;; unlikely to be profitable.
10368    (set_attr "conds" "clob")]
10371 (define_expand "eh_epilogue"
10372   [(use (match_operand:SI 0 "register_operand" ""))
10373    (use (match_operand:SI 1 "register_operand" ""))
10374    (use (match_operand:SI 2 "register_operand" ""))]
10375   "TARGET_EITHER"
10376   "
10377   {
10378     cfun->machine->eh_epilogue_sp_ofs = operands[1];
10379     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10380       {
10381         rtx ra = gen_rtx_REG (Pmode, 2);
10383         emit_move_insn (ra, operands[2]);
10384         operands[2] = ra;
10385       }
10386     /* This is a hack -- we may have crystalized the function type too
10387        early.  */
10388     cfun->machine->func_type = 0;
10389   }"
10392 ;; This split is only used during output to reduce the number of patterns
10393 ;; that need assembler instructions adding to them.  We allowed the setting
10394 ;; of the conditions to be implicit during rtl generation so that
10395 ;; the conditional compare patterns would work.  However this conflicts to
10396 ;; some extent with the conditional data operations, so we have to split them
10397 ;; up again here.
10399 ;; ??? Need to audit these splitters for Thumb-2.  Why isn't normal
10400 ;; conditional execution sufficient?
10402 (define_split
10403   [(set (match_operand:SI 0 "s_register_operand" "")
10404         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10405                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10406                          (match_dup 0)
10407                          (match_operand 4 "" "")))
10408    (clobber (reg:CC CC_REGNUM))]
10409   "TARGET_ARM && reload_completed"
10410   [(set (match_dup 5) (match_dup 6))
10411    (cond_exec (match_dup 7)
10412               (set (match_dup 0) (match_dup 4)))]
10413   "
10414   {
10415     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10416                                              operands[2], operands[3]);
10417     enum rtx_code rc = GET_CODE (operands[1]);
10419     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10420     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10421     if (mode == CCFPmode || mode == CCFPEmode)
10422       rc = reverse_condition_maybe_unordered (rc);
10423     else
10424       rc = reverse_condition (rc);
10426     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10427   }"
10430 (define_split
10431   [(set (match_operand:SI 0 "s_register_operand" "")
10432         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10433                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10434                          (match_operand 4 "" "")
10435                          (match_dup 0)))
10436    (clobber (reg:CC CC_REGNUM))]
10437   "TARGET_ARM && reload_completed"
10438   [(set (match_dup 5) (match_dup 6))
10439    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10440               (set (match_dup 0) (match_dup 4)))]
10441   "
10442   {
10443     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10444                                              operands[2], operands[3]);
10446     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10447     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10448   }"
10451 (define_split
10452   [(set (match_operand:SI 0 "s_register_operand" "")
10453         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10454                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10455                          (match_operand 4 "" "")
10456                          (match_operand 5 "" "")))
10457    (clobber (reg:CC CC_REGNUM))]
10458   "TARGET_ARM && reload_completed"
10459   [(set (match_dup 6) (match_dup 7))
10460    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10461               (set (match_dup 0) (match_dup 4)))
10462    (cond_exec (match_dup 8)
10463               (set (match_dup 0) (match_dup 5)))]
10464   "
10465   {
10466     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10467                                              operands[2], operands[3]);
10468     enum rtx_code rc = GET_CODE (operands[1]);
10470     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10471     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10472     if (mode == CCFPmode || mode == CCFPEmode)
10473       rc = reverse_condition_maybe_unordered (rc);
10474     else
10475       rc = reverse_condition (rc);
10477     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10478   }"
10481 (define_split
10482   [(set (match_operand:SI 0 "s_register_operand" "")
10483         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10484                           [(match_operand:SI 2 "s_register_operand" "")
10485                            (match_operand:SI 3 "arm_add_operand" "")])
10486                          (match_operand:SI 4 "arm_rhs_operand" "")
10487                          (not:SI
10488                           (match_operand:SI 5 "s_register_operand" ""))))
10489    (clobber (reg:CC CC_REGNUM))]
10490   "TARGET_ARM && reload_completed"
10491   [(set (match_dup 6) (match_dup 7))
10492    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10493               (set (match_dup 0) (match_dup 4)))
10494    (cond_exec (match_dup 8)
10495               (set (match_dup 0) (not:SI (match_dup 5))))]
10496   "
10497   {
10498     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10499                                              operands[2], operands[3]);
10500     enum rtx_code rc = GET_CODE (operands[1]);
10502     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10503     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10504     if (mode == CCFPmode || mode == CCFPEmode)
10505       rc = reverse_condition_maybe_unordered (rc);
10506     else
10507       rc = reverse_condition (rc);
10509     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10510   }"
10513 (define_insn "*cond_move_not"
10514   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10515         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10516                           [(match_operand 3 "cc_register" "") (const_int 0)])
10517                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10518                          (not:SI
10519                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
10520   "TARGET_ARM"
10521   "@
10522    mvn%D4\\t%0, %2
10523    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
10524   [(set_attr "conds" "use")
10525    (set_attr "length" "4,8")]
10528 ;; The next two patterns occur when an AND operation is followed by a
10529 ;; scc insn sequence 
10531 (define_insn "*sign_extract_onebit"
10532   [(set (match_operand:SI 0 "s_register_operand" "=r")
10533         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10534                          (const_int 1)
10535                          (match_operand:SI 2 "const_int_operand" "n")))
10536     (clobber (reg:CC CC_REGNUM))]
10537   "TARGET_ARM"
10538   "*
10539     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10540     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10541     return \"mvnne\\t%0, #0\";
10542   "
10543   [(set_attr "conds" "clob")
10544    (set_attr "length" "8")]
10547 (define_insn "*not_signextract_onebit"
10548   [(set (match_operand:SI 0 "s_register_operand" "=r")
10549         (not:SI
10550          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10551                           (const_int 1)
10552                           (match_operand:SI 2 "const_int_operand" "n"))))
10553    (clobber (reg:CC CC_REGNUM))]
10554   "TARGET_ARM"
10555   "*
10556     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10557     output_asm_insn (\"tst\\t%1, %2\", operands);
10558     output_asm_insn (\"mvneq\\t%0, #0\", operands);
10559     return \"movne\\t%0, #0\";
10560   "
10561   [(set_attr "conds" "clob")
10562    (set_attr "length" "12")]
10564 ;; ??? The above patterns need auditing for Thumb-2
10566 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
10567 ;; expressions.  For simplicity, the first register is also in the unspec
10568 ;; part.
10569 (define_insn "*push_multi"
10570   [(match_parallel 2 "multi_register_push"
10571     [(set (match_operand:BLK 0 "memory_operand" "=m")
10572           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
10573                       UNSPEC_PUSH_MULT))])]
10574   "TARGET_32BIT"
10575   "*
10576   {
10577     int num_saves = XVECLEN (operands[2], 0);
10578      
10579     /* For the StrongARM at least it is faster to
10580        use STR to store only a single register.
10581        In Thumb mode always use push, and the assembler will pick
10582        something appropriate.  */
10583     if (num_saves == 1 && TARGET_ARM)
10584       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10585     else
10586       {
10587         int i;
10588         char pattern[100];
10590         if (TARGET_ARM)
10591             strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10592         else
10593             strcpy (pattern, \"push\\t{%1\");
10595         for (i = 1; i < num_saves; i++)
10596           {
10597             strcat (pattern, \", %|\");
10598             strcat (pattern,
10599                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10600           }
10602         strcat (pattern, \"}\");
10603         output_asm_insn (pattern, operands);
10604       }
10606     return \"\";
10607   }"
10608   [(set_attr "type" "store4")]
10611 (define_insn "stack_tie"
10612   [(set (mem:BLK (scratch))
10613         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
10614                      (match_operand:SI 1 "s_register_operand" "r")]
10615                     UNSPEC_PRLG_STK))]
10616   ""
10617   ""
10618   [(set_attr "length" "0")]
10621 ;; Similarly for the floating point registers
10622 (define_insn "*push_fp_multi"
10623   [(match_parallel 2 "multi_register_push"
10624     [(set (match_operand:BLK 0 "memory_operand" "=m")
10625           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10626                       UNSPEC_PUSH_MULT))])]
10627   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
10628   "*
10629   {
10630     char pattern[100];
10632     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10633     output_asm_insn (pattern, operands);
10634     return \"\";
10635   }"
10636   [(set_attr "type" "f_store")]
10639 ;; Special patterns for dealing with the constant pool
10641 (define_insn "align_4"
10642   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10643   "TARGET_EITHER"
10644   "*
10645   assemble_align (32);
10646   return \"\";
10647   "
10650 (define_insn "align_8"
10651   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10652   "TARGET_EITHER"
10653   "*
10654   assemble_align (64);
10655   return \"\";
10656   "
10659 (define_insn "consttable_end"
10660   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10661   "TARGET_EITHER"
10662   "*
10663   making_const_table = FALSE;
10664   return \"\";
10665   "
10668 (define_insn "consttable_1"
10669   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10670   "TARGET_THUMB1"
10671   "*
10672   making_const_table = TRUE;
10673   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10674   assemble_zeros (3);
10675   return \"\";
10676   "
10677   [(set_attr "length" "4")]
10680 (define_insn "consttable_2"
10681   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10682   "TARGET_THUMB1"
10683   "*
10684   making_const_table = TRUE;
10685   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10686   assemble_zeros (2);
10687   return \"\";
10688   "
10689   [(set_attr "length" "4")]
10692 (define_insn "consttable_4"
10693   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10694   "TARGET_EITHER"
10695   "*
10696   {
10697     making_const_table = TRUE;
10698     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10699       {
10700       case MODE_FLOAT:
10701       {
10702         REAL_VALUE_TYPE r;
10703         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10704         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10705         break;
10706       }
10707       default:
10708         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
10709         break;
10710       }
10711     return \"\";
10712   }"
10713   [(set_attr "length" "4")]
10716 (define_insn "consttable_8"
10717   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10718   "TARGET_EITHER"
10719   "*
10720   {
10721     making_const_table = TRUE;
10722     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10723       {
10724        case MODE_FLOAT:
10725         {
10726           REAL_VALUE_TYPE r;
10727           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10728           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10729           break;
10730         }
10731       default:
10732         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10733         break;
10734       }
10735     return \"\";
10736   }"
10737   [(set_attr "length" "8")]
10740 (define_insn "consttable_16"
10741   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
10742   "TARGET_EITHER"
10743   "*
10744   {
10745     making_const_table = TRUE;
10746     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10747       {
10748        case MODE_FLOAT:
10749         {
10750           REAL_VALUE_TYPE r;
10751           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10752           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10753           break;
10754         }
10755       default:
10756         assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
10757         break;
10758       }
10759     return \"\";
10760   }"
10761   [(set_attr "length" "16")]
10764 ;; Miscellaneous Thumb patterns
10766 (define_expand "tablejump"
10767   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10768               (use (label_ref (match_operand 1 "" "")))])]
10769   "TARGET_THUMB1"
10770   "
10771   if (flag_pic)
10772     {
10773       /* Hopefully, CSE will eliminate this copy.  */
10774       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10775       rtx reg2 = gen_reg_rtx (SImode);
10777       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10778       operands[0] = reg2;
10779     }
10780   "
10783 ;; NB never uses BX.
10784 (define_insn "*thumb1_tablejump"
10785   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10786    (use (label_ref (match_operand 1 "" "")))]
10787   "TARGET_THUMB1"
10788   "mov\\t%|pc, %0"
10789   [(set_attr "length" "2")]
10792 ;; V5 Instructions,
10794 (define_insn "clzsi2"
10795   [(set (match_operand:SI 0 "s_register_operand" "=r")
10796         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10797   "TARGET_32BIT && arm_arch5"
10798   "clz%?\\t%0, %1"
10799   [(set_attr "predicable" "yes")
10800    (set_attr "insn" "clz")])
10802 ;; V5E instructions.
10804 (define_insn "prefetch"
10805   [(prefetch (match_operand:SI 0 "address_operand" "p")
10806              (match_operand:SI 1 "" "")
10807              (match_operand:SI 2 "" ""))]
10808   "TARGET_32BIT && arm_arch5e"
10809   "pld\\t%a0")
10811 ;; General predication pattern
10813 (define_cond_exec
10814   [(match_operator 0 "arm_comparison_operator"
10815     [(match_operand 1 "cc_register" "")
10816      (const_int 0)])]
10817   "TARGET_32BIT"
10818   ""
10821 (define_insn "prologue_use"
10822   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10823   ""
10824   "%@ %0 needed for prologue"
10828 ;; Patterns for exception handling
10830 (define_expand "eh_return"
10831   [(use (match_operand 0 "general_operand" ""))]
10832   "TARGET_EITHER"
10833   "
10834   {
10835     if (TARGET_32BIT)
10836       emit_insn (gen_arm_eh_return (operands[0]));
10837     else
10838       emit_insn (gen_thumb_eh_return (operands[0]));
10839     DONE;
10840   }"
10842                                    
10843 ;; We can't expand this before we know where the link register is stored.
10844 (define_insn_and_split "arm_eh_return"
10845   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10846                     VUNSPEC_EH_RETURN)
10847    (clobber (match_scratch:SI 1 "=&r"))]
10848   "TARGET_ARM"
10849   "#"
10850   "&& reload_completed"
10851   [(const_int 0)]
10852   "
10853   {
10854     arm_set_return_address (operands[0], operands[1]);
10855     DONE;
10856   }"
10859 (define_insn_and_split "thumb_eh_return"
10860   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10861                     VUNSPEC_EH_RETURN)
10862    (clobber (match_scratch:SI 1 "=&l"))]
10863   "TARGET_THUMB1"
10864   "#"
10865   "&& reload_completed"
10866   [(const_int 0)]
10867   "
10868   {
10869     thumb_set_return_address (operands[0], operands[1]);
10870     DONE;
10871   }"
10875 ;; TLS support
10877 (define_insn "load_tp_hard"
10878   [(set (match_operand:SI 0 "register_operand" "=r")
10879         (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10880   "TARGET_HARD_TP"
10881   "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
10882   [(set_attr "predicable" "yes")]
10885 ;; Doesn't clobber R1-R3.  Must use r0 for the first operand.
10886 (define_insn "load_tp_soft"
10887   [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10888    (clobber (reg:SI LR_REGNUM))
10889    (clobber (reg:SI IP_REGNUM))
10890    (clobber (reg:CC CC_REGNUM))]
10891   "TARGET_SOFT_TP"
10892   "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
10893   [(set_attr "conds" "clob")]
10896 ;; Load the FPA co-processor patterns
10897 (include "fpa.md")
10898 ;; Load the Maverick co-processor patterns
10899 (include "cirrus.md")
10900 ;; Vector bits common to IWMMXT and Neon
10901 (include "vec-common.md")
10902 ;; Load the Intel Wireless Multimedia Extension patterns
10903 (include "iwmmxt.md")
10904 ;; Load the VFP co-processor patterns
10905 (include "vfp.md")
10906 ;; Thumb-2 patterns
10907 (include "thumb2.md")
10908 ;; Neon patterns
10909 (include "neon.md")