OSDN Git Service

gcc/
[pf3gnuchains/gcc-fork.git] / gcc / config / arm / arm.md
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, 2008, 2009, 2010
4 ;;  Free Software Foundation, Inc.
5 ;;  Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
6 ;;  and Martin Simmons (@harleqn.co.uk).
7 ;;  More major hacks by Richard Earnshaw (rearnsha@arm.com).
8
9 ;; This file is part of GCC.
10
11 ;; GCC is free software; you can redistribute it and/or modify it
12 ;; under the terms of the GNU General Public License as published
13 ;; by the Free Software Foundation; either version 3, or (at your
14 ;; option) any later version.
15
16 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
17 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
19 ;; License for more details.
20
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GCC; see the file COPYING3.  If not see
23 ;; <http://www.gnu.org/licenses/>.
24
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26
27 \f
28 ;;---------------------------------------------------------------------------
29 ;; Constants
30
31 ;; Register numbers
32 (define_constants
33   [(R0_REGNUM        0)         ; First CORE register
34    (IP_REGNUM       12)         ; Scratch register
35    (SP_REGNUM       13)         ; Stack pointer
36    (LR_REGNUM       14)         ; Return address register
37    (PC_REGNUM       15)         ; Program counter
38    (CC_REGNUM       24)         ; Condition code pseudo register
39    (LAST_ARM_REGNUM 15)         ;
40    (FPA_F0_REGNUM   16)         ; FIRST_FPA_REGNUM
41    (FPA_F7_REGNUM   23)         ; LAST_FPA_REGNUM
42   ]
43 )
44 ;; 3rd operand to select_dominance_cc_mode
45 (define_constants
46   [(DOM_CC_X_AND_Y  0)
47    (DOM_CC_NX_OR_Y  1)
48    (DOM_CC_X_OR_Y   2)
49   ]
50 )
51
52 ;; UNSPEC Usage:
53 ;; Note: sin and cos are no-longer used.
54 ;; Unspec constants for Neon are defined in neon.md.
55
56 (define_constants
57   [(UNSPEC_SIN       0) ; `sin' operation (MODE_FLOAT):
58                         ;   operand 0 is the result,
59                         ;   operand 1 the parameter.
60    (UNPSEC_COS       1) ; `cos' operation (MODE_FLOAT):
61                         ;   operand 0 is the result,
62                         ;   operand 1 the parameter.
63    (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
64                         ;   operand 0 is the first register,
65                         ;   subsequent registers are in parallel (use ...)
66                         ;   expressions.
67    (UNSPEC_PIC_SYM   3) ; A symbol that has been treated properly for pic
68                         ;   usage, that is, we will add the pic_register
69                         ;   value to it before trying to dereference it.
70    (UNSPEC_PIC_BASE  4) ; Add PC and all but the last operand together,
71                         ;   The last operand is the number of a PIC_LABEL
72                         ;   that points at the containing instruction.
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 22) ; Doubleword aligned stack pointer.  Used to
97                            ; generate correct unwind information.
98    (UNSPEC_PIC_OFFSET 23) ; A symbolic 12-bit OFFSET that has been treated
99                           ; correctly for PIC usage.
100    (UNSPEC_GOTSYM_OFF 24) ; The offset of the start of the the GOT from a
101                           ; a given symbolic address.
102    (UNSPEC_THUMB1_CASESI 25) ; A Thumb1 compressed dispatch-table call.
103    (UNSPEC_RBIT 26)       ; rbit operation.
104    (UNSPEC_SYMBOL_OFFSET 27) ; The offset of the start of the symbol from
105                              ; another symbolic address.
106   ]
107 )
108
109 ;; UNSPEC_VOLATILE Usage:
110
111 (define_constants
112   [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
113                         ;   insn in the code.
114    (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
115                         ;   instruction epilogue sequence that isn't expanded
116                         ;   into normal RTL.  Used for both normal and sibcall
117                         ;   epilogues.
118    (VUNSPEC_ALIGN    2) ; `align' insn.  Used at the head of a minipool table 
119                         ;   for inlined constants.
120    (VUNSPEC_POOL_END 3) ; `end-of-table'.  Used to mark the end of a minipool
121                         ;   table.
122    (VUNSPEC_POOL_1   4) ; `pool-entry(1)'.  An entry in the constant pool for
123                         ;   an 8-bit object.
124    (VUNSPEC_POOL_2   5) ; `pool-entry(2)'.  An entry in the constant pool for
125                         ;   a 16-bit object.
126    (VUNSPEC_POOL_4   6) ; `pool-entry(4)'.  An entry in the constant pool for
127                         ;   a 32-bit object.
128    (VUNSPEC_POOL_8   7) ; `pool-entry(8)'.  An entry in the constant pool for
129                         ;   a 64-bit object.
130    (VUNSPEC_POOL_16  8) ; `pool-entry(16)'.  An entry in the constant pool for
131                         ;   a 128-bit object.
132    (VUNSPEC_TMRC     9) ; Used by the iWMMXt TMRC instruction.
133    (VUNSPEC_TMCR     10) ; Used by the iWMMXt TMCR instruction.
134    (VUNSPEC_ALIGN8   11) ; 8-byte alignment version of VUNSPEC_ALIGN
135    (VUNSPEC_WCMP_EQ  12) ; Used by the iWMMXt WCMPEQ instructions
136    (VUNSPEC_WCMP_GTU 13) ; Used by the iWMMXt WCMPGTU instructions
137    (VUNSPEC_WCMP_GT  14) ; Used by the iwMMXT WCMPGT instructions
138    (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
139                          ; handling.
140   ]
141 )
142 \f
143 ;;---------------------------------------------------------------------------
144 ;; Attributes
145
146 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
147 ; generating ARM code.  This is used to control the length of some insn
148 ; patterns that share the same RTL in both ARM and Thumb code.
149 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
150
151 ;; Operand number of an input operand that is shifted.  Zero if the
152 ;; given instruction does not shift one of its input operands.
153 (define_attr "shift" "" (const_int 0))
154
155 ; Floating Point Unit.  If we only have floating point emulation, then there
156 ; is no point in scheduling the floating point insns.  (Well, for best
157 ; performance we should try and group them together).
158 (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
159   (const (symbol_ref "arm_fpu_attr")))
160
161 ; LENGTH of an instruction (in bytes)
162 (define_attr "length" "" (const_int 4))
163
164 ; POOL_RANGE is how far away from a constant pool entry that this insn
165 ; can be placed.  If the distance is zero, then this insn will never
166 ; reference the pool.
167 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
168 ; before its address.
169 (define_attr "pool_range" "" (const_int 0))
170 (define_attr "neg_pool_range" "" (const_int 0))
171
172 ; An assembler sequence may clobber the condition codes without us knowing.
173 ; If such an insn references the pool, then we have no way of knowing how,
174 ; so use the most conservative value for pool_range.
175 (define_asm_attributes
176  [(set_attr "conds" "clob")
177   (set_attr "length" "4")
178   (set_attr "pool_range" "250")])
179
180 ;; The instruction used to implement a particular pattern.  This
181 ;; information is used by pipeline descriptions to provide accurate
182 ;; scheduling information.
183
184 (define_attr "insn"
185         "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,sdiv,udiv,other"
186         (const_string "other"))
187
188 ; TYPE attribute is used to detect floating point instructions which, if
189 ; running on a co-processor can run in parallel with other, basic instructions
190 ; If write-buffer scheduling is enabled then it can also be used in the
191 ; scheduling of writes.
192
193 ; Classification of each insn
194 ; Note: vfp.md has different meanings for some of these, and some further
195 ; types as well.  See that file for details.
196 ; alu           any alu  instruction that doesn't hit memory or fp
197 ;               regs or have a shifted source operand
198 ; alu_shift     any data instruction that doesn't hit memory or fp
199 ;               regs, but has a source operand shifted by a constant
200 ; alu_shift_reg any data instruction that doesn't hit memory or fp
201 ;               regs, but has a source operand shifted by a register value
202 ; mult          a multiply instruction
203 ; block         blockage insn, this blocks all functional units
204 ; float         a floating point arithmetic operation (subject to expansion)
205 ; fdivd         DFmode floating point division
206 ; fdivs         SFmode floating point division
207 ; fmul          Floating point multiply
208 ; ffmul         Fast floating point multiply
209 ; farith        Floating point arithmetic (4 cycle)
210 ; ffarith       Fast floating point arithmetic (2 cycle)
211 ; float_em      a floating point arithmetic operation that is normally emulated
212 ;               even on a machine with an fpa.
213 ; f_load        a floating point load from memory
214 ; f_store       a floating point store to memory
215 ; f_load[sd]    single/double load from memory
216 ; f_store[sd]   single/double store to memory
217 ; f_flag        a transfer of co-processor flags to the CPSR
218 ; f_mem_r       a transfer of a floating point register to a real reg via mem
219 ; r_mem_f       the reverse of f_mem_r
220 ; f_2_r         fast transfer float to arm (no memory needed)
221 ; r_2_f         fast transfer arm to float
222 ; f_cvt         convert floating<->integral
223 ; branch        a branch
224 ; call          a subroutine call
225 ; load_byte     load byte(s) from memory to arm registers
226 ; load1         load 1 word from memory to arm registers
227 ; load2         load 2 words from memory to arm registers
228 ; load3         load 3 words from memory to arm registers
229 ; load4         load 4 words from memory to arm registers
230 ; store         store 1 word to memory from arm registers
231 ; store2        store 2 words
232 ; store3        store 3 words
233 ; store4        store 4 (or more) words
234 ;  Additions for Cirrus Maverick co-processor:
235 ; mav_farith    Floating point arithmetic (4 cycle)
236 ; mav_dmult     Double multiplies (7 cycle)
237 ;
238
239 (define_attr "type"
240         "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,fconsts,fconstd,fadds,faddd,ffariths,ffarithd,fcmps,fcmpd,fcpys"
241         (if_then_else 
242          (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
243          (const_string "mult")
244          (const_string "alu")))
245
246 ; Load scheduling, set from the arm_ld_sched variable
247 ; initialized by arm_override_options() 
248 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
249
250 ;; Classification of NEON instructions for scheduling purposes.
251 ;; Do not set this attribute and the "type" attribute together in
252 ;; any one instruction pattern.
253 (define_attr "neon_type"
254    "neon_int_1,\
255    neon_int_2,\
256    neon_int_3,\
257    neon_int_4,\
258    neon_int_5,\
259    neon_vqneg_vqabs,\
260    neon_vmov,\
261    neon_vaba,\
262    neon_vsma,\
263    neon_vaba_qqq,\
264    neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
265    neon_mul_qqq_8_16_32_ddd_32,\
266    neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,\
267    neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
268    neon_mla_qqq_8_16,\
269    neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,\
270    neon_mla_qqq_32_qqd_32_scalar,\
271    neon_mul_ddd_16_scalar_32_16_long_scalar,\
272    neon_mul_qqd_32_scalar,\
273    neon_mla_ddd_16_scalar_qdd_32_16_long_scalar,\
274    neon_shift_1,\
275    neon_shift_2,\
276    neon_shift_3,\
277    neon_vshl_ddd,\
278    neon_vqshl_vrshl_vqrshl_qqq,\
279    neon_vsra_vrsra,\
280    neon_fp_vadd_ddd_vabs_dd,\
281    neon_fp_vadd_qqq_vabs_qq,\
282    neon_fp_vsum,\
283    neon_fp_vmul_ddd,\
284    neon_fp_vmul_qqd,\
285    neon_fp_vmla_ddd,\
286    neon_fp_vmla_qqq,\
287    neon_fp_vmla_ddd_scalar,\
288    neon_fp_vmla_qqq_scalar,\
289    neon_fp_vrecps_vrsqrts_ddd,\
290    neon_fp_vrecps_vrsqrts_qqq,\
291    neon_bp_simple,\
292    neon_bp_2cycle,\
293    neon_bp_3cycle,\
294    neon_ldr,\
295    neon_str,\
296    neon_vld1_1_2_regs,\
297    neon_vld1_3_4_regs,\
298    neon_vld2_2_regs_vld1_vld2_all_lanes,\
299    neon_vld2_4_regs,\
300    neon_vld3_vld4,\
301    neon_vst1_1_2_regs_vst2_2_regs,\
302    neon_vst1_3_4_regs,\
303    neon_vst2_4_regs_vst3_vst4,\
304    neon_vst3_vst4,\
305    neon_vld1_vld2_lane,\
306    neon_vld3_vld4_lane,\
307    neon_vst1_vst2_lane,\
308    neon_vst3_vst4_lane,\
309    neon_vld3_vld4_all_lanes,\
310    neon_mcr,\
311    neon_mcr_2_mcrr,\
312    neon_mrc,\
313    neon_mrrc,\
314    neon_ldm_2,\
315    neon_stm_2,\
316    none"
317  (const_string "none"))
318
319 ; condition codes: this one is used by final_prescan_insn to speed up
320 ; conditionalizing instructions.  It saves having to scan the rtl to see if
321 ; it uses or alters the condition codes.
322
323 ; USE means that the condition codes are used by the insn in the process of
324 ;   outputting code, this means (at present) that we can't use the insn in
325 ;   inlined branches
326 ;
327 ; SET means that the purpose of the insn is to set the condition codes in a
328 ;   well defined manner.
329 ;
330 ; CLOB means that the condition codes are altered in an undefined manner, if
331 ;   they are altered at all
332 ;
333 ; UNCONDITIONAL means the instions can not be conditionally executed.
334 ;
335 ; NOCOND means that the condition codes are neither altered nor affect the
336 ;   output of this insn
337
338 (define_attr "conds" "use,set,clob,unconditional,nocond"
339         (if_then_else (eq_attr "type" "call")
340          (const_string "clob")
341          (if_then_else (eq_attr "neon_type" "none")
342           (const_string "nocond")
343           (const_string "unconditional"))))
344
345 ; Predicable means that the insn can be conditionally executed based on
346 ; an automatically added predicate (additional patterns are generated by 
347 ; gen...).  We default to 'no' because no Thumb patterns match this rule
348 ; and not all ARM patterns do.
349 (define_attr "predicable" "no,yes" (const_string "no"))
350
351 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
352 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
353 ; suffer blockages enough to warrant modelling this (and it can adversely
354 ; affect the schedule).
355 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
356
357 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
358 ; to stall the processor.  Used with model_wbuf above.
359 (define_attr "write_conflict" "no,yes"
360   (if_then_else (eq_attr "type"
361                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
362                 (const_string "yes")
363                 (const_string "no")))
364
365 ; Classify the insns into those that take one cycle and those that take more
366 ; than one on the main cpu execution unit.
367 (define_attr "core_cycles" "single,multi"
368   (if_then_else (eq_attr "type"
369                  "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
370                 (const_string "single")
371                 (const_string "multi")))
372
373 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
374 ;; distant label.  Only applicable to Thumb code.
375 (define_attr "far_jump" "yes,no" (const_string "no"))
376
377
378 ;; The number of machine instructions this pattern expands to.
379 ;; Used for Thumb-2 conditional execution.
380 (define_attr "ce_count" "" (const_int 1))
381
382 ;;---------------------------------------------------------------------------
383 ;; Mode iterators
384
385 ; A list of modes that are exactly 64 bits in size.  We use this to expand
386 ; some splits that are the same for all modes when operating on ARM 
387 ; registers.
388 (define_mode_iterator ANY64 [DI DF V8QI V4HI V2SI V2SF])
389
390 ;; The integer modes up to word size
391 (define_mode_iterator QHSI [QI HI SI])
392
393 ;;---------------------------------------------------------------------------
394 ;; Predicates
395
396 (include "predicates.md")
397 (include "constraints.md")
398
399 ;;---------------------------------------------------------------------------
400 ;; Pipeline descriptions
401
402 ;; Processor type.  This is created automatically from arm-cores.def.
403 (include "arm-tune.md")
404
405 (define_attr "tune_cortexr4" "yes,no"
406   (const (if_then_else
407           (eq_attr "tune" "cortexr4,cortexr4f")
408           (const_string "yes")
409           (const_string "no"))))
410
411 ;; True if the generic scheduling description should be used.
412
413 (define_attr "generic_sched" "yes,no"
414   (const (if_then_else 
415           (ior (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa8,cortexa9")
416               (eq_attr "tune_cortexr4" "yes"))
417           (const_string "no")
418           (const_string "yes"))))
419
420 (define_attr "generic_vfp" "yes,no"
421   (const (if_then_else
422           (and (eq_attr "fpu" "vfp")
423                (eq_attr "tune" "!arm1020e,arm1022e,cortexa8,cortexa9")
424                (eq_attr "tune_cortexr4" "no"))
425           (const_string "yes")
426           (const_string "no"))))
427
428 (include "arm-generic.md")
429 (include "arm926ejs.md")
430 (include "arm1020e.md")
431 (include "arm1026ejs.md")
432 (include "arm1136jfs.md")
433 (include "cortex-a8.md")
434 (include "cortex-a9.md")
435 (include "cortex-r4.md")
436 (include "cortex-r4f.md")
437 (include "vfp11.md")
438
439 \f
440 ;;---------------------------------------------------------------------------
441 ;; Insn patterns
442 ;;
443 ;; Addition insns.
444
445 ;; Note: For DImode insns, there is normally no reason why operands should
446 ;; not be in the same register, what we don't want is for something being
447 ;; written to partially overlap something that is an input.
448 ;; Cirrus 64bit additions should not be split because we have a native
449 ;; 64bit addition instructions.
450
451 (define_expand "adddi3"
452  [(parallel
453    [(set (match_operand:DI           0 "s_register_operand" "")
454           (plus:DI (match_operand:DI 1 "s_register_operand" "")
455                    (match_operand:DI 2 "s_register_operand" "")))
456     (clobber (reg:CC CC_REGNUM))])]
457   "TARGET_EITHER"
458   "
459   if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
460     {
461       if (!cirrus_fp_register (operands[0], DImode))
462         operands[0] = force_reg (DImode, operands[0]);
463       if (!cirrus_fp_register (operands[1], DImode))
464         operands[1] = force_reg (DImode, operands[1]);
465       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
466       DONE;
467     }
468
469   if (TARGET_THUMB1)
470     {
471       if (GET_CODE (operands[1]) != REG)
472         operands[1] = force_reg (DImode, operands[1]);
473       if (GET_CODE (operands[2]) != REG)
474         operands[2] = force_reg (DImode, operands[2]);
475      }
476   "
477 )
478
479 (define_insn "*thumb1_adddi3"
480   [(set (match_operand:DI          0 "register_operand" "=l")
481         (plus:DI (match_operand:DI 1 "register_operand" "%0")
482                  (match_operand:DI 2 "register_operand" "l")))
483    (clobber (reg:CC CC_REGNUM))
484   ]
485   "TARGET_THUMB1"
486   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
487   [(set_attr "length" "4")]
488 )
489
490 (define_insn_and_split "*arm_adddi3"
491   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
492         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
493                  (match_operand:DI 2 "s_register_operand" "r,  0")))
494    (clobber (reg:CC CC_REGNUM))]
495   "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
496   "#"
497   "TARGET_32BIT && reload_completed"
498   [(parallel [(set (reg:CC_C CC_REGNUM)
499                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
500                                  (match_dup 1)))
501               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
502    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
503                                (plus:SI (match_dup 4) (match_dup 5))))]
504   "
505   {
506     operands[3] = gen_highpart (SImode, operands[0]);
507     operands[0] = gen_lowpart (SImode, operands[0]);
508     operands[4] = gen_highpart (SImode, operands[1]);
509     operands[1] = gen_lowpart (SImode, operands[1]);
510     operands[5] = gen_highpart (SImode, operands[2]);
511     operands[2] = gen_lowpart (SImode, operands[2]);
512   }"
513   [(set_attr "conds" "clob")
514    (set_attr "length" "8")]
515 )
516
517 (define_insn_and_split "*adddi_sesidi_di"
518   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
519         (plus:DI (sign_extend:DI
520                   (match_operand:SI 2 "s_register_operand" "r,r"))
521                  (match_operand:DI 1 "s_register_operand" "0,r")))
522    (clobber (reg:CC CC_REGNUM))]
523   "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
524   "#"
525   "TARGET_32BIT && reload_completed"
526   [(parallel [(set (reg:CC_C CC_REGNUM)
527                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
528                                  (match_dup 1)))
529               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
530    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
531                                (plus:SI (ashiftrt:SI (match_dup 2)
532                                                      (const_int 31))
533                                         (match_dup 4))))]
534   "
535   {
536     operands[3] = gen_highpart (SImode, operands[0]);
537     operands[0] = gen_lowpart (SImode, operands[0]);
538     operands[4] = gen_highpart (SImode, operands[1]);
539     operands[1] = gen_lowpart (SImode, operands[1]);
540     operands[2] = gen_lowpart (SImode, operands[2]);
541   }"
542   [(set_attr "conds" "clob")
543    (set_attr "length" "8")]
544 )
545
546 (define_insn_and_split "*adddi_zesidi_di"
547   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
548         (plus:DI (zero_extend:DI
549                   (match_operand:SI 2 "s_register_operand" "r,r"))
550                  (match_operand:DI 1 "s_register_operand" "0,r")))
551    (clobber (reg:CC CC_REGNUM))]
552   "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
553   "#"
554   "TARGET_32BIT && reload_completed"
555   [(parallel [(set (reg:CC_C CC_REGNUM)
556                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
557                                  (match_dup 1)))
558               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
559    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
560                                (plus:SI (match_dup 4) (const_int 0))))]
561   "
562   {
563     operands[3] = gen_highpart (SImode, operands[0]);
564     operands[0] = gen_lowpart (SImode, operands[0]);
565     operands[4] = gen_highpart (SImode, operands[1]);
566     operands[1] = gen_lowpart (SImode, operands[1]);
567     operands[2] = gen_lowpart (SImode, operands[2]);
568   }"
569   [(set_attr "conds" "clob")
570    (set_attr "length" "8")]
571 )
572
573 (define_expand "addsi3"
574   [(set (match_operand:SI          0 "s_register_operand" "")
575         (plus:SI (match_operand:SI 1 "s_register_operand" "")
576                  (match_operand:SI 2 "reg_or_int_operand" "")))]
577   "TARGET_EITHER"
578   "
579   if (TARGET_32BIT && GET_CODE (operands[2]) == CONST_INT)
580     {
581       arm_split_constant (PLUS, SImode, NULL_RTX,
582                           INTVAL (operands[2]), operands[0], operands[1],
583                           optimize && can_create_pseudo_p ());
584       DONE;
585     }
586   "
587 )
588
589 ; If there is a scratch available, this will be faster than synthesizing the
590 ; addition.
591 (define_peephole2
592   [(match_scratch:SI 3 "r")
593    (set (match_operand:SI          0 "arm_general_register_operand" "")
594         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
595                  (match_operand:SI 2 "const_int_operand"  "")))]
596   "TARGET_32BIT &&
597    !(const_ok_for_arm (INTVAL (operands[2]))
598      || const_ok_for_arm (-INTVAL (operands[2])))
599     && const_ok_for_arm (~INTVAL (operands[2]))"
600   [(set (match_dup 3) (match_dup 2))
601    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
602   ""
603 )
604
605 ;; The r/r/k alternative is required when reloading the address
606 ;;  (plus (reg rN) (reg sp)) into (reg rN).  In this case reload will
607 ;; put the duplicated register first, and not try the commutative version.
608 (define_insn_and_split "*arm_addsi3"
609   [(set (match_operand:SI          0 "s_register_operand" "=r, !k, r,r, !k,r")
610         (plus:SI (match_operand:SI 1 "s_register_operand" "%rk,!k, r,rk,!k,rk")
611                  (match_operand:SI 2 "reg_or_int_operand" "rI, rI,!k,L, L,?n")))]
612   "TARGET_32BIT"
613   "@
614    add%?\\t%0, %1, %2
615    add%?\\t%0, %1, %2
616    add%?\\t%0, %2, %1
617    sub%?\\t%0, %1, #%n2
618    sub%?\\t%0, %1, #%n2
619    #"
620   "TARGET_32BIT
621    && GET_CODE (operands[2]) == CONST_INT
622    && !(const_ok_for_arm (INTVAL (operands[2]))
623         || const_ok_for_arm (-INTVAL (operands[2])))
624    && (reload_completed || !arm_eliminable_register (operands[1]))"
625   [(clobber (const_int 0))]
626   "
627   arm_split_constant (PLUS, SImode, curr_insn,
628                       INTVAL (operands[2]), operands[0],
629                       operands[1], 0);
630   DONE;
631   "
632   [(set_attr "length" "4,4,4,4,4,16")
633    (set_attr "predicable" "yes")]
634 )
635
636 ;; Register group 'k' is a single register group containing only the stack
637 ;; register.  Trying to reload it will always fail catastrophically,
638 ;; so never allow those alternatives to match if reloading is needed.
639
640 (define_insn_and_split "*thumb1_addsi3"
641   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*rk,*hk,l,!k,l,l")
642         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k,0,l")
643                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,!M,!O,Pa,Pb")))]
644   "TARGET_THUMB1"
645   "*
646    static const char * const asms[] = 
647    {
648      \"add\\t%0, %0, %2\",
649      \"sub\\t%0, %0, #%n2\",
650      \"add\\t%0, %1, %2\",
651      \"add\\t%0, %0, %2\",
652      \"add\\t%0, %0, %2\",
653      \"add\\t%0, %1, %2\",
654      \"add\\t%0, %1, %2\",
655      \"#\",
656      \"#\"
657    };
658    if ((which_alternative == 2 || which_alternative == 6)
659        && GET_CODE (operands[2]) == CONST_INT
660        && INTVAL (operands[2]) < 0)
661      return \"sub\\t%0, %1, #%n2\";
662    return asms[which_alternative];
663   "
664   "&& reload_completed && CONST_INT_P (operands[2])
665    && operands[1] != stack_pointer_rtx
666    && (INTVAL (operands[2]) > 255 || INTVAL (operands[2]) < -255)"
667   [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
668    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
669   {
670     HOST_WIDE_INT offset = INTVAL (operands[2]);
671     if (offset > 255)
672       offset = 255;
673     else if (offset < -255)
674       offset = -255;
675     
676     operands[3] = GEN_INT (offset);
677     operands[2] = GEN_INT (INTVAL (operands[2]) - offset);
678   }
679   [(set_attr "length" "2,2,2,2,2,2,2,4,4")]
680 )
681
682 ;; Reloading and elimination of the frame pointer can
683 ;; sometimes cause this optimization to be missed.
684 (define_peephole2
685   [(set (match_operand:SI 0 "arm_general_register_operand" "")
686         (match_operand:SI 1 "const_int_operand" ""))
687    (set (match_dup 0)
688         (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
689   "TARGET_THUMB1
690    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
691    && (INTVAL (operands[1]) & 3) == 0"
692   [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
693   ""
694 )
695
696 (define_insn "*addsi3_compare0"
697   [(set (reg:CC_NOOV CC_REGNUM)
698         (compare:CC_NOOV
699          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
700                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
701          (const_int 0)))
702    (set (match_operand:SI 0 "s_register_operand" "=r,r")
703         (plus:SI (match_dup 1) (match_dup 2)))]
704   "TARGET_ARM"
705   "@
706    add%.\\t%0, %1, %2
707    sub%.\\t%0, %1, #%n2"
708   [(set_attr "conds" "set")]
709 )
710
711 (define_insn "*addsi3_compare0_scratch"
712   [(set (reg:CC_NOOV CC_REGNUM)
713         (compare:CC_NOOV
714          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
715                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
716          (const_int 0)))]
717   "TARGET_ARM"
718   "@
719    cmn%?\\t%0, %1
720    cmp%?\\t%0, #%n1"
721   [(set_attr "conds" "set")]
722 )
723
724 (define_insn "*compare_negsi_si"
725   [(set (reg:CC_Z CC_REGNUM)
726         (compare:CC_Z
727          (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
728          (match_operand:SI 1 "s_register_operand" "r")))]
729   "TARGET_32BIT"
730   "cmn%?\\t%1, %0"
731   [(set_attr "conds" "set")]
732 )
733
734 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
735 ;; addend is a constant.
736 (define_insn "*cmpsi2_addneg"
737   [(set (reg:CC CC_REGNUM)
738         (compare:CC
739          (match_operand:SI 1 "s_register_operand" "r,r")
740          (match_operand:SI 2 "arm_addimm_operand" "I,L")))
741    (set (match_operand:SI 0 "s_register_operand" "=r,r")
742         (plus:SI (match_dup 1)
743                  (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
744   "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
745   "@
746    sub%.\\t%0, %1, %2
747    add%.\\t%0, %1, #%n2"
748   [(set_attr "conds" "set")]
749 )
750
751 ;; Convert the sequence
752 ;;  sub  rd, rn, #1
753 ;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
754 ;;  bne  dest
755 ;; into
756 ;;  subs rd, rn, #1
757 ;;  bcs  dest   ((unsigned)rn >= 1)
758 ;; similarly for the beq variant using bcc.
759 ;; This is a common looping idiom (while (n--))
760 (define_peephole2
761   [(set (match_operand:SI 0 "arm_general_register_operand" "")
762         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
763                  (const_int -1)))
764    (set (match_operand 2 "cc_register" "")
765         (compare (match_dup 0) (const_int -1)))
766    (set (pc)
767         (if_then_else (match_operator 3 "equality_operator"
768                        [(match_dup 2) (const_int 0)])
769                       (match_operand 4 "" "")
770                       (match_operand 5 "" "")))]
771   "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
772   [(parallel[
773     (set (match_dup 2)
774          (compare:CC
775           (match_dup 1) (const_int 1)))
776     (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
777    (set (pc)
778         (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
779                       (match_dup 4)
780                       (match_dup 5)))]
781   "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
782    operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
783                                   ? GEU : LTU),
784                                  VOIDmode, 
785                                  operands[2], const0_rtx);"
786 )
787
788 ;; The next four insns work because they compare the result with one of
789 ;; the operands, and we know that the use of the condition code is
790 ;; either GEU or LTU, so we can use the carry flag from the addition
791 ;; instead of doing the compare a second time.
792 (define_insn "*addsi3_compare_op1"
793   [(set (reg:CC_C CC_REGNUM)
794         (compare:CC_C
795          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
796                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
797          (match_dup 1)))
798    (set (match_operand:SI 0 "s_register_operand" "=r,r")
799         (plus:SI (match_dup 1) (match_dup 2)))]
800   "TARGET_32BIT"
801   "@
802    add%.\\t%0, %1, %2
803    sub%.\\t%0, %1, #%n2"
804   [(set_attr "conds" "set")]
805 )
806
807 (define_insn "*addsi3_compare_op2"
808   [(set (reg:CC_C CC_REGNUM)
809         (compare:CC_C
810          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
811                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
812          (match_dup 2)))
813    (set (match_operand:SI 0 "s_register_operand" "=r,r")
814         (plus:SI (match_dup 1) (match_dup 2)))]
815   "TARGET_32BIT"
816   "@
817    add%.\\t%0, %1, %2
818    sub%.\\t%0, %1, #%n2"
819   [(set_attr "conds" "set")]
820 )
821
822 (define_insn "*compare_addsi2_op0"
823   [(set (reg:CC_C CC_REGNUM)
824         (compare:CC_C
825          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
826                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
827          (match_dup 0)))]
828   "TARGET_32BIT"
829   "@
830    cmn%?\\t%0, %1
831    cmp%?\\t%0, #%n1"
832   [(set_attr "conds" "set")]
833 )
834
835 (define_insn "*compare_addsi2_op1"
836   [(set (reg:CC_C CC_REGNUM)
837         (compare:CC_C
838          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
839                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
840          (match_dup 1)))]
841   "TARGET_32BIT"
842   "@
843    cmn%?\\t%0, %1
844    cmp%?\\t%0, #%n1"
845   [(set_attr "conds" "set")]
846 )
847
848 (define_insn "*addsi3_carryin"
849   [(set (match_operand:SI 0 "s_register_operand" "=r")
850         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
851                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
852                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
853   "TARGET_32BIT"
854   "adc%?\\t%0, %1, %2"
855   [(set_attr "conds" "use")]
856 )
857
858 (define_insn "*addsi3_carryin_shift"
859   [(set (match_operand:SI 0 "s_register_operand" "=r")
860         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
861                  (plus:SI
862                    (match_operator:SI 2 "shift_operator"
863                       [(match_operand:SI 3 "s_register_operand" "r")
864                        (match_operand:SI 4 "reg_or_int_operand" "rM")])
865                     (match_operand:SI 1 "s_register_operand" "r"))))]
866   "TARGET_32BIT"
867   "adc%?\\t%0, %1, %3%S2"
868   [(set_attr "conds" "use")
869    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
870                       (const_string "alu_shift")
871                       (const_string "alu_shift_reg")))]
872 )
873
874 (define_insn "*addsi3_carryin_alt1"
875   [(set (match_operand:SI 0 "s_register_operand" "=r")
876         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
877                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
878                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
879   "TARGET_32BIT"
880   "adc%?\\t%0, %1, %2"
881   [(set_attr "conds" "use")]
882 )
883
884 (define_insn "*addsi3_carryin_alt2"
885   [(set (match_operand:SI 0 "s_register_operand" "=r")
886         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
887                           (match_operand:SI 1 "s_register_operand" "r"))
888                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
889   "TARGET_32BIT"
890   "adc%?\\t%0, %1, %2"
891   [(set_attr "conds" "use")]
892 )
893
894 (define_insn "*addsi3_carryin_alt3"
895   [(set (match_operand:SI 0 "s_register_operand" "=r")
896         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
897                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
898                  (match_operand:SI 1 "s_register_operand" "r")))]
899   "TARGET_32BIT"
900   "adc%?\\t%0, %1, %2"
901   [(set_attr "conds" "use")]
902 )
903
904 (define_expand "incscc"
905   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
906         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
907                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
908                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
909   "TARGET_32BIT"
910   ""
911 )
912
913 (define_insn "*arm_incscc"
914   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
915         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
916                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
917                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
918   "TARGET_ARM"
919   "@
920   add%d2\\t%0, %1, #1
921   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
922   [(set_attr "conds" "use")
923    (set_attr "length" "4,8")]
924 )
925
926 ; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
927 (define_split
928   [(set (match_operand:SI 0 "s_register_operand" "")
929         (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
930                             (match_operand:SI 2 "s_register_operand" ""))
931                  (const_int -1)))
932    (clobber (match_operand:SI 3 "s_register_operand" ""))]
933   "TARGET_32BIT"
934   [(set (match_dup 3) (match_dup 1))
935    (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
936   "
937   operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
938 ")
939
940 (define_expand "addsf3"
941   [(set (match_operand:SF          0 "s_register_operand" "")
942         (plus:SF (match_operand:SF 1 "s_register_operand" "")
943                  (match_operand:SF 2 "arm_float_add_operand" "")))]
944   "TARGET_32BIT && TARGET_HARD_FLOAT"
945   "
946   if (TARGET_MAVERICK
947       && !cirrus_fp_register (operands[2], SFmode))
948     operands[2] = force_reg (SFmode, operands[2]);
949 ")
950
951 (define_expand "adddf3"
952   [(set (match_operand:DF          0 "s_register_operand" "")
953         (plus:DF (match_operand:DF 1 "s_register_operand" "")
954                  (match_operand:DF 2 "arm_float_add_operand" "")))]
955   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
956   "
957   if (TARGET_MAVERICK
958       && !cirrus_fp_register (operands[2], DFmode))
959     operands[2] = force_reg (DFmode, operands[2]);
960 ")
961
962 (define_expand "subdi3"
963  [(parallel
964    [(set (match_operand:DI            0 "s_register_operand" "")
965           (minus:DI (match_operand:DI 1 "s_register_operand" "")
966                     (match_operand:DI 2 "s_register_operand" "")))
967     (clobber (reg:CC CC_REGNUM))])]
968   "TARGET_EITHER"
969   "
970   if (TARGET_HARD_FLOAT && TARGET_MAVERICK
971       && TARGET_32BIT
972       && cirrus_fp_register (operands[0], DImode)
973       && cirrus_fp_register (operands[1], DImode))
974     {
975       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
976       DONE;
977     }
978
979   if (TARGET_THUMB1)
980     {
981       if (GET_CODE (operands[1]) != REG)
982         operands[1] = force_reg (DImode, operands[1]);
983       if (GET_CODE (operands[2]) != REG)
984         operands[2] = force_reg (DImode, operands[2]);
985      }  
986   "
987 )
988
989 (define_insn "*arm_subdi3"
990   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
991         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
992                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
993    (clobber (reg:CC CC_REGNUM))]
994   "TARGET_32BIT"
995   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
996   [(set_attr "conds" "clob")
997    (set_attr "length" "8")]
998 )
999
1000 (define_insn "*thumb_subdi3"
1001   [(set (match_operand:DI           0 "register_operand" "=l")
1002         (minus:DI (match_operand:DI 1 "register_operand"  "0")
1003                   (match_operand:DI 2 "register_operand"  "l")))
1004    (clobber (reg:CC CC_REGNUM))]
1005   "TARGET_THUMB1"
1006   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
1007   [(set_attr "length" "4")]
1008 )
1009
1010 (define_insn "*subdi_di_zesidi"
1011   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
1012         (minus:DI (match_operand:DI 1 "s_register_operand"  "0,r")
1013                   (zero_extend:DI
1014                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
1015    (clobber (reg:CC CC_REGNUM))]
1016   "TARGET_32BIT"
1017   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
1018   [(set_attr "conds" "clob")
1019    (set_attr "length" "8")]
1020 )
1021
1022 (define_insn "*subdi_di_sesidi"
1023   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
1024         (minus:DI (match_operand:DI  1 "s_register_operand"  "0,r")
1025                   (sign_extend:DI
1026                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
1027    (clobber (reg:CC CC_REGNUM))]
1028   "TARGET_32BIT"
1029   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
1030   [(set_attr "conds" "clob")
1031    (set_attr "length" "8")]
1032 )
1033
1034 (define_insn "*subdi_zesidi_di"
1035   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
1036         (minus:DI (zero_extend:DI
1037                    (match_operand:SI 2 "s_register_operand"  "r,r"))
1038                   (match_operand:DI  1 "s_register_operand" "0,r")))
1039    (clobber (reg:CC CC_REGNUM))]
1040   "TARGET_ARM"
1041   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
1042   [(set_attr "conds" "clob")
1043    (set_attr "length" "8")]
1044 )
1045
1046 (define_insn "*subdi_sesidi_di"
1047   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
1048         (minus:DI (sign_extend:DI
1049                    (match_operand:SI 2 "s_register_operand"   "r,r"))
1050                   (match_operand:DI  1 "s_register_operand"  "0,r")))
1051    (clobber (reg:CC CC_REGNUM))]
1052   "TARGET_ARM"
1053   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
1054   [(set_attr "conds" "clob")
1055    (set_attr "length" "8")]
1056 )
1057
1058 (define_insn "*subdi_zesidi_zesidi"
1059   [(set (match_operand:DI            0 "s_register_operand" "=r")
1060         (minus:DI (zero_extend:DI
1061                    (match_operand:SI 1 "s_register_operand"  "r"))
1062                   (zero_extend:DI
1063                    (match_operand:SI 2 "s_register_operand"  "r"))))
1064    (clobber (reg:CC CC_REGNUM))]
1065   "TARGET_32BIT"
1066   "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
1067   [(set_attr "conds" "clob")
1068    (set_attr "length" "8")]
1069 )
1070
1071 (define_expand "subsi3"
1072   [(set (match_operand:SI           0 "s_register_operand" "")
1073         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1074                   (match_operand:SI 2 "s_register_operand" "")))]
1075   "TARGET_EITHER"
1076   "
1077   if (GET_CODE (operands[1]) == CONST_INT)
1078     {
1079       if (TARGET_32BIT)
1080         {
1081           arm_split_constant (MINUS, SImode, NULL_RTX,
1082                               INTVAL (operands[1]), operands[0],
1083                               operands[2], optimize && can_create_pseudo_p ());
1084           DONE;
1085         }
1086       else /* TARGET_THUMB1 */
1087         operands[1] = force_reg (SImode, operands[1]);
1088     }
1089   "
1090 )
1091
1092 (define_insn "*thumb1_subsi3_insn"
1093   [(set (match_operand:SI           0 "register_operand" "=l")
1094         (minus:SI (match_operand:SI 1 "register_operand" "l")
1095                   (match_operand:SI 2 "register_operand" "l")))]
1096   "TARGET_THUMB1"
1097   "sub\\t%0, %1, %2"
1098   [(set_attr "length" "2")]
1099 )
1100
1101 ; ??? Check Thumb-2 split length
1102 (define_insn_and_split "*arm_subsi3_insn"
1103   [(set (match_operand:SI           0 "s_register_operand" "=r,rk,r")
1104         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,!k,?n")
1105                   (match_operand:SI 2 "s_register_operand" "r, r, r")))]
1106   "TARGET_32BIT"
1107   "@
1108    rsb%?\\t%0, %2, %1
1109    sub%?\\t%0, %1, %2
1110    #"
1111   "TARGET_32BIT
1112    && GET_CODE (operands[1]) == CONST_INT
1113    && !const_ok_for_arm (INTVAL (operands[1]))"
1114   [(clobber (const_int 0))]
1115   "
1116   arm_split_constant (MINUS, SImode, curr_insn,
1117                       INTVAL (operands[1]), operands[0], operands[2], 0);
1118   DONE;
1119   "
1120   [(set_attr "length" "4,4,16")
1121    (set_attr "predicable" "yes")]
1122 )
1123
1124 (define_peephole2
1125   [(match_scratch:SI 3 "r")
1126    (set (match_operand:SI 0 "arm_general_register_operand" "")
1127         (minus:SI (match_operand:SI 1 "const_int_operand" "")
1128                   (match_operand:SI 2 "arm_general_register_operand" "")))]
1129   "TARGET_32BIT
1130    && !const_ok_for_arm (INTVAL (operands[1]))
1131    && const_ok_for_arm (~INTVAL (operands[1]))"
1132   [(set (match_dup 3) (match_dup 1))
1133    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1134   ""
1135 )
1136
1137 (define_insn "*subsi3_compare0"
1138   [(set (reg:CC_NOOV CC_REGNUM)
1139         (compare:CC_NOOV
1140          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1141                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1142          (const_int 0)))
1143    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1144         (minus:SI (match_dup 1) (match_dup 2)))]
1145   "TARGET_32BIT"
1146   "@
1147    sub%.\\t%0, %1, %2
1148    rsb%.\\t%0, %2, %1"
1149   [(set_attr "conds" "set")]
1150 )
1151
1152 (define_expand "decscc"
1153   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1154         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1155                   (match_operator:SI 2 "arm_comparison_operator"
1156                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1157   "TARGET_32BIT"
1158   ""
1159 )
1160
1161 (define_insn "*arm_decscc"
1162   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1163         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1164                   (match_operator:SI 2 "arm_comparison_operator"
1165                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1166   "TARGET_ARM"
1167   "@
1168    sub%d2\\t%0, %1, #1
1169    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1170   [(set_attr "conds" "use")
1171    (set_attr "length" "*,8")]
1172 )
1173
1174 (define_expand "subsf3"
1175   [(set (match_operand:SF           0 "s_register_operand" "")
1176         (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1177                   (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1178   "TARGET_32BIT && TARGET_HARD_FLOAT"
1179   "
1180   if (TARGET_MAVERICK)
1181     {
1182       if (!cirrus_fp_register (operands[1], SFmode))
1183         operands[1] = force_reg (SFmode, operands[1]);
1184       if (!cirrus_fp_register (operands[2], SFmode))
1185         operands[2] = force_reg (SFmode, operands[2]);
1186     }
1187 ")
1188
1189 (define_expand "subdf3"
1190   [(set (match_operand:DF           0 "s_register_operand" "")
1191         (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1192                   (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1193   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
1194   "
1195   if (TARGET_MAVERICK)
1196     {
1197        if (!cirrus_fp_register (operands[1], DFmode))
1198          operands[1] = force_reg (DFmode, operands[1]);
1199        if (!cirrus_fp_register (operands[2], DFmode))
1200          operands[2] = force_reg (DFmode, operands[2]);
1201     }
1202 ")
1203
1204 \f
1205 ;; Multiplication insns
1206
1207 (define_expand "mulsi3"
1208   [(set (match_operand:SI          0 "s_register_operand" "")
1209         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1210                  (match_operand:SI 1 "s_register_operand" "")))]
1211   "TARGET_EITHER"
1212   ""
1213 )
1214
1215 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1216 (define_insn "*arm_mulsi3"
1217   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1218         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1219                  (match_operand:SI 1 "s_register_operand" "%0,r")))]
1220   "TARGET_32BIT && !arm_arch6"
1221   "mul%?\\t%0, %2, %1"
1222   [(set_attr "insn" "mul")
1223    (set_attr "predicable" "yes")]
1224 )
1225
1226 (define_insn "*arm_mulsi3_v6"
1227   [(set (match_operand:SI          0 "s_register_operand" "=r")
1228         (mult:SI (match_operand:SI 1 "s_register_operand" "r")
1229                  (match_operand:SI 2 "s_register_operand" "r")))]
1230   "TARGET_32BIT && arm_arch6"
1231   "mul%?\\t%0, %1, %2"
1232   [(set_attr "insn" "mul")
1233    (set_attr "predicable" "yes")]
1234 )
1235
1236 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1237 ; 1 and 2; are the same, because reload will make operand 0 match 
1238 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1239 ; this by adding another alternative to match this case, and then `reload' 
1240 ; it ourselves.  This alternative must come first.
1241 (define_insn "*thumb_mulsi3"
1242   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1243         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1244                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1245   "TARGET_THUMB1 && !arm_arch6"
1246   "*
1247   if (which_alternative < 2)
1248     return \"mov\\t%0, %1\;mul\\t%0, %2\";
1249   else
1250     return \"mul\\t%0, %2\";
1251   "
1252   [(set_attr "length" "4,4,2")
1253    (set_attr "insn" "mul")]
1254 )
1255
1256 (define_insn "*thumb_mulsi3_v6"
1257   [(set (match_operand:SI          0 "register_operand" "=l,l,l")
1258         (mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
1259                  (match_operand:SI 2 "register_operand" "l,0,0")))]
1260   "TARGET_THUMB1 && arm_arch6"
1261   "@
1262    mul\\t%0, %2
1263    mul\\t%0, %1
1264    mul\\t%0, %1"
1265   [(set_attr "length" "2")
1266    (set_attr "insn" "mul")]
1267 )
1268
1269 (define_insn "*mulsi3_compare0"
1270   [(set (reg:CC_NOOV CC_REGNUM)
1271         (compare:CC_NOOV (mult:SI
1272                           (match_operand:SI 2 "s_register_operand" "r,r")
1273                           (match_operand:SI 1 "s_register_operand" "%0,r"))
1274                          (const_int 0)))
1275    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1276         (mult:SI (match_dup 2) (match_dup 1)))]
1277   "TARGET_ARM && !arm_arch6"
1278   "mul%.\\t%0, %2, %1"
1279   [(set_attr "conds" "set")
1280    (set_attr "insn" "muls")]
1281 )
1282
1283 (define_insn "*mulsi3_compare0_v6"
1284   [(set (reg:CC_NOOV CC_REGNUM)
1285         (compare:CC_NOOV (mult:SI
1286                           (match_operand:SI 2 "s_register_operand" "r")
1287                           (match_operand:SI 1 "s_register_operand" "r"))
1288                          (const_int 0)))
1289    (set (match_operand:SI 0 "s_register_operand" "=r")
1290         (mult:SI (match_dup 2) (match_dup 1)))]
1291   "TARGET_ARM && arm_arch6 && optimize_size"
1292   "mul%.\\t%0, %2, %1"
1293   [(set_attr "conds" "set")
1294    (set_attr "insn" "muls")]
1295 )
1296
1297 (define_insn "*mulsi_compare0_scratch"
1298   [(set (reg:CC_NOOV CC_REGNUM)
1299         (compare:CC_NOOV (mult:SI
1300                           (match_operand:SI 2 "s_register_operand" "r,r")
1301                           (match_operand:SI 1 "s_register_operand" "%0,r"))
1302                          (const_int 0)))
1303    (clobber (match_scratch:SI 0 "=&r,&r"))]
1304   "TARGET_ARM && !arm_arch6"
1305   "mul%.\\t%0, %2, %1"
1306   [(set_attr "conds" "set")
1307    (set_attr "insn" "muls")]
1308 )
1309
1310 (define_insn "*mulsi_compare0_scratch_v6"
1311   [(set (reg:CC_NOOV CC_REGNUM)
1312         (compare:CC_NOOV (mult:SI
1313                           (match_operand:SI 2 "s_register_operand" "r")
1314                           (match_operand:SI 1 "s_register_operand" "r"))
1315                          (const_int 0)))
1316    (clobber (match_scratch:SI 0 "=r"))]
1317   "TARGET_ARM && arm_arch6 && optimize_size"
1318   "mul%.\\t%0, %2, %1"
1319   [(set_attr "conds" "set")
1320    (set_attr "insn" "muls")]
1321 )
1322
1323 ;; Unnamed templates to match MLA instruction.
1324
1325 (define_insn "*mulsi3addsi"
1326   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1327         (plus:SI
1328           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1329                    (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1330           (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
1331   "TARGET_32BIT && !arm_arch6"
1332   "mla%?\\t%0, %2, %1, %3"
1333   [(set_attr "insn" "mla")
1334    (set_attr "predicable" "yes")]
1335 )
1336
1337 (define_insn "*mulsi3addsi_v6"
1338   [(set (match_operand:SI 0 "s_register_operand" "=r")
1339         (plus:SI
1340           (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1341                    (match_operand:SI 1 "s_register_operand" "r"))
1342           (match_operand:SI 3 "s_register_operand" "r")))]
1343   "TARGET_32BIT && arm_arch6"
1344   "mla%?\\t%0, %2, %1, %3"
1345   [(set_attr "insn" "mla")
1346    (set_attr "predicable" "yes")]
1347 )
1348
1349 (define_insn "*mulsi3addsi_compare0"
1350   [(set (reg:CC_NOOV CC_REGNUM)
1351         (compare:CC_NOOV
1352          (plus:SI (mult:SI
1353                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1354                    (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1355                   (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
1356          (const_int 0)))
1357    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1358         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1359                  (match_dup 3)))]
1360   "TARGET_ARM && arm_arch6"
1361   "mla%.\\t%0, %2, %1, %3"
1362   [(set_attr "conds" "set")
1363    (set_attr "insn" "mlas")]
1364 )
1365
1366 (define_insn "*mulsi3addsi_compare0_v6"
1367   [(set (reg:CC_NOOV CC_REGNUM)
1368         (compare:CC_NOOV
1369          (plus:SI (mult:SI
1370                    (match_operand:SI 2 "s_register_operand" "r")
1371                    (match_operand:SI 1 "s_register_operand" "r"))
1372                   (match_operand:SI 3 "s_register_operand" "r"))
1373          (const_int 0)))
1374    (set (match_operand:SI 0 "s_register_operand" "=r")
1375         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1376                  (match_dup 3)))]
1377   "TARGET_ARM && arm_arch6 && optimize_size"
1378   "mla%.\\t%0, %2, %1, %3"
1379   [(set_attr "conds" "set")
1380    (set_attr "insn" "mlas")]
1381 )
1382
1383 (define_insn "*mulsi3addsi_compare0_scratch"
1384   [(set (reg:CC_NOOV CC_REGNUM)
1385         (compare:CC_NOOV
1386          (plus:SI (mult:SI
1387                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1388                    (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1389                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1390          (const_int 0)))
1391    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1392   "TARGET_ARM && !arm_arch6"
1393   "mla%.\\t%0, %2, %1, %3"
1394   [(set_attr "conds" "set")
1395    (set_attr "insn" "mlas")]
1396 )
1397
1398 (define_insn "*mulsi3addsi_compare0_scratch_v6"
1399   [(set (reg:CC_NOOV CC_REGNUM)
1400         (compare:CC_NOOV
1401          (plus:SI (mult:SI
1402                    (match_operand:SI 2 "s_register_operand" "r")
1403                    (match_operand:SI 1 "s_register_operand" "r"))
1404                   (match_operand:SI 3 "s_register_operand" "r"))
1405          (const_int 0)))
1406    (clobber (match_scratch:SI 0 "=r"))]
1407   "TARGET_ARM && arm_arch6 && optimize_size"
1408   "mla%.\\t%0, %2, %1, %3"
1409   [(set_attr "conds" "set")
1410    (set_attr "insn" "mlas")]
1411 )
1412
1413 (define_insn "*mulsi3subsi"
1414   [(set (match_operand:SI 0 "s_register_operand" "=r")
1415         (minus:SI
1416           (match_operand:SI 3 "s_register_operand" "r")
1417           (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1418                    (match_operand:SI 1 "s_register_operand" "r"))))]
1419   "TARGET_32BIT && arm_arch_thumb2"
1420   "mls%?\\t%0, %2, %1, %3"
1421   [(set_attr "insn" "mla")
1422    (set_attr "predicable" "yes")]
1423 )
1424
1425 ;; Unnamed template to match long long multiply-accumulate (smlal)
1426
1427 (define_insn "*mulsidi3adddi"
1428   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1429         (plus:DI
1430          (mult:DI
1431           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1432           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1433          (match_operand:DI 1 "s_register_operand" "0")))]
1434   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1435   "smlal%?\\t%Q0, %R0, %3, %2"
1436   [(set_attr "insn" "smlal")
1437    (set_attr "predicable" "yes")]
1438 )
1439
1440 (define_insn "*mulsidi3adddi_v6"
1441   [(set (match_operand:DI 0 "s_register_operand" "=r")
1442         (plus:DI
1443          (mult:DI
1444           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1445           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1446          (match_operand:DI 1 "s_register_operand" "0")))]
1447   "TARGET_32BIT && arm_arch6"
1448   "smlal%?\\t%Q0, %R0, %3, %2"
1449   [(set_attr "insn" "smlal")
1450    (set_attr "predicable" "yes")]
1451 )
1452
1453 ;; 32x32->64 widening multiply.
1454 ;; As with mulsi3, the only difference between the v3-5 and v6+
1455 ;; versions of these patterns is the requirement that the output not
1456 ;; overlap the inputs, but that still means we have to have a named
1457 ;; expander and two different starred insns.
1458
1459 (define_expand "mulsidi3"
1460   [(set (match_operand:DI 0 "s_register_operand" "")
1461         (mult:DI
1462          (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1463          (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1464   "TARGET_32BIT && arm_arch3m"
1465   ""
1466 )
1467
1468 (define_insn "*mulsidi3_nov6"
1469   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1470         (mult:DI
1471          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1472          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1473   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1474   "smull%?\\t%Q0, %R0, %1, %2"
1475   [(set_attr "insn" "smull")
1476    (set_attr "predicable" "yes")]
1477 )
1478
1479 (define_insn "*mulsidi3_v6"
1480   [(set (match_operand:DI 0 "s_register_operand" "=r")
1481         (mult:DI
1482          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1483          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1484   "TARGET_32BIT && arm_arch6"
1485   "smull%?\\t%Q0, %R0, %1, %2"
1486   [(set_attr "insn" "smull")
1487    (set_attr "predicable" "yes")]
1488 )
1489
1490 (define_expand "umulsidi3"
1491   [(set (match_operand:DI 0 "s_register_operand" "")
1492         (mult:DI
1493          (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1494          (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1495   "TARGET_32BIT && arm_arch3m"
1496   ""
1497 )
1498
1499 (define_insn "*umulsidi3_nov6"
1500   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1501         (mult:DI
1502          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1503          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1504   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1505   "umull%?\\t%Q0, %R0, %1, %2"
1506   [(set_attr "insn" "umull")
1507    (set_attr "predicable" "yes")]
1508 )
1509
1510 (define_insn "*umulsidi3_v6"
1511   [(set (match_operand:DI 0 "s_register_operand" "=r")
1512         (mult:DI
1513          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1514          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1515   "TARGET_32BIT && arm_arch6"
1516   "umull%?\\t%Q0, %R0, %1, %2"
1517   [(set_attr "insn" "umull")
1518    (set_attr "predicable" "yes")]
1519 )
1520
1521 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1522
1523 (define_insn "*umulsidi3adddi"
1524   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1525         (plus:DI
1526          (mult:DI
1527           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1528           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1529          (match_operand:DI 1 "s_register_operand" "0")))]
1530   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1531   "umlal%?\\t%Q0, %R0, %3, %2"
1532   [(set_attr "insn" "umlal")
1533    (set_attr "predicable" "yes")]
1534 )
1535
1536 (define_insn "*umulsidi3adddi_v6"
1537   [(set (match_operand:DI 0 "s_register_operand" "=r")
1538         (plus:DI
1539          (mult:DI
1540           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1541           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1542          (match_operand:DI 1 "s_register_operand" "0")))]
1543   "TARGET_32BIT && arm_arch6"
1544   "umlal%?\\t%Q0, %R0, %3, %2"
1545   [(set_attr "insn" "umlal")
1546    (set_attr "predicable" "yes")]
1547 )
1548
1549 (define_expand "smulsi3_highpart"
1550   [(parallel
1551     [(set (match_operand:SI 0 "s_register_operand" "")
1552           (truncate:SI
1553            (lshiftrt:DI
1554             (mult:DI
1555              (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1556              (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1557             (const_int 32))))
1558      (clobber (match_scratch:SI 3 ""))])]
1559   "TARGET_32BIT && arm_arch3m"
1560   ""
1561 )
1562
1563 (define_insn "*smulsi3_highpart_nov6"
1564   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1565         (truncate:SI
1566          (lshiftrt:DI
1567           (mult:DI
1568            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
1569            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1570           (const_int 32))))
1571    (clobber (match_scratch:SI 3 "=&r,&r"))]
1572   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1573   "smull%?\\t%3, %0, %2, %1"
1574   [(set_attr "insn" "smull")
1575    (set_attr "predicable" "yes")]
1576 )
1577
1578 (define_insn "*smulsi3_highpart_v6"
1579   [(set (match_operand:SI 0 "s_register_operand" "=r")
1580         (truncate:SI
1581          (lshiftrt:DI
1582           (mult:DI
1583            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1584            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1585           (const_int 32))))
1586    (clobber (match_scratch:SI 3 "=r"))]
1587   "TARGET_32BIT && arm_arch6"
1588   "smull%?\\t%3, %0, %2, %1"
1589   [(set_attr "insn" "smull")
1590    (set_attr "predicable" "yes")]
1591 )
1592
1593 (define_expand "umulsi3_highpart"
1594   [(parallel
1595     [(set (match_operand:SI 0 "s_register_operand" "")
1596           (truncate:SI
1597            (lshiftrt:DI
1598             (mult:DI
1599              (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1600               (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1601             (const_int 32))))
1602      (clobber (match_scratch:SI 3 ""))])]
1603   "TARGET_32BIT && arm_arch3m"
1604   ""
1605 )
1606
1607 (define_insn "*umulsi3_highpart_nov6"
1608   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1609         (truncate:SI
1610          (lshiftrt:DI
1611           (mult:DI
1612            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
1613            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1614           (const_int 32))))
1615    (clobber (match_scratch:SI 3 "=&r,&r"))]
1616   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1617   "umull%?\\t%3, %0, %2, %1"
1618   [(set_attr "insn" "umull")
1619    (set_attr "predicable" "yes")]
1620 )
1621
1622 (define_insn "*umulsi3_highpart_v6"
1623   [(set (match_operand:SI 0 "s_register_operand" "=r")
1624         (truncate:SI
1625          (lshiftrt:DI
1626           (mult:DI
1627            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1628            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1629           (const_int 32))))
1630    (clobber (match_scratch:SI 3 "=r"))]
1631   "TARGET_32BIT && arm_arch6"
1632   "umull%?\\t%3, %0, %2, %1"
1633   [(set_attr "insn" "umull")
1634    (set_attr "predicable" "yes")]
1635 )
1636
1637 (define_insn "mulhisi3"
1638   [(set (match_operand:SI 0 "s_register_operand" "=r")
1639         (mult:SI (sign_extend:SI
1640                   (match_operand:HI 1 "s_register_operand" "%r"))
1641                  (sign_extend:SI
1642                   (match_operand:HI 2 "s_register_operand" "r"))))]
1643   "TARGET_DSP_MULTIPLY"
1644   "smulbb%?\\t%0, %1, %2"
1645   [(set_attr "insn" "smulxy")
1646    (set_attr "predicable" "yes")]
1647 )
1648
1649 (define_insn "*mulhisi3tb"
1650   [(set (match_operand:SI 0 "s_register_operand" "=r")
1651         (mult:SI (ashiftrt:SI
1652                   (match_operand:SI 1 "s_register_operand" "r")
1653                   (const_int 16))
1654                  (sign_extend:SI
1655                   (match_operand:HI 2 "s_register_operand" "r"))))]
1656   "TARGET_DSP_MULTIPLY"
1657   "smultb%?\\t%0, %1, %2"
1658   [(set_attr "insn" "smulxy")
1659    (set_attr "predicable" "yes")]
1660 )
1661
1662 (define_insn "*mulhisi3bt"
1663   [(set (match_operand:SI 0 "s_register_operand" "=r")
1664         (mult:SI (sign_extend:SI
1665                   (match_operand:HI 1 "s_register_operand" "r"))
1666                  (ashiftrt:SI
1667                   (match_operand:SI 2 "s_register_operand" "r")
1668                   (const_int 16))))]
1669   "TARGET_DSP_MULTIPLY"
1670   "smulbt%?\\t%0, %1, %2"
1671   [(set_attr "insn" "smulxy")
1672    (set_attr "predicable" "yes")]
1673 )
1674
1675 (define_insn "*mulhisi3tt"
1676   [(set (match_operand:SI 0 "s_register_operand" "=r")
1677         (mult:SI (ashiftrt:SI
1678                   (match_operand:SI 1 "s_register_operand" "r")
1679                   (const_int 16))
1680                  (ashiftrt:SI
1681                   (match_operand:SI 2 "s_register_operand" "r")
1682                   (const_int 16))))]
1683   "TARGET_DSP_MULTIPLY"
1684   "smultt%?\\t%0, %1, %2"
1685   [(set_attr "insn" "smulxy")
1686    (set_attr "predicable" "yes")]
1687 )
1688
1689 (define_insn "*mulhisi3addsi"
1690   [(set (match_operand:SI 0 "s_register_operand" "=r")
1691         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1692                  (mult:SI (sign_extend:SI
1693                            (match_operand:HI 2 "s_register_operand" "%r"))
1694                           (sign_extend:SI
1695                            (match_operand:HI 3 "s_register_operand" "r")))))]
1696   "TARGET_DSP_MULTIPLY"
1697   "smlabb%?\\t%0, %2, %3, %1"
1698   [(set_attr "insn" "smlaxy")
1699    (set_attr "predicable" "yes")]
1700 )
1701
1702 (define_insn "*mulhidi3adddi"
1703   [(set (match_operand:DI 0 "s_register_operand" "=r")
1704         (plus:DI
1705           (match_operand:DI 1 "s_register_operand" "0")
1706           (mult:DI (sign_extend:DI
1707                     (match_operand:HI 2 "s_register_operand" "%r"))
1708                    (sign_extend:DI
1709                     (match_operand:HI 3 "s_register_operand" "r")))))]
1710   "TARGET_DSP_MULTIPLY"
1711   "smlalbb%?\\t%Q0, %R0, %2, %3"
1712   [(set_attr "insn" "smlalxy")
1713    (set_attr "predicable" "yes")])
1714
1715 (define_expand "mulsf3"
1716   [(set (match_operand:SF          0 "s_register_operand" "")
1717         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1718                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1719   "TARGET_32BIT && TARGET_HARD_FLOAT"
1720   "
1721   if (TARGET_MAVERICK
1722       && !cirrus_fp_register (operands[2], SFmode))
1723     operands[2] = force_reg (SFmode, operands[2]);
1724 ")
1725
1726 (define_expand "muldf3"
1727   [(set (match_operand:DF          0 "s_register_operand" "")
1728         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1729                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1730   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
1731   "
1732   if (TARGET_MAVERICK
1733       && !cirrus_fp_register (operands[2], DFmode))
1734     operands[2] = force_reg (DFmode, operands[2]);
1735 ")
1736 \f
1737 ;; Division insns
1738
1739 (define_expand "divsf3"
1740   [(set (match_operand:SF 0 "s_register_operand" "")
1741         (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1742                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1743   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1744   "")
1745
1746 (define_expand "divdf3"
1747   [(set (match_operand:DF 0 "s_register_operand" "")
1748         (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1749                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1750   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
1751   "")
1752 \f
1753 ;; Modulo insns
1754
1755 (define_expand "modsf3"
1756   [(set (match_operand:SF 0 "s_register_operand" "")
1757         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1758                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1759   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
1760   "")
1761
1762 (define_expand "moddf3"
1763   [(set (match_operand:DF 0 "s_register_operand" "")
1764         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1765                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1766   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
1767   "")
1768 \f
1769 ;; Boolean and,ior,xor insns
1770
1771 ;; Split up double word logical operations
1772
1773 ;; Split up simple DImode logical operations.  Simply perform the logical
1774 ;; operation on the upper and lower halves of the registers.
1775 (define_split
1776   [(set (match_operand:DI 0 "s_register_operand" "")
1777         (match_operator:DI 6 "logical_binary_operator"
1778           [(match_operand:DI 1 "s_register_operand" "")
1779            (match_operand:DI 2 "s_register_operand" "")]))]
1780   "TARGET_32BIT && reload_completed
1781    && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1782   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1783    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1784   "
1785   {
1786     operands[3] = gen_highpart (SImode, operands[0]);
1787     operands[0] = gen_lowpart (SImode, operands[0]);
1788     operands[4] = gen_highpart (SImode, operands[1]);
1789     operands[1] = gen_lowpart (SImode, operands[1]);
1790     operands[5] = gen_highpart (SImode, operands[2]);
1791     operands[2] = gen_lowpart (SImode, operands[2]);
1792   }"
1793 )
1794
1795 (define_split
1796   [(set (match_operand:DI 0 "s_register_operand" "")
1797         (match_operator:DI 6 "logical_binary_operator"
1798           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1799            (match_operand:DI 1 "s_register_operand" "")]))]
1800   "TARGET_32BIT && reload_completed"
1801   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1802    (set (match_dup 3) (match_op_dup:SI 6
1803                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1804                          (match_dup 4)]))]
1805   "
1806   {
1807     operands[3] = gen_highpart (SImode, operands[0]);
1808     operands[0] = gen_lowpart (SImode, operands[0]);
1809     operands[4] = gen_highpart (SImode, operands[1]);
1810     operands[1] = gen_lowpart (SImode, operands[1]);
1811     operands[5] = gen_highpart (SImode, operands[2]);
1812     operands[2] = gen_lowpart (SImode, operands[2]);
1813   }"
1814 )
1815
1816 ;; The zero extend of operand 2 means we can just copy the high part of
1817 ;; operand1 into operand0.
1818 (define_split
1819   [(set (match_operand:DI 0 "s_register_operand" "")
1820         (ior:DI
1821           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1822           (match_operand:DI 1 "s_register_operand" "")))]
1823   "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
1824   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1825    (set (match_dup 3) (match_dup 4))]
1826   "
1827   {
1828     operands[4] = gen_highpart (SImode, operands[1]);
1829     operands[3] = gen_highpart (SImode, operands[0]);
1830     operands[0] = gen_lowpart (SImode, operands[0]);
1831     operands[1] = gen_lowpart (SImode, operands[1]);
1832   }"
1833 )
1834
1835 ;; The zero extend of operand 2 means we can just copy the high part of
1836 ;; operand1 into operand0.
1837 (define_split
1838   [(set (match_operand:DI 0 "s_register_operand" "")
1839         (xor:DI
1840           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1841           (match_operand:DI 1 "s_register_operand" "")))]
1842   "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
1843   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1844    (set (match_dup 3) (match_dup 4))]
1845   "
1846   {
1847     operands[4] = gen_highpart (SImode, operands[1]);
1848     operands[3] = gen_highpart (SImode, operands[0]);
1849     operands[0] = gen_lowpart (SImode, operands[0]);
1850     operands[1] = gen_lowpart (SImode, operands[1]);
1851   }"
1852 )
1853
1854 (define_insn "anddi3"
1855   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1856         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1857                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1858   "TARGET_32BIT && ! TARGET_IWMMXT"
1859   "#"
1860   [(set_attr "length" "8")]
1861 )
1862
1863 (define_insn_and_split "*anddi_zesidi_di"
1864   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1865         (and:DI (zero_extend:DI
1866                  (match_operand:SI 2 "s_register_operand" "r,r"))
1867                 (match_operand:DI 1 "s_register_operand" "0,r")))]
1868   "TARGET_32BIT"
1869   "#"
1870   "TARGET_32BIT && reload_completed"
1871   ; The zero extend of operand 2 clears the high word of the output
1872   ; operand.
1873   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1874    (set (match_dup 3) (const_int 0))]
1875   "
1876   {
1877     operands[3] = gen_highpart (SImode, operands[0]);
1878     operands[0] = gen_lowpart (SImode, operands[0]);
1879     operands[1] = gen_lowpart (SImode, operands[1]);
1880   }"
1881   [(set_attr "length" "8")]
1882 )
1883
1884 (define_insn "*anddi_sesdi_di"
1885   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1886         (and:DI (sign_extend:DI
1887                  (match_operand:SI 2 "s_register_operand" "r,r"))
1888                 (match_operand:DI  1 "s_register_operand" "0,r")))]
1889   "TARGET_32BIT"
1890   "#"
1891   [(set_attr "length" "8")]
1892 )
1893
1894 (define_expand "andsi3"
1895   [(set (match_operand:SI         0 "s_register_operand" "")
1896         (and:SI (match_operand:SI 1 "s_register_operand" "")
1897                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1898   "TARGET_EITHER"
1899   "
1900   if (TARGET_32BIT)
1901     {
1902       if (GET_CODE (operands[2]) == CONST_INT)
1903         {
1904           arm_split_constant (AND, SImode, NULL_RTX,
1905                               INTVAL (operands[2]), operands[0],
1906                               operands[1], optimize && can_create_pseudo_p ());
1907
1908           DONE;
1909         }
1910     }
1911   else /* TARGET_THUMB1 */
1912     {
1913       if (GET_CODE (operands[2]) != CONST_INT)
1914         {
1915           rtx tmp = force_reg (SImode, operands[2]);
1916           if (rtx_equal_p (operands[0], operands[1]))
1917             operands[2] = tmp;
1918           else
1919             {
1920               operands[2] = operands[1];
1921               operands[1] = tmp;
1922             }
1923         }
1924       else
1925         {
1926           int i;
1927           
1928           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1929             {
1930               operands[2] = force_reg (SImode,
1931                                        GEN_INT (~INTVAL (operands[2])));
1932               
1933               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1934               
1935               DONE;
1936             }
1937
1938           for (i = 9; i <= 31; i++)
1939             {
1940               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1941                 {
1942                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1943                                         const0_rtx));
1944                   DONE;
1945                 }
1946               else if ((((HOST_WIDE_INT) 1) << i) - 1
1947                        == ~INTVAL (operands[2]))
1948                 {
1949                   rtx shift = GEN_INT (i);
1950                   rtx reg = gen_reg_rtx (SImode);
1951                 
1952                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1953                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1954                   
1955                   DONE;
1956                 }
1957             }
1958
1959           operands[2] = force_reg (SImode, operands[2]);
1960         }
1961     }
1962   "
1963 )
1964
1965 ; ??? Check split length for Thumb-2
1966 (define_insn_and_split "*arm_andsi3_insn"
1967   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1968         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1969                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1970   "TARGET_32BIT"
1971   "@
1972    and%?\\t%0, %1, %2
1973    bic%?\\t%0, %1, #%B2
1974    #"
1975   "TARGET_32BIT
1976    && GET_CODE (operands[2]) == CONST_INT
1977    && !(const_ok_for_arm (INTVAL (operands[2]))
1978         || const_ok_for_arm (~INTVAL (operands[2])))"
1979   [(clobber (const_int 0))]
1980   "
1981   arm_split_constant  (AND, SImode, curr_insn, 
1982                        INTVAL (operands[2]), operands[0], operands[1], 0);
1983   DONE;
1984   "
1985   [(set_attr "length" "4,4,16")
1986    (set_attr "predicable" "yes")]
1987 )
1988
1989 (define_insn "*thumb1_andsi3_insn"
1990   [(set (match_operand:SI         0 "register_operand" "=l")
1991         (and:SI (match_operand:SI 1 "register_operand" "%0")
1992                 (match_operand:SI 2 "register_operand" "l")))]
1993   "TARGET_THUMB1"
1994   "and\\t%0, %0, %2"
1995   [(set_attr "length" "2")]
1996 )
1997
1998 (define_insn "*andsi3_compare0"
1999   [(set (reg:CC_NOOV CC_REGNUM)
2000         (compare:CC_NOOV
2001          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
2002                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
2003          (const_int 0)))
2004    (set (match_operand:SI          0 "s_register_operand" "=r,r")
2005         (and:SI (match_dup 1) (match_dup 2)))]
2006   "TARGET_32BIT"
2007   "@
2008    and%.\\t%0, %1, %2
2009    bic%.\\t%0, %1, #%B2"
2010   [(set_attr "conds" "set")]
2011 )
2012
2013 (define_insn "*andsi3_compare0_scratch"
2014   [(set (reg:CC_NOOV CC_REGNUM)
2015         (compare:CC_NOOV
2016          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
2017                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
2018          (const_int 0)))
2019    (clobber (match_scratch:SI 2 "=X,r"))]
2020   "TARGET_32BIT"
2021   "@
2022    tst%?\\t%0, %1
2023    bic%.\\t%2, %0, #%B1"
2024   [(set_attr "conds" "set")]
2025 )
2026
2027 (define_insn "*zeroextractsi_compare0_scratch"
2028   [(set (reg:CC_NOOV CC_REGNUM)
2029         (compare:CC_NOOV (zero_extract:SI
2030                           (match_operand:SI 0 "s_register_operand" "r")
2031                           (match_operand 1 "const_int_operand" "n")
2032                           (match_operand 2 "const_int_operand" "n"))
2033                          (const_int 0)))]
2034   "TARGET_32BIT
2035   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2036       && INTVAL (operands[1]) > 0 
2037       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2038       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
2039   "*
2040   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2041                          << INTVAL (operands[2]));
2042   output_asm_insn (\"tst%?\\t%0, %1\", operands);
2043   return \"\";
2044   "
2045   [(set_attr "conds" "set")]
2046 )
2047
2048 (define_insn_and_split "*ne_zeroextractsi"
2049   [(set (match_operand:SI 0 "s_register_operand" "=r")
2050         (ne:SI (zero_extract:SI
2051                 (match_operand:SI 1 "s_register_operand" "r")
2052                 (match_operand:SI 2 "const_int_operand" "n")
2053                 (match_operand:SI 3 "const_int_operand" "n"))
2054                (const_int 0)))
2055    (clobber (reg:CC CC_REGNUM))]
2056   "TARGET_32BIT
2057    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2058        && INTVAL (operands[2]) > 0 
2059        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2060        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2061   "#"
2062   "TARGET_32BIT
2063    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2064        && INTVAL (operands[2]) > 0 
2065        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2066        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2067   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2068                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2069                                     (const_int 0)))
2070               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2071    (set (match_dup 0)
2072         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2073                          (match_dup 0) (const_int 1)))]
2074   "
2075   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2076                          << INTVAL (operands[3])); 
2077   "
2078   [(set_attr "conds" "clob")
2079    (set (attr "length")
2080         (if_then_else (eq_attr "is_thumb" "yes")
2081                       (const_int 12)
2082                       (const_int 8)))]
2083 )
2084
2085 (define_insn_and_split "*ne_zeroextractsi_shifted"
2086   [(set (match_operand:SI 0 "s_register_operand" "=r")
2087         (ne:SI (zero_extract:SI
2088                 (match_operand:SI 1 "s_register_operand" "r")
2089                 (match_operand:SI 2 "const_int_operand" "n")
2090                 (const_int 0))
2091                (const_int 0)))
2092    (clobber (reg:CC CC_REGNUM))]
2093   "TARGET_ARM"
2094   "#"
2095   "TARGET_ARM"
2096   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2097                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2098                                     (const_int 0)))
2099               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2100    (set (match_dup 0)
2101         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2102                          (match_dup 0) (const_int 1)))]
2103   "
2104   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2105   "
2106   [(set_attr "conds" "clob")
2107    (set_attr "length" "8")]
2108 )
2109
2110 (define_insn_and_split "*ite_ne_zeroextractsi"
2111   [(set (match_operand:SI 0 "s_register_operand" "=r")
2112         (if_then_else:SI (ne (zero_extract:SI
2113                               (match_operand:SI 1 "s_register_operand" "r")
2114                               (match_operand:SI 2 "const_int_operand" "n")
2115                               (match_operand:SI 3 "const_int_operand" "n"))
2116                              (const_int 0))
2117                          (match_operand:SI 4 "arm_not_operand" "rIK")
2118                          (const_int 0)))
2119    (clobber (reg:CC CC_REGNUM))]
2120   "TARGET_ARM
2121    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2122        && INTVAL (operands[2]) > 0 
2123        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2124        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2125    && !reg_overlap_mentioned_p (operands[0], operands[4])"
2126   "#"
2127   "TARGET_ARM
2128    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2129        && INTVAL (operands[2]) > 0 
2130        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2131        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2132    && !reg_overlap_mentioned_p (operands[0], operands[4])"
2133   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2134                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2135                                     (const_int 0)))
2136               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2137    (set (match_dup 0)
2138         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2139                          (match_dup 0) (match_dup 4)))]
2140   "
2141   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2142                          << INTVAL (operands[3])); 
2143   "
2144   [(set_attr "conds" "clob")
2145    (set_attr "length" "8")]
2146 )
2147
2148 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2149   [(set (match_operand:SI 0 "s_register_operand" "=r")
2150         (if_then_else:SI (ne (zero_extract:SI
2151                               (match_operand:SI 1 "s_register_operand" "r")
2152                               (match_operand:SI 2 "const_int_operand" "n")
2153                               (const_int 0))
2154                              (const_int 0))
2155                          (match_operand:SI 3 "arm_not_operand" "rIK")
2156                          (const_int 0)))
2157    (clobber (reg:CC CC_REGNUM))]
2158   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2159   "#"
2160   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2161   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2162                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2163                                     (const_int 0)))
2164               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2165    (set (match_dup 0)
2166         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2167                          (match_dup 0) (match_dup 3)))]
2168   "
2169   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2170   "
2171   [(set_attr "conds" "clob")
2172    (set_attr "length" "8")]
2173 )
2174
2175 (define_split
2176   [(set (match_operand:SI 0 "s_register_operand" "")
2177         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
2178                          (match_operand:SI 2 "const_int_operand" "")
2179                          (match_operand:SI 3 "const_int_operand" "")))
2180    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2181   "TARGET_THUMB1"
2182   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
2183    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
2184   "{
2185      HOST_WIDE_INT temp = INTVAL (operands[2]);
2186
2187      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2188      operands[3] = GEN_INT (32 - temp);
2189    }"
2190 )
2191
2192 ;; ??? Use Thumb-2 has bitfield insert/extract instructions.
2193 (define_split
2194   [(set (match_operand:SI 0 "s_register_operand" "")
2195         (match_operator:SI 1 "shiftable_operator"
2196          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2197                            (match_operand:SI 3 "const_int_operand" "")
2198                            (match_operand:SI 4 "const_int_operand" ""))
2199           (match_operand:SI 5 "s_register_operand" "")]))
2200    (clobber (match_operand:SI 6 "s_register_operand" ""))]
2201   "TARGET_ARM"
2202   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2203    (set (match_dup 0)
2204         (match_op_dup 1
2205          [(lshiftrt:SI (match_dup 6) (match_dup 4))
2206           (match_dup 5)]))]
2207   "{
2208      HOST_WIDE_INT temp = INTVAL (operands[3]);
2209
2210      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2211      operands[4] = GEN_INT (32 - temp);
2212    }"
2213 )
2214   
2215 (define_split
2216   [(set (match_operand:SI 0 "s_register_operand" "")
2217         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2218                          (match_operand:SI 2 "const_int_operand" "")
2219                          (match_operand:SI 3 "const_int_operand" "")))]
2220   "TARGET_THUMB1"
2221   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2222    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2223   "{
2224      HOST_WIDE_INT temp = INTVAL (operands[2]);
2225
2226      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2227      operands[3] = GEN_INT (32 - temp);
2228    }"
2229 )
2230
2231 (define_split
2232   [(set (match_operand:SI 0 "s_register_operand" "")
2233         (match_operator:SI 1 "shiftable_operator"
2234          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2235                            (match_operand:SI 3 "const_int_operand" "")
2236                            (match_operand:SI 4 "const_int_operand" ""))
2237           (match_operand:SI 5 "s_register_operand" "")]))
2238    (clobber (match_operand:SI 6 "s_register_operand" ""))]
2239   "TARGET_ARM"
2240   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2241    (set (match_dup 0)
2242         (match_op_dup 1
2243          [(ashiftrt:SI (match_dup 6) (match_dup 4))
2244           (match_dup 5)]))]
2245   "{
2246      HOST_WIDE_INT temp = INTVAL (operands[3]);
2247
2248      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2249      operands[4] = GEN_INT (32 - temp);
2250    }"
2251 )
2252   
2253 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
2254 ;;; represented by the bitfield, then this will produce incorrect results.
2255 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
2256 ;;; which have a real bit-field insert instruction, the truncation happens
2257 ;;; in the bit-field insert instruction itself.  Since arm does not have a
2258 ;;; bit-field insert instruction, we would have to emit code here to truncate
2259 ;;; the value before we insert.  This loses some of the advantage of having
2260 ;;; this insv pattern, so this pattern needs to be reevalutated.
2261
2262 (define_expand "insv"
2263   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
2264                          (match_operand:SI 1 "general_operand" "")
2265                          (match_operand:SI 2 "general_operand" ""))
2266         (match_operand:SI 3 "reg_or_int_operand" ""))]
2267   "TARGET_ARM || arm_arch_thumb2"
2268   "
2269   {
2270     int start_bit = INTVAL (operands[2]);
2271     int width = INTVAL (operands[1]);
2272     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2273     rtx target, subtarget;
2274
2275     if (arm_arch_thumb2)
2276       {
2277         bool use_bfi = TRUE;
2278
2279         if (GET_CODE (operands[3]) == CONST_INT)
2280           {
2281             HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2282
2283             if (val == 0)
2284               {
2285                 emit_insn (gen_insv_zero (operands[0], operands[1],
2286                                           operands[2]));
2287                 DONE;
2288               }
2289
2290             /* See if the set can be done with a single orr instruction.  */
2291             if (val == mask && const_ok_for_arm (val << start_bit))
2292               use_bfi = FALSE;
2293           }
2294           
2295         if (use_bfi)
2296           {
2297             if (GET_CODE (operands[3]) != REG)
2298               operands[3] = force_reg (SImode, operands[3]);
2299
2300             emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2301                                     operands[3]));
2302             DONE;
2303           }
2304       }
2305
2306     target = copy_rtx (operands[0]);
2307     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
2308        subreg as the final target.  */
2309     if (GET_CODE (target) == SUBREG)
2310       {
2311         subtarget = gen_reg_rtx (SImode);
2312         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2313             < GET_MODE_SIZE (SImode))
2314           target = SUBREG_REG (target);
2315       }
2316     else
2317       subtarget = target;    
2318
2319     if (GET_CODE (operands[3]) == CONST_INT)
2320       {
2321         /* Since we are inserting a known constant, we may be able to
2322            reduce the number of bits that we have to clear so that
2323            the mask becomes simple.  */
2324         /* ??? This code does not check to see if the new mask is actually
2325            simpler.  It may not be.  */
2326         rtx op1 = gen_reg_rtx (SImode);
2327         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
2328            start of this pattern.  */
2329         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2330         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2331
2332         emit_insn (gen_andsi3 (op1, operands[0],
2333                                gen_int_mode (~mask2, SImode)));
2334         emit_insn (gen_iorsi3 (subtarget, op1,
2335                                gen_int_mode (op3_value << start_bit, SImode)));
2336       }
2337     else if (start_bit == 0
2338              && !(const_ok_for_arm (mask)
2339                   || const_ok_for_arm (~mask)))
2340       {
2341         /* A Trick, since we are setting the bottom bits in the word,
2342            we can shift operand[3] up, operand[0] down, OR them together
2343            and rotate the result back again.  This takes 3 insns, and
2344            the third might be mergeable into another op.  */
2345         /* The shift up copes with the possibility that operand[3] is
2346            wider than the bitfield.  */
2347         rtx op0 = gen_reg_rtx (SImode);
2348         rtx op1 = gen_reg_rtx (SImode);
2349
2350         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2351         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2352         emit_insn (gen_iorsi3  (op1, op1, op0));
2353         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2354       }
2355     else if ((width + start_bit == 32)
2356              && !(const_ok_for_arm (mask)
2357                   || const_ok_for_arm (~mask)))
2358       {
2359         /* Similar trick, but slightly less efficient.  */
2360
2361         rtx op0 = gen_reg_rtx (SImode);
2362         rtx op1 = gen_reg_rtx (SImode);
2363
2364         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2365         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2366         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2367         emit_insn (gen_iorsi3 (subtarget, op1, op0));
2368       }
2369     else
2370       {
2371         rtx op0 = gen_int_mode (mask, SImode);
2372         rtx op1 = gen_reg_rtx (SImode);
2373         rtx op2 = gen_reg_rtx (SImode);
2374
2375         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2376           {
2377             rtx tmp = gen_reg_rtx (SImode);
2378
2379             emit_insn (gen_movsi (tmp, op0));
2380             op0 = tmp;
2381           }
2382
2383         /* Mask out any bits in operand[3] that are not needed.  */
2384            emit_insn (gen_andsi3 (op1, operands[3], op0));
2385
2386         if (GET_CODE (op0) == CONST_INT
2387             && (const_ok_for_arm (mask << start_bit)
2388                 || const_ok_for_arm (~(mask << start_bit))))
2389           {
2390             op0 = gen_int_mode (~(mask << start_bit), SImode);
2391             emit_insn (gen_andsi3 (op2, operands[0], op0));
2392           }
2393         else
2394           {
2395             if (GET_CODE (op0) == CONST_INT)
2396               {
2397                 rtx tmp = gen_reg_rtx (SImode);
2398
2399                 emit_insn (gen_movsi (tmp, op0));
2400                 op0 = tmp;
2401               }
2402
2403             if (start_bit != 0)
2404               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
2405             
2406             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2407           }
2408
2409         if (start_bit != 0)
2410           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
2411
2412         emit_insn (gen_iorsi3 (subtarget, op1, op2));
2413       }
2414
2415     if (subtarget != target)
2416       {
2417         /* If TARGET is still a SUBREG, then it must be wider than a word,
2418            so we must be careful only to set the subword we were asked to.  */
2419         if (GET_CODE (target) == SUBREG)
2420           emit_move_insn (target, subtarget);
2421         else
2422           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2423       }
2424
2425     DONE;
2426   }"
2427 )
2428
2429 (define_insn "insv_zero"
2430   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2431                          (match_operand:SI 1 "const_int_operand" "M")
2432                          (match_operand:SI 2 "const_int_operand" "M"))
2433         (const_int 0))]
2434   "arm_arch_thumb2"
2435   "bfc%?\t%0, %2, %1"
2436   [(set_attr "length" "4")
2437    (set_attr "predicable" "yes")]
2438 )
2439
2440 (define_insn "insv_t2"
2441   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2442                          (match_operand:SI 1 "const_int_operand" "M")
2443                          (match_operand:SI 2 "const_int_operand" "M"))
2444         (match_operand:SI 3 "s_register_operand" "r"))]
2445   "arm_arch_thumb2"
2446   "bfi%?\t%0, %3, %2, %1"
2447   [(set_attr "length" "4")
2448    (set_attr "predicable" "yes")]
2449 )
2450
2451 ; constants for op 2 will never be given to these patterns.
2452 (define_insn_and_split "*anddi_notdi_di"
2453   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2454         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2455                 (match_operand:DI 2 "s_register_operand" "r,0")))]
2456   "TARGET_32BIT"
2457   "#"
2458   "TARGET_32BIT && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2459   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2460    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2461   "
2462   {
2463     operands[3] = gen_highpart (SImode, operands[0]);
2464     operands[0] = gen_lowpart (SImode, operands[0]);
2465     operands[4] = gen_highpart (SImode, operands[1]);
2466     operands[1] = gen_lowpart (SImode, operands[1]);
2467     operands[5] = gen_highpart (SImode, operands[2]);
2468     operands[2] = gen_lowpart (SImode, operands[2]);
2469   }"
2470   [(set_attr "length" "8")
2471    (set_attr "predicable" "yes")]
2472 )
2473   
2474 (define_insn_and_split "*anddi_notzesidi_di"
2475   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2476         (and:DI (not:DI (zero_extend:DI
2477                          (match_operand:SI 2 "s_register_operand" "r,r")))
2478                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2479   "TARGET_32BIT"
2480   "@
2481    bic%?\\t%Q0, %Q1, %2
2482    #"
2483   ; (not (zero_extend ...)) allows us to just copy the high word from
2484   ; operand1 to operand0.
2485   "TARGET_32BIT
2486    && reload_completed
2487    && operands[0] != operands[1]"
2488   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2489    (set (match_dup 3) (match_dup 4))]
2490   "
2491   {
2492     operands[3] = gen_highpart (SImode, operands[0]);
2493     operands[0] = gen_lowpart (SImode, operands[0]);
2494     operands[4] = gen_highpart (SImode, operands[1]);
2495     operands[1] = gen_lowpart (SImode, operands[1]);
2496   }"
2497   [(set_attr "length" "4,8")
2498    (set_attr "predicable" "yes")]
2499 )
2500   
2501 (define_insn_and_split "*anddi_notsesidi_di"
2502   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2503         (and:DI (not:DI (sign_extend:DI
2504                          (match_operand:SI 2 "s_register_operand" "r,r")))
2505                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2506   "TARGET_32BIT"
2507   "#"
2508   "TARGET_32BIT && reload_completed"
2509   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2510    (set (match_dup 3) (and:SI (not:SI
2511                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2512                                (match_dup 4)))]
2513   "
2514   {
2515     operands[3] = gen_highpart (SImode, operands[0]);
2516     operands[0] = gen_lowpart (SImode, operands[0]);
2517     operands[4] = gen_highpart (SImode, operands[1]);
2518     operands[1] = gen_lowpart (SImode, operands[1]);
2519   }"
2520   [(set_attr "length" "8")
2521    (set_attr "predicable" "yes")]
2522 )
2523   
2524 (define_insn "andsi_notsi_si"
2525   [(set (match_operand:SI 0 "s_register_operand" "=r")
2526         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2527                 (match_operand:SI 1 "s_register_operand" "r")))]
2528   "TARGET_32BIT"
2529   "bic%?\\t%0, %1, %2"
2530   [(set_attr "predicable" "yes")]
2531 )
2532
2533 (define_insn "bicsi3"
2534   [(set (match_operand:SI                 0 "register_operand" "=l")
2535         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2536                 (match_operand:SI         2 "register_operand" "0")))]
2537   "TARGET_THUMB1"
2538   "bic\\t%0, %0, %1"
2539   [(set_attr "length" "2")]
2540 )
2541
2542 (define_insn "andsi_not_shiftsi_si"
2543   [(set (match_operand:SI 0 "s_register_operand" "=r")
2544         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2545                          [(match_operand:SI 2 "s_register_operand" "r")
2546                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2547                 (match_operand:SI 1 "s_register_operand" "r")))]
2548   "TARGET_ARM"
2549   "bic%?\\t%0, %1, %2%S4"
2550   [(set_attr "predicable" "yes")
2551    (set_attr "shift" "2")
2552    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2553                       (const_string "alu_shift")
2554                       (const_string "alu_shift_reg")))]
2555 )
2556
2557 (define_insn "*andsi_notsi_si_compare0"
2558   [(set (reg:CC_NOOV CC_REGNUM)
2559         (compare:CC_NOOV
2560          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2561                  (match_operand:SI 1 "s_register_operand" "r"))
2562          (const_int 0)))
2563    (set (match_operand:SI 0 "s_register_operand" "=r")
2564         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2565   "TARGET_32BIT"
2566   "bic%.\\t%0, %1, %2"
2567   [(set_attr "conds" "set")]
2568 )
2569
2570 (define_insn "*andsi_notsi_si_compare0_scratch"
2571   [(set (reg:CC_NOOV CC_REGNUM)
2572         (compare:CC_NOOV
2573          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2574                  (match_operand:SI 1 "s_register_operand" "r"))
2575          (const_int 0)))
2576    (clobber (match_scratch:SI 0 "=r"))]
2577   "TARGET_32BIT"
2578   "bic%.\\t%0, %1, %2"
2579   [(set_attr "conds" "set")]
2580 )
2581
2582 (define_insn "iordi3"
2583   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2584         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2585                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2586   "TARGET_32BIT && ! TARGET_IWMMXT"
2587   "#"
2588   [(set_attr "length" "8")
2589    (set_attr "predicable" "yes")]
2590 )
2591
2592 (define_insn "*iordi_zesidi_di"
2593   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2594         (ior:DI (zero_extend:DI
2595                  (match_operand:SI 2 "s_register_operand" "r,r"))
2596                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2597   "TARGET_32BIT"
2598   "@
2599    orr%?\\t%Q0, %Q1, %2
2600    #"
2601   [(set_attr "length" "4,8")
2602    (set_attr "predicable" "yes")]
2603 )
2604
2605 (define_insn "*iordi_sesidi_di"
2606   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2607         (ior:DI (sign_extend:DI
2608                  (match_operand:SI 2 "s_register_operand" "r,r"))
2609                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2610   "TARGET_32BIT"
2611   "#"
2612   [(set_attr "length" "8")
2613    (set_attr "predicable" "yes")]
2614 )
2615
2616 (define_expand "iorsi3"
2617   [(set (match_operand:SI         0 "s_register_operand" "")
2618         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2619                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2620   "TARGET_EITHER"
2621   "
2622   if (GET_CODE (operands[2]) == CONST_INT)
2623     {
2624       if (TARGET_32BIT)
2625         {
2626           arm_split_constant (IOR, SImode, NULL_RTX,
2627                               INTVAL (operands[2]), operands[0], operands[1],
2628                               optimize && can_create_pseudo_p ());
2629           DONE;
2630         }
2631       else /* TARGET_THUMB1 */
2632         {
2633           rtx tmp = force_reg (SImode, operands[2]);
2634           if (rtx_equal_p (operands[0], operands[1]))
2635             operands[2] = tmp;
2636           else
2637             {
2638               operands[2] = operands[1];
2639               operands[1] = tmp;
2640             }
2641         }
2642     }
2643   "
2644 )
2645
2646 (define_insn_and_split "*arm_iorsi3"
2647   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2648         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2649                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2650   "TARGET_ARM"
2651   "@
2652    orr%?\\t%0, %1, %2
2653    #"
2654   "TARGET_ARM
2655    && GET_CODE (operands[2]) == CONST_INT
2656    && !const_ok_for_arm (INTVAL (operands[2]))"
2657   [(clobber (const_int 0))]
2658   "
2659   arm_split_constant (IOR, SImode, curr_insn, 
2660                       INTVAL (operands[2]), operands[0], operands[1], 0);
2661   DONE;
2662   "
2663   [(set_attr "length" "4,16")
2664    (set_attr "predicable" "yes")]
2665 )
2666
2667 (define_insn "*thumb1_iorsi3"
2668   [(set (match_operand:SI         0 "register_operand" "=l")
2669         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2670                 (match_operand:SI 2 "register_operand" "l")))]
2671   "TARGET_THUMB1"
2672   "orr\\t%0, %0, %2"
2673   [(set_attr "length" "2")]
2674 )
2675
2676 (define_peephole2
2677   [(match_scratch:SI 3 "r")
2678    (set (match_operand:SI 0 "arm_general_register_operand" "")
2679         (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2680                 (match_operand:SI 2 "const_int_operand" "")))]
2681   "TARGET_ARM
2682    && !const_ok_for_arm (INTVAL (operands[2]))
2683    && const_ok_for_arm (~INTVAL (operands[2]))"
2684   [(set (match_dup 3) (match_dup 2))
2685    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2686   ""
2687 )
2688
2689 (define_insn "*iorsi3_compare0"
2690   [(set (reg:CC_NOOV CC_REGNUM)
2691         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2692                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2693                          (const_int 0)))
2694    (set (match_operand:SI 0 "s_register_operand" "=r")
2695         (ior:SI (match_dup 1) (match_dup 2)))]
2696   "TARGET_32BIT"
2697   "orr%.\\t%0, %1, %2"
2698   [(set_attr "conds" "set")]
2699 )
2700
2701 (define_insn "*iorsi3_compare0_scratch"
2702   [(set (reg:CC_NOOV CC_REGNUM)
2703         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2704                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2705                          (const_int 0)))
2706    (clobber (match_scratch:SI 0 "=r"))]
2707   "TARGET_32BIT"
2708   "orr%.\\t%0, %1, %2"
2709   [(set_attr "conds" "set")]
2710 )
2711
2712 (define_insn "xordi3"
2713   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2714         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2715                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2716   "TARGET_32BIT && !TARGET_IWMMXT"
2717   "#"
2718   [(set_attr "length" "8")
2719    (set_attr "predicable" "yes")]
2720 )
2721
2722 (define_insn "*xordi_zesidi_di"
2723   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2724         (xor:DI (zero_extend:DI
2725                  (match_operand:SI 2 "s_register_operand" "r,r"))
2726                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2727   "TARGET_32BIT"
2728   "@
2729    eor%?\\t%Q0, %Q1, %2
2730    #"
2731   [(set_attr "length" "4,8")
2732    (set_attr "predicable" "yes")]
2733 )
2734
2735 (define_insn "*xordi_sesidi_di"
2736   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2737         (xor:DI (sign_extend:DI
2738                  (match_operand:SI 2 "s_register_operand" "r,r"))
2739                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2740   "TARGET_32BIT"
2741   "#"
2742   [(set_attr "length" "8")
2743    (set_attr "predicable" "yes")]
2744 )
2745
2746 (define_expand "xorsi3"
2747   [(set (match_operand:SI         0 "s_register_operand" "")
2748         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2749                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2750   "TARGET_EITHER"
2751   "if (GET_CODE (operands[2]) == CONST_INT)
2752     {
2753       if (TARGET_32BIT)
2754         {
2755           arm_split_constant (XOR, SImode, NULL_RTX,
2756                               INTVAL (operands[2]), operands[0], operands[1],
2757                               optimize && can_create_pseudo_p ());
2758           DONE;
2759         }
2760       else /* TARGET_THUMB1 */
2761         {
2762           rtx tmp = force_reg (SImode, operands[2]);
2763           if (rtx_equal_p (operands[0], operands[1]))
2764             operands[2] = tmp;
2765           else
2766             {
2767               operands[2] = operands[1];
2768               operands[1] = tmp;
2769             }
2770         }
2771     }"
2772 )
2773
2774 (define_insn "*arm_xorsi3"
2775   [(set (match_operand:SI         0 "s_register_operand" "=r")
2776         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2777                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2778   "TARGET_32BIT"
2779   "eor%?\\t%0, %1, %2"
2780   [(set_attr "predicable" "yes")]
2781 )
2782
2783 (define_insn "*thumb1_xorsi3"
2784   [(set (match_operand:SI         0 "register_operand" "=l")
2785         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2786                 (match_operand:SI 2 "register_operand" "l")))]
2787   "TARGET_THUMB1"
2788   "eor\\t%0, %0, %2"
2789   [(set_attr "length" "2")]
2790 )
2791
2792 (define_insn "*xorsi3_compare0"
2793   [(set (reg:CC_NOOV CC_REGNUM)
2794         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2795                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2796                          (const_int 0)))
2797    (set (match_operand:SI 0 "s_register_operand" "=r")
2798         (xor:SI (match_dup 1) (match_dup 2)))]
2799   "TARGET_32BIT"
2800   "eor%.\\t%0, %1, %2"
2801   [(set_attr "conds" "set")]
2802 )
2803
2804 (define_insn "*xorsi3_compare0_scratch"
2805   [(set (reg:CC_NOOV CC_REGNUM)
2806         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2807                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2808                          (const_int 0)))]
2809   "TARGET_32BIT"
2810   "teq%?\\t%0, %1"
2811   [(set_attr "conds" "set")]
2812 )
2813
2814 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2815 ; (NOT D) we can sometimes merge the final NOT into one of the following
2816 ; insns.
2817
2818 (define_split
2819   [(set (match_operand:SI 0 "s_register_operand" "")
2820         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2821                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2822                 (match_operand:SI 3 "arm_rhs_operand" "")))
2823    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2824   "TARGET_32BIT"
2825   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2826                               (not:SI (match_dup 3))))
2827    (set (match_dup 0) (not:SI (match_dup 4)))]
2828   ""
2829 )
2830
2831 (define_insn "*andsi_iorsi3_notsi"
2832   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2833         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
2834                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2835                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2836   "TARGET_32BIT"
2837   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2838   [(set_attr "length" "8")
2839    (set_attr "ce_count" "2")
2840    (set_attr "predicable" "yes")]
2841 )
2842
2843 ; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
2844 ; insns are available?
2845 (define_split
2846   [(set (match_operand:SI 0 "s_register_operand" "")
2847         (match_operator:SI 1 "logical_binary_operator"
2848          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2849                            (match_operand:SI 3 "const_int_operand" "")
2850                            (match_operand:SI 4 "const_int_operand" ""))
2851           (match_operator:SI 9 "logical_binary_operator"
2852            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2853                          (match_operand:SI 6 "const_int_operand" ""))
2854             (match_operand:SI 7 "s_register_operand" "")])]))
2855    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2856   "TARGET_32BIT
2857    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2858    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2859   [(set (match_dup 8)
2860         (match_op_dup 1
2861          [(ashift:SI (match_dup 2) (match_dup 4))
2862           (match_dup 5)]))
2863    (set (match_dup 0)
2864         (match_op_dup 1
2865          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2866           (match_dup 7)]))]
2867   "
2868   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2869 ")
2870
2871 (define_split
2872   [(set (match_operand:SI 0 "s_register_operand" "")
2873         (match_operator:SI 1 "logical_binary_operator"
2874          [(match_operator:SI 9 "logical_binary_operator"
2875            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2876                          (match_operand:SI 6 "const_int_operand" ""))
2877             (match_operand:SI 7 "s_register_operand" "")])
2878           (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2879                            (match_operand:SI 3 "const_int_operand" "")
2880                            (match_operand:SI 4 "const_int_operand" ""))]))
2881    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2882   "TARGET_32BIT
2883    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2884    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2885   [(set (match_dup 8)
2886         (match_op_dup 1
2887          [(ashift:SI (match_dup 2) (match_dup 4))
2888           (match_dup 5)]))
2889    (set (match_dup 0)
2890         (match_op_dup 1
2891          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2892           (match_dup 7)]))]
2893   "
2894   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2895 ")
2896
2897 (define_split
2898   [(set (match_operand:SI 0 "s_register_operand" "")
2899         (match_operator:SI 1 "logical_binary_operator"
2900          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2901                            (match_operand:SI 3 "const_int_operand" "")
2902                            (match_operand:SI 4 "const_int_operand" ""))
2903           (match_operator:SI 9 "logical_binary_operator"
2904            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2905                          (match_operand:SI 6 "const_int_operand" ""))
2906             (match_operand:SI 7 "s_register_operand" "")])]))
2907    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2908   "TARGET_32BIT
2909    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2910    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2911   [(set (match_dup 8)
2912         (match_op_dup 1
2913          [(ashift:SI (match_dup 2) (match_dup 4))
2914           (match_dup 5)]))
2915    (set (match_dup 0)
2916         (match_op_dup 1
2917          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2918           (match_dup 7)]))]
2919   "
2920   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2921 ")
2922
2923 (define_split
2924   [(set (match_operand:SI 0 "s_register_operand" "")
2925         (match_operator:SI 1 "logical_binary_operator"
2926          [(match_operator:SI 9 "logical_binary_operator"
2927            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2928                          (match_operand:SI 6 "const_int_operand" ""))
2929             (match_operand:SI 7 "s_register_operand" "")])
2930           (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2931                            (match_operand:SI 3 "const_int_operand" "")
2932                            (match_operand:SI 4 "const_int_operand" ""))]))
2933    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2934   "TARGET_32BIT
2935    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2936    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2937   [(set (match_dup 8)
2938         (match_op_dup 1
2939          [(ashift:SI (match_dup 2) (match_dup 4))
2940           (match_dup 5)]))
2941    (set (match_dup 0)
2942         (match_op_dup 1
2943          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2944           (match_dup 7)]))]
2945   "
2946   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2947 ")
2948 \f
2949
2950 ;; Minimum and maximum insns
2951
2952 (define_expand "smaxsi3"
2953   [(parallel [
2954     (set (match_operand:SI 0 "s_register_operand" "")
2955          (smax:SI (match_operand:SI 1 "s_register_operand" "")
2956                   (match_operand:SI 2 "arm_rhs_operand" "")))
2957     (clobber (reg:CC CC_REGNUM))])]
2958   "TARGET_32BIT"
2959   "
2960   if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
2961     {
2962       /* No need for a clobber of the condition code register here.  */
2963       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2964                               gen_rtx_SMAX (SImode, operands[1],
2965                                             operands[2])));
2966       DONE;
2967     }
2968 ")
2969
2970 (define_insn "*smax_0"
2971   [(set (match_operand:SI 0 "s_register_operand" "=r")
2972         (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2973                  (const_int 0)))]
2974   "TARGET_32BIT"
2975   "bic%?\\t%0, %1, %1, asr #31"
2976   [(set_attr "predicable" "yes")]
2977 )
2978
2979 (define_insn "*smax_m1"
2980   [(set (match_operand:SI 0 "s_register_operand" "=r")
2981         (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2982                  (const_int -1)))]
2983   "TARGET_32BIT"
2984   "orr%?\\t%0, %1, %1, asr #31"
2985   [(set_attr "predicable" "yes")]
2986 )
2987
2988 (define_insn "*arm_smax_insn"
2989   [(set (match_operand:SI          0 "s_register_operand" "=r,r")
2990         (smax:SI (match_operand:SI 1 "s_register_operand"  "%0,?r")
2991                  (match_operand:SI 2 "arm_rhs_operand"    "rI,rI")))
2992    (clobber (reg:CC CC_REGNUM))]
2993   "TARGET_ARM"
2994   "@
2995    cmp\\t%1, %2\;movlt\\t%0, %2
2996    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2997   [(set_attr "conds" "clob")
2998    (set_attr "length" "8,12")]
2999 )
3000
3001 (define_expand "sminsi3"
3002   [(parallel [
3003     (set (match_operand:SI 0 "s_register_operand" "")
3004          (smin:SI (match_operand:SI 1 "s_register_operand" "")
3005                   (match_operand:SI 2 "arm_rhs_operand" "")))
3006     (clobber (reg:CC CC_REGNUM))])]
3007   "TARGET_32BIT"
3008   "
3009   if (operands[2] == const0_rtx)
3010     {
3011       /* No need for a clobber of the condition code register here.  */
3012       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3013                               gen_rtx_SMIN (SImode, operands[1],
3014                                             operands[2])));
3015       DONE;
3016     }
3017 ")
3018
3019 (define_insn "*smin_0"
3020   [(set (match_operand:SI 0 "s_register_operand" "=r")
3021         (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3022                  (const_int 0)))]
3023   "TARGET_32BIT"
3024   "and%?\\t%0, %1, %1, asr #31"
3025   [(set_attr "predicable" "yes")]
3026 )
3027
3028 (define_insn "*arm_smin_insn"
3029   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3030         (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3031                  (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
3032    (clobber (reg:CC CC_REGNUM))]
3033   "TARGET_ARM"
3034   "@
3035    cmp\\t%1, %2\;movge\\t%0, %2
3036    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
3037   [(set_attr "conds" "clob")
3038    (set_attr "length" "8,12")]
3039 )
3040
3041 (define_expand "umaxsi3"
3042   [(parallel [
3043     (set (match_operand:SI 0 "s_register_operand" "")
3044          (umax:SI (match_operand:SI 1 "s_register_operand" "")
3045                   (match_operand:SI 2 "arm_rhs_operand" "")))
3046     (clobber (reg:CC CC_REGNUM))])]
3047   "TARGET_32BIT"
3048   ""
3049 )
3050
3051 (define_insn "*arm_umaxsi3"
3052   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3053         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3054                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
3055    (clobber (reg:CC CC_REGNUM))]
3056   "TARGET_ARM"
3057   "@
3058    cmp\\t%1, %2\;movcc\\t%0, %2
3059    cmp\\t%1, %2\;movcs\\t%0, %1
3060    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
3061   [(set_attr "conds" "clob")
3062    (set_attr "length" "8,8,12")]
3063 )
3064
3065 (define_expand "uminsi3"
3066   [(parallel [
3067     (set (match_operand:SI 0 "s_register_operand" "")
3068          (umin:SI (match_operand:SI 1 "s_register_operand" "")
3069                   (match_operand:SI 2 "arm_rhs_operand" "")))
3070     (clobber (reg:CC CC_REGNUM))])]
3071   "TARGET_32BIT"
3072   ""
3073 )
3074
3075 (define_insn "*arm_uminsi3"
3076   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3077         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3078                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
3079    (clobber (reg:CC CC_REGNUM))]
3080   "TARGET_ARM"
3081   "@
3082    cmp\\t%1, %2\;movcs\\t%0, %2
3083    cmp\\t%1, %2\;movcc\\t%0, %1
3084    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
3085   [(set_attr "conds" "clob")
3086    (set_attr "length" "8,8,12")]
3087 )
3088
3089 (define_insn "*store_minmaxsi"
3090   [(set (match_operand:SI 0 "memory_operand" "=m")
3091         (match_operator:SI 3 "minmax_operator"
3092          [(match_operand:SI 1 "s_register_operand" "r")
3093           (match_operand:SI 2 "s_register_operand" "r")]))
3094    (clobber (reg:CC CC_REGNUM))]
3095   "TARGET_32BIT"
3096   "*
3097   operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3098                                 operands[1], operands[2]);
3099   output_asm_insn (\"cmp\\t%1, %2\", operands);
3100   if (TARGET_THUMB2)
3101     output_asm_insn (\"ite\t%d3\", operands);
3102   output_asm_insn (\"str%d3\\t%1, %0\", operands);
3103   output_asm_insn (\"str%D3\\t%2, %0\", operands);
3104   return \"\";
3105   "
3106   [(set_attr "conds" "clob")
3107    (set (attr "length")
3108         (if_then_else (eq_attr "is_thumb" "yes")
3109                       (const_int 14)
3110                       (const_int 12)))
3111    (set_attr "type" "store1")]
3112 )
3113
3114 ; Reject the frame pointer in operand[1], since reloading this after
3115 ; it has been eliminated can cause carnage.
3116 (define_insn "*minmax_arithsi"
3117   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3118         (match_operator:SI 4 "shiftable_operator"
3119          [(match_operator:SI 5 "minmax_operator"
3120            [(match_operand:SI 2 "s_register_operand" "r,r")
3121             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3122           (match_operand:SI 1 "s_register_operand" "0,?r")]))
3123    (clobber (reg:CC CC_REGNUM))]
3124   "TARGET_32BIT && !arm_eliminable_register (operands[1])"
3125   "*
3126   {
3127     enum rtx_code code = GET_CODE (operands[4]);
3128     bool need_else;
3129
3130     if (which_alternative != 0 || operands[3] != const0_rtx
3131         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
3132       need_else = true;
3133     else
3134       need_else = false;
3135
3136     operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3137                                   operands[2], operands[3]);
3138     output_asm_insn (\"cmp\\t%2, %3\", operands);
3139     if (TARGET_THUMB2)
3140       {
3141         if (need_else)
3142           output_asm_insn (\"ite\\t%d5\", operands);
3143         else
3144           output_asm_insn (\"it\\t%d5\", operands);
3145       }
3146     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
3147     if (need_else)
3148       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3149     return \"\";
3150   }"
3151   [(set_attr "conds" "clob")
3152    (set (attr "length")
3153         (if_then_else (eq_attr "is_thumb" "yes")
3154                       (const_int 14)
3155                       (const_int 12)))]
3156 )
3157
3158 \f
3159 ;; Shift and rotation insns
3160
3161 (define_expand "ashldi3"
3162   [(set (match_operand:DI            0 "s_register_operand" "")
3163         (ashift:DI (match_operand:DI 1 "s_register_operand" "")
3164                    (match_operand:SI 2 "reg_or_int_operand" "")))]
3165   "TARGET_32BIT"
3166   "
3167   if (GET_CODE (operands[2]) == CONST_INT)
3168     {
3169       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3170         {
3171           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3172           DONE;
3173         }
3174         /* Ideally we shouldn't fail here if we could know that operands[1] 
3175            ends up already living in an iwmmxt register. Otherwise it's
3176            cheaper to have the alternate code being generated than moving
3177            values to iwmmxt regs and back.  */
3178         FAIL;
3179     }
3180   else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
3181     FAIL;
3182   "
3183 )
3184
3185 (define_insn "arm_ashldi3_1bit"
3186   [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
3187         (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
3188                    (const_int 1)))
3189    (clobber (reg:CC CC_REGNUM))]
3190   "TARGET_32BIT"
3191   "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
3192   [(set_attr "conds" "clob")
3193    (set_attr "length" "8")]
3194 )
3195
3196 (define_expand "ashlsi3"
3197   [(set (match_operand:SI            0 "s_register_operand" "")
3198         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3199                    (match_operand:SI 2 "arm_rhs_operand" "")))]
3200   "TARGET_EITHER"
3201   "
3202   if (GET_CODE (operands[2]) == CONST_INT
3203       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3204     {
3205       emit_insn (gen_movsi (operands[0], const0_rtx));
3206       DONE;
3207     }
3208   "
3209 )
3210
3211 (define_insn "*thumb1_ashlsi3"
3212   [(set (match_operand:SI            0 "register_operand" "=l,l")
3213         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
3214                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
3215   "TARGET_THUMB1"
3216   "lsl\\t%0, %1, %2"
3217   [(set_attr "length" "2")]
3218 )
3219
3220 (define_expand "ashrdi3"
3221   [(set (match_operand:DI              0 "s_register_operand" "")
3222         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3223                      (match_operand:SI 2 "reg_or_int_operand" "")))]
3224   "TARGET_32BIT"
3225   "
3226   if (GET_CODE (operands[2]) == CONST_INT)
3227     {
3228       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3229         {
3230           emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3231           DONE;
3232         }
3233         /* Ideally we shouldn't fail here if we could know that operands[1] 
3234            ends up already living in an iwmmxt register. Otherwise it's
3235            cheaper to have the alternate code being generated than moving
3236            values to iwmmxt regs and back.  */
3237         FAIL;
3238     }
3239   else if (!TARGET_REALLY_IWMMXT)
3240     FAIL;
3241   "
3242 )
3243
3244 (define_insn "arm_ashrdi3_1bit"
3245   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
3246         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
3247                      (const_int 1)))
3248    (clobber (reg:CC CC_REGNUM))]
3249   "TARGET_32BIT"
3250   "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
3251   [(set_attr "conds" "clob")
3252    (set_attr "length" "8")]
3253 )
3254
3255 (define_expand "ashrsi3"
3256   [(set (match_operand:SI              0 "s_register_operand" "")
3257         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3258                      (match_operand:SI 2 "arm_rhs_operand" "")))]
3259   "TARGET_EITHER"
3260   "
3261   if (GET_CODE (operands[2]) == CONST_INT
3262       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3263     operands[2] = GEN_INT (31);
3264   "
3265 )
3266
3267 (define_insn "*thumb1_ashrsi3"
3268   [(set (match_operand:SI              0 "register_operand" "=l,l")
3269         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3270                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
3271   "TARGET_THUMB1"
3272   "asr\\t%0, %1, %2"
3273   [(set_attr "length" "2")]
3274 )
3275
3276 (define_expand "lshrdi3"
3277   [(set (match_operand:DI              0 "s_register_operand" "")
3278         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3279                      (match_operand:SI 2 "reg_or_int_operand" "")))]
3280   "TARGET_32BIT"
3281   "
3282   if (GET_CODE (operands[2]) == CONST_INT)
3283     {
3284       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3285         {
3286           emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3287           DONE;
3288         }
3289         /* Ideally we shouldn't fail here if we could know that operands[1] 
3290            ends up already living in an iwmmxt register. Otherwise it's
3291            cheaper to have the alternate code being generated than moving
3292            values to iwmmxt regs and back.  */
3293         FAIL;
3294     }
3295   else if (!TARGET_REALLY_IWMMXT)
3296     FAIL;
3297   "
3298 )
3299
3300 (define_insn "arm_lshrdi3_1bit"
3301   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
3302         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
3303                      (const_int 1)))
3304    (clobber (reg:CC CC_REGNUM))]
3305   "TARGET_32BIT"
3306   "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
3307   [(set_attr "conds" "clob")
3308    (set_attr "length" "8")]
3309 )
3310
3311 (define_expand "lshrsi3"
3312   [(set (match_operand:SI              0 "s_register_operand" "")
3313         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3314                      (match_operand:SI 2 "arm_rhs_operand" "")))]
3315   "TARGET_EITHER"
3316   "
3317   if (GET_CODE (operands[2]) == CONST_INT
3318       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3319     {
3320       emit_insn (gen_movsi (operands[0], const0_rtx));
3321       DONE;
3322     }
3323   "
3324 )
3325
3326 (define_insn "*thumb1_lshrsi3"
3327   [(set (match_operand:SI              0 "register_operand" "=l,l")
3328         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3329                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
3330   "TARGET_THUMB1"
3331   "lsr\\t%0, %1, %2"
3332   [(set_attr "length" "2")]
3333 )
3334
3335 (define_expand "rotlsi3"
3336   [(set (match_operand:SI              0 "s_register_operand" "")
3337         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3338                      (match_operand:SI 2 "reg_or_int_operand" "")))]
3339   "TARGET_32BIT"
3340   "
3341   if (GET_CODE (operands[2]) == CONST_INT)
3342     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3343   else
3344     {
3345       rtx reg = gen_reg_rtx (SImode);
3346       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3347       operands[2] = reg;
3348     }
3349   "
3350 )
3351
3352 (define_expand "rotrsi3"
3353   [(set (match_operand:SI              0 "s_register_operand" "")
3354         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3355                      (match_operand:SI 2 "arm_rhs_operand" "")))]
3356   "TARGET_EITHER"
3357   "
3358   if (TARGET_32BIT)
3359     {
3360       if (GET_CODE (operands[2]) == CONST_INT
3361           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3362         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3363     }
3364   else /* TARGET_THUMB1 */
3365     {
3366       if (GET_CODE (operands [2]) == CONST_INT)
3367         operands [2] = force_reg (SImode, operands[2]);
3368     }
3369   "
3370 )
3371
3372 (define_insn "*thumb1_rotrsi3"
3373   [(set (match_operand:SI              0 "register_operand" "=l")
3374         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
3375                      (match_operand:SI 2 "register_operand" "l")))]
3376   "TARGET_THUMB1"
3377   "ror\\t%0, %0, %2"
3378   [(set_attr "length" "2")]
3379 )
3380
3381 (define_insn "*arm_shiftsi3"
3382   [(set (match_operand:SI   0 "s_register_operand" "=r")
3383         (match_operator:SI  3 "shift_operator"
3384          [(match_operand:SI 1 "s_register_operand"  "r")
3385           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
3386   "TARGET_32BIT"
3387   "* return arm_output_shift(operands, 0);"
3388   [(set_attr "predicable" "yes")
3389    (set_attr "shift" "1")
3390    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3391                       (const_string "alu_shift")
3392                       (const_string "alu_shift_reg")))]
3393 )
3394
3395 (define_insn "*shiftsi3_compare0"
3396   [(set (reg:CC_NOOV CC_REGNUM)
3397         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3398                           [(match_operand:SI 1 "s_register_operand" "r")
3399                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
3400                          (const_int 0)))
3401    (set (match_operand:SI 0 "s_register_operand" "=r")
3402         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
3403   "TARGET_32BIT"
3404   "* return arm_output_shift(operands, 1);"
3405   [(set_attr "conds" "set")
3406    (set_attr "shift" "1")
3407    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3408                       (const_string "alu_shift")
3409                       (const_string "alu_shift_reg")))]
3410 )
3411
3412 (define_insn "*shiftsi3_compare0_scratch"
3413   [(set (reg:CC_NOOV CC_REGNUM)
3414         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3415                           [(match_operand:SI 1 "s_register_operand" "r")
3416                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
3417                          (const_int 0)))
3418    (clobber (match_scratch:SI 0 "=r"))]
3419   "TARGET_32BIT"
3420   "* return arm_output_shift(operands, 1);"
3421   [(set_attr "conds" "set")
3422    (set_attr "shift" "1")]
3423 )
3424
3425 (define_insn "*arm_notsi_shiftsi"
3426   [(set (match_operand:SI 0 "s_register_operand" "=r")
3427         (not:SI (match_operator:SI 3 "shift_operator"
3428                  [(match_operand:SI 1 "s_register_operand" "r")
3429                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
3430   "TARGET_ARM"
3431   "mvn%?\\t%0, %1%S3"
3432   [(set_attr "predicable" "yes")
3433    (set_attr "shift" "1")
3434    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3435                       (const_string "alu_shift")
3436                       (const_string "alu_shift_reg")))]
3437 )
3438
3439 (define_insn "*arm_notsi_shiftsi_compare0"
3440   [(set (reg:CC_NOOV CC_REGNUM)
3441         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
3442                           [(match_operand:SI 1 "s_register_operand" "r")
3443                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
3444                          (const_int 0)))
3445    (set (match_operand:SI 0 "s_register_operand" "=r")
3446         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
3447   "TARGET_ARM"
3448   "mvn%.\\t%0, %1%S3"
3449   [(set_attr "conds" "set")
3450    (set_attr "shift" "1")
3451    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3452                       (const_string "alu_shift")
3453                       (const_string "alu_shift_reg")))]
3454 )
3455
3456 (define_insn "*arm_not_shiftsi_compare0_scratch"
3457   [(set (reg:CC_NOOV CC_REGNUM)
3458         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
3459                           [(match_operand:SI 1 "s_register_operand" "r")
3460                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
3461                          (const_int 0)))
3462    (clobber (match_scratch:SI 0 "=r"))]
3463   "TARGET_ARM"
3464   "mvn%.\\t%0, %1%S3"
3465   [(set_attr "conds" "set")
3466    (set_attr "shift" "1")
3467    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3468                       (const_string "alu_shift")
3469                       (const_string "alu_shift_reg")))]
3470 )
3471
3472 ;; We don't really have extzv, but defining this using shifts helps
3473 ;; to reduce register pressure later on.
3474
3475 (define_expand "extzv"
3476   [(set (match_dup 4)
3477         (ashift:SI (match_operand:SI   1 "register_operand" "")
3478                    (match_operand:SI   2 "const_int_operand" "")))
3479    (set (match_operand:SI              0 "register_operand" "")
3480         (lshiftrt:SI (match_dup 4)
3481                      (match_operand:SI 3 "const_int_operand" "")))]
3482   "TARGET_THUMB1 || arm_arch_thumb2"
3483   "
3484   {
3485     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3486     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3487     
3488     if (arm_arch_thumb2)
3489       {
3490         emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
3491                                  operands[3]));
3492         DONE;
3493       }
3494
3495     operands[3] = GEN_INT (rshift);
3496     
3497     if (lshift == 0)
3498       {
3499         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3500         DONE;
3501       }
3502       
3503     operands[2] = GEN_INT (lshift);
3504     operands[4] = gen_reg_rtx (SImode);
3505   }"
3506 )
3507
3508 (define_insn "extv"
3509   [(set (match_operand:SI 0 "s_register_operand" "=r")
3510         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3511                          (match_operand:SI 2 "const_int_operand" "M")
3512                          (match_operand:SI 3 "const_int_operand" "M")))]
3513   "arm_arch_thumb2"
3514   "sbfx%?\t%0, %1, %3, %2"
3515   [(set_attr "length" "4")
3516    (set_attr "predicable" "yes")]
3517 )
3518
3519 (define_insn "extzv_t2"
3520   [(set (match_operand:SI 0 "s_register_operand" "=r")
3521         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3522                          (match_operand:SI 2 "const_int_operand" "M")
3523                          (match_operand:SI 3 "const_int_operand" "M")))]
3524   "arm_arch_thumb2"
3525   "ubfx%?\t%0, %1, %3, %2"
3526   [(set_attr "length" "4")
3527    (set_attr "predicable" "yes")]
3528 )
3529
3530 \f
3531 ;; Unary arithmetic insns
3532
3533 (define_expand "negdi2"
3534  [(parallel
3535    [(set (match_operand:DI 0 "s_register_operand" "")
3536          (neg:DI (match_operand:DI 1 "s_register_operand" "")))
3537     (clobber (reg:CC CC_REGNUM))])]
3538   "TARGET_EITHER"
3539   ""
3540 )
3541
3542 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
3543 ;; The first alternative allows the common case of a *full* overlap.
3544 (define_insn "*arm_negdi2"
3545   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
3546         (neg:DI (match_operand:DI 1 "s_register_operand"  "0,r")))
3547    (clobber (reg:CC CC_REGNUM))]
3548   "TARGET_ARM"
3549   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
3550   [(set_attr "conds" "clob")
3551    (set_attr "length" "8")]
3552 )
3553
3554 (define_insn "*thumb1_negdi2"
3555   [(set (match_operand:DI 0 "register_operand" "=&l")
3556         (neg:DI (match_operand:DI 1 "register_operand" "l")))
3557    (clobber (reg:CC CC_REGNUM))]
3558   "TARGET_THUMB1"
3559   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
3560   [(set_attr "length" "6")]
3561 )
3562
3563 (define_expand "negsi2"
3564   [(set (match_operand:SI         0 "s_register_operand" "")
3565         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
3566   "TARGET_EITHER"
3567   ""
3568 )
3569
3570 (define_insn "*arm_negsi2"
3571   [(set (match_operand:SI         0 "s_register_operand" "=r")
3572         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
3573   "TARGET_32BIT"
3574   "rsb%?\\t%0, %1, #0"
3575   [(set_attr "predicable" "yes")]
3576 )
3577
3578 (define_insn "*thumb1_negsi2"
3579   [(set (match_operand:SI         0 "register_operand" "=l")
3580         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
3581   "TARGET_THUMB1"
3582   "neg\\t%0, %1"
3583   [(set_attr "length" "2")]
3584 )
3585
3586 (define_expand "negsf2"
3587   [(set (match_operand:SF         0 "s_register_operand" "")
3588         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
3589   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3590   ""
3591 )
3592
3593 (define_expand "negdf2"
3594   [(set (match_operand:DF         0 "s_register_operand" "")
3595         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
3596   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
3597   "")
3598
3599 ;; abssi2 doesn't really clobber the condition codes if a different register
3600 ;; is being set.  To keep things simple, assume during rtl manipulations that
3601 ;; it does, but tell the final scan operator the truth.  Similarly for
3602 ;; (neg (abs...))
3603
3604 (define_expand "abssi2"
3605   [(parallel
3606     [(set (match_operand:SI         0 "s_register_operand" "")
3607           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3608      (clobber (match_dup 2))])]
3609   "TARGET_EITHER"
3610   "
3611   if (TARGET_THUMB1)
3612     operands[2] = gen_rtx_SCRATCH (SImode);
3613   else
3614     operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
3615 ")
3616
3617 (define_insn "*arm_abssi2"
3618   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3619         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3620    (clobber (reg:CC CC_REGNUM))]
3621   "TARGET_ARM"
3622   "@
3623    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3624    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3625   [(set_attr "conds" "clob,*")
3626    (set_attr "shift" "1")
3627    ;; predicable can't be set based on the variant, so left as no
3628    (set_attr "length" "8")]
3629 )
3630
3631 (define_insn_and_split "*thumb1_abssi2"
3632   [(set (match_operand:SI 0 "s_register_operand" "=l")
3633         (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
3634    (clobber (match_scratch:SI 2 "=&l"))]
3635   "TARGET_THUMB1"
3636   "#"
3637   "TARGET_THUMB1 && reload_completed"
3638   [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3639    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
3640    (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3641   ""
3642   [(set_attr "length" "6")]
3643 )
3644
3645 (define_insn "*arm_neg_abssi2"
3646   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3647         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3648    (clobber (reg:CC CC_REGNUM))]
3649   "TARGET_ARM"
3650   "@
3651    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3652    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3653   [(set_attr "conds" "clob,*")
3654    (set_attr "shift" "1")
3655    ;; predicable can't be set based on the variant, so left as no
3656    (set_attr "length" "8")]
3657 )
3658
3659 (define_insn_and_split "*thumb1_neg_abssi2"
3660   [(set (match_operand:SI 0 "s_register_operand" "=l")
3661         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
3662    (clobber (match_scratch:SI 2 "=&l"))]
3663   "TARGET_THUMB1"
3664   "#"
3665   "TARGET_THUMB1 && reload_completed"
3666   [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3667    (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
3668    (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3669   ""
3670   [(set_attr "length" "6")]
3671 )
3672
3673 (define_expand "abssf2"
3674   [(set (match_operand:SF         0 "s_register_operand" "")
3675         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3676   "TARGET_32BIT && TARGET_HARD_FLOAT"
3677   "")
3678
3679 (define_expand "absdf2"
3680   [(set (match_operand:DF         0 "s_register_operand" "")
3681         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3682   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
3683   "")
3684
3685 (define_expand "sqrtsf2"
3686   [(set (match_operand:SF 0 "s_register_operand" "")
3687         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3688   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3689   "")
3690
3691 (define_expand "sqrtdf2"
3692   [(set (match_operand:DF 0 "s_register_operand" "")
3693         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3694   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
3695   "")
3696
3697 (define_insn_and_split "one_cmpldi2"
3698   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3699         (not:DI (match_operand:DI 1 "s_register_operand" "0,r")))]
3700   "TARGET_32BIT"
3701   "#"
3702   "TARGET_32BIT && reload_completed"
3703   [(set (match_dup 0) (not:SI (match_dup 1)))
3704    (set (match_dup 2) (not:SI (match_dup 3)))]
3705   "
3706   {
3707     operands[2] = gen_highpart (SImode, operands[0]);
3708     operands[0] = gen_lowpart (SImode, operands[0]);
3709     operands[3] = gen_highpart (SImode, operands[1]);
3710     operands[1] = gen_lowpart (SImode, operands[1]);
3711   }"
3712   [(set_attr "length" "8")
3713    (set_attr "predicable" "yes")]
3714 )
3715
3716 (define_expand "one_cmplsi2"
3717   [(set (match_operand:SI         0 "s_register_operand" "")
3718         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3719   "TARGET_EITHER"
3720   ""
3721 )
3722
3723 (define_insn "*arm_one_cmplsi2"
3724   [(set (match_operand:SI         0 "s_register_operand" "=r")
3725         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3726   "TARGET_32BIT"
3727   "mvn%?\\t%0, %1"
3728   [(set_attr "predicable" "yes")]
3729 )
3730
3731 (define_insn "*thumb1_one_cmplsi2"
3732   [(set (match_operand:SI         0 "register_operand" "=l")
3733         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3734   "TARGET_THUMB1"
3735   "mvn\\t%0, %1"
3736   [(set_attr "length" "2")]
3737 )
3738
3739 (define_insn "*notsi_compare0"
3740   [(set (reg:CC_NOOV CC_REGNUM)
3741         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3742                          (const_int 0)))
3743    (set (match_operand:SI 0 "s_register_operand" "=r")
3744         (not:SI (match_dup 1)))]
3745   "TARGET_32BIT"
3746   "mvn%.\\t%0, %1"
3747   [(set_attr "conds" "set")]
3748 )
3749
3750 (define_insn "*notsi_compare0_scratch"
3751   [(set (reg:CC_NOOV CC_REGNUM)
3752         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3753                          (const_int 0)))
3754    (clobber (match_scratch:SI 0 "=r"))]
3755   "TARGET_32BIT"
3756   "mvn%.\\t%0, %1"
3757   [(set_attr "conds" "set")]
3758 )
3759 \f
3760 ;; Fixed <--> Floating conversion insns
3761
3762 (define_expand "floatsihf2"
3763   [(set (match_operand:HF           0 "general_operand" "")
3764         (float:HF (match_operand:SI 1 "general_operand" "")))]
3765   "TARGET_EITHER"
3766   "
3767   {
3768     rtx op1 = gen_reg_rtx (SFmode);
3769     expand_float (op1, operands[1], 0);
3770     op1 = convert_to_mode (HFmode, op1, 0);
3771     emit_move_insn (operands[0], op1);
3772     DONE;
3773   }"
3774 )
3775
3776 (define_expand "floatdihf2"
3777   [(set (match_operand:HF           0 "general_operand" "")
3778         (float:HF (match_operand:DI 1 "general_operand" "")))]
3779   "TARGET_EITHER"
3780   "
3781   {
3782     rtx op1 = gen_reg_rtx (SFmode);
3783     expand_float (op1, operands[1], 0);
3784     op1 = convert_to_mode (HFmode, op1, 0);
3785     emit_move_insn (operands[0], op1);
3786     DONE;
3787   }"
3788 )
3789
3790 (define_expand "floatsisf2"
3791   [(set (match_operand:SF           0 "s_register_operand" "")
3792         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3793   "TARGET_32BIT && TARGET_HARD_FLOAT"
3794   "
3795   if (TARGET_MAVERICK)
3796     {
3797       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3798       DONE;
3799     }
3800 ")
3801
3802 (define_expand "floatsidf2"
3803   [(set (match_operand:DF           0 "s_register_operand" "")
3804         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3805   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
3806   "
3807   if (TARGET_MAVERICK)
3808     {
3809       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3810       DONE;
3811     }
3812 ")
3813
3814 (define_expand "fix_trunchfsi2"
3815   [(set (match_operand:SI         0 "general_operand" "")
3816         (fix:SI (fix:HF (match_operand:HF 1 "general_operand"  ""))))]
3817   "TARGET_EITHER"
3818   "
3819   {
3820     rtx op1 = convert_to_mode (SFmode, operands[1], 0);
3821     expand_fix (operands[0], op1, 0);
3822     DONE;
3823   }"
3824 )
3825
3826 (define_expand "fix_trunchfdi2"
3827   [(set (match_operand:DI         0 "general_operand" "")
3828         (fix:DI (fix:HF (match_operand:HF 1 "general_operand"  ""))))]
3829   "TARGET_EITHER"
3830   "
3831   {
3832     rtx op1 = convert_to_mode (SFmode, operands[1], 0);
3833     expand_fix (operands[0], op1, 0);
3834     DONE;
3835   }"
3836 )
3837
3838 (define_expand "fix_truncsfsi2"
3839   [(set (match_operand:SI         0 "s_register_operand" "")
3840         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3841   "TARGET_32BIT && TARGET_HARD_FLOAT"
3842   "
3843   if (TARGET_MAVERICK)
3844     {
3845       if (!cirrus_fp_register (operands[0], SImode))
3846         operands[0] = force_reg (SImode, operands[0]);
3847       if (!cirrus_fp_register (operands[1], SFmode))
3848         operands[1] = force_reg (SFmode, operands[0]);
3849       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3850       DONE;
3851     }
3852 ")
3853
3854 (define_expand "fix_truncdfsi2"
3855   [(set (match_operand:SI         0 "s_register_operand" "")
3856         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3857   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
3858   "
3859   if (TARGET_MAVERICK)
3860     {
3861       if (!cirrus_fp_register (operands[1], DFmode))
3862         operands[1] = force_reg (DFmode, operands[0]);
3863       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3864       DONE;
3865     }
3866 ")
3867
3868 ;; Truncation insns
3869
3870 (define_expand "truncdfsf2"
3871   [(set (match_operand:SF  0 "s_register_operand" "")
3872         (float_truncate:SF
3873          (match_operand:DF 1 "s_register_operand" "")))]
3874   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
3875   ""
3876 )
3877
3878 /* DFmode -> HFmode conversions have to go through SFmode.  */
3879 (define_expand "truncdfhf2"
3880   [(set (match_operand:HF  0 "general_operand" "")
3881         (float_truncate:HF
3882          (match_operand:DF 1 "general_operand" "")))]
3883   "TARGET_EITHER"
3884   "
3885   {
3886     rtx op1;
3887     op1 = convert_to_mode (SFmode, operands[1], 0);
3888     op1 = convert_to_mode (HFmode, op1, 0);
3889     emit_move_insn (operands[0], op1);
3890     DONE;
3891   }"
3892 )
3893 \f
3894 ;; Zero and sign extension instructions.
3895
3896 (define_expand "zero_extendsidi2"
3897   [(set (match_operand:DI 0 "s_register_operand" "")
3898         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
3899   "TARGET_32BIT"
3900   ""
3901 )
3902
3903 (define_insn "*arm_zero_extendsidi2"
3904   [(set (match_operand:DI 0 "s_register_operand" "=r")
3905         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3906   "TARGET_ARM"
3907   "*
3908     if (REGNO (operands[1])
3909         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3910       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3911     return \"mov%?\\t%R0, #0\";
3912   "
3913   [(set_attr "length" "8")
3914    (set_attr "predicable" "yes")]
3915 )
3916
3917 (define_expand "zero_extendqidi2"
3918   [(set (match_operand:DI                 0 "s_register_operand"  "")
3919         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))]
3920   "TARGET_32BIT"
3921   ""
3922 )
3923
3924 (define_insn "*arm_zero_extendqidi2"
3925   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3926         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3927   "TARGET_ARM"
3928   "@
3929    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3930    ldr%(b%)\\t%Q0, %1\;mov%?\\t%R0, #0"
3931   [(set_attr "length" "8")
3932    (set_attr "predicable" "yes")
3933    (set_attr "type" "*,load_byte")
3934    (set_attr "pool_range" "*,4092")
3935    (set_attr "neg_pool_range" "*,4084")]
3936 )
3937
3938 (define_expand "extendsidi2"
3939   [(set (match_operand:DI 0 "s_register_operand" "")
3940         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
3941   "TARGET_32BIT"
3942   ""
3943 )
3944
3945 (define_insn "*arm_extendsidi2"
3946   [(set (match_operand:DI 0 "s_register_operand" "=r")
3947         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3948   "TARGET_ARM"
3949   "*
3950     if (REGNO (operands[1])
3951         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3952       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3953     return \"mov%?\\t%R0, %Q0, asr #31\";
3954   "
3955   [(set_attr "length" "8")
3956    (set_attr "shift" "1")
3957    (set_attr "predicable" "yes")]
3958 )
3959
3960 (define_expand "zero_extendhisi2"
3961   [(set (match_dup 2)
3962         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3963                    (const_int 16)))
3964    (set (match_operand:SI 0 "s_register_operand" "")
3965         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3966   "TARGET_EITHER"
3967   "
3968   {
3969     if ((TARGET_THUMB1 || arm_arch4) && GET_CODE (operands[1]) == MEM)
3970       {
3971         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3972                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3973         DONE;
3974       }
3975
3976     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3977       {
3978         emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3979         DONE;
3980       }
3981
3982     if (!s_register_operand (operands[1], HImode))
3983       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3984
3985     if (arm_arch6)
3986       {
3987         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3988                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3989         DONE;
3990       }
3991
3992     operands[1] = gen_lowpart (SImode, operands[1]);
3993     operands[2] = gen_reg_rtx (SImode);
3994   }"
3995 )
3996
3997 (define_insn "*thumb1_zero_extendhisi2"
3998   [(set (match_operand:SI 0 "register_operand" "=l")
3999         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
4000   "TARGET_THUMB1 && !arm_arch6"
4001   "*
4002   rtx mem = XEXP (operands[1], 0);
4003
4004   if (GET_CODE (mem) == CONST)
4005     mem = XEXP (mem, 0);
4006     
4007   if (GET_CODE (mem) == LABEL_REF)
4008     return \"ldr\\t%0, %1\";
4009     
4010   if (GET_CODE (mem) == PLUS)
4011     {
4012       rtx a = XEXP (mem, 0);
4013       rtx b = XEXP (mem, 1);
4014
4015       /* This can happen due to bugs in reload.  */
4016       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
4017         {
4018           rtx ops[2];
4019           ops[0] = operands[0];
4020           ops[1] = a;
4021       
4022           output_asm_insn (\"mov        %0, %1\", ops);
4023
4024           XEXP (mem, 0) = operands[0];
4025        }
4026
4027       else if (   GET_CODE (a) == LABEL_REF
4028                && GET_CODE (b) == CONST_INT)
4029         return \"ldr\\t%0, %1\";
4030     }
4031     
4032   return \"ldrh\\t%0, %1\";
4033   "
4034   [(set_attr "length" "4")
4035    (set_attr "type" "load_byte")
4036    (set_attr "pool_range" "60")]
4037 )
4038
4039 (define_insn "*thumb1_zero_extendhisi2_v6"
4040   [(set (match_operand:SI 0 "register_operand" "=l,l")
4041         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
4042   "TARGET_THUMB1 && arm_arch6"
4043   "*
4044   rtx mem;
4045
4046   if (which_alternative == 0)
4047     return \"uxth\\t%0, %1\";
4048
4049   mem = XEXP (operands[1], 0);
4050
4051   if (GET_CODE (mem) == CONST)
4052     mem = XEXP (mem, 0);
4053     
4054   if (GET_CODE (mem) == LABEL_REF)
4055     return \"ldr\\t%0, %1\";
4056     
4057   if (GET_CODE (mem) == PLUS)
4058     {
4059       rtx a = XEXP (mem, 0);
4060       rtx b = XEXP (mem, 1);
4061
4062       /* This can happen due to bugs in reload.  */
4063       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
4064         {
4065           rtx ops[2];
4066           ops[0] = operands[0];
4067           ops[1] = a;
4068       
4069           output_asm_insn (\"mov        %0, %1\", ops);
4070
4071           XEXP (mem, 0) = operands[0];
4072        }
4073
4074       else if (   GET_CODE (a) == LABEL_REF
4075                && GET_CODE (b) == CONST_INT)
4076         return \"ldr\\t%0, %1\";
4077     }
4078     
4079   return \"ldrh\\t%0, %1\";
4080   "
4081   [(set_attr "length" "2,4")
4082    (set_attr "type" "alu_shift,load_byte")
4083    (set_attr "pool_range" "*,60")]
4084 )
4085
4086 (define_insn "*arm_zero_extendhisi2"
4087   [(set (match_operand:SI 0 "s_register_operand" "=r")
4088         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
4089   "TARGET_ARM && arm_arch4 && !arm_arch6"
4090   "ldr%(h%)\\t%0, %1"
4091   [(set_attr "type" "load_byte")
4092    (set_attr "predicable" "yes")
4093    (set_attr "pool_range" "256")
4094    (set_attr "neg_pool_range" "244")]
4095 )
4096
4097 (define_insn "*arm_zero_extendhisi2_v6"
4098   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4099         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4100   "TARGET_ARM && arm_arch6"
4101   "@
4102    uxth%?\\t%0, %1
4103    ldr%(h%)\\t%0, %1"
4104   [(set_attr "type" "alu_shift,load_byte")
4105    (set_attr "predicable" "yes")
4106    (set_attr "pool_range" "*,256")
4107    (set_attr "neg_pool_range" "*,244")]
4108 )
4109
4110 (define_insn "*arm_zero_extendhisi2addsi"
4111   [(set (match_operand:SI 0 "s_register_operand" "=r")
4112         (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4113                  (match_operand:SI 2 "s_register_operand" "r")))]
4114   "TARGET_INT_SIMD"
4115   "uxtah%?\\t%0, %2, %1"
4116   [(set_attr "type" "alu_shift")
4117    (set_attr "predicable" "yes")]
4118 )
4119
4120 (define_expand "zero_extendqisi2"
4121   [(set (match_operand:SI 0 "s_register_operand" "")
4122         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
4123   "TARGET_EITHER"
4124   "
4125   if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
4126     {
4127       if (TARGET_ARM)
4128         {
4129           emit_insn (gen_andsi3 (operands[0],
4130                                  gen_lowpart (SImode, operands[1]),
4131                                  GEN_INT (255)));
4132         }
4133       else /* TARGET_THUMB */
4134         {
4135           rtx temp = gen_reg_rtx (SImode);
4136           rtx ops[3];
4137           
4138           operands[1] = copy_to_mode_reg (QImode, operands[1]);
4139           operands[1] = gen_lowpart (SImode, operands[1]);
4140
4141           ops[0] = temp;
4142           ops[1] = operands[1];
4143           ops[2] = GEN_INT (24);
4144
4145           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
4146                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
4147           
4148           ops[0] = operands[0];
4149           ops[1] = temp;
4150           ops[2] = GEN_INT (24);
4151
4152           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
4153                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
4154         }
4155       DONE;
4156     }
4157   "
4158 )
4159
4160 (define_insn "*thumb1_zero_extendqisi2"
4161   [(set (match_operand:SI 0 "register_operand" "=l")
4162         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
4163   "TARGET_THUMB1 && !arm_arch6"
4164   "ldrb\\t%0, %1"
4165   [(set_attr "length" "2")
4166    (set_attr "type" "load_byte")
4167    (set_attr "pool_range" "32")]
4168 )
4169
4170 (define_insn "*thumb1_zero_extendqisi2_v6"
4171   [(set (match_operand:SI 0 "register_operand" "=l,l")
4172         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
4173   "TARGET_THUMB1 && arm_arch6"
4174   "@
4175    uxtb\\t%0, %1
4176    ldrb\\t%0, %1"
4177   [(set_attr "length" "2,2")
4178    (set_attr "type" "alu_shift,load_byte")
4179    (set_attr "pool_range" "*,32")]
4180 )
4181
4182 (define_insn "*arm_zero_extendqisi2"
4183   [(set (match_operand:SI 0 "s_register_operand" "=r")
4184         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
4185   "TARGET_ARM && !arm_arch6"
4186   "ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
4187   [(set_attr "type" "load_byte")
4188    (set_attr "predicable" "yes")
4189    (set_attr "pool_range" "4096")
4190    (set_attr "neg_pool_range" "4084")]
4191 )
4192
4193 (define_insn "*arm_zero_extendqisi2_v6"
4194   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4195         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4196   "TARGET_ARM && arm_arch6"
4197   "@
4198    uxtb%(%)\\t%0, %1
4199    ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
4200   [(set_attr "type" "alu_shift,load_byte")
4201    (set_attr "predicable" "yes")
4202    (set_attr "pool_range" "*,4096")
4203    (set_attr "neg_pool_range" "*,4084")]
4204 )
4205
4206 (define_insn "*arm_zero_extendqisi2addsi"
4207   [(set (match_operand:SI 0 "s_register_operand" "=r")
4208         (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4209                  (match_operand:SI 2 "s_register_operand" "r")))]
4210   "TARGET_INT_SIMD"
4211   "uxtab%?\\t%0, %2, %1"
4212   [(set_attr "predicable" "yes")
4213    (set_attr "insn" "xtab")
4214    (set_attr "type" "alu_shift")]
4215 )
4216
4217 (define_split
4218   [(set (match_operand:SI 0 "s_register_operand" "")
4219         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
4220    (clobber (match_operand:SI 2 "s_register_operand" ""))]
4221   "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
4222   [(set (match_dup 2) (match_dup 1))
4223    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4224   ""
4225 )
4226
4227 (define_split
4228   [(set (match_operand:SI 0 "s_register_operand" "")
4229         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
4230    (clobber (match_operand:SI 2 "s_register_operand" ""))]
4231   "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
4232   [(set (match_dup 2) (match_dup 1))
4233    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4234   ""
4235 )
4236
4237 (define_code_iterator ior_xor [ior xor])
4238
4239 (define_split
4240   [(set (match_operand:SI 0 "s_register_operand" "")
4241         (ior_xor:SI (and:SI (ashift:SI
4242                              (match_operand:SI 1 "s_register_operand" "")
4243                              (match_operand:SI 2 "const_int_operand" ""))
4244                             (match_operand:SI 3 "const_int_operand" ""))
4245                     (zero_extend:SI
4246                      (match_operator 5 "subreg_lowpart_operator"
4247                       [(match_operand:SI 4 "s_register_operand" "")]))))]
4248   "TARGET_32BIT
4249    && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
4250        == (GET_MODE_MASK (GET_MODE (operands[5]))
4251            & (GET_MODE_MASK (GET_MODE (operands[5]))
4252               << (INTVAL (operands[2])))))"
4253   [(set (match_dup 0) (ior_xor:SI (ashift:SI (match_dup 1) (match_dup 2))
4254                                   (match_dup 4)))
4255    (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
4256   "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
4257 )
4258
4259 (define_insn "*compareqi_eq0"
4260   [(set (reg:CC_Z CC_REGNUM)
4261         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
4262                          (const_int 0)))]
4263   "TARGET_32BIT"
4264   "tst\\t%0, #255"
4265   [(set_attr "conds" "set")]
4266 )
4267
4268 (define_expand "extendhisi2"
4269   [(set (match_dup 2)
4270         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
4271                    (const_int 16)))
4272    (set (match_operand:SI 0 "s_register_operand" "")
4273         (ashiftrt:SI (match_dup 2)
4274                      (const_int 16)))]
4275   "TARGET_EITHER"
4276   "
4277   {
4278     if (GET_CODE (operands[1]) == MEM)
4279       {
4280         if (TARGET_THUMB1)
4281           {
4282             emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
4283             DONE;
4284           }
4285         else if (arm_arch4)
4286           {
4287             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4288                        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4289             DONE;
4290           }
4291       }
4292
4293     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
4294       {
4295         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
4296         DONE;
4297       }
4298
4299     if (!s_register_operand (operands[1], HImode))
4300       operands[1] = copy_to_mode_reg (HImode, operands[1]);
4301
4302     if (arm_arch6)
4303       {
4304         if (TARGET_THUMB1)
4305           emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
4306         else
4307           emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4308                      gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4309
4310         DONE;
4311       }
4312
4313     operands[1] = gen_lowpart (SImode, operands[1]);
4314     operands[2] = gen_reg_rtx (SImode);
4315   }"
4316 )
4317
4318 (define_insn "thumb1_extendhisi2"
4319   [(set (match_operand:SI 0 "register_operand" "=l")
4320         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
4321    (clobber (match_scratch:SI 2 "=&l"))]
4322   "TARGET_THUMB1 && !arm_arch6"
4323   "*
4324   {
4325     rtx ops[4];
4326     rtx mem = XEXP (operands[1], 0);
4327
4328     /* This code used to try to use 'V', and fix the address only if it was
4329        offsettable, but this fails for e.g. REG+48 because 48 is outside the
4330        range of QImode offsets, and offsettable_address_p does a QImode
4331        address check.  */
4332        
4333     if (GET_CODE (mem) == CONST)
4334       mem = XEXP (mem, 0);
4335     
4336     if (GET_CODE (mem) == LABEL_REF)
4337       return \"ldr\\t%0, %1\";
4338     
4339     if (GET_CODE (mem) == PLUS)
4340       {
4341         rtx a = XEXP (mem, 0);
4342         rtx b = XEXP (mem, 1);
4343
4344         if (GET_CODE (a) == LABEL_REF
4345             && GET_CODE (b) == CONST_INT)
4346           return \"ldr\\t%0, %1\";
4347
4348         if (GET_CODE (b) == REG)
4349           return \"ldrsh\\t%0, %1\";
4350           
4351         ops[1] = a;
4352         ops[2] = b;
4353       }
4354     else
4355       {
4356         ops[1] = mem;
4357         ops[2] = const0_rtx;
4358       }
4359
4360     gcc_assert (GET_CODE (ops[1]) == REG);
4361
4362     ops[0] = operands[0];
4363     ops[3] = operands[2];
4364     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4365     return \"\";
4366   }"
4367   [(set_attr "length" "4")
4368    (set_attr "type" "load_byte")
4369    (set_attr "pool_range" "1020")]
4370 )
4371
4372 ;; We used to have an early-clobber on the scratch register here.
4373 ;; However, there's a bug somewhere in reload which means that this
4374 ;; can be partially ignored during spill allocation if the memory
4375 ;; address also needs reloading; this causes us to die later on when
4376 ;; we try to verify the operands.  Fortunately, we don't really need
4377 ;; the early-clobber: we can always use operand 0 if operand 2
4378 ;; overlaps the address.
4379 (define_insn "*thumb1_extendhisi2_insn_v6"
4380   [(set (match_operand:SI 0 "register_operand" "=l,l")
4381         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
4382    (clobber (match_scratch:SI 2 "=X,l"))]
4383   "TARGET_THUMB1 && arm_arch6"
4384   "*
4385   {
4386     rtx ops[4];
4387     rtx mem;
4388
4389     if (which_alternative == 0)
4390       return \"sxth\\t%0, %1\";
4391
4392     mem = XEXP (operands[1], 0);
4393
4394     /* This code used to try to use 'V', and fix the address only if it was
4395        offsettable, but this fails for e.g. REG+48 because 48 is outside the
4396        range of QImode offsets, and offsettable_address_p does a QImode
4397        address check.  */
4398        
4399     if (GET_CODE (mem) == CONST)
4400       mem = XEXP (mem, 0);
4401     
4402     if (GET_CODE (mem) == LABEL_REF)
4403       return \"ldr\\t%0, %1\";
4404     
4405     if (GET_CODE (mem) == PLUS)
4406       {
4407         rtx a = XEXP (mem, 0);
4408         rtx b = XEXP (mem, 1);
4409
4410         if (GET_CODE (a) == LABEL_REF
4411             && GET_CODE (b) == CONST_INT)
4412           return \"ldr\\t%0, %1\";
4413
4414         if (GET_CODE (b) == REG)
4415           return \"ldrsh\\t%0, %1\";
4416           
4417         ops[1] = a;
4418         ops[2] = b;
4419       }
4420     else
4421       {
4422         ops[1] = mem;
4423         ops[2] = const0_rtx;
4424       }
4425       
4426     gcc_assert (GET_CODE (ops[1]) == REG);
4427
4428     ops[0] = operands[0];
4429     if (reg_mentioned_p (operands[2], ops[1]))
4430       ops[3] = ops[0];
4431     else
4432       ops[3] = operands[2];
4433     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4434     return \"\";
4435   }"
4436   [(set_attr "length" "2,4")
4437    (set_attr "type" "alu_shift,load_byte")
4438    (set_attr "pool_range" "*,1020")]
4439 )
4440
4441 ;; This pattern will only be used when ldsh is not available
4442 (define_expand "extendhisi2_mem"
4443   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4444    (set (match_dup 3)
4445         (zero_extend:SI (match_dup 7)))
4446    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4447    (set (match_operand:SI 0 "" "")
4448         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
4449   "TARGET_ARM"
4450   "
4451   {
4452     rtx mem1, mem2;
4453     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4454
4455     mem1 = change_address (operands[1], QImode, addr);
4456     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
4457     operands[0] = gen_lowpart (SImode, operands[0]);
4458     operands[1] = mem1;
4459     operands[2] = gen_reg_rtx (SImode);
4460     operands[3] = gen_reg_rtx (SImode);
4461     operands[6] = gen_reg_rtx (SImode);
4462     operands[7] = mem2;
4463
4464     if (BYTES_BIG_ENDIAN)
4465       {
4466         operands[4] = operands[2];
4467         operands[5] = operands[3];
4468       }
4469     else
4470       {
4471         operands[4] = operands[3];
4472         operands[5] = operands[2];
4473       }
4474   }"
4475 )
4476
4477 (define_insn "*arm_extendhisi2"
4478   [(set (match_operand:SI 0 "s_register_operand" "=r")
4479         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
4480   "TARGET_ARM && arm_arch4 && !arm_arch6"
4481   "ldr%(sh%)\\t%0, %1"
4482   [(set_attr "type" "load_byte")
4483    (set_attr "predicable" "yes")
4484    (set_attr "pool_range" "256")
4485    (set_attr "neg_pool_range" "244")]
4486 )
4487
4488 ;; ??? Check Thumb-2 pool range
4489 (define_insn "*arm_extendhisi2_v6"
4490   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4491         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4492   "TARGET_32BIT && arm_arch6"
4493   "@
4494    sxth%?\\t%0, %1
4495    ldr%(sh%)\\t%0, %1"
4496   [(set_attr "type" "alu_shift,load_byte")
4497    (set_attr "predicable" "yes")
4498    (set_attr "pool_range" "*,256")
4499    (set_attr "neg_pool_range" "*,244")]
4500 )
4501
4502 (define_insn "*arm_extendhisi2addsi"
4503   [(set (match_operand:SI 0 "s_register_operand" "=r")
4504         (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4505                  (match_operand:SI 2 "s_register_operand" "r")))]
4506   "TARGET_INT_SIMD"
4507   "sxtah%?\\t%0, %2, %1"
4508 )
4509
4510 (define_expand "extendqihi2"
4511   [(set (match_dup 2)
4512         (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
4513                    (const_int 24)))
4514    (set (match_operand:HI 0 "s_register_operand" "")
4515         (ashiftrt:SI (match_dup 2)
4516                      (const_int 24)))]
4517   "TARGET_ARM"
4518   "
4519   {
4520     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
4521       {
4522         emit_insn (gen_rtx_SET (VOIDmode,
4523                                 operands[0],
4524                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
4525         DONE;
4526       }
4527     if (!s_register_operand (operands[1], QImode))
4528       operands[1] = copy_to_mode_reg (QImode, operands[1]);
4529     operands[0] = gen_lowpart (SImode, operands[0]);
4530     operands[1] = gen_lowpart (SImode, operands[1]);
4531     operands[2] = gen_reg_rtx (SImode);
4532   }"
4533 )
4534
4535 (define_insn "*arm_extendqihi_insn"
4536   [(set (match_operand:HI 0 "s_register_operand" "=r")
4537         (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
4538   "TARGET_ARM && arm_arch4"
4539   "ldr%(sb%)\\t%0, %1"
4540   [(set_attr "type" "load_byte")
4541    (set_attr "predicable" "yes")
4542    (set_attr "pool_range" "256")
4543    (set_attr "neg_pool_range" "244")]
4544 )
4545
4546 (define_expand "extendqisi2"
4547   [(set (match_dup 2)
4548         (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
4549                    (const_int 24)))
4550    (set (match_operand:SI 0 "s_register_operand" "")
4551         (ashiftrt:SI (match_dup 2)
4552                      (const_int 24)))]
4553   "TARGET_EITHER"
4554   "
4555   {
4556     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
4557       {
4558         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4559                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4560         DONE;
4561       }
4562
4563     if (!s_register_operand (operands[1], QImode))
4564       operands[1] = copy_to_mode_reg (QImode, operands[1]);
4565
4566     if (arm_arch6)
4567       {
4568         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4569                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4570         DONE;
4571       }
4572
4573     operands[1] = gen_lowpart (SImode, operands[1]);
4574     operands[2] = gen_reg_rtx (SImode);
4575   }"
4576 )
4577
4578 (define_insn "*arm_extendqisi"
4579   [(set (match_operand:SI 0 "s_register_operand" "=r")
4580         (sign_extend:SI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
4581   "TARGET_ARM && arm_arch4 && !arm_arch6"
4582   "ldr%(sb%)\\t%0, %1"
4583   [(set_attr "type" "load_byte")
4584    (set_attr "predicable" "yes")
4585    (set_attr "pool_range" "256")
4586    (set_attr "neg_pool_range" "244")]
4587 )
4588
4589 (define_insn "*arm_extendqisi_v6"
4590   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4591         (sign_extend:SI
4592          (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
4593   "TARGET_ARM && arm_arch6"
4594   "@
4595    sxtb%?\\t%0, %1
4596    ldr%(sb%)\\t%0, %1"
4597   [(set_attr "type" "alu_shift,load_byte")
4598    (set_attr "predicable" "yes")
4599    (set_attr "pool_range" "*,256")
4600    (set_attr "neg_pool_range" "*,244")]
4601 )
4602
4603 (define_insn "*arm_extendqisi2addsi"
4604   [(set (match_operand:SI 0 "s_register_operand" "=r")
4605         (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4606                  (match_operand:SI 2 "s_register_operand" "r")))]
4607   "TARGET_INT_SIMD"
4608   "sxtab%?\\t%0, %2, %1"
4609   [(set_attr "type" "alu_shift")
4610    (set_attr "insn" "xtab")
4611    (set_attr "predicable" "yes")]
4612 )
4613
4614 (define_insn "*thumb1_extendqisi2"
4615   [(set (match_operand:SI 0 "register_operand" "=l,l")
4616         (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
4617   "TARGET_THUMB1 && !arm_arch6"
4618   "*
4619   {
4620     rtx ops[3];
4621     rtx mem = XEXP (operands[1], 0);
4622     
4623     if (GET_CODE (mem) == CONST)
4624       mem = XEXP (mem, 0);
4625     
4626     if (GET_CODE (mem) == LABEL_REF)
4627       return \"ldr\\t%0, %1\";
4628
4629     if (GET_CODE (mem) == PLUS
4630         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4631       return \"ldr\\t%0, %1\";
4632       
4633     if (which_alternative == 0)
4634       return \"ldrsb\\t%0, %1\";
4635       
4636     ops[0] = operands[0];
4637     
4638     if (GET_CODE (mem) == PLUS)
4639       {
4640         rtx a = XEXP (mem, 0);
4641         rtx b = XEXP (mem, 1);
4642         
4643         ops[1] = a;
4644         ops[2] = b;
4645
4646         if (GET_CODE (a) == REG)
4647           {
4648             if (GET_CODE (b) == REG)
4649               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4650             else if (REGNO (a) == REGNO (ops[0]))
4651               {
4652                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4653                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4654                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4655               }
4656             else
4657               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4658           }
4659         else
4660           {
4661             gcc_assert (GET_CODE (b) == REG);
4662             if (REGNO (b) == REGNO (ops[0]))
4663               {
4664                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4665                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4666                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4667               }
4668             else
4669               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4670           }
4671       }
4672     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4673       {
4674         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4675         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4676         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4677       }
4678     else
4679       {
4680         ops[1] = mem;
4681         ops[2] = const0_rtx;
4682         
4683         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4684       }
4685     return \"\";
4686   }"
4687   [(set_attr "length" "2,6")
4688    (set_attr "type" "load_byte,load_byte")
4689    (set_attr "pool_range" "32,32")]
4690 )
4691
4692 (define_insn "*thumb1_extendqisi2_v6"
4693   [(set (match_operand:SI 0 "register_operand" "=l,l,l")
4694         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
4695   "TARGET_THUMB1 && arm_arch6"
4696   "*
4697   {
4698     rtx ops[3];
4699     rtx mem;
4700
4701     if (which_alternative == 0)
4702       return \"sxtb\\t%0, %1\";
4703
4704     mem = XEXP (operands[1], 0);
4705     
4706     if (GET_CODE (mem) == CONST)
4707       mem = XEXP (mem, 0);
4708     
4709     if (GET_CODE (mem) == LABEL_REF)
4710       return \"ldr\\t%0, %1\";
4711
4712     if (GET_CODE (mem) == PLUS
4713         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4714       return \"ldr\\t%0, %1\";
4715       
4716     if (which_alternative == 0)
4717       return \"ldrsb\\t%0, %1\";
4718       
4719     ops[0] = operands[0];
4720     
4721     if (GET_CODE (mem) == PLUS)
4722       {
4723         rtx a = XEXP (mem, 0);
4724         rtx b = XEXP (mem, 1);
4725         
4726         ops[1] = a;
4727         ops[2] = b;
4728
4729         if (GET_CODE (a) == REG)
4730           {
4731             if (GET_CODE (b) == REG)
4732               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4733             else if (REGNO (a) == REGNO (ops[0]))
4734               {
4735                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4736                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4737               }
4738             else
4739               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4740           }
4741         else
4742           {
4743             gcc_assert (GET_CODE (b) == REG);
4744             if (REGNO (b) == REGNO (ops[0]))
4745               {
4746                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4747                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4748               }
4749             else
4750               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4751           }
4752       }
4753     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4754       {
4755         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4756         output_asm_insn (\"sxtb\\t%0, %0\", ops);
4757       }
4758     else
4759       {
4760         ops[1] = mem;
4761         ops[2] = const0_rtx;
4762         
4763         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4764       }
4765     return \"\";
4766   }"
4767   [(set_attr "length" "2,2,4")
4768    (set_attr "type" "alu_shift,load_byte,load_byte")
4769    (set_attr "pool_range" "*,32,32")]
4770 )
4771
4772 (define_expand "extendsfdf2"
4773   [(set (match_operand:DF                  0 "s_register_operand" "")
4774         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
4775   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
4776   ""
4777 )
4778
4779 /* HFmode -> DFmode conversions have to go through SFmode.  */
4780 (define_expand "extendhfdf2"
4781   [(set (match_operand:DF                  0 "general_operand" "")
4782         (float_extend:DF (match_operand:HF 1 "general_operand"  "")))]
4783   "TARGET_EITHER"
4784   "
4785   {
4786     rtx op1;
4787     op1 = convert_to_mode (SFmode, operands[1], 0);
4788     op1 = convert_to_mode (DFmode, op1, 0);
4789     emit_insn (gen_movdf (operands[0], op1));
4790     DONE;
4791   }"
4792 )
4793 \f
4794 ;; Move insns (including loads and stores)
4795
4796 ;; XXX Just some ideas about movti.
4797 ;; I don't think these are a good idea on the arm, there just aren't enough
4798 ;; registers
4799 ;;(define_expand "loadti"
4800 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
4801 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
4802 ;;  "" "")
4803
4804 ;;(define_expand "storeti"
4805 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4806 ;;      (match_operand:TI 1 "s_register_operand" ""))]
4807 ;;  "" "")
4808
4809 ;;(define_expand "movti"
4810 ;;  [(set (match_operand:TI 0 "general_operand" "")
4811 ;;      (match_operand:TI 1 "general_operand" ""))]
4812 ;;  ""
4813 ;;  "
4814 ;;{
4815 ;;  rtx insn;
4816 ;;
4817 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4818 ;;    operands[1] = copy_to_reg (operands[1]);
4819 ;;  if (GET_CODE (operands[0]) == MEM)
4820 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4821 ;;  else if (GET_CODE (operands[1]) == MEM)
4822 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4823 ;;  else
4824 ;;    FAIL;
4825 ;;
4826 ;;  emit_insn (insn);
4827 ;;  DONE;
4828 ;;}")
4829
4830 ;; Recognize garbage generated above.
4831
4832 ;;(define_insn ""
4833 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4834 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4835 ;;  ""
4836 ;;  "*
4837 ;;  {
4838 ;;    register mem = (which_alternative < 3);
4839 ;;    register const char *template;
4840 ;;
4841 ;;    operands[mem] = XEXP (operands[mem], 0);
4842 ;;    switch (which_alternative)
4843 ;;      {
4844 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4845 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
4846 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
4847 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
4848 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
4849 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
4850 ;;      }
4851 ;;    output_asm_insn (template, operands);
4852 ;;    return \"\";
4853 ;;  }")
4854
4855 (define_expand "movdi"
4856   [(set (match_operand:DI 0 "general_operand" "")
4857         (match_operand:DI 1 "general_operand" ""))]
4858   "TARGET_EITHER"
4859   "
4860   if (can_create_pseudo_p ())
4861     {
4862       if (GET_CODE (operands[0]) != REG)
4863         operands[1] = force_reg (DImode, operands[1]);
4864     }
4865   "
4866 )
4867
4868 (define_insn "*arm_movdi"
4869   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4870         (match_operand:DI 1 "di_operand"              "rDa,Db,Dc,mi,r"))]
4871   "TARGET_ARM
4872    && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4873    && !TARGET_IWMMXT
4874    && (   register_operand (operands[0], DImode)
4875        || register_operand (operands[1], DImode))"
4876   "*
4877   switch (which_alternative)
4878     {
4879     case 0:
4880     case 1:
4881     case 2:
4882       return \"#\";
4883     default:
4884       return output_move_double (operands);
4885     }
4886   "
4887   [(set_attr "length" "8,12,16,8,8")
4888    (set_attr "type" "*,*,*,load2,store2")
4889    (set_attr "pool_range" "*,*,*,1020,*")
4890    (set_attr "neg_pool_range" "*,*,*,1008,*")]
4891 )
4892
4893 (define_split
4894   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4895         (match_operand:ANY64 1 "const_double_operand" ""))]
4896   "TARGET_32BIT
4897    && reload_completed
4898    && (arm_const_double_inline_cost (operands[1])
4899        <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4900   [(const_int 0)]
4901   "
4902   arm_split_constant (SET, SImode, curr_insn,
4903                       INTVAL (gen_lowpart (SImode, operands[1])),
4904                       gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4905   arm_split_constant (SET, SImode, curr_insn,
4906                       INTVAL (gen_highpart_mode (SImode,
4907                                                  GET_MODE (operands[0]),
4908                                                  operands[1])),
4909                       gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4910   DONE;
4911   "
4912 )
4913
4914 ; If optimizing for size, or if we have load delay slots, then 
4915 ; we want to split the constant into two separate operations. 
4916 ; In both cases this may split a trivial part into a single data op
4917 ; leaving a single complex constant to load.  We can also get longer
4918 ; offsets in a LDR which means we get better chances of sharing the pool
4919 ; entries.  Finally, we can normally do a better job of scheduling
4920 ; LDR instructions than we can with LDM.
4921 ; This pattern will only match if the one above did not.
4922 (define_split
4923   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4924         (match_operand:ANY64 1 "const_double_operand" ""))]
4925   "TARGET_ARM && reload_completed
4926    && arm_const_double_by_parts (operands[1])"
4927   [(set (match_dup 0) (match_dup 1))
4928    (set (match_dup 2) (match_dup 3))]
4929   "
4930   operands[2] = gen_highpart (SImode, operands[0]);
4931   operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4932                                    operands[1]);
4933   operands[0] = gen_lowpart (SImode, operands[0]);
4934   operands[1] = gen_lowpart (SImode, operands[1]);
4935   "
4936 )
4937
4938 (define_split
4939   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4940         (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4941   "TARGET_EITHER && reload_completed"
4942   [(set (match_dup 0) (match_dup 1))
4943    (set (match_dup 2) (match_dup 3))]
4944   "
4945   operands[2] = gen_highpart (SImode, operands[0]);
4946   operands[3] = gen_highpart (SImode, operands[1]);
4947   operands[0] = gen_lowpart (SImode, operands[0]);
4948   operands[1] = gen_lowpart (SImode, operands[1]);
4949
4950   /* Handle a partial overlap.  */
4951   if (rtx_equal_p (operands[0], operands[3]))
4952     {
4953       rtx tmp0 = operands[0];
4954       rtx tmp1 = operands[1];
4955
4956       operands[0] = operands[2];
4957       operands[1] = operands[3];
4958       operands[2] = tmp0;
4959       operands[3] = tmp1;
4960     }
4961   "
4962 )
4963
4964 ;; We can't actually do base+index doubleword loads if the index and
4965 ;; destination overlap.  Split here so that we at least have chance to
4966 ;; schedule.
4967 (define_split
4968   [(set (match_operand:DI 0 "s_register_operand" "")
4969         (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4970                          (match_operand:SI 2 "s_register_operand" ""))))]
4971   "TARGET_LDRD
4972   && reg_overlap_mentioned_p (operands[0], operands[1])
4973   && reg_overlap_mentioned_p (operands[0], operands[2])"
4974   [(set (match_dup 4)
4975         (plus:SI (match_dup 1)
4976                  (match_dup 2)))
4977    (set (match_dup 0)
4978         (mem:DI (match_dup 4)))]
4979   "
4980   operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4981   "
4982 )
4983
4984 ;;; ??? This should have alternatives for constants.
4985 ;;; ??? This was originally identical to the movdf_insn pattern.
4986 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4987 ;;; thumb_reorg with a memory reference.
4988 (define_insn "*thumb1_movdi_insn"
4989   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4990         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
4991   "TARGET_THUMB1
4992    && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4993    && (   register_operand (operands[0], DImode)
4994        || register_operand (operands[1], DImode))"
4995   "*
4996   {
4997   switch (which_alternative)
4998     {
4999     default:
5000     case 0:
5001       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5002         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
5003       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
5004     case 1:
5005       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
5006     case 2:
5007       operands[1] = GEN_INT (- INTVAL (operands[1]));
5008       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
5009     case 3:
5010       return \"ldmia\\t%1, {%0, %H0}\";
5011     case 4:
5012       return \"stmia\\t%0, {%1, %H1}\";
5013     case 5:
5014       return thumb_load_double_from_address (operands);
5015     case 6:
5016       operands[2] = gen_rtx_MEM (SImode,
5017                              plus_constant (XEXP (operands[0], 0), 4));
5018       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5019       return \"\";
5020     case 7:
5021       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5022         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5023       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5024     }
5025   }"
5026   [(set_attr "length" "4,4,6,2,2,6,4,4")
5027    (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
5028    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
5029 )
5030
5031 (define_expand "movsi"
5032   [(set (match_operand:SI 0 "general_operand" "")
5033         (match_operand:SI 1 "general_operand" ""))]
5034   "TARGET_EITHER"
5035   "
5036   {
5037   rtx base, offset, tmp;
5038
5039   if (TARGET_32BIT)
5040     {
5041       /* Everything except mem = const or mem = mem can be done easily.  */
5042       if (GET_CODE (operands[0]) == MEM)
5043         operands[1] = force_reg (SImode, operands[1]);
5044       if (arm_general_register_operand (operands[0], SImode)
5045           && GET_CODE (operands[1]) == CONST_INT
5046           && !(const_ok_for_arm (INTVAL (operands[1]))
5047                || const_ok_for_arm (~INTVAL (operands[1]))))
5048         {
5049            arm_split_constant (SET, SImode, NULL_RTX,
5050                                INTVAL (operands[1]), operands[0], NULL_RTX,
5051                                optimize && can_create_pseudo_p ());
5052           DONE;
5053         }
5054
5055       if (TARGET_USE_MOVT && !target_word_relocations
5056           && GET_CODE (operands[1]) == SYMBOL_REF
5057           && !flag_pic && !arm_tls_referenced_p (operands[1]))
5058         {
5059           arm_emit_movpair (operands[0], operands[1]);
5060           DONE;
5061         }
5062     }
5063   else /* TARGET_THUMB1...  */
5064     {
5065       if (can_create_pseudo_p ())
5066         {
5067           if (GET_CODE (operands[0]) != REG)
5068             operands[1] = force_reg (SImode, operands[1]);
5069         }
5070     }
5071
5072   if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
5073     {
5074       split_const (operands[1], &base, &offset);
5075       if (GET_CODE (base) == SYMBOL_REF
5076           && !offset_within_block_p (base, INTVAL (offset)))
5077         {
5078           tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5079           emit_move_insn (tmp, base);
5080           emit_insn (gen_addsi3 (operands[0], tmp, offset));
5081           DONE;
5082         }
5083     }
5084
5085   /* Recognize the case where operand[1] is a reference to thread-local
5086      data and load its address to a register.  */
5087   if (arm_tls_referenced_p (operands[1]))
5088     {
5089       rtx tmp = operands[1];
5090       rtx addend = NULL;
5091
5092       if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
5093         {
5094           addend = XEXP (XEXP (tmp, 0), 1);
5095           tmp = XEXP (XEXP (tmp, 0), 0);
5096         }
5097
5098       gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
5099       gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
5100
5101       tmp = legitimize_tls_address (tmp,
5102                                     !can_create_pseudo_p () ? operands[0] : 0);
5103       if (addend)
5104         {
5105           tmp = gen_rtx_PLUS (SImode, tmp, addend);
5106           tmp = force_operand (tmp, operands[0]);
5107         }
5108       operands[1] = tmp;
5109     }
5110   else if (flag_pic
5111            && (CONSTANT_P (operands[1])
5112                || symbol_mentioned_p (operands[1])
5113                || label_mentioned_p (operands[1])))
5114       operands[1] = legitimize_pic_address (operands[1], SImode,
5115                                             (!can_create_pseudo_p ()
5116                                              ? operands[0]
5117                                              : 0));
5118   }
5119   "
5120 )
5121
5122 ;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5123 ;; LO_SUM adds in the high bits.  Fortunately these are opaque operations
5124 ;; so this does not matter.
5125 (define_insn "*arm_movt"
5126   [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5127         (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5128                    (match_operand:SI 2 "general_operand"      "i")))]
5129   "TARGET_32BIT"
5130   "movt%?\t%0, #:upper16:%c2"
5131   [(set_attr "predicable" "yes")
5132    (set_attr "length" "4")]
5133 )
5134
5135 (define_insn "*arm_movsi_insn"
5136   [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
5137         (match_operand:SI 1 "general_operand"      "rk, I,K,j,mi,rk"))]
5138   "TARGET_ARM && ! TARGET_IWMMXT
5139    && !(TARGET_HARD_FLOAT && TARGET_VFP)
5140    && (   register_operand (operands[0], SImode)
5141        || register_operand (operands[1], SImode))"
5142   "@
5143    mov%?\\t%0, %1
5144    mov%?\\t%0, %1
5145    mvn%?\\t%0, #%B1
5146    movw%?\\t%0, %1
5147    ldr%?\\t%0, %1
5148    str%?\\t%1, %0"
5149   [(set_attr "type" "*,*,*,*,load1,store1")
5150    (set_attr "predicable" "yes")
5151    (set_attr "pool_range" "*,*,*,*,4096,*")
5152    (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
5153 )
5154
5155 (define_split
5156   [(set (match_operand:SI 0 "arm_general_register_operand" "")
5157         (match_operand:SI 1 "const_int_operand" ""))]
5158   "TARGET_32BIT
5159   && (!(const_ok_for_arm (INTVAL (operands[1]))
5160         || const_ok_for_arm (~INTVAL (operands[1]))))"
5161   [(clobber (const_int 0))]
5162   "
5163   arm_split_constant (SET, SImode, NULL_RTX, 
5164                       INTVAL (operands[1]), operands[0], NULL_RTX, 0);
5165   DONE;
5166   "
5167 )
5168
5169 (define_insn "*thumb1_movsi_insn"
5170   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lhk")
5171         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lhk"))]
5172   "TARGET_THUMB1
5173    && (   register_operand (operands[0], SImode) 
5174        || register_operand (operands[1], SImode))"
5175   "@
5176    mov  %0, %1
5177    mov  %0, %1
5178    #
5179    #
5180    ldmia\\t%1, {%0}
5181    stmia\\t%0, {%1}
5182    ldr\\t%0, %1
5183    str\\t%1, %0
5184    mov\\t%0, %1"
5185   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
5186    (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
5187    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
5188 )
5189
5190 (define_split 
5191   [(set (match_operand:SI 0 "register_operand" "")
5192         (match_operand:SI 1 "const_int_operand" ""))]
5193   "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
5194   [(set (match_dup 0) (match_dup 1))
5195    (set (match_dup 0) (neg:SI (match_dup 0)))]
5196   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
5197 )
5198
5199 (define_split 
5200   [(set (match_operand:SI 0 "register_operand" "")
5201         (match_operand:SI 1 "const_int_operand" ""))]
5202   "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
5203   [(set (match_dup 0) (match_dup 1))
5204    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
5205   "
5206   {
5207     unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu;
5208     unsigned HOST_WIDE_INT mask = 0xff;
5209     int i;
5210     
5211     for (i = 0; i < 25; i++)
5212       if ((val & (mask << i)) == val)
5213         break;
5214
5215     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
5216     if (i == 0)
5217       FAIL;
5218
5219     operands[1] = GEN_INT (val >> i);
5220     operands[2] = GEN_INT (i);
5221   }"
5222 )
5223
5224 ;; When generating pic, we need to load the symbol offset into a register.
5225 ;; So that the optimizer does not confuse this with a normal symbol load
5226 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
5227 ;; since that is the only type of relocation we can use.
5228
5229 ;; The rather odd constraints on the following are to force reload to leave
5230 ;; the insn alone, and to force the minipool generation pass to then move
5231 ;; the GOT symbol to memory.
5232
5233 (define_insn "pic_load_addr_32bit"
5234   [(set (match_operand:SI 0 "s_register_operand" "=r")
5235         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
5236   "TARGET_32BIT && flag_pic"
5237   "ldr%?\\t%0, %1"
5238   [(set_attr "type" "load1")
5239    (set_attr "pool_range" "4096")
5240    (set (attr "neg_pool_range")
5241         (if_then_else (eq_attr "is_thumb" "no")
5242                       (const_int 4084)
5243                       (const_int 0)))]
5244 )
5245
5246 (define_insn "pic_load_addr_thumb1"
5247   [(set (match_operand:SI 0 "s_register_operand" "=l")
5248         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
5249   "TARGET_THUMB1 && flag_pic"
5250   "ldr\\t%0, %1"
5251   [(set_attr "type" "load1")
5252    (set (attr "pool_range") (const_int 1024))]
5253 )
5254
5255 (define_insn "pic_add_dot_plus_four"
5256   [(set (match_operand:SI 0 "register_operand" "=r")
5257         (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5258                     (const_int 4)
5259                     (match_operand 2 "" "")]
5260                    UNSPEC_PIC_BASE))]
5261   "TARGET_THUMB"
5262   "*
5263   (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5264                                      INTVAL (operands[2]));
5265   return \"add\\t%0, %|pc\";
5266   "
5267   [(set_attr "length" "2")]
5268 )
5269
5270 (define_insn "pic_add_dot_plus_eight"
5271   [(set (match_operand:SI 0 "register_operand" "=r")
5272         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5273                     (const_int 8)
5274                     (match_operand 2 "" "")]
5275                    UNSPEC_PIC_BASE))]
5276   "TARGET_ARM"
5277   "*
5278     (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5279                                        INTVAL (operands[2]));
5280     return \"add%?\\t%0, %|pc, %1\";
5281   "
5282   [(set_attr "predicable" "yes")]
5283 )
5284
5285 (define_insn "tls_load_dot_plus_eight"
5286   [(set (match_operand:SI 0 "register_operand" "=r")
5287         (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5288                             (const_int 8)
5289                             (match_operand 2 "" "")]
5290                            UNSPEC_PIC_BASE)))]
5291   "TARGET_ARM"
5292   "*
5293     (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5294                                        INTVAL (operands[2]));
5295     return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5296   "
5297   [(set_attr "predicable" "yes")]
5298 )
5299
5300 ;; PIC references to local variables can generate pic_add_dot_plus_eight
5301 ;; followed by a load.  These sequences can be crunched down to
5302 ;; tls_load_dot_plus_eight by a peephole.
5303
5304 (define_peephole2
5305   [(set (match_operand:SI 0 "register_operand" "")
5306         (unspec:SI [(match_operand:SI 3 "register_operand" "")
5307                     (const_int 8)
5308                     (match_operand 1 "" "")]
5309                    UNSPEC_PIC_BASE))
5310    (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
5311   "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
5312   [(set (match_dup 2)
5313         (mem:SI (unspec:SI [(match_dup 3)
5314                             (const_int 8)
5315                             (match_dup 1)]
5316                            UNSPEC_PIC_BASE)))]
5317   ""
5318 )
5319
5320 (define_insn "pic_offset_arm"
5321   [(set (match_operand:SI 0 "register_operand" "=r")
5322         (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5323                          (unspec:SI [(match_operand:SI 2 "" "X")]
5324                                     UNSPEC_PIC_OFFSET))))]
5325   "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5326   "ldr%?\\t%0, [%1,%2]"
5327   [(set_attr "type" "load1")]
5328 )
5329
5330 (define_expand "builtin_setjmp_receiver"
5331   [(label_ref (match_operand 0 "" ""))]
5332   "flag_pic"
5333   "
5334 {
5335   /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5336      register.  */
5337   if (arm_pic_register != INVALID_REGNUM)
5338     arm_load_pic_register (1UL << 3);
5339   DONE;
5340 }")
5341
5342 ;; If copying one reg to another we can set the condition codes according to
5343 ;; its value.  Such a move is common after a return from subroutine and the
5344 ;; result is being tested against zero.
5345
5346 (define_insn "*movsi_compare0"
5347   [(set (reg:CC CC_REGNUM)
5348         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5349                     (const_int 0)))
5350    (set (match_operand:SI 0 "s_register_operand" "=r,r")
5351         (match_dup 1))]
5352   "TARGET_32BIT"
5353   "@
5354    cmp%?\\t%0, #0
5355    sub%.\\t%0, %1, #0"
5356   [(set_attr "conds" "set")]
5357 )
5358
5359 ;; Subroutine to store a half word from a register into memory.
5360 ;; Operand 0 is the source register (HImode)
5361 ;; Operand 1 is the destination address in a register (SImode)
5362
5363 ;; In both this routine and the next, we must be careful not to spill
5364 ;; a memory address of reg+large_const into a separate PLUS insn, since this
5365 ;; can generate unrecognizable rtl.
5366
5367 (define_expand "storehi"
5368   [;; store the low byte
5369    (set (match_operand 1 "" "") (match_dup 3))
5370    ;; extract the high byte
5371    (set (match_dup 2)
5372         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
5373    ;; store the high byte
5374    (set (match_dup 4) (match_dup 5))]
5375   "TARGET_ARM"
5376   "
5377   {
5378     rtx op1 = operands[1];
5379     rtx addr = XEXP (op1, 0);
5380     enum rtx_code code = GET_CODE (addr);
5381
5382     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5383         || code == MINUS)
5384       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
5385
5386     operands[4] = adjust_address (op1, QImode, 1);
5387     operands[1] = adjust_address (operands[1], QImode, 0);
5388     operands[3] = gen_lowpart (QImode, operands[0]);
5389     operands[0] = gen_lowpart (SImode, operands[0]);
5390     operands[2] = gen_reg_rtx (SImode);
5391     operands[5] = gen_lowpart (QImode, operands[2]);
5392   }"
5393 )
5394
5395 (define_expand "storehi_bigend"
5396   [(set (match_dup 4) (match_dup 3))
5397    (set (match_dup 2)
5398         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
5399    (set (match_operand 1 "" "") (match_dup 5))]
5400   "TARGET_ARM"
5401   "
5402   {
5403     rtx op1 = operands[1];
5404     rtx addr = XEXP (op1, 0);
5405     enum rtx_code code = GET_CODE (addr);
5406
5407     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5408         || code == MINUS)
5409       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
5410
5411     operands[4] = adjust_address (op1, QImode, 1);
5412     operands[1] = adjust_address (operands[1], QImode, 0);
5413     operands[3] = gen_lowpart (QImode, operands[0]);
5414     operands[0] = gen_lowpart (SImode, operands[0]);
5415     operands[2] = gen_reg_rtx (SImode);
5416     operands[5] = gen_lowpart (QImode, operands[2]);
5417   }"
5418 )
5419
5420 ;; Subroutine to store a half word integer constant into memory.
5421 (define_expand "storeinthi"
5422   [(set (match_operand 0 "" "")
5423         (match_operand 1 "" ""))
5424    (set (match_dup 3) (match_dup 2))]
5425   "TARGET_ARM"
5426   "
5427   {
5428     HOST_WIDE_INT value = INTVAL (operands[1]);
5429     rtx addr = XEXP (operands[0], 0);
5430     rtx op0 = operands[0];
5431     enum rtx_code code = GET_CODE (addr);
5432
5433     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5434         || code == MINUS)
5435       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
5436
5437     operands[1] = gen_reg_rtx (SImode);
5438     if (BYTES_BIG_ENDIAN)
5439       {
5440         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5441         if ((value & 255) == ((value >> 8) & 255))
5442           operands[2] = operands[1];
5443         else
5444           {
5445             operands[2] = gen_reg_rtx (SImode);
5446             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5447           }
5448       }
5449     else
5450       {
5451         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5452         if ((value & 255) == ((value >> 8) & 255))
5453           operands[2] = operands[1];
5454         else
5455           {
5456             operands[2] = gen_reg_rtx (SImode);
5457             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5458           }
5459       }
5460
5461     operands[3] = adjust_address (op0, QImode, 1);
5462     operands[0] = adjust_address (operands[0], QImode, 0);
5463     operands[2] = gen_lowpart (QImode, operands[2]);
5464     operands[1] = gen_lowpart (QImode, operands[1]);
5465   }"
5466 )
5467
5468 (define_expand "storehi_single_op"
5469   [(set (match_operand:HI 0 "memory_operand" "")
5470         (match_operand:HI 1 "general_operand" ""))]
5471   "TARGET_32BIT && arm_arch4"
5472   "
5473   if (!s_register_operand (operands[1], HImode))
5474     operands[1] = copy_to_mode_reg (HImode, operands[1]);
5475   "
5476 )
5477
5478 (define_expand "movhi"
5479   [(set (match_operand:HI 0 "general_operand" "")
5480         (match_operand:HI 1 "general_operand" ""))]
5481   "TARGET_EITHER"
5482   "
5483   if (TARGET_ARM)
5484     {
5485       if (can_create_pseudo_p ())
5486         {
5487           if (GET_CODE (operands[0]) == MEM)
5488             {
5489               if (arm_arch4)
5490                 {
5491                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5492                   DONE;
5493                 }
5494               if (GET_CODE (operands[1]) == CONST_INT)
5495                 emit_insn (gen_storeinthi (operands[0], operands[1]));
5496               else
5497                 {
5498                   if (GET_CODE (operands[1]) == MEM)
5499                     operands[1] = force_reg (HImode, operands[1]);
5500                   if (BYTES_BIG_ENDIAN)
5501                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
5502                   else
5503                    emit_insn (gen_storehi (operands[1], operands[0]));
5504                 }
5505               DONE;
5506             }
5507           /* Sign extend a constant, and keep it in an SImode reg.  */
5508           else if (GET_CODE (operands[1]) == CONST_INT)
5509             {
5510               rtx reg = gen_reg_rtx (SImode);
5511               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5512
5513               /* If the constant is already valid, leave it alone.  */
5514               if (!const_ok_for_arm (val))
5515                 {
5516                   /* If setting all the top bits will make the constant 
5517                      loadable in a single instruction, then set them.  
5518                      Otherwise, sign extend the number.  */
5519
5520                   if (const_ok_for_arm (~(val | ~0xffff)))
5521                     val |= ~0xffff;
5522                   else if (val & 0x8000)
5523                     val |= ~0xffff;
5524                 }
5525
5526               emit_insn (gen_movsi (reg, GEN_INT (val)));
5527               operands[1] = gen_lowpart (HImode, reg);
5528             }
5529           else if (arm_arch4 && optimize && can_create_pseudo_p ()
5530                    && GET_CODE (operands[1]) == MEM)
5531             {
5532               rtx reg = gen_reg_rtx (SImode);
5533
5534               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5535               operands[1] = gen_lowpart (HImode, reg);
5536             }
5537           else if (!arm_arch4)
5538             {
5539               if (GET_CODE (operands[1]) == MEM)
5540                 {
5541                   rtx base;
5542                   rtx offset = const0_rtx;
5543                   rtx reg = gen_reg_rtx (SImode);
5544
5545                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
5546                        || (GET_CODE (base) == PLUS
5547                            && (GET_CODE (offset = XEXP (base, 1))
5548                                == CONST_INT)
5549                            && ((INTVAL(offset) & 1) != 1)
5550                            && GET_CODE (base = XEXP (base, 0)) == REG))
5551                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
5552                     {
5553                       rtx new_rtx;
5554
5555                       new_rtx = widen_memory_access (operands[1], SImode,
5556                                                      ((INTVAL (offset) & ~3)
5557                                                       - INTVAL (offset)));
5558                       emit_insn (gen_movsi (reg, new_rtx));
5559                       if (((INTVAL (offset) & 2) != 0)
5560                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
5561                         {
5562                           rtx reg2 = gen_reg_rtx (SImode);
5563
5564                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
5565                           reg = reg2;
5566                         }
5567                     }
5568                   else
5569                     emit_insn (gen_movhi_bytes (reg, operands[1]));
5570
5571                   operands[1] = gen_lowpart (HImode, reg);
5572                }
5573            }
5574         }
5575       /* Handle loading a large integer during reload.  */
5576       else if (GET_CODE (operands[1]) == CONST_INT
5577                && !const_ok_for_arm (INTVAL (operands[1]))
5578                && !const_ok_for_arm (~INTVAL (operands[1])))
5579         {
5580           /* Writing a constant to memory needs a scratch, which should
5581              be handled with SECONDARY_RELOADs.  */
5582           gcc_assert (GET_CODE (operands[0]) == REG);
5583
5584           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5585           emit_insn (gen_movsi (operands[0], operands[1]));
5586           DONE;
5587        }
5588     }
5589   else if (TARGET_THUMB2)
5590     {
5591       /* Thumb-2 can do everything except mem=mem and mem=const easily.  */
5592       if (can_create_pseudo_p ())
5593         {
5594           if (GET_CODE (operands[0]) != REG)
5595             operands[1] = force_reg (HImode, operands[1]);
5596           /* Zero extend a constant, and keep it in an SImode reg.  */
5597           else if (GET_CODE (operands[1]) == CONST_INT)
5598             {
5599               rtx reg = gen_reg_rtx (SImode);
5600               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5601
5602               emit_insn (gen_movsi (reg, GEN_INT (val)));
5603               operands[1] = gen_lowpart (HImode, reg);
5604             }
5605         }
5606     }
5607   else /* TARGET_THUMB1 */
5608     {
5609       if (can_create_pseudo_p ())
5610         {
5611           if (GET_CODE (operands[1]) == CONST_INT)
5612             {
5613               rtx reg = gen_reg_rtx (SImode);
5614
5615               emit_insn (gen_movsi (reg, operands[1]));
5616               operands[1] = gen_lowpart (HImode, reg);
5617             }
5618
5619           /* ??? We shouldn't really get invalid addresses here, but this can
5620              happen if we are passed a SP (never OK for HImode/QImode) or 
5621              virtual register (also rejected as illegitimate for HImode/QImode)
5622              relative address.  */
5623           /* ??? This should perhaps be fixed elsewhere, for instance, in
5624              fixup_stack_1, by checking for other kinds of invalid addresses,
5625              e.g. a bare reference to a virtual register.  This may confuse the
5626              alpha though, which must handle this case differently.  */
5627           if (GET_CODE (operands[0]) == MEM
5628               && !memory_address_p (GET_MODE (operands[0]),
5629                                     XEXP (operands[0], 0)))
5630             operands[0]
5631               = replace_equiv_address (operands[0],
5632                                        copy_to_reg (XEXP (operands[0], 0)));
5633    
5634           if (GET_CODE (operands[1]) == MEM
5635               && !memory_address_p (GET_MODE (operands[1]),
5636                                     XEXP (operands[1], 0)))
5637             operands[1]
5638               = replace_equiv_address (operands[1],
5639                                        copy_to_reg (XEXP (operands[1], 0)));
5640
5641           if (GET_CODE (operands[1]) == MEM && optimize > 0)
5642             {
5643               rtx reg = gen_reg_rtx (SImode);
5644
5645               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5646               operands[1] = gen_lowpart (HImode, reg);
5647             }
5648
5649           if (GET_CODE (operands[0]) == MEM)
5650             operands[1] = force_reg (HImode, operands[1]);
5651         }
5652       else if (GET_CODE (operands[1]) == CONST_INT
5653                 && !satisfies_constraint_I (operands[1]))
5654         {
5655           /* Handle loading a large integer during reload.  */
5656
5657           /* Writing a constant to memory needs a scratch, which should
5658              be handled with SECONDARY_RELOADs.  */
5659           gcc_assert (GET_CODE (operands[0]) == REG);
5660
5661           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5662           emit_insn (gen_movsi (operands[0], operands[1]));
5663           DONE;
5664         }
5665     }
5666   "
5667 )
5668
5669 (define_insn "*thumb1_movhi_insn"
5670   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5671         (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
5672   "TARGET_THUMB1
5673    && (   register_operand (operands[0], HImode)
5674        || register_operand (operands[1], HImode))"
5675   "*
5676   switch (which_alternative)
5677     {
5678     case 0: return \"add        %0, %1, #0\";
5679     case 2: return \"strh       %1, %0\";
5680     case 3: return \"mov        %0, %1\";
5681     case 4: return \"mov        %0, %1\";
5682     case 5: return \"mov        %0, %1\";
5683     default: gcc_unreachable ();
5684     case 1:
5685       /* The stack pointer can end up being taken as an index register.
5686           Catch this case here and deal with it.  */
5687       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
5688           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
5689           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
5690         {
5691           rtx ops[2];
5692           ops[0] = operands[0];
5693           ops[1] = XEXP (XEXP (operands[1], 0), 0);
5694       
5695           output_asm_insn (\"mov        %0, %1\", ops);
5696
5697           XEXP (XEXP (operands[1], 0), 0) = operands[0];
5698     
5699         }
5700       return \"ldrh     %0, %1\";
5701     }"
5702   [(set_attr "length" "2,4,2,2,2,2")
5703    (set_attr "type" "*,load1,store1,*,*,*")]
5704 )
5705
5706
5707 (define_expand "movhi_bytes"
5708   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
5709    (set (match_dup 3)
5710         (zero_extend:SI (match_dup 6)))
5711    (set (match_operand:SI 0 "" "")
5712          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
5713   "TARGET_ARM"
5714   "
5715   {
5716     rtx mem1, mem2;
5717     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5718
5719     mem1 = change_address (operands[1], QImode, addr);
5720     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
5721     operands[0] = gen_lowpart (SImode, operands[0]);
5722     operands[1] = mem1;
5723     operands[2] = gen_reg_rtx (SImode);
5724     operands[3] = gen_reg_rtx (SImode);
5725     operands[6] = mem2;
5726
5727     if (BYTES_BIG_ENDIAN)
5728       {
5729         operands[4] = operands[2];
5730         operands[5] = operands[3];
5731       }
5732     else
5733       {
5734         operands[4] = operands[3];
5735         operands[5] = operands[2];
5736       }
5737   }"
5738 )
5739
5740 (define_expand "movhi_bigend"
5741   [(set (match_dup 2)
5742         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
5743                    (const_int 16)))
5744    (set (match_dup 3)
5745         (ashiftrt:SI (match_dup 2) (const_int 16)))
5746    (set (match_operand:HI 0 "s_register_operand" "")
5747         (match_dup 4))]
5748   "TARGET_ARM"
5749   "
5750   operands[2] = gen_reg_rtx (SImode);
5751   operands[3] = gen_reg_rtx (SImode);
5752   operands[4] = gen_lowpart (HImode, operands[3]);
5753   "
5754 )
5755
5756 ;; Pattern to recognize insn generated default case above
5757 (define_insn "*movhi_insn_arch4"
5758   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
5759         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
5760   "TARGET_ARM
5761    && arm_arch4
5762    && (GET_CODE (operands[1]) != CONST_INT
5763        || const_ok_for_arm (INTVAL (operands[1]))
5764        || const_ok_for_arm (~INTVAL (operands[1])))"
5765   "@
5766    mov%?\\t%0, %1\\t%@ movhi
5767    mvn%?\\t%0, #%B1\\t%@ movhi
5768    str%(h%)\\t%1, %0\\t%@ movhi
5769    ldr%(h%)\\t%0, %1\\t%@ movhi"
5770   [(set_attr "type" "*,*,store1,load1")
5771    (set_attr "predicable" "yes")
5772    (set_attr "pool_range" "*,*,*,256")
5773    (set_attr "neg_pool_range" "*,*,*,244")]
5774 )
5775
5776 (define_insn "*movhi_bytes"
5777   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
5778         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
5779   "TARGET_ARM"
5780   "@
5781    mov%?\\t%0, %1\\t%@ movhi
5782    mvn%?\\t%0, #%B1\\t%@ movhi"
5783   [(set_attr "predicable" "yes")]
5784 )
5785
5786 (define_expand "thumb_movhi_clobber"
5787   [(set (match_operand:HI     0 "memory_operand"   "")
5788         (match_operand:HI     1 "register_operand" ""))
5789    (clobber (match_operand:DI 2 "register_operand" ""))]
5790   "TARGET_THUMB1"
5791   "
5792   if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
5793       && REGNO (operands[1]) <= LAST_LO_REGNUM)
5794     {
5795       emit_insn (gen_movhi (operands[0], operands[1]));
5796       DONE;
5797     }
5798   /* XXX Fixme, need to handle other cases here as well.  */
5799   gcc_unreachable ();
5800   "
5801 )
5802         
5803 ;; We use a DImode scratch because we may occasionally need an additional
5804 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
5805 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
5806 (define_expand "reload_outhi"
5807   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
5808               (match_operand:HI 1 "s_register_operand"        "r")
5809               (match_operand:DI 2 "s_register_operand"        "=&l")])]
5810   "TARGET_EITHER"
5811   "if (TARGET_ARM)
5812      arm_reload_out_hi (operands);
5813    else
5814      thumb_reload_out_hi (operands);
5815   DONE;
5816   "
5817 )
5818
5819 (define_expand "reload_inhi"
5820   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
5821               (match_operand:HI 1 "arm_reload_memory_operand" "o")
5822               (match_operand:DI 2 "s_register_operand" "=&r")])]
5823   "TARGET_EITHER"
5824   "
5825   if (TARGET_ARM)
5826     arm_reload_in_hi (operands);
5827   else
5828     thumb_reload_out_hi (operands);
5829   DONE;
5830 ")
5831
5832 (define_expand "movqi"
5833   [(set (match_operand:QI 0 "general_operand" "")
5834         (match_operand:QI 1 "general_operand" ""))]
5835   "TARGET_EITHER"
5836   "
5837   /* Everything except mem = const or mem = mem can be done easily */
5838
5839   if (can_create_pseudo_p ())
5840     {
5841       if (GET_CODE (operands[1]) == CONST_INT)
5842         {
5843           rtx reg = gen_reg_rtx (SImode);
5844
5845           /* For thumb we want an unsigned immediate, then we are more likely 
5846              to be able to use a movs insn.  */
5847           if (TARGET_THUMB)
5848             operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
5849
5850           emit_insn (gen_movsi (reg, operands[1]));
5851           operands[1] = gen_lowpart (QImode, reg);
5852         }
5853
5854       if (TARGET_THUMB)
5855         {
5856           /* ??? We shouldn't really get invalid addresses here, but this can
5857              happen if we are passed a SP (never OK for HImode/QImode) or
5858              virtual register (also rejected as illegitimate for HImode/QImode)
5859              relative address.  */
5860           /* ??? This should perhaps be fixed elsewhere, for instance, in
5861              fixup_stack_1, by checking for other kinds of invalid addresses,
5862              e.g. a bare reference to a virtual register.  This may confuse the
5863              alpha though, which must handle this case differently.  */
5864           if (GET_CODE (operands[0]) == MEM
5865               && !memory_address_p (GET_MODE (operands[0]),
5866                                      XEXP (operands[0], 0)))
5867             operands[0]
5868               = replace_equiv_address (operands[0],
5869                                        copy_to_reg (XEXP (operands[0], 0)));
5870           if (GET_CODE (operands[1]) == MEM
5871               && !memory_address_p (GET_MODE (operands[1]),
5872                                     XEXP (operands[1], 0)))
5873              operands[1]
5874                = replace_equiv_address (operands[1],
5875                                         copy_to_reg (XEXP (operands[1], 0)));
5876         }
5877
5878       if (GET_CODE (operands[1]) == MEM && optimize > 0)
5879         {
5880           rtx reg = gen_reg_rtx (SImode);
5881
5882           emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5883           operands[1] = gen_lowpart (QImode, reg);
5884         }
5885
5886       if (GET_CODE (operands[0]) == MEM)
5887         operands[1] = force_reg (QImode, operands[1]);
5888     }
5889   else if (TARGET_THUMB
5890            && GET_CODE (operands[1]) == CONST_INT
5891            && !satisfies_constraint_I (operands[1]))
5892     {
5893       /* Handle loading a large integer during reload.  */
5894
5895       /* Writing a constant to memory needs a scratch, which should
5896          be handled with SECONDARY_RELOADs.  */
5897       gcc_assert (GET_CODE (operands[0]) == REG);
5898
5899       operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5900       emit_insn (gen_movsi (operands[0], operands[1]));
5901       DONE;
5902     }
5903   "
5904 )
5905
5906
5907 (define_insn "*arm_movqi_insn"
5908   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5909         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5910   "TARGET_32BIT
5911    && (   register_operand (operands[0], QImode)
5912        || register_operand (operands[1], QImode))"
5913   "@
5914    mov%?\\t%0, %1
5915    mvn%?\\t%0, #%B1
5916    ldr%(b%)\\t%0, %1
5917    str%(b%)\\t%1, %0"
5918   [(set_attr "type" "*,*,load1,store1")
5919    (set_attr "predicable" "yes")]
5920 )
5921
5922 (define_insn "*thumb1_movqi_insn"
5923   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5924         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
5925   "TARGET_THUMB1
5926    && (   register_operand (operands[0], QImode)
5927        || register_operand (operands[1], QImode))"
5928   "@
5929    add\\t%0, %1, #0
5930    ldrb\\t%0, %1
5931    strb\\t%1, %0
5932    mov\\t%0, %1
5933    mov\\t%0, %1
5934    mov\\t%0, %1"
5935   [(set_attr "length" "2")
5936    (set_attr "type" "*,load1,store1,*,*,*")
5937    (set_attr "pool_range" "*,32,*,*,*,*")]
5938 )
5939
5940 ;; HFmode moves
5941 (define_expand "movhf"
5942   [(set (match_operand:HF 0 "general_operand" "")
5943         (match_operand:HF 1 "general_operand" ""))]
5944   "TARGET_EITHER"
5945   "
5946   if (TARGET_32BIT)
5947     {
5948       if (GET_CODE (operands[0]) == MEM)
5949         operands[1] = force_reg (HFmode, operands[1]);
5950     }
5951   else /* TARGET_THUMB1 */
5952     {
5953       if (can_create_pseudo_p ())
5954         {
5955            if (GET_CODE (operands[0]) != REG)
5956              operands[1] = force_reg (HFmode, operands[1]);
5957         }
5958     }
5959   "
5960 )
5961
5962 (define_insn "*arm32_movhf"
5963   [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
5964         (match_operand:HF 1 "general_operand"      " m,r,r,F"))]
5965   "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16)
5966    && (   s_register_operand (operands[0], HFmode)
5967        || s_register_operand (operands[1], HFmode))"
5968   "*
5969   switch (which_alternative)
5970     {
5971     case 0:     /* ARM register from memory */
5972       return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
5973     case 1:     /* memory from ARM register */
5974       return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
5975     case 2:     /* ARM register from ARM register */
5976       return \"mov%?\\t%0, %1\\t%@ __fp16\";
5977     case 3:     /* ARM register from constant */
5978       {
5979         REAL_VALUE_TYPE r;
5980         long bits;
5981         rtx ops[4];
5982
5983         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
5984         bits = real_to_target (NULL, &r, HFmode);
5985         ops[0] = operands[0];
5986         ops[1] = GEN_INT (bits);
5987         ops[2] = GEN_INT (bits & 0xff00);
5988         ops[3] = GEN_INT (bits & 0x00ff);
5989
5990         if (arm_arch_thumb2)
5991           output_asm_insn (\"movw%?\\t%0, %1\", ops);
5992         else
5993           output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
5994         return \"\";
5995        }
5996     default:
5997       gcc_unreachable ();
5998     }
5999   "
6000   [(set_attr "conds" "unconditional")
6001    (set_attr "type" "load1,store1,*,*")
6002    (set_attr "length" "4,4,4,8")
6003    (set_attr "predicable" "yes")
6004    ]
6005 )
6006
6007 (define_insn "*thumb1_movhf"
6008   [(set (match_operand:HF     0 "nonimmediate_operand" "=l,l,m,*r,*h")
6009         (match_operand:HF     1 "general_operand"      "l,mF,l,*h,*r"))]
6010   "TARGET_THUMB1
6011    && (   s_register_operand (operands[0], HFmode) 
6012        || s_register_operand (operands[1], HFmode))"
6013   "*
6014   switch (which_alternative)
6015     {
6016     case 1:
6017       {
6018         rtx addr;
6019         gcc_assert (GET_CODE(operands[1]) == MEM);
6020         addr = XEXP (operands[1], 0);
6021         if (GET_CODE (addr) == LABEL_REF
6022             || (GET_CODE (addr) == CONST
6023                 && GET_CODE (XEXP (addr, 0)) == PLUS
6024                 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF
6025                 && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT))
6026           {
6027             /* Constant pool entry.  */
6028             return \"ldr\\t%0, %1\";
6029           }
6030         return \"ldrh\\t%0, %1\";
6031       }
6032     case 2: return \"strh\\t%1, %0\";
6033     default: return \"mov\\t%0, %1\";
6034     }
6035   "
6036   [(set_attr "length" "2")
6037    (set_attr "type" "*,load1,store1,*,*")
6038    (set_attr "pool_range" "*,1020,*,*,*")]
6039 )
6040
6041 (define_expand "movsf"
6042   [(set (match_operand:SF 0 "general_operand" "")
6043         (match_operand:SF 1 "general_operand" ""))]
6044   "TARGET_EITHER"
6045   "
6046   if (TARGET_32BIT)
6047     {
6048       if (GET_CODE (operands[0]) == MEM)
6049         operands[1] = force_reg (SFmode, operands[1]);
6050     }
6051   else /* TARGET_THUMB1 */
6052     {
6053       if (can_create_pseudo_p ())
6054         {
6055            if (GET_CODE (operands[0]) != REG)
6056              operands[1] = force_reg (SFmode, operands[1]);
6057         }
6058     }
6059   "
6060 )
6061
6062 ;; Transform a floating-point move of a constant into a core register into
6063 ;; an SImode operation.
6064 (define_split
6065   [(set (match_operand:SF 0 "arm_general_register_operand" "")
6066         (match_operand:SF 1 "immediate_operand" ""))]
6067   "TARGET_EITHER
6068    && reload_completed
6069    && GET_CODE (operands[1]) == CONST_DOUBLE"
6070   [(set (match_dup 2) (match_dup 3))]
6071   "
6072   operands[2] = gen_lowpart (SImode, operands[0]);
6073   operands[3] = gen_lowpart (SImode, operands[1]);
6074   if (operands[2] == 0 || operands[3] == 0)
6075     FAIL;
6076   "
6077 )
6078
6079 (define_insn "*arm_movsf_soft_insn"
6080   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6081         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
6082   "TARGET_ARM
6083    && TARGET_SOFT_FLOAT
6084    && (GET_CODE (operands[0]) != MEM
6085        || register_operand (operands[1], SFmode))"
6086   "@
6087    mov%?\\t%0, %1
6088    ldr%?\\t%0, %1\\t%@ float
6089    str%?\\t%1, %0\\t%@ float"
6090   [(set_attr "length" "4,4,4")
6091    (set_attr "predicable" "yes")
6092    (set_attr "type" "*,load1,store1")
6093    (set_attr "pool_range" "*,4096,*")
6094    (set_attr "neg_pool_range" "*,4084,*")]
6095 )
6096
6097 ;;; ??? This should have alternatives for constants.
6098 (define_insn "*thumb1_movsf_insn"
6099   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
6100         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
6101   "TARGET_THUMB1
6102    && (   register_operand (operands[0], SFmode) 
6103        || register_operand (operands[1], SFmode))"
6104   "@
6105    add\\t%0, %1, #0
6106    ldmia\\t%1, {%0}
6107    stmia\\t%0, {%1}
6108    ldr\\t%0, %1
6109    str\\t%1, %0
6110    mov\\t%0, %1
6111    mov\\t%0, %1"
6112   [(set_attr "length" "2")
6113    (set_attr "type" "*,load1,store1,load1,store1,*,*")
6114    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
6115 )
6116
6117 (define_expand "movdf"
6118   [(set (match_operand:DF 0 "general_operand" "")
6119         (match_operand:DF 1 "general_operand" ""))]
6120   "TARGET_EITHER"
6121   "
6122   if (TARGET_32BIT)
6123     {
6124       if (GET_CODE (operands[0]) == MEM)
6125         operands[1] = force_reg (DFmode, operands[1]);
6126     }
6127   else /* TARGET_THUMB */
6128     {
6129       if (can_create_pseudo_p ())
6130         {
6131           if (GET_CODE (operands[0]) != REG)
6132             operands[1] = force_reg (DFmode, operands[1]);
6133         }
6134     }
6135   "
6136 )
6137
6138 ;; Reloading a df mode value stored in integer regs to memory can require a
6139 ;; scratch reg.
6140 (define_expand "reload_outdf"
6141   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
6142    (match_operand:DF 1 "s_register_operand" "r")
6143    (match_operand:SI 2 "s_register_operand" "=&r")]
6144   "TARGET_32BIT"
6145   "
6146   {
6147     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
6148
6149     if (code == REG)
6150       operands[2] = XEXP (operands[0], 0);
6151     else if (code == POST_INC || code == PRE_DEC)
6152       {
6153         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6154         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6155         emit_insn (gen_movdi (operands[0], operands[1]));
6156         DONE;
6157       }
6158     else if (code == PRE_INC)
6159       {
6160         rtx reg = XEXP (XEXP (operands[0], 0), 0);
6161
6162         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6163         operands[2] = reg;
6164       }
6165     else if (code == POST_DEC)
6166       operands[2] = XEXP (XEXP (operands[0], 0), 0);
6167     else
6168       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6169                              XEXP (XEXP (operands[0], 0), 1)));
6170
6171     emit_insn (gen_rtx_SET (VOIDmode,
6172                             replace_equiv_address (operands[0], operands[2]),
6173                             operands[1]));
6174
6175     if (code == POST_DEC)
6176       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6177
6178     DONE;
6179   }"
6180 )
6181
6182 (define_insn "*movdf_soft_insn"
6183   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
6184         (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
6185   "TARGET_ARM && TARGET_SOFT_FLOAT
6186    && (   register_operand (operands[0], DFmode)
6187        || register_operand (operands[1], DFmode))"
6188   "*
6189   switch (which_alternative)
6190     {
6191     case 0:
6192     case 1:
6193     case 2:
6194       return \"#\";
6195     default:
6196       return output_move_double (operands);
6197     }
6198   "
6199   [(set_attr "length" "8,12,16,8,8")
6200    (set_attr "type" "*,*,*,load2,store2")
6201    (set_attr "pool_range" "1020")
6202    (set_attr "neg_pool_range" "1008")]
6203 )
6204
6205 ;;; ??? This should have alternatives for constants.
6206 ;;; ??? This was originally identical to the movdi_insn pattern.
6207 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
6208 ;;; thumb_reorg with a memory reference.
6209 (define_insn "*thumb_movdf_insn"
6210   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
6211         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
6212   "TARGET_THUMB1
6213    && (   register_operand (operands[0], DFmode)
6214        || register_operand (operands[1], DFmode))"
6215   "*
6216   switch (which_alternative)
6217     {
6218     default:
6219     case 0:
6220       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6221         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
6222       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
6223     case 1:
6224       return \"ldmia\\t%1, {%0, %H0}\";
6225     case 2:
6226       return \"stmia\\t%0, {%1, %H1}\";
6227     case 3:
6228       return thumb_load_double_from_address (operands);
6229     case 4:
6230       operands[2] = gen_rtx_MEM (SImode,
6231                                  plus_constant (XEXP (operands[0], 0), 4));
6232       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
6233       return \"\";
6234     case 5:
6235       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6236         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
6237       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
6238     }
6239   "
6240   [(set_attr "length" "4,2,2,6,4,4")
6241    (set_attr "type" "*,load2,store2,load2,store2,*")
6242    (set_attr "pool_range" "*,*,*,1020,*,*")]
6243 )
6244
6245 (define_expand "movxf"
6246   [(set (match_operand:XF 0 "general_operand" "")
6247         (match_operand:XF 1 "general_operand" ""))]
6248   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
6249   "
6250   if (GET_CODE (operands[0]) == MEM)
6251     operands[1] = force_reg (XFmode, operands[1]);
6252   "
6253 )
6254
6255 \f
6256
6257 ;; load- and store-multiple insns
6258 ;; The arm can load/store any set of registers, provided that they are in
6259 ;; ascending order; but that is beyond GCC so stick with what it knows.
6260
6261 (define_expand "load_multiple"
6262   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6263                           (match_operand:SI 1 "" ""))
6264                      (use (match_operand:SI 2 "" ""))])]
6265   "TARGET_32BIT"
6266 {
6267   HOST_WIDE_INT offset = 0;
6268
6269   /* Support only fixed point registers.  */
6270   if (GET_CODE (operands[2]) != CONST_INT
6271       || INTVAL (operands[2]) > 14
6272       || INTVAL (operands[2]) < 2
6273       || GET_CODE (operands[1]) != MEM
6274       || GET_CODE (operands[0]) != REG
6275       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6276       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
6277     FAIL;
6278
6279   operands[3]
6280     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
6281                              force_reg (SImode, XEXP (operands[1], 0)),
6282                              TRUE, FALSE, operands[1], &offset);
6283 })
6284
6285 ;; Load multiple with write-back
6286
6287 (define_insn "*ldmsi_postinc4"
6288   [(match_parallel 0 "load_multiple_operation"
6289     [(set (match_operand:SI 1 "s_register_operand" "=r")
6290           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6291                    (const_int 16)))
6292      (set (match_operand:SI 3 "arm_hard_register_operand" "")
6293           (mem:SI (match_dup 2)))
6294      (set (match_operand:SI 4 "arm_hard_register_operand" "")
6295           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
6296      (set (match_operand:SI 5 "arm_hard_register_operand" "")
6297           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
6298      (set (match_operand:SI 6 "arm_hard_register_operand" "")
6299           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
6300   "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
6301   "ldm%(ia%)\\t%1!, {%3, %4, %5, %6}"
6302   [(set_attr "type" "load4")
6303    (set_attr "predicable" "yes")]
6304 )
6305
6306 (define_insn "*ldmsi_postinc4_thumb1"
6307   [(match_parallel 0 "load_multiple_operation"
6308     [(set (match_operand:SI 1 "s_register_operand" "=l")
6309           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6310                    (const_int 16)))
6311      (set (match_operand:SI 3 "arm_hard_register_operand" "")
6312           (mem:SI (match_dup 2)))
6313      (set (match_operand:SI 4 "arm_hard_register_operand" "")
6314           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
6315      (set (match_operand:SI 5 "arm_hard_register_operand" "")
6316           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
6317      (set (match_operand:SI 6 "arm_hard_register_operand" "")
6318           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
6319   "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
6320   "ldmia\\t%1!, {%3, %4, %5, %6}"
6321   [(set_attr "type" "load4")]
6322 )
6323
6324 (define_insn "*ldmsi_postinc3"
6325   [(match_parallel 0 "load_multiple_operation"
6326     [(set (match_operand:SI 1 "s_register_operand" "=r")
6327           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6328                    (const_int 12)))
6329      (set (match_operand:SI 3 "arm_hard_register_operand" "")
6330           (mem:SI (match_dup 2)))
6331      (set (match_operand:SI 4 "arm_hard_register_operand" "")
6332           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
6333      (set (match_operand:SI 5 "arm_hard_register_operand" "")
6334           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
6335   "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6336   "ldm%(ia%)\\t%1!, {%3, %4, %5}"
6337   [(set_attr "type" "load3")
6338    (set_attr "predicable" "yes")]
6339 )
6340
6341 (define_insn "*ldmsi_postinc2"
6342   [(match_parallel 0 "load_multiple_operation"
6343     [(set (match_operand:SI 1 "s_register_operand" "=r")
6344           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6345                    (const_int 8)))
6346      (set (match_operand:SI 3 "arm_hard_register_operand" "")
6347           (mem:SI (match_dup 2)))
6348      (set (match_operand:SI 4 "arm_hard_register_operand" "")
6349           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
6350   "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6351   "ldm%(ia%)\\t%1!, {%3, %4}"
6352   [(set_attr "type" "load2")
6353    (set_attr "predicable" "yes")]
6354 )
6355
6356 ;; Ordinary load multiple
6357
6358 (define_insn "*ldmsi4"
6359   [(match_parallel 0 "load_multiple_operation"
6360     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
6361           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
6362      (set (match_operand:SI 3 "arm_hard_register_operand" "")
6363           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
6364      (set (match_operand:SI 4 "arm_hard_register_operand" "")
6365           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
6366      (set (match_operand:SI 5 "arm_hard_register_operand" "")
6367           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
6368   "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6369   "ldm%(ia%)\\t%1, {%2, %3, %4, %5}"
6370   [(set_attr "type" "load4")
6371    (set_attr "predicable" "yes")]
6372 )
6373
6374 (define_insn "*ldmsi3"
6375   [(match_parallel 0 "load_multiple_operation"
6376     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
6377           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
6378      (set (match_operand:SI 3 "arm_hard_register_operand" "")
6379           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
6380      (set (match_operand:SI 4 "arm_hard_register_operand" "")
6381           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
6382   "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6383   "ldm%(ia%)\\t%1, {%2, %3, %4}"
6384   [(set_attr "type" "load3")
6385    (set_attr "predicable" "yes")]
6386 )
6387
6388 (define_insn "*ldmsi2"
6389   [(match_parallel 0 "load_multiple_operation"
6390     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
6391           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
6392      (set (match_operand:SI 3 "arm_hard_register_operand" "")
6393           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
6394   "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
6395   "ldm%(ia%)\\t%1, {%2, %3}"
6396   [(set_attr "type" "load2")
6397    (set_attr "predicable" "yes")]
6398 )
6399
6400 (define_expand "store_multiple"
6401   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6402                           (match_operand:SI 1 "" ""))
6403                      (use (match_operand:SI 2 "" ""))])]
6404   "TARGET_32BIT"
6405 {
6406   HOST_WIDE_INT offset = 0;
6407
6408   /* Support only fixed point registers.  */
6409   if (GET_CODE (operands[2]) != CONST_INT
6410       || INTVAL (operands[2]) > 14
6411       || INTVAL (operands[2]) < 2
6412       || GET_CODE (operands[1]) != REG
6413       || GET_CODE (operands[0]) != MEM
6414       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6415       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
6416     FAIL;
6417
6418   operands[3]
6419     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
6420                               force_reg (SImode, XEXP (operands[0], 0)),
6421                               TRUE, FALSE, operands[0], &offset);
6422 })
6423
6424 ;; Store multiple with write-back
6425
6426 (define_insn "*stmsi_postinc4"
6427   [(match_parallel 0 "store_multiple_operation"
6428     [(set (match_operand:SI 1 "s_register_operand" "=r")
6429           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6430                    (const_int 16)))
6431      (set (mem:SI (match_dup 2))
6432           (match_operand:SI 3 "arm_hard_register_operand" ""))
6433      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6434           (match_operand:SI 4 "arm_hard_register_operand" ""))
6435      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6436           (match_operand:SI 5 "arm_hard_register_operand" ""))
6437      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
6438           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
6439   "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
6440   "stm%(ia%)\\t%1!, {%3, %4, %5, %6}"
6441   [(set_attr "predicable" "yes")
6442    (set_attr "type" "store4")]
6443 )
6444
6445 (define_insn "*stmsi_postinc4_thumb1"
6446   [(match_parallel 0 "store_multiple_operation"
6447     [(set (match_operand:SI 1 "s_register_operand" "=l")
6448           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6449                    (const_int 16)))
6450      (set (mem:SI (match_dup 2))
6451           (match_operand:SI 3 "arm_hard_register_operand" ""))
6452      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6453           (match_operand:SI 4 "arm_hard_register_operand" ""))
6454      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6455           (match_operand:SI 5 "arm_hard_register_operand" ""))
6456      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
6457           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
6458   "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
6459   "stmia\\t%1!, {%3, %4, %5, %6}"
6460   [(set_attr "type" "store4")]
6461 )
6462
6463 (define_insn "*stmsi_postinc3"
6464   [(match_parallel 0 "store_multiple_operation"
6465     [(set (match_operand:SI 1 "s_register_operand" "=r")
6466           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6467                    (const_int 12)))
6468      (set (mem:SI (match_dup 2))
6469           (match_operand:SI 3 "arm_hard_register_operand" ""))
6470      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6471           (match_operand:SI 4 "arm_hard_register_operand" ""))
6472      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6473           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
6474   "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6475   "stm%(ia%)\\t%1!, {%3, %4, %5}"
6476   [(set_attr "predicable" "yes")
6477    (set_attr "type" "store3")]
6478 )
6479
6480 (define_insn "*stmsi_postinc2"
6481   [(match_parallel 0 "store_multiple_operation"
6482     [(set (match_operand:SI 1 "s_register_operand" "=r")
6483           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6484                    (const_int 8)))
6485      (set (mem:SI (match_dup 2))
6486           (match_operand:SI 3 "arm_hard_register_operand" ""))
6487      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6488           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
6489   "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6490   "stm%(ia%)\\t%1!, {%3, %4}"
6491   [(set_attr "predicable" "yes")
6492    (set_attr "type" "store2")]
6493 )
6494
6495 ;; Ordinary store multiple
6496
6497 (define_insn "*stmsi4"
6498   [(match_parallel 0 "store_multiple_operation"
6499     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6500           (match_operand:SI 2 "arm_hard_register_operand" ""))
6501      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6502           (match_operand:SI 3 "arm_hard_register_operand" ""))
6503      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
6504           (match_operand:SI 4 "arm_hard_register_operand" ""))
6505      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
6506           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
6507   "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6508   "stm%(ia%)\\t%1, {%2, %3, %4, %5}"
6509   [(set_attr "predicable" "yes")
6510    (set_attr "type" "store4")]
6511 )
6512
6513 (define_insn "*stmsi3"
6514   [(match_parallel 0 "store_multiple_operation"
6515     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6516           (match_operand:SI 2 "arm_hard_register_operand" ""))
6517      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6518           (match_operand:SI 3 "arm_hard_register_operand" ""))
6519      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
6520           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
6521   "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6522   "stm%(ia%)\\t%1, {%2, %3, %4}"
6523   [(set_attr "predicable" "yes")
6524    (set_attr "type" "store3")]
6525 )
6526
6527 (define_insn "*stmsi2"
6528   [(match_parallel 0 "store_multiple_operation"
6529     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6530           (match_operand:SI 2 "arm_hard_register_operand" ""))
6531      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6532           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
6533   "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
6534   "stm%(ia%)\\t%1, {%2, %3}"
6535   [(set_attr "predicable" "yes")
6536    (set_attr "type" "store2")]
6537 )
6538
6539 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
6540 ;; We could let this apply for blocks of less than this, but it clobbers so
6541 ;; many registers that there is then probably a better way.
6542
6543 (define_expand "movmemqi"
6544   [(match_operand:BLK 0 "general_operand" "")
6545    (match_operand:BLK 1 "general_operand" "")
6546    (match_operand:SI 2 "const_int_operand" "")
6547    (match_operand:SI 3 "const_int_operand" "")]
6548   "TARGET_EITHER"
6549   "
6550   if (TARGET_32BIT)
6551     {
6552       if (arm_gen_movmemqi (operands))
6553         DONE;
6554       FAIL;
6555     }
6556   else /* TARGET_THUMB1 */
6557     {
6558       if (   INTVAL (operands[3]) != 4
6559           || INTVAL (operands[2]) > 48)
6560         FAIL;
6561
6562       thumb_expand_movmemqi (operands);
6563       DONE;
6564     }
6565   "
6566 )
6567
6568 ;; Thumb block-move insns
6569
6570 (define_insn "movmem12b"
6571   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6572         (mem:SI (match_operand:SI 3 "register_operand" "1")))
6573    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6574         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6575    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6576         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
6577    (set (match_operand:SI 0 "register_operand" "=l")
6578         (plus:SI (match_dup 2) (const_int 12)))
6579    (set (match_operand:SI 1 "register_operand" "=l")
6580         (plus:SI (match_dup 3) (const_int 12)))
6581    (clobber (match_scratch:SI 4 "=&l"))
6582    (clobber (match_scratch:SI 5 "=&l"))
6583    (clobber (match_scratch:SI 6 "=&l"))]
6584   "TARGET_THUMB1"
6585   "* return thumb_output_move_mem_multiple (3, operands);"
6586   [(set_attr "length" "4")
6587    ; This isn't entirely accurate...  It loads as well, but in terms of
6588    ; scheduling the following insn it is better to consider it as a store
6589    (set_attr "type" "store3")]
6590 )
6591
6592 (define_insn "movmem8b"
6593   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6594         (mem:SI (match_operand:SI 3 "register_operand" "1")))
6595    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6596         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6597    (set (match_operand:SI 0 "register_operand" "=l")
6598         (plus:SI (match_dup 2) (const_int 8)))
6599    (set (match_operand:SI 1 "register_operand" "=l")
6600         (plus:SI (match_dup 3) (const_int 8)))
6601    (clobber (match_scratch:SI 4 "=&l"))
6602    (clobber (match_scratch:SI 5 "=&l"))]
6603   "TARGET_THUMB1"
6604   "* return thumb_output_move_mem_multiple (2, operands);"
6605   [(set_attr "length" "4")
6606    ; This isn't entirely accurate...  It loads as well, but in terms of
6607    ; scheduling the following insn it is better to consider it as a store
6608    (set_attr "type" "store2")]
6609 )
6610
6611 \f
6612
6613 ;; Compare & branch insns
6614 ;; The range calculations are based as follows:
6615 ;; For forward branches, the address calculation returns the address of
6616 ;; the next instruction.  This is 2 beyond the branch instruction.
6617 ;; For backward branches, the address calculation returns the address of
6618 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
6619 ;; instruction for the shortest sequence, and 4 before the branch instruction
6620 ;; if we have to jump around an unconditional branch.
6621 ;; To the basic branch range the PC offset must be added (this is +4).
6622 ;; So for forward branches we have 
6623 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6624 ;; And for backward branches we have 
6625 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6626 ;;
6627 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6628 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
6629
6630 (define_expand "cbranchsi4"
6631   [(set (pc) (if_then_else
6632               (match_operator 0 "arm_comparison_operator"
6633                [(match_operand:SI 1 "s_register_operand" "")
6634                 (match_operand:SI 2 "nonmemory_operand" "")])
6635               (label_ref (match_operand 3 "" ""))
6636               (pc)))]
6637   "TARGET_THUMB1 || TARGET_32BIT"
6638   "
6639   if (!TARGET_THUMB1)
6640     {
6641       if (!arm_add_operand (operands[2], SImode))
6642         operands[2] = force_reg (SImode, operands[2]);
6643       emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6644                                       operands[3]));
6645       DONE;
6646     }
6647   if (thumb1_cmpneg_operand (operands[2], SImode))
6648     {
6649       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6650                                               operands[3], operands[0]));
6651       DONE;
6652     }
6653   if (!thumb1_cmp_operand (operands[2], SImode))
6654     operands[2] = force_reg (SImode, operands[2]);
6655   ")
6656
6657 ;; A pattern to recognize a special situation and optimize for it.
6658 ;; On the thumb, zero-extension from memory is preferrable to sign-extension
6659 ;; due to the available addressing modes.  Hence, convert a signed comparison
6660 ;; with zero into an unsigned comparison with 127 if possible.
6661 (define_expand "cbranchqi4"
6662   [(set (pc) (if_then_else
6663               (match_operator 0 "lt_ge_comparison_operator"
6664                [(match_operand:QI 1 "memory_operand" "")
6665                 (match_operand:QI 2 "const0_operand" "")])
6666               (label_ref (match_operand 3 "" ""))
6667               (pc)))]
6668   "TARGET_THUMB1"
6669 {
6670   rtx xops[3];
6671   xops[1] = gen_reg_rtx (SImode);
6672   emit_insn (gen_zero_extendqisi2 (xops[1], operands[1]));
6673   xops[2] = GEN_INT (127);
6674   xops[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]) == GE ? LEU : GTU,
6675                             VOIDmode, xops[1], xops[2]);
6676   xops[3] = operands[3];
6677   emit_insn (gen_cbranchsi4 (xops[0], xops[1], xops[2], xops[3]));
6678   DONE;
6679 })
6680
6681 (define_expand "cbranchsf4"
6682   [(set (pc) (if_then_else
6683               (match_operator 0 "arm_comparison_operator"
6684                [(match_operand:SF 1 "s_register_operand" "")
6685                 (match_operand:SF 2 "arm_float_compare_operand" "")])
6686               (label_ref (match_operand 3 "" ""))
6687               (pc)))]
6688   "TARGET_32BIT && TARGET_HARD_FLOAT"
6689   "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6690                                    operands[3])); DONE;"
6691 )
6692
6693 (define_expand "cbranchdf4"
6694   [(set (pc) (if_then_else
6695               (match_operator 0 "arm_comparison_operator"
6696                [(match_operand:DF 1 "s_register_operand" "")
6697                 (match_operand:DF 2 "arm_float_compare_operand" "")])
6698               (label_ref (match_operand 3 "" ""))
6699               (pc)))]
6700   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
6701   "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6702                                    operands[3])); DONE;"
6703 )
6704
6705 ;; this uses the Cirrus DI compare instruction
6706 (define_expand "cbranchdi4"
6707   [(set (pc) (if_then_else
6708               (match_operator 0 "arm_comparison_operator"
6709                [(match_operand:DI 1 "cirrus_fp_register" "")
6710                 (match_operand:DI 2 "cirrus_fp_register" "")])
6711               (label_ref (match_operand 3 "" ""))
6712               (pc)))]
6713   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6714   "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6715                                    operands[3])); DONE;"
6716 )
6717
6718 (define_insn "cbranchsi4_insn"
6719   [(set (pc) (if_then_else
6720               (match_operator 0 "arm_comparison_operator"
6721                [(match_operand:SI 1 "s_register_operand" "l,*h")
6722                 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
6723               (label_ref (match_operand 3 "" ""))
6724               (pc)))]
6725   "TARGET_THUMB1"
6726   "*
6727   rtx t = prev_nonnote_insn (insn);
6728   if (t != NULL_RTX
6729       && INSN_P (t)
6730       && INSN_CODE (t) == CODE_FOR_cbranchsi4_insn)
6731     {
6732       t = XEXP (SET_SRC (PATTERN (t)), 0);
6733       if (!rtx_equal_p (XEXP (t, 0), operands[1])
6734           || !rtx_equal_p (XEXP (t, 1), operands[2]))
6735         t = NULL_RTX;
6736     }
6737   else
6738     t = NULL_RTX;
6739   if (t == NULL_RTX)
6740     output_asm_insn (\"cmp\\t%1, %2\", operands);
6741
6742   switch (get_attr_length (insn))
6743     {
6744     case 4:  return \"b%d0\\t%l3\";
6745     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6746     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6747     }
6748   "
6749   [(set (attr "far_jump")
6750         (if_then_else
6751             (eq_attr "length" "8")
6752             (const_string "yes")
6753             (const_string "no")))
6754    (set (attr "length") 
6755         (if_then_else
6756             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6757                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6758             (const_int 4)
6759             (if_then_else
6760                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6761                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6762                 (const_int 6)
6763                 (const_int 8))))]
6764 )
6765
6766 (define_insn "cbranchsi4_scratch"
6767   [(set (pc) (if_then_else
6768               (match_operator 4 "arm_comparison_operator"
6769                [(match_operand:SI 1 "s_register_operand" "l,0")
6770                 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
6771               (label_ref (match_operand 3 "" ""))
6772               (pc)))
6773    (clobber (match_scratch:SI 0 "=l,l"))]
6774   "TARGET_THUMB1"
6775   "*
6776   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
6777
6778   switch (get_attr_length (insn))
6779     {
6780     case 4:  return \"b%d4\\t%l3\";
6781     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6782     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6783     }
6784   "
6785   [(set (attr "far_jump")
6786         (if_then_else
6787             (eq_attr "length" "8")
6788             (const_string "yes")
6789             (const_string "no")))
6790    (set (attr "length") 
6791         (if_then_else
6792             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6793                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6794             (const_int 4)
6795             (if_then_else
6796                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6797                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6798                 (const_int 6)
6799                 (const_int 8))))]
6800 )
6801
6802 (define_insn "*movsi_cbranchsi4"
6803   [(set (pc)
6804         (if_then_else
6805          (match_operator 3 "arm_comparison_operator"
6806           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
6807            (const_int 0)])
6808          (label_ref (match_operand 2 "" ""))
6809          (pc)))
6810    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
6811         (match_dup 1))]
6812   "TARGET_THUMB1"
6813   "*{
6814   if (which_alternative == 0)
6815     output_asm_insn (\"cmp\t%0, #0\", operands);
6816   else if (which_alternative == 1)
6817     output_asm_insn (\"sub\t%0, %1, #0\", operands);
6818   else
6819     {
6820       output_asm_insn (\"cmp\t%1, #0\", operands);
6821       if (which_alternative == 2)
6822         output_asm_insn (\"mov\t%0, %1\", operands);
6823       else
6824         output_asm_insn (\"str\t%1, %0\", operands);
6825     }
6826   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
6827     {
6828     case 4:  return \"b%d3\\t%l2\";
6829     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6830     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
6831     }
6832   }"
6833   [(set (attr "far_jump")
6834         (if_then_else
6835             (ior (and (gt (symbol_ref ("which_alternative"))
6836                           (const_int 1))
6837                       (eq_attr "length" "8"))
6838                  (eq_attr "length" "10"))
6839             (const_string "yes")
6840             (const_string "no")))
6841    (set (attr "length")
6842      (if_then_else
6843        (le (symbol_ref ("which_alternative"))
6844                        (const_int 1))
6845        (if_then_else
6846          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6847               (le (minus (match_dup 2) (pc)) (const_int 256)))
6848          (const_int 4)
6849          (if_then_else
6850            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6851                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6852            (const_int 6)
6853            (const_int 8)))
6854        (if_then_else
6855          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
6856               (le (minus (match_dup 2) (pc)) (const_int 256)))
6857          (const_int 6)
6858          (if_then_else
6859            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
6860                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6861            (const_int 8)
6862            (const_int 10)))))]
6863 )
6864
6865 (define_peephole2
6866   [(set (match_operand:SI 0 "low_register_operand" "")
6867         (match_operand:SI 1 "low_register_operand" ""))
6868    (set (pc)
6869         (if_then_else (match_operator 2 "arm_comparison_operator"
6870                        [(match_dup 1) (const_int 0)])
6871                       (label_ref (match_operand 3 "" ""))
6872                       (pc)))]
6873   "TARGET_THUMB1"
6874   [(parallel
6875     [(set (pc)
6876         (if_then_else (match_op_dup 2 [(match_dup 1) (const_int 0)])
6877                       (label_ref (match_dup 3))
6878                       (pc)))
6879      (set (match_dup 0) (match_dup 1))])]
6880   ""
6881 )
6882
6883 ;; Sigh!  This variant shouldn't be needed, but combine often fails to
6884 ;; merge cases like this because the op1 is a hard register in
6885 ;; CLASS_LIKELY_SPILLED_P.
6886 (define_peephole2
6887   [(set (match_operand:SI 0 "low_register_operand" "")
6888         (match_operand:SI 1 "low_register_operand" ""))
6889    (set (pc)
6890         (if_then_else (match_operator 2 "arm_comparison_operator"
6891                        [(match_dup 0) (const_int 0)])
6892                       (label_ref (match_operand 3 "" ""))
6893                       (pc)))]
6894   "TARGET_THUMB1"
6895   [(parallel
6896     [(set (pc)
6897         (if_then_else (match_op_dup 2 [(match_dup 1) (const_int 0)])
6898                       (label_ref (match_dup 3))
6899                       (pc)))
6900      (set (match_dup 0) (match_dup 1))])]
6901   ""
6902 )
6903
6904 (define_insn "*negated_cbranchsi4"
6905   [(set (pc)
6906         (if_then_else
6907          (match_operator 0 "equality_operator"
6908           [(match_operand:SI 1 "s_register_operand" "l")
6909            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
6910          (label_ref (match_operand 3 "" ""))
6911          (pc)))]
6912   "TARGET_THUMB1"
6913   "*
6914   output_asm_insn (\"cmn\\t%1, %2\", operands);
6915   switch (get_attr_length (insn))
6916     {
6917     case 4:  return \"b%d0\\t%l3\";
6918     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6919     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6920     }
6921   "
6922   [(set (attr "far_jump")
6923         (if_then_else
6924             (eq_attr "length" "8")
6925             (const_string "yes")
6926             (const_string "no")))
6927    (set (attr "length") 
6928         (if_then_else
6929             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6930                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6931             (const_int 4)
6932             (if_then_else
6933                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6934                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6935                 (const_int 6)
6936                 (const_int 8))))]
6937 )
6938
6939 (define_insn "*tbit_cbranch"
6940   [(set (pc)
6941         (if_then_else
6942          (match_operator 0 "equality_operator"
6943           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6944                             (const_int 1)
6945                             (match_operand:SI 2 "const_int_operand" "i"))
6946            (const_int 0)])
6947          (label_ref (match_operand 3 "" ""))
6948          (pc)))
6949    (clobber (match_scratch:SI 4 "=l"))]
6950   "TARGET_THUMB1"
6951   "*
6952   {
6953   rtx op[3];
6954   op[0] = operands[4];
6955   op[1] = operands[1];
6956   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
6957
6958   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6959   switch (get_attr_length (insn))
6960     {
6961     case 4:  return \"b%d0\\t%l3\";
6962     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6963     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6964     }
6965   }"
6966   [(set (attr "far_jump")
6967         (if_then_else
6968             (eq_attr "length" "8")
6969             (const_string "yes")
6970             (const_string "no")))
6971    (set (attr "length") 
6972         (if_then_else
6973             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6974                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6975             (const_int 4)
6976             (if_then_else
6977                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6978                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6979                 (const_int 6)
6980                 (const_int 8))))]
6981 )
6982   
6983 (define_insn "*tlobits_cbranch"
6984   [(set (pc)
6985         (if_then_else
6986          (match_operator 0 "equality_operator"
6987           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6988                             (match_operand:SI 2 "const_int_operand" "i")
6989                             (const_int 0))
6990            (const_int 0)])
6991          (label_ref (match_operand 3 "" ""))
6992          (pc)))
6993    (clobber (match_scratch:SI 4 "=l"))]
6994   "TARGET_THUMB1"
6995   "*
6996   {
6997   rtx op[3];
6998   op[0] = operands[4];
6999   op[1] = operands[1];
7000   op[2] = GEN_INT (32 - INTVAL (operands[2]));
7001
7002   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
7003   switch (get_attr_length (insn))
7004     {
7005     case 4:  return \"b%d0\\t%l3\";
7006     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7007     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7008     }
7009   }"
7010   [(set (attr "far_jump")
7011         (if_then_else
7012             (eq_attr "length" "8")
7013             (const_string "yes")
7014             (const_string "no")))
7015    (set (attr "length") 
7016         (if_then_else
7017             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7018                  (le (minus (match_dup 3) (pc)) (const_int 256)))
7019             (const_int 4)
7020             (if_then_else
7021                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7022                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
7023                 (const_int 6)
7024                 (const_int 8))))]
7025 )
7026   
7027 (define_insn "*tstsi3_cbranch"
7028   [(set (pc)
7029         (if_then_else
7030          (match_operator 3 "equality_operator"
7031           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
7032                    (match_operand:SI 1 "s_register_operand" "l"))
7033            (const_int 0)])
7034          (label_ref (match_operand 2 "" ""))
7035          (pc)))]
7036   "TARGET_THUMB1"
7037   "*
7038   {
7039   output_asm_insn (\"tst\\t%0, %1\", operands);
7040   switch (get_attr_length (insn))
7041     {
7042     case 4:  return \"b%d3\\t%l2\";
7043     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
7044     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
7045     }
7046   }"
7047   [(set (attr "far_jump")
7048         (if_then_else
7049             (eq_attr "length" "8")
7050             (const_string "yes")
7051             (const_string "no")))
7052    (set (attr "length") 
7053         (if_then_else
7054             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
7055                  (le (minus (match_dup 2) (pc)) (const_int 256)))
7056             (const_int 4)
7057             (if_then_else
7058                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
7059                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
7060                 (const_int 6)
7061                 (const_int 8))))]
7062 )
7063   
7064 (define_insn "*andsi3_cbranch"
7065   [(set (pc)
7066         (if_then_else
7067          (match_operator 5 "equality_operator"
7068           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
7069                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7070            (const_int 0)])
7071          (label_ref (match_operand 4 "" ""))
7072          (pc)))
7073    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
7074         (and:SI (match_dup 2) (match_dup 3)))
7075    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
7076   "TARGET_THUMB1"
7077   "*
7078   {
7079   if (which_alternative == 0)
7080     output_asm_insn (\"and\\t%0, %3\", operands);
7081   else if (which_alternative == 1)
7082     {
7083       output_asm_insn (\"and\\t%1, %3\", operands);
7084       output_asm_insn (\"mov\\t%0, %1\", operands);
7085     }
7086   else
7087     {
7088       output_asm_insn (\"and\\t%1, %3\", operands);
7089       output_asm_insn (\"str\\t%1, %0\", operands);
7090     }
7091
7092   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7093     {
7094     case 4:  return \"b%d5\\t%l4\";
7095     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7096     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7097     }
7098   }"
7099   [(set (attr "far_jump")
7100         (if_then_else
7101             (ior (and (eq (symbol_ref ("which_alternative"))
7102                           (const_int 0))
7103                       (eq_attr "length" "8"))
7104                  (eq_attr "length" "10"))
7105             (const_string "yes")
7106             (const_string "no")))
7107    (set (attr "length")
7108      (if_then_else
7109        (eq (symbol_ref ("which_alternative"))
7110                        (const_int 0))
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)))
7120        (if_then_else
7121          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7122               (le (minus (match_dup 4) (pc)) (const_int 256)))
7123          (const_int 6)
7124          (if_then_else
7125            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7126                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7127            (const_int 8)
7128            (const_int 10)))))]
7129 )
7130
7131 (define_insn "*orrsi3_cbranch_scratch"
7132   [(set (pc)
7133         (if_then_else
7134          (match_operator 4 "equality_operator"
7135           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
7136                    (match_operand:SI 2 "s_register_operand" "l"))
7137            (const_int 0)])
7138          (label_ref (match_operand 3 "" ""))
7139          (pc)))
7140    (clobber (match_scratch:SI 0 "=l"))]
7141   "TARGET_THUMB1"
7142   "*
7143   {
7144   output_asm_insn (\"orr\\t%0, %2\", operands);
7145   switch (get_attr_length (insn))
7146     {
7147     case 4:  return \"b%d4\\t%l3\";
7148     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7149     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7150     }
7151   }"
7152   [(set (attr "far_jump")
7153         (if_then_else
7154             (eq_attr "length" "8")
7155             (const_string "yes")
7156             (const_string "no")))
7157    (set (attr "length") 
7158         (if_then_else
7159             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7160                  (le (minus (match_dup 3) (pc)) (const_int 256)))
7161             (const_int 4)
7162             (if_then_else
7163                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7164                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
7165                 (const_int 6)
7166                 (const_int 8))))]
7167 )
7168   
7169 (define_insn "*orrsi3_cbranch"
7170   [(set (pc)
7171         (if_then_else
7172          (match_operator 5 "equality_operator"
7173           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
7174                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7175            (const_int 0)])
7176          (label_ref (match_operand 4 "" ""))
7177          (pc)))
7178    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
7179         (ior:SI (match_dup 2) (match_dup 3)))
7180    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
7181   "TARGET_THUMB1"
7182   "*
7183   {
7184   if (which_alternative == 0)
7185     output_asm_insn (\"orr\\t%0, %3\", operands);
7186   else if (which_alternative == 1)
7187     {
7188       output_asm_insn (\"orr\\t%1, %3\", operands);
7189       output_asm_insn (\"mov\\t%0, %1\", operands);
7190     }
7191   else
7192     {
7193       output_asm_insn (\"orr\\t%1, %3\", operands);
7194       output_asm_insn (\"str\\t%1, %0\", operands);
7195     }
7196
7197   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7198     {
7199     case 4:  return \"b%d5\\t%l4\";
7200     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7201     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7202     }
7203   }"
7204   [(set (attr "far_jump")
7205         (if_then_else
7206             (ior (and (eq (symbol_ref ("which_alternative"))
7207                           (const_int 0))
7208                       (eq_attr "length" "8"))
7209                  (eq_attr "length" "10"))
7210             (const_string "yes")
7211             (const_string "no")))
7212    (set (attr "length")
7213      (if_then_else
7214        (eq (symbol_ref ("which_alternative"))
7215                        (const_int 0))
7216        (if_then_else
7217          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7218               (le (minus (match_dup 4) (pc)) (const_int 256)))
7219          (const_int 4)
7220          (if_then_else
7221            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7222                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7223            (const_int 6)
7224            (const_int 8)))
7225        (if_then_else
7226          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7227               (le (minus (match_dup 4) (pc)) (const_int 256)))
7228          (const_int 6)
7229          (if_then_else
7230            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7231                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7232            (const_int 8)
7233            (const_int 10)))))]
7234 )
7235
7236 (define_insn "*xorsi3_cbranch_scratch"
7237   [(set (pc)
7238         (if_then_else
7239          (match_operator 4 "equality_operator"
7240           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
7241                    (match_operand:SI 2 "s_register_operand" "l"))
7242            (const_int 0)])
7243          (label_ref (match_operand 3 "" ""))
7244          (pc)))
7245    (clobber (match_scratch:SI 0 "=l"))]
7246   "TARGET_THUMB1"
7247   "*
7248   {
7249   output_asm_insn (\"eor\\t%0, %2\", operands);
7250   switch (get_attr_length (insn))
7251     {
7252     case 4:  return \"b%d4\\t%l3\";
7253     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7254     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7255     }
7256   }"
7257   [(set (attr "far_jump")
7258         (if_then_else
7259             (eq_attr "length" "8")
7260             (const_string "yes")
7261             (const_string "no")))
7262    (set (attr "length") 
7263         (if_then_else
7264             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7265                  (le (minus (match_dup 3) (pc)) (const_int 256)))
7266             (const_int 4)
7267             (if_then_else
7268                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7269                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
7270                 (const_int 6)
7271                 (const_int 8))))]
7272 )
7273   
7274 (define_insn "*xorsi3_cbranch"
7275   [(set (pc)
7276         (if_then_else
7277          (match_operator 5 "equality_operator"
7278           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
7279                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7280            (const_int 0)])
7281          (label_ref (match_operand 4 "" ""))
7282          (pc)))
7283    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
7284         (xor:SI (match_dup 2) (match_dup 3)))
7285    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
7286   "TARGET_THUMB1"
7287   "*
7288   {
7289   if (which_alternative == 0)
7290     output_asm_insn (\"eor\\t%0, %3\", operands);
7291   else if (which_alternative == 1)
7292     {
7293       output_asm_insn (\"eor\\t%1, %3\", operands);
7294       output_asm_insn (\"mov\\t%0, %1\", operands);
7295     }
7296   else
7297     {
7298       output_asm_insn (\"eor\\t%1, %3\", operands);
7299       output_asm_insn (\"str\\t%1, %0\", operands);
7300     }
7301
7302   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7303     {
7304     case 4:  return \"b%d5\\t%l4\";
7305     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7306     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7307     }
7308   }"
7309   [(set (attr "far_jump")
7310         (if_then_else
7311             (ior (and (eq (symbol_ref ("which_alternative"))
7312                           (const_int 0))
7313                       (eq_attr "length" "8"))
7314                  (eq_attr "length" "10"))
7315             (const_string "yes")
7316             (const_string "no")))
7317    (set (attr "length")
7318      (if_then_else
7319        (eq (symbol_ref ("which_alternative"))
7320                        (const_int 0))
7321        (if_then_else
7322          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7323               (le (minus (match_dup 4) (pc)) (const_int 256)))
7324          (const_int 4)
7325          (if_then_else
7326            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7327                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7328            (const_int 6)
7329            (const_int 8)))
7330        (if_then_else
7331          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7332               (le (minus (match_dup 4) (pc)) (const_int 256)))
7333          (const_int 6)
7334          (if_then_else
7335            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7336                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7337            (const_int 8)
7338            (const_int 10)))))]
7339 )
7340
7341 (define_insn "*bicsi3_cbranch_scratch"
7342   [(set (pc)
7343         (if_then_else
7344          (match_operator 4 "equality_operator"
7345           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
7346                    (match_operand:SI 1 "s_register_operand" "0"))
7347            (const_int 0)])
7348          (label_ref (match_operand 3 "" ""))
7349          (pc)))
7350    (clobber (match_scratch:SI 0 "=l"))]
7351   "TARGET_THUMB1"
7352   "*
7353   {
7354   output_asm_insn (\"bic\\t%0, %2\", operands);
7355   switch (get_attr_length (insn))
7356     {
7357     case 4:  return \"b%d4\\t%l3\";
7358     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7359     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7360     }
7361   }"
7362   [(set (attr "far_jump")
7363         (if_then_else
7364             (eq_attr "length" "8")
7365             (const_string "yes")
7366             (const_string "no")))
7367    (set (attr "length") 
7368         (if_then_else
7369             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7370                  (le (minus (match_dup 3) (pc)) (const_int 256)))
7371             (const_int 4)
7372             (if_then_else
7373                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7374                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
7375                 (const_int 6)
7376                 (const_int 8))))]
7377 )
7378   
7379 (define_insn "*bicsi3_cbranch"
7380   [(set (pc)
7381         (if_then_else
7382          (match_operator 5 "equality_operator"
7383           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
7384                    (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
7385            (const_int 0)])
7386          (label_ref (match_operand 4 "" ""))
7387          (pc)))
7388    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
7389         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
7390    (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
7391   "TARGET_THUMB1"
7392   "*
7393   {
7394   if (which_alternative == 0)
7395     output_asm_insn (\"bic\\t%0, %3\", operands);
7396   else if (which_alternative <= 2)
7397     {
7398       output_asm_insn (\"bic\\t%1, %3\", operands);
7399       /* It's ok if OP0 is a lo-reg, even though the mov will set the
7400          conditions again, since we're only testing for equality.  */
7401       output_asm_insn (\"mov\\t%0, %1\", operands);
7402     }
7403   else
7404     {
7405       output_asm_insn (\"bic\\t%1, %3\", operands);
7406       output_asm_insn (\"str\\t%1, %0\", operands);
7407     }
7408
7409   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7410     {
7411     case 4:  return \"b%d5\\t%l4\";
7412     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7413     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7414     }
7415   }"
7416   [(set (attr "far_jump")
7417         (if_then_else
7418             (ior (and (eq (symbol_ref ("which_alternative"))
7419                           (const_int 0))
7420                       (eq_attr "length" "8"))
7421                  (eq_attr "length" "10"))
7422             (const_string "yes")
7423             (const_string "no")))
7424    (set (attr "length")
7425      (if_then_else
7426        (eq (symbol_ref ("which_alternative"))
7427                        (const_int 0))
7428        (if_then_else
7429          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7430               (le (minus (match_dup 4) (pc)) (const_int 256)))
7431          (const_int 4)
7432          (if_then_else
7433            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7434                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7435            (const_int 6)
7436            (const_int 8)))
7437        (if_then_else
7438          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7439               (le (minus (match_dup 4) (pc)) (const_int 256)))
7440          (const_int 6)
7441          (if_then_else
7442            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7443                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7444            (const_int 8)
7445            (const_int 10)))))]
7446 )
7447
7448 (define_insn "*cbranchne_decr1"
7449   [(set (pc)
7450         (if_then_else (match_operator 3 "equality_operator"
7451                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
7452                         (const_int 0)])
7453                       (label_ref (match_operand 4 "" ""))
7454                       (pc)))
7455    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
7456         (plus:SI (match_dup 2) (const_int -1)))
7457    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
7458   "TARGET_THUMB1"
7459   "*
7460    {
7461      rtx cond[2];
7462      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
7463                                 ? GEU : LTU),
7464                                VOIDmode, operands[2], const1_rtx);
7465      cond[1] = operands[4];
7466
7467      if (which_alternative == 0)
7468        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
7469      else if (which_alternative == 1)
7470        {
7471          /* We must provide an alternative for a hi reg because reload 
7472             cannot handle output reloads on a jump instruction, but we
7473             can't subtract into that.  Fortunately a mov from lo to hi
7474             does not clobber the condition codes.  */
7475          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7476          output_asm_insn (\"mov\\t%0, %1\", operands);
7477        }
7478      else
7479        {
7480          /* Similarly, but the target is memory.  */
7481          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7482          output_asm_insn (\"str\\t%1, %0\", operands);
7483        }
7484
7485      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7486        {
7487          case 4:
7488            output_asm_insn (\"b%d0\\t%l1\", cond);
7489            return \"\";
7490          case 6:
7491            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
7492            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
7493          default:
7494            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
7495            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7496        }
7497    }
7498   "
7499   [(set (attr "far_jump")
7500         (if_then_else
7501             (ior (and (eq (symbol_ref ("which_alternative"))
7502                           (const_int 0))
7503                       (eq_attr "length" "8"))
7504                  (eq_attr "length" "10"))
7505             (const_string "yes")
7506             (const_string "no")))
7507    (set_attr_alternative "length"
7508       [
7509        ;; Alternative 0
7510        (if_then_else
7511          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7512               (le (minus (match_dup 4) (pc)) (const_int 256)))
7513          (const_int 4)
7514          (if_then_else
7515            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7516                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7517            (const_int 6)
7518            (const_int 8)))
7519        ;; Alternative 1
7520        (if_then_else
7521          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7522               (le (minus (match_dup 4) (pc)) (const_int 256)))
7523          (const_int 6)
7524          (if_then_else
7525            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7526                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7527            (const_int 8)
7528            (const_int 10)))
7529        ;; Alternative 2
7530        (if_then_else
7531          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7532               (le (minus (match_dup 4) (pc)) (const_int 256)))
7533          (const_int 6)
7534          (if_then_else
7535            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7536                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7537            (const_int 8)
7538            (const_int 10)))
7539        ;; Alternative 3
7540        (if_then_else
7541          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7542               (le (minus (match_dup 4) (pc)) (const_int 256)))
7543          (const_int 6)
7544          (if_then_else
7545            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7546                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7547            (const_int 8)
7548            (const_int 10)))])]
7549 )
7550
7551 (define_insn "*addsi3_cbranch"
7552   [(set (pc)
7553         (if_then_else
7554          (match_operator 4 "arm_comparison_operator"
7555           [(plus:SI
7556             (match_operand:SI 2 "s_register_operand" "%l,0,*l,1,1,1")
7557             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*l,lIJ,lIJ,lIJ"))
7558            (const_int 0)])
7559          (label_ref (match_operand 5 "" ""))
7560          (pc)))
7561    (set
7562     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
7563     (plus:SI (match_dup 2) (match_dup 3)))
7564    (clobber (match_scratch:SI 1 "=X,X,l,l,&l,&l"))]
7565   "TARGET_THUMB1
7566    && (GET_CODE (operands[4]) == EQ
7567        || GET_CODE (operands[4]) == NE
7568        || GET_CODE (operands[4]) == GE
7569        || GET_CODE (operands[4]) == LT)"
7570   "*
7571    {
7572      rtx cond[3];
7573
7574      cond[0] = (which_alternative < 2) ? operands[0] : operands[1];
7575      cond[1] = operands[2];
7576      cond[2] = operands[3];
7577
7578      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
7579        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
7580      else
7581        output_asm_insn (\"add\\t%0, %1, %2\", cond);
7582
7583      if (which_alternative >= 2
7584          && which_alternative < 4)
7585        output_asm_insn (\"mov\\t%0, %1\", operands);
7586      else if (which_alternative >= 4)
7587        output_asm_insn (\"str\\t%1, %0\", operands);
7588
7589      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
7590        {
7591          case 4:
7592            return \"b%d4\\t%l5\";
7593          case 6:
7594            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7595          default:
7596            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7597        }
7598    }
7599   "
7600   [(set (attr "far_jump")
7601         (if_then_else
7602             (ior (and (lt (symbol_ref ("which_alternative"))
7603                           (const_int 3))
7604                       (eq_attr "length" "8"))
7605                  (eq_attr "length" "10"))
7606             (const_string "yes")
7607             (const_string "no")))
7608    (set (attr "length")
7609      (if_then_else
7610        (lt (symbol_ref ("which_alternative"))
7611                        (const_int 3))
7612        (if_then_else
7613          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7614               (le (minus (match_dup 5) (pc)) (const_int 256)))
7615          (const_int 4)
7616          (if_then_else
7617            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7618                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7619            (const_int 6)
7620            (const_int 8)))
7621        (if_then_else
7622          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7623               (le (minus (match_dup 5) (pc)) (const_int 256)))
7624          (const_int 6)
7625          (if_then_else
7626            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7627                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7628            (const_int 8)
7629            (const_int 10)))))]
7630 )
7631
7632 (define_insn "*addsi3_cbranch_scratch"
7633   [(set (pc)
7634         (if_then_else
7635          (match_operator 3 "arm_comparison_operator"
7636           [(plus:SI
7637             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
7638             (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
7639            (const_int 0)])
7640          (label_ref (match_operand 4 "" ""))
7641          (pc)))
7642    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
7643   "TARGET_THUMB1
7644    && (GET_CODE (operands[3]) == EQ
7645        || GET_CODE (operands[3]) == NE
7646        || GET_CODE (operands[3]) == GE
7647        || GET_CODE (operands[3]) == LT)"
7648   "*
7649    {
7650      switch (which_alternative)
7651        {
7652        case 0:
7653          output_asm_insn (\"cmp\t%1, #%n2\", operands);
7654          break;
7655        case 1:
7656          output_asm_insn (\"cmn\t%1, %2\", operands);
7657          break;
7658        case 2:
7659          if (INTVAL (operands[2]) < 0)
7660            output_asm_insn (\"sub\t%0, %1, %2\", operands);
7661          else
7662            output_asm_insn (\"add\t%0, %1, %2\", operands);
7663          break;
7664        case 3:
7665          if (INTVAL (operands[2]) < 0)
7666            output_asm_insn (\"sub\t%0, %0, %2\", operands);
7667          else
7668            output_asm_insn (\"add\t%0, %0, %2\", operands);
7669          break;
7670        }
7671
7672      switch (get_attr_length (insn))
7673        {
7674          case 4:
7675            return \"b%d3\\t%l4\";
7676          case 6:
7677            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7678          default:
7679            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7680        }
7681    }
7682   "
7683   [(set (attr "far_jump")
7684         (if_then_else
7685             (eq_attr "length" "8")
7686             (const_string "yes")
7687             (const_string "no")))
7688    (set (attr "length")
7689        (if_then_else
7690          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7691               (le (minus (match_dup 4) (pc)) (const_int 256)))
7692          (const_int 4)
7693          (if_then_else
7694            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7695                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7696            (const_int 6)
7697            (const_int 8))))]
7698 )
7699
7700 (define_insn "*subsi3_cbranch"
7701   [(set (pc)
7702         (if_then_else
7703          (match_operator 4 "arm_comparison_operator"
7704           [(minus:SI
7705             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
7706             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7707            (const_int 0)])
7708          (label_ref (match_operand 5 "" ""))
7709          (pc)))
7710    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
7711         (minus:SI (match_dup 2) (match_dup 3)))
7712    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
7713   "TARGET_THUMB1
7714    && (GET_CODE (operands[4]) == EQ
7715        || GET_CODE (operands[4]) == NE
7716        || GET_CODE (operands[4]) == GE
7717        || GET_CODE (operands[4]) == LT)"
7718   "*
7719    {
7720      if (which_alternative == 0)
7721        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
7722      else if (which_alternative == 1)
7723        {
7724          /* We must provide an alternative for a hi reg because reload 
7725             cannot handle output reloads on a jump instruction, but we
7726             can't subtract into that.  Fortunately a mov from lo to hi
7727             does not clobber the condition codes.  */
7728          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
7729          output_asm_insn (\"mov\\t%0, %1\", operands);
7730        }
7731      else
7732        {
7733          /* Similarly, but the target is memory.  */
7734          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
7735          output_asm_insn (\"str\\t%1, %0\", operands);
7736        }
7737
7738      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
7739        {
7740          case 4:
7741            return \"b%d4\\t%l5\";
7742          case 6:
7743            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7744          default:
7745            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7746        }
7747    }
7748   "
7749   [(set (attr "far_jump")
7750         (if_then_else
7751             (ior (and (eq (symbol_ref ("which_alternative"))
7752                           (const_int 0))
7753                       (eq_attr "length" "8"))
7754                  (eq_attr "length" "10"))
7755             (const_string "yes")
7756             (const_string "no")))
7757    (set (attr "length")
7758      (if_then_else
7759        (eq (symbol_ref ("which_alternative"))
7760                        (const_int 0))
7761        (if_then_else
7762          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7763               (le (minus (match_dup 5) (pc)) (const_int 256)))
7764          (const_int 4)
7765          (if_then_else
7766            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7767                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7768            (const_int 6)
7769            (const_int 8)))
7770        (if_then_else
7771          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7772               (le (minus (match_dup 5) (pc)) (const_int 256)))
7773          (const_int 6)
7774          (if_then_else
7775            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7776                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7777            (const_int 8)
7778            (const_int 10)))))]
7779 )
7780
7781 (define_insn "*subsi3_cbranch_scratch"
7782   [(set (pc)
7783         (if_then_else
7784          (match_operator 0 "arm_comparison_operator"
7785           [(minus:SI (match_operand:SI 1 "register_operand" "l")
7786                      (match_operand:SI 2 "nonmemory_operand" "l"))
7787            (const_int 0)])
7788          (label_ref (match_operand 3 "" ""))
7789          (pc)))]
7790   "TARGET_THUMB1
7791    && (GET_CODE (operands[0]) == EQ
7792        || GET_CODE (operands[0]) == NE
7793        || GET_CODE (operands[0]) == GE
7794        || GET_CODE (operands[0]) == LT)"
7795   "*
7796   output_asm_insn (\"cmp\\t%1, %2\", operands);
7797   switch (get_attr_length (insn))
7798     {
7799     case 4:  return \"b%d0\\t%l3\";
7800     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7801     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7802     }
7803   "
7804   [(set (attr "far_jump")
7805         (if_then_else
7806             (eq_attr "length" "8")
7807             (const_string "yes")
7808             (const_string "no")))
7809    (set (attr "length") 
7810         (if_then_else
7811             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7812                  (le (minus (match_dup 3) (pc)) (const_int 256)))
7813             (const_int 4)
7814             (if_then_else
7815                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7816                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
7817                 (const_int 6)
7818                 (const_int 8))))]
7819 )
7820
7821 ;; Comparison and test insns
7822
7823 (define_insn "*arm_cmpsi_insn"
7824   [(set (reg:CC CC_REGNUM)
7825         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
7826                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
7827   "TARGET_32BIT"
7828   "@
7829    cmp%?\\t%0, %1
7830    cmn%?\\t%0, #%n1"
7831   [(set_attr "conds" "set")]
7832 )
7833
7834 (define_insn "*arm_cmpsi_shiftsi"
7835   [(set (reg:CC CC_REGNUM)
7836         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
7837                     (match_operator:SI  3 "shift_operator"
7838                      [(match_operand:SI 1 "s_register_operand" "r")
7839                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
7840   "TARGET_ARM"
7841   "cmp%?\\t%0, %1%S3"
7842   [(set_attr "conds" "set")
7843    (set_attr "shift" "1")
7844    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
7845                       (const_string "alu_shift")
7846                       (const_string "alu_shift_reg")))]
7847 )
7848
7849 (define_insn "*arm_cmpsi_shiftsi_swp"
7850   [(set (reg:CC_SWP CC_REGNUM)
7851         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
7852                          [(match_operand:SI 1 "s_register_operand" "r")
7853                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
7854                         (match_operand:SI 0 "s_register_operand" "r")))]
7855   "TARGET_ARM"
7856   "cmp%?\\t%0, %1%S3"
7857   [(set_attr "conds" "set")
7858    (set_attr "shift" "1")
7859    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
7860                       (const_string "alu_shift")
7861                       (const_string "alu_shift_reg")))]
7862 )
7863
7864 (define_insn "*arm_cmpsi_negshiftsi_si"
7865   [(set (reg:CC_Z CC_REGNUM)
7866         (compare:CC_Z
7867          (neg:SI (match_operator:SI 1 "shift_operator"
7868                     [(match_operand:SI 2 "s_register_operand" "r")
7869                      (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7870          (match_operand:SI 0 "s_register_operand" "r")))]
7871   "TARGET_ARM"
7872   "cmn%?\\t%0, %2%S1"
7873   [(set_attr "conds" "set")
7874    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7875                                     (const_string "alu_shift")
7876                                     (const_string "alu_shift_reg")))]
7877 )
7878
7879 ;; Cirrus SF compare instruction
7880 (define_insn "*cirrus_cmpsf"
7881   [(set (reg:CCFP CC_REGNUM)
7882         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
7883                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
7884   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7885   "cfcmps%?\\tr15, %V0, %V1"
7886   [(set_attr "type"   "mav_farith")
7887    (set_attr "cirrus" "compare")]
7888 )
7889
7890 ;; Cirrus DF compare instruction
7891 (define_insn "*cirrus_cmpdf"
7892   [(set (reg:CCFP CC_REGNUM)
7893         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
7894                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
7895   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7896   "cfcmpd%?\\tr15, %V0, %V1"
7897   [(set_attr "type"   "mav_farith")
7898    (set_attr "cirrus" "compare")]
7899 )
7900
7901 (define_insn "*cirrus_cmpdi"
7902   [(set (reg:CC CC_REGNUM)
7903         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
7904                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
7905   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7906   "cfcmp64%?\\tr15, %V0, %V1"
7907   [(set_attr "type"   "mav_farith")
7908    (set_attr "cirrus" "compare")]
7909 )
7910
7911 ; This insn allows redundant compares to be removed by cse, nothing should
7912 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7913 ; is deleted later on. The match_dup will match the mode here, so that
7914 ; mode changes of the condition codes aren't lost by this even though we don't
7915 ; specify what they are.
7916
7917 (define_insn "*deleted_compare"
7918   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
7919   "TARGET_32BIT"
7920   "\\t%@ deleted compare"
7921   [(set_attr "conds" "set")
7922    (set_attr "length" "0")]
7923 )
7924
7925 \f
7926 ;; Conditional branch insns
7927
7928 (define_expand "cbranch_cc"
7929   [(set (pc)
7930         (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7931                                             (match_operand 2 "" "")])
7932                       (label_ref (match_operand 3 "" ""))
7933                       (pc)))]
7934   "TARGET_32BIT"
7935   "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
7936                                       operands[1], operands[2]);
7937    operands[2] = const0_rtx;"
7938 )
7939
7940 ;;
7941 ;; Patterns to match conditional branch insns.
7942 ;;
7943
7944 (define_insn "*arm_cond_branch"
7945   [(set (pc)
7946         (if_then_else (match_operator 1 "arm_comparison_operator"
7947                        [(match_operand 2 "cc_register" "") (const_int 0)])
7948                       (label_ref (match_operand 0 "" ""))
7949                       (pc)))]
7950   "TARGET_32BIT"
7951   "*
7952   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7953     {
7954       arm_ccfsm_state += 2;
7955       return \"\";
7956     }
7957   return \"b%d1\\t%l0\";
7958   "
7959   [(set_attr "conds" "use")
7960    (set_attr "type" "branch")]
7961 )
7962
7963 (define_insn "*arm_cond_branch_reversed"
7964   [(set (pc)
7965         (if_then_else (match_operator 1 "arm_comparison_operator"
7966                        [(match_operand 2 "cc_register" "") (const_int 0)])
7967                       (pc)
7968                       (label_ref (match_operand 0 "" ""))))]
7969   "TARGET_32BIT"
7970   "*
7971   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7972     {
7973       arm_ccfsm_state += 2;
7974       return \"\";
7975     }
7976   return \"b%D1\\t%l0\";
7977   "
7978   [(set_attr "conds" "use")
7979    (set_attr "type" "branch")]
7980 )
7981
7982 \f
7983
7984 ; scc insns
7985
7986 (define_expand "cstore_cc"
7987   [(set (match_operand:SI 0 "s_register_operand" "")
7988         (match_operator:SI 1 "" [(match_operand 2 "" "")
7989                                  (match_operand 3 "" "")]))]
7990   "TARGET_32BIT"
7991   "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
7992                                       operands[2], operands[3]);
7993    operands[3] = const0_rtx;"
7994 )
7995
7996 (define_insn "*mov_scc"
7997   [(set (match_operand:SI 0 "s_register_operand" "=r")
7998         (match_operator:SI 1 "arm_comparison_operator"
7999          [(match_operand 2 "cc_register" "") (const_int 0)]))]
8000   "TARGET_ARM"
8001   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
8002   [(set_attr "conds" "use")
8003    (set_attr "length" "8")]
8004 )
8005
8006 (define_insn "*mov_negscc"
8007   [(set (match_operand:SI 0 "s_register_operand" "=r")
8008         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8009                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
8010   "TARGET_ARM"
8011   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
8012   [(set_attr "conds" "use")
8013    (set_attr "length" "8")]
8014 )
8015
8016 (define_insn "*mov_notscc"
8017   [(set (match_operand:SI 0 "s_register_operand" "=r")
8018         (not:SI (match_operator:SI 1 "arm_comparison_operator"
8019                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
8020   "TARGET_ARM"
8021   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
8022   [(set_attr "conds" "use")
8023    (set_attr "length" "8")]
8024 )
8025
8026 (define_expand "cstoresi4"
8027   [(set (match_operand:SI 0 "s_register_operand" "")
8028         (match_operator:SI 1 "arm_comparison_operator"
8029          [(match_operand:SI 2 "s_register_operand" "")
8030           (match_operand:SI 3 "reg_or_int_operand" "")]))]
8031   "TARGET_32BIT || TARGET_THUMB1"
8032   "{
8033   rtx op3, scratch, scratch2;
8034
8035   if (!TARGET_THUMB1)
8036     {
8037       if (!arm_add_operand (operands[3], SImode))
8038         operands[3] = force_reg (SImode, operands[3]);
8039       emit_insn (gen_cstore_cc (operands[0], operands[1],
8040                                 operands[2], operands[3]));
8041       DONE;
8042     }
8043
8044   if (operands[3] == const0_rtx)
8045     {
8046       switch (GET_CODE (operands[1]))
8047         {
8048         case EQ:
8049           emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
8050           break;
8051
8052         case NE:
8053           emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
8054           break;
8055
8056         case LE:
8057           scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
8058                                   NULL_RTX, 0, OPTAB_WIDEN);
8059           scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
8060                                   NULL_RTX, 0, OPTAB_WIDEN);
8061           expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
8062                         operands[0], 1, OPTAB_WIDEN);
8063           break;
8064
8065         case GE:
8066           scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
8067                                  NULL_RTX, 1);
8068           expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
8069                         NULL_RTX, 1, OPTAB_WIDEN);
8070           break;
8071
8072         case GT:
8073           scratch = expand_binop (SImode, ashr_optab, operands[2],
8074                                   GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
8075           scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
8076                                   NULL_RTX, 0, OPTAB_WIDEN);
8077           expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
8078                         0, OPTAB_WIDEN);
8079           break;
8080
8081         /* LT is handled by generic code.  No need for unsigned with 0.  */
8082         default:
8083           FAIL;
8084         }
8085       DONE;
8086     }
8087
8088   switch (GET_CODE (operands[1]))
8089     {
8090     case EQ:
8091       scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
8092                               NULL_RTX, 0, OPTAB_WIDEN);
8093       emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
8094       break;
8095
8096     case NE:
8097       scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
8098                               NULL_RTX, 0, OPTAB_WIDEN);
8099       emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
8100       break;
8101
8102     case LE:
8103       op3 = force_reg (SImode, operands[3]);
8104
8105       scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
8106                               NULL_RTX, 1, OPTAB_WIDEN);
8107       scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
8108                               NULL_RTX, 0, OPTAB_WIDEN);
8109       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
8110                                           op3, operands[2]));
8111       break;
8112
8113     case GE:
8114       op3 = operands[3];
8115       if (!thumb1_cmp_operand (op3, SImode))
8116         op3 = force_reg (SImode, op3);
8117       scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
8118                               NULL_RTX, 0, OPTAB_WIDEN);
8119       scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
8120                                NULL_RTX, 1, OPTAB_WIDEN);
8121       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
8122                                           operands[2], op3));
8123       break;
8124
8125     case LEU:
8126       op3 = force_reg (SImode, operands[3]);
8127       scratch = force_reg (SImode, const0_rtx);
8128       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
8129                                           op3, operands[2]));
8130       break;
8131
8132     case GEU:
8133       op3 = operands[3];
8134       if (!thumb1_cmp_operand (op3, SImode))
8135         op3 = force_reg (SImode, op3);
8136       scratch = force_reg (SImode, const0_rtx);
8137       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
8138                                           operands[2], op3));
8139       break;
8140
8141     case LTU:
8142       op3 = operands[3];
8143       if (!thumb1_cmp_operand (op3, SImode))
8144         op3 = force_reg (SImode, op3);
8145       scratch = gen_reg_rtx (SImode);
8146       emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
8147       break;
8148
8149     case GTU:
8150       op3 = force_reg (SImode, operands[3]);
8151       scratch = gen_reg_rtx (SImode);
8152       emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
8153       break;
8154
8155     /* No good sequences for GT, LT.  */
8156     default:
8157       FAIL;
8158     }
8159   DONE;
8160 }")
8161
8162 (define_expand "cstoresf4"
8163   [(set (match_operand:SI 0 "s_register_operand" "")
8164         (match_operator:SI 1 "arm_comparison_operator"
8165          [(match_operand:SF 2 "s_register_operand" "")
8166           (match_operand:SF 3 "arm_float_compare_operand" "")]))]
8167   "TARGET_32BIT && TARGET_HARD_FLOAT"
8168   "emit_insn (gen_cstore_cc (operands[0], operands[1],
8169                              operands[2], operands[3])); DONE;"
8170 )
8171
8172 (define_expand "cstoredf4"
8173   [(set (match_operand:SI 0 "s_register_operand" "")
8174         (match_operator:SI 1 "arm_comparison_operator"
8175          [(match_operand:DF 2 "s_register_operand" "")
8176           (match_operand:DF 3 "arm_float_compare_operand" "")]))]
8177   "TARGET_32BIT && TARGET_HARD_FLOAT"
8178   "emit_insn (gen_cstore_cc (operands[0], operands[1],
8179                              operands[2], operands[3])); DONE;"
8180 )
8181
8182 ;; this uses the Cirrus DI compare instruction
8183 (define_expand "cstoredi4"
8184   [(set (match_operand:SI 0 "s_register_operand" "")
8185         (match_operator:SI 1 "arm_comparison_operator"
8186          [(match_operand:DI 2 "cirrus_fp_register" "")
8187           (match_operand:DI 3 "cirrus_fp_register" "")]))]
8188   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
8189   "emit_insn (gen_cstore_cc (operands[0], operands[1],
8190                              operands[2], operands[3])); DONE;"
8191 )
8192
8193
8194 (define_expand "cstoresi_eq0_thumb1"
8195   [(parallel
8196     [(set (match_operand:SI 0 "s_register_operand" "")
8197           (eq:SI (match_operand:SI 1 "s_register_operand" "")
8198                  (const_int 0)))
8199      (clobber (match_dup:SI 2))])]
8200   "TARGET_THUMB1"
8201   "operands[2] = gen_reg_rtx (SImode);"
8202 )
8203
8204 (define_expand "cstoresi_ne0_thumb1"
8205   [(parallel
8206     [(set (match_operand:SI 0 "s_register_operand" "")
8207           (ne:SI (match_operand:SI 1 "s_register_operand" "")
8208                  (const_int 0)))
8209      (clobber (match_dup:SI 2))])]
8210   "TARGET_THUMB1"
8211   "operands[2] = gen_reg_rtx (SImode);"
8212 )
8213
8214 (define_insn "*cstoresi_eq0_thumb1_insn"
8215   [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
8216         (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
8217                (const_int 0)))
8218    (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
8219   "TARGET_THUMB1"
8220   "@
8221    neg\\t%0, %1\;adc\\t%0, %0, %1
8222    neg\\t%2, %1\;adc\\t%0, %1, %2"
8223   [(set_attr "length" "4")]
8224 )
8225
8226 (define_insn "*cstoresi_ne0_thumb1_insn"
8227   [(set (match_operand:SI 0 "s_register_operand" "=l")
8228         (ne:SI (match_operand:SI 1 "s_register_operand" "0")
8229                (const_int 0)))
8230    (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
8231   "TARGET_THUMB1"
8232   "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
8233   [(set_attr "length" "4")]
8234 )
8235
8236 ;; Used as part of the expansion of thumb ltu and gtu sequences
8237 (define_insn "cstoresi_nltu_thumb1"
8238   [(set (match_operand:SI 0 "s_register_operand" "=l,l")
8239         (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
8240                         (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
8241   "TARGET_THUMB1"
8242   "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
8243   [(set_attr "length" "4")]
8244 )
8245
8246 (define_insn_and_split "cstoresi_ltu_thumb1"
8247   [(set (match_operand:SI 0 "s_register_operand" "=l,l")
8248         (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
8249                 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")))]
8250   "TARGET_THUMB1"
8251   "#"
8252   "TARGET_THUMB1"
8253   [(set (match_dup 3)
8254         (neg:SI (ltu:SI (match_dup 1) (match_dup 2))))
8255    (set (match_dup 0) (neg:SI (match_dup 3)))]
8256   "operands[3] = gen_reg_rtx (SImode);"
8257   [(set_attr "length" "4")]
8258 )
8259
8260 ;; Used as part of the expansion of thumb les sequence.
8261 (define_insn "thumb1_addsi3_addgeu"
8262   [(set (match_operand:SI 0 "s_register_operand" "=l")
8263         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8264                           (match_operand:SI 2 "s_register_operand" "l"))
8265                  (geu:SI (match_operand:SI 3 "s_register_operand" "l")
8266                          (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
8267   "TARGET_THUMB1"
8268   "cmp\\t%3, %4\;adc\\t%0, %1, %2"
8269   [(set_attr "length" "4")]
8270 )
8271
8272 \f
8273 ;; Conditional move insns
8274
8275 (define_expand "movsicc"
8276   [(set (match_operand:SI 0 "s_register_operand" "")
8277         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
8278                          (match_operand:SI 2 "arm_not_operand" "")
8279                          (match_operand:SI 3 "arm_not_operand" "")))]
8280   "TARGET_32BIT"
8281   "
8282   {
8283     enum rtx_code code = GET_CODE (operands[1]);
8284     rtx ccreg;
8285
8286     if (code == UNEQ || code == LTGT)
8287       FAIL;
8288
8289     ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8290                                  XEXP (operands[1], 1));
8291     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
8292   }"
8293 )
8294
8295 (define_expand "movsfcc"
8296   [(set (match_operand:SF 0 "s_register_operand" "")
8297         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
8298                          (match_operand:SF 2 "s_register_operand" "")
8299                          (match_operand:SF 3 "nonmemory_operand" "")))]
8300   "TARGET_32BIT && TARGET_HARD_FLOAT"
8301   "
8302   {
8303     enum rtx_code code = GET_CODE (operands[1]);
8304     rtx ccreg;
8305
8306     if (code == UNEQ || code == LTGT)
8307       FAIL;
8308
8309     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
8310        Otherwise, ensure it is a valid FP add operand */
8311     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
8312         || (!arm_float_add_operand (operands[3], SFmode)))
8313       operands[3] = force_reg (SFmode, operands[3]);
8314
8315     ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8316                                  XEXP (operands[1], 1));
8317     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
8318   }"
8319 )
8320
8321 (define_expand "movdfcc"
8322   [(set (match_operand:DF 0 "s_register_operand" "")
8323         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
8324                          (match_operand:DF 2 "s_register_operand" "")
8325                          (match_operand:DF 3 "arm_float_add_operand" "")))]
8326   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
8327   "
8328   {
8329     enum rtx_code code = GET_CODE (operands[1]);
8330     rtx ccreg;
8331
8332     if (code == UNEQ || code == LTGT)
8333       FAIL;
8334
8335     ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8336                                  XEXP (operands[1], 1));
8337     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
8338   }"
8339 )
8340
8341 (define_insn "*movsicc_insn"
8342   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8343         (if_then_else:SI
8344          (match_operator 3 "arm_comparison_operator"
8345           [(match_operand 4 "cc_register" "") (const_int 0)])
8346          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
8347          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
8348   "TARGET_ARM"
8349   "@
8350    mov%D3\\t%0, %2
8351    mvn%D3\\t%0, #%B2
8352    mov%d3\\t%0, %1
8353    mvn%d3\\t%0, #%B1
8354    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
8355    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
8356    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
8357    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
8358   [(set_attr "length" "4,4,4,4,8,8,8,8")
8359    (set_attr "conds" "use")]
8360 )
8361
8362 (define_insn "*movsfcc_soft_insn"
8363   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8364         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8365                           [(match_operand 4 "cc_register" "") (const_int 0)])
8366                          (match_operand:SF 1 "s_register_operand" "0,r")
8367                          (match_operand:SF 2 "s_register_operand" "r,0")))]
8368   "TARGET_ARM && TARGET_SOFT_FLOAT"
8369   "@
8370    mov%D3\\t%0, %2
8371    mov%d3\\t%0, %1"
8372   [(set_attr "conds" "use")]
8373 )
8374
8375 \f
8376 ;; Jump and linkage insns
8377
8378 (define_expand "jump"
8379   [(set (pc)
8380         (label_ref (match_operand 0 "" "")))]
8381   "TARGET_EITHER"
8382   ""
8383 )
8384
8385 (define_insn "*arm_jump"
8386   [(set (pc)
8387         (label_ref (match_operand 0 "" "")))]
8388   "TARGET_32BIT"
8389   "*
8390   {
8391     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
8392       {
8393         arm_ccfsm_state += 2;
8394         return \"\";
8395       }
8396     return \"b%?\\t%l0\";
8397   }
8398   "
8399   [(set_attr "predicable" "yes")]
8400 )
8401
8402 (define_insn "*thumb_jump"
8403   [(set (pc)
8404         (label_ref (match_operand 0 "" "")))]
8405   "TARGET_THUMB1"
8406   "*
8407   if (get_attr_length (insn) == 2)
8408     return \"b\\t%l0\";
8409   return \"bl\\t%l0\\t%@ far jump\";
8410   "
8411   [(set (attr "far_jump")
8412         (if_then_else
8413             (eq_attr "length" "4")
8414             (const_string "yes")
8415             (const_string "no")))
8416    (set (attr "length") 
8417         (if_then_else
8418             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8419                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
8420             (const_int 2)
8421             (const_int 4)))]
8422 )
8423
8424 (define_expand "call"
8425   [(parallel [(call (match_operand 0 "memory_operand" "")
8426                     (match_operand 1 "general_operand" ""))
8427               (use (match_operand 2 "" ""))
8428               (clobber (reg:SI LR_REGNUM))])]
8429   "TARGET_EITHER"
8430   "
8431   {
8432     rtx callee, pat;
8433     
8434     /* In an untyped call, we can get NULL for operand 2.  */
8435     if (operands[2] == NULL_RTX)
8436       operands[2] = const0_rtx;
8437       
8438     /* Decide if we should generate indirect calls by loading the
8439        32-bit address of the callee into a register before performing the
8440        branch and link.  */
8441     callee = XEXP (operands[0], 0);
8442     if (GET_CODE (callee) == SYMBOL_REF
8443         ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8444         : !REG_P (callee))
8445       XEXP (operands[0], 0) = force_reg (Pmode, callee);
8446
8447     pat = gen_call_internal (operands[0], operands[1], operands[2]);
8448     arm_emit_call_insn (pat, XEXP (operands[0], 0));
8449     DONE;
8450   }"
8451 )
8452
8453 (define_expand "call_internal"
8454   [(parallel [(call (match_operand 0 "memory_operand" "")
8455                     (match_operand 1 "general_operand" ""))
8456               (use (match_operand 2 "" ""))
8457               (clobber (reg:SI LR_REGNUM))])])
8458
8459 (define_insn "*call_reg_armv5"
8460   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8461          (match_operand 1 "" ""))
8462    (use (match_operand 2 "" ""))
8463    (clobber (reg:SI LR_REGNUM))]
8464   "TARGET_ARM && arm_arch5"
8465   "blx%?\\t%0"
8466   [(set_attr "type" "call")]
8467 )
8468
8469 (define_insn "*call_reg_arm"
8470   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8471          (match_operand 1 "" ""))
8472    (use (match_operand 2 "" ""))
8473    (clobber (reg:SI LR_REGNUM))]
8474   "TARGET_ARM && !arm_arch5"
8475   "*
8476   return output_call (operands);
8477   "
8478   ;; length is worst case, normally it is only two
8479   [(set_attr "length" "12")
8480    (set_attr "type" "call")]
8481 )
8482
8483
8484 ;; Note: not used for armv5+ because the sequence used (ldr pc, ...) is not
8485 ;; considered a function call by the branch predictor of some cores (PR40887).
8486 ;; Falls back to blx rN (*call_reg_armv5).
8487
8488 (define_insn "*call_mem"
8489   [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
8490          (match_operand 1 "" ""))
8491    (use (match_operand 2 "" ""))
8492    (clobber (reg:SI LR_REGNUM))]
8493   "TARGET_ARM && !arm_arch5"
8494   "*
8495   return output_call_mem (operands);
8496   "
8497   [(set_attr "length" "12")
8498    (set_attr "type" "call")]
8499 )
8500
8501 (define_insn "*call_reg_thumb1_v5"
8502   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8503          (match_operand 1 "" ""))
8504    (use (match_operand 2 "" ""))
8505    (clobber (reg:SI LR_REGNUM))]
8506   "TARGET_THUMB1 && arm_arch5"
8507   "blx\\t%0"
8508   [(set_attr "length" "2")
8509    (set_attr "type" "call")]
8510 )
8511
8512 (define_insn "*call_reg_thumb1"
8513   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8514          (match_operand 1 "" ""))
8515    (use (match_operand 2 "" ""))
8516    (clobber (reg:SI LR_REGNUM))]
8517   "TARGET_THUMB1 && !arm_arch5"
8518   "*
8519   {
8520     if (!TARGET_CALLER_INTERWORKING)
8521       return thumb_call_via_reg (operands[0]);
8522     else if (operands[1] == const0_rtx)
8523       return \"bl\\t%__interwork_call_via_%0\";
8524     else if (frame_pointer_needed)
8525       return \"bl\\t%__interwork_r7_call_via_%0\";
8526     else
8527       return \"bl\\t%__interwork_r11_call_via_%0\";
8528   }"
8529   [(set_attr "type" "call")]
8530 )
8531
8532 (define_expand "call_value"
8533   [(parallel [(set (match_operand       0 "" "")
8534                    (call (match_operand 1 "memory_operand" "")
8535                          (match_operand 2 "general_operand" "")))
8536               (use (match_operand 3 "" ""))
8537               (clobber (reg:SI LR_REGNUM))])]
8538   "TARGET_EITHER"
8539   "
8540   {
8541     rtx pat, callee;
8542     
8543     /* In an untyped call, we can get NULL for operand 2.  */
8544     if (operands[3] == 0)
8545       operands[3] = const0_rtx;
8546       
8547     /* Decide if we should generate indirect calls by loading the
8548        32-bit address of the callee into a register before performing the
8549        branch and link.  */
8550     callee = XEXP (operands[1], 0);
8551     if (GET_CODE (callee) == SYMBOL_REF
8552         ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8553         : !REG_P (callee))
8554       XEXP (operands[1], 0) = force_reg (Pmode, callee);
8555
8556     pat = gen_call_value_internal (operands[0], operands[1],
8557                                    operands[2], operands[3]);
8558     arm_emit_call_insn (pat, XEXP (operands[1], 0));
8559     DONE;
8560   }"
8561 )
8562
8563 (define_expand "call_value_internal"
8564   [(parallel [(set (match_operand       0 "" "")
8565                    (call (match_operand 1 "memory_operand" "")
8566                          (match_operand 2 "general_operand" "")))
8567               (use (match_operand 3 "" ""))
8568               (clobber (reg:SI LR_REGNUM))])])
8569
8570 (define_insn "*call_value_reg_armv5"
8571   [(set (match_operand 0 "" "")
8572         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8573               (match_operand 2 "" "")))
8574    (use (match_operand 3 "" ""))
8575    (clobber (reg:SI LR_REGNUM))]
8576   "TARGET_ARM && arm_arch5"
8577   "blx%?\\t%1"
8578   [(set_attr "type" "call")]
8579 )
8580
8581 (define_insn "*call_value_reg_arm"
8582   [(set (match_operand 0 "" "")
8583         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8584               (match_operand 2 "" "")))
8585    (use (match_operand 3 "" ""))
8586    (clobber (reg:SI LR_REGNUM))]
8587   "TARGET_ARM && !arm_arch5"
8588   "*
8589   return output_call (&operands[1]);
8590   "
8591   [(set_attr "length" "12")
8592    (set_attr "type" "call")]
8593 )
8594
8595 ;; Note: see *call_mem
8596
8597 (define_insn "*call_value_mem"
8598   [(set (match_operand 0 "" "")
8599         (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
8600               (match_operand 2 "" "")))
8601    (use (match_operand 3 "" ""))
8602    (clobber (reg:SI LR_REGNUM))]
8603   "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
8604   "*
8605   return output_call_mem (&operands[1]);
8606   "
8607   [(set_attr "length" "12")
8608    (set_attr "type" "call")]
8609 )
8610
8611 (define_insn "*call_value_reg_thumb1_v5"
8612   [(set (match_operand 0 "" "")
8613         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8614               (match_operand 2 "" "")))
8615    (use (match_operand 3 "" ""))
8616    (clobber (reg:SI LR_REGNUM))]
8617   "TARGET_THUMB1 && arm_arch5"
8618   "blx\\t%1"
8619   [(set_attr "length" "2")
8620    (set_attr "type" "call")]
8621 )
8622
8623 (define_insn "*call_value_reg_thumb1"
8624   [(set (match_operand 0 "" "")
8625         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8626               (match_operand 2 "" "")))
8627    (use (match_operand 3 "" ""))
8628    (clobber (reg:SI LR_REGNUM))]
8629   "TARGET_THUMB1 && !arm_arch5"
8630   "*
8631   {
8632     if (!TARGET_CALLER_INTERWORKING)
8633       return thumb_call_via_reg (operands[1]);
8634     else if (operands[2] == const0_rtx)
8635       return \"bl\\t%__interwork_call_via_%1\";
8636     else if (frame_pointer_needed)
8637       return \"bl\\t%__interwork_r7_call_via_%1\";
8638     else
8639       return \"bl\\t%__interwork_r11_call_via_%1\";
8640   }"
8641   [(set_attr "type" "call")]
8642 )
8643
8644 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8645 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8646
8647 (define_insn "*call_symbol"
8648   [(call (mem:SI (match_operand:SI 0 "" ""))
8649          (match_operand 1 "" ""))
8650    (use (match_operand 2 "" ""))
8651    (clobber (reg:SI LR_REGNUM))]
8652   "TARGET_32BIT
8653    && (GET_CODE (operands[0]) == SYMBOL_REF)
8654    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
8655   "*
8656   {
8657     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
8658   }"
8659   [(set_attr "type" "call")]
8660 )
8661
8662 (define_insn "*call_value_symbol"
8663   [(set (match_operand 0 "" "")
8664         (call (mem:SI (match_operand:SI 1 "" ""))
8665         (match_operand:SI 2 "" "")))
8666    (use (match_operand 3 "" ""))
8667    (clobber (reg:SI LR_REGNUM))]
8668   "TARGET_32BIT
8669    && (GET_CODE (operands[1]) == SYMBOL_REF)
8670    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
8671   "*
8672   {
8673     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
8674   }"
8675   [(set_attr "type" "call")]
8676 )
8677
8678 (define_insn "*call_insn"
8679   [(call (mem:SI (match_operand:SI 0 "" ""))
8680          (match_operand:SI 1 "" ""))
8681    (use (match_operand 2 "" ""))
8682    (clobber (reg:SI LR_REGNUM))]
8683   "TARGET_THUMB1
8684    && GET_CODE (operands[0]) == SYMBOL_REF
8685    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
8686   "bl\\t%a0"
8687   [(set_attr "length" "4")
8688    (set_attr "type" "call")]
8689 )
8690
8691 (define_insn "*call_value_insn"
8692   [(set (match_operand 0 "" "")
8693         (call (mem:SI (match_operand 1 "" ""))
8694               (match_operand 2 "" "")))
8695    (use (match_operand 3 "" ""))
8696    (clobber (reg:SI LR_REGNUM))]
8697   "TARGET_THUMB1
8698    && GET_CODE (operands[1]) == SYMBOL_REF
8699    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
8700   "bl\\t%a1"
8701   [(set_attr "length" "4")
8702    (set_attr "type" "call")]
8703 )
8704
8705 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
8706 (define_expand "sibcall"
8707   [(parallel [(call (match_operand 0 "memory_operand" "")
8708                     (match_operand 1 "general_operand" ""))
8709               (return)
8710               (use (match_operand 2 "" ""))])]
8711   "TARGET_32BIT"
8712   "
8713   {
8714     if (operands[2] == NULL_RTX)
8715       operands[2] = const0_rtx;
8716   }"
8717 )
8718
8719 (define_expand "sibcall_value"
8720   [(parallel [(set (match_operand 0 "" "")
8721                    (call (match_operand 1 "memory_operand" "")
8722                          (match_operand 2 "general_operand" "")))
8723               (return)
8724               (use (match_operand 3 "" ""))])]
8725   "TARGET_32BIT"
8726   "
8727   {
8728     if (operands[3] == NULL_RTX)
8729       operands[3] = const0_rtx;
8730   }"
8731 )
8732
8733 (define_insn "*sibcall_insn"
8734  [(call (mem:SI (match_operand:SI 0 "" "X"))
8735         (match_operand 1 "" ""))
8736   (return)
8737   (use (match_operand 2 "" ""))]
8738   "TARGET_32BIT && GET_CODE (operands[0]) == SYMBOL_REF"
8739   "*
8740   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8741   "
8742   [(set_attr "type" "call")]
8743 )
8744
8745 (define_insn "*sibcall_value_insn"
8746  [(set (match_operand 0 "" "")
8747        (call (mem:SI (match_operand:SI 1 "" "X"))
8748              (match_operand 2 "" "")))
8749   (return)
8750   (use (match_operand 3 "" ""))]
8751   "TARGET_32BIT && GET_CODE (operands[1]) == SYMBOL_REF"
8752   "*
8753   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8754   "
8755   [(set_attr "type" "call")]
8756 )
8757
8758 (define_expand "return"
8759   [(return)]
8760   "TARGET_32BIT && USE_RETURN_INSN (FALSE)"
8761   "")
8762
8763 ;; Often the return insn will be the same as loading from memory, so set attr
8764 (define_insn "*arm_return"
8765   [(return)]
8766   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
8767   "*
8768   {
8769     if (arm_ccfsm_state == 2)
8770       {
8771         arm_ccfsm_state += 2;
8772         return \"\";
8773       }
8774     return output_return_instruction (const_true_rtx, TRUE, FALSE);
8775   }"
8776   [(set_attr "type" "load1")
8777    (set_attr "length" "12")
8778    (set_attr "predicable" "yes")]
8779 )
8780
8781 (define_insn "*cond_return"
8782   [(set (pc)
8783         (if_then_else (match_operator 0 "arm_comparison_operator"
8784                        [(match_operand 1 "cc_register" "") (const_int 0)])
8785                       (return)
8786                       (pc)))]
8787   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
8788   "*
8789   {
8790     if (arm_ccfsm_state == 2)
8791       {
8792         arm_ccfsm_state += 2;
8793         return \"\";
8794       }
8795     return output_return_instruction (operands[0], TRUE, FALSE);
8796   }"
8797   [(set_attr "conds" "use")
8798    (set_attr "length" "12")
8799    (set_attr "type" "load1")]
8800 )
8801
8802 (define_insn "*cond_return_inverted"
8803   [(set (pc)
8804         (if_then_else (match_operator 0 "arm_comparison_operator"
8805                        [(match_operand 1 "cc_register" "") (const_int 0)])
8806                       (pc)
8807                       (return)))]
8808   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
8809   "*
8810   {
8811     if (arm_ccfsm_state == 2)
8812       {
8813         arm_ccfsm_state += 2;
8814         return \"\";
8815       }
8816     return output_return_instruction (operands[0], TRUE, TRUE);
8817   }"
8818   [(set_attr "conds" "use")
8819    (set_attr "length" "12")
8820    (set_attr "type" "load1")]
8821 )
8822
8823 ;; Generate a sequence of instructions to determine if the processor is
8824 ;; in 26-bit or 32-bit mode, and return the appropriate return address
8825 ;; mask.
8826
8827 (define_expand "return_addr_mask"
8828   [(set (match_dup 1)
8829       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8830                        (const_int 0)))
8831    (set (match_operand:SI 0 "s_register_operand" "")
8832       (if_then_else:SI (eq (match_dup 1) (const_int 0))
8833                        (const_int -1)
8834                        (const_int 67108860)))] ; 0x03fffffc
8835   "TARGET_ARM"
8836   "
8837   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
8838   ")
8839
8840 (define_insn "*check_arch2"
8841   [(set (match_operand:CC_NOOV 0 "cc_register" "")
8842       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8843                        (const_int 0)))]
8844   "TARGET_ARM"
8845   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8846   [(set_attr "length" "8")
8847    (set_attr "conds" "set")]
8848 )
8849
8850 ;; Call subroutine returning any type.
8851
8852 (define_expand "untyped_call"
8853   [(parallel [(call (match_operand 0 "" "")
8854                     (const_int 0))
8855               (match_operand 1 "" "")
8856               (match_operand 2 "" "")])]
8857   "TARGET_EITHER"
8858   "
8859   {
8860     int i;
8861     rtx par = gen_rtx_PARALLEL (VOIDmode,
8862                                 rtvec_alloc (XVECLEN (operands[2], 0)));
8863     rtx addr = gen_reg_rtx (Pmode);
8864     rtx mem;
8865     int size = 0;
8866
8867     emit_move_insn (addr, XEXP (operands[1], 0));
8868     mem = change_address (operands[1], BLKmode, addr);
8869
8870     for (i = 0; i < XVECLEN (operands[2], 0); i++)
8871       {
8872         rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
8873
8874         /* Default code only uses r0 as a return value, but we could
8875            be using anything up to 4 registers.  */
8876         if (REGNO (src) == R0_REGNUM)
8877           src = gen_rtx_REG (TImode, R0_REGNUM);
8878
8879         XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8880                                                  GEN_INT (size));
8881         size += GET_MODE_SIZE (GET_MODE (src));
8882       }
8883
8884     emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8885                                     const0_rtx));
8886
8887     size = 0;
8888
8889     for (i = 0; i < XVECLEN (par, 0); i++)
8890       {
8891         HOST_WIDE_INT offset = 0;
8892         rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8893
8894         if (size != 0)
8895           emit_move_insn (addr, plus_constant (addr, size));
8896
8897         mem = change_address (mem, GET_MODE (reg), NULL);
8898         if (REGNO (reg) == R0_REGNUM)
8899           {
8900             /* On thumb we have to use a write-back instruction.  */
8901             emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
8902                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8903             size = TARGET_ARM ? 16 : 0;
8904           }
8905         else
8906           {
8907             emit_move_insn (mem, reg);
8908             size = GET_MODE_SIZE (GET_MODE (reg));
8909           }
8910       }
8911
8912     /* The optimizer does not know that the call sets the function value
8913        registers we stored in the result block.  We avoid problems by
8914        claiming that all hard registers are used and clobbered at this
8915        point.  */
8916     emit_insn (gen_blockage ());
8917
8918     DONE;
8919   }"
8920 )
8921
8922 (define_expand "untyped_return"
8923   [(match_operand:BLK 0 "memory_operand" "")
8924    (match_operand 1 "" "")]
8925   "TARGET_EITHER"
8926   "
8927   {
8928     int i;
8929     rtx addr = gen_reg_rtx (Pmode);
8930     rtx mem;
8931     int size = 0;
8932
8933     emit_move_insn (addr, XEXP (operands[0], 0));
8934     mem = change_address (operands[0], BLKmode, addr);
8935
8936     for (i = 0; i < XVECLEN (operands[1], 0); i++)
8937       {
8938         HOST_WIDE_INT offset = 0;
8939         rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8940
8941         if (size != 0)
8942           emit_move_insn (addr, plus_constant (addr, size));
8943
8944         mem = change_address (mem, GET_MODE (reg), NULL);
8945         if (REGNO (reg) == R0_REGNUM)
8946           {
8947             /* On thumb we have to use a write-back instruction.  */
8948             emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
8949                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8950             size = TARGET_ARM ? 16 : 0;
8951           }
8952         else
8953           {
8954             emit_move_insn (reg, mem);
8955             size = GET_MODE_SIZE (GET_MODE (reg));
8956           }
8957       }
8958
8959     /* Emit USE insns before the return.  */
8960     for (i = 0; i < XVECLEN (operands[1], 0); i++)
8961       emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
8962
8963     /* Construct the return.  */
8964     expand_naked_return ();
8965
8966     DONE;
8967   }"
8968 )
8969
8970 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8971 ;; all of memory.  This blocks insns from being moved across this point.
8972
8973 (define_insn "blockage"
8974   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
8975   "TARGET_EITHER"
8976   ""
8977   [(set_attr "length" "0")
8978    (set_attr "type" "block")]
8979 )
8980
8981 (define_expand "casesi"
8982   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
8983    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
8984    (match_operand:SI 2 "const_int_operand" "")  ; total range
8985    (match_operand:SI 3 "" "")                   ; table label
8986    (match_operand:SI 4 "" "")]                  ; Out of range label
8987   "TARGET_32BIT || optimize_size || flag_pic"
8988   "
8989   {
8990     enum insn_code code;
8991     if (operands[1] != const0_rtx)
8992       {
8993         rtx reg = gen_reg_rtx (SImode);
8994
8995         emit_insn (gen_addsi3 (reg, operands[0],
8996                                GEN_INT (-INTVAL (operands[1]))));
8997         operands[0] = reg;
8998       }
8999
9000     if (TARGET_ARM)
9001       code = CODE_FOR_arm_casesi_internal;
9002     else if (TARGET_THUMB1)
9003       code = CODE_FOR_thumb1_casesi_internal_pic;
9004     else if (flag_pic)
9005       code = CODE_FOR_thumb2_casesi_internal_pic;
9006     else
9007       code = CODE_FOR_thumb2_casesi_internal;
9008
9009     if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
9010       operands[2] = force_reg (SImode, operands[2]);
9011
9012     emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
9013                                           operands[3], operands[4]));
9014     DONE;
9015   }"
9016 )
9017
9018 ;; The USE in this pattern is needed to tell flow analysis that this is
9019 ;; a CASESI insn.  It has no other purpose.
9020 (define_insn "arm_casesi_internal"
9021   [(parallel [(set (pc)
9022                (if_then_else
9023                 (leu (match_operand:SI 0 "s_register_operand" "r")
9024                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
9025                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
9026                                  (label_ref (match_operand 2 "" ""))))
9027                 (label_ref (match_operand 3 "" ""))))
9028               (clobber (reg:CC CC_REGNUM))
9029               (use (label_ref (match_dup 2)))])]
9030   "TARGET_ARM"
9031   "*
9032     if (flag_pic)
9033       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
9034     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
9035   "
9036   [(set_attr "conds" "clob")
9037    (set_attr "length" "12")]
9038 )
9039
9040 (define_expand "thumb1_casesi_internal_pic"
9041   [(match_operand:SI 0 "s_register_operand" "")
9042    (match_operand:SI 1 "thumb1_cmp_operand" "")
9043    (match_operand 2 "" "")
9044    (match_operand 3 "" "")]
9045   "TARGET_THUMB1"
9046   {
9047     rtx reg0;
9048     rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[1]);
9049     emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[1],
9050                                     operands[3]));
9051     reg0 = gen_rtx_REG (SImode, 0);
9052     emit_move_insn (reg0, operands[0]);
9053     emit_jump_insn (gen_thumb1_casesi_dispatch (operands[2]/*, operands[3]*/));
9054     DONE;
9055   }
9056 )
9057
9058 (define_insn "thumb1_casesi_dispatch"
9059   [(parallel [(set (pc) (unspec [(reg:SI 0)
9060                                  (label_ref (match_operand 0 "" ""))
9061 ;;                               (label_ref (match_operand 1 "" ""))
9062 ]
9063                          UNSPEC_THUMB1_CASESI))
9064               (clobber (reg:SI IP_REGNUM))
9065               (clobber (reg:SI LR_REGNUM))])]
9066   "TARGET_THUMB1"
9067   "* return thumb1_output_casesi(operands);"
9068   [(set_attr "length" "4")]
9069 )
9070
9071 (define_expand "indirect_jump"
9072   [(set (pc)
9073         (match_operand:SI 0 "s_register_operand" ""))]
9074   "TARGET_EITHER"
9075   "
9076   /* Thumb-2 doesn't have mov pc, reg.  Explicitly set the low bit of the
9077      address and use bx.  */
9078   if (TARGET_THUMB2)
9079     {
9080       rtx tmp;
9081       tmp = gen_reg_rtx (SImode);
9082       emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
9083       operands[0] = tmp;
9084     }
9085   "
9086 )
9087
9088 ;; NB Never uses BX.
9089 (define_insn "*arm_indirect_jump"
9090   [(set (pc)
9091         (match_operand:SI 0 "s_register_operand" "r"))]
9092   "TARGET_ARM"
9093   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
9094   [(set_attr "predicable" "yes")]
9095 )
9096
9097 (define_insn "*load_indirect_jump"
9098   [(set (pc)
9099         (match_operand:SI 0 "memory_operand" "m"))]
9100   "TARGET_ARM"
9101   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
9102   [(set_attr "type" "load1")
9103    (set_attr "pool_range" "4096")
9104    (set_attr "neg_pool_range" "4084")
9105    (set_attr "predicable" "yes")]
9106 )
9107
9108 ;; NB Never uses BX.
9109 (define_insn "*thumb1_indirect_jump"
9110   [(set (pc)
9111         (match_operand:SI 0 "register_operand" "l*r"))]
9112   "TARGET_THUMB1"
9113   "mov\\tpc, %0"
9114   [(set_attr "conds" "clob")
9115    (set_attr "length" "2")]
9116 )
9117
9118 \f
9119 ;; Misc insns
9120
9121 (define_insn "nop"
9122   [(const_int 0)]
9123   "TARGET_EITHER"
9124   "*
9125   if (TARGET_UNIFIED_ASM)
9126     return \"nop\";
9127   if (TARGET_ARM)
9128     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
9129   return  \"mov\\tr8, r8\";
9130   "
9131   [(set (attr "length")
9132         (if_then_else (eq_attr "is_thumb" "yes")
9133                       (const_int 2)
9134                       (const_int 4)))]
9135 )
9136
9137 \f
9138 ;; Patterns to allow combination of arithmetic, cond code and shifts
9139
9140 (define_insn "*arith_shiftsi"
9141   [(set (match_operand:SI 0 "s_register_operand" "=r")
9142         (match_operator:SI 1 "shiftable_operator"
9143           [(match_operator:SI 3 "shift_operator"
9144              [(match_operand:SI 4 "s_register_operand" "r")
9145               (match_operand:SI 5 "reg_or_int_operand" "rI")])
9146            (match_operand:SI 2 "s_register_operand" "r")]))]
9147   "TARGET_ARM"
9148   "%i1%?\\t%0, %2, %4%S3"
9149   [(set_attr "predicable" "yes")
9150    (set_attr "shift" "4")
9151    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
9152                       (const_string "alu_shift")
9153                       (const_string "alu_shift_reg")))]
9154 )
9155
9156 (define_split
9157   [(set (match_operand:SI 0 "s_register_operand" "")
9158         (match_operator:SI 1 "shiftable_operator"
9159          [(match_operator:SI 2 "shiftable_operator"
9160            [(match_operator:SI 3 "shift_operator"
9161              [(match_operand:SI 4 "s_register_operand" "")
9162               (match_operand:SI 5 "reg_or_int_operand" "")])
9163             (match_operand:SI 6 "s_register_operand" "")])
9164           (match_operand:SI 7 "arm_rhs_operand" "")]))
9165    (clobber (match_operand:SI 8 "s_register_operand" ""))]
9166   "TARGET_ARM"
9167   [(set (match_dup 8)
9168         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9169                          (match_dup 6)]))
9170    (set (match_dup 0)
9171         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
9172   "")
9173
9174 (define_insn "*arith_shiftsi_compare0"
9175   [(set (reg:CC_NOOV CC_REGNUM)
9176         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
9177                           [(match_operator:SI 3 "shift_operator"
9178                             [(match_operand:SI 4 "s_register_operand" "r")
9179                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
9180                            (match_operand:SI 2 "s_register_operand" "r")])
9181                          (const_int 0)))
9182    (set (match_operand:SI 0 "s_register_operand" "=r")
9183         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9184                          (match_dup 2)]))]
9185   "TARGET_ARM"
9186   "%i1%.\\t%0, %2, %4%S3"
9187   [(set_attr "conds" "set")
9188    (set_attr "shift" "4")
9189    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
9190                       (const_string "alu_shift")
9191                       (const_string "alu_shift_reg")))]
9192 )
9193
9194 (define_insn "*arith_shiftsi_compare0_scratch"
9195   [(set (reg:CC_NOOV CC_REGNUM)
9196         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
9197                           [(match_operator:SI 3 "shift_operator"
9198                             [(match_operand:SI 4 "s_register_operand" "r")
9199                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
9200                            (match_operand:SI 2 "s_register_operand" "r")])
9201                          (const_int 0)))
9202    (clobber (match_scratch:SI 0 "=r"))]
9203   "TARGET_ARM"
9204   "%i1%.\\t%0, %2, %4%S3"
9205   [(set_attr "conds" "set")
9206    (set_attr "shift" "4")
9207    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
9208                       (const_string "alu_shift")
9209                       (const_string "alu_shift_reg")))]
9210 )
9211
9212 (define_insn "*sub_shiftsi"
9213   [(set (match_operand:SI 0 "s_register_operand" "=r")
9214         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
9215                   (match_operator:SI 2 "shift_operator"
9216                    [(match_operand:SI 3 "s_register_operand" "r")
9217                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
9218   "TARGET_ARM"
9219   "sub%?\\t%0, %1, %3%S2"
9220   [(set_attr "predicable" "yes")
9221    (set_attr "shift" "3")
9222    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
9223                       (const_string "alu_shift")
9224                       (const_string "alu_shift_reg")))]
9225 )
9226
9227 (define_insn "*sub_shiftsi_compare0"
9228   [(set (reg:CC_NOOV CC_REGNUM)
9229         (compare:CC_NOOV
9230          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
9231                    (match_operator:SI 2 "shift_operator"
9232                     [(match_operand:SI 3 "s_register_operand" "r")
9233                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
9234          (const_int 0)))
9235    (set (match_operand:SI 0 "s_register_operand" "=r")
9236         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9237                                                  (match_dup 4)])))]
9238   "TARGET_ARM"
9239   "sub%.\\t%0, %1, %3%S2"
9240   [(set_attr "conds" "set")
9241    (set_attr "shift" "3")
9242    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
9243                       (const_string "alu_shift")
9244                       (const_string "alu_shift_reg")))]
9245 )
9246
9247 (define_insn "*sub_shiftsi_compare0_scratch"
9248   [(set (reg:CC_NOOV CC_REGNUM)
9249         (compare:CC_NOOV
9250          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
9251                    (match_operator:SI 2 "shift_operator"
9252                     [(match_operand:SI 3 "s_register_operand" "r")
9253                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
9254          (const_int 0)))
9255    (clobber (match_scratch:SI 0 "=r"))]
9256   "TARGET_ARM"
9257   "sub%.\\t%0, %1, %3%S2"
9258   [(set_attr "conds" "set")
9259    (set_attr "shift" "3")
9260    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
9261                       (const_string "alu_shift")
9262                       (const_string "alu_shift_reg")))]
9263 )
9264
9265 \f
9266
9267 (define_insn "*and_scc"
9268   [(set (match_operand:SI 0 "s_register_operand" "=r")
9269         (and:SI (match_operator:SI 1 "arm_comparison_operator"
9270                  [(match_operand 3 "cc_register" "") (const_int 0)])
9271                 (match_operand:SI 2 "s_register_operand" "r")))]
9272   "TARGET_ARM"
9273   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
9274   [(set_attr "conds" "use")
9275    (set_attr "length" "8")]
9276 )
9277
9278 (define_insn "*ior_scc"
9279   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9280         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
9281                  [(match_operand 3 "cc_register" "") (const_int 0)])
9282                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
9283   "TARGET_ARM"
9284   "@
9285    orr%d2\\t%0, %1, #1
9286    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
9287   [(set_attr "conds" "use")
9288    (set_attr "length" "4,8")]
9289 )
9290
9291 (define_insn "*compare_scc"
9292   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9293         (match_operator:SI 1 "arm_comparison_operator"
9294          [(match_operand:SI 2 "s_register_operand" "r,r")
9295           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
9296    (clobber (reg:CC CC_REGNUM))]
9297   "TARGET_ARM"
9298   "*
9299     if (operands[3] == const0_rtx)
9300       {
9301         if (GET_CODE (operands[1]) == LT)
9302           return \"mov\\t%0, %2, lsr #31\";
9303
9304         if (GET_CODE (operands[1]) == GE)
9305           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
9306
9307         if (GET_CODE (operands[1]) == EQ)
9308           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
9309       }
9310
9311     if (GET_CODE (operands[1]) == NE)
9312       {
9313         if (which_alternative == 1)
9314           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
9315         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
9316       }
9317     if (which_alternative == 1)
9318       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9319     else
9320       output_asm_insn (\"cmp\\t%2, %3\", operands);
9321     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
9322   "
9323   [(set_attr "conds" "clob")
9324    (set_attr "length" "12")]
9325 )
9326
9327 (define_insn "*cond_move"
9328   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9329         (if_then_else:SI (match_operator 3 "equality_operator"
9330                           [(match_operator 4 "arm_comparison_operator"
9331                             [(match_operand 5 "cc_register" "") (const_int 0)])
9332                            (const_int 0)])
9333                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9334                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
9335   "TARGET_ARM"
9336   "*
9337     if (GET_CODE (operands[3]) == NE)
9338       {
9339         if (which_alternative != 1)
9340           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
9341         if (which_alternative != 0)
9342           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
9343         return \"\";
9344       }
9345     if (which_alternative != 0)
9346       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9347     if (which_alternative != 1)
9348       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
9349     return \"\";
9350   "
9351   [(set_attr "conds" "use")
9352    (set_attr "length" "4,4,8")]
9353 )
9354
9355 (define_insn "*cond_arith"
9356   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9357         (match_operator:SI 5 "shiftable_operator" 
9358          [(match_operator:SI 4 "arm_comparison_operator"
9359            [(match_operand:SI 2 "s_register_operand" "r,r")
9360             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9361           (match_operand:SI 1 "s_register_operand" "0,?r")]))
9362    (clobber (reg:CC CC_REGNUM))]
9363   "TARGET_ARM"
9364   "*
9365     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
9366       return \"%i5\\t%0, %1, %2, lsr #31\";
9367
9368     output_asm_insn (\"cmp\\t%2, %3\", operands);
9369     if (GET_CODE (operands[5]) == AND)
9370       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
9371     else if (GET_CODE (operands[5]) == MINUS)
9372       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
9373     else if (which_alternative != 0)
9374       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9375     return \"%i5%d4\\t%0, %1, #1\";
9376   "
9377   [(set_attr "conds" "clob")
9378    (set_attr "length" "12")]
9379 )
9380
9381 (define_insn "*cond_sub"
9382   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9383         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
9384                   (match_operator:SI 4 "arm_comparison_operator"
9385                    [(match_operand:SI 2 "s_register_operand" "r,r")
9386                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
9387    (clobber (reg:CC CC_REGNUM))]
9388   "TARGET_ARM"
9389   "*
9390     output_asm_insn (\"cmp\\t%2, %3\", operands);
9391     if (which_alternative != 0)
9392       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9393     return \"sub%d4\\t%0, %1, #1\";
9394   "
9395   [(set_attr "conds" "clob")
9396    (set_attr "length" "8,12")]
9397 )
9398
9399 ;; ??? Is it worth using these conditional patterns in Thumb-2 mode?
9400 (define_insn "*cmp_ite0"
9401   [(set (match_operand 6 "dominant_cc_register" "")
9402         (compare
9403          (if_then_else:SI
9404           (match_operator 4 "arm_comparison_operator"
9405            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9406             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9407           (match_operator:SI 5 "arm_comparison_operator"
9408            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9409             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
9410           (const_int 0))
9411          (const_int 0)))]
9412   "TARGET_ARM"
9413   "*
9414   {
9415     static const char * const opcodes[4][2] =
9416     {
9417       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9418        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9419       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9420        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9421       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9422        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9423       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9424        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9425     };
9426     int swap =
9427       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9428
9429     return opcodes[which_alternative][swap];
9430   }"
9431   [(set_attr "conds" "set")
9432    (set_attr "length" "8")]
9433 )
9434
9435 (define_insn "*cmp_ite1"
9436   [(set (match_operand 6 "dominant_cc_register" "")
9437         (compare
9438          (if_then_else:SI
9439           (match_operator 4 "arm_comparison_operator"
9440            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9441             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9442           (match_operator:SI 5 "arm_comparison_operator"
9443            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9444             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
9445           (const_int 1))
9446          (const_int 0)))]
9447   "TARGET_ARM"
9448   "*
9449   {
9450     static const char * const opcodes[4][2] =
9451     {
9452       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
9453        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9454       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
9455        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9456       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
9457        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9458       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
9459        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9460     };
9461     int swap =
9462       comparison_dominates_p (GET_CODE (operands[5]),
9463                               reverse_condition (GET_CODE (operands[4])));
9464
9465     return opcodes[which_alternative][swap];
9466   }"
9467   [(set_attr "conds" "set")
9468    (set_attr "length" "8")]
9469 )
9470
9471 (define_insn "*cmp_and"
9472   [(set (match_operand 6 "dominant_cc_register" "")
9473         (compare
9474          (and:SI
9475           (match_operator 4 "arm_comparison_operator"
9476            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9477             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9478           (match_operator:SI 5 "arm_comparison_operator"
9479            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9480             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9481          (const_int 0)))]
9482   "TARGET_ARM"
9483   "*
9484   {
9485     static const char *const opcodes[4][2] =
9486     {
9487       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9488        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9489       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9490        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9491       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9492        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9493       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9494        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9495     };
9496     int swap =
9497       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9498
9499     return opcodes[which_alternative][swap];
9500   }"
9501   [(set_attr "conds" "set")
9502    (set_attr "predicable" "no")
9503    (set_attr "length" "8")]
9504 )
9505
9506 (define_insn "*cmp_ior"
9507   [(set (match_operand 6 "dominant_cc_register" "")
9508         (compare
9509          (ior:SI
9510           (match_operator 4 "arm_comparison_operator"
9511            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9512             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9513           (match_operator:SI 5 "arm_comparison_operator"
9514            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9515             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9516          (const_int 0)))]
9517   "TARGET_ARM"
9518   "*
9519 {
9520   static const char *const opcodes[4][2] =
9521   {
9522     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
9523      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9524     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
9525      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9526     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
9527      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9528     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
9529      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9530   };
9531   int swap =
9532     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9533
9534   return opcodes[which_alternative][swap];
9535 }
9536 "
9537   [(set_attr "conds" "set")
9538    (set_attr "length" "8")]
9539 )
9540
9541 (define_insn_and_split "*ior_scc_scc"
9542   [(set (match_operand:SI 0 "s_register_operand" "=r")
9543         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9544                  [(match_operand:SI 1 "s_register_operand" "r")
9545                   (match_operand:SI 2 "arm_add_operand" "rIL")])
9546                 (match_operator:SI 6 "arm_comparison_operator"
9547                  [(match_operand:SI 4 "s_register_operand" "r")
9548                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
9549    (clobber (reg:CC CC_REGNUM))]
9550   "TARGET_ARM
9551    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9552        != CCmode)"
9553   "#"
9554   "TARGET_ARM && reload_completed"
9555   [(set (match_dup 7)
9556         (compare
9557          (ior:SI
9558           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9559           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9560          (const_int 0)))
9561    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9562   "operands[7]
9563      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9564                                                   DOM_CC_X_OR_Y),
9565                     CC_REGNUM);"
9566   [(set_attr "conds" "clob")
9567    (set_attr "length" "16")])
9568
9569 ; If the above pattern is followed by a CMP insn, then the compare is 
9570 ; redundant, since we can rework the conditional instruction that follows.
9571 (define_insn_and_split "*ior_scc_scc_cmp"
9572   [(set (match_operand 0 "dominant_cc_register" "")
9573         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9574                           [(match_operand:SI 1 "s_register_operand" "r")
9575                            (match_operand:SI 2 "arm_add_operand" "rIL")])
9576                          (match_operator:SI 6 "arm_comparison_operator"
9577                           [(match_operand:SI 4 "s_register_operand" "r")
9578                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
9579                  (const_int 0)))
9580    (set (match_operand:SI 7 "s_register_operand" "=r")
9581         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9582                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9583   "TARGET_ARM"
9584   "#"
9585   "TARGET_ARM && reload_completed"
9586   [(set (match_dup 0)
9587         (compare
9588          (ior:SI
9589           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9590           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9591          (const_int 0)))
9592    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9593   ""
9594   [(set_attr "conds" "set")
9595    (set_attr "length" "16")])
9596
9597 (define_insn_and_split "*and_scc_scc"
9598   [(set (match_operand:SI 0 "s_register_operand" "=r")
9599         (and:SI (match_operator:SI 3 "arm_comparison_operator"
9600                  [(match_operand:SI 1 "s_register_operand" "r")
9601                   (match_operand:SI 2 "arm_add_operand" "rIL")])
9602                 (match_operator:SI 6 "arm_comparison_operator"
9603                  [(match_operand:SI 4 "s_register_operand" "r")
9604                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
9605    (clobber (reg:CC CC_REGNUM))]
9606   "TARGET_ARM
9607    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9608        != CCmode)"
9609   "#"
9610   "TARGET_ARM && reload_completed
9611    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9612        != CCmode)"
9613   [(set (match_dup 7)
9614         (compare
9615          (and:SI
9616           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9617           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9618          (const_int 0)))
9619    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9620   "operands[7]
9621      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9622                                                   DOM_CC_X_AND_Y),
9623                     CC_REGNUM);"
9624   [(set_attr "conds" "clob")
9625    (set_attr "length" "16")])
9626
9627 ; If the above pattern is followed by a CMP insn, then the compare is 
9628 ; redundant, since we can rework the conditional instruction that follows.
9629 (define_insn_and_split "*and_scc_scc_cmp"
9630   [(set (match_operand 0 "dominant_cc_register" "")
9631         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9632                           [(match_operand:SI 1 "s_register_operand" "r")
9633                            (match_operand:SI 2 "arm_add_operand" "rIL")])
9634                          (match_operator:SI 6 "arm_comparison_operator"
9635                           [(match_operand:SI 4 "s_register_operand" "r")
9636                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
9637                  (const_int 0)))
9638    (set (match_operand:SI 7 "s_register_operand" "=r")
9639         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9640                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9641   "TARGET_ARM"
9642   "#"
9643   "TARGET_ARM && reload_completed"
9644   [(set (match_dup 0)
9645         (compare
9646          (and:SI
9647           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9648           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9649          (const_int 0)))
9650    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9651   ""
9652   [(set_attr "conds" "set")
9653    (set_attr "length" "16")])
9654
9655 ;; If there is no dominance in the comparison, then we can still save an
9656 ;; instruction in the AND case, since we can know that the second compare
9657 ;; need only zero the value if false (if true, then the value is already
9658 ;; correct).
9659 (define_insn_and_split "*and_scc_scc_nodom"
9660   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
9661         (and:SI (match_operator:SI 3 "arm_comparison_operator"
9662                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
9663                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9664                 (match_operator:SI 6 "arm_comparison_operator"
9665                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
9666                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9667    (clobber (reg:CC CC_REGNUM))]
9668   "TARGET_ARM
9669    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9670        == CCmode)"
9671   "#"
9672   "TARGET_ARM && reload_completed"
9673   [(parallel [(set (match_dup 0)
9674                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9675               (clobber (reg:CC CC_REGNUM))])
9676    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9677    (set (match_dup 0)
9678         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9679                          (match_dup 0)
9680                          (const_int 0)))]
9681   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9682                                               operands[4], operands[5]),
9683                               CC_REGNUM);
9684    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9685                                   operands[5]);"
9686   [(set_attr "conds" "clob")
9687    (set_attr "length" "20")])
9688
9689 (define_split
9690   [(set (reg:CC_NOOV CC_REGNUM)
9691         (compare:CC_NOOV (ior:SI
9692                           (and:SI (match_operand:SI 0 "s_register_operand" "")
9693                                   (const_int 1))
9694                           (match_operator:SI 1 "arm_comparison_operator"
9695                            [(match_operand:SI 2 "s_register_operand" "")
9696                             (match_operand:SI 3 "arm_add_operand" "")]))
9697                          (const_int 0)))
9698    (clobber (match_operand:SI 4 "s_register_operand" ""))]
9699   "TARGET_ARM"
9700   [(set (match_dup 4)
9701         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9702                 (match_dup 0)))
9703    (set (reg:CC_NOOV CC_REGNUM)
9704         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9705                          (const_int 0)))]
9706   "")
9707
9708 (define_split
9709   [(set (reg:CC_NOOV CC_REGNUM)
9710         (compare:CC_NOOV (ior:SI
9711                           (match_operator:SI 1 "arm_comparison_operator"
9712                            [(match_operand:SI 2 "s_register_operand" "")
9713                             (match_operand:SI 3 "arm_add_operand" "")])
9714                           (and:SI (match_operand:SI 0 "s_register_operand" "")
9715                                   (const_int 1)))
9716                          (const_int 0)))
9717    (clobber (match_operand:SI 4 "s_register_operand" ""))]
9718   "TARGET_ARM"
9719   [(set (match_dup 4)
9720         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9721                 (match_dup 0)))
9722    (set (reg:CC_NOOV CC_REGNUM)
9723         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9724                          (const_int 0)))]
9725   "")
9726 ;; ??? The conditional patterns above need checking for Thumb-2 usefulness
9727
9728 (define_insn "*negscc"
9729   [(set (match_operand:SI 0 "s_register_operand" "=r")
9730         (neg:SI (match_operator 3 "arm_comparison_operator"
9731                  [(match_operand:SI 1 "s_register_operand" "r")
9732                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
9733    (clobber (reg:CC CC_REGNUM))]
9734   "TARGET_ARM"
9735   "*
9736   if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
9737     return \"mov\\t%0, %1, asr #31\";
9738
9739   if (GET_CODE (operands[3]) == NE)
9740     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9741
9742   output_asm_insn (\"cmp\\t%1, %2\", operands);
9743   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9744   return \"mvn%d3\\t%0, #0\";
9745   "
9746   [(set_attr "conds" "clob")
9747    (set_attr "length" "12")]
9748 )
9749
9750 (define_insn "movcond"
9751   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9752         (if_then_else:SI
9753          (match_operator 5 "arm_comparison_operator"
9754           [(match_operand:SI 3 "s_register_operand" "r,r,r")
9755            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9756          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9757          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
9758    (clobber (reg:CC CC_REGNUM))]
9759   "TARGET_ARM"
9760   "*
9761   if (GET_CODE (operands[5]) == LT
9762       && (operands[4] == const0_rtx))
9763     {
9764       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9765         {
9766           if (operands[2] == const0_rtx)
9767             return \"and\\t%0, %1, %3, asr #31\";
9768           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9769         }
9770       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9771         {
9772           if (operands[1] == const0_rtx)
9773             return \"bic\\t%0, %2, %3, asr #31\";
9774           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9775         }
9776       /* The only case that falls through to here is when both ops 1 & 2
9777          are constants.  */
9778     }
9779
9780   if (GET_CODE (operands[5]) == GE
9781       && (operands[4] == const0_rtx))
9782     {
9783       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9784         {
9785           if (operands[2] == const0_rtx)
9786             return \"bic\\t%0, %1, %3, asr #31\";
9787           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9788         }
9789       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9790         {
9791           if (operands[1] == const0_rtx)
9792             return \"and\\t%0, %2, %3, asr #31\";
9793           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9794         }
9795       /* The only case that falls through to here is when both ops 1 & 2
9796          are constants.  */
9797     }
9798   if (GET_CODE (operands[4]) == CONST_INT
9799       && !const_ok_for_arm (INTVAL (operands[4])))
9800     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9801   else
9802     output_asm_insn (\"cmp\\t%3, %4\", operands);
9803   if (which_alternative != 0)
9804     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9805   if (which_alternative != 1)
9806     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9807   return \"\";
9808   "
9809   [(set_attr "conds" "clob")
9810    (set_attr "length" "8,8,12")]
9811 )
9812
9813 ;; ??? The patterns below need checking for Thumb-2 usefulness.
9814
9815 (define_insn "*ifcompare_plus_move"
9816   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9817         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9818                           [(match_operand:SI 4 "s_register_operand" "r,r")
9819                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9820                          (plus:SI
9821                           (match_operand:SI 2 "s_register_operand" "r,r")
9822                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
9823                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9824    (clobber (reg:CC CC_REGNUM))]
9825   "TARGET_ARM"
9826   "#"
9827   [(set_attr "conds" "clob")
9828    (set_attr "length" "8,12")]
9829 )
9830
9831 (define_insn "*if_plus_move"
9832   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9833         (if_then_else:SI
9834          (match_operator 4 "arm_comparison_operator"
9835           [(match_operand 5 "cc_register" "") (const_int 0)])
9836          (plus:SI
9837           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9838           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9839          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
9840   "TARGET_ARM"
9841   "@
9842    add%d4\\t%0, %2, %3
9843    sub%d4\\t%0, %2, #%n3
9844    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
9845    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
9846   [(set_attr "conds" "use")
9847    (set_attr "length" "4,4,8,8")
9848    (set_attr "type" "*,*,*,*")]
9849 )
9850
9851 (define_insn "*ifcompare_move_plus"
9852   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9853         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9854                           [(match_operand:SI 4 "s_register_operand" "r,r")
9855                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9856                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9857                          (plus:SI
9858                           (match_operand:SI 2 "s_register_operand" "r,r")
9859                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
9860    (clobber (reg:CC CC_REGNUM))]
9861   "TARGET_ARM"
9862   "#"
9863   [(set_attr "conds" "clob")
9864    (set_attr "length" "8,12")]
9865 )
9866
9867 (define_insn "*if_move_plus"
9868   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9869         (if_then_else:SI
9870          (match_operator 4 "arm_comparison_operator"
9871           [(match_operand 5 "cc_register" "") (const_int 0)])
9872          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
9873          (plus:SI
9874           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9875           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
9876   "TARGET_ARM"
9877   "@
9878    add%D4\\t%0, %2, %3
9879    sub%D4\\t%0, %2, #%n3
9880    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
9881    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
9882   [(set_attr "conds" "use")
9883    (set_attr "length" "4,4,8,8")
9884    (set_attr "type" "*,*,*,*")]
9885 )
9886
9887 (define_insn "*ifcompare_arith_arith"
9888   [(set (match_operand:SI 0 "s_register_operand" "=r")
9889         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
9890                           [(match_operand:SI 5 "s_register_operand" "r")
9891                            (match_operand:SI 6 "arm_add_operand" "rIL")])
9892                          (match_operator:SI 8 "shiftable_operator"
9893                           [(match_operand:SI 1 "s_register_operand" "r")
9894                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
9895                          (match_operator:SI 7 "shiftable_operator"
9896                           [(match_operand:SI 3 "s_register_operand" "r")
9897                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
9898    (clobber (reg:CC CC_REGNUM))]
9899   "TARGET_ARM"
9900   "#"
9901   [(set_attr "conds" "clob")
9902    (set_attr "length" "12")]
9903 )
9904
9905 (define_insn "*if_arith_arith"
9906   [(set (match_operand:SI 0 "s_register_operand" "=r")
9907         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
9908                           [(match_operand 8 "cc_register" "") (const_int 0)])
9909                          (match_operator:SI 6 "shiftable_operator"
9910                           [(match_operand:SI 1 "s_register_operand" "r")
9911                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
9912                          (match_operator:SI 7 "shiftable_operator"
9913                           [(match_operand:SI 3 "s_register_operand" "r")
9914                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
9915   "TARGET_ARM"
9916   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
9917   [(set_attr "conds" "use")
9918    (set_attr "length" "8")]
9919 )
9920
9921 (define_insn "*ifcompare_arith_move"
9922   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9923         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9924                           [(match_operand:SI 2 "s_register_operand" "r,r")
9925                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9926                          (match_operator:SI 7 "shiftable_operator"
9927                           [(match_operand:SI 4 "s_register_operand" "r,r")
9928                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
9929                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9930    (clobber (reg:CC CC_REGNUM))]
9931   "TARGET_ARM"
9932   "*
9933   /* If we have an operation where (op x 0) is the identity operation and
9934      the conditional operator is LT or GE and we are comparing against zero and
9935      everything is in registers then we can do this in two instructions.  */
9936   if (operands[3] == const0_rtx
9937       && GET_CODE (operands[7]) != AND
9938       && GET_CODE (operands[5]) == REG
9939       && GET_CODE (operands[1]) == REG 
9940       && REGNO (operands[1]) == REGNO (operands[4])
9941       && REGNO (operands[4]) != REGNO (operands[0]))
9942     {
9943       if (GET_CODE (operands[6]) == LT)
9944         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9945       else if (GET_CODE (operands[6]) == GE)
9946         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9947     }
9948   if (GET_CODE (operands[3]) == CONST_INT
9949       && !const_ok_for_arm (INTVAL (operands[3])))
9950     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9951   else
9952     output_asm_insn (\"cmp\\t%2, %3\", operands);
9953   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9954   if (which_alternative != 0)
9955     return \"mov%D6\\t%0, %1\";
9956   return \"\";
9957   "
9958   [(set_attr "conds" "clob")
9959    (set_attr "length" "8,12")]
9960 )
9961
9962 (define_insn "*if_arith_move"
9963   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9964         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9965                           [(match_operand 6 "cc_register" "") (const_int 0)])
9966                          (match_operator:SI 5 "shiftable_operator"
9967                           [(match_operand:SI 2 "s_register_operand" "r,r")
9968                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9969                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
9970   "TARGET_ARM"
9971   "@
9972    %I5%d4\\t%0, %2, %3
9973    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
9974   [(set_attr "conds" "use")
9975    (set_attr "length" "4,8")
9976    (set_attr "type" "*,*")]
9977 )
9978
9979 (define_insn "*ifcompare_move_arith"
9980   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9981         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9982                           [(match_operand:SI 4 "s_register_operand" "r,r")
9983                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9984                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9985                          (match_operator:SI 7 "shiftable_operator"
9986                           [(match_operand:SI 2 "s_register_operand" "r,r")
9987                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
9988    (clobber (reg:CC CC_REGNUM))]
9989   "TARGET_ARM"
9990   "*
9991   /* If we have an operation where (op x 0) is the identity operation and
9992      the conditional operator is LT or GE and we are comparing against zero and
9993      everything is in registers then we can do this in two instructions */
9994   if (operands[5] == const0_rtx
9995       && GET_CODE (operands[7]) != AND
9996       && GET_CODE (operands[3]) == REG
9997       && GET_CODE (operands[1]) == REG 
9998       && REGNO (operands[1]) == REGNO (operands[2])
9999       && REGNO (operands[2]) != REGNO (operands[0]))
10000     {
10001       if (GET_CODE (operands[6]) == GE)
10002         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
10003       else if (GET_CODE (operands[6]) == LT)
10004         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
10005     }
10006
10007   if (GET_CODE (operands[5]) == CONST_INT
10008       && !const_ok_for_arm (INTVAL (operands[5])))
10009     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
10010   else
10011     output_asm_insn (\"cmp\\t%4, %5\", operands);
10012
10013   if (which_alternative != 0)
10014     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
10015   return \"%I7%D6\\t%0, %2, %3\";
10016   "
10017   [(set_attr "conds" "clob")
10018    (set_attr "length" "8,12")]
10019 )
10020
10021 (define_insn "*if_move_arith"
10022   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10023         (if_then_else:SI
10024          (match_operator 4 "arm_comparison_operator"
10025           [(match_operand 6 "cc_register" "") (const_int 0)])
10026          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10027          (match_operator:SI 5 "shiftable_operator"
10028           [(match_operand:SI 2 "s_register_operand" "r,r")
10029            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
10030   "TARGET_ARM"
10031   "@
10032    %I5%D4\\t%0, %2, %3
10033    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
10034   [(set_attr "conds" "use")
10035    (set_attr "length" "4,8")
10036    (set_attr "type" "*,*")]
10037 )
10038
10039 (define_insn "*ifcompare_move_not"
10040   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10041         (if_then_else:SI
10042          (match_operator 5 "arm_comparison_operator"
10043           [(match_operand:SI 3 "s_register_operand" "r,r")
10044            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10045          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10046          (not:SI
10047           (match_operand:SI 2 "s_register_operand" "r,r"))))
10048    (clobber (reg:CC CC_REGNUM))]
10049   "TARGET_ARM"
10050   "#"
10051   [(set_attr "conds" "clob")
10052    (set_attr "length" "8,12")]
10053 )
10054
10055 (define_insn "*if_move_not"
10056   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10057         (if_then_else:SI
10058          (match_operator 4 "arm_comparison_operator"
10059           [(match_operand 3 "cc_register" "") (const_int 0)])
10060          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10061          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
10062   "TARGET_ARM"
10063   "@
10064    mvn%D4\\t%0, %2
10065    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
10066    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
10067   [(set_attr "conds" "use")
10068    (set_attr "length" "4,8,8")]
10069 )
10070
10071 (define_insn "*ifcompare_not_move"
10072   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10073         (if_then_else:SI 
10074          (match_operator 5 "arm_comparison_operator"
10075           [(match_operand:SI 3 "s_register_operand" "r,r")
10076            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10077          (not:SI
10078           (match_operand:SI 2 "s_register_operand" "r,r"))
10079          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
10080    (clobber (reg:CC CC_REGNUM))]
10081   "TARGET_ARM"
10082   "#"
10083   [(set_attr "conds" "clob")
10084    (set_attr "length" "8,12")]
10085 )
10086
10087 (define_insn "*if_not_move"
10088   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10089         (if_then_else:SI
10090          (match_operator 4 "arm_comparison_operator"
10091           [(match_operand 3 "cc_register" "") (const_int 0)])
10092          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10093          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
10094   "TARGET_ARM"
10095   "@
10096    mvn%d4\\t%0, %2
10097    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
10098    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
10099   [(set_attr "conds" "use")
10100    (set_attr "length" "4,8,8")]
10101 )
10102
10103 (define_insn "*ifcompare_shift_move"
10104   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10105         (if_then_else:SI
10106          (match_operator 6 "arm_comparison_operator"
10107           [(match_operand:SI 4 "s_register_operand" "r,r")
10108            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10109          (match_operator:SI 7 "shift_operator"
10110           [(match_operand:SI 2 "s_register_operand" "r,r")
10111            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
10112          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
10113    (clobber (reg:CC CC_REGNUM))]
10114   "TARGET_ARM"
10115   "#"
10116   [(set_attr "conds" "clob")
10117    (set_attr "length" "8,12")]
10118 )
10119
10120 (define_insn "*if_shift_move"
10121   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10122         (if_then_else:SI
10123          (match_operator 5 "arm_comparison_operator"
10124           [(match_operand 6 "cc_register" "") (const_int 0)])
10125          (match_operator:SI 4 "shift_operator"
10126           [(match_operand:SI 2 "s_register_operand" "r,r,r")
10127            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
10128          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
10129   "TARGET_ARM"
10130   "@
10131    mov%d5\\t%0, %2%S4
10132    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
10133    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
10134   [(set_attr "conds" "use")
10135    (set_attr "shift" "2")
10136    (set_attr "length" "4,8,8")
10137    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
10138                       (const_string "alu_shift")
10139                       (const_string "alu_shift_reg")))]
10140 )
10141
10142 (define_insn "*ifcompare_move_shift"
10143   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10144         (if_then_else:SI
10145          (match_operator 6 "arm_comparison_operator"
10146           [(match_operand:SI 4 "s_register_operand" "r,r")
10147            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10148          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10149          (match_operator:SI 7 "shift_operator"
10150           [(match_operand:SI 2 "s_register_operand" "r,r")
10151            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
10152    (clobber (reg:CC CC_REGNUM))]
10153   "TARGET_ARM"
10154   "#"
10155   [(set_attr "conds" "clob")
10156    (set_attr "length" "8,12")]
10157 )
10158
10159 (define_insn "*if_move_shift"
10160   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10161         (if_then_else:SI
10162          (match_operator 5 "arm_comparison_operator"
10163           [(match_operand 6 "cc_register" "") (const_int 0)])
10164          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10165          (match_operator:SI 4 "shift_operator"
10166           [(match_operand:SI 2 "s_register_operand" "r,r,r")
10167            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
10168   "TARGET_ARM"
10169   "@
10170    mov%D5\\t%0, %2%S4
10171    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
10172    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
10173   [(set_attr "conds" "use")
10174    (set_attr "shift" "2")
10175    (set_attr "length" "4,8,8")
10176    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
10177                       (const_string "alu_shift")
10178                       (const_string "alu_shift_reg")))]
10179 )
10180
10181 (define_insn "*ifcompare_shift_shift"
10182   [(set (match_operand:SI 0 "s_register_operand" "=r")
10183         (if_then_else:SI
10184          (match_operator 7 "arm_comparison_operator"
10185           [(match_operand:SI 5 "s_register_operand" "r")
10186            (match_operand:SI 6 "arm_add_operand" "rIL")])
10187          (match_operator:SI 8 "shift_operator"
10188           [(match_operand:SI 1 "s_register_operand" "r")
10189            (match_operand:SI 2 "arm_rhs_operand" "rM")])
10190          (match_operator:SI 9 "shift_operator"
10191           [(match_operand:SI 3 "s_register_operand" "r")
10192            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
10193    (clobber (reg:CC CC_REGNUM))]
10194   "TARGET_ARM"
10195   "#"
10196   [(set_attr "conds" "clob")
10197    (set_attr "length" "12")]
10198 )
10199
10200 (define_insn "*if_shift_shift"
10201   [(set (match_operand:SI 0 "s_register_operand" "=r")
10202         (if_then_else:SI
10203          (match_operator 5 "arm_comparison_operator"
10204           [(match_operand 8 "cc_register" "") (const_int 0)])
10205          (match_operator:SI 6 "shift_operator"
10206           [(match_operand:SI 1 "s_register_operand" "r")
10207            (match_operand:SI 2 "arm_rhs_operand" "rM")])
10208          (match_operator:SI 7 "shift_operator"
10209           [(match_operand:SI 3 "s_register_operand" "r")
10210            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
10211   "TARGET_ARM"
10212   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
10213   [(set_attr "conds" "use")
10214    (set_attr "shift" "1")
10215    (set_attr "length" "8")
10216    (set (attr "type") (if_then_else
10217                         (and (match_operand 2 "const_int_operand" "")
10218                              (match_operand 4 "const_int_operand" ""))
10219                       (const_string "alu_shift")
10220                       (const_string "alu_shift_reg")))]
10221 )
10222
10223 (define_insn "*ifcompare_not_arith"
10224   [(set (match_operand:SI 0 "s_register_operand" "=r")
10225         (if_then_else:SI
10226          (match_operator 6 "arm_comparison_operator"
10227           [(match_operand:SI 4 "s_register_operand" "r")
10228            (match_operand:SI 5 "arm_add_operand" "rIL")])
10229          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10230          (match_operator:SI 7 "shiftable_operator"
10231           [(match_operand:SI 2 "s_register_operand" "r")
10232            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
10233    (clobber (reg:CC CC_REGNUM))]
10234   "TARGET_ARM"
10235   "#"
10236   [(set_attr "conds" "clob")
10237    (set_attr "length" "12")]
10238 )
10239
10240 (define_insn "*if_not_arith"
10241   [(set (match_operand:SI 0 "s_register_operand" "=r")
10242         (if_then_else:SI
10243          (match_operator 5 "arm_comparison_operator"
10244           [(match_operand 4 "cc_register" "") (const_int 0)])
10245          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10246          (match_operator:SI 6 "shiftable_operator"
10247           [(match_operand:SI 2 "s_register_operand" "r")
10248            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
10249   "TARGET_ARM"
10250   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
10251   [(set_attr "conds" "use")
10252    (set_attr "length" "8")]
10253 )
10254
10255 (define_insn "*ifcompare_arith_not"
10256   [(set (match_operand:SI 0 "s_register_operand" "=r")
10257         (if_then_else:SI
10258          (match_operator 6 "arm_comparison_operator"
10259           [(match_operand:SI 4 "s_register_operand" "r")
10260            (match_operand:SI 5 "arm_add_operand" "rIL")])
10261          (match_operator:SI 7 "shiftable_operator"
10262           [(match_operand:SI 2 "s_register_operand" "r")
10263            (match_operand:SI 3 "arm_rhs_operand" "rI")])
10264          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
10265    (clobber (reg:CC CC_REGNUM))]
10266   "TARGET_ARM"
10267   "#"
10268   [(set_attr "conds" "clob")
10269    (set_attr "length" "12")]
10270 )
10271
10272 (define_insn "*if_arith_not"
10273   [(set (match_operand:SI 0 "s_register_operand" "=r")
10274         (if_then_else:SI
10275          (match_operator 5 "arm_comparison_operator"
10276           [(match_operand 4 "cc_register" "") (const_int 0)])
10277          (match_operator:SI 6 "shiftable_operator"
10278           [(match_operand:SI 2 "s_register_operand" "r")
10279            (match_operand:SI 3 "arm_rhs_operand" "rI")])
10280          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
10281   "TARGET_ARM"
10282   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
10283   [(set_attr "conds" "use")
10284    (set_attr "length" "8")]
10285 )
10286
10287 (define_insn "*ifcompare_neg_move"
10288   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10289         (if_then_else:SI
10290          (match_operator 5 "arm_comparison_operator"
10291           [(match_operand:SI 3 "s_register_operand" "r,r")
10292            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10293          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10294          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
10295    (clobber (reg:CC CC_REGNUM))]
10296   "TARGET_ARM"
10297   "#"
10298   [(set_attr "conds" "clob")
10299    (set_attr "length" "8,12")]
10300 )
10301
10302 (define_insn "*if_neg_move"
10303   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10304         (if_then_else:SI
10305          (match_operator 4 "arm_comparison_operator"
10306           [(match_operand 3 "cc_register" "") (const_int 0)])
10307          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10308          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
10309   "TARGET_ARM"
10310   "@
10311    rsb%d4\\t%0, %2, #0
10312    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
10313    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
10314   [(set_attr "conds" "use")
10315    (set_attr "length" "4,8,8")]
10316 )
10317
10318 (define_insn "*ifcompare_move_neg"
10319   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10320         (if_then_else:SI
10321          (match_operator 5 "arm_comparison_operator"
10322           [(match_operand:SI 3 "s_register_operand" "r,r")
10323            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10324          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10325          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
10326    (clobber (reg:CC CC_REGNUM))]
10327   "TARGET_ARM"
10328   "#"
10329   [(set_attr "conds" "clob")
10330    (set_attr "length" "8,12")]
10331 )
10332
10333 (define_insn "*if_move_neg"
10334   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10335         (if_then_else:SI
10336          (match_operator 4 "arm_comparison_operator"
10337           [(match_operand 3 "cc_register" "") (const_int 0)])
10338          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10339          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
10340   "TARGET_ARM"
10341   "@
10342    rsb%D4\\t%0, %2, #0
10343    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
10344    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
10345   [(set_attr "conds" "use")
10346    (set_attr "length" "4,8,8")]
10347 )
10348
10349 (define_insn "*arith_adjacentmem"
10350   [(set (match_operand:SI 0 "s_register_operand" "=r")
10351         (match_operator:SI 1 "shiftable_operator"
10352          [(match_operand:SI 2 "memory_operand" "m")
10353           (match_operand:SI 3 "memory_operand" "m")]))
10354    (clobber (match_scratch:SI 4 "=r"))]
10355   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
10356   "*
10357   {
10358     rtx ldm[3];
10359     rtx arith[4];
10360     rtx base_reg;
10361     HOST_WIDE_INT val1 = 0, val2 = 0;
10362
10363     if (REGNO (operands[0]) > REGNO (operands[4]))
10364       {
10365         ldm[1] = operands[4];
10366         ldm[2] = operands[0];
10367       }
10368     else
10369       {
10370         ldm[1] = operands[0];
10371         ldm[2] = operands[4];
10372       }
10373
10374     base_reg = XEXP (operands[2], 0);
10375
10376     if (!REG_P (base_reg))
10377       {
10378         val1 = INTVAL (XEXP (base_reg, 1));
10379         base_reg = XEXP (base_reg, 0);
10380       }
10381
10382     if (!REG_P (XEXP (operands[3], 0)))
10383       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
10384
10385     arith[0] = operands[0];
10386     arith[3] = operands[1];
10387
10388     if (val1 < val2)
10389       {
10390         arith[1] = ldm[1];
10391         arith[2] = ldm[2];
10392       }
10393     else
10394       {
10395         arith[1] = ldm[2];
10396         arith[2] = ldm[1];
10397       }
10398
10399     ldm[0] = base_reg;
10400     if (val1 !=0 && val2 != 0)
10401       {
10402         rtx ops[3];
10403
10404         if (val1 == 4 || val2 == 4)
10405           /* Other val must be 8, since we know they are adjacent and neither
10406              is zero.  */
10407           output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
10408         else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
10409           {
10410             ldm[0] = ops[0] = operands[4];
10411             ops[1] = base_reg;
10412             ops[2] = GEN_INT (val1);
10413             output_add_immediate (ops);
10414             if (val1 < val2)
10415               output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
10416             else
10417               output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
10418           }
10419         else
10420           {
10421             /* Offset is out of range for a single add, so use two ldr.  */
10422             ops[0] = ldm[1];
10423             ops[1] = base_reg;
10424             ops[2] = GEN_INT (val1);
10425             output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10426             ops[0] = ldm[2];
10427             ops[2] = GEN_INT (val2);
10428             output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10429           }
10430       }
10431     else if (val1 != 0)
10432       {
10433         if (val1 < val2)
10434           output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
10435         else
10436           output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
10437       }
10438     else
10439       {
10440         if (val1 < val2)
10441           output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
10442         else
10443           output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
10444       }
10445     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10446     return \"\";
10447   }"
10448   [(set_attr "length" "12")
10449    (set_attr "predicable" "yes")
10450    (set_attr "type" "load1")]
10451 )
10452
10453 ; This pattern is never tried by combine, so do it as a peephole
10454
10455 (define_peephole2
10456   [(set (match_operand:SI 0 "arm_general_register_operand" "")
10457         (match_operand:SI 1 "arm_general_register_operand" ""))
10458    (set (reg:CC CC_REGNUM)
10459         (compare:CC (match_dup 1) (const_int 0)))]
10460   "TARGET_ARM"
10461   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10462               (set (match_dup 0) (match_dup 1))])]
10463   ""
10464 )
10465
10466 ; Peepholes to spot possible load- and store-multiples, if the ordering is
10467 ; reversed, check that the memory references aren't volatile.
10468
10469 (define_peephole
10470   [(set (match_operand:SI 0 "s_register_operand" "=rk")
10471         (match_operand:SI 4 "memory_operand" "m"))
10472    (set (match_operand:SI 1 "s_register_operand" "=rk")
10473         (match_operand:SI 5 "memory_operand" "m"))
10474    (set (match_operand:SI 2 "s_register_operand" "=rk")
10475         (match_operand:SI 6 "memory_operand" "m"))
10476    (set (match_operand:SI 3 "s_register_operand" "=rk")
10477         (match_operand:SI 7 "memory_operand" "m"))]
10478   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
10479   "*
10480   return emit_ldm_seq (operands, 4);
10481   "
10482 )
10483
10484 (define_peephole
10485   [(set (match_operand:SI 0 "s_register_operand" "=rk")
10486         (match_operand:SI 3 "memory_operand" "m"))
10487    (set (match_operand:SI 1 "s_register_operand" "=rk")
10488         (match_operand:SI 4 "memory_operand" "m"))
10489    (set (match_operand:SI 2 "s_register_operand" "=rk")
10490         (match_operand:SI 5 "memory_operand" "m"))]
10491   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
10492   "*
10493   return emit_ldm_seq (operands, 3);
10494   "
10495 )
10496
10497 (define_peephole
10498   [(set (match_operand:SI 0 "s_register_operand" "=rk")
10499         (match_operand:SI 2 "memory_operand" "m"))
10500    (set (match_operand:SI 1 "s_register_operand" "=rk")
10501         (match_operand:SI 3 "memory_operand" "m"))]
10502   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
10503   "*
10504   return emit_ldm_seq (operands, 2);
10505   "
10506 )
10507
10508 (define_peephole
10509   [(set (match_operand:SI 4 "memory_operand" "=m")
10510         (match_operand:SI 0 "s_register_operand" "rk"))
10511    (set (match_operand:SI 5 "memory_operand" "=m")
10512         (match_operand:SI 1 "s_register_operand" "rk"))
10513    (set (match_operand:SI 6 "memory_operand" "=m")
10514         (match_operand:SI 2 "s_register_operand" "rk"))
10515    (set (match_operand:SI 7 "memory_operand" "=m")
10516         (match_operand:SI 3 "s_register_operand" "rk"))]
10517   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
10518   "*
10519   return emit_stm_seq (operands, 4);
10520   "
10521 )
10522
10523 (define_peephole
10524   [(set (match_operand:SI 3 "memory_operand" "=m")
10525         (match_operand:SI 0 "s_register_operand" "rk"))
10526    (set (match_operand:SI 4 "memory_operand" "=m")
10527         (match_operand:SI 1 "s_register_operand" "rk"))
10528    (set (match_operand:SI 5 "memory_operand" "=m")
10529         (match_operand:SI 2 "s_register_operand" "rk"))]
10530   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
10531   "*
10532   return emit_stm_seq (operands, 3);
10533   "
10534 )
10535
10536 (define_peephole
10537   [(set (match_operand:SI 2 "memory_operand" "=m")
10538         (match_operand:SI 0 "s_register_operand" "rk"))
10539    (set (match_operand:SI 3 "memory_operand" "=m")
10540         (match_operand:SI 1 "s_register_operand" "rk"))]
10541   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
10542   "*
10543   return emit_stm_seq (operands, 2);
10544   "
10545 )
10546
10547 (define_split
10548   [(set (match_operand:SI 0 "s_register_operand" "")
10549         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10550                        (const_int 0))
10551                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
10552                          [(match_operand:SI 3 "s_register_operand" "")
10553                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
10554    (clobber (match_operand:SI 5 "s_register_operand" ""))]
10555   "TARGET_ARM"
10556   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10557    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10558                               (match_dup 5)))]
10559   ""
10560 )
10561
10562 ;; This split can be used because CC_Z mode implies that the following
10563 ;; branch will be an equality, or an unsigned inequality, so the sign
10564 ;; extension is not needed.
10565
10566 (define_split
10567   [(set (reg:CC_Z CC_REGNUM)
10568         (compare:CC_Z
10569          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
10570                     (const_int 24))
10571          (match_operand 1 "const_int_operand" "")))
10572    (clobber (match_scratch:SI 2 ""))]
10573   "TARGET_ARM
10574    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10575        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
10576   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
10577    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
10578   "
10579   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
10580   "
10581 )
10582 ;; ??? Check the patterns above for Thumb-2 usefulness
10583
10584 (define_expand "prologue"
10585   [(clobber (const_int 0))]
10586   "TARGET_EITHER"
10587   "if (TARGET_32BIT)
10588      arm_expand_prologue ();
10589    else
10590      thumb1_expand_prologue ();
10591   DONE;
10592   "
10593 )
10594
10595 (define_expand "epilogue"
10596   [(clobber (const_int 0))]
10597   "TARGET_EITHER"
10598   "
10599   if (crtl->calls_eh_return)
10600     emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
10601   if (TARGET_THUMB1)
10602     thumb1_expand_epilogue ();
10603   else if (USE_RETURN_INSN (FALSE))
10604     {
10605       emit_jump_insn (gen_return ());
10606       DONE;
10607     }
10608   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10609         gen_rtvec (1,
10610                 gen_rtx_RETURN (VOIDmode)),
10611         VUNSPEC_EPILOGUE));
10612   DONE;
10613   "
10614 )
10615
10616 ;; Note - although unspec_volatile's USE all hard registers,
10617 ;; USEs are ignored after relaod has completed.  Thus we need
10618 ;; to add an unspec of the link register to ensure that flow
10619 ;; does not think that it is unused by the sibcall branch that
10620 ;; will replace the standard function epilogue.
10621 (define_insn "sibcall_epilogue"
10622   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
10623               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10624   "TARGET_32BIT"
10625   "*
10626   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
10627     return output_return_instruction (const_true_rtx, FALSE, FALSE);
10628   return arm_output_epilogue (next_nonnote_insn (insn));
10629   "
10630 ;; Length is absolute worst case
10631   [(set_attr "length" "44")
10632    (set_attr "type" "block")
10633    ;; We don't clobber the conditions, but the potential length of this
10634    ;; operation is sufficient to make conditionalizing the sequence 
10635    ;; unlikely to be profitable.
10636    (set_attr "conds" "clob")]
10637 )
10638
10639 (define_insn "*epilogue_insns"
10640   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
10641   "TARGET_EITHER"
10642   "*
10643   if (TARGET_32BIT)
10644     return arm_output_epilogue (NULL);
10645   else /* TARGET_THUMB1 */
10646     return thumb_unexpanded_epilogue ();
10647   "
10648   ; Length is absolute worst case
10649   [(set_attr "length" "44")
10650    (set_attr "type" "block")
10651    ;; We don't clobber the conditions, but the potential length of this
10652    ;; operation is sufficient to make conditionalizing the sequence 
10653    ;; unlikely to be profitable.
10654    (set_attr "conds" "clob")]
10655 )
10656
10657 (define_expand "eh_epilogue"
10658   [(use (match_operand:SI 0 "register_operand" ""))
10659    (use (match_operand:SI 1 "register_operand" ""))
10660    (use (match_operand:SI 2 "register_operand" ""))]
10661   "TARGET_EITHER"
10662   "
10663   {
10664     cfun->machine->eh_epilogue_sp_ofs = operands[1];
10665     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10666       {
10667         rtx ra = gen_rtx_REG (Pmode, 2);
10668
10669         emit_move_insn (ra, operands[2]);
10670         operands[2] = ra;
10671       }
10672     /* This is a hack -- we may have crystalized the function type too
10673        early.  */
10674     cfun->machine->func_type = 0;
10675   }"
10676 )
10677
10678 ;; This split is only used during output to reduce the number of patterns
10679 ;; that need assembler instructions adding to them.  We allowed the setting
10680 ;; of the conditions to be implicit during rtl generation so that
10681 ;; the conditional compare patterns would work.  However this conflicts to
10682 ;; some extent with the conditional data operations, so we have to split them
10683 ;; up again here.
10684
10685 ;; ??? Need to audit these splitters for Thumb-2.  Why isn't normal
10686 ;; conditional execution sufficient?
10687
10688 (define_split
10689   [(set (match_operand:SI 0 "s_register_operand" "")
10690         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10691                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10692                          (match_dup 0)
10693                          (match_operand 4 "" "")))
10694    (clobber (reg:CC CC_REGNUM))]
10695   "TARGET_ARM && reload_completed"
10696   [(set (match_dup 5) (match_dup 6))
10697    (cond_exec (match_dup 7)
10698               (set (match_dup 0) (match_dup 4)))]
10699   "
10700   {
10701     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10702                                              operands[2], operands[3]);
10703     enum rtx_code rc = GET_CODE (operands[1]);
10704
10705     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10706     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10707     if (mode == CCFPmode || mode == CCFPEmode)
10708       rc = reverse_condition_maybe_unordered (rc);
10709     else
10710       rc = reverse_condition (rc);
10711
10712     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10713   }"
10714 )
10715
10716 (define_split
10717   [(set (match_operand:SI 0 "s_register_operand" "")
10718         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10719                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10720                          (match_operand 4 "" "")
10721                          (match_dup 0)))
10722    (clobber (reg:CC CC_REGNUM))]
10723   "TARGET_ARM && reload_completed"
10724   [(set (match_dup 5) (match_dup 6))
10725    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10726               (set (match_dup 0) (match_dup 4)))]
10727   "
10728   {
10729     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10730                                              operands[2], operands[3]);
10731
10732     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10733     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10734   }"
10735 )
10736
10737 (define_split
10738   [(set (match_operand:SI 0 "s_register_operand" "")
10739         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10740                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10741                          (match_operand 4 "" "")
10742                          (match_operand 5 "" "")))
10743    (clobber (reg:CC CC_REGNUM))]
10744   "TARGET_ARM && reload_completed"
10745   [(set (match_dup 6) (match_dup 7))
10746    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10747               (set (match_dup 0) (match_dup 4)))
10748    (cond_exec (match_dup 8)
10749               (set (match_dup 0) (match_dup 5)))]
10750   "
10751   {
10752     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10753                                              operands[2], operands[3]);
10754     enum rtx_code rc = GET_CODE (operands[1]);
10755
10756     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10757     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10758     if (mode == CCFPmode || mode == CCFPEmode)
10759       rc = reverse_condition_maybe_unordered (rc);
10760     else
10761       rc = reverse_condition (rc);
10762
10763     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10764   }"
10765 )
10766
10767 (define_split
10768   [(set (match_operand:SI 0 "s_register_operand" "")
10769         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10770                           [(match_operand:SI 2 "s_register_operand" "")
10771                            (match_operand:SI 3 "arm_add_operand" "")])
10772                          (match_operand:SI 4 "arm_rhs_operand" "")
10773                          (not:SI
10774                           (match_operand:SI 5 "s_register_operand" ""))))
10775    (clobber (reg:CC CC_REGNUM))]
10776   "TARGET_ARM && reload_completed"
10777   [(set (match_dup 6) (match_dup 7))
10778    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10779               (set (match_dup 0) (match_dup 4)))
10780    (cond_exec (match_dup 8)
10781               (set (match_dup 0) (not:SI (match_dup 5))))]
10782   "
10783   {
10784     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10785                                              operands[2], operands[3]);
10786     enum rtx_code rc = GET_CODE (operands[1]);
10787
10788     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10789     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10790     if (mode == CCFPmode || mode == CCFPEmode)
10791       rc = reverse_condition_maybe_unordered (rc);
10792     else
10793       rc = reverse_condition (rc);
10794
10795     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10796   }"
10797 )
10798
10799 (define_insn "*cond_move_not"
10800   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10801         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10802                           [(match_operand 3 "cc_register" "") (const_int 0)])
10803                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10804                          (not:SI
10805                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
10806   "TARGET_ARM"
10807   "@
10808    mvn%D4\\t%0, %2
10809    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
10810   [(set_attr "conds" "use")
10811    (set_attr "length" "4,8")]
10812 )
10813
10814 ;; The next two patterns occur when an AND operation is followed by a
10815 ;; scc insn sequence 
10816
10817 (define_insn "*sign_extract_onebit"
10818   [(set (match_operand:SI 0 "s_register_operand" "=r")
10819         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10820                          (const_int 1)
10821                          (match_operand:SI 2 "const_int_operand" "n")))
10822     (clobber (reg:CC CC_REGNUM))]
10823   "TARGET_ARM"
10824   "*
10825     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10826     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10827     return \"mvnne\\t%0, #0\";
10828   "
10829   [(set_attr "conds" "clob")
10830    (set_attr "length" "8")]
10831 )
10832
10833 (define_insn "*not_signextract_onebit"
10834   [(set (match_operand:SI 0 "s_register_operand" "=r")
10835         (not:SI
10836          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10837                           (const_int 1)
10838                           (match_operand:SI 2 "const_int_operand" "n"))))
10839    (clobber (reg:CC CC_REGNUM))]
10840   "TARGET_ARM"
10841   "*
10842     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10843     output_asm_insn (\"tst\\t%1, %2\", operands);
10844     output_asm_insn (\"mvneq\\t%0, #0\", operands);
10845     return \"movne\\t%0, #0\";
10846   "
10847   [(set_attr "conds" "clob")
10848    (set_attr "length" "12")]
10849 )
10850 ;; ??? The above patterns need auditing for Thumb-2
10851
10852 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
10853 ;; expressions.  For simplicity, the first register is also in the unspec
10854 ;; part.
10855 (define_insn "*push_multi"
10856   [(match_parallel 2 "multi_register_push"
10857     [(set (match_operand:BLK 0 "memory_operand" "=m")
10858           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
10859                       UNSPEC_PUSH_MULT))])]
10860   "TARGET_32BIT"
10861   "*
10862   {
10863     int num_saves = XVECLEN (operands[2], 0);
10864      
10865     /* For the StrongARM at least it is faster to
10866        use STR to store only a single register.
10867        In Thumb mode always use push, and the assembler will pick
10868        something appropriate.  */
10869     if (num_saves == 1 && TARGET_ARM)
10870       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10871     else
10872       {
10873         int i;
10874         char pattern[100];
10875
10876         if (TARGET_ARM)
10877             strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10878         else
10879             strcpy (pattern, \"push\\t{%1\");
10880
10881         for (i = 1; i < num_saves; i++)
10882           {
10883             strcat (pattern, \", %|\");
10884             strcat (pattern,
10885                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10886           }
10887
10888         strcat (pattern, \"}\");
10889         output_asm_insn (pattern, operands);
10890       }
10891
10892     return \"\";
10893   }"
10894   [(set_attr "type" "store4")]
10895 )
10896
10897 (define_insn "stack_tie"
10898   [(set (mem:BLK (scratch))
10899         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10900                      (match_operand:SI 1 "s_register_operand" "rk")]
10901                     UNSPEC_PRLG_STK))]
10902   ""
10903   ""
10904   [(set_attr "length" "0")]
10905 )
10906
10907 ;; Similarly for the floating point registers
10908 (define_insn "*push_fp_multi"
10909   [(match_parallel 2 "multi_register_push"
10910     [(set (match_operand:BLK 0 "memory_operand" "=m")
10911           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10912                       UNSPEC_PUSH_MULT))])]
10913   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
10914   "*
10915   {
10916     char pattern[100];
10917
10918     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10919     output_asm_insn (pattern, operands);
10920     return \"\";
10921   }"
10922   [(set_attr "type" "f_store")]
10923 )
10924
10925 ;; Special patterns for dealing with the constant pool
10926
10927 (define_insn "align_4"
10928   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10929   "TARGET_EITHER"
10930   "*
10931   assemble_align (32);
10932   return \"\";
10933   "
10934 )
10935
10936 (define_insn "align_8"
10937   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10938   "TARGET_EITHER"
10939   "*
10940   assemble_align (64);
10941   return \"\";
10942   "
10943 )
10944
10945 (define_insn "consttable_end"
10946   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10947   "TARGET_EITHER"
10948   "*
10949   making_const_table = FALSE;
10950   return \"\";
10951   "
10952 )
10953
10954 (define_insn "consttable_1"
10955   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10956   "TARGET_THUMB1"
10957   "*
10958   making_const_table = TRUE;
10959   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10960   assemble_zeros (3);
10961   return \"\";
10962   "
10963   [(set_attr "length" "4")]
10964 )
10965
10966 (define_insn "consttable_2"
10967   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10968   "TARGET_THUMB1"
10969   "*
10970   making_const_table = TRUE;
10971   gcc_assert (GET_MODE_CLASS (GET_MODE (operands[0])) != MODE_FLOAT);
10972   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10973   assemble_zeros (2);
10974   return \"\";
10975   "
10976   [(set_attr "length" "4")]
10977 )
10978
10979 (define_insn "consttable_4"
10980   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10981   "TARGET_EITHER"
10982   "*
10983   {
10984     rtx x = operands[0];
10985     making_const_table = TRUE;
10986     switch (GET_MODE_CLASS (GET_MODE (x)))
10987       {
10988       case MODE_FLOAT:
10989         if (GET_MODE (x) == HFmode)
10990           arm_emit_fp16_const (x);
10991         else
10992           {
10993             REAL_VALUE_TYPE r;
10994             REAL_VALUE_FROM_CONST_DOUBLE (r, x);
10995             assemble_real (r, GET_MODE (x), BITS_PER_WORD);
10996           }
10997         break;
10998       default:
10999         /* XXX: Sometimes gcc does something really dumb and ends up with
11000            a HIGH in a constant pool entry, usually because it's trying to
11001            load into a VFP register.  We know this will always be used in
11002            combination with a LO_SUM which ignores the high bits, so just
11003            strip off the HIGH.  */
11004         if (GET_CODE (x) == HIGH)
11005           x = XEXP (x, 0);
11006         assemble_integer (x, 4, BITS_PER_WORD, 1);
11007         mark_symbol_refs_as_used (x);
11008         break;
11009       }
11010     return \"\";
11011   }"
11012   [(set_attr "length" "4")]
11013 )
11014
11015 (define_insn "consttable_8"
11016   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
11017   "TARGET_EITHER"
11018   "*
11019   {
11020     making_const_table = TRUE;
11021     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
11022       {
11023        case MODE_FLOAT:
11024         {
11025           REAL_VALUE_TYPE r;
11026           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
11027           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
11028           break;
11029         }
11030       default:
11031         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
11032         break;
11033       }
11034     return \"\";
11035   }"
11036   [(set_attr "length" "8")]
11037 )
11038
11039 (define_insn "consttable_16"
11040   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
11041   "TARGET_EITHER"
11042   "*
11043   {
11044     making_const_table = TRUE;
11045     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
11046       {
11047        case MODE_FLOAT:
11048         {
11049           REAL_VALUE_TYPE r;
11050           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
11051           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
11052           break;
11053         }
11054       default:
11055         assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
11056         break;
11057       }
11058     return \"\";
11059   }"
11060   [(set_attr "length" "16")]
11061 )
11062
11063 ;; Miscellaneous Thumb patterns
11064
11065 (define_expand "tablejump"
11066   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
11067               (use (label_ref (match_operand 1 "" "")))])]
11068   "TARGET_THUMB1"
11069   "
11070   if (flag_pic)
11071     {
11072       /* Hopefully, CSE will eliminate this copy.  */
11073       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
11074       rtx reg2 = gen_reg_rtx (SImode);
11075
11076       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
11077       operands[0] = reg2;
11078     }
11079   "
11080 )
11081
11082 ;; NB never uses BX.
11083 (define_insn "*thumb1_tablejump"
11084   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
11085    (use (label_ref (match_operand 1 "" "")))]
11086   "TARGET_THUMB1"
11087   "mov\\t%|pc, %0"
11088   [(set_attr "length" "2")]
11089 )
11090
11091 ;; V5 Instructions,
11092
11093 (define_insn "clzsi2"
11094   [(set (match_operand:SI 0 "s_register_operand" "=r")
11095         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
11096   "TARGET_32BIT && arm_arch5"
11097   "clz%?\\t%0, %1"
11098   [(set_attr "predicable" "yes")
11099    (set_attr "insn" "clz")])
11100
11101 (define_insn "rbitsi2"
11102   [(set (match_operand:SI 0 "s_register_operand" "=r")
11103         (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
11104   "TARGET_32BIT && arm_arch_thumb2"
11105   "rbit%?\\t%0, %1"
11106   [(set_attr "predicable" "yes")
11107    (set_attr "insn" "clz")])
11108
11109 (define_expand "ctzsi2"
11110  [(set (match_operand:SI           0 "s_register_operand" "")
11111        (ctz:SI (match_operand:SI  1 "s_register_operand" "")))]
11112   "TARGET_32BIT && arm_arch_thumb2"
11113   "
11114    {
11115      rtx tmp = gen_reg_rtx (SImode); 
11116      emit_insn (gen_rbitsi2 (tmp, operands[1]));
11117      emit_insn (gen_clzsi2 (operands[0], tmp));
11118    }
11119    DONE;
11120   "
11121 )
11122
11123 ;; V5E instructions.
11124
11125 (define_insn "prefetch"
11126   [(prefetch (match_operand:SI 0 "address_operand" "p")
11127              (match_operand:SI 1 "" "")
11128              (match_operand:SI 2 "" ""))]
11129   "TARGET_32BIT && arm_arch5e"
11130   "pld\\t%a0")
11131
11132 ;; General predication pattern
11133
11134 (define_cond_exec
11135   [(match_operator 0 "arm_comparison_operator"
11136     [(match_operand 1 "cc_register" "")
11137      (const_int 0)])]
11138   "TARGET_32BIT"
11139   ""
11140 )
11141
11142 (define_insn "prologue_use"
11143   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
11144   ""
11145   "%@ %0 needed for prologue"
11146   [(set_attr "length" "0")]
11147 )
11148
11149
11150 ;; Patterns for exception handling
11151
11152 (define_expand "eh_return"
11153   [(use (match_operand 0 "general_operand" ""))]
11154   "TARGET_EITHER"
11155   "
11156   {
11157     if (TARGET_32BIT)
11158       emit_insn (gen_arm_eh_return (operands[0]));
11159     else
11160       emit_insn (gen_thumb_eh_return (operands[0]));
11161     DONE;
11162   }"
11163 )
11164                                    
11165 ;; We can't expand this before we know where the link register is stored.
11166 (define_insn_and_split "arm_eh_return"
11167   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
11168                     VUNSPEC_EH_RETURN)
11169    (clobber (match_scratch:SI 1 "=&r"))]
11170   "TARGET_ARM"
11171   "#"
11172   "&& reload_completed"
11173   [(const_int 0)]
11174   "
11175   {
11176     arm_set_return_address (operands[0], operands[1]);
11177     DONE;
11178   }"
11179 )
11180
11181 (define_insn_and_split "thumb_eh_return"
11182   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
11183                     VUNSPEC_EH_RETURN)
11184    (clobber (match_scratch:SI 1 "=&l"))]
11185   "TARGET_THUMB1"
11186   "#"
11187   "&& reload_completed"
11188   [(const_int 0)]
11189   "
11190   {
11191     thumb_set_return_address (operands[0], operands[1]);
11192     DONE;
11193   }"
11194 )
11195
11196 \f
11197 ;; TLS support
11198
11199 (define_insn "load_tp_hard"
11200   [(set (match_operand:SI 0 "register_operand" "=r")
11201         (unspec:SI [(const_int 0)] UNSPEC_TLS))]
11202   "TARGET_HARD_TP"
11203   "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
11204   [(set_attr "predicable" "yes")]
11205 )
11206
11207 ;; Doesn't clobber R1-R3.  Must use r0 for the first operand.
11208 (define_insn "load_tp_soft"
11209   [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
11210    (clobber (reg:SI LR_REGNUM))
11211    (clobber (reg:SI IP_REGNUM))
11212    (clobber (reg:CC CC_REGNUM))]
11213   "TARGET_SOFT_TP"
11214   "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
11215   [(set_attr "conds" "clob")]
11216 )
11217
11218 (define_insn "*arm_movtas_ze" 
11219   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
11220                    (const_int 16)
11221                    (const_int 16))
11222         (match_operand:SI 1 "const_int_operand" ""))]
11223   "TARGET_32BIT"
11224   "movt%?\t%0, %c1"
11225  [(set_attr "predicable" "yes")
11226    (set_attr "length" "4")]
11227 )
11228
11229 (define_insn "arm_rev"
11230   [(set (match_operand:SI 0 "s_register_operand" "=r")
11231         (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
11232   "TARGET_EITHER && arm_arch6"
11233   "rev\t%0, %1"
11234   [(set (attr "length")
11235         (if_then_else (eq_attr "is_thumb" "yes")
11236                       (const_int 2)
11237                       (const_int 4)))]
11238 )
11239
11240 (define_expand "arm_legacy_rev"
11241   [(set (match_operand:SI 2 "s_register_operand" "")
11242         (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
11243                              (const_int 16))
11244                 (match_dup 1)))
11245    (set (match_dup 2)
11246         (lshiftrt:SI (match_dup 2)
11247                      (const_int 8)))
11248    (set (match_operand:SI 3 "s_register_operand" "")
11249         (rotatert:SI (match_dup 1)
11250                      (const_int 8)))
11251    (set (match_dup 2)
11252         (and:SI (match_dup 2)
11253                 (const_int -65281)))
11254    (set (match_operand:SI 0 "s_register_operand" "")
11255         (xor:SI (match_dup 3)
11256                 (match_dup 2)))]
11257   "TARGET_32BIT"
11258   ""
11259 )
11260
11261 ;; Reuse temporaries to keep register pressure down.
11262 (define_expand "thumb_legacy_rev"
11263   [(set (match_operand:SI 2 "s_register_operand" "")
11264      (ashift:SI (match_operand:SI 1 "s_register_operand" "")
11265                 (const_int 24)))
11266    (set (match_operand:SI 3 "s_register_operand" "")
11267      (lshiftrt:SI (match_dup 1)
11268                   (const_int 24)))
11269    (set (match_dup 3)
11270      (ior:SI (match_dup 3)
11271              (match_dup 2)))
11272    (set (match_operand:SI 4 "s_register_operand" "")
11273      (const_int 16))
11274    (set (match_operand:SI 5 "s_register_operand" "")
11275      (rotatert:SI (match_dup 1)
11276                   (match_dup 4)))
11277    (set (match_dup 2)
11278      (ashift:SI (match_dup 5)
11279                 (const_int 24)))
11280    (set (match_dup 5)
11281      (lshiftrt:SI (match_dup 5)
11282                   (const_int 24)))
11283    (set (match_dup 5)
11284      (ior:SI (match_dup 5)
11285              (match_dup 2)))
11286    (set (match_dup 5)
11287      (rotatert:SI (match_dup 5)
11288                   (match_dup 4)))
11289    (set (match_operand:SI 0 "s_register_operand" "")
11290      (ior:SI (match_dup 5)
11291              (match_dup 3)))]
11292   "TARGET_THUMB"
11293   ""
11294 )
11295
11296 (define_expand "bswapsi2"
11297   [(set (match_operand:SI 0 "s_register_operand" "=r")
11298         (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
11299 "TARGET_EITHER"
11300 "
11301   if (!arm_arch6)
11302     {
11303       if (!optimize_size)
11304         {
11305           rtx op2 = gen_reg_rtx (SImode);
11306           rtx op3 = gen_reg_rtx (SImode);
11307
11308           if (TARGET_THUMB)
11309             {
11310               rtx op4 = gen_reg_rtx (SImode);
11311               rtx op5 = gen_reg_rtx (SImode);
11312
11313               emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
11314                                                op2, op3, op4, op5));
11315             }
11316           else
11317             {
11318               emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
11319                                              op2, op3));
11320             }
11321
11322           DONE;
11323         }
11324       else
11325         FAIL;
11326     }
11327   "
11328 )
11329
11330 ;; Load the FPA co-processor patterns
11331 (include "fpa.md")
11332 ;; Load the Maverick co-processor patterns
11333 (include "cirrus.md")
11334 ;; Vector bits common to IWMMXT and Neon
11335 (include "vec-common.md")
11336 ;; Load the Intel Wireless Multimedia Extension patterns
11337 (include "iwmmxt.md")
11338 ;; Load the VFP co-processor patterns
11339 (include "vfp.md")
11340 ;; Thumb-2 patterns
11341 (include "thumb2.md")
11342 ;; Neon patterns
11343 (include "neon.md")
11344