OSDN Git Service

PR target/43902
[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" "L,I")))
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" "I,L")))]
744   "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
745   "@
746    add%.\\t%0, %1, %3
747    sub%.\\t%0, %1, #%n3"
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 (define_expand "maddsidi4"
1426   [(set (match_operand:DI 0 "s_register_operand" "")
1427         (plus:DI
1428          (mult:DI
1429           (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1430           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1431          (match_operand:DI 3 "s_register_operand" "")))]
1432   "TARGET_32BIT && arm_arch3m"
1433   "")
1434
1435 (define_insn "*mulsidi3adddi"
1436   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1437         (plus:DI
1438          (mult:DI
1439           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1440           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1441          (match_operand:DI 1 "s_register_operand" "0")))]
1442   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1443   "smlal%?\\t%Q0, %R0, %3, %2"
1444   [(set_attr "insn" "smlal")
1445    (set_attr "predicable" "yes")]
1446 )
1447
1448 (define_insn "*mulsidi3adddi_v6"
1449   [(set (match_operand:DI 0 "s_register_operand" "=r")
1450         (plus:DI
1451          (mult:DI
1452           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1453           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1454          (match_operand:DI 1 "s_register_operand" "0")))]
1455   "TARGET_32BIT && arm_arch6"
1456   "smlal%?\\t%Q0, %R0, %3, %2"
1457   [(set_attr "insn" "smlal")
1458    (set_attr "predicable" "yes")]
1459 )
1460
1461 ;; 32x32->64 widening multiply.
1462 ;; As with mulsi3, the only difference between the v3-5 and v6+
1463 ;; versions of these patterns is the requirement that the output not
1464 ;; overlap the inputs, but that still means we have to have a named
1465 ;; expander and two different starred insns.
1466
1467 (define_expand "mulsidi3"
1468   [(set (match_operand:DI 0 "s_register_operand" "")
1469         (mult:DI
1470          (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1471          (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1472   "TARGET_32BIT && arm_arch3m"
1473   ""
1474 )
1475
1476 (define_insn "*mulsidi3_nov6"
1477   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1478         (mult:DI
1479          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1480          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1481   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1482   "smull%?\\t%Q0, %R0, %1, %2"
1483   [(set_attr "insn" "smull")
1484    (set_attr "predicable" "yes")]
1485 )
1486
1487 (define_insn "*mulsidi3_v6"
1488   [(set (match_operand:DI 0 "s_register_operand" "=r")
1489         (mult:DI
1490          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1491          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1492   "TARGET_32BIT && arm_arch6"
1493   "smull%?\\t%Q0, %R0, %1, %2"
1494   [(set_attr "insn" "smull")
1495    (set_attr "predicable" "yes")]
1496 )
1497
1498 (define_expand "umulsidi3"
1499   [(set (match_operand:DI 0 "s_register_operand" "")
1500         (mult:DI
1501          (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1502          (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1503   "TARGET_32BIT && arm_arch3m"
1504   ""
1505 )
1506
1507 (define_insn "*umulsidi3_nov6"
1508   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1509         (mult:DI
1510          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1511          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1512   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1513   "umull%?\\t%Q0, %R0, %1, %2"
1514   [(set_attr "insn" "umull")
1515    (set_attr "predicable" "yes")]
1516 )
1517
1518 (define_insn "*umulsidi3_v6"
1519   [(set (match_operand:DI 0 "s_register_operand" "=r")
1520         (mult:DI
1521          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1522          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1523   "TARGET_32BIT && arm_arch6"
1524   "umull%?\\t%Q0, %R0, %1, %2"
1525   [(set_attr "insn" "umull")
1526    (set_attr "predicable" "yes")]
1527 )
1528
1529 (define_expand "umaddsidi4"
1530   [(set (match_operand:DI 0 "s_register_operand" "")
1531         (plus:DI
1532          (mult:DI
1533           (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1534           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1535          (match_operand:DI 3 "s_register_operand" "")))]
1536   "TARGET_32BIT && arm_arch3m"
1537   "")
1538
1539 (define_insn "*umulsidi3adddi"
1540   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1541         (plus:DI
1542          (mult:DI
1543           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1544           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1545          (match_operand:DI 1 "s_register_operand" "0")))]
1546   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1547   "umlal%?\\t%Q0, %R0, %3, %2"
1548   [(set_attr "insn" "umlal")
1549    (set_attr "predicable" "yes")]
1550 )
1551
1552 (define_insn "*umulsidi3adddi_v6"
1553   [(set (match_operand:DI 0 "s_register_operand" "=r")
1554         (plus:DI
1555          (mult:DI
1556           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1557           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1558          (match_operand:DI 1 "s_register_operand" "0")))]
1559   "TARGET_32BIT && arm_arch6"
1560   "umlal%?\\t%Q0, %R0, %3, %2"
1561   [(set_attr "insn" "umlal")
1562    (set_attr "predicable" "yes")]
1563 )
1564
1565 (define_expand "smulsi3_highpart"
1566   [(parallel
1567     [(set (match_operand:SI 0 "s_register_operand" "")
1568           (truncate:SI
1569            (lshiftrt:DI
1570             (mult:DI
1571              (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1572              (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1573             (const_int 32))))
1574      (clobber (match_scratch:SI 3 ""))])]
1575   "TARGET_32BIT && arm_arch3m"
1576   ""
1577 )
1578
1579 (define_insn "*smulsi3_highpart_nov6"
1580   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1581         (truncate:SI
1582          (lshiftrt:DI
1583           (mult:DI
1584            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
1585            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1586           (const_int 32))))
1587    (clobber (match_scratch:SI 3 "=&r,&r"))]
1588   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1589   "smull%?\\t%3, %0, %2, %1"
1590   [(set_attr "insn" "smull")
1591    (set_attr "predicable" "yes")]
1592 )
1593
1594 (define_insn "*smulsi3_highpart_v6"
1595   [(set (match_operand:SI 0 "s_register_operand" "=r")
1596         (truncate:SI
1597          (lshiftrt:DI
1598           (mult:DI
1599            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1600            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1601           (const_int 32))))
1602    (clobber (match_scratch:SI 3 "=r"))]
1603   "TARGET_32BIT && arm_arch6"
1604   "smull%?\\t%3, %0, %2, %1"
1605   [(set_attr "insn" "smull")
1606    (set_attr "predicable" "yes")]
1607 )
1608
1609 (define_expand "umulsi3_highpart"
1610   [(parallel
1611     [(set (match_operand:SI 0 "s_register_operand" "")
1612           (truncate:SI
1613            (lshiftrt:DI
1614             (mult:DI
1615              (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1616               (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1617             (const_int 32))))
1618      (clobber (match_scratch:SI 3 ""))])]
1619   "TARGET_32BIT && arm_arch3m"
1620   ""
1621 )
1622
1623 (define_insn "*umulsi3_highpart_nov6"
1624   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1625         (truncate:SI
1626          (lshiftrt:DI
1627           (mult:DI
1628            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
1629            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1630           (const_int 32))))
1631    (clobber (match_scratch:SI 3 "=&r,&r"))]
1632   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1633   "umull%?\\t%3, %0, %2, %1"
1634   [(set_attr "insn" "umull")
1635    (set_attr "predicable" "yes")]
1636 )
1637
1638 (define_insn "*umulsi3_highpart_v6"
1639   [(set (match_operand:SI 0 "s_register_operand" "=r")
1640         (truncate:SI
1641          (lshiftrt:DI
1642           (mult:DI
1643            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1644            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1645           (const_int 32))))
1646    (clobber (match_scratch:SI 3 "=r"))]
1647   "TARGET_32BIT && arm_arch6"
1648   "umull%?\\t%3, %0, %2, %1"
1649   [(set_attr "insn" "umull")
1650    (set_attr "predicable" "yes")]
1651 )
1652
1653 (define_insn "mulhisi3"
1654   [(set (match_operand:SI 0 "s_register_operand" "=r")
1655         (mult:SI (sign_extend:SI
1656                   (match_operand:HI 1 "s_register_operand" "%r"))
1657                  (sign_extend:SI
1658                   (match_operand:HI 2 "s_register_operand" "r"))))]
1659   "TARGET_DSP_MULTIPLY"
1660   "smulbb%?\\t%0, %1, %2"
1661   [(set_attr "insn" "smulxy")
1662    (set_attr "predicable" "yes")]
1663 )
1664
1665 (define_insn "*mulhisi3tb"
1666   [(set (match_operand:SI 0 "s_register_operand" "=r")
1667         (mult:SI (ashiftrt:SI
1668                   (match_operand:SI 1 "s_register_operand" "r")
1669                   (const_int 16))
1670                  (sign_extend:SI
1671                   (match_operand:HI 2 "s_register_operand" "r"))))]
1672   "TARGET_DSP_MULTIPLY"
1673   "smultb%?\\t%0, %1, %2"
1674   [(set_attr "insn" "smulxy")
1675    (set_attr "predicable" "yes")]
1676 )
1677
1678 (define_insn "*mulhisi3bt"
1679   [(set (match_operand:SI 0 "s_register_operand" "=r")
1680         (mult:SI (sign_extend:SI
1681                   (match_operand:HI 1 "s_register_operand" "r"))
1682                  (ashiftrt:SI
1683                   (match_operand:SI 2 "s_register_operand" "r")
1684                   (const_int 16))))]
1685   "TARGET_DSP_MULTIPLY"
1686   "smulbt%?\\t%0, %1, %2"
1687   [(set_attr "insn" "smulxy")
1688    (set_attr "predicable" "yes")]
1689 )
1690
1691 (define_insn "*mulhisi3tt"
1692   [(set (match_operand:SI 0 "s_register_operand" "=r")
1693         (mult:SI (ashiftrt:SI
1694                   (match_operand:SI 1 "s_register_operand" "r")
1695                   (const_int 16))
1696                  (ashiftrt:SI
1697                   (match_operand:SI 2 "s_register_operand" "r")
1698                   (const_int 16))))]
1699   "TARGET_DSP_MULTIPLY"
1700   "smultt%?\\t%0, %1, %2"
1701   [(set_attr "insn" "smulxy")
1702    (set_attr "predicable" "yes")]
1703 )
1704
1705 (define_insn "maddhisi4"
1706   [(set (match_operand:SI 0 "s_register_operand" "=r")
1707         (plus:SI (match_operand:SI 3 "s_register_operand" "r")
1708                  (mult:SI (sign_extend:SI
1709                            (match_operand:HI 1 "s_register_operand" "%r"))
1710                           (sign_extend:SI
1711                            (match_operand:HI 2 "s_register_operand" "r")))))]
1712   "TARGET_DSP_MULTIPLY"
1713   "smlabb%?\\t%0, %1, %2, %3"
1714   [(set_attr "insn" "smlaxy")
1715    (set_attr "predicable" "yes")]
1716 )
1717
1718 (define_insn "*maddhidi4"
1719   [(set (match_operand:DI 0 "s_register_operand" "=r")
1720         (plus:DI
1721           (match_operand:DI 3 "s_register_operand" "0")
1722           (mult:DI (sign_extend:DI
1723                     (match_operand:HI 1 "s_register_operand" "%r"))
1724                    (sign_extend:DI
1725                     (match_operand:HI 2 "s_register_operand" "r")))))]
1726   "TARGET_DSP_MULTIPLY"
1727   "smlalbb%?\\t%Q0, %R0, %1, %2"
1728   [(set_attr "insn" "smlalxy")
1729    (set_attr "predicable" "yes")])
1730
1731 (define_expand "mulsf3"
1732   [(set (match_operand:SF          0 "s_register_operand" "")
1733         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1734                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1735   "TARGET_32BIT && TARGET_HARD_FLOAT"
1736   "
1737   if (TARGET_MAVERICK
1738       && !cirrus_fp_register (operands[2], SFmode))
1739     operands[2] = force_reg (SFmode, operands[2]);
1740 ")
1741
1742 (define_expand "muldf3"
1743   [(set (match_operand:DF          0 "s_register_operand" "")
1744         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1745                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1746   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
1747   "
1748   if (TARGET_MAVERICK
1749       && !cirrus_fp_register (operands[2], DFmode))
1750     operands[2] = force_reg (DFmode, operands[2]);
1751 ")
1752 \f
1753 ;; Division insns
1754
1755 (define_expand "divsf3"
1756   [(set (match_operand:SF 0 "s_register_operand" "")
1757         (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1758                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1759   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1760   "")
1761
1762 (define_expand "divdf3"
1763   [(set (match_operand:DF 0 "s_register_operand" "")
1764         (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1765                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1766   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
1767   "")
1768 \f
1769 ;; Modulo insns
1770
1771 (define_expand "modsf3"
1772   [(set (match_operand:SF 0 "s_register_operand" "")
1773         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1774                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1775   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
1776   "")
1777
1778 (define_expand "moddf3"
1779   [(set (match_operand:DF 0 "s_register_operand" "")
1780         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1781                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1782   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
1783   "")
1784 \f
1785 ;; Boolean and,ior,xor insns
1786
1787 ;; Split up double word logical operations
1788
1789 ;; Split up simple DImode logical operations.  Simply perform the logical
1790 ;; operation on the upper and lower halves of the registers.
1791 (define_split
1792   [(set (match_operand:DI 0 "s_register_operand" "")
1793         (match_operator:DI 6 "logical_binary_operator"
1794           [(match_operand:DI 1 "s_register_operand" "")
1795            (match_operand:DI 2 "s_register_operand" "")]))]
1796   "TARGET_32BIT && reload_completed
1797    && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1798   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1799    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1800   "
1801   {
1802     operands[3] = gen_highpart (SImode, operands[0]);
1803     operands[0] = gen_lowpart (SImode, operands[0]);
1804     operands[4] = gen_highpart (SImode, operands[1]);
1805     operands[1] = gen_lowpart (SImode, operands[1]);
1806     operands[5] = gen_highpart (SImode, operands[2]);
1807     operands[2] = gen_lowpart (SImode, operands[2]);
1808   }"
1809 )
1810
1811 (define_split
1812   [(set (match_operand:DI 0 "s_register_operand" "")
1813         (match_operator:DI 6 "logical_binary_operator"
1814           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1815            (match_operand:DI 1 "s_register_operand" "")]))]
1816   "TARGET_32BIT && reload_completed"
1817   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1818    (set (match_dup 3) (match_op_dup:SI 6
1819                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1820                          (match_dup 4)]))]
1821   "
1822   {
1823     operands[3] = gen_highpart (SImode, operands[0]);
1824     operands[0] = gen_lowpart (SImode, operands[0]);
1825     operands[4] = gen_highpart (SImode, operands[1]);
1826     operands[1] = gen_lowpart (SImode, operands[1]);
1827     operands[5] = gen_highpart (SImode, operands[2]);
1828     operands[2] = gen_lowpart (SImode, operands[2]);
1829   }"
1830 )
1831
1832 ;; The zero extend of operand 2 means we can just copy the high part of
1833 ;; operand1 into operand0.
1834 (define_split
1835   [(set (match_operand:DI 0 "s_register_operand" "")
1836         (ior:DI
1837           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1838           (match_operand:DI 1 "s_register_operand" "")))]
1839   "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
1840   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1841    (set (match_dup 3) (match_dup 4))]
1842   "
1843   {
1844     operands[4] = gen_highpart (SImode, operands[1]);
1845     operands[3] = gen_highpart (SImode, operands[0]);
1846     operands[0] = gen_lowpart (SImode, operands[0]);
1847     operands[1] = gen_lowpart (SImode, operands[1]);
1848   }"
1849 )
1850
1851 ;; The zero extend of operand 2 means we can just copy the high part of
1852 ;; operand1 into operand0.
1853 (define_split
1854   [(set (match_operand:DI 0 "s_register_operand" "")
1855         (xor:DI
1856           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1857           (match_operand:DI 1 "s_register_operand" "")))]
1858   "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
1859   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1860    (set (match_dup 3) (match_dup 4))]
1861   "
1862   {
1863     operands[4] = gen_highpart (SImode, operands[1]);
1864     operands[3] = gen_highpart (SImode, operands[0]);
1865     operands[0] = gen_lowpart (SImode, operands[0]);
1866     operands[1] = gen_lowpart (SImode, operands[1]);
1867   }"
1868 )
1869
1870 (define_insn "anddi3"
1871   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1872         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1873                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1874   "TARGET_32BIT && ! TARGET_IWMMXT"
1875   "#"
1876   [(set_attr "length" "8")]
1877 )
1878
1879 (define_insn_and_split "*anddi_zesidi_di"
1880   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1881         (and:DI (zero_extend:DI
1882                  (match_operand:SI 2 "s_register_operand" "r,r"))
1883                 (match_operand:DI 1 "s_register_operand" "0,r")))]
1884   "TARGET_32BIT"
1885   "#"
1886   "TARGET_32BIT && reload_completed"
1887   ; The zero extend of operand 2 clears the high word of the output
1888   ; operand.
1889   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1890    (set (match_dup 3) (const_int 0))]
1891   "
1892   {
1893     operands[3] = gen_highpart (SImode, operands[0]);
1894     operands[0] = gen_lowpart (SImode, operands[0]);
1895     operands[1] = gen_lowpart (SImode, operands[1]);
1896   }"
1897   [(set_attr "length" "8")]
1898 )
1899
1900 (define_insn "*anddi_sesdi_di"
1901   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1902         (and:DI (sign_extend:DI
1903                  (match_operand:SI 2 "s_register_operand" "r,r"))
1904                 (match_operand:DI  1 "s_register_operand" "0,r")))]
1905   "TARGET_32BIT"
1906   "#"
1907   [(set_attr "length" "8")]
1908 )
1909
1910 (define_expand "andsi3"
1911   [(set (match_operand:SI         0 "s_register_operand" "")
1912         (and:SI (match_operand:SI 1 "s_register_operand" "")
1913                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1914   "TARGET_EITHER"
1915   "
1916   if (TARGET_32BIT)
1917     {
1918       if (GET_CODE (operands[2]) == CONST_INT)
1919         {
1920           arm_split_constant (AND, SImode, NULL_RTX,
1921                               INTVAL (operands[2]), operands[0],
1922                               operands[1], optimize && can_create_pseudo_p ());
1923
1924           DONE;
1925         }
1926     }
1927   else /* TARGET_THUMB1 */
1928     {
1929       if (GET_CODE (operands[2]) != CONST_INT)
1930         {
1931           rtx tmp = force_reg (SImode, operands[2]);
1932           if (rtx_equal_p (operands[0], operands[1]))
1933             operands[2] = tmp;
1934           else
1935             {
1936               operands[2] = operands[1];
1937               operands[1] = tmp;
1938             }
1939         }
1940       else
1941         {
1942           int i;
1943           
1944           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1945             {
1946               operands[2] = force_reg (SImode,
1947                                        GEN_INT (~INTVAL (operands[2])));
1948               
1949               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1950               
1951               DONE;
1952             }
1953
1954           for (i = 9; i <= 31; i++)
1955             {
1956               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1957                 {
1958                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1959                                         const0_rtx));
1960                   DONE;
1961                 }
1962               else if ((((HOST_WIDE_INT) 1) << i) - 1
1963                        == ~INTVAL (operands[2]))
1964                 {
1965                   rtx shift = GEN_INT (i);
1966                   rtx reg = gen_reg_rtx (SImode);
1967                 
1968                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1969                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1970                   
1971                   DONE;
1972                 }
1973             }
1974
1975           operands[2] = force_reg (SImode, operands[2]);
1976         }
1977     }
1978   "
1979 )
1980
1981 ; ??? Check split length for Thumb-2
1982 (define_insn_and_split "*arm_andsi3_insn"
1983   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1984         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1985                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1986   "TARGET_32BIT"
1987   "@
1988    and%?\\t%0, %1, %2
1989    bic%?\\t%0, %1, #%B2
1990    #"
1991   "TARGET_32BIT
1992    && GET_CODE (operands[2]) == CONST_INT
1993    && !(const_ok_for_arm (INTVAL (operands[2]))
1994         || const_ok_for_arm (~INTVAL (operands[2])))"
1995   [(clobber (const_int 0))]
1996   "
1997   arm_split_constant  (AND, SImode, curr_insn, 
1998                        INTVAL (operands[2]), operands[0], operands[1], 0);
1999   DONE;
2000   "
2001   [(set_attr "length" "4,4,16")
2002    (set_attr "predicable" "yes")]
2003 )
2004
2005 (define_insn "*thumb1_andsi3_insn"
2006   [(set (match_operand:SI         0 "register_operand" "=l")
2007         (and:SI (match_operand:SI 1 "register_operand" "%0")
2008                 (match_operand:SI 2 "register_operand" "l")))]
2009   "TARGET_THUMB1"
2010   "and\\t%0, %0, %2"
2011   [(set_attr "length" "2")]
2012 )
2013
2014 (define_insn "*andsi3_compare0"
2015   [(set (reg:CC_NOOV CC_REGNUM)
2016         (compare:CC_NOOV
2017          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
2018                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
2019          (const_int 0)))
2020    (set (match_operand:SI          0 "s_register_operand" "=r,r")
2021         (and:SI (match_dup 1) (match_dup 2)))]
2022   "TARGET_32BIT"
2023   "@
2024    and%.\\t%0, %1, %2
2025    bic%.\\t%0, %1, #%B2"
2026   [(set_attr "conds" "set")]
2027 )
2028
2029 (define_insn "*andsi3_compare0_scratch"
2030   [(set (reg:CC_NOOV CC_REGNUM)
2031         (compare:CC_NOOV
2032          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
2033                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
2034          (const_int 0)))
2035    (clobber (match_scratch:SI 2 "=X,r"))]
2036   "TARGET_32BIT"
2037   "@
2038    tst%?\\t%0, %1
2039    bic%.\\t%2, %0, #%B1"
2040   [(set_attr "conds" "set")]
2041 )
2042
2043 (define_insn "*zeroextractsi_compare0_scratch"
2044   [(set (reg:CC_NOOV CC_REGNUM)
2045         (compare:CC_NOOV (zero_extract:SI
2046                           (match_operand:SI 0 "s_register_operand" "r")
2047                           (match_operand 1 "const_int_operand" "n")
2048                           (match_operand 2 "const_int_operand" "n"))
2049                          (const_int 0)))]
2050   "TARGET_32BIT
2051   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2052       && INTVAL (operands[1]) > 0 
2053       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2054       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
2055   "*
2056   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2057                          << INTVAL (operands[2]));
2058   output_asm_insn (\"tst%?\\t%0, %1\", operands);
2059   return \"\";
2060   "
2061   [(set_attr "conds" "set")]
2062 )
2063
2064 (define_insn_and_split "*ne_zeroextractsi"
2065   [(set (match_operand:SI 0 "s_register_operand" "=r")
2066         (ne:SI (zero_extract:SI
2067                 (match_operand:SI 1 "s_register_operand" "r")
2068                 (match_operand:SI 2 "const_int_operand" "n")
2069                 (match_operand:SI 3 "const_int_operand" "n"))
2070                (const_int 0)))
2071    (clobber (reg:CC CC_REGNUM))]
2072   "TARGET_32BIT
2073    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2074        && INTVAL (operands[2]) > 0 
2075        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2076        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2077   "#"
2078   "TARGET_32BIT
2079    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2080        && INTVAL (operands[2]) > 0 
2081        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2082        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2083   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2084                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2085                                     (const_int 0)))
2086               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2087    (set (match_dup 0)
2088         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2089                          (match_dup 0) (const_int 1)))]
2090   "
2091   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2092                          << INTVAL (operands[3])); 
2093   "
2094   [(set_attr "conds" "clob")
2095    (set (attr "length")
2096         (if_then_else (eq_attr "is_thumb" "yes")
2097                       (const_int 12)
2098                       (const_int 8)))]
2099 )
2100
2101 (define_insn_and_split "*ne_zeroextractsi_shifted"
2102   [(set (match_operand:SI 0 "s_register_operand" "=r")
2103         (ne:SI (zero_extract:SI
2104                 (match_operand:SI 1 "s_register_operand" "r")
2105                 (match_operand:SI 2 "const_int_operand" "n")
2106                 (const_int 0))
2107                (const_int 0)))
2108    (clobber (reg:CC CC_REGNUM))]
2109   "TARGET_ARM"
2110   "#"
2111   "TARGET_ARM"
2112   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2113                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2114                                     (const_int 0)))
2115               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2116    (set (match_dup 0)
2117         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2118                          (match_dup 0) (const_int 1)))]
2119   "
2120   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2121   "
2122   [(set_attr "conds" "clob")
2123    (set_attr "length" "8")]
2124 )
2125
2126 (define_insn_and_split "*ite_ne_zeroextractsi"
2127   [(set (match_operand:SI 0 "s_register_operand" "=r")
2128         (if_then_else:SI (ne (zero_extract:SI
2129                               (match_operand:SI 1 "s_register_operand" "r")
2130                               (match_operand:SI 2 "const_int_operand" "n")
2131                               (match_operand:SI 3 "const_int_operand" "n"))
2132                              (const_int 0))
2133                          (match_operand:SI 4 "arm_not_operand" "rIK")
2134                          (const_int 0)))
2135    (clobber (reg:CC CC_REGNUM))]
2136   "TARGET_ARM
2137    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2138        && INTVAL (operands[2]) > 0 
2139        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2140        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2141    && !reg_overlap_mentioned_p (operands[0], operands[4])"
2142   "#"
2143   "TARGET_ARM
2144    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2145        && INTVAL (operands[2]) > 0 
2146        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2147        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2148    && !reg_overlap_mentioned_p (operands[0], operands[4])"
2149   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2150                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2151                                     (const_int 0)))
2152               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2153    (set (match_dup 0)
2154         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2155                          (match_dup 0) (match_dup 4)))]
2156   "
2157   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2158                          << INTVAL (operands[3])); 
2159   "
2160   [(set_attr "conds" "clob")
2161    (set_attr "length" "8")]
2162 )
2163
2164 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2165   [(set (match_operand:SI 0 "s_register_operand" "=r")
2166         (if_then_else:SI (ne (zero_extract:SI
2167                               (match_operand:SI 1 "s_register_operand" "r")
2168                               (match_operand:SI 2 "const_int_operand" "n")
2169                               (const_int 0))
2170                              (const_int 0))
2171                          (match_operand:SI 3 "arm_not_operand" "rIK")
2172                          (const_int 0)))
2173    (clobber (reg:CC CC_REGNUM))]
2174   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2175   "#"
2176   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2177   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2178                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2179                                     (const_int 0)))
2180               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2181    (set (match_dup 0)
2182         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2183                          (match_dup 0) (match_dup 3)))]
2184   "
2185   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2186   "
2187   [(set_attr "conds" "clob")
2188    (set_attr "length" "8")]
2189 )
2190
2191 (define_split
2192   [(set (match_operand:SI 0 "s_register_operand" "")
2193         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
2194                          (match_operand:SI 2 "const_int_operand" "")
2195                          (match_operand:SI 3 "const_int_operand" "")))
2196    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2197   "TARGET_THUMB1"
2198   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
2199    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
2200   "{
2201      HOST_WIDE_INT temp = INTVAL (operands[2]);
2202
2203      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2204      operands[3] = GEN_INT (32 - temp);
2205    }"
2206 )
2207
2208 ;; ??? Use Thumb-2 has bitfield insert/extract instructions.
2209 (define_split
2210   [(set (match_operand:SI 0 "s_register_operand" "")
2211         (match_operator:SI 1 "shiftable_operator"
2212          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2213                            (match_operand:SI 3 "const_int_operand" "")
2214                            (match_operand:SI 4 "const_int_operand" ""))
2215           (match_operand:SI 5 "s_register_operand" "")]))
2216    (clobber (match_operand:SI 6 "s_register_operand" ""))]
2217   "TARGET_ARM"
2218   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2219    (set (match_dup 0)
2220         (match_op_dup 1
2221          [(lshiftrt:SI (match_dup 6) (match_dup 4))
2222           (match_dup 5)]))]
2223   "{
2224      HOST_WIDE_INT temp = INTVAL (operands[3]);
2225
2226      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2227      operands[4] = GEN_INT (32 - temp);
2228    }"
2229 )
2230   
2231 (define_split
2232   [(set (match_operand:SI 0 "s_register_operand" "")
2233         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2234                          (match_operand:SI 2 "const_int_operand" "")
2235                          (match_operand:SI 3 "const_int_operand" "")))]
2236   "TARGET_THUMB1"
2237   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2238    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2239   "{
2240      HOST_WIDE_INT temp = INTVAL (operands[2]);
2241
2242      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2243      operands[3] = GEN_INT (32 - temp);
2244    }"
2245 )
2246
2247 (define_split
2248   [(set (match_operand:SI 0 "s_register_operand" "")
2249         (match_operator:SI 1 "shiftable_operator"
2250          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2251                            (match_operand:SI 3 "const_int_operand" "")
2252                            (match_operand:SI 4 "const_int_operand" ""))
2253           (match_operand:SI 5 "s_register_operand" "")]))
2254    (clobber (match_operand:SI 6 "s_register_operand" ""))]
2255   "TARGET_ARM"
2256   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2257    (set (match_dup 0)
2258         (match_op_dup 1
2259          [(ashiftrt:SI (match_dup 6) (match_dup 4))
2260           (match_dup 5)]))]
2261   "{
2262      HOST_WIDE_INT temp = INTVAL (operands[3]);
2263
2264      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2265      operands[4] = GEN_INT (32 - temp);
2266    }"
2267 )
2268   
2269 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
2270 ;;; represented by the bitfield, then this will produce incorrect results.
2271 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
2272 ;;; which have a real bit-field insert instruction, the truncation happens
2273 ;;; in the bit-field insert instruction itself.  Since arm does not have a
2274 ;;; bit-field insert instruction, we would have to emit code here to truncate
2275 ;;; the value before we insert.  This loses some of the advantage of having
2276 ;;; this insv pattern, so this pattern needs to be reevalutated.
2277
2278 (define_expand "insv"
2279   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
2280                          (match_operand:SI 1 "general_operand" "")
2281                          (match_operand:SI 2 "general_operand" ""))
2282         (match_operand:SI 3 "reg_or_int_operand" ""))]
2283   "TARGET_ARM || arm_arch_thumb2"
2284   "
2285   {
2286     int start_bit = INTVAL (operands[2]);
2287     int width = INTVAL (operands[1]);
2288     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2289     rtx target, subtarget;
2290
2291     if (arm_arch_thumb2)
2292       {
2293         bool use_bfi = TRUE;
2294
2295         if (GET_CODE (operands[3]) == CONST_INT)
2296           {
2297             HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2298
2299             if (val == 0)
2300               {
2301                 emit_insn (gen_insv_zero (operands[0], operands[1],
2302                                           operands[2]));
2303                 DONE;
2304               }
2305
2306             /* See if the set can be done with a single orr instruction.  */
2307             if (val == mask && const_ok_for_arm (val << start_bit))
2308               use_bfi = FALSE;
2309           }
2310           
2311         if (use_bfi)
2312           {
2313             if (GET_CODE (operands[3]) != REG)
2314               operands[3] = force_reg (SImode, operands[3]);
2315
2316             emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2317                                     operands[3]));
2318             DONE;
2319           }
2320       }
2321
2322     target = copy_rtx (operands[0]);
2323     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
2324        subreg as the final target.  */
2325     if (GET_CODE (target) == SUBREG)
2326       {
2327         subtarget = gen_reg_rtx (SImode);
2328         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2329             < GET_MODE_SIZE (SImode))
2330           target = SUBREG_REG (target);
2331       }
2332     else
2333       subtarget = target;    
2334
2335     if (GET_CODE (operands[3]) == CONST_INT)
2336       {
2337         /* Since we are inserting a known constant, we may be able to
2338            reduce the number of bits that we have to clear so that
2339            the mask becomes simple.  */
2340         /* ??? This code does not check to see if the new mask is actually
2341            simpler.  It may not be.  */
2342         rtx op1 = gen_reg_rtx (SImode);
2343         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
2344            start of this pattern.  */
2345         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2346         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2347
2348         emit_insn (gen_andsi3 (op1, operands[0],
2349                                gen_int_mode (~mask2, SImode)));
2350         emit_insn (gen_iorsi3 (subtarget, op1,
2351                                gen_int_mode (op3_value << start_bit, SImode)));
2352       }
2353     else if (start_bit == 0
2354              && !(const_ok_for_arm (mask)
2355                   || const_ok_for_arm (~mask)))
2356       {
2357         /* A Trick, since we are setting the bottom bits in the word,
2358            we can shift operand[3] up, operand[0] down, OR them together
2359            and rotate the result back again.  This takes 3 insns, and
2360            the third might be mergeable into another op.  */
2361         /* The shift up copes with the possibility that operand[3] is
2362            wider than the bitfield.  */
2363         rtx op0 = gen_reg_rtx (SImode);
2364         rtx op1 = gen_reg_rtx (SImode);
2365
2366         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2367         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2368         emit_insn (gen_iorsi3  (op1, op1, op0));
2369         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2370       }
2371     else if ((width + start_bit == 32)
2372              && !(const_ok_for_arm (mask)
2373                   || const_ok_for_arm (~mask)))
2374       {
2375         /* Similar trick, but slightly less efficient.  */
2376
2377         rtx op0 = gen_reg_rtx (SImode);
2378         rtx op1 = gen_reg_rtx (SImode);
2379
2380         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2381         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2382         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2383         emit_insn (gen_iorsi3 (subtarget, op1, op0));
2384       }
2385     else
2386       {
2387         rtx op0 = gen_int_mode (mask, SImode);
2388         rtx op1 = gen_reg_rtx (SImode);
2389         rtx op2 = gen_reg_rtx (SImode);
2390
2391         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2392           {
2393             rtx tmp = gen_reg_rtx (SImode);
2394
2395             emit_insn (gen_movsi (tmp, op0));
2396             op0 = tmp;
2397           }
2398
2399         /* Mask out any bits in operand[3] that are not needed.  */
2400            emit_insn (gen_andsi3 (op1, operands[3], op0));
2401
2402         if (GET_CODE (op0) == CONST_INT
2403             && (const_ok_for_arm (mask << start_bit)
2404                 || const_ok_for_arm (~(mask << start_bit))))
2405           {
2406             op0 = gen_int_mode (~(mask << start_bit), SImode);
2407             emit_insn (gen_andsi3 (op2, operands[0], op0));
2408           }
2409         else
2410           {
2411             if (GET_CODE (op0) == CONST_INT)
2412               {
2413                 rtx tmp = gen_reg_rtx (SImode);
2414
2415                 emit_insn (gen_movsi (tmp, op0));
2416                 op0 = tmp;
2417               }
2418
2419             if (start_bit != 0)
2420               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
2421             
2422             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2423           }
2424
2425         if (start_bit != 0)
2426           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
2427
2428         emit_insn (gen_iorsi3 (subtarget, op1, op2));
2429       }
2430
2431     if (subtarget != target)
2432       {
2433         /* If TARGET is still a SUBREG, then it must be wider than a word,
2434            so we must be careful only to set the subword we were asked to.  */
2435         if (GET_CODE (target) == SUBREG)
2436           emit_move_insn (target, subtarget);
2437         else
2438           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2439       }
2440
2441     DONE;
2442   }"
2443 )
2444
2445 (define_insn "insv_zero"
2446   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2447                          (match_operand:SI 1 "const_int_operand" "M")
2448                          (match_operand:SI 2 "const_int_operand" "M"))
2449         (const_int 0))]
2450   "arm_arch_thumb2"
2451   "bfc%?\t%0, %2, %1"
2452   [(set_attr "length" "4")
2453    (set_attr "predicable" "yes")]
2454 )
2455
2456 (define_insn "insv_t2"
2457   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2458                          (match_operand:SI 1 "const_int_operand" "M")
2459                          (match_operand:SI 2 "const_int_operand" "M"))
2460         (match_operand:SI 3 "s_register_operand" "r"))]
2461   "arm_arch_thumb2"
2462   "bfi%?\t%0, %3, %2, %1"
2463   [(set_attr "length" "4")
2464    (set_attr "predicable" "yes")]
2465 )
2466
2467 ; constants for op 2 will never be given to these patterns.
2468 (define_insn_and_split "*anddi_notdi_di"
2469   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2470         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2471                 (match_operand:DI 2 "s_register_operand" "r,0")))]
2472   "TARGET_32BIT"
2473   "#"
2474   "TARGET_32BIT && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2475   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2476    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2477   "
2478   {
2479     operands[3] = gen_highpart (SImode, operands[0]);
2480     operands[0] = gen_lowpart (SImode, operands[0]);
2481     operands[4] = gen_highpart (SImode, operands[1]);
2482     operands[1] = gen_lowpart (SImode, operands[1]);
2483     operands[5] = gen_highpart (SImode, operands[2]);
2484     operands[2] = gen_lowpart (SImode, operands[2]);
2485   }"
2486   [(set_attr "length" "8")
2487    (set_attr "predicable" "yes")]
2488 )
2489   
2490 (define_insn_and_split "*anddi_notzesidi_di"
2491   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2492         (and:DI (not:DI (zero_extend:DI
2493                          (match_operand:SI 2 "s_register_operand" "r,r")))
2494                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2495   "TARGET_32BIT"
2496   "@
2497    bic%?\\t%Q0, %Q1, %2
2498    #"
2499   ; (not (zero_extend ...)) allows us to just copy the high word from
2500   ; operand1 to operand0.
2501   "TARGET_32BIT
2502    && reload_completed
2503    && operands[0] != operands[1]"
2504   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2505    (set (match_dup 3) (match_dup 4))]
2506   "
2507   {
2508     operands[3] = gen_highpart (SImode, operands[0]);
2509     operands[0] = gen_lowpart (SImode, operands[0]);
2510     operands[4] = gen_highpart (SImode, operands[1]);
2511     operands[1] = gen_lowpart (SImode, operands[1]);
2512   }"
2513   [(set_attr "length" "4,8")
2514    (set_attr "predicable" "yes")]
2515 )
2516   
2517 (define_insn_and_split "*anddi_notsesidi_di"
2518   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2519         (and:DI (not:DI (sign_extend:DI
2520                          (match_operand:SI 2 "s_register_operand" "r,r")))
2521                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2522   "TARGET_32BIT"
2523   "#"
2524   "TARGET_32BIT && reload_completed"
2525   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2526    (set (match_dup 3) (and:SI (not:SI
2527                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2528                                (match_dup 4)))]
2529   "
2530   {
2531     operands[3] = gen_highpart (SImode, operands[0]);
2532     operands[0] = gen_lowpart (SImode, operands[0]);
2533     operands[4] = gen_highpart (SImode, operands[1]);
2534     operands[1] = gen_lowpart (SImode, operands[1]);
2535   }"
2536   [(set_attr "length" "8")
2537    (set_attr "predicable" "yes")]
2538 )
2539   
2540 (define_insn "andsi_notsi_si"
2541   [(set (match_operand:SI 0 "s_register_operand" "=r")
2542         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2543                 (match_operand:SI 1 "s_register_operand" "r")))]
2544   "TARGET_32BIT"
2545   "bic%?\\t%0, %1, %2"
2546   [(set_attr "predicable" "yes")]
2547 )
2548
2549 (define_insn "bicsi3"
2550   [(set (match_operand:SI                 0 "register_operand" "=l")
2551         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2552                 (match_operand:SI         2 "register_operand" "0")))]
2553   "TARGET_THUMB1"
2554   "bic\\t%0, %0, %1"
2555   [(set_attr "length" "2")]
2556 )
2557
2558 (define_insn "andsi_not_shiftsi_si"
2559   [(set (match_operand:SI 0 "s_register_operand" "=r")
2560         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2561                          [(match_operand:SI 2 "s_register_operand" "r")
2562                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2563                 (match_operand:SI 1 "s_register_operand" "r")))]
2564   "TARGET_ARM"
2565   "bic%?\\t%0, %1, %2%S4"
2566   [(set_attr "predicable" "yes")
2567    (set_attr "shift" "2")
2568    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2569                       (const_string "alu_shift")
2570                       (const_string "alu_shift_reg")))]
2571 )
2572
2573 (define_insn "*andsi_notsi_si_compare0"
2574   [(set (reg:CC_NOOV CC_REGNUM)
2575         (compare:CC_NOOV
2576          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2577                  (match_operand:SI 1 "s_register_operand" "r"))
2578          (const_int 0)))
2579    (set (match_operand:SI 0 "s_register_operand" "=r")
2580         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2581   "TARGET_32BIT"
2582   "bic%.\\t%0, %1, %2"
2583   [(set_attr "conds" "set")]
2584 )
2585
2586 (define_insn "*andsi_notsi_si_compare0_scratch"
2587   [(set (reg:CC_NOOV CC_REGNUM)
2588         (compare:CC_NOOV
2589          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2590                  (match_operand:SI 1 "s_register_operand" "r"))
2591          (const_int 0)))
2592    (clobber (match_scratch:SI 0 "=r"))]
2593   "TARGET_32BIT"
2594   "bic%.\\t%0, %1, %2"
2595   [(set_attr "conds" "set")]
2596 )
2597
2598 (define_insn "iordi3"
2599   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2600         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2601                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2602   "TARGET_32BIT && ! TARGET_IWMMXT"
2603   "#"
2604   [(set_attr "length" "8")
2605    (set_attr "predicable" "yes")]
2606 )
2607
2608 (define_insn "*iordi_zesidi_di"
2609   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2610         (ior:DI (zero_extend:DI
2611                  (match_operand:SI 2 "s_register_operand" "r,r"))
2612                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2613   "TARGET_32BIT"
2614   "@
2615    orr%?\\t%Q0, %Q1, %2
2616    #"
2617   [(set_attr "length" "4,8")
2618    (set_attr "predicable" "yes")]
2619 )
2620
2621 (define_insn "*iordi_sesidi_di"
2622   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2623         (ior:DI (sign_extend:DI
2624                  (match_operand:SI 2 "s_register_operand" "r,r"))
2625                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2626   "TARGET_32BIT"
2627   "#"
2628   [(set_attr "length" "8")
2629    (set_attr "predicable" "yes")]
2630 )
2631
2632 (define_expand "iorsi3"
2633   [(set (match_operand:SI         0 "s_register_operand" "")
2634         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2635                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2636   "TARGET_EITHER"
2637   "
2638   if (GET_CODE (operands[2]) == CONST_INT)
2639     {
2640       if (TARGET_32BIT)
2641         {
2642           arm_split_constant (IOR, SImode, NULL_RTX,
2643                               INTVAL (operands[2]), operands[0], operands[1],
2644                               optimize && can_create_pseudo_p ());
2645           DONE;
2646         }
2647       else /* TARGET_THUMB1 */
2648         {
2649           rtx tmp = force_reg (SImode, operands[2]);
2650           if (rtx_equal_p (operands[0], operands[1]))
2651             operands[2] = tmp;
2652           else
2653             {
2654               operands[2] = operands[1];
2655               operands[1] = tmp;
2656             }
2657         }
2658     }
2659   "
2660 )
2661
2662 (define_insn_and_split "*arm_iorsi3"
2663   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2664         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2665                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2666   "TARGET_ARM"
2667   "@
2668    orr%?\\t%0, %1, %2
2669    #"
2670   "TARGET_ARM
2671    && GET_CODE (operands[2]) == CONST_INT
2672    && !const_ok_for_arm (INTVAL (operands[2]))"
2673   [(clobber (const_int 0))]
2674   "
2675   arm_split_constant (IOR, SImode, curr_insn, 
2676                       INTVAL (operands[2]), operands[0], operands[1], 0);
2677   DONE;
2678   "
2679   [(set_attr "length" "4,16")
2680    (set_attr "predicable" "yes")]
2681 )
2682
2683 (define_insn "*thumb1_iorsi3"
2684   [(set (match_operand:SI         0 "register_operand" "=l")
2685         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2686                 (match_operand:SI 2 "register_operand" "l")))]
2687   "TARGET_THUMB1"
2688   "orr\\t%0, %0, %2"
2689   [(set_attr "length" "2")]
2690 )
2691
2692 (define_peephole2
2693   [(match_scratch:SI 3 "r")
2694    (set (match_operand:SI 0 "arm_general_register_operand" "")
2695         (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2696                 (match_operand:SI 2 "const_int_operand" "")))]
2697   "TARGET_ARM
2698    && !const_ok_for_arm (INTVAL (operands[2]))
2699    && const_ok_for_arm (~INTVAL (operands[2]))"
2700   [(set (match_dup 3) (match_dup 2))
2701    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2702   ""
2703 )
2704
2705 (define_insn "*iorsi3_compare0"
2706   [(set (reg:CC_NOOV CC_REGNUM)
2707         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2708                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2709                          (const_int 0)))
2710    (set (match_operand:SI 0 "s_register_operand" "=r")
2711         (ior:SI (match_dup 1) (match_dup 2)))]
2712   "TARGET_32BIT"
2713   "orr%.\\t%0, %1, %2"
2714   [(set_attr "conds" "set")]
2715 )
2716
2717 (define_insn "*iorsi3_compare0_scratch"
2718   [(set (reg:CC_NOOV CC_REGNUM)
2719         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2720                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2721                          (const_int 0)))
2722    (clobber (match_scratch:SI 0 "=r"))]
2723   "TARGET_32BIT"
2724   "orr%.\\t%0, %1, %2"
2725   [(set_attr "conds" "set")]
2726 )
2727
2728 (define_insn "xordi3"
2729   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2730         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2731                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2732   "TARGET_32BIT && !TARGET_IWMMXT"
2733   "#"
2734   [(set_attr "length" "8")
2735    (set_attr "predicable" "yes")]
2736 )
2737
2738 (define_insn "*xordi_zesidi_di"
2739   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2740         (xor:DI (zero_extend:DI
2741                  (match_operand:SI 2 "s_register_operand" "r,r"))
2742                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2743   "TARGET_32BIT"
2744   "@
2745    eor%?\\t%Q0, %Q1, %2
2746    #"
2747   [(set_attr "length" "4,8")
2748    (set_attr "predicable" "yes")]
2749 )
2750
2751 (define_insn "*xordi_sesidi_di"
2752   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2753         (xor:DI (sign_extend:DI
2754                  (match_operand:SI 2 "s_register_operand" "r,r"))
2755                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2756   "TARGET_32BIT"
2757   "#"
2758   [(set_attr "length" "8")
2759    (set_attr "predicable" "yes")]
2760 )
2761
2762 (define_expand "xorsi3"
2763   [(set (match_operand:SI         0 "s_register_operand" "")
2764         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2765                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2766   "TARGET_EITHER"
2767   "if (GET_CODE (operands[2]) == CONST_INT)
2768     {
2769       if (TARGET_32BIT)
2770         {
2771           arm_split_constant (XOR, SImode, NULL_RTX,
2772                               INTVAL (operands[2]), operands[0], operands[1],
2773                               optimize && can_create_pseudo_p ());
2774           DONE;
2775         }
2776       else /* TARGET_THUMB1 */
2777         {
2778           rtx tmp = force_reg (SImode, operands[2]);
2779           if (rtx_equal_p (operands[0], operands[1]))
2780             operands[2] = tmp;
2781           else
2782             {
2783               operands[2] = operands[1];
2784               operands[1] = tmp;
2785             }
2786         }
2787     }"
2788 )
2789
2790 (define_insn "*arm_xorsi3"
2791   [(set (match_operand:SI         0 "s_register_operand" "=r")
2792         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2793                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2794   "TARGET_32BIT"
2795   "eor%?\\t%0, %1, %2"
2796   [(set_attr "predicable" "yes")]
2797 )
2798
2799 (define_insn "*thumb1_xorsi3"
2800   [(set (match_operand:SI         0 "register_operand" "=l")
2801         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2802                 (match_operand:SI 2 "register_operand" "l")))]
2803   "TARGET_THUMB1"
2804   "eor\\t%0, %0, %2"
2805   [(set_attr "length" "2")]
2806 )
2807
2808 (define_insn "*xorsi3_compare0"
2809   [(set (reg:CC_NOOV CC_REGNUM)
2810         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2811                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2812                          (const_int 0)))
2813    (set (match_operand:SI 0 "s_register_operand" "=r")
2814         (xor:SI (match_dup 1) (match_dup 2)))]
2815   "TARGET_32BIT"
2816   "eor%.\\t%0, %1, %2"
2817   [(set_attr "conds" "set")]
2818 )
2819
2820 (define_insn "*xorsi3_compare0_scratch"
2821   [(set (reg:CC_NOOV CC_REGNUM)
2822         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2823                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2824                          (const_int 0)))]
2825   "TARGET_32BIT"
2826   "teq%?\\t%0, %1"
2827   [(set_attr "conds" "set")]
2828 )
2829
2830 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2831 ; (NOT D) we can sometimes merge the final NOT into one of the following
2832 ; insns.
2833
2834 (define_split
2835   [(set (match_operand:SI 0 "s_register_operand" "")
2836         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2837                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2838                 (match_operand:SI 3 "arm_rhs_operand" "")))
2839    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2840   "TARGET_32BIT"
2841   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2842                               (not:SI (match_dup 3))))
2843    (set (match_dup 0) (not:SI (match_dup 4)))]
2844   ""
2845 )
2846
2847 (define_insn "*andsi_iorsi3_notsi"
2848   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2849         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
2850                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2851                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2852   "TARGET_32BIT"
2853   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2854   [(set_attr "length" "8")
2855    (set_attr "ce_count" "2")
2856    (set_attr "predicable" "yes")]
2857 )
2858
2859 ; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
2860 ; insns are available?
2861 (define_split
2862   [(set (match_operand:SI 0 "s_register_operand" "")
2863         (match_operator:SI 1 "logical_binary_operator"
2864          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2865                            (match_operand:SI 3 "const_int_operand" "")
2866                            (match_operand:SI 4 "const_int_operand" ""))
2867           (match_operator:SI 9 "logical_binary_operator"
2868            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2869                          (match_operand:SI 6 "const_int_operand" ""))
2870             (match_operand:SI 7 "s_register_operand" "")])]))
2871    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2872   "TARGET_32BIT
2873    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2874    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2875   [(set (match_dup 8)
2876         (match_op_dup 1
2877          [(ashift:SI (match_dup 2) (match_dup 4))
2878           (match_dup 5)]))
2879    (set (match_dup 0)
2880         (match_op_dup 1
2881          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2882           (match_dup 7)]))]
2883   "
2884   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2885 ")
2886
2887 (define_split
2888   [(set (match_operand:SI 0 "s_register_operand" "")
2889         (match_operator:SI 1 "logical_binary_operator"
2890          [(match_operator:SI 9 "logical_binary_operator"
2891            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2892                          (match_operand:SI 6 "const_int_operand" ""))
2893             (match_operand:SI 7 "s_register_operand" "")])
2894           (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2895                            (match_operand:SI 3 "const_int_operand" "")
2896                            (match_operand:SI 4 "const_int_operand" ""))]))
2897    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2898   "TARGET_32BIT
2899    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2900    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2901   [(set (match_dup 8)
2902         (match_op_dup 1
2903          [(ashift:SI (match_dup 2) (match_dup 4))
2904           (match_dup 5)]))
2905    (set (match_dup 0)
2906         (match_op_dup 1
2907          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2908           (match_dup 7)]))]
2909   "
2910   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2911 ")
2912
2913 (define_split
2914   [(set (match_operand:SI 0 "s_register_operand" "")
2915         (match_operator:SI 1 "logical_binary_operator"
2916          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2917                            (match_operand:SI 3 "const_int_operand" "")
2918                            (match_operand:SI 4 "const_int_operand" ""))
2919           (match_operator:SI 9 "logical_binary_operator"
2920            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2921                          (match_operand:SI 6 "const_int_operand" ""))
2922             (match_operand:SI 7 "s_register_operand" "")])]))
2923    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2924   "TARGET_32BIT
2925    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2926    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2927   [(set (match_dup 8)
2928         (match_op_dup 1
2929          [(ashift:SI (match_dup 2) (match_dup 4))
2930           (match_dup 5)]))
2931    (set (match_dup 0)
2932         (match_op_dup 1
2933          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2934           (match_dup 7)]))]
2935   "
2936   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2937 ")
2938
2939 (define_split
2940   [(set (match_operand:SI 0 "s_register_operand" "")
2941         (match_operator:SI 1 "logical_binary_operator"
2942          [(match_operator:SI 9 "logical_binary_operator"
2943            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2944                          (match_operand:SI 6 "const_int_operand" ""))
2945             (match_operand:SI 7 "s_register_operand" "")])
2946           (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2947                            (match_operand:SI 3 "const_int_operand" "")
2948                            (match_operand:SI 4 "const_int_operand" ""))]))
2949    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2950   "TARGET_32BIT
2951    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2952    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2953   [(set (match_dup 8)
2954         (match_op_dup 1
2955          [(ashift:SI (match_dup 2) (match_dup 4))
2956           (match_dup 5)]))
2957    (set (match_dup 0)
2958         (match_op_dup 1
2959          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2960           (match_dup 7)]))]
2961   "
2962   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2963 ")
2964 \f
2965
2966 ;; Minimum and maximum insns
2967
2968 (define_expand "smaxsi3"
2969   [(parallel [
2970     (set (match_operand:SI 0 "s_register_operand" "")
2971          (smax:SI (match_operand:SI 1 "s_register_operand" "")
2972                   (match_operand:SI 2 "arm_rhs_operand" "")))
2973     (clobber (reg:CC CC_REGNUM))])]
2974   "TARGET_32BIT"
2975   "
2976   if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
2977     {
2978       /* No need for a clobber of the condition code register here.  */
2979       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2980                               gen_rtx_SMAX (SImode, operands[1],
2981                                             operands[2])));
2982       DONE;
2983     }
2984 ")
2985
2986 (define_insn "*smax_0"
2987   [(set (match_operand:SI 0 "s_register_operand" "=r")
2988         (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2989                  (const_int 0)))]
2990   "TARGET_32BIT"
2991   "bic%?\\t%0, %1, %1, asr #31"
2992   [(set_attr "predicable" "yes")]
2993 )
2994
2995 (define_insn "*smax_m1"
2996   [(set (match_operand:SI 0 "s_register_operand" "=r")
2997         (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2998                  (const_int -1)))]
2999   "TARGET_32BIT"
3000   "orr%?\\t%0, %1, %1, asr #31"
3001   [(set_attr "predicable" "yes")]
3002 )
3003
3004 (define_insn "*arm_smax_insn"
3005   [(set (match_operand:SI          0 "s_register_operand" "=r,r")
3006         (smax:SI (match_operand:SI 1 "s_register_operand"  "%0,?r")
3007                  (match_operand:SI 2 "arm_rhs_operand"    "rI,rI")))
3008    (clobber (reg:CC CC_REGNUM))]
3009   "TARGET_ARM"
3010   "@
3011    cmp\\t%1, %2\;movlt\\t%0, %2
3012    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
3013   [(set_attr "conds" "clob")
3014    (set_attr "length" "8,12")]
3015 )
3016
3017 (define_expand "sminsi3"
3018   [(parallel [
3019     (set (match_operand:SI 0 "s_register_operand" "")
3020          (smin:SI (match_operand:SI 1 "s_register_operand" "")
3021                   (match_operand:SI 2 "arm_rhs_operand" "")))
3022     (clobber (reg:CC CC_REGNUM))])]
3023   "TARGET_32BIT"
3024   "
3025   if (operands[2] == const0_rtx)
3026     {
3027       /* No need for a clobber of the condition code register here.  */
3028       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3029                               gen_rtx_SMIN (SImode, operands[1],
3030                                             operands[2])));
3031       DONE;
3032     }
3033 ")
3034
3035 (define_insn "*smin_0"
3036   [(set (match_operand:SI 0 "s_register_operand" "=r")
3037         (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3038                  (const_int 0)))]
3039   "TARGET_32BIT"
3040   "and%?\\t%0, %1, %1, asr #31"
3041   [(set_attr "predicable" "yes")]
3042 )
3043
3044 (define_insn "*arm_smin_insn"
3045   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3046         (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3047                  (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
3048    (clobber (reg:CC CC_REGNUM))]
3049   "TARGET_ARM"
3050   "@
3051    cmp\\t%1, %2\;movge\\t%0, %2
3052    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
3053   [(set_attr "conds" "clob")
3054    (set_attr "length" "8,12")]
3055 )
3056
3057 (define_expand "umaxsi3"
3058   [(parallel [
3059     (set (match_operand:SI 0 "s_register_operand" "")
3060          (umax:SI (match_operand:SI 1 "s_register_operand" "")
3061                   (match_operand:SI 2 "arm_rhs_operand" "")))
3062     (clobber (reg:CC CC_REGNUM))])]
3063   "TARGET_32BIT"
3064   ""
3065 )
3066
3067 (define_insn "*arm_umaxsi3"
3068   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3069         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3070                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
3071    (clobber (reg:CC CC_REGNUM))]
3072   "TARGET_ARM"
3073   "@
3074    cmp\\t%1, %2\;movcc\\t%0, %2
3075    cmp\\t%1, %2\;movcs\\t%0, %1
3076    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
3077   [(set_attr "conds" "clob")
3078    (set_attr "length" "8,8,12")]
3079 )
3080
3081 (define_expand "uminsi3"
3082   [(parallel [
3083     (set (match_operand:SI 0 "s_register_operand" "")
3084          (umin:SI (match_operand:SI 1 "s_register_operand" "")
3085                   (match_operand:SI 2 "arm_rhs_operand" "")))
3086     (clobber (reg:CC CC_REGNUM))])]
3087   "TARGET_32BIT"
3088   ""
3089 )
3090
3091 (define_insn "*arm_uminsi3"
3092   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3093         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3094                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
3095    (clobber (reg:CC CC_REGNUM))]
3096   "TARGET_ARM"
3097   "@
3098    cmp\\t%1, %2\;movcs\\t%0, %2
3099    cmp\\t%1, %2\;movcc\\t%0, %1
3100    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
3101   [(set_attr "conds" "clob")
3102    (set_attr "length" "8,8,12")]
3103 )
3104
3105 (define_insn "*store_minmaxsi"
3106   [(set (match_operand:SI 0 "memory_operand" "=m")
3107         (match_operator:SI 3 "minmax_operator"
3108          [(match_operand:SI 1 "s_register_operand" "r")
3109           (match_operand:SI 2 "s_register_operand" "r")]))
3110    (clobber (reg:CC CC_REGNUM))]
3111   "TARGET_32BIT"
3112   "*
3113   operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3114                                 operands[1], operands[2]);
3115   output_asm_insn (\"cmp\\t%1, %2\", operands);
3116   if (TARGET_THUMB2)
3117     output_asm_insn (\"ite\t%d3\", operands);
3118   output_asm_insn (\"str%d3\\t%1, %0\", operands);
3119   output_asm_insn (\"str%D3\\t%2, %0\", operands);
3120   return \"\";
3121   "
3122   [(set_attr "conds" "clob")
3123    (set (attr "length")
3124         (if_then_else (eq_attr "is_thumb" "yes")
3125                       (const_int 14)
3126                       (const_int 12)))
3127    (set_attr "type" "store1")]
3128 )
3129
3130 ; Reject the frame pointer in operand[1], since reloading this after
3131 ; it has been eliminated can cause carnage.
3132 (define_insn "*minmax_arithsi"
3133   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3134         (match_operator:SI 4 "shiftable_operator"
3135          [(match_operator:SI 5 "minmax_operator"
3136            [(match_operand:SI 2 "s_register_operand" "r,r")
3137             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3138           (match_operand:SI 1 "s_register_operand" "0,?r")]))
3139    (clobber (reg:CC CC_REGNUM))]
3140   "TARGET_32BIT && !arm_eliminable_register (operands[1])"
3141   "*
3142   {
3143     enum rtx_code code = GET_CODE (operands[4]);
3144     bool need_else;
3145
3146     if (which_alternative != 0 || operands[3] != const0_rtx
3147         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
3148       need_else = true;
3149     else
3150       need_else = false;
3151
3152     operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3153                                   operands[2], operands[3]);
3154     output_asm_insn (\"cmp\\t%2, %3\", operands);
3155     if (TARGET_THUMB2)
3156       {
3157         if (need_else)
3158           output_asm_insn (\"ite\\t%d5\", operands);
3159         else
3160           output_asm_insn (\"it\\t%d5\", operands);
3161       }
3162     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
3163     if (need_else)
3164       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3165     return \"\";
3166   }"
3167   [(set_attr "conds" "clob")
3168    (set (attr "length")
3169         (if_then_else (eq_attr "is_thumb" "yes")
3170                       (const_int 14)
3171                       (const_int 12)))]
3172 )
3173
3174 \f
3175 ;; Shift and rotation insns
3176
3177 (define_expand "ashldi3"
3178   [(set (match_operand:DI            0 "s_register_operand" "")
3179         (ashift:DI (match_operand:DI 1 "s_register_operand" "")
3180                    (match_operand:SI 2 "reg_or_int_operand" "")))]
3181   "TARGET_32BIT"
3182   "
3183   if (GET_CODE (operands[2]) == CONST_INT)
3184     {
3185       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3186         {
3187           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3188           DONE;
3189         }
3190         /* Ideally we shouldn't fail here if we could know that operands[1] 
3191            ends up already living in an iwmmxt register. Otherwise it's
3192            cheaper to have the alternate code being generated than moving
3193            values to iwmmxt regs and back.  */
3194         FAIL;
3195     }
3196   else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
3197     FAIL;
3198   "
3199 )
3200
3201 (define_insn "arm_ashldi3_1bit"
3202   [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
3203         (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
3204                    (const_int 1)))
3205    (clobber (reg:CC CC_REGNUM))]
3206   "TARGET_32BIT"
3207   "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
3208   [(set_attr "conds" "clob")
3209    (set_attr "length" "8")]
3210 )
3211
3212 (define_expand "ashlsi3"
3213   [(set (match_operand:SI            0 "s_register_operand" "")
3214         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3215                    (match_operand:SI 2 "arm_rhs_operand" "")))]
3216   "TARGET_EITHER"
3217   "
3218   if (GET_CODE (operands[2]) == CONST_INT
3219       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3220     {
3221       emit_insn (gen_movsi (operands[0], const0_rtx));
3222       DONE;
3223     }
3224   "
3225 )
3226
3227 (define_insn "*thumb1_ashlsi3"
3228   [(set (match_operand:SI            0 "register_operand" "=l,l")
3229         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
3230                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
3231   "TARGET_THUMB1"
3232   "lsl\\t%0, %1, %2"
3233   [(set_attr "length" "2")]
3234 )
3235
3236 (define_expand "ashrdi3"
3237   [(set (match_operand:DI              0 "s_register_operand" "")
3238         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3239                      (match_operand:SI 2 "reg_or_int_operand" "")))]
3240   "TARGET_32BIT"
3241   "
3242   if (GET_CODE (operands[2]) == CONST_INT)
3243     {
3244       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3245         {
3246           emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3247           DONE;
3248         }
3249         /* Ideally we shouldn't fail here if we could know that operands[1] 
3250            ends up already living in an iwmmxt register. Otherwise it's
3251            cheaper to have the alternate code being generated than moving
3252            values to iwmmxt regs and back.  */
3253         FAIL;
3254     }
3255   else if (!TARGET_REALLY_IWMMXT)
3256     FAIL;
3257   "
3258 )
3259
3260 (define_insn "arm_ashrdi3_1bit"
3261   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
3262         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
3263                      (const_int 1)))
3264    (clobber (reg:CC CC_REGNUM))]
3265   "TARGET_32BIT"
3266   "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
3267   [(set_attr "conds" "clob")
3268    (set_attr "length" "8")]
3269 )
3270
3271 (define_expand "ashrsi3"
3272   [(set (match_operand:SI              0 "s_register_operand" "")
3273         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3274                      (match_operand:SI 2 "arm_rhs_operand" "")))]
3275   "TARGET_EITHER"
3276   "
3277   if (GET_CODE (operands[2]) == CONST_INT
3278       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3279     operands[2] = GEN_INT (31);
3280   "
3281 )
3282
3283 (define_insn "*thumb1_ashrsi3"
3284   [(set (match_operand:SI              0 "register_operand" "=l,l")
3285         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3286                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
3287   "TARGET_THUMB1"
3288   "asr\\t%0, %1, %2"
3289   [(set_attr "length" "2")]
3290 )
3291
3292 (define_expand "lshrdi3"
3293   [(set (match_operand:DI              0 "s_register_operand" "")
3294         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3295                      (match_operand:SI 2 "reg_or_int_operand" "")))]
3296   "TARGET_32BIT"
3297   "
3298   if (GET_CODE (operands[2]) == CONST_INT)
3299     {
3300       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3301         {
3302           emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3303           DONE;
3304         }
3305         /* Ideally we shouldn't fail here if we could know that operands[1] 
3306            ends up already living in an iwmmxt register. Otherwise it's
3307            cheaper to have the alternate code being generated than moving
3308            values to iwmmxt regs and back.  */
3309         FAIL;
3310     }
3311   else if (!TARGET_REALLY_IWMMXT)
3312     FAIL;
3313   "
3314 )
3315
3316 (define_insn "arm_lshrdi3_1bit"
3317   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
3318         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
3319                      (const_int 1)))
3320    (clobber (reg:CC CC_REGNUM))]
3321   "TARGET_32BIT"
3322   "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
3323   [(set_attr "conds" "clob")
3324    (set_attr "length" "8")]
3325 )
3326
3327 (define_expand "lshrsi3"
3328   [(set (match_operand:SI              0 "s_register_operand" "")
3329         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3330                      (match_operand:SI 2 "arm_rhs_operand" "")))]
3331   "TARGET_EITHER"
3332   "
3333   if (GET_CODE (operands[2]) == CONST_INT
3334       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3335     {
3336       emit_insn (gen_movsi (operands[0], const0_rtx));
3337       DONE;
3338     }
3339   "
3340 )
3341
3342 (define_insn "*thumb1_lshrsi3"
3343   [(set (match_operand:SI              0 "register_operand" "=l,l")
3344         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3345                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
3346   "TARGET_THUMB1"
3347   "lsr\\t%0, %1, %2"
3348   [(set_attr "length" "2")]
3349 )
3350
3351 (define_expand "rotlsi3"
3352   [(set (match_operand:SI              0 "s_register_operand" "")
3353         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3354                      (match_operand:SI 2 "reg_or_int_operand" "")))]
3355   "TARGET_32BIT"
3356   "
3357   if (GET_CODE (operands[2]) == CONST_INT)
3358     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3359   else
3360     {
3361       rtx reg = gen_reg_rtx (SImode);
3362       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3363       operands[2] = reg;
3364     }
3365   "
3366 )
3367
3368 (define_expand "rotrsi3"
3369   [(set (match_operand:SI              0 "s_register_operand" "")
3370         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3371                      (match_operand:SI 2 "arm_rhs_operand" "")))]
3372   "TARGET_EITHER"
3373   "
3374   if (TARGET_32BIT)
3375     {
3376       if (GET_CODE (operands[2]) == CONST_INT
3377           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3378         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3379     }
3380   else /* TARGET_THUMB1 */
3381     {
3382       if (GET_CODE (operands [2]) == CONST_INT)
3383         operands [2] = force_reg (SImode, operands[2]);
3384     }
3385   "
3386 )
3387
3388 (define_insn "*thumb1_rotrsi3"
3389   [(set (match_operand:SI              0 "register_operand" "=l")
3390         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
3391                      (match_operand:SI 2 "register_operand" "l")))]
3392   "TARGET_THUMB1"
3393   "ror\\t%0, %0, %2"
3394   [(set_attr "length" "2")]
3395 )
3396
3397 (define_insn "*arm_shiftsi3"
3398   [(set (match_operand:SI   0 "s_register_operand" "=r")
3399         (match_operator:SI  3 "shift_operator"
3400          [(match_operand:SI 1 "s_register_operand"  "r")
3401           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
3402   "TARGET_32BIT"
3403   "* return arm_output_shift(operands, 0);"
3404   [(set_attr "predicable" "yes")
3405    (set_attr "shift" "1")
3406    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3407                       (const_string "alu_shift")
3408                       (const_string "alu_shift_reg")))]
3409 )
3410
3411 (define_insn "*shiftsi3_compare0"
3412   [(set (reg:CC_NOOV CC_REGNUM)
3413         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3414                           [(match_operand:SI 1 "s_register_operand" "r")
3415                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
3416                          (const_int 0)))
3417    (set (match_operand:SI 0 "s_register_operand" "=r")
3418         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
3419   "TARGET_32BIT"
3420   "* return arm_output_shift(operands, 1);"
3421   [(set_attr "conds" "set")
3422    (set_attr "shift" "1")
3423    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3424                       (const_string "alu_shift")
3425                       (const_string "alu_shift_reg")))]
3426 )
3427
3428 (define_insn "*shiftsi3_compare0_scratch"
3429   [(set (reg:CC_NOOV CC_REGNUM)
3430         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3431                           [(match_operand:SI 1 "s_register_operand" "r")
3432                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
3433                          (const_int 0)))
3434    (clobber (match_scratch:SI 0 "=r"))]
3435   "TARGET_32BIT"
3436   "* return arm_output_shift(operands, 1);"
3437   [(set_attr "conds" "set")
3438    (set_attr "shift" "1")]
3439 )
3440
3441 (define_insn "*arm_notsi_shiftsi"
3442   [(set (match_operand:SI 0 "s_register_operand" "=r")
3443         (not:SI (match_operator:SI 3 "shift_operator"
3444                  [(match_operand:SI 1 "s_register_operand" "r")
3445                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
3446   "TARGET_ARM"
3447   "mvn%?\\t%0, %1%S3"
3448   [(set_attr "predicable" "yes")
3449    (set_attr "shift" "1")
3450    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3451                       (const_string "alu_shift")
3452                       (const_string "alu_shift_reg")))]
3453 )
3454
3455 (define_insn "*arm_notsi_shiftsi_compare0"
3456   [(set (reg:CC_NOOV CC_REGNUM)
3457         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
3458                           [(match_operand:SI 1 "s_register_operand" "r")
3459                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
3460                          (const_int 0)))
3461    (set (match_operand:SI 0 "s_register_operand" "=r")
3462         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
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 (define_insn "*arm_not_shiftsi_compare0_scratch"
3473   [(set (reg:CC_NOOV CC_REGNUM)
3474         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
3475                           [(match_operand:SI 1 "s_register_operand" "r")
3476                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
3477                          (const_int 0)))
3478    (clobber (match_scratch:SI 0 "=r"))]
3479   "TARGET_ARM"
3480   "mvn%.\\t%0, %1%S3"
3481   [(set_attr "conds" "set")
3482    (set_attr "shift" "1")
3483    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3484                       (const_string "alu_shift")
3485                       (const_string "alu_shift_reg")))]
3486 )
3487
3488 ;; We don't really have extzv, but defining this using shifts helps
3489 ;; to reduce register pressure later on.
3490
3491 (define_expand "extzv"
3492   [(set (match_dup 4)
3493         (ashift:SI (match_operand:SI   1 "register_operand" "")
3494                    (match_operand:SI   2 "const_int_operand" "")))
3495    (set (match_operand:SI              0 "register_operand" "")
3496         (lshiftrt:SI (match_dup 4)
3497                      (match_operand:SI 3 "const_int_operand" "")))]
3498   "TARGET_THUMB1 || arm_arch_thumb2"
3499   "
3500   {
3501     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3502     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3503     
3504     if (arm_arch_thumb2)
3505       {
3506         emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
3507                                  operands[3]));
3508         DONE;
3509       }
3510
3511     operands[3] = GEN_INT (rshift);
3512     
3513     if (lshift == 0)
3514       {
3515         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3516         DONE;
3517       }
3518       
3519     operands[2] = GEN_INT (lshift);
3520     operands[4] = gen_reg_rtx (SImode);
3521   }"
3522 )
3523
3524 (define_insn "extv"
3525   [(set (match_operand:SI 0 "s_register_operand" "=r")
3526         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3527                          (match_operand:SI 2 "const_int_operand" "M")
3528                          (match_operand:SI 3 "const_int_operand" "M")))]
3529   "arm_arch_thumb2"
3530   "sbfx%?\t%0, %1, %3, %2"
3531   [(set_attr "length" "4")
3532    (set_attr "predicable" "yes")]
3533 )
3534
3535 (define_insn "extzv_t2"
3536   [(set (match_operand:SI 0 "s_register_operand" "=r")
3537         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3538                          (match_operand:SI 2 "const_int_operand" "M")
3539                          (match_operand:SI 3 "const_int_operand" "M")))]
3540   "arm_arch_thumb2"
3541   "ubfx%?\t%0, %1, %3, %2"
3542   [(set_attr "length" "4")
3543    (set_attr "predicable" "yes")]
3544 )
3545
3546 \f
3547 ;; Unary arithmetic insns
3548
3549 (define_expand "negdi2"
3550  [(parallel
3551    [(set (match_operand:DI 0 "s_register_operand" "")
3552          (neg:DI (match_operand:DI 1 "s_register_operand" "")))
3553     (clobber (reg:CC CC_REGNUM))])]
3554   "TARGET_EITHER"
3555   ""
3556 )
3557
3558 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
3559 ;; The first alternative allows the common case of a *full* overlap.
3560 (define_insn "*arm_negdi2"
3561   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
3562         (neg:DI (match_operand:DI 1 "s_register_operand"  "0,r")))
3563    (clobber (reg:CC CC_REGNUM))]
3564   "TARGET_ARM"
3565   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
3566   [(set_attr "conds" "clob")
3567    (set_attr "length" "8")]
3568 )
3569
3570 (define_insn "*thumb1_negdi2"
3571   [(set (match_operand:DI 0 "register_operand" "=&l")
3572         (neg:DI (match_operand:DI 1 "register_operand" "l")))
3573    (clobber (reg:CC CC_REGNUM))]
3574   "TARGET_THUMB1"
3575   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
3576   [(set_attr "length" "6")]
3577 )
3578
3579 (define_expand "negsi2"
3580   [(set (match_operand:SI         0 "s_register_operand" "")
3581         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
3582   "TARGET_EITHER"
3583   ""
3584 )
3585
3586 (define_insn "*arm_negsi2"
3587   [(set (match_operand:SI         0 "s_register_operand" "=r")
3588         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
3589   "TARGET_32BIT"
3590   "rsb%?\\t%0, %1, #0"
3591   [(set_attr "predicable" "yes")]
3592 )
3593
3594 (define_insn "*thumb1_negsi2"
3595   [(set (match_operand:SI         0 "register_operand" "=l")
3596         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
3597   "TARGET_THUMB1"
3598   "neg\\t%0, %1"
3599   [(set_attr "length" "2")]
3600 )
3601
3602 (define_expand "negsf2"
3603   [(set (match_operand:SF         0 "s_register_operand" "")
3604         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
3605   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3606   ""
3607 )
3608
3609 (define_expand "negdf2"
3610   [(set (match_operand:DF         0 "s_register_operand" "")
3611         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
3612   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
3613   "")
3614
3615 ;; abssi2 doesn't really clobber the condition codes if a different register
3616 ;; is being set.  To keep things simple, assume during rtl manipulations that
3617 ;; it does, but tell the final scan operator the truth.  Similarly for
3618 ;; (neg (abs...))
3619
3620 (define_expand "abssi2"
3621   [(parallel
3622     [(set (match_operand:SI         0 "s_register_operand" "")
3623           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3624      (clobber (match_dup 2))])]
3625   "TARGET_EITHER"
3626   "
3627   if (TARGET_THUMB1)
3628     operands[2] = gen_rtx_SCRATCH (SImode);
3629   else
3630     operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
3631 ")
3632
3633 (define_insn "*arm_abssi2"
3634   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3635         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3636    (clobber (reg:CC CC_REGNUM))]
3637   "TARGET_ARM"
3638   "@
3639    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3640    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3641   [(set_attr "conds" "clob,*")
3642    (set_attr "shift" "1")
3643    ;; predicable can't be set based on the variant, so left as no
3644    (set_attr "length" "8")]
3645 )
3646
3647 (define_insn_and_split "*thumb1_abssi2"
3648   [(set (match_operand:SI 0 "s_register_operand" "=l")
3649         (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
3650    (clobber (match_scratch:SI 2 "=&l"))]
3651   "TARGET_THUMB1"
3652   "#"
3653   "TARGET_THUMB1 && reload_completed"
3654   [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3655    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
3656    (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3657   ""
3658   [(set_attr "length" "6")]
3659 )
3660
3661 (define_insn "*arm_neg_abssi2"
3662   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3663         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3664    (clobber (reg:CC CC_REGNUM))]
3665   "TARGET_ARM"
3666   "@
3667    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3668    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3669   [(set_attr "conds" "clob,*")
3670    (set_attr "shift" "1")
3671    ;; predicable can't be set based on the variant, so left as no
3672    (set_attr "length" "8")]
3673 )
3674
3675 (define_insn_and_split "*thumb1_neg_abssi2"
3676   [(set (match_operand:SI 0 "s_register_operand" "=l")
3677         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
3678    (clobber (match_scratch:SI 2 "=&l"))]
3679   "TARGET_THUMB1"
3680   "#"
3681   "TARGET_THUMB1 && reload_completed"
3682   [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3683    (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
3684    (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3685   ""
3686   [(set_attr "length" "6")]
3687 )
3688
3689 (define_expand "abssf2"
3690   [(set (match_operand:SF         0 "s_register_operand" "")
3691         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3692   "TARGET_32BIT && TARGET_HARD_FLOAT"
3693   "")
3694
3695 (define_expand "absdf2"
3696   [(set (match_operand:DF         0 "s_register_operand" "")
3697         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3698   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
3699   "")
3700
3701 (define_expand "sqrtsf2"
3702   [(set (match_operand:SF 0 "s_register_operand" "")
3703         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3704   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3705   "")
3706
3707 (define_expand "sqrtdf2"
3708   [(set (match_operand:DF 0 "s_register_operand" "")
3709         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3710   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
3711   "")
3712
3713 (define_insn_and_split "one_cmpldi2"
3714   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3715         (not:DI (match_operand:DI 1 "s_register_operand" "0,r")))]
3716   "TARGET_32BIT"
3717   "#"
3718   "TARGET_32BIT && reload_completed"
3719   [(set (match_dup 0) (not:SI (match_dup 1)))
3720    (set (match_dup 2) (not:SI (match_dup 3)))]
3721   "
3722   {
3723     operands[2] = gen_highpart (SImode, operands[0]);
3724     operands[0] = gen_lowpart (SImode, operands[0]);
3725     operands[3] = gen_highpart (SImode, operands[1]);
3726     operands[1] = gen_lowpart (SImode, operands[1]);
3727   }"
3728   [(set_attr "length" "8")
3729    (set_attr "predicable" "yes")]
3730 )
3731
3732 (define_expand "one_cmplsi2"
3733   [(set (match_operand:SI         0 "s_register_operand" "")
3734         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3735   "TARGET_EITHER"
3736   ""
3737 )
3738
3739 (define_insn "*arm_one_cmplsi2"
3740   [(set (match_operand:SI         0 "s_register_operand" "=r")
3741         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3742   "TARGET_32BIT"
3743   "mvn%?\\t%0, %1"
3744   [(set_attr "predicable" "yes")]
3745 )
3746
3747 (define_insn "*thumb1_one_cmplsi2"
3748   [(set (match_operand:SI         0 "register_operand" "=l")
3749         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3750   "TARGET_THUMB1"
3751   "mvn\\t%0, %1"
3752   [(set_attr "length" "2")]
3753 )
3754
3755 (define_insn "*notsi_compare0"
3756   [(set (reg:CC_NOOV CC_REGNUM)
3757         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3758                          (const_int 0)))
3759    (set (match_operand:SI 0 "s_register_operand" "=r")
3760         (not:SI (match_dup 1)))]
3761   "TARGET_32BIT"
3762   "mvn%.\\t%0, %1"
3763   [(set_attr "conds" "set")]
3764 )
3765
3766 (define_insn "*notsi_compare0_scratch"
3767   [(set (reg:CC_NOOV CC_REGNUM)
3768         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3769                          (const_int 0)))
3770    (clobber (match_scratch:SI 0 "=r"))]
3771   "TARGET_32BIT"
3772   "mvn%.\\t%0, %1"
3773   [(set_attr "conds" "set")]
3774 )
3775 \f
3776 ;; Fixed <--> Floating conversion insns
3777
3778 (define_expand "floatsihf2"
3779   [(set (match_operand:HF           0 "general_operand" "")
3780         (float:HF (match_operand:SI 1 "general_operand" "")))]
3781   "TARGET_EITHER"
3782   "
3783   {
3784     rtx op1 = gen_reg_rtx (SFmode);
3785     expand_float (op1, operands[1], 0);
3786     op1 = convert_to_mode (HFmode, op1, 0);
3787     emit_move_insn (operands[0], op1);
3788     DONE;
3789   }"
3790 )
3791
3792 (define_expand "floatdihf2"
3793   [(set (match_operand:HF           0 "general_operand" "")
3794         (float:HF (match_operand:DI 1 "general_operand" "")))]
3795   "TARGET_EITHER"
3796   "
3797   {
3798     rtx op1 = gen_reg_rtx (SFmode);
3799     expand_float (op1, operands[1], 0);
3800     op1 = convert_to_mode (HFmode, op1, 0);
3801     emit_move_insn (operands[0], op1);
3802     DONE;
3803   }"
3804 )
3805
3806 (define_expand "floatsisf2"
3807   [(set (match_operand:SF           0 "s_register_operand" "")
3808         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3809   "TARGET_32BIT && TARGET_HARD_FLOAT"
3810   "
3811   if (TARGET_MAVERICK)
3812     {
3813       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3814       DONE;
3815     }
3816 ")
3817
3818 (define_expand "floatsidf2"
3819   [(set (match_operand:DF           0 "s_register_operand" "")
3820         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3821   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
3822   "
3823   if (TARGET_MAVERICK)
3824     {
3825       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3826       DONE;
3827     }
3828 ")
3829
3830 (define_expand "fix_trunchfsi2"
3831   [(set (match_operand:SI         0 "general_operand" "")
3832         (fix:SI (fix:HF (match_operand:HF 1 "general_operand"  ""))))]
3833   "TARGET_EITHER"
3834   "
3835   {
3836     rtx op1 = convert_to_mode (SFmode, operands[1], 0);
3837     expand_fix (operands[0], op1, 0);
3838     DONE;
3839   }"
3840 )
3841
3842 (define_expand "fix_trunchfdi2"
3843   [(set (match_operand:DI         0 "general_operand" "")
3844         (fix:DI (fix:HF (match_operand:HF 1 "general_operand"  ""))))]
3845   "TARGET_EITHER"
3846   "
3847   {
3848     rtx op1 = convert_to_mode (SFmode, operands[1], 0);
3849     expand_fix (operands[0], op1, 0);
3850     DONE;
3851   }"
3852 )
3853
3854 (define_expand "fix_truncsfsi2"
3855   [(set (match_operand:SI         0 "s_register_operand" "")
3856         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3857   "TARGET_32BIT && TARGET_HARD_FLOAT"
3858   "
3859   if (TARGET_MAVERICK)
3860     {
3861       if (!cirrus_fp_register (operands[0], SImode))
3862         operands[0] = force_reg (SImode, operands[0]);
3863       if (!cirrus_fp_register (operands[1], SFmode))
3864         operands[1] = force_reg (SFmode, operands[0]);
3865       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3866       DONE;
3867     }
3868 ")
3869
3870 (define_expand "fix_truncdfsi2"
3871   [(set (match_operand:SI         0 "s_register_operand" "")
3872         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3873   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
3874   "
3875   if (TARGET_MAVERICK)
3876     {
3877       if (!cirrus_fp_register (operands[1], DFmode))
3878         operands[1] = force_reg (DFmode, operands[0]);
3879       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3880       DONE;
3881     }
3882 ")
3883
3884 ;; Truncation insns
3885
3886 (define_expand "truncdfsf2"
3887   [(set (match_operand:SF  0 "s_register_operand" "")
3888         (float_truncate:SF
3889          (match_operand:DF 1 "s_register_operand" "")))]
3890   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
3891   ""
3892 )
3893
3894 /* DFmode -> HFmode conversions have to go through SFmode.  */
3895 (define_expand "truncdfhf2"
3896   [(set (match_operand:HF  0 "general_operand" "")
3897         (float_truncate:HF
3898          (match_operand:DF 1 "general_operand" "")))]
3899   "TARGET_EITHER"
3900   "
3901   {
3902     rtx op1;
3903     op1 = convert_to_mode (SFmode, operands[1], 0);
3904     op1 = convert_to_mode (HFmode, op1, 0);
3905     emit_move_insn (operands[0], op1);
3906     DONE;
3907   }"
3908 )
3909 \f
3910 ;; Zero and sign extension instructions.
3911
3912 (define_expand "zero_extendsidi2"
3913   [(set (match_operand:DI 0 "s_register_operand" "")
3914         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
3915   "TARGET_32BIT"
3916   ""
3917 )
3918
3919 (define_insn "*arm_zero_extendsidi2"
3920   [(set (match_operand:DI 0 "s_register_operand" "=r")
3921         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3922   "TARGET_ARM"
3923   "*
3924     if (REGNO (operands[1])
3925         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3926       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3927     return \"mov%?\\t%R0, #0\";
3928   "
3929   [(set_attr "length" "8")
3930    (set_attr "predicable" "yes")]
3931 )
3932
3933 (define_expand "zero_extendqidi2"
3934   [(set (match_operand:DI                 0 "s_register_operand"  "")
3935         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))]
3936   "TARGET_32BIT"
3937   ""
3938 )
3939
3940 (define_insn "*arm_zero_extendqidi2"
3941   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3942         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3943   "TARGET_ARM"
3944   "@
3945    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3946    ldr%(b%)\\t%Q0, %1\;mov%?\\t%R0, #0"
3947   [(set_attr "length" "8")
3948    (set_attr "predicable" "yes")
3949    (set_attr "type" "*,load_byte")
3950    (set_attr "pool_range" "*,4092")
3951    (set_attr "neg_pool_range" "*,4084")]
3952 )
3953
3954 (define_expand "extendsidi2"
3955   [(set (match_operand:DI 0 "s_register_operand" "")
3956         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
3957   "TARGET_32BIT"
3958   ""
3959 )
3960
3961 (define_insn "*arm_extendsidi2"
3962   [(set (match_operand:DI 0 "s_register_operand" "=r")
3963         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3964   "TARGET_ARM"
3965   "*
3966     if (REGNO (operands[1])
3967         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3968       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3969     return \"mov%?\\t%R0, %Q0, asr #31\";
3970   "
3971   [(set_attr "length" "8")
3972    (set_attr "shift" "1")
3973    (set_attr "predicable" "yes")]
3974 )
3975
3976 (define_expand "zero_extendhisi2"
3977   [(set (match_dup 2)
3978         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3979                    (const_int 16)))
3980    (set (match_operand:SI 0 "s_register_operand" "")
3981         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3982   "TARGET_EITHER"
3983   "
3984   {
3985     if ((TARGET_THUMB1 || arm_arch4) && GET_CODE (operands[1]) == MEM)
3986       {
3987         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3988                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3989         DONE;
3990       }
3991
3992     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3993       {
3994         emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3995         DONE;
3996       }
3997
3998     if (!s_register_operand (operands[1], HImode))
3999       operands[1] = copy_to_mode_reg (HImode, operands[1]);
4000
4001     if (arm_arch6)
4002       {
4003         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4004                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
4005         DONE;
4006       }
4007
4008     operands[1] = gen_lowpart (SImode, operands[1]);
4009     operands[2] = gen_reg_rtx (SImode);
4010   }"
4011 )
4012
4013 (define_insn "*thumb1_zero_extendhisi2"
4014   [(set (match_operand:SI 0 "register_operand" "=l")
4015         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
4016   "TARGET_THUMB1 && !arm_arch6"
4017   "*
4018   rtx mem = XEXP (operands[1], 0);
4019
4020   if (GET_CODE (mem) == CONST)
4021     mem = XEXP (mem, 0);
4022     
4023   if (GET_CODE (mem) == LABEL_REF)
4024     return \"ldr\\t%0, %1\";
4025     
4026   if (GET_CODE (mem) == PLUS)
4027     {
4028       rtx a = XEXP (mem, 0);
4029       rtx b = XEXP (mem, 1);
4030
4031       /* This can happen due to bugs in reload.  */
4032       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
4033         {
4034           rtx ops[2];
4035           ops[0] = operands[0];
4036           ops[1] = a;
4037       
4038           output_asm_insn (\"mov        %0, %1\", ops);
4039
4040           XEXP (mem, 0) = operands[0];
4041        }
4042
4043       else if (   GET_CODE (a) == LABEL_REF
4044                && GET_CODE (b) == CONST_INT)
4045         return \"ldr\\t%0, %1\";
4046     }
4047     
4048   return \"ldrh\\t%0, %1\";
4049   "
4050   [(set_attr "length" "4")
4051    (set_attr "type" "load_byte")
4052    (set_attr "pool_range" "60")]
4053 )
4054
4055 (define_insn "*thumb1_zero_extendhisi2_v6"
4056   [(set (match_operand:SI 0 "register_operand" "=l,l")
4057         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
4058   "TARGET_THUMB1 && arm_arch6"
4059   "*
4060   rtx mem;
4061
4062   if (which_alternative == 0)
4063     return \"uxth\\t%0, %1\";
4064
4065   mem = XEXP (operands[1], 0);
4066
4067   if (GET_CODE (mem) == CONST)
4068     mem = XEXP (mem, 0);
4069     
4070   if (GET_CODE (mem) == LABEL_REF)
4071     return \"ldr\\t%0, %1\";
4072     
4073   if (GET_CODE (mem) == PLUS)
4074     {
4075       rtx a = XEXP (mem, 0);
4076       rtx b = XEXP (mem, 1);
4077
4078       /* This can happen due to bugs in reload.  */
4079       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
4080         {
4081           rtx ops[2];
4082           ops[0] = operands[0];
4083           ops[1] = a;
4084       
4085           output_asm_insn (\"mov        %0, %1\", ops);
4086
4087           XEXP (mem, 0) = operands[0];
4088        }
4089
4090       else if (   GET_CODE (a) == LABEL_REF
4091                && GET_CODE (b) == CONST_INT)
4092         return \"ldr\\t%0, %1\";
4093     }
4094     
4095   return \"ldrh\\t%0, %1\";
4096   "
4097   [(set_attr "length" "2,4")
4098    (set_attr "type" "alu_shift,load_byte")
4099    (set_attr "pool_range" "*,60")]
4100 )
4101
4102 (define_insn "*arm_zero_extendhisi2"
4103   [(set (match_operand:SI 0 "s_register_operand" "=r")
4104         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
4105   "TARGET_ARM && arm_arch4 && !arm_arch6"
4106   "ldr%(h%)\\t%0, %1"
4107   [(set_attr "type" "load_byte")
4108    (set_attr "predicable" "yes")
4109    (set_attr "pool_range" "256")
4110    (set_attr "neg_pool_range" "244")]
4111 )
4112
4113 (define_insn "*arm_zero_extendhisi2_v6"
4114   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4115         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4116   "TARGET_ARM && arm_arch6"
4117   "@
4118    uxth%?\\t%0, %1
4119    ldr%(h%)\\t%0, %1"
4120   [(set_attr "type" "alu_shift,load_byte")
4121    (set_attr "predicable" "yes")
4122    (set_attr "pool_range" "*,256")
4123    (set_attr "neg_pool_range" "*,244")]
4124 )
4125
4126 (define_insn "*arm_zero_extendhisi2addsi"
4127   [(set (match_operand:SI 0 "s_register_operand" "=r")
4128         (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4129                  (match_operand:SI 2 "s_register_operand" "r")))]
4130   "TARGET_INT_SIMD"
4131   "uxtah%?\\t%0, %2, %1"
4132   [(set_attr "type" "alu_shift")
4133    (set_attr "predicable" "yes")]
4134 )
4135
4136 (define_expand "zero_extendqisi2"
4137   [(set (match_operand:SI 0 "s_register_operand" "")
4138         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
4139   "TARGET_EITHER"
4140   "
4141   if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
4142     {
4143       if (TARGET_ARM)
4144         {
4145           emit_insn (gen_andsi3 (operands[0],
4146                                  gen_lowpart (SImode, operands[1]),
4147                                  GEN_INT (255)));
4148         }
4149       else /* TARGET_THUMB */
4150         {
4151           rtx temp = gen_reg_rtx (SImode);
4152           rtx ops[3];
4153           
4154           operands[1] = copy_to_mode_reg (QImode, operands[1]);
4155           operands[1] = gen_lowpart (SImode, operands[1]);
4156
4157           ops[0] = temp;
4158           ops[1] = operands[1];
4159           ops[2] = GEN_INT (24);
4160
4161           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
4162                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
4163           
4164           ops[0] = operands[0];
4165           ops[1] = temp;
4166           ops[2] = GEN_INT (24);
4167
4168           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
4169                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
4170         }
4171       DONE;
4172     }
4173   "
4174 )
4175
4176 (define_insn "*thumb1_zero_extendqisi2"
4177   [(set (match_operand:SI 0 "register_operand" "=l")
4178         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
4179   "TARGET_THUMB1 && !arm_arch6"
4180   "ldrb\\t%0, %1"
4181   [(set_attr "length" "2")
4182    (set_attr "type" "load_byte")
4183    (set_attr "pool_range" "32")]
4184 )
4185
4186 (define_insn "*thumb1_zero_extendqisi2_v6"
4187   [(set (match_operand:SI 0 "register_operand" "=l,l")
4188         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
4189   "TARGET_THUMB1 && arm_arch6"
4190   "@
4191    uxtb\\t%0, %1
4192    ldrb\\t%0, %1"
4193   [(set_attr "length" "2,2")
4194    (set_attr "type" "alu_shift,load_byte")
4195    (set_attr "pool_range" "*,32")]
4196 )
4197
4198 (define_insn "*arm_zero_extendqisi2"
4199   [(set (match_operand:SI 0 "s_register_operand" "=r")
4200         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
4201   "TARGET_ARM && !arm_arch6"
4202   "ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
4203   [(set_attr "type" "load_byte")
4204    (set_attr "predicable" "yes")
4205    (set_attr "pool_range" "4096")
4206    (set_attr "neg_pool_range" "4084")]
4207 )
4208
4209 (define_insn "*arm_zero_extendqisi2_v6"
4210   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4211         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4212   "TARGET_ARM && arm_arch6"
4213   "@
4214    uxtb%(%)\\t%0, %1
4215    ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
4216   [(set_attr "type" "alu_shift,load_byte")
4217    (set_attr "predicable" "yes")
4218    (set_attr "pool_range" "*,4096")
4219    (set_attr "neg_pool_range" "*,4084")]
4220 )
4221
4222 (define_insn "*arm_zero_extendqisi2addsi"
4223   [(set (match_operand:SI 0 "s_register_operand" "=r")
4224         (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4225                  (match_operand:SI 2 "s_register_operand" "r")))]
4226   "TARGET_INT_SIMD"
4227   "uxtab%?\\t%0, %2, %1"
4228   [(set_attr "predicable" "yes")
4229    (set_attr "insn" "xtab")
4230    (set_attr "type" "alu_shift")]
4231 )
4232
4233 (define_split
4234   [(set (match_operand:SI 0 "s_register_operand" "")
4235         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
4236    (clobber (match_operand:SI 2 "s_register_operand" ""))]
4237   "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
4238   [(set (match_dup 2) (match_dup 1))
4239    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4240   ""
4241 )
4242
4243 (define_split
4244   [(set (match_operand:SI 0 "s_register_operand" "")
4245         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
4246    (clobber (match_operand:SI 2 "s_register_operand" ""))]
4247   "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
4248   [(set (match_dup 2) (match_dup 1))
4249    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4250   ""
4251 )
4252
4253 (define_code_iterator ior_xor [ior xor])
4254
4255 (define_split
4256   [(set (match_operand:SI 0 "s_register_operand" "")
4257         (ior_xor:SI (and:SI (ashift:SI
4258                              (match_operand:SI 1 "s_register_operand" "")
4259                              (match_operand:SI 2 "const_int_operand" ""))
4260                             (match_operand:SI 3 "const_int_operand" ""))
4261                     (zero_extend:SI
4262                      (match_operator 5 "subreg_lowpart_operator"
4263                       [(match_operand:SI 4 "s_register_operand" "")]))))]
4264   "TARGET_32BIT
4265    && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
4266        == (GET_MODE_MASK (GET_MODE (operands[5]))
4267            & (GET_MODE_MASK (GET_MODE (operands[5]))
4268               << (INTVAL (operands[2])))))"
4269   [(set (match_dup 0) (ior_xor:SI (ashift:SI (match_dup 1) (match_dup 2))
4270                                   (match_dup 4)))
4271    (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
4272   "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
4273 )
4274
4275 (define_insn "*compareqi_eq0"
4276   [(set (reg:CC_Z CC_REGNUM)
4277         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
4278                          (const_int 0)))]
4279   "TARGET_32BIT"
4280   "tst\\t%0, #255"
4281   [(set_attr "conds" "set")]
4282 )
4283
4284 (define_expand "extendhisi2"
4285   [(set (match_dup 2)
4286         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
4287                    (const_int 16)))
4288    (set (match_operand:SI 0 "s_register_operand" "")
4289         (ashiftrt:SI (match_dup 2)
4290                      (const_int 16)))]
4291   "TARGET_EITHER"
4292   "
4293   {
4294     if (GET_CODE (operands[1]) == MEM)
4295       {
4296         if (TARGET_THUMB1)
4297           {
4298             emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
4299             DONE;
4300           }
4301         else if (arm_arch4)
4302           {
4303             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4304                        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4305             DONE;
4306           }
4307       }
4308
4309     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
4310       {
4311         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
4312         DONE;
4313       }
4314
4315     if (!s_register_operand (operands[1], HImode))
4316       operands[1] = copy_to_mode_reg (HImode, operands[1]);
4317
4318     if (arm_arch6)
4319       {
4320         if (TARGET_THUMB1)
4321           emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
4322         else
4323           emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4324                      gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4325
4326         DONE;
4327       }
4328
4329     operands[1] = gen_lowpart (SImode, operands[1]);
4330     operands[2] = gen_reg_rtx (SImode);
4331   }"
4332 )
4333
4334 (define_insn "thumb1_extendhisi2"
4335   [(set (match_operand:SI 0 "register_operand" "=l")
4336         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
4337    (clobber (match_scratch:SI 2 "=&l"))]
4338   "TARGET_THUMB1 && !arm_arch6"
4339   "*
4340   {
4341     rtx ops[4];
4342     rtx mem = XEXP (operands[1], 0);
4343
4344     /* This code used to try to use 'V', and fix the address only if it was
4345        offsettable, but this fails for e.g. REG+48 because 48 is outside the
4346        range of QImode offsets, and offsettable_address_p does a QImode
4347        address check.  */
4348        
4349     if (GET_CODE (mem) == CONST)
4350       mem = XEXP (mem, 0);
4351     
4352     if (GET_CODE (mem) == LABEL_REF)
4353       return \"ldr\\t%0, %1\";
4354     
4355     if (GET_CODE (mem) == PLUS)
4356       {
4357         rtx a = XEXP (mem, 0);
4358         rtx b = XEXP (mem, 1);
4359
4360         if (GET_CODE (a) == LABEL_REF
4361             && GET_CODE (b) == CONST_INT)
4362           return \"ldr\\t%0, %1\";
4363
4364         if (GET_CODE (b) == REG)
4365           return \"ldrsh\\t%0, %1\";
4366           
4367         ops[1] = a;
4368         ops[2] = b;
4369       }
4370     else
4371       {
4372         ops[1] = mem;
4373         ops[2] = const0_rtx;
4374       }
4375
4376     gcc_assert (GET_CODE (ops[1]) == REG);
4377
4378     ops[0] = operands[0];
4379     ops[3] = operands[2];
4380     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4381     return \"\";
4382   }"
4383   [(set_attr "length" "4")
4384    (set_attr "type" "load_byte")
4385    (set_attr "pool_range" "1020")]
4386 )
4387
4388 ;; We used to have an early-clobber on the scratch register here.
4389 ;; However, there's a bug somewhere in reload which means that this
4390 ;; can be partially ignored during spill allocation if the memory
4391 ;; address also needs reloading; this causes us to die later on when
4392 ;; we try to verify the operands.  Fortunately, we don't really need
4393 ;; the early-clobber: we can always use operand 0 if operand 2
4394 ;; overlaps the address.
4395 (define_insn "*thumb1_extendhisi2_insn_v6"
4396   [(set (match_operand:SI 0 "register_operand" "=l,l")
4397         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
4398    (clobber (match_scratch:SI 2 "=X,l"))]
4399   "TARGET_THUMB1 && arm_arch6"
4400   "*
4401   {
4402     rtx ops[4];
4403     rtx mem;
4404
4405     if (which_alternative == 0)
4406       return \"sxth\\t%0, %1\";
4407
4408     mem = XEXP (operands[1], 0);
4409
4410     /* This code used to try to use 'V', and fix the address only if it was
4411        offsettable, but this fails for e.g. REG+48 because 48 is outside the
4412        range of QImode offsets, and offsettable_address_p does a QImode
4413        address check.  */
4414        
4415     if (GET_CODE (mem) == CONST)
4416       mem = XEXP (mem, 0);
4417     
4418     if (GET_CODE (mem) == LABEL_REF)
4419       return \"ldr\\t%0, %1\";
4420     
4421     if (GET_CODE (mem) == PLUS)
4422       {
4423         rtx a = XEXP (mem, 0);
4424         rtx b = XEXP (mem, 1);
4425
4426         if (GET_CODE (a) == LABEL_REF
4427             && GET_CODE (b) == CONST_INT)
4428           return \"ldr\\t%0, %1\";
4429
4430         if (GET_CODE (b) == REG)
4431           return \"ldrsh\\t%0, %1\";
4432           
4433         ops[1] = a;
4434         ops[2] = b;
4435       }
4436     else
4437       {
4438         ops[1] = mem;
4439         ops[2] = const0_rtx;
4440       }
4441       
4442     gcc_assert (GET_CODE (ops[1]) == REG);
4443
4444     ops[0] = operands[0];
4445     if (reg_mentioned_p (operands[2], ops[1]))
4446       ops[3] = ops[0];
4447     else
4448       ops[3] = operands[2];
4449     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4450     return \"\";
4451   }"
4452   [(set_attr "length" "2,4")
4453    (set_attr "type" "alu_shift,load_byte")
4454    (set_attr "pool_range" "*,1020")]
4455 )
4456
4457 ;; This pattern will only be used when ldsh is not available
4458 (define_expand "extendhisi2_mem"
4459   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4460    (set (match_dup 3)
4461         (zero_extend:SI (match_dup 7)))
4462    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4463    (set (match_operand:SI 0 "" "")
4464         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
4465   "TARGET_ARM"
4466   "
4467   {
4468     rtx mem1, mem2;
4469     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4470
4471     mem1 = change_address (operands[1], QImode, addr);
4472     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
4473     operands[0] = gen_lowpart (SImode, operands[0]);
4474     operands[1] = mem1;
4475     operands[2] = gen_reg_rtx (SImode);
4476     operands[3] = gen_reg_rtx (SImode);
4477     operands[6] = gen_reg_rtx (SImode);
4478     operands[7] = mem2;
4479
4480     if (BYTES_BIG_ENDIAN)
4481       {
4482         operands[4] = operands[2];
4483         operands[5] = operands[3];
4484       }
4485     else
4486       {
4487         operands[4] = operands[3];
4488         operands[5] = operands[2];
4489       }
4490   }"
4491 )
4492
4493 (define_insn "*arm_extendhisi2"
4494   [(set (match_operand:SI 0 "s_register_operand" "=r")
4495         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
4496   "TARGET_ARM && arm_arch4 && !arm_arch6"
4497   "ldr%(sh%)\\t%0, %1"
4498   [(set_attr "type" "load_byte")
4499    (set_attr "predicable" "yes")
4500    (set_attr "pool_range" "256")
4501    (set_attr "neg_pool_range" "244")]
4502 )
4503
4504 ;; ??? Check Thumb-2 pool range
4505 (define_insn "*arm_extendhisi2_v6"
4506   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4507         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4508   "TARGET_32BIT && arm_arch6"
4509   "@
4510    sxth%?\\t%0, %1
4511    ldr%(sh%)\\t%0, %1"
4512   [(set_attr "type" "alu_shift,load_byte")
4513    (set_attr "predicable" "yes")
4514    (set_attr "pool_range" "*,256")
4515    (set_attr "neg_pool_range" "*,244")]
4516 )
4517
4518 (define_insn "*arm_extendhisi2addsi"
4519   [(set (match_operand:SI 0 "s_register_operand" "=r")
4520         (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4521                  (match_operand:SI 2 "s_register_operand" "r")))]
4522   "TARGET_INT_SIMD"
4523   "sxtah%?\\t%0, %2, %1"
4524 )
4525
4526 (define_expand "extendqihi2"
4527   [(set (match_dup 2)
4528         (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
4529                    (const_int 24)))
4530    (set (match_operand:HI 0 "s_register_operand" "")
4531         (ashiftrt:SI (match_dup 2)
4532                      (const_int 24)))]
4533   "TARGET_ARM"
4534   "
4535   {
4536     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
4537       {
4538         emit_insn (gen_rtx_SET (VOIDmode,
4539                                 operands[0],
4540                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
4541         DONE;
4542       }
4543     if (!s_register_operand (operands[1], QImode))
4544       operands[1] = copy_to_mode_reg (QImode, operands[1]);
4545     operands[0] = gen_lowpart (SImode, operands[0]);
4546     operands[1] = gen_lowpart (SImode, operands[1]);
4547     operands[2] = gen_reg_rtx (SImode);
4548   }"
4549 )
4550
4551 (define_insn "*arm_extendqihi_insn"
4552   [(set (match_operand:HI 0 "s_register_operand" "=r")
4553         (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
4554   "TARGET_ARM && arm_arch4"
4555   "ldr%(sb%)\\t%0, %1"
4556   [(set_attr "type" "load_byte")
4557    (set_attr "predicable" "yes")
4558    (set_attr "pool_range" "256")
4559    (set_attr "neg_pool_range" "244")]
4560 )
4561
4562 (define_expand "extendqisi2"
4563   [(set (match_dup 2)
4564         (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
4565                    (const_int 24)))
4566    (set (match_operand:SI 0 "s_register_operand" "")
4567         (ashiftrt:SI (match_dup 2)
4568                      (const_int 24)))]
4569   "TARGET_EITHER"
4570   "
4571   {
4572     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
4573       {
4574         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4575                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4576         DONE;
4577       }
4578
4579     if (!s_register_operand (operands[1], QImode))
4580       operands[1] = copy_to_mode_reg (QImode, operands[1]);
4581
4582     if (arm_arch6)
4583       {
4584         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4585                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4586         DONE;
4587       }
4588
4589     operands[1] = gen_lowpart (SImode, operands[1]);
4590     operands[2] = gen_reg_rtx (SImode);
4591   }"
4592 )
4593
4594 (define_insn "*arm_extendqisi"
4595   [(set (match_operand:SI 0 "s_register_operand" "=r")
4596         (sign_extend:SI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
4597   "TARGET_ARM && arm_arch4 && !arm_arch6"
4598   "ldr%(sb%)\\t%0, %1"
4599   [(set_attr "type" "load_byte")
4600    (set_attr "predicable" "yes")
4601    (set_attr "pool_range" "256")
4602    (set_attr "neg_pool_range" "244")]
4603 )
4604
4605 (define_insn "*arm_extendqisi_v6"
4606   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4607         (sign_extend:SI
4608          (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
4609   "TARGET_ARM && arm_arch6"
4610   "@
4611    sxtb%?\\t%0, %1
4612    ldr%(sb%)\\t%0, %1"
4613   [(set_attr "type" "alu_shift,load_byte")
4614    (set_attr "predicable" "yes")
4615    (set_attr "pool_range" "*,256")
4616    (set_attr "neg_pool_range" "*,244")]
4617 )
4618
4619 (define_insn "*arm_extendqisi2addsi"
4620   [(set (match_operand:SI 0 "s_register_operand" "=r")
4621         (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4622                  (match_operand:SI 2 "s_register_operand" "r")))]
4623   "TARGET_INT_SIMD"
4624   "sxtab%?\\t%0, %2, %1"
4625   [(set_attr "type" "alu_shift")
4626    (set_attr "insn" "xtab")
4627    (set_attr "predicable" "yes")]
4628 )
4629
4630 (define_insn "*thumb1_extendqisi2"
4631   [(set (match_operand:SI 0 "register_operand" "=l,l")
4632         (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
4633   "TARGET_THUMB1 && !arm_arch6"
4634   "*
4635   {
4636     rtx ops[3];
4637     rtx mem = XEXP (operands[1], 0);
4638     
4639     if (GET_CODE (mem) == CONST)
4640       mem = XEXP (mem, 0);
4641     
4642     if (GET_CODE (mem) == LABEL_REF)
4643       return \"ldr\\t%0, %1\";
4644
4645     if (GET_CODE (mem) == PLUS
4646         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4647       return \"ldr\\t%0, %1\";
4648       
4649     if (which_alternative == 0)
4650       return \"ldrsb\\t%0, %1\";
4651       
4652     ops[0] = operands[0];
4653     
4654     if (GET_CODE (mem) == PLUS)
4655       {
4656         rtx a = XEXP (mem, 0);
4657         rtx b = XEXP (mem, 1);
4658         
4659         ops[1] = a;
4660         ops[2] = b;
4661
4662         if (GET_CODE (a) == REG)
4663           {
4664             if (GET_CODE (b) == REG)
4665               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4666             else if (REGNO (a) == REGNO (ops[0]))
4667               {
4668                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4669                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4670                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4671               }
4672             else
4673               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4674           }
4675         else
4676           {
4677             gcc_assert (GET_CODE (b) == REG);
4678             if (REGNO (b) == REGNO (ops[0]))
4679               {
4680                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4681                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4682                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4683               }
4684             else
4685               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4686           }
4687       }
4688     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4689       {
4690         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4691         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4692         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4693       }
4694     else
4695       {
4696         ops[1] = mem;
4697         ops[2] = const0_rtx;
4698         
4699         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4700       }
4701     return \"\";
4702   }"
4703   [(set_attr "length" "2,6")
4704    (set_attr "type" "load_byte,load_byte")
4705    (set_attr "pool_range" "32,32")]
4706 )
4707
4708 (define_insn "*thumb1_extendqisi2_v6"
4709   [(set (match_operand:SI 0 "register_operand" "=l,l,l")
4710         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
4711   "TARGET_THUMB1 && arm_arch6"
4712   "*
4713   {
4714     rtx ops[3];
4715     rtx mem;
4716
4717     if (which_alternative == 0)
4718       return \"sxtb\\t%0, %1\";
4719
4720     mem = XEXP (operands[1], 0);
4721     
4722     if (GET_CODE (mem) == CONST)
4723       mem = XEXP (mem, 0);
4724     
4725     if (GET_CODE (mem) == LABEL_REF)
4726       return \"ldr\\t%0, %1\";
4727
4728     if (GET_CODE (mem) == PLUS
4729         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4730       return \"ldr\\t%0, %1\";
4731       
4732     if (which_alternative == 0)
4733       return \"ldrsb\\t%0, %1\";
4734       
4735     ops[0] = operands[0];
4736     
4737     if (GET_CODE (mem) == PLUS)
4738       {
4739         rtx a = XEXP (mem, 0);
4740         rtx b = XEXP (mem, 1);
4741         
4742         ops[1] = a;
4743         ops[2] = b;
4744
4745         if (GET_CODE (a) == REG)
4746           {
4747             if (GET_CODE (b) == REG)
4748               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4749             else if (REGNO (a) == REGNO (ops[0]))
4750               {
4751                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4752                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4753               }
4754             else
4755               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4756           }
4757         else
4758           {
4759             gcc_assert (GET_CODE (b) == REG);
4760             if (REGNO (b) == REGNO (ops[0]))
4761               {
4762                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4763                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4764               }
4765             else
4766               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4767           }
4768       }
4769     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4770       {
4771         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4772         output_asm_insn (\"sxtb\\t%0, %0\", ops);
4773       }
4774     else
4775       {
4776         ops[1] = mem;
4777         ops[2] = const0_rtx;
4778         
4779         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4780       }
4781     return \"\";
4782   }"
4783   [(set_attr "length" "2,2,4")
4784    (set_attr "type" "alu_shift,load_byte,load_byte")
4785    (set_attr "pool_range" "*,32,32")]
4786 )
4787
4788 (define_expand "extendsfdf2"
4789   [(set (match_operand:DF                  0 "s_register_operand" "")
4790         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
4791   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
4792   ""
4793 )
4794
4795 /* HFmode -> DFmode conversions have to go through SFmode.  */
4796 (define_expand "extendhfdf2"
4797   [(set (match_operand:DF                  0 "general_operand" "")
4798         (float_extend:DF (match_operand:HF 1 "general_operand"  "")))]
4799   "TARGET_EITHER"
4800   "
4801   {
4802     rtx op1;
4803     op1 = convert_to_mode (SFmode, operands[1], 0);
4804     op1 = convert_to_mode (DFmode, op1, 0);
4805     emit_insn (gen_movdf (operands[0], op1));
4806     DONE;
4807   }"
4808 )
4809 \f
4810 ;; Move insns (including loads and stores)
4811
4812 ;; XXX Just some ideas about movti.
4813 ;; I don't think these are a good idea on the arm, there just aren't enough
4814 ;; registers
4815 ;;(define_expand "loadti"
4816 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
4817 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
4818 ;;  "" "")
4819
4820 ;;(define_expand "storeti"
4821 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4822 ;;      (match_operand:TI 1 "s_register_operand" ""))]
4823 ;;  "" "")
4824
4825 ;;(define_expand "movti"
4826 ;;  [(set (match_operand:TI 0 "general_operand" "")
4827 ;;      (match_operand:TI 1 "general_operand" ""))]
4828 ;;  ""
4829 ;;  "
4830 ;;{
4831 ;;  rtx insn;
4832 ;;
4833 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4834 ;;    operands[1] = copy_to_reg (operands[1]);
4835 ;;  if (GET_CODE (operands[0]) == MEM)
4836 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4837 ;;  else if (GET_CODE (operands[1]) == MEM)
4838 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4839 ;;  else
4840 ;;    FAIL;
4841 ;;
4842 ;;  emit_insn (insn);
4843 ;;  DONE;
4844 ;;}")
4845
4846 ;; Recognize garbage generated above.
4847
4848 ;;(define_insn ""
4849 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4850 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4851 ;;  ""
4852 ;;  "*
4853 ;;  {
4854 ;;    register mem = (which_alternative < 3);
4855 ;;    register const char *template;
4856 ;;
4857 ;;    operands[mem] = XEXP (operands[mem], 0);
4858 ;;    switch (which_alternative)
4859 ;;      {
4860 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4861 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
4862 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
4863 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
4864 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
4865 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
4866 ;;      }
4867 ;;    output_asm_insn (template, operands);
4868 ;;    return \"\";
4869 ;;  }")
4870
4871 (define_expand "movdi"
4872   [(set (match_operand:DI 0 "general_operand" "")
4873         (match_operand:DI 1 "general_operand" ""))]
4874   "TARGET_EITHER"
4875   "
4876   if (can_create_pseudo_p ())
4877     {
4878       if (GET_CODE (operands[0]) != REG)
4879         operands[1] = force_reg (DImode, operands[1]);
4880     }
4881   "
4882 )
4883
4884 (define_insn "*arm_movdi"
4885   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4886         (match_operand:DI 1 "di_operand"              "rDa,Db,Dc,mi,r"))]
4887   "TARGET_ARM
4888    && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4889    && !TARGET_IWMMXT
4890    && (   register_operand (operands[0], DImode)
4891        || register_operand (operands[1], DImode))"
4892   "*
4893   switch (which_alternative)
4894     {
4895     case 0:
4896     case 1:
4897     case 2:
4898       return \"#\";
4899     default:
4900       return output_move_double (operands);
4901     }
4902   "
4903   [(set_attr "length" "8,12,16,8,8")
4904    (set_attr "type" "*,*,*,load2,store2")
4905    (set_attr "pool_range" "*,*,*,1020,*")
4906    (set_attr "neg_pool_range" "*,*,*,1008,*")]
4907 )
4908
4909 (define_split
4910   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4911         (match_operand:ANY64 1 "const_double_operand" ""))]
4912   "TARGET_32BIT
4913    && reload_completed
4914    && (arm_const_double_inline_cost (operands[1])
4915        <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4916   [(const_int 0)]
4917   "
4918   arm_split_constant (SET, SImode, curr_insn,
4919                       INTVAL (gen_lowpart (SImode, operands[1])),
4920                       gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4921   arm_split_constant (SET, SImode, curr_insn,
4922                       INTVAL (gen_highpart_mode (SImode,
4923                                                  GET_MODE (operands[0]),
4924                                                  operands[1])),
4925                       gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4926   DONE;
4927   "
4928 )
4929
4930 ; If optimizing for size, or if we have load delay slots, then 
4931 ; we want to split the constant into two separate operations. 
4932 ; In both cases this may split a trivial part into a single data op
4933 ; leaving a single complex constant to load.  We can also get longer
4934 ; offsets in a LDR which means we get better chances of sharing the pool
4935 ; entries.  Finally, we can normally do a better job of scheduling
4936 ; LDR instructions than we can with LDM.
4937 ; This pattern will only match if the one above did not.
4938 (define_split
4939   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4940         (match_operand:ANY64 1 "const_double_operand" ""))]
4941   "TARGET_ARM && reload_completed
4942    && arm_const_double_by_parts (operands[1])"
4943   [(set (match_dup 0) (match_dup 1))
4944    (set (match_dup 2) (match_dup 3))]
4945   "
4946   operands[2] = gen_highpart (SImode, operands[0]);
4947   operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4948                                    operands[1]);
4949   operands[0] = gen_lowpart (SImode, operands[0]);
4950   operands[1] = gen_lowpart (SImode, operands[1]);
4951   "
4952 )
4953
4954 (define_split
4955   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4956         (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4957   "TARGET_EITHER && reload_completed"
4958   [(set (match_dup 0) (match_dup 1))
4959    (set (match_dup 2) (match_dup 3))]
4960   "
4961   operands[2] = gen_highpart (SImode, operands[0]);
4962   operands[3] = gen_highpart (SImode, operands[1]);
4963   operands[0] = gen_lowpart (SImode, operands[0]);
4964   operands[1] = gen_lowpart (SImode, operands[1]);
4965
4966   /* Handle a partial overlap.  */
4967   if (rtx_equal_p (operands[0], operands[3]))
4968     {
4969       rtx tmp0 = operands[0];
4970       rtx tmp1 = operands[1];
4971
4972       operands[0] = operands[2];
4973       operands[1] = operands[3];
4974       operands[2] = tmp0;
4975       operands[3] = tmp1;
4976     }
4977   "
4978 )
4979
4980 ;; We can't actually do base+index doubleword loads if the index and
4981 ;; destination overlap.  Split here so that we at least have chance to
4982 ;; schedule.
4983 (define_split
4984   [(set (match_operand:DI 0 "s_register_operand" "")
4985         (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4986                          (match_operand:SI 2 "s_register_operand" ""))))]
4987   "TARGET_LDRD
4988   && reg_overlap_mentioned_p (operands[0], operands[1])
4989   && reg_overlap_mentioned_p (operands[0], operands[2])"
4990   [(set (match_dup 4)
4991         (plus:SI (match_dup 1)
4992                  (match_dup 2)))
4993    (set (match_dup 0)
4994         (mem:DI (match_dup 4)))]
4995   "
4996   operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4997   "
4998 )
4999
5000 ;;; ??? This should have alternatives for constants.
5001 ;;; ??? This was originally identical to the movdf_insn pattern.
5002 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
5003 ;;; thumb_reorg with a memory reference.
5004 (define_insn "*thumb1_movdi_insn"
5005   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
5006         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
5007   "TARGET_THUMB1
5008    && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
5009    && (   register_operand (operands[0], DImode)
5010        || register_operand (operands[1], DImode))"
5011   "*
5012   {
5013   switch (which_alternative)
5014     {
5015     default:
5016     case 0:
5017       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5018         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
5019       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
5020     case 1:
5021       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
5022     case 2:
5023       operands[1] = GEN_INT (- INTVAL (operands[1]));
5024       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
5025     case 3:
5026       return \"ldmia\\t%1, {%0, %H0}\";
5027     case 4:
5028       return \"stmia\\t%0, {%1, %H1}\";
5029     case 5:
5030       return thumb_load_double_from_address (operands);
5031     case 6:
5032       operands[2] = gen_rtx_MEM (SImode,
5033                              plus_constant (XEXP (operands[0], 0), 4));
5034       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5035       return \"\";
5036     case 7:
5037       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5038         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5039       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5040     }
5041   }"
5042   [(set_attr "length" "4,4,6,2,2,6,4,4")
5043    (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
5044    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
5045 )
5046
5047 (define_expand "movsi"
5048   [(set (match_operand:SI 0 "general_operand" "")
5049         (match_operand:SI 1 "general_operand" ""))]
5050   "TARGET_EITHER"
5051   "
5052   {
5053   rtx base, offset, tmp;
5054
5055   if (TARGET_32BIT)
5056     {
5057       /* Everything except mem = const or mem = mem can be done easily.  */
5058       if (GET_CODE (operands[0]) == MEM)
5059         operands[1] = force_reg (SImode, operands[1]);
5060       if (arm_general_register_operand (operands[0], SImode)
5061           && GET_CODE (operands[1]) == CONST_INT
5062           && !(const_ok_for_arm (INTVAL (operands[1]))
5063                || const_ok_for_arm (~INTVAL (operands[1]))))
5064         {
5065            arm_split_constant (SET, SImode, NULL_RTX,
5066                                INTVAL (operands[1]), operands[0], NULL_RTX,
5067                                optimize && can_create_pseudo_p ());
5068           DONE;
5069         }
5070
5071       if (TARGET_USE_MOVT && !target_word_relocations
5072           && GET_CODE (operands[1]) == SYMBOL_REF
5073           && !flag_pic && !arm_tls_referenced_p (operands[1]))
5074         {
5075           arm_emit_movpair (operands[0], operands[1]);
5076           DONE;
5077         }
5078     }
5079   else /* TARGET_THUMB1...  */
5080     {
5081       if (can_create_pseudo_p ())
5082         {
5083           if (GET_CODE (operands[0]) != REG)
5084             operands[1] = force_reg (SImode, operands[1]);
5085         }
5086     }
5087
5088   if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
5089     {
5090       split_const (operands[1], &base, &offset);
5091       if (GET_CODE (base) == SYMBOL_REF
5092           && !offset_within_block_p (base, INTVAL (offset)))
5093         {
5094           tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5095           emit_move_insn (tmp, base);
5096           emit_insn (gen_addsi3 (operands[0], tmp, offset));
5097           DONE;
5098         }
5099     }
5100
5101   /* Recognize the case where operand[1] is a reference to thread-local
5102      data and load its address to a register.  */
5103   if (arm_tls_referenced_p (operands[1]))
5104     {
5105       rtx tmp = operands[1];
5106       rtx addend = NULL;
5107
5108       if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
5109         {
5110           addend = XEXP (XEXP (tmp, 0), 1);
5111           tmp = XEXP (XEXP (tmp, 0), 0);
5112         }
5113
5114       gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
5115       gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
5116
5117       tmp = legitimize_tls_address (tmp,
5118                                     !can_create_pseudo_p () ? operands[0] : 0);
5119       if (addend)
5120         {
5121           tmp = gen_rtx_PLUS (SImode, tmp, addend);
5122           tmp = force_operand (tmp, operands[0]);
5123         }
5124       operands[1] = tmp;
5125     }
5126   else if (flag_pic
5127            && (CONSTANT_P (operands[1])
5128                || symbol_mentioned_p (operands[1])
5129                || label_mentioned_p (operands[1])))
5130       operands[1] = legitimize_pic_address (operands[1], SImode,
5131                                             (!can_create_pseudo_p ()
5132                                              ? operands[0]
5133                                              : 0));
5134   }
5135   "
5136 )
5137
5138 ;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5139 ;; LO_SUM adds in the high bits.  Fortunately these are opaque operations
5140 ;; so this does not matter.
5141 (define_insn "*arm_movt"
5142   [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5143         (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5144                    (match_operand:SI 2 "general_operand"      "i")))]
5145   "TARGET_32BIT"
5146   "movt%?\t%0, #:upper16:%c2"
5147   [(set_attr "predicable" "yes")
5148    (set_attr "length" "4")]
5149 )
5150
5151 (define_insn "*arm_movsi_insn"
5152   [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
5153         (match_operand:SI 1 "general_operand"      "rk, I,K,j,mi,rk"))]
5154   "TARGET_ARM && ! TARGET_IWMMXT
5155    && !(TARGET_HARD_FLOAT && TARGET_VFP)
5156    && (   register_operand (operands[0], SImode)
5157        || register_operand (operands[1], SImode))"
5158   "@
5159    mov%?\\t%0, %1
5160    mov%?\\t%0, %1
5161    mvn%?\\t%0, #%B1
5162    movw%?\\t%0, %1
5163    ldr%?\\t%0, %1
5164    str%?\\t%1, %0"
5165   [(set_attr "type" "*,*,*,*,load1,store1")
5166    (set_attr "predicable" "yes")
5167    (set_attr "pool_range" "*,*,*,*,4096,*")
5168    (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
5169 )
5170
5171 (define_split
5172   [(set (match_operand:SI 0 "arm_general_register_operand" "")
5173         (match_operand:SI 1 "const_int_operand" ""))]
5174   "TARGET_32BIT
5175   && (!(const_ok_for_arm (INTVAL (operands[1]))
5176         || const_ok_for_arm (~INTVAL (operands[1]))))"
5177   [(clobber (const_int 0))]
5178   "
5179   arm_split_constant (SET, SImode, NULL_RTX, 
5180                       INTVAL (operands[1]), operands[0], NULL_RTX, 0);
5181   DONE;
5182   "
5183 )
5184
5185 (define_insn "*thumb1_movsi_insn"
5186   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lhk")
5187         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lhk"))]
5188   "TARGET_THUMB1
5189    && (   register_operand (operands[0], SImode) 
5190        || register_operand (operands[1], SImode))"
5191   "@
5192    mov  %0, %1
5193    mov  %0, %1
5194    #
5195    #
5196    ldmia\\t%1, {%0}
5197    stmia\\t%0, {%1}
5198    ldr\\t%0, %1
5199    str\\t%1, %0
5200    mov\\t%0, %1"
5201   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
5202    (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
5203    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
5204 )
5205
5206 (define_split 
5207   [(set (match_operand:SI 0 "register_operand" "")
5208         (match_operand:SI 1 "const_int_operand" ""))]
5209   "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
5210   [(set (match_dup 0) (match_dup 1))
5211    (set (match_dup 0) (neg:SI (match_dup 0)))]
5212   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
5213 )
5214
5215 (define_split 
5216   [(set (match_operand:SI 0 "register_operand" "")
5217         (match_operand:SI 1 "const_int_operand" ""))]
5218   "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
5219   [(set (match_dup 0) (match_dup 1))
5220    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
5221   "
5222   {
5223     unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu;
5224     unsigned HOST_WIDE_INT mask = 0xff;
5225     int i;
5226     
5227     for (i = 0; i < 25; i++)
5228       if ((val & (mask << i)) == val)
5229         break;
5230
5231     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
5232     if (i == 0)
5233       FAIL;
5234
5235     operands[1] = GEN_INT (val >> i);
5236     operands[2] = GEN_INT (i);
5237   }"
5238 )
5239
5240 ;; When generating pic, we need to load the symbol offset into a register.
5241 ;; So that the optimizer does not confuse this with a normal symbol load
5242 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
5243 ;; since that is the only type of relocation we can use.
5244
5245 ;; The rather odd constraints on the following are to force reload to leave
5246 ;; the insn alone, and to force the minipool generation pass to then move
5247 ;; the GOT symbol to memory.
5248
5249 (define_insn "pic_load_addr_32bit"
5250   [(set (match_operand:SI 0 "s_register_operand" "=r")
5251         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
5252   "TARGET_32BIT && flag_pic"
5253   "ldr%?\\t%0, %1"
5254   [(set_attr "type" "load1")
5255    (set_attr "pool_range" "4096")
5256    (set (attr "neg_pool_range")
5257         (if_then_else (eq_attr "is_thumb" "no")
5258                       (const_int 4084)
5259                       (const_int 0)))]
5260 )
5261
5262 (define_insn "pic_load_addr_thumb1"
5263   [(set (match_operand:SI 0 "s_register_operand" "=l")
5264         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
5265   "TARGET_THUMB1 && flag_pic"
5266   "ldr\\t%0, %1"
5267   [(set_attr "type" "load1")
5268    (set (attr "pool_range") (const_int 1024))]
5269 )
5270
5271 (define_insn "pic_add_dot_plus_four"
5272   [(set (match_operand:SI 0 "register_operand" "=r")
5273         (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5274                     (const_int 4)
5275                     (match_operand 2 "" "")]
5276                    UNSPEC_PIC_BASE))]
5277   "TARGET_THUMB"
5278   "*
5279   (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5280                                      INTVAL (operands[2]));
5281   return \"add\\t%0, %|pc\";
5282   "
5283   [(set_attr "length" "2")]
5284 )
5285
5286 (define_insn "pic_add_dot_plus_eight"
5287   [(set (match_operand:SI 0 "register_operand" "=r")
5288         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5289                     (const_int 8)
5290                     (match_operand 2 "" "")]
5291                    UNSPEC_PIC_BASE))]
5292   "TARGET_ARM"
5293   "*
5294     (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5295                                        INTVAL (operands[2]));
5296     return \"add%?\\t%0, %|pc, %1\";
5297   "
5298   [(set_attr "predicable" "yes")]
5299 )
5300
5301 (define_insn "tls_load_dot_plus_eight"
5302   [(set (match_operand:SI 0 "register_operand" "=r")
5303         (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5304                             (const_int 8)
5305                             (match_operand 2 "" "")]
5306                            UNSPEC_PIC_BASE)))]
5307   "TARGET_ARM"
5308   "*
5309     (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5310                                        INTVAL (operands[2]));
5311     return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5312   "
5313   [(set_attr "predicable" "yes")]
5314 )
5315
5316 ;; PIC references to local variables can generate pic_add_dot_plus_eight
5317 ;; followed by a load.  These sequences can be crunched down to
5318 ;; tls_load_dot_plus_eight by a peephole.
5319
5320 (define_peephole2
5321   [(set (match_operand:SI 0 "register_operand" "")
5322         (unspec:SI [(match_operand:SI 3 "register_operand" "")
5323                     (const_int 8)
5324                     (match_operand 1 "" "")]
5325                    UNSPEC_PIC_BASE))
5326    (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
5327   "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
5328   [(set (match_dup 2)
5329         (mem:SI (unspec:SI [(match_dup 3)
5330                             (const_int 8)
5331                             (match_dup 1)]
5332                            UNSPEC_PIC_BASE)))]
5333   ""
5334 )
5335
5336 (define_insn "pic_offset_arm"
5337   [(set (match_operand:SI 0 "register_operand" "=r")
5338         (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5339                          (unspec:SI [(match_operand:SI 2 "" "X")]
5340                                     UNSPEC_PIC_OFFSET))))]
5341   "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5342   "ldr%?\\t%0, [%1,%2]"
5343   [(set_attr "type" "load1")]
5344 )
5345
5346 (define_expand "builtin_setjmp_receiver"
5347   [(label_ref (match_operand 0 "" ""))]
5348   "flag_pic"
5349   "
5350 {
5351   /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5352      register.  */
5353   if (arm_pic_register != INVALID_REGNUM)
5354     arm_load_pic_register (1UL << 3);
5355   DONE;
5356 }")
5357
5358 ;; If copying one reg to another we can set the condition codes according to
5359 ;; its value.  Such a move is common after a return from subroutine and the
5360 ;; result is being tested against zero.
5361
5362 (define_insn "*movsi_compare0"
5363   [(set (reg:CC CC_REGNUM)
5364         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5365                     (const_int 0)))
5366    (set (match_operand:SI 0 "s_register_operand" "=r,r")
5367         (match_dup 1))]
5368   "TARGET_32BIT"
5369   "@
5370    cmp%?\\t%0, #0
5371    sub%.\\t%0, %1, #0"
5372   [(set_attr "conds" "set")]
5373 )
5374
5375 ;; Subroutine to store a half word from a register into memory.
5376 ;; Operand 0 is the source register (HImode)
5377 ;; Operand 1 is the destination address in a register (SImode)
5378
5379 ;; In both this routine and the next, we must be careful not to spill
5380 ;; a memory address of reg+large_const into a separate PLUS insn, since this
5381 ;; can generate unrecognizable rtl.
5382
5383 (define_expand "storehi"
5384   [;; store the low byte
5385    (set (match_operand 1 "" "") (match_dup 3))
5386    ;; extract the high byte
5387    (set (match_dup 2)
5388         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
5389    ;; store the high byte
5390    (set (match_dup 4) (match_dup 5))]
5391   "TARGET_ARM"
5392   "
5393   {
5394     rtx op1 = operands[1];
5395     rtx addr = XEXP (op1, 0);
5396     enum rtx_code code = GET_CODE (addr);
5397
5398     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5399         || code == MINUS)
5400       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
5401
5402     operands[4] = adjust_address (op1, QImode, 1);
5403     operands[1] = adjust_address (operands[1], QImode, 0);
5404     operands[3] = gen_lowpart (QImode, operands[0]);
5405     operands[0] = gen_lowpart (SImode, operands[0]);
5406     operands[2] = gen_reg_rtx (SImode);
5407     operands[5] = gen_lowpart (QImode, operands[2]);
5408   }"
5409 )
5410
5411 (define_expand "storehi_bigend"
5412   [(set (match_dup 4) (match_dup 3))
5413    (set (match_dup 2)
5414         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
5415    (set (match_operand 1 "" "") (match_dup 5))]
5416   "TARGET_ARM"
5417   "
5418   {
5419     rtx op1 = operands[1];
5420     rtx addr = XEXP (op1, 0);
5421     enum rtx_code code = GET_CODE (addr);
5422
5423     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5424         || code == MINUS)
5425       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
5426
5427     operands[4] = adjust_address (op1, QImode, 1);
5428     operands[1] = adjust_address (operands[1], QImode, 0);
5429     operands[3] = gen_lowpart (QImode, operands[0]);
5430     operands[0] = gen_lowpart (SImode, operands[0]);
5431     operands[2] = gen_reg_rtx (SImode);
5432     operands[5] = gen_lowpart (QImode, operands[2]);
5433   }"
5434 )
5435
5436 ;; Subroutine to store a half word integer constant into memory.
5437 (define_expand "storeinthi"
5438   [(set (match_operand 0 "" "")
5439         (match_operand 1 "" ""))
5440    (set (match_dup 3) (match_dup 2))]
5441   "TARGET_ARM"
5442   "
5443   {
5444     HOST_WIDE_INT value = INTVAL (operands[1]);
5445     rtx addr = XEXP (operands[0], 0);
5446     rtx op0 = operands[0];
5447     enum rtx_code code = GET_CODE (addr);
5448
5449     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5450         || code == MINUS)
5451       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
5452
5453     operands[1] = gen_reg_rtx (SImode);
5454     if (BYTES_BIG_ENDIAN)
5455       {
5456         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5457         if ((value & 255) == ((value >> 8) & 255))
5458           operands[2] = operands[1];
5459         else
5460           {
5461             operands[2] = gen_reg_rtx (SImode);
5462             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5463           }
5464       }
5465     else
5466       {
5467         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5468         if ((value & 255) == ((value >> 8) & 255))
5469           operands[2] = operands[1];
5470         else
5471           {
5472             operands[2] = gen_reg_rtx (SImode);
5473             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5474           }
5475       }
5476
5477     operands[3] = adjust_address (op0, QImode, 1);
5478     operands[0] = adjust_address (operands[0], QImode, 0);
5479     operands[2] = gen_lowpart (QImode, operands[2]);
5480     operands[1] = gen_lowpart (QImode, operands[1]);
5481   }"
5482 )
5483
5484 (define_expand "storehi_single_op"
5485   [(set (match_operand:HI 0 "memory_operand" "")
5486         (match_operand:HI 1 "general_operand" ""))]
5487   "TARGET_32BIT && arm_arch4"
5488   "
5489   if (!s_register_operand (operands[1], HImode))
5490     operands[1] = copy_to_mode_reg (HImode, operands[1]);
5491   "
5492 )
5493
5494 (define_expand "movhi"
5495   [(set (match_operand:HI 0 "general_operand" "")
5496         (match_operand:HI 1 "general_operand" ""))]
5497   "TARGET_EITHER"
5498   "
5499   if (TARGET_ARM)
5500     {
5501       if (can_create_pseudo_p ())
5502         {
5503           if (GET_CODE (operands[0]) == MEM)
5504             {
5505               if (arm_arch4)
5506                 {
5507                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5508                   DONE;
5509                 }
5510               if (GET_CODE (operands[1]) == CONST_INT)
5511                 emit_insn (gen_storeinthi (operands[0], operands[1]));
5512               else
5513                 {
5514                   if (GET_CODE (operands[1]) == MEM)
5515                     operands[1] = force_reg (HImode, operands[1]);
5516                   if (BYTES_BIG_ENDIAN)
5517                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
5518                   else
5519                    emit_insn (gen_storehi (operands[1], operands[0]));
5520                 }
5521               DONE;
5522             }
5523           /* Sign extend a constant, and keep it in an SImode reg.  */
5524           else if (GET_CODE (operands[1]) == CONST_INT)
5525             {
5526               rtx reg = gen_reg_rtx (SImode);
5527               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5528
5529               /* If the constant is already valid, leave it alone.  */
5530               if (!const_ok_for_arm (val))
5531                 {
5532                   /* If setting all the top bits will make the constant 
5533                      loadable in a single instruction, then set them.  
5534                      Otherwise, sign extend the number.  */
5535
5536                   if (const_ok_for_arm (~(val | ~0xffff)))
5537                     val |= ~0xffff;
5538                   else if (val & 0x8000)
5539                     val |= ~0xffff;
5540                 }
5541
5542               emit_insn (gen_movsi (reg, GEN_INT (val)));
5543               operands[1] = gen_lowpart (HImode, reg);
5544             }
5545           else if (arm_arch4 && optimize && can_create_pseudo_p ()
5546                    && GET_CODE (operands[1]) == MEM)
5547             {
5548               rtx reg = gen_reg_rtx (SImode);
5549
5550               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5551               operands[1] = gen_lowpart (HImode, reg);
5552             }
5553           else if (!arm_arch4)
5554             {
5555               if (GET_CODE (operands[1]) == MEM)
5556                 {
5557                   rtx base;
5558                   rtx offset = const0_rtx;
5559                   rtx reg = gen_reg_rtx (SImode);
5560
5561                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
5562                        || (GET_CODE (base) == PLUS
5563                            && (GET_CODE (offset = XEXP (base, 1))
5564                                == CONST_INT)
5565                            && ((INTVAL(offset) & 1) != 1)
5566                            && GET_CODE (base = XEXP (base, 0)) == REG))
5567                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
5568                     {
5569                       rtx new_rtx;
5570
5571                       new_rtx = widen_memory_access (operands[1], SImode,
5572                                                      ((INTVAL (offset) & ~3)
5573                                                       - INTVAL (offset)));
5574                       emit_insn (gen_movsi (reg, new_rtx));
5575                       if (((INTVAL (offset) & 2) != 0)
5576                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
5577                         {
5578                           rtx reg2 = gen_reg_rtx (SImode);
5579
5580                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
5581                           reg = reg2;
5582                         }
5583                     }
5584                   else
5585                     emit_insn (gen_movhi_bytes (reg, operands[1]));
5586
5587                   operands[1] = gen_lowpart (HImode, reg);
5588                }
5589            }
5590         }
5591       /* Handle loading a large integer during reload.  */
5592       else if (GET_CODE (operands[1]) == CONST_INT
5593                && !const_ok_for_arm (INTVAL (operands[1]))
5594                && !const_ok_for_arm (~INTVAL (operands[1])))
5595         {
5596           /* Writing a constant to memory needs a scratch, which should
5597              be handled with SECONDARY_RELOADs.  */
5598           gcc_assert (GET_CODE (operands[0]) == REG);
5599
5600           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5601           emit_insn (gen_movsi (operands[0], operands[1]));
5602           DONE;
5603        }
5604     }
5605   else if (TARGET_THUMB2)
5606     {
5607       /* Thumb-2 can do everything except mem=mem and mem=const easily.  */
5608       if (can_create_pseudo_p ())
5609         {
5610           if (GET_CODE (operands[0]) != REG)
5611             operands[1] = force_reg (HImode, operands[1]);
5612           /* Zero extend a constant, and keep it in an SImode reg.  */
5613           else if (GET_CODE (operands[1]) == CONST_INT)
5614             {
5615               rtx reg = gen_reg_rtx (SImode);
5616               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5617
5618               emit_insn (gen_movsi (reg, GEN_INT (val)));
5619               operands[1] = gen_lowpart (HImode, reg);
5620             }
5621         }
5622     }
5623   else /* TARGET_THUMB1 */
5624     {
5625       if (can_create_pseudo_p ())
5626         {
5627           if (GET_CODE (operands[1]) == CONST_INT)
5628             {
5629               rtx reg = gen_reg_rtx (SImode);
5630
5631               emit_insn (gen_movsi (reg, operands[1]));
5632               operands[1] = gen_lowpart (HImode, reg);
5633             }
5634
5635           /* ??? We shouldn't really get invalid addresses here, but this can
5636              happen if we are passed a SP (never OK for HImode/QImode) or 
5637              virtual register (also rejected as illegitimate for HImode/QImode)
5638              relative address.  */
5639           /* ??? This should perhaps be fixed elsewhere, for instance, in
5640              fixup_stack_1, by checking for other kinds of invalid addresses,
5641              e.g. a bare reference to a virtual register.  This may confuse the
5642              alpha though, which must handle this case differently.  */
5643           if (GET_CODE (operands[0]) == MEM
5644               && !memory_address_p (GET_MODE (operands[0]),
5645                                     XEXP (operands[0], 0)))
5646             operands[0]
5647               = replace_equiv_address (operands[0],
5648                                        copy_to_reg (XEXP (operands[0], 0)));
5649    
5650           if (GET_CODE (operands[1]) == MEM
5651               && !memory_address_p (GET_MODE (operands[1]),
5652                                     XEXP (operands[1], 0)))
5653             operands[1]
5654               = replace_equiv_address (operands[1],
5655                                        copy_to_reg (XEXP (operands[1], 0)));
5656
5657           if (GET_CODE (operands[1]) == MEM && optimize > 0)
5658             {
5659               rtx reg = gen_reg_rtx (SImode);
5660
5661               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5662               operands[1] = gen_lowpart (HImode, reg);
5663             }
5664
5665           if (GET_CODE (operands[0]) == MEM)
5666             operands[1] = force_reg (HImode, operands[1]);
5667         }
5668       else if (GET_CODE (operands[1]) == CONST_INT
5669                 && !satisfies_constraint_I (operands[1]))
5670         {
5671           /* Handle loading a large integer during reload.  */
5672
5673           /* Writing a constant to memory needs a scratch, which should
5674              be handled with SECONDARY_RELOADs.  */
5675           gcc_assert (GET_CODE (operands[0]) == REG);
5676
5677           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5678           emit_insn (gen_movsi (operands[0], operands[1]));
5679           DONE;
5680         }
5681     }
5682   "
5683 )
5684
5685 (define_insn "*thumb1_movhi_insn"
5686   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5687         (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
5688   "TARGET_THUMB1
5689    && (   register_operand (operands[0], HImode)
5690        || register_operand (operands[1], HImode))"
5691   "*
5692   switch (which_alternative)
5693     {
5694     case 0: return \"add        %0, %1, #0\";
5695     case 2: return \"strh       %1, %0\";
5696     case 3: return \"mov        %0, %1\";
5697     case 4: return \"mov        %0, %1\";
5698     case 5: return \"mov        %0, %1\";
5699     default: gcc_unreachable ();
5700     case 1:
5701       /* The stack pointer can end up being taken as an index register.
5702           Catch this case here and deal with it.  */
5703       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
5704           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
5705           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
5706         {
5707           rtx ops[2];
5708           ops[0] = operands[0];
5709           ops[1] = XEXP (XEXP (operands[1], 0), 0);
5710       
5711           output_asm_insn (\"mov        %0, %1\", ops);
5712
5713           XEXP (XEXP (operands[1], 0), 0) = operands[0];
5714     
5715         }
5716       return \"ldrh     %0, %1\";
5717     }"
5718   [(set_attr "length" "2,4,2,2,2,2")
5719    (set_attr "type" "*,load1,store1,*,*,*")]
5720 )
5721
5722
5723 (define_expand "movhi_bytes"
5724   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
5725    (set (match_dup 3)
5726         (zero_extend:SI (match_dup 6)))
5727    (set (match_operand:SI 0 "" "")
5728          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
5729   "TARGET_ARM"
5730   "
5731   {
5732     rtx mem1, mem2;
5733     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5734
5735     mem1 = change_address (operands[1], QImode, addr);
5736     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
5737     operands[0] = gen_lowpart (SImode, operands[0]);
5738     operands[1] = mem1;
5739     operands[2] = gen_reg_rtx (SImode);
5740     operands[3] = gen_reg_rtx (SImode);
5741     operands[6] = mem2;
5742
5743     if (BYTES_BIG_ENDIAN)
5744       {
5745         operands[4] = operands[2];
5746         operands[5] = operands[3];
5747       }
5748     else
5749       {
5750         operands[4] = operands[3];
5751         operands[5] = operands[2];
5752       }
5753   }"
5754 )
5755
5756 (define_expand "movhi_bigend"
5757   [(set (match_dup 2)
5758         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
5759                    (const_int 16)))
5760    (set (match_dup 3)
5761         (ashiftrt:SI (match_dup 2) (const_int 16)))
5762    (set (match_operand:HI 0 "s_register_operand" "")
5763         (match_dup 4))]
5764   "TARGET_ARM"
5765   "
5766   operands[2] = gen_reg_rtx (SImode);
5767   operands[3] = gen_reg_rtx (SImode);
5768   operands[4] = gen_lowpart (HImode, operands[3]);
5769   "
5770 )
5771
5772 ;; Pattern to recognize insn generated default case above
5773 (define_insn "*movhi_insn_arch4"
5774   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
5775         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
5776   "TARGET_ARM
5777    && arm_arch4
5778    && (GET_CODE (operands[1]) != CONST_INT
5779        || const_ok_for_arm (INTVAL (operands[1]))
5780        || const_ok_for_arm (~INTVAL (operands[1])))"
5781   "@
5782    mov%?\\t%0, %1\\t%@ movhi
5783    mvn%?\\t%0, #%B1\\t%@ movhi
5784    str%(h%)\\t%1, %0\\t%@ movhi
5785    ldr%(h%)\\t%0, %1\\t%@ movhi"
5786   [(set_attr "type" "*,*,store1,load1")
5787    (set_attr "predicable" "yes")
5788    (set_attr "pool_range" "*,*,*,256")
5789    (set_attr "neg_pool_range" "*,*,*,244")]
5790 )
5791
5792 (define_insn "*movhi_bytes"
5793   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
5794         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
5795   "TARGET_ARM"
5796   "@
5797    mov%?\\t%0, %1\\t%@ movhi
5798    mvn%?\\t%0, #%B1\\t%@ movhi"
5799   [(set_attr "predicable" "yes")]
5800 )
5801
5802 (define_expand "thumb_movhi_clobber"
5803   [(set (match_operand:HI     0 "memory_operand"   "")
5804         (match_operand:HI     1 "register_operand" ""))
5805    (clobber (match_operand:DI 2 "register_operand" ""))]
5806   "TARGET_THUMB1"
5807   "
5808   if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
5809       && REGNO (operands[1]) <= LAST_LO_REGNUM)
5810     {
5811       emit_insn (gen_movhi (operands[0], operands[1]));
5812       DONE;
5813     }
5814   /* XXX Fixme, need to handle other cases here as well.  */
5815   gcc_unreachable ();
5816   "
5817 )
5818         
5819 ;; We use a DImode scratch because we may occasionally need an additional
5820 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
5821 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
5822 (define_expand "reload_outhi"
5823   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
5824               (match_operand:HI 1 "s_register_operand"        "r")
5825               (match_operand:DI 2 "s_register_operand"        "=&l")])]
5826   "TARGET_EITHER"
5827   "if (TARGET_ARM)
5828      arm_reload_out_hi (operands);
5829    else
5830      thumb_reload_out_hi (operands);
5831   DONE;
5832   "
5833 )
5834
5835 (define_expand "reload_inhi"
5836   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
5837               (match_operand:HI 1 "arm_reload_memory_operand" "o")
5838               (match_operand:DI 2 "s_register_operand" "=&r")])]
5839   "TARGET_EITHER"
5840   "
5841   if (TARGET_ARM)
5842     arm_reload_in_hi (operands);
5843   else
5844     thumb_reload_out_hi (operands);
5845   DONE;
5846 ")
5847
5848 (define_expand "movqi"
5849   [(set (match_operand:QI 0 "general_operand" "")
5850         (match_operand:QI 1 "general_operand" ""))]
5851   "TARGET_EITHER"
5852   "
5853   /* Everything except mem = const or mem = mem can be done easily */
5854
5855   if (can_create_pseudo_p ())
5856     {
5857       if (GET_CODE (operands[1]) == CONST_INT)
5858         {
5859           rtx reg = gen_reg_rtx (SImode);
5860
5861           /* For thumb we want an unsigned immediate, then we are more likely 
5862              to be able to use a movs insn.  */
5863           if (TARGET_THUMB)
5864             operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
5865
5866           emit_insn (gen_movsi (reg, operands[1]));
5867           operands[1] = gen_lowpart (QImode, reg);
5868         }
5869
5870       if (TARGET_THUMB)
5871         {
5872           /* ??? We shouldn't really get invalid addresses here, but this can
5873              happen if we are passed a SP (never OK for HImode/QImode) or
5874              virtual register (also rejected as illegitimate for HImode/QImode)
5875              relative address.  */
5876           /* ??? This should perhaps be fixed elsewhere, for instance, in
5877              fixup_stack_1, by checking for other kinds of invalid addresses,
5878              e.g. a bare reference to a virtual register.  This may confuse the
5879              alpha though, which must handle this case differently.  */
5880           if (GET_CODE (operands[0]) == MEM
5881               && !memory_address_p (GET_MODE (operands[0]),
5882                                      XEXP (operands[0], 0)))
5883             operands[0]
5884               = replace_equiv_address (operands[0],
5885                                        copy_to_reg (XEXP (operands[0], 0)));
5886           if (GET_CODE (operands[1]) == MEM
5887               && !memory_address_p (GET_MODE (operands[1]),
5888                                     XEXP (operands[1], 0)))
5889              operands[1]
5890                = replace_equiv_address (operands[1],
5891                                         copy_to_reg (XEXP (operands[1], 0)));
5892         }
5893
5894       if (GET_CODE (operands[1]) == MEM && optimize > 0)
5895         {
5896           rtx reg = gen_reg_rtx (SImode);
5897
5898           emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5899           operands[1] = gen_lowpart (QImode, reg);
5900         }
5901
5902       if (GET_CODE (operands[0]) == MEM)
5903         operands[1] = force_reg (QImode, operands[1]);
5904     }
5905   else if (TARGET_THUMB
5906            && GET_CODE (operands[1]) == CONST_INT
5907            && !satisfies_constraint_I (operands[1]))
5908     {
5909       /* Handle loading a large integer during reload.  */
5910
5911       /* Writing a constant to memory needs a scratch, which should
5912          be handled with SECONDARY_RELOADs.  */
5913       gcc_assert (GET_CODE (operands[0]) == REG);
5914
5915       operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5916       emit_insn (gen_movsi (operands[0], operands[1]));
5917       DONE;
5918     }
5919   "
5920 )
5921
5922
5923 (define_insn "*arm_movqi_insn"
5924   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5925         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5926   "TARGET_32BIT
5927    && (   register_operand (operands[0], QImode)
5928        || register_operand (operands[1], QImode))"
5929   "@
5930    mov%?\\t%0, %1
5931    mvn%?\\t%0, #%B1
5932    ldr%(b%)\\t%0, %1
5933    str%(b%)\\t%1, %0"
5934   [(set_attr "type" "*,*,load1,store1")
5935    (set_attr "predicable" "yes")]
5936 )
5937
5938 (define_insn "*thumb1_movqi_insn"
5939   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5940         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
5941   "TARGET_THUMB1
5942    && (   register_operand (operands[0], QImode)
5943        || register_operand (operands[1], QImode))"
5944   "@
5945    add\\t%0, %1, #0
5946    ldrb\\t%0, %1
5947    strb\\t%1, %0
5948    mov\\t%0, %1
5949    mov\\t%0, %1
5950    mov\\t%0, %1"
5951   [(set_attr "length" "2")
5952    (set_attr "type" "*,load1,store1,*,*,*")
5953    (set_attr "pool_range" "*,32,*,*,*,*")]
5954 )
5955
5956 ;; HFmode moves
5957 (define_expand "movhf"
5958   [(set (match_operand:HF 0 "general_operand" "")
5959         (match_operand:HF 1 "general_operand" ""))]
5960   "TARGET_EITHER"
5961   "
5962   if (TARGET_32BIT)
5963     {
5964       if (GET_CODE (operands[0]) == MEM)
5965         operands[1] = force_reg (HFmode, operands[1]);
5966     }
5967   else /* TARGET_THUMB1 */
5968     {
5969       if (can_create_pseudo_p ())
5970         {
5971            if (GET_CODE (operands[0]) != REG)
5972              operands[1] = force_reg (HFmode, operands[1]);
5973         }
5974     }
5975   "
5976 )
5977
5978 (define_insn "*arm32_movhf"
5979   [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
5980         (match_operand:HF 1 "general_operand"      " m,r,r,F"))]
5981   "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16)
5982    && (   s_register_operand (operands[0], HFmode)
5983        || s_register_operand (operands[1], HFmode))"
5984   "*
5985   switch (which_alternative)
5986     {
5987     case 0:     /* ARM register from memory */
5988       return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
5989     case 1:     /* memory from ARM register */
5990       return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
5991     case 2:     /* ARM register from ARM register */
5992       return \"mov%?\\t%0, %1\\t%@ __fp16\";
5993     case 3:     /* ARM register from constant */
5994       {
5995         REAL_VALUE_TYPE r;
5996         long bits;
5997         rtx ops[4];
5998
5999         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
6000         bits = real_to_target (NULL, &r, HFmode);
6001         ops[0] = operands[0];
6002         ops[1] = GEN_INT (bits);
6003         ops[2] = GEN_INT (bits & 0xff00);
6004         ops[3] = GEN_INT (bits & 0x00ff);
6005
6006         if (arm_arch_thumb2)
6007           output_asm_insn (\"movw%?\\t%0, %1\", ops);
6008         else
6009           output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6010         return \"\";
6011        }
6012     default:
6013       gcc_unreachable ();
6014     }
6015   "
6016   [(set_attr "conds" "unconditional")
6017    (set_attr "type" "load1,store1,*,*")
6018    (set_attr "length" "4,4,4,8")
6019    (set_attr "predicable" "yes")
6020    ]
6021 )
6022
6023 (define_insn "*thumb1_movhf"
6024   [(set (match_operand:HF     0 "nonimmediate_operand" "=l,l,m,*r,*h")
6025         (match_operand:HF     1 "general_operand"      "l,mF,l,*h,*r"))]
6026   "TARGET_THUMB1
6027    && (   s_register_operand (operands[0], HFmode) 
6028        || s_register_operand (operands[1], HFmode))"
6029   "*
6030   switch (which_alternative)
6031     {
6032     case 1:
6033       {
6034         rtx addr;
6035         gcc_assert (GET_CODE(operands[1]) == MEM);
6036         addr = XEXP (operands[1], 0);
6037         if (GET_CODE (addr) == LABEL_REF
6038             || (GET_CODE (addr) == CONST
6039                 && GET_CODE (XEXP (addr, 0)) == PLUS
6040                 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF
6041                 && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT))
6042           {
6043             /* Constant pool entry.  */
6044             return \"ldr\\t%0, %1\";
6045           }
6046         return \"ldrh\\t%0, %1\";
6047       }
6048     case 2: return \"strh\\t%1, %0\";
6049     default: return \"mov\\t%0, %1\";
6050     }
6051   "
6052   [(set_attr "length" "2")
6053    (set_attr "type" "*,load1,store1,*,*")
6054    (set_attr "pool_range" "*,1020,*,*,*")]
6055 )
6056
6057 (define_expand "movsf"
6058   [(set (match_operand:SF 0 "general_operand" "")
6059         (match_operand:SF 1 "general_operand" ""))]
6060   "TARGET_EITHER"
6061   "
6062   if (TARGET_32BIT)
6063     {
6064       if (GET_CODE (operands[0]) == MEM)
6065         operands[1] = force_reg (SFmode, operands[1]);
6066     }
6067   else /* TARGET_THUMB1 */
6068     {
6069       if (can_create_pseudo_p ())
6070         {
6071            if (GET_CODE (operands[0]) != REG)
6072              operands[1] = force_reg (SFmode, operands[1]);
6073         }
6074     }
6075   "
6076 )
6077
6078 ;; Transform a floating-point move of a constant into a core register into
6079 ;; an SImode operation.
6080 (define_split
6081   [(set (match_operand:SF 0 "arm_general_register_operand" "")
6082         (match_operand:SF 1 "immediate_operand" ""))]
6083   "TARGET_EITHER
6084    && reload_completed
6085    && GET_CODE (operands[1]) == CONST_DOUBLE"
6086   [(set (match_dup 2) (match_dup 3))]
6087   "
6088   operands[2] = gen_lowpart (SImode, operands[0]);
6089   operands[3] = gen_lowpart (SImode, operands[1]);
6090   if (operands[2] == 0 || operands[3] == 0)
6091     FAIL;
6092   "
6093 )
6094
6095 (define_insn "*arm_movsf_soft_insn"
6096   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6097         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
6098   "TARGET_ARM
6099    && TARGET_SOFT_FLOAT
6100    && (GET_CODE (operands[0]) != MEM
6101        || register_operand (operands[1], SFmode))"
6102   "@
6103    mov%?\\t%0, %1
6104    ldr%?\\t%0, %1\\t%@ float
6105    str%?\\t%1, %0\\t%@ float"
6106   [(set_attr "length" "4,4,4")
6107    (set_attr "predicable" "yes")
6108    (set_attr "type" "*,load1,store1")
6109    (set_attr "pool_range" "*,4096,*")
6110    (set_attr "neg_pool_range" "*,4084,*")]
6111 )
6112
6113 ;;; ??? This should have alternatives for constants.
6114 (define_insn "*thumb1_movsf_insn"
6115   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
6116         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
6117   "TARGET_THUMB1
6118    && (   register_operand (operands[0], SFmode) 
6119        || register_operand (operands[1], SFmode))"
6120   "@
6121    add\\t%0, %1, #0
6122    ldmia\\t%1, {%0}
6123    stmia\\t%0, {%1}
6124    ldr\\t%0, %1
6125    str\\t%1, %0
6126    mov\\t%0, %1
6127    mov\\t%0, %1"
6128   [(set_attr "length" "2")
6129    (set_attr "type" "*,load1,store1,load1,store1,*,*")
6130    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
6131 )
6132
6133 (define_expand "movdf"
6134   [(set (match_operand:DF 0 "general_operand" "")
6135         (match_operand:DF 1 "general_operand" ""))]
6136   "TARGET_EITHER"
6137   "
6138   if (TARGET_32BIT)
6139     {
6140       if (GET_CODE (operands[0]) == MEM)
6141         operands[1] = force_reg (DFmode, operands[1]);
6142     }
6143   else /* TARGET_THUMB */
6144     {
6145       if (can_create_pseudo_p ())
6146         {
6147           if (GET_CODE (operands[0]) != REG)
6148             operands[1] = force_reg (DFmode, operands[1]);
6149         }
6150     }
6151   "
6152 )
6153
6154 ;; Reloading a df mode value stored in integer regs to memory can require a
6155 ;; scratch reg.
6156 (define_expand "reload_outdf"
6157   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
6158    (match_operand:DF 1 "s_register_operand" "r")
6159    (match_operand:SI 2 "s_register_operand" "=&r")]
6160   "TARGET_32BIT"
6161   "
6162   {
6163     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
6164
6165     if (code == REG)
6166       operands[2] = XEXP (operands[0], 0);
6167     else if (code == POST_INC || code == PRE_DEC)
6168       {
6169         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6170         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6171         emit_insn (gen_movdi (operands[0], operands[1]));
6172         DONE;
6173       }
6174     else if (code == PRE_INC)
6175       {
6176         rtx reg = XEXP (XEXP (operands[0], 0), 0);
6177
6178         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6179         operands[2] = reg;
6180       }
6181     else if (code == POST_DEC)
6182       operands[2] = XEXP (XEXP (operands[0], 0), 0);
6183     else
6184       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6185                              XEXP (XEXP (operands[0], 0), 1)));
6186
6187     emit_insn (gen_rtx_SET (VOIDmode,
6188                             replace_equiv_address (operands[0], operands[2]),
6189                             operands[1]));
6190
6191     if (code == POST_DEC)
6192       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6193
6194     DONE;
6195   }"
6196 )
6197
6198 (define_insn "*movdf_soft_insn"
6199   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
6200         (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
6201   "TARGET_ARM && TARGET_SOFT_FLOAT
6202    && (   register_operand (operands[0], DFmode)
6203        || register_operand (operands[1], DFmode))"
6204   "*
6205   switch (which_alternative)
6206     {
6207     case 0:
6208     case 1:
6209     case 2:
6210       return \"#\";
6211     default:
6212       return output_move_double (operands);
6213     }
6214   "
6215   [(set_attr "length" "8,12,16,8,8")
6216    (set_attr "type" "*,*,*,load2,store2")
6217    (set_attr "pool_range" "1020")
6218    (set_attr "neg_pool_range" "1008")]
6219 )
6220
6221 ;;; ??? This should have alternatives for constants.
6222 ;;; ??? This was originally identical to the movdi_insn pattern.
6223 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
6224 ;;; thumb_reorg with a memory reference.
6225 (define_insn "*thumb_movdf_insn"
6226   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
6227         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
6228   "TARGET_THUMB1
6229    && (   register_operand (operands[0], DFmode)
6230        || register_operand (operands[1], DFmode))"
6231   "*
6232   switch (which_alternative)
6233     {
6234     default:
6235     case 0:
6236       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6237         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
6238       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
6239     case 1:
6240       return \"ldmia\\t%1, {%0, %H0}\";
6241     case 2:
6242       return \"stmia\\t%0, {%1, %H1}\";
6243     case 3:
6244       return thumb_load_double_from_address (operands);
6245     case 4:
6246       operands[2] = gen_rtx_MEM (SImode,
6247                                  plus_constant (XEXP (operands[0], 0), 4));
6248       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
6249       return \"\";
6250     case 5:
6251       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6252         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
6253       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
6254     }
6255   "
6256   [(set_attr "length" "4,2,2,6,4,4")
6257    (set_attr "type" "*,load2,store2,load2,store2,*")
6258    (set_attr "pool_range" "*,*,*,1020,*,*")]
6259 )
6260
6261 (define_expand "movxf"
6262   [(set (match_operand:XF 0 "general_operand" "")
6263         (match_operand:XF 1 "general_operand" ""))]
6264   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
6265   "
6266   if (GET_CODE (operands[0]) == MEM)
6267     operands[1] = force_reg (XFmode, operands[1]);
6268   "
6269 )
6270
6271 \f
6272
6273 ;; load- and store-multiple insns
6274 ;; The arm can load/store any set of registers, provided that they are in
6275 ;; ascending order; but that is beyond GCC so stick with what it knows.
6276
6277 (define_expand "load_multiple"
6278   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6279                           (match_operand:SI 1 "" ""))
6280                      (use (match_operand:SI 2 "" ""))])]
6281   "TARGET_32BIT"
6282 {
6283   HOST_WIDE_INT offset = 0;
6284
6285   /* Support only fixed point registers.  */
6286   if (GET_CODE (operands[2]) != CONST_INT
6287       || INTVAL (operands[2]) > 14
6288       || INTVAL (operands[2]) < 2
6289       || GET_CODE (operands[1]) != MEM
6290       || GET_CODE (operands[0]) != REG
6291       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6292       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
6293     FAIL;
6294
6295   operands[3]
6296     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
6297                              force_reg (SImode, XEXP (operands[1], 0)),
6298                              TRUE, FALSE, operands[1], &offset);
6299 })
6300
6301 ;; Load multiple with write-back
6302
6303 (define_insn "*ldmsi_postinc4"
6304   [(match_parallel 0 "load_multiple_operation"
6305     [(set (match_operand:SI 1 "s_register_operand" "=r")
6306           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6307                    (const_int 16)))
6308      (set (match_operand:SI 3 "arm_hard_register_operand" "")
6309           (mem:SI (match_dup 2)))
6310      (set (match_operand:SI 4 "arm_hard_register_operand" "")
6311           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
6312      (set (match_operand:SI 5 "arm_hard_register_operand" "")
6313           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
6314      (set (match_operand:SI 6 "arm_hard_register_operand" "")
6315           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
6316   "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
6317   "ldm%(ia%)\\t%1!, {%3, %4, %5, %6}"
6318   [(set_attr "type" "load4")
6319    (set_attr "predicable" "yes")]
6320 )
6321
6322 (define_insn "*ldmsi_postinc4_thumb1"
6323   [(match_parallel 0 "load_multiple_operation"
6324     [(set (match_operand:SI 1 "s_register_operand" "=l")
6325           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6326                    (const_int 16)))
6327      (set (match_operand:SI 3 "arm_hard_register_operand" "")
6328           (mem:SI (match_dup 2)))
6329      (set (match_operand:SI 4 "arm_hard_register_operand" "")
6330           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
6331      (set (match_operand:SI 5 "arm_hard_register_operand" "")
6332           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
6333      (set (match_operand:SI 6 "arm_hard_register_operand" "")
6334           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
6335   "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
6336   "ldmia\\t%1!, {%3, %4, %5, %6}"
6337   [(set_attr "type" "load4")]
6338 )
6339
6340 (define_insn "*ldmsi_postinc3"
6341   [(match_parallel 0 "load_multiple_operation"
6342     [(set (match_operand:SI 1 "s_register_operand" "=r")
6343           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6344                    (const_int 12)))
6345      (set (match_operand:SI 3 "arm_hard_register_operand" "")
6346           (mem:SI (match_dup 2)))
6347      (set (match_operand:SI 4 "arm_hard_register_operand" "")
6348           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
6349      (set (match_operand:SI 5 "arm_hard_register_operand" "")
6350           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
6351   "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6352   "ldm%(ia%)\\t%1!, {%3, %4, %5}"
6353   [(set_attr "type" "load3")
6354    (set_attr "predicable" "yes")]
6355 )
6356
6357 (define_insn "*ldmsi_postinc2"
6358   [(match_parallel 0 "load_multiple_operation"
6359     [(set (match_operand:SI 1 "s_register_operand" "=r")
6360           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6361                    (const_int 8)))
6362      (set (match_operand:SI 3 "arm_hard_register_operand" "")
6363           (mem:SI (match_dup 2)))
6364      (set (match_operand:SI 4 "arm_hard_register_operand" "")
6365           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
6366   "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6367   "ldm%(ia%)\\t%1!, {%3, %4}"
6368   [(set_attr "type" "load2")
6369    (set_attr "predicable" "yes")]
6370 )
6371
6372 ;; Ordinary load multiple
6373
6374 (define_insn "*ldmsi4"
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      (set (match_operand:SI 5 "arm_hard_register_operand" "")
6383           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
6384   "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6385   "ldm%(ia%)\\t%1, {%2, %3, %4, %5}"
6386   [(set_attr "type" "load4")
6387    (set_attr "predicable" "yes")]
6388 )
6389
6390 (define_insn "*ldmsi3"
6391   [(match_parallel 0 "load_multiple_operation"
6392     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
6393           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
6394      (set (match_operand:SI 3 "arm_hard_register_operand" "")
6395           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
6396      (set (match_operand:SI 4 "arm_hard_register_operand" "")
6397           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
6398   "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6399   "ldm%(ia%)\\t%1, {%2, %3, %4}"
6400   [(set_attr "type" "load3")
6401    (set_attr "predicable" "yes")]
6402 )
6403
6404 (define_insn "*ldmsi2"
6405   [(match_parallel 0 "load_multiple_operation"
6406     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
6407           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
6408      (set (match_operand:SI 3 "arm_hard_register_operand" "")
6409           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
6410   "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
6411   "ldm%(ia%)\\t%1, {%2, %3}"
6412   [(set_attr "type" "load2")
6413    (set_attr "predicable" "yes")]
6414 )
6415
6416 (define_expand "store_multiple"
6417   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6418                           (match_operand:SI 1 "" ""))
6419                      (use (match_operand:SI 2 "" ""))])]
6420   "TARGET_32BIT"
6421 {
6422   HOST_WIDE_INT offset = 0;
6423
6424   /* Support only fixed point registers.  */
6425   if (GET_CODE (operands[2]) != CONST_INT
6426       || INTVAL (operands[2]) > 14
6427       || INTVAL (operands[2]) < 2
6428       || GET_CODE (operands[1]) != REG
6429       || GET_CODE (operands[0]) != MEM
6430       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6431       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
6432     FAIL;
6433
6434   operands[3]
6435     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
6436                               force_reg (SImode, XEXP (operands[0], 0)),
6437                               TRUE, FALSE, operands[0], &offset);
6438 })
6439
6440 ;; Store multiple with write-back
6441
6442 (define_insn "*stmsi_postinc4"
6443   [(match_parallel 0 "store_multiple_operation"
6444     [(set (match_operand:SI 1 "s_register_operand" "=r")
6445           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6446                    (const_int 16)))
6447      (set (mem:SI (match_dup 2))
6448           (match_operand:SI 3 "arm_hard_register_operand" ""))
6449      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6450           (match_operand:SI 4 "arm_hard_register_operand" ""))
6451      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6452           (match_operand:SI 5 "arm_hard_register_operand" ""))
6453      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
6454           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
6455   "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
6456   "stm%(ia%)\\t%1!, {%3, %4, %5, %6}"
6457   [(set_attr "predicable" "yes")
6458    (set_attr "type" "store4")]
6459 )
6460
6461 (define_insn "*stmsi_postinc4_thumb1"
6462   [(match_parallel 0 "store_multiple_operation"
6463     [(set (match_operand:SI 1 "s_register_operand" "=l")
6464           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6465                    (const_int 16)))
6466      (set (mem:SI (match_dup 2))
6467           (match_operand:SI 3 "arm_hard_register_operand" ""))
6468      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6469           (match_operand:SI 4 "arm_hard_register_operand" ""))
6470      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6471           (match_operand:SI 5 "arm_hard_register_operand" ""))
6472      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
6473           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
6474   "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
6475   "stmia\\t%1!, {%3, %4, %5, %6}"
6476   [(set_attr "type" "store4")]
6477 )
6478
6479 (define_insn "*stmsi_postinc3"
6480   [(match_parallel 0 "store_multiple_operation"
6481     [(set (match_operand:SI 1 "s_register_operand" "=r")
6482           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6483                    (const_int 12)))
6484      (set (mem:SI (match_dup 2))
6485           (match_operand:SI 3 "arm_hard_register_operand" ""))
6486      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6487           (match_operand:SI 4 "arm_hard_register_operand" ""))
6488      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6489           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
6490   "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6491   "stm%(ia%)\\t%1!, {%3, %4, %5}"
6492   [(set_attr "predicable" "yes")
6493    (set_attr "type" "store3")]
6494 )
6495
6496 (define_insn "*stmsi_postinc2"
6497   [(match_parallel 0 "store_multiple_operation"
6498     [(set (match_operand:SI 1 "s_register_operand" "=r")
6499           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6500                    (const_int 8)))
6501      (set (mem:SI (match_dup 2))
6502           (match_operand:SI 3 "arm_hard_register_operand" ""))
6503      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6504           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
6505   "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6506   "stm%(ia%)\\t%1!, {%3, %4}"
6507   [(set_attr "predicable" "yes")
6508    (set_attr "type" "store2")]
6509 )
6510
6511 ;; Ordinary store multiple
6512
6513 (define_insn "*stmsi4"
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      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
6522           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
6523   "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6524   "stm%(ia%)\\t%1, {%2, %3, %4, %5}"
6525   [(set_attr "predicable" "yes")
6526    (set_attr "type" "store4")]
6527 )
6528
6529 (define_insn "*stmsi3"
6530   [(match_parallel 0 "store_multiple_operation"
6531     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6532           (match_operand:SI 2 "arm_hard_register_operand" ""))
6533      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6534           (match_operand:SI 3 "arm_hard_register_operand" ""))
6535      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
6536           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
6537   "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6538   "stm%(ia%)\\t%1, {%2, %3, %4}"
6539   [(set_attr "predicable" "yes")
6540    (set_attr "type" "store3")]
6541 )
6542
6543 (define_insn "*stmsi2"
6544   [(match_parallel 0 "store_multiple_operation"
6545     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6546           (match_operand:SI 2 "arm_hard_register_operand" ""))
6547      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6548           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
6549   "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
6550   "stm%(ia%)\\t%1, {%2, %3}"
6551   [(set_attr "predicable" "yes")
6552    (set_attr "type" "store2")]
6553 )
6554
6555 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
6556 ;; We could let this apply for blocks of less than this, but it clobbers so
6557 ;; many registers that there is then probably a better way.
6558
6559 (define_expand "movmemqi"
6560   [(match_operand:BLK 0 "general_operand" "")
6561    (match_operand:BLK 1 "general_operand" "")
6562    (match_operand:SI 2 "const_int_operand" "")
6563    (match_operand:SI 3 "const_int_operand" "")]
6564   "TARGET_EITHER"
6565   "
6566   if (TARGET_32BIT)
6567     {
6568       if (arm_gen_movmemqi (operands))
6569         DONE;
6570       FAIL;
6571     }
6572   else /* TARGET_THUMB1 */
6573     {
6574       if (   INTVAL (operands[3]) != 4
6575           || INTVAL (operands[2]) > 48)
6576         FAIL;
6577
6578       thumb_expand_movmemqi (operands);
6579       DONE;
6580     }
6581   "
6582 )
6583
6584 ;; Thumb block-move insns
6585
6586 (define_insn "movmem12b"
6587   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6588         (mem:SI (match_operand:SI 3 "register_operand" "1")))
6589    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6590         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6591    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6592         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
6593    (set (match_operand:SI 0 "register_operand" "=l")
6594         (plus:SI (match_dup 2) (const_int 12)))
6595    (set (match_operand:SI 1 "register_operand" "=l")
6596         (plus:SI (match_dup 3) (const_int 12)))
6597    (clobber (match_scratch:SI 4 "=&l"))
6598    (clobber (match_scratch:SI 5 "=&l"))
6599    (clobber (match_scratch:SI 6 "=&l"))]
6600   "TARGET_THUMB1"
6601   "* return thumb_output_move_mem_multiple (3, operands);"
6602   [(set_attr "length" "4")
6603    ; This isn't entirely accurate...  It loads as well, but in terms of
6604    ; scheduling the following insn it is better to consider it as a store
6605    (set_attr "type" "store3")]
6606 )
6607
6608 (define_insn "movmem8b"
6609   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6610         (mem:SI (match_operand:SI 3 "register_operand" "1")))
6611    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6612         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6613    (set (match_operand:SI 0 "register_operand" "=l")
6614         (plus:SI (match_dup 2) (const_int 8)))
6615    (set (match_operand:SI 1 "register_operand" "=l")
6616         (plus:SI (match_dup 3) (const_int 8)))
6617    (clobber (match_scratch:SI 4 "=&l"))
6618    (clobber (match_scratch:SI 5 "=&l"))]
6619   "TARGET_THUMB1"
6620   "* return thumb_output_move_mem_multiple (2, operands);"
6621   [(set_attr "length" "4")
6622    ; This isn't entirely accurate...  It loads as well, but in terms of
6623    ; scheduling the following insn it is better to consider it as a store
6624    (set_attr "type" "store2")]
6625 )
6626
6627 \f
6628
6629 ;; Compare & branch insns
6630 ;; The range calculations are based as follows:
6631 ;; For forward branches, the address calculation returns the address of
6632 ;; the next instruction.  This is 2 beyond the branch instruction.
6633 ;; For backward branches, the address calculation returns the address of
6634 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
6635 ;; instruction for the shortest sequence, and 4 before the branch instruction
6636 ;; if we have to jump around an unconditional branch.
6637 ;; To the basic branch range the PC offset must be added (this is +4).
6638 ;; So for forward branches we have 
6639 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6640 ;; And for backward branches we have 
6641 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6642 ;;
6643 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6644 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
6645
6646 (define_expand "cbranchsi4"
6647   [(set (pc) (if_then_else
6648               (match_operator 0 "arm_comparison_operator"
6649                [(match_operand:SI 1 "s_register_operand" "")
6650                 (match_operand:SI 2 "nonmemory_operand" "")])
6651               (label_ref (match_operand 3 "" ""))
6652               (pc)))]
6653   "TARGET_THUMB1 || TARGET_32BIT"
6654   "
6655   if (!TARGET_THUMB1)
6656     {
6657       if (!arm_add_operand (operands[2], SImode))
6658         operands[2] = force_reg (SImode, operands[2]);
6659       emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6660                                       operands[3]));
6661       DONE;
6662     }
6663   if (thumb1_cmpneg_operand (operands[2], SImode))
6664     {
6665       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6666                                               operands[3], operands[0]));
6667       DONE;
6668     }
6669   if (!thumb1_cmp_operand (operands[2], SImode))
6670     operands[2] = force_reg (SImode, operands[2]);
6671   ")
6672
6673 ;; A pattern to recognize a special situation and optimize for it.
6674 ;; On the thumb, zero-extension from memory is preferrable to sign-extension
6675 ;; due to the available addressing modes.  Hence, convert a signed comparison
6676 ;; with zero into an unsigned comparison with 127 if possible.
6677 (define_expand "cbranchqi4"
6678   [(set (pc) (if_then_else
6679               (match_operator 0 "lt_ge_comparison_operator"
6680                [(match_operand:QI 1 "memory_operand" "")
6681                 (match_operand:QI 2 "const0_operand" "")])
6682               (label_ref (match_operand 3 "" ""))
6683               (pc)))]
6684   "TARGET_THUMB1"
6685 {
6686   rtx xops[3];
6687   xops[1] = gen_reg_rtx (SImode);
6688   emit_insn (gen_zero_extendqisi2 (xops[1], operands[1]));
6689   xops[2] = GEN_INT (127);
6690   xops[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]) == GE ? LEU : GTU,
6691                             VOIDmode, xops[1], xops[2]);
6692   xops[3] = operands[3];
6693   emit_insn (gen_cbranchsi4 (xops[0], xops[1], xops[2], xops[3]));
6694   DONE;
6695 })
6696
6697 (define_expand "cbranchsf4"
6698   [(set (pc) (if_then_else
6699               (match_operator 0 "arm_comparison_operator"
6700                [(match_operand:SF 1 "s_register_operand" "")
6701                 (match_operand:SF 2 "arm_float_compare_operand" "")])
6702               (label_ref (match_operand 3 "" ""))
6703               (pc)))]
6704   "TARGET_32BIT && TARGET_HARD_FLOAT"
6705   "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6706                                    operands[3])); DONE;"
6707 )
6708
6709 (define_expand "cbranchdf4"
6710   [(set (pc) (if_then_else
6711               (match_operator 0 "arm_comparison_operator"
6712                [(match_operand:DF 1 "s_register_operand" "")
6713                 (match_operand:DF 2 "arm_float_compare_operand" "")])
6714               (label_ref (match_operand 3 "" ""))
6715               (pc)))]
6716   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
6717   "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6718                                    operands[3])); DONE;"
6719 )
6720
6721 ;; this uses the Cirrus DI compare instruction
6722 (define_expand "cbranchdi4"
6723   [(set (pc) (if_then_else
6724               (match_operator 0 "arm_comparison_operator"
6725                [(match_operand:DI 1 "cirrus_fp_register" "")
6726                 (match_operand:DI 2 "cirrus_fp_register" "")])
6727               (label_ref (match_operand 3 "" ""))
6728               (pc)))]
6729   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6730   "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6731                                    operands[3])); DONE;"
6732 )
6733
6734 (define_insn "cbranchsi4_insn"
6735   [(set (pc) (if_then_else
6736               (match_operator 0 "arm_comparison_operator"
6737                [(match_operand:SI 1 "s_register_operand" "l,*h")
6738                 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
6739               (label_ref (match_operand 3 "" ""))
6740               (pc)))]
6741   "TARGET_THUMB1"
6742   "*
6743   rtx t = prev_nonnote_insn (insn);
6744   if (t != NULL_RTX
6745       && INSN_P (t)
6746       && INSN_CODE (t) == CODE_FOR_cbranchsi4_insn)
6747     {
6748       t = XEXP (SET_SRC (PATTERN (t)), 0);
6749       if (!rtx_equal_p (XEXP (t, 0), operands[1])
6750           || !rtx_equal_p (XEXP (t, 1), operands[2]))
6751         t = NULL_RTX;
6752     }
6753   else
6754     t = NULL_RTX;
6755   if (t == NULL_RTX)
6756     output_asm_insn (\"cmp\\t%1, %2\", operands);
6757
6758   switch (get_attr_length (insn))
6759     {
6760     case 4:  return \"b%d0\\t%l3\";
6761     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6762     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6763     }
6764   "
6765   [(set (attr "far_jump")
6766         (if_then_else
6767             (eq_attr "length" "8")
6768             (const_string "yes")
6769             (const_string "no")))
6770    (set (attr "length") 
6771         (if_then_else
6772             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6773                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6774             (const_int 4)
6775             (if_then_else
6776                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6777                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6778                 (const_int 6)
6779                 (const_int 8))))]
6780 )
6781
6782 (define_insn "cbranchsi4_scratch"
6783   [(set (pc) (if_then_else
6784               (match_operator 4 "arm_comparison_operator"
6785                [(match_operand:SI 1 "s_register_operand" "l,0")
6786                 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
6787               (label_ref (match_operand 3 "" ""))
6788               (pc)))
6789    (clobber (match_scratch:SI 0 "=l,l"))]
6790   "TARGET_THUMB1"
6791   "*
6792   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
6793
6794   switch (get_attr_length (insn))
6795     {
6796     case 4:  return \"b%d4\\t%l3\";
6797     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6798     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6799     }
6800   "
6801   [(set (attr "far_jump")
6802         (if_then_else
6803             (eq_attr "length" "8")
6804             (const_string "yes")
6805             (const_string "no")))
6806    (set (attr "length") 
6807         (if_then_else
6808             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6809                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6810             (const_int 4)
6811             (if_then_else
6812                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6813                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6814                 (const_int 6)
6815                 (const_int 8))))]
6816 )
6817
6818 (define_insn "*movsi_cbranchsi4"
6819   [(set (pc)
6820         (if_then_else
6821          (match_operator 3 "arm_comparison_operator"
6822           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
6823            (const_int 0)])
6824          (label_ref (match_operand 2 "" ""))
6825          (pc)))
6826    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
6827         (match_dup 1))]
6828   "TARGET_THUMB1"
6829   "*{
6830   if (which_alternative == 0)
6831     output_asm_insn (\"cmp\t%0, #0\", operands);
6832   else if (which_alternative == 1)
6833     output_asm_insn (\"sub\t%0, %1, #0\", operands);
6834   else
6835     {
6836       output_asm_insn (\"cmp\t%1, #0\", operands);
6837       if (which_alternative == 2)
6838         output_asm_insn (\"mov\t%0, %1\", operands);
6839       else
6840         output_asm_insn (\"str\t%1, %0\", operands);
6841     }
6842   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
6843     {
6844     case 4:  return \"b%d3\\t%l2\";
6845     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6846     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
6847     }
6848   }"
6849   [(set (attr "far_jump")
6850         (if_then_else
6851             (ior (and (gt (symbol_ref ("which_alternative"))
6852                           (const_int 1))
6853                       (eq_attr "length" "8"))
6854                  (eq_attr "length" "10"))
6855             (const_string "yes")
6856             (const_string "no")))
6857    (set (attr "length")
6858      (if_then_else
6859        (le (symbol_ref ("which_alternative"))
6860                        (const_int 1))
6861        (if_then_else
6862          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6863               (le (minus (match_dup 2) (pc)) (const_int 256)))
6864          (const_int 4)
6865          (if_then_else
6866            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6867                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6868            (const_int 6)
6869            (const_int 8)))
6870        (if_then_else
6871          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
6872               (le (minus (match_dup 2) (pc)) (const_int 256)))
6873          (const_int 6)
6874          (if_then_else
6875            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
6876                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6877            (const_int 8)
6878            (const_int 10)))))]
6879 )
6880
6881 (define_peephole2
6882   [(set (match_operand:SI 0 "low_register_operand" "")
6883         (match_operand:SI 1 "low_register_operand" ""))
6884    (set (pc)
6885         (if_then_else (match_operator 2 "arm_comparison_operator"
6886                        [(match_dup 1) (const_int 0)])
6887                       (label_ref (match_operand 3 "" ""))
6888                       (pc)))]
6889   "TARGET_THUMB1"
6890   [(parallel
6891     [(set (pc)
6892         (if_then_else (match_op_dup 2 [(match_dup 1) (const_int 0)])
6893                       (label_ref (match_dup 3))
6894                       (pc)))
6895      (set (match_dup 0) (match_dup 1))])]
6896   ""
6897 )
6898
6899 ;; Sigh!  This variant shouldn't be needed, but combine often fails to
6900 ;; merge cases like this because the op1 is a hard register in
6901 ;; CLASS_LIKELY_SPILLED_P.
6902 (define_peephole2
6903   [(set (match_operand:SI 0 "low_register_operand" "")
6904         (match_operand:SI 1 "low_register_operand" ""))
6905    (set (pc)
6906         (if_then_else (match_operator 2 "arm_comparison_operator"
6907                        [(match_dup 0) (const_int 0)])
6908                       (label_ref (match_operand 3 "" ""))
6909                       (pc)))]
6910   "TARGET_THUMB1"
6911   [(parallel
6912     [(set (pc)
6913         (if_then_else (match_op_dup 2 [(match_dup 1) (const_int 0)])
6914                       (label_ref (match_dup 3))
6915                       (pc)))
6916      (set (match_dup 0) (match_dup 1))])]
6917   ""
6918 )
6919
6920 (define_insn "*negated_cbranchsi4"
6921   [(set (pc)
6922         (if_then_else
6923          (match_operator 0 "equality_operator"
6924           [(match_operand:SI 1 "s_register_operand" "l")
6925            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
6926          (label_ref (match_operand 3 "" ""))
6927          (pc)))]
6928   "TARGET_THUMB1"
6929   "*
6930   output_asm_insn (\"cmn\\t%1, %2\", operands);
6931   switch (get_attr_length (insn))
6932     {
6933     case 4:  return \"b%d0\\t%l3\";
6934     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6935     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6936     }
6937   "
6938   [(set (attr "far_jump")
6939         (if_then_else
6940             (eq_attr "length" "8")
6941             (const_string "yes")
6942             (const_string "no")))
6943    (set (attr "length") 
6944         (if_then_else
6945             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6946                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6947             (const_int 4)
6948             (if_then_else
6949                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6950                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6951                 (const_int 6)
6952                 (const_int 8))))]
6953 )
6954
6955 (define_insn "*tbit_cbranch"
6956   [(set (pc)
6957         (if_then_else
6958          (match_operator 0 "equality_operator"
6959           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6960                             (const_int 1)
6961                             (match_operand:SI 2 "const_int_operand" "i"))
6962            (const_int 0)])
6963          (label_ref (match_operand 3 "" ""))
6964          (pc)))
6965    (clobber (match_scratch:SI 4 "=l"))]
6966   "TARGET_THUMB1"
6967   "*
6968   {
6969   rtx op[3];
6970   op[0] = operands[4];
6971   op[1] = operands[1];
6972   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
6973
6974   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6975   switch (get_attr_length (insn))
6976     {
6977     case 4:  return \"b%d0\\t%l3\";
6978     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6979     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6980     }
6981   }"
6982   [(set (attr "far_jump")
6983         (if_then_else
6984             (eq_attr "length" "8")
6985             (const_string "yes")
6986             (const_string "no")))
6987    (set (attr "length") 
6988         (if_then_else
6989             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6990                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6991             (const_int 4)
6992             (if_then_else
6993                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6994                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6995                 (const_int 6)
6996                 (const_int 8))))]
6997 )
6998   
6999 (define_insn "*tlobits_cbranch"
7000   [(set (pc)
7001         (if_then_else
7002          (match_operator 0 "equality_operator"
7003           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
7004                             (match_operand:SI 2 "const_int_operand" "i")
7005                             (const_int 0))
7006            (const_int 0)])
7007          (label_ref (match_operand 3 "" ""))
7008          (pc)))
7009    (clobber (match_scratch:SI 4 "=l"))]
7010   "TARGET_THUMB1"
7011   "*
7012   {
7013   rtx op[3];
7014   op[0] = operands[4];
7015   op[1] = operands[1];
7016   op[2] = GEN_INT (32 - INTVAL (operands[2]));
7017
7018   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
7019   switch (get_attr_length (insn))
7020     {
7021     case 4:  return \"b%d0\\t%l3\";
7022     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7023     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7024     }
7025   }"
7026   [(set (attr "far_jump")
7027         (if_then_else
7028             (eq_attr "length" "8")
7029             (const_string "yes")
7030             (const_string "no")))
7031    (set (attr "length") 
7032         (if_then_else
7033             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7034                  (le (minus (match_dup 3) (pc)) (const_int 256)))
7035             (const_int 4)
7036             (if_then_else
7037                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7038                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
7039                 (const_int 6)
7040                 (const_int 8))))]
7041 )
7042   
7043 (define_insn "*tstsi3_cbranch"
7044   [(set (pc)
7045         (if_then_else
7046          (match_operator 3 "equality_operator"
7047           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
7048                    (match_operand:SI 1 "s_register_operand" "l"))
7049            (const_int 0)])
7050          (label_ref (match_operand 2 "" ""))
7051          (pc)))]
7052   "TARGET_THUMB1"
7053   "*
7054   {
7055   output_asm_insn (\"tst\\t%0, %1\", operands);
7056   switch (get_attr_length (insn))
7057     {
7058     case 4:  return \"b%d3\\t%l2\";
7059     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
7060     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
7061     }
7062   }"
7063   [(set (attr "far_jump")
7064         (if_then_else
7065             (eq_attr "length" "8")
7066             (const_string "yes")
7067             (const_string "no")))
7068    (set (attr "length") 
7069         (if_then_else
7070             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
7071                  (le (minus (match_dup 2) (pc)) (const_int 256)))
7072             (const_int 4)
7073             (if_then_else
7074                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
7075                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
7076                 (const_int 6)
7077                 (const_int 8))))]
7078 )
7079   
7080 (define_insn "*andsi3_cbranch"
7081   [(set (pc)
7082         (if_then_else
7083          (match_operator 5 "equality_operator"
7084           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
7085                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7086            (const_int 0)])
7087          (label_ref (match_operand 4 "" ""))
7088          (pc)))
7089    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
7090         (and:SI (match_dup 2) (match_dup 3)))
7091    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
7092   "TARGET_THUMB1"
7093   "*
7094   {
7095   if (which_alternative == 0)
7096     output_asm_insn (\"and\\t%0, %3\", operands);
7097   else if (which_alternative == 1)
7098     {
7099       output_asm_insn (\"and\\t%1, %3\", operands);
7100       output_asm_insn (\"mov\\t%0, %1\", operands);
7101     }
7102   else
7103     {
7104       output_asm_insn (\"and\\t%1, %3\", operands);
7105       output_asm_insn (\"str\\t%1, %0\", operands);
7106     }
7107
7108   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7109     {
7110     case 4:  return \"b%d5\\t%l4\";
7111     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7112     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7113     }
7114   }"
7115   [(set (attr "far_jump")
7116         (if_then_else
7117             (ior (and (eq (symbol_ref ("which_alternative"))
7118                           (const_int 0))
7119                       (eq_attr "length" "8"))
7120                  (eq_attr "length" "10"))
7121             (const_string "yes")
7122             (const_string "no")))
7123    (set (attr "length")
7124      (if_then_else
7125        (eq (symbol_ref ("which_alternative"))
7126                        (const_int 0))
7127        (if_then_else
7128          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7129               (le (minus (match_dup 4) (pc)) (const_int 256)))
7130          (const_int 4)
7131          (if_then_else
7132            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7133                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7134            (const_int 6)
7135            (const_int 8)))
7136        (if_then_else
7137          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7138               (le (minus (match_dup 4) (pc)) (const_int 256)))
7139          (const_int 6)
7140          (if_then_else
7141            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7142                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7143            (const_int 8)
7144            (const_int 10)))))]
7145 )
7146
7147 (define_insn "*orrsi3_cbranch_scratch"
7148   [(set (pc)
7149         (if_then_else
7150          (match_operator 4 "equality_operator"
7151           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
7152                    (match_operand:SI 2 "s_register_operand" "l"))
7153            (const_int 0)])
7154          (label_ref (match_operand 3 "" ""))
7155          (pc)))
7156    (clobber (match_scratch:SI 0 "=l"))]
7157   "TARGET_THUMB1"
7158   "*
7159   {
7160   output_asm_insn (\"orr\\t%0, %2\", operands);
7161   switch (get_attr_length (insn))
7162     {
7163     case 4:  return \"b%d4\\t%l3\";
7164     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7165     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7166     }
7167   }"
7168   [(set (attr "far_jump")
7169         (if_then_else
7170             (eq_attr "length" "8")
7171             (const_string "yes")
7172             (const_string "no")))
7173    (set (attr "length") 
7174         (if_then_else
7175             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7176                  (le (minus (match_dup 3) (pc)) (const_int 256)))
7177             (const_int 4)
7178             (if_then_else
7179                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7180                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
7181                 (const_int 6)
7182                 (const_int 8))))]
7183 )
7184   
7185 (define_insn "*orrsi3_cbranch"
7186   [(set (pc)
7187         (if_then_else
7188          (match_operator 5 "equality_operator"
7189           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
7190                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7191            (const_int 0)])
7192          (label_ref (match_operand 4 "" ""))
7193          (pc)))
7194    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
7195         (ior:SI (match_dup 2) (match_dup 3)))
7196    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
7197   "TARGET_THUMB1"
7198   "*
7199   {
7200   if (which_alternative == 0)
7201     output_asm_insn (\"orr\\t%0, %3\", operands);
7202   else if (which_alternative == 1)
7203     {
7204       output_asm_insn (\"orr\\t%1, %3\", operands);
7205       output_asm_insn (\"mov\\t%0, %1\", operands);
7206     }
7207   else
7208     {
7209       output_asm_insn (\"orr\\t%1, %3\", operands);
7210       output_asm_insn (\"str\\t%1, %0\", operands);
7211     }
7212
7213   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7214     {
7215     case 4:  return \"b%d5\\t%l4\";
7216     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7217     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7218     }
7219   }"
7220   [(set (attr "far_jump")
7221         (if_then_else
7222             (ior (and (eq (symbol_ref ("which_alternative"))
7223                           (const_int 0))
7224                       (eq_attr "length" "8"))
7225                  (eq_attr "length" "10"))
7226             (const_string "yes")
7227             (const_string "no")))
7228    (set (attr "length")
7229      (if_then_else
7230        (eq (symbol_ref ("which_alternative"))
7231                        (const_int 0))
7232        (if_then_else
7233          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7234               (le (minus (match_dup 4) (pc)) (const_int 256)))
7235          (const_int 4)
7236          (if_then_else
7237            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7238                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7239            (const_int 6)
7240            (const_int 8)))
7241        (if_then_else
7242          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7243               (le (minus (match_dup 4) (pc)) (const_int 256)))
7244          (const_int 6)
7245          (if_then_else
7246            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7247                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7248            (const_int 8)
7249            (const_int 10)))))]
7250 )
7251
7252 (define_insn "*xorsi3_cbranch_scratch"
7253   [(set (pc)
7254         (if_then_else
7255          (match_operator 4 "equality_operator"
7256           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
7257                    (match_operand:SI 2 "s_register_operand" "l"))
7258            (const_int 0)])
7259          (label_ref (match_operand 3 "" ""))
7260          (pc)))
7261    (clobber (match_scratch:SI 0 "=l"))]
7262   "TARGET_THUMB1"
7263   "*
7264   {
7265   output_asm_insn (\"eor\\t%0, %2\", operands);
7266   switch (get_attr_length (insn))
7267     {
7268     case 4:  return \"b%d4\\t%l3\";
7269     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7270     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7271     }
7272   }"
7273   [(set (attr "far_jump")
7274         (if_then_else
7275             (eq_attr "length" "8")
7276             (const_string "yes")
7277             (const_string "no")))
7278    (set (attr "length") 
7279         (if_then_else
7280             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7281                  (le (minus (match_dup 3) (pc)) (const_int 256)))
7282             (const_int 4)
7283             (if_then_else
7284                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7285                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
7286                 (const_int 6)
7287                 (const_int 8))))]
7288 )
7289   
7290 (define_insn "*xorsi3_cbranch"
7291   [(set (pc)
7292         (if_then_else
7293          (match_operator 5 "equality_operator"
7294           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
7295                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7296            (const_int 0)])
7297          (label_ref (match_operand 4 "" ""))
7298          (pc)))
7299    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
7300         (xor:SI (match_dup 2) (match_dup 3)))
7301    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
7302   "TARGET_THUMB1"
7303   "*
7304   {
7305   if (which_alternative == 0)
7306     output_asm_insn (\"eor\\t%0, %3\", operands);
7307   else if (which_alternative == 1)
7308     {
7309       output_asm_insn (\"eor\\t%1, %3\", operands);
7310       output_asm_insn (\"mov\\t%0, %1\", operands);
7311     }
7312   else
7313     {
7314       output_asm_insn (\"eor\\t%1, %3\", operands);
7315       output_asm_insn (\"str\\t%1, %0\", operands);
7316     }
7317
7318   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7319     {
7320     case 4:  return \"b%d5\\t%l4\";
7321     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7322     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7323     }
7324   }"
7325   [(set (attr "far_jump")
7326         (if_then_else
7327             (ior (and (eq (symbol_ref ("which_alternative"))
7328                           (const_int 0))
7329                       (eq_attr "length" "8"))
7330                  (eq_attr "length" "10"))
7331             (const_string "yes")
7332             (const_string "no")))
7333    (set (attr "length")
7334      (if_then_else
7335        (eq (symbol_ref ("which_alternative"))
7336                        (const_int 0))
7337        (if_then_else
7338          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7339               (le (minus (match_dup 4) (pc)) (const_int 256)))
7340          (const_int 4)
7341          (if_then_else
7342            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7343                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7344            (const_int 6)
7345            (const_int 8)))
7346        (if_then_else
7347          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7348               (le (minus (match_dup 4) (pc)) (const_int 256)))
7349          (const_int 6)
7350          (if_then_else
7351            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7352                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7353            (const_int 8)
7354            (const_int 10)))))]
7355 )
7356
7357 (define_insn "*bicsi3_cbranch_scratch"
7358   [(set (pc)
7359         (if_then_else
7360          (match_operator 4 "equality_operator"
7361           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
7362                    (match_operand:SI 1 "s_register_operand" "0"))
7363            (const_int 0)])
7364          (label_ref (match_operand 3 "" ""))
7365          (pc)))
7366    (clobber (match_scratch:SI 0 "=l"))]
7367   "TARGET_THUMB1"
7368   "*
7369   {
7370   output_asm_insn (\"bic\\t%0, %2\", operands);
7371   switch (get_attr_length (insn))
7372     {
7373     case 4:  return \"b%d4\\t%l3\";
7374     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7375     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7376     }
7377   }"
7378   [(set (attr "far_jump")
7379         (if_then_else
7380             (eq_attr "length" "8")
7381             (const_string "yes")
7382             (const_string "no")))
7383    (set (attr "length") 
7384         (if_then_else
7385             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7386                  (le (minus (match_dup 3) (pc)) (const_int 256)))
7387             (const_int 4)
7388             (if_then_else
7389                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7390                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
7391                 (const_int 6)
7392                 (const_int 8))))]
7393 )
7394   
7395 (define_insn "*bicsi3_cbranch"
7396   [(set (pc)
7397         (if_then_else
7398          (match_operator 5 "equality_operator"
7399           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
7400                    (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
7401            (const_int 0)])
7402          (label_ref (match_operand 4 "" ""))
7403          (pc)))
7404    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
7405         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
7406    (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
7407   "TARGET_THUMB1"
7408   "*
7409   {
7410   if (which_alternative == 0)
7411     output_asm_insn (\"bic\\t%0, %3\", operands);
7412   else if (which_alternative <= 2)
7413     {
7414       output_asm_insn (\"bic\\t%1, %3\", operands);
7415       /* It's ok if OP0 is a lo-reg, even though the mov will set the
7416          conditions again, since we're only testing for equality.  */
7417       output_asm_insn (\"mov\\t%0, %1\", operands);
7418     }
7419   else
7420     {
7421       output_asm_insn (\"bic\\t%1, %3\", operands);
7422       output_asm_insn (\"str\\t%1, %0\", operands);
7423     }
7424
7425   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7426     {
7427     case 4:  return \"b%d5\\t%l4\";
7428     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7429     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7430     }
7431   }"
7432   [(set (attr "far_jump")
7433         (if_then_else
7434             (ior (and (eq (symbol_ref ("which_alternative"))
7435                           (const_int 0))
7436                       (eq_attr "length" "8"))
7437                  (eq_attr "length" "10"))
7438             (const_string "yes")
7439             (const_string "no")))
7440    (set (attr "length")
7441      (if_then_else
7442        (eq (symbol_ref ("which_alternative"))
7443                        (const_int 0))
7444        (if_then_else
7445          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7446               (le (minus (match_dup 4) (pc)) (const_int 256)))
7447          (const_int 4)
7448          (if_then_else
7449            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7450                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7451            (const_int 6)
7452            (const_int 8)))
7453        (if_then_else
7454          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7455               (le (minus (match_dup 4) (pc)) (const_int 256)))
7456          (const_int 6)
7457          (if_then_else
7458            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7459                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7460            (const_int 8)
7461            (const_int 10)))))]
7462 )
7463
7464 (define_insn "*cbranchne_decr1"
7465   [(set (pc)
7466         (if_then_else (match_operator 3 "equality_operator"
7467                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
7468                         (const_int 0)])
7469                       (label_ref (match_operand 4 "" ""))
7470                       (pc)))
7471    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
7472         (plus:SI (match_dup 2) (const_int -1)))
7473    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
7474   "TARGET_THUMB1"
7475   "*
7476    {
7477      rtx cond[2];
7478      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
7479                                 ? GEU : LTU),
7480                                VOIDmode, operands[2], const1_rtx);
7481      cond[1] = operands[4];
7482
7483      if (which_alternative == 0)
7484        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
7485      else if (which_alternative == 1)
7486        {
7487          /* We must provide an alternative for a hi reg because reload 
7488             cannot handle output reloads on a jump instruction, but we
7489             can't subtract into that.  Fortunately a mov from lo to hi
7490             does not clobber the condition codes.  */
7491          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7492          output_asm_insn (\"mov\\t%0, %1\", operands);
7493        }
7494      else
7495        {
7496          /* Similarly, but the target is memory.  */
7497          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7498          output_asm_insn (\"str\\t%1, %0\", operands);
7499        }
7500
7501      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7502        {
7503          case 4:
7504            output_asm_insn (\"b%d0\\t%l1\", cond);
7505            return \"\";
7506          case 6:
7507            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
7508            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
7509          default:
7510            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
7511            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7512        }
7513    }
7514   "
7515   [(set (attr "far_jump")
7516         (if_then_else
7517             (ior (and (eq (symbol_ref ("which_alternative"))
7518                           (const_int 0))
7519                       (eq_attr "length" "8"))
7520                  (eq_attr "length" "10"))
7521             (const_string "yes")
7522             (const_string "no")))
7523    (set_attr_alternative "length"
7524       [
7525        ;; Alternative 0
7526        (if_then_else
7527          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7528               (le (minus (match_dup 4) (pc)) (const_int 256)))
7529          (const_int 4)
7530          (if_then_else
7531            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7532                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7533            (const_int 6)
7534            (const_int 8)))
7535        ;; Alternative 1
7536        (if_then_else
7537          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7538               (le (minus (match_dup 4) (pc)) (const_int 256)))
7539          (const_int 6)
7540          (if_then_else
7541            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7542                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7543            (const_int 8)
7544            (const_int 10)))
7545        ;; Alternative 2
7546        (if_then_else
7547          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7548               (le (minus (match_dup 4) (pc)) (const_int 256)))
7549          (const_int 6)
7550          (if_then_else
7551            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7552                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7553            (const_int 8)
7554            (const_int 10)))
7555        ;; Alternative 3
7556        (if_then_else
7557          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7558               (le (minus (match_dup 4) (pc)) (const_int 256)))
7559          (const_int 6)
7560          (if_then_else
7561            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7562                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7563            (const_int 8)
7564            (const_int 10)))])]
7565 )
7566
7567 (define_insn "*addsi3_cbranch"
7568   [(set (pc)
7569         (if_then_else
7570          (match_operator 4 "arm_comparison_operator"
7571           [(plus:SI
7572             (match_operand:SI 2 "s_register_operand" "%l,0,*l,1,1,1")
7573             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*l,lIJ,lIJ,lIJ"))
7574            (const_int 0)])
7575          (label_ref (match_operand 5 "" ""))
7576          (pc)))
7577    (set
7578     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
7579     (plus:SI (match_dup 2) (match_dup 3)))
7580    (clobber (match_scratch:SI 1 "=X,X,l,l,&l,&l"))]
7581   "TARGET_THUMB1
7582    && (GET_CODE (operands[4]) == EQ
7583        || GET_CODE (operands[4]) == NE
7584        || GET_CODE (operands[4]) == GE
7585        || GET_CODE (operands[4]) == LT)"
7586   "*
7587    {
7588      rtx cond[3];
7589
7590      cond[0] = (which_alternative < 2) ? operands[0] : operands[1];
7591      cond[1] = operands[2];
7592      cond[2] = operands[3];
7593
7594      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
7595        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
7596      else
7597        output_asm_insn (\"add\\t%0, %1, %2\", cond);
7598
7599      if (which_alternative >= 2
7600          && which_alternative < 4)
7601        output_asm_insn (\"mov\\t%0, %1\", operands);
7602      else if (which_alternative >= 4)
7603        output_asm_insn (\"str\\t%1, %0\", operands);
7604
7605      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
7606        {
7607          case 4:
7608            return \"b%d4\\t%l5\";
7609          case 6:
7610            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7611          default:
7612            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7613        }
7614    }
7615   "
7616   [(set (attr "far_jump")
7617         (if_then_else
7618             (ior (and (lt (symbol_ref ("which_alternative"))
7619                           (const_int 3))
7620                       (eq_attr "length" "8"))
7621                  (eq_attr "length" "10"))
7622             (const_string "yes")
7623             (const_string "no")))
7624    (set (attr "length")
7625      (if_then_else
7626        (lt (symbol_ref ("which_alternative"))
7627                        (const_int 3))
7628        (if_then_else
7629          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7630               (le (minus (match_dup 5) (pc)) (const_int 256)))
7631          (const_int 4)
7632          (if_then_else
7633            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7634                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7635            (const_int 6)
7636            (const_int 8)))
7637        (if_then_else
7638          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7639               (le (minus (match_dup 5) (pc)) (const_int 256)))
7640          (const_int 6)
7641          (if_then_else
7642            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7643                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7644            (const_int 8)
7645            (const_int 10)))))]
7646 )
7647
7648 (define_insn "*addsi3_cbranch_scratch"
7649   [(set (pc)
7650         (if_then_else
7651          (match_operator 3 "arm_comparison_operator"
7652           [(plus:SI
7653             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
7654             (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
7655            (const_int 0)])
7656          (label_ref (match_operand 4 "" ""))
7657          (pc)))
7658    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
7659   "TARGET_THUMB1
7660    && (GET_CODE (operands[3]) == EQ
7661        || GET_CODE (operands[3]) == NE
7662        || GET_CODE (operands[3]) == GE
7663        || GET_CODE (operands[3]) == LT)"
7664   "*
7665    {
7666      switch (which_alternative)
7667        {
7668        case 0:
7669          output_asm_insn (\"cmp\t%1, #%n2\", operands);
7670          break;
7671        case 1:
7672          output_asm_insn (\"cmn\t%1, %2\", operands);
7673          break;
7674        case 2:
7675          if (INTVAL (operands[2]) < 0)
7676            output_asm_insn (\"sub\t%0, %1, %2\", operands);
7677          else
7678            output_asm_insn (\"add\t%0, %1, %2\", operands);
7679          break;
7680        case 3:
7681          if (INTVAL (operands[2]) < 0)
7682            output_asm_insn (\"sub\t%0, %0, %2\", operands);
7683          else
7684            output_asm_insn (\"add\t%0, %0, %2\", operands);
7685          break;
7686        }
7687
7688      switch (get_attr_length (insn))
7689        {
7690          case 4:
7691            return \"b%d3\\t%l4\";
7692          case 6:
7693            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7694          default:
7695            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7696        }
7697    }
7698   "
7699   [(set (attr "far_jump")
7700         (if_then_else
7701             (eq_attr "length" "8")
7702             (const_string "yes")
7703             (const_string "no")))
7704    (set (attr "length")
7705        (if_then_else
7706          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7707               (le (minus (match_dup 4) (pc)) (const_int 256)))
7708          (const_int 4)
7709          (if_then_else
7710            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7711                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7712            (const_int 6)
7713            (const_int 8))))]
7714 )
7715
7716 (define_insn "*subsi3_cbranch"
7717   [(set (pc)
7718         (if_then_else
7719          (match_operator 4 "arm_comparison_operator"
7720           [(minus:SI
7721             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
7722             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7723            (const_int 0)])
7724          (label_ref (match_operand 5 "" ""))
7725          (pc)))
7726    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
7727         (minus:SI (match_dup 2) (match_dup 3)))
7728    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
7729   "TARGET_THUMB1
7730    && (GET_CODE (operands[4]) == EQ
7731        || GET_CODE (operands[4]) == NE
7732        || GET_CODE (operands[4]) == GE
7733        || GET_CODE (operands[4]) == LT)"
7734   "*
7735    {
7736      if (which_alternative == 0)
7737        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
7738      else if (which_alternative == 1)
7739        {
7740          /* We must provide an alternative for a hi reg because reload 
7741             cannot handle output reloads on a jump instruction, but we
7742             can't subtract into that.  Fortunately a mov from lo to hi
7743             does not clobber the condition codes.  */
7744          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
7745          output_asm_insn (\"mov\\t%0, %1\", operands);
7746        }
7747      else
7748        {
7749          /* Similarly, but the target is memory.  */
7750          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
7751          output_asm_insn (\"str\\t%1, %0\", operands);
7752        }
7753
7754      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
7755        {
7756          case 4:
7757            return \"b%d4\\t%l5\";
7758          case 6:
7759            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7760          default:
7761            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7762        }
7763    }
7764   "
7765   [(set (attr "far_jump")
7766         (if_then_else
7767             (ior (and (eq (symbol_ref ("which_alternative"))
7768                           (const_int 0))
7769                       (eq_attr "length" "8"))
7770                  (eq_attr "length" "10"))
7771             (const_string "yes")
7772             (const_string "no")))
7773    (set (attr "length")
7774      (if_then_else
7775        (eq (symbol_ref ("which_alternative"))
7776                        (const_int 0))
7777        (if_then_else
7778          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7779               (le (minus (match_dup 5) (pc)) (const_int 256)))
7780          (const_int 4)
7781          (if_then_else
7782            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7783                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7784            (const_int 6)
7785            (const_int 8)))
7786        (if_then_else
7787          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7788               (le (minus (match_dup 5) (pc)) (const_int 256)))
7789          (const_int 6)
7790          (if_then_else
7791            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7792                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7793            (const_int 8)
7794            (const_int 10)))))]
7795 )
7796
7797 (define_insn "*subsi3_cbranch_scratch"
7798   [(set (pc)
7799         (if_then_else
7800          (match_operator 0 "arm_comparison_operator"
7801           [(minus:SI (match_operand:SI 1 "register_operand" "l")
7802                      (match_operand:SI 2 "nonmemory_operand" "l"))
7803            (const_int 0)])
7804          (label_ref (match_operand 3 "" ""))
7805          (pc)))]
7806   "TARGET_THUMB1
7807    && (GET_CODE (operands[0]) == EQ
7808        || GET_CODE (operands[0]) == NE
7809        || GET_CODE (operands[0]) == GE
7810        || GET_CODE (operands[0]) == LT)"
7811   "*
7812   output_asm_insn (\"cmp\\t%1, %2\", operands);
7813   switch (get_attr_length (insn))
7814     {
7815     case 4:  return \"b%d0\\t%l3\";
7816     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7817     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7818     }
7819   "
7820   [(set (attr "far_jump")
7821         (if_then_else
7822             (eq_attr "length" "8")
7823             (const_string "yes")
7824             (const_string "no")))
7825    (set (attr "length") 
7826         (if_then_else
7827             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7828                  (le (minus (match_dup 3) (pc)) (const_int 256)))
7829             (const_int 4)
7830             (if_then_else
7831                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7832                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
7833                 (const_int 6)
7834                 (const_int 8))))]
7835 )
7836
7837 ;; Comparison and test insns
7838
7839 (define_insn "*arm_cmpsi_insn"
7840   [(set (reg:CC CC_REGNUM)
7841         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
7842                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
7843   "TARGET_32BIT"
7844   "@
7845    cmp%?\\t%0, %1
7846    cmn%?\\t%0, #%n1"
7847   [(set_attr "conds" "set")]
7848 )
7849
7850 (define_insn "*arm_cmpsi_shiftsi"
7851   [(set (reg:CC CC_REGNUM)
7852         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
7853                     (match_operator:SI  3 "shift_operator"
7854                      [(match_operand:SI 1 "s_register_operand" "r")
7855                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
7856   "TARGET_ARM"
7857   "cmp%?\\t%0, %1%S3"
7858   [(set_attr "conds" "set")
7859    (set_attr "shift" "1")
7860    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
7861                       (const_string "alu_shift")
7862                       (const_string "alu_shift_reg")))]
7863 )
7864
7865 (define_insn "*arm_cmpsi_shiftsi_swp"
7866   [(set (reg:CC_SWP CC_REGNUM)
7867         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
7868                          [(match_operand:SI 1 "s_register_operand" "r")
7869                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
7870                         (match_operand:SI 0 "s_register_operand" "r")))]
7871   "TARGET_ARM"
7872   "cmp%?\\t%0, %1%S3"
7873   [(set_attr "conds" "set")
7874    (set_attr "shift" "1")
7875    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
7876                       (const_string "alu_shift")
7877                       (const_string "alu_shift_reg")))]
7878 )
7879
7880 (define_insn "*arm_cmpsi_negshiftsi_si"
7881   [(set (reg:CC_Z CC_REGNUM)
7882         (compare:CC_Z
7883          (neg:SI (match_operator:SI 1 "shift_operator"
7884                     [(match_operand:SI 2 "s_register_operand" "r")
7885                      (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7886          (match_operand:SI 0 "s_register_operand" "r")))]
7887   "TARGET_ARM"
7888   "cmn%?\\t%0, %2%S1"
7889   [(set_attr "conds" "set")
7890    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7891                                     (const_string "alu_shift")
7892                                     (const_string "alu_shift_reg")))]
7893 )
7894
7895 ;; Cirrus SF compare instruction
7896 (define_insn "*cirrus_cmpsf"
7897   [(set (reg:CCFP CC_REGNUM)
7898         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
7899                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
7900   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7901   "cfcmps%?\\tr15, %V0, %V1"
7902   [(set_attr "type"   "mav_farith")
7903    (set_attr "cirrus" "compare")]
7904 )
7905
7906 ;; Cirrus DF compare instruction
7907 (define_insn "*cirrus_cmpdf"
7908   [(set (reg:CCFP CC_REGNUM)
7909         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
7910                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
7911   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7912   "cfcmpd%?\\tr15, %V0, %V1"
7913   [(set_attr "type"   "mav_farith")
7914    (set_attr "cirrus" "compare")]
7915 )
7916
7917 (define_insn "*cirrus_cmpdi"
7918   [(set (reg:CC CC_REGNUM)
7919         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
7920                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
7921   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7922   "cfcmp64%?\\tr15, %V0, %V1"
7923   [(set_attr "type"   "mav_farith")
7924    (set_attr "cirrus" "compare")]
7925 )
7926
7927 ; This insn allows redundant compares to be removed by cse, nothing should
7928 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7929 ; is deleted later on. The match_dup will match the mode here, so that
7930 ; mode changes of the condition codes aren't lost by this even though we don't
7931 ; specify what they are.
7932
7933 (define_insn "*deleted_compare"
7934   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
7935   "TARGET_32BIT"
7936   "\\t%@ deleted compare"
7937   [(set_attr "conds" "set")
7938    (set_attr "length" "0")]
7939 )
7940
7941 \f
7942 ;; Conditional branch insns
7943
7944 (define_expand "cbranch_cc"
7945   [(set (pc)
7946         (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7947                                             (match_operand 2 "" "")])
7948                       (label_ref (match_operand 3 "" ""))
7949                       (pc)))]
7950   "TARGET_32BIT"
7951   "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
7952                                       operands[1], operands[2]);
7953    operands[2] = const0_rtx;"
7954 )
7955
7956 ;;
7957 ;; Patterns to match conditional branch insns.
7958 ;;
7959
7960 (define_insn "*arm_cond_branch"
7961   [(set (pc)
7962         (if_then_else (match_operator 1 "arm_comparison_operator"
7963                        [(match_operand 2 "cc_register" "") (const_int 0)])
7964                       (label_ref (match_operand 0 "" ""))
7965                       (pc)))]
7966   "TARGET_32BIT"
7967   "*
7968   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7969     {
7970       arm_ccfsm_state += 2;
7971       return \"\";
7972     }
7973   return \"b%d1\\t%l0\";
7974   "
7975   [(set_attr "conds" "use")
7976    (set_attr "type" "branch")]
7977 )
7978
7979 (define_insn "*arm_cond_branch_reversed"
7980   [(set (pc)
7981         (if_then_else (match_operator 1 "arm_comparison_operator"
7982                        [(match_operand 2 "cc_register" "") (const_int 0)])
7983                       (pc)
7984                       (label_ref (match_operand 0 "" ""))))]
7985   "TARGET_32BIT"
7986   "*
7987   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7988     {
7989       arm_ccfsm_state += 2;
7990       return \"\";
7991     }
7992   return \"b%D1\\t%l0\";
7993   "
7994   [(set_attr "conds" "use")
7995    (set_attr "type" "branch")]
7996 )
7997
7998 \f
7999
8000 ; scc insns
8001
8002 (define_expand "cstore_cc"
8003   [(set (match_operand:SI 0 "s_register_operand" "")
8004         (match_operator:SI 1 "" [(match_operand 2 "" "")
8005                                  (match_operand 3 "" "")]))]
8006   "TARGET_32BIT"
8007   "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
8008                                       operands[2], operands[3]);
8009    operands[3] = const0_rtx;"
8010 )
8011
8012 (define_insn "*mov_scc"
8013   [(set (match_operand:SI 0 "s_register_operand" "=r")
8014         (match_operator:SI 1 "arm_comparison_operator"
8015          [(match_operand 2 "cc_register" "") (const_int 0)]))]
8016   "TARGET_ARM"
8017   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
8018   [(set_attr "conds" "use")
8019    (set_attr "length" "8")]
8020 )
8021
8022 (define_insn "*mov_negscc"
8023   [(set (match_operand:SI 0 "s_register_operand" "=r")
8024         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8025                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
8026   "TARGET_ARM"
8027   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
8028   [(set_attr "conds" "use")
8029    (set_attr "length" "8")]
8030 )
8031
8032 (define_insn "*mov_notscc"
8033   [(set (match_operand:SI 0 "s_register_operand" "=r")
8034         (not:SI (match_operator:SI 1 "arm_comparison_operator"
8035                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
8036   "TARGET_ARM"
8037   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
8038   [(set_attr "conds" "use")
8039    (set_attr "length" "8")]
8040 )
8041
8042 (define_expand "cstoresi4"
8043   [(set (match_operand:SI 0 "s_register_operand" "")
8044         (match_operator:SI 1 "arm_comparison_operator"
8045          [(match_operand:SI 2 "s_register_operand" "")
8046           (match_operand:SI 3 "reg_or_int_operand" "")]))]
8047   "TARGET_32BIT || TARGET_THUMB1"
8048   "{
8049   rtx op3, scratch, scratch2;
8050
8051   if (!TARGET_THUMB1)
8052     {
8053       if (!arm_add_operand (operands[3], SImode))
8054         operands[3] = force_reg (SImode, operands[3]);
8055       emit_insn (gen_cstore_cc (operands[0], operands[1],
8056                                 operands[2], operands[3]));
8057       DONE;
8058     }
8059
8060   if (operands[3] == const0_rtx)
8061     {
8062       switch (GET_CODE (operands[1]))
8063         {
8064         case EQ:
8065           emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
8066           break;
8067
8068         case NE:
8069           emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
8070           break;
8071
8072         case LE:
8073           scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
8074                                   NULL_RTX, 0, OPTAB_WIDEN);
8075           scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
8076                                   NULL_RTX, 0, OPTAB_WIDEN);
8077           expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
8078                         operands[0], 1, OPTAB_WIDEN);
8079           break;
8080
8081         case GE:
8082           scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
8083                                  NULL_RTX, 1);
8084           expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
8085                         NULL_RTX, 1, OPTAB_WIDEN);
8086           break;
8087
8088         case GT:
8089           scratch = expand_binop (SImode, ashr_optab, operands[2],
8090                                   GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
8091           scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
8092                                   NULL_RTX, 0, OPTAB_WIDEN);
8093           expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
8094                         0, OPTAB_WIDEN);
8095           break;
8096
8097         /* LT is handled by generic code.  No need for unsigned with 0.  */
8098         default:
8099           FAIL;
8100         }
8101       DONE;
8102     }
8103
8104   switch (GET_CODE (operands[1]))
8105     {
8106     case EQ:
8107       scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
8108                               NULL_RTX, 0, OPTAB_WIDEN);
8109       emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
8110       break;
8111
8112     case NE:
8113       scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
8114                               NULL_RTX, 0, OPTAB_WIDEN);
8115       emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
8116       break;
8117
8118     case LE:
8119       op3 = force_reg (SImode, operands[3]);
8120
8121       scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
8122                               NULL_RTX, 1, OPTAB_WIDEN);
8123       scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
8124                               NULL_RTX, 0, OPTAB_WIDEN);
8125       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
8126                                           op3, operands[2]));
8127       break;
8128
8129     case GE:
8130       op3 = operands[3];
8131       if (!thumb1_cmp_operand (op3, SImode))
8132         op3 = force_reg (SImode, op3);
8133       scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
8134                               NULL_RTX, 0, OPTAB_WIDEN);
8135       scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
8136                                NULL_RTX, 1, OPTAB_WIDEN);
8137       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
8138                                           operands[2], op3));
8139       break;
8140
8141     case LEU:
8142       op3 = force_reg (SImode, operands[3]);
8143       scratch = force_reg (SImode, const0_rtx);
8144       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
8145                                           op3, operands[2]));
8146       break;
8147
8148     case GEU:
8149       op3 = operands[3];
8150       if (!thumb1_cmp_operand (op3, SImode))
8151         op3 = force_reg (SImode, op3);
8152       scratch = force_reg (SImode, const0_rtx);
8153       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
8154                                           operands[2], op3));
8155       break;
8156
8157     case LTU:
8158       op3 = operands[3];
8159       if (!thumb1_cmp_operand (op3, SImode))
8160         op3 = force_reg (SImode, op3);
8161       scratch = gen_reg_rtx (SImode);
8162       emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
8163       break;
8164
8165     case GTU:
8166       op3 = force_reg (SImode, operands[3]);
8167       scratch = gen_reg_rtx (SImode);
8168       emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
8169       break;
8170
8171     /* No good sequences for GT, LT.  */
8172     default:
8173       FAIL;
8174     }
8175   DONE;
8176 }")
8177
8178 (define_expand "cstoresf4"
8179   [(set (match_operand:SI 0 "s_register_operand" "")
8180         (match_operator:SI 1 "arm_comparison_operator"
8181          [(match_operand:SF 2 "s_register_operand" "")
8182           (match_operand:SF 3 "arm_float_compare_operand" "")]))]
8183   "TARGET_32BIT && TARGET_HARD_FLOAT"
8184   "emit_insn (gen_cstore_cc (operands[0], operands[1],
8185                              operands[2], operands[3])); DONE;"
8186 )
8187
8188 (define_expand "cstoredf4"
8189   [(set (match_operand:SI 0 "s_register_operand" "")
8190         (match_operator:SI 1 "arm_comparison_operator"
8191          [(match_operand:DF 2 "s_register_operand" "")
8192           (match_operand:DF 3 "arm_float_compare_operand" "")]))]
8193   "TARGET_32BIT && TARGET_HARD_FLOAT"
8194   "emit_insn (gen_cstore_cc (operands[0], operands[1],
8195                              operands[2], operands[3])); DONE;"
8196 )
8197
8198 ;; this uses the Cirrus DI compare instruction
8199 (define_expand "cstoredi4"
8200   [(set (match_operand:SI 0 "s_register_operand" "")
8201         (match_operator:SI 1 "arm_comparison_operator"
8202          [(match_operand:DI 2 "cirrus_fp_register" "")
8203           (match_operand:DI 3 "cirrus_fp_register" "")]))]
8204   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
8205   "emit_insn (gen_cstore_cc (operands[0], operands[1],
8206                              operands[2], operands[3])); DONE;"
8207 )
8208
8209
8210 (define_expand "cstoresi_eq0_thumb1"
8211   [(parallel
8212     [(set (match_operand:SI 0 "s_register_operand" "")
8213           (eq:SI (match_operand:SI 1 "s_register_operand" "")
8214                  (const_int 0)))
8215      (clobber (match_dup:SI 2))])]
8216   "TARGET_THUMB1"
8217   "operands[2] = gen_reg_rtx (SImode);"
8218 )
8219
8220 (define_expand "cstoresi_ne0_thumb1"
8221   [(parallel
8222     [(set (match_operand:SI 0 "s_register_operand" "")
8223           (ne:SI (match_operand:SI 1 "s_register_operand" "")
8224                  (const_int 0)))
8225      (clobber (match_dup:SI 2))])]
8226   "TARGET_THUMB1"
8227   "operands[2] = gen_reg_rtx (SImode);"
8228 )
8229
8230 (define_insn "*cstoresi_eq0_thumb1_insn"
8231   [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
8232         (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
8233                (const_int 0)))
8234    (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
8235   "TARGET_THUMB1"
8236   "@
8237    neg\\t%0, %1\;adc\\t%0, %0, %1
8238    neg\\t%2, %1\;adc\\t%0, %1, %2"
8239   [(set_attr "length" "4")]
8240 )
8241
8242 (define_insn "*cstoresi_ne0_thumb1_insn"
8243   [(set (match_operand:SI 0 "s_register_operand" "=l")
8244         (ne:SI (match_operand:SI 1 "s_register_operand" "0")
8245                (const_int 0)))
8246    (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
8247   "TARGET_THUMB1"
8248   "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
8249   [(set_attr "length" "4")]
8250 )
8251
8252 ;; Used as part of the expansion of thumb ltu and gtu sequences
8253 (define_insn "cstoresi_nltu_thumb1"
8254   [(set (match_operand:SI 0 "s_register_operand" "=l,l")
8255         (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
8256                         (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
8257   "TARGET_THUMB1"
8258   "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
8259   [(set_attr "length" "4")]
8260 )
8261
8262 (define_insn_and_split "cstoresi_ltu_thumb1"
8263   [(set (match_operand:SI 0 "s_register_operand" "=l,l")
8264         (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
8265                 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")))]
8266   "TARGET_THUMB1"
8267   "#"
8268   "TARGET_THUMB1"
8269   [(set (match_dup 3)
8270         (neg:SI (ltu:SI (match_dup 1) (match_dup 2))))
8271    (set (match_dup 0) (neg:SI (match_dup 3)))]
8272   "operands[3] = gen_reg_rtx (SImode);"
8273   [(set_attr "length" "4")]
8274 )
8275
8276 ;; Used as part of the expansion of thumb les sequence.
8277 (define_insn "thumb1_addsi3_addgeu"
8278   [(set (match_operand:SI 0 "s_register_operand" "=l")
8279         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8280                           (match_operand:SI 2 "s_register_operand" "l"))
8281                  (geu:SI (match_operand:SI 3 "s_register_operand" "l")
8282                          (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
8283   "TARGET_THUMB1"
8284   "cmp\\t%3, %4\;adc\\t%0, %1, %2"
8285   [(set_attr "length" "4")]
8286 )
8287
8288 \f
8289 ;; Conditional move insns
8290
8291 (define_expand "movsicc"
8292   [(set (match_operand:SI 0 "s_register_operand" "")
8293         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
8294                          (match_operand:SI 2 "arm_not_operand" "")
8295                          (match_operand:SI 3 "arm_not_operand" "")))]
8296   "TARGET_32BIT"
8297   "
8298   {
8299     enum rtx_code code = GET_CODE (operands[1]);
8300     rtx ccreg;
8301
8302     if (code == UNEQ || code == LTGT)
8303       FAIL;
8304
8305     ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8306                                  XEXP (operands[1], 1));
8307     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
8308   }"
8309 )
8310
8311 (define_expand "movsfcc"
8312   [(set (match_operand:SF 0 "s_register_operand" "")
8313         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
8314                          (match_operand:SF 2 "s_register_operand" "")
8315                          (match_operand:SF 3 "nonmemory_operand" "")))]
8316   "TARGET_32BIT && TARGET_HARD_FLOAT"
8317   "
8318   {
8319     enum rtx_code code = GET_CODE (operands[1]);
8320     rtx ccreg;
8321
8322     if (code == UNEQ || code == LTGT)
8323       FAIL;
8324
8325     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
8326        Otherwise, ensure it is a valid FP add operand */
8327     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
8328         || (!arm_float_add_operand (operands[3], SFmode)))
8329       operands[3] = force_reg (SFmode, operands[3]);
8330
8331     ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8332                                  XEXP (operands[1], 1));
8333     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
8334   }"
8335 )
8336
8337 (define_expand "movdfcc"
8338   [(set (match_operand:DF 0 "s_register_operand" "")
8339         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
8340                          (match_operand:DF 2 "s_register_operand" "")
8341                          (match_operand:DF 3 "arm_float_add_operand" "")))]
8342   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
8343   "
8344   {
8345     enum rtx_code code = GET_CODE (operands[1]);
8346     rtx ccreg;
8347
8348     if (code == UNEQ || code == LTGT)
8349       FAIL;
8350
8351     ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8352                                  XEXP (operands[1], 1));
8353     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
8354   }"
8355 )
8356
8357 (define_insn "*movsicc_insn"
8358   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8359         (if_then_else:SI
8360          (match_operator 3 "arm_comparison_operator"
8361           [(match_operand 4 "cc_register" "") (const_int 0)])
8362          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
8363          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
8364   "TARGET_ARM"
8365   "@
8366    mov%D3\\t%0, %2
8367    mvn%D3\\t%0, #%B2
8368    mov%d3\\t%0, %1
8369    mvn%d3\\t%0, #%B1
8370    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
8371    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
8372    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
8373    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
8374   [(set_attr "length" "4,4,4,4,8,8,8,8")
8375    (set_attr "conds" "use")]
8376 )
8377
8378 (define_insn "*movsfcc_soft_insn"
8379   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8380         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8381                           [(match_operand 4 "cc_register" "") (const_int 0)])
8382                          (match_operand:SF 1 "s_register_operand" "0,r")
8383                          (match_operand:SF 2 "s_register_operand" "r,0")))]
8384   "TARGET_ARM && TARGET_SOFT_FLOAT"
8385   "@
8386    mov%D3\\t%0, %2
8387    mov%d3\\t%0, %1"
8388   [(set_attr "conds" "use")]
8389 )
8390
8391 \f
8392 ;; Jump and linkage insns
8393
8394 (define_expand "jump"
8395   [(set (pc)
8396         (label_ref (match_operand 0 "" "")))]
8397   "TARGET_EITHER"
8398   ""
8399 )
8400
8401 (define_insn "*arm_jump"
8402   [(set (pc)
8403         (label_ref (match_operand 0 "" "")))]
8404   "TARGET_32BIT"
8405   "*
8406   {
8407     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
8408       {
8409         arm_ccfsm_state += 2;
8410         return \"\";
8411       }
8412     return \"b%?\\t%l0\";
8413   }
8414   "
8415   [(set_attr "predicable" "yes")]
8416 )
8417
8418 (define_insn "*thumb_jump"
8419   [(set (pc)
8420         (label_ref (match_operand 0 "" "")))]
8421   "TARGET_THUMB1"
8422   "*
8423   if (get_attr_length (insn) == 2)
8424     return \"b\\t%l0\";
8425   return \"bl\\t%l0\\t%@ far jump\";
8426   "
8427   [(set (attr "far_jump")
8428         (if_then_else
8429             (eq_attr "length" "4")
8430             (const_string "yes")
8431             (const_string "no")))
8432    (set (attr "length") 
8433         (if_then_else
8434             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8435                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
8436             (const_int 2)
8437             (const_int 4)))]
8438 )
8439
8440 (define_expand "call"
8441   [(parallel [(call (match_operand 0 "memory_operand" "")
8442                     (match_operand 1 "general_operand" ""))
8443               (use (match_operand 2 "" ""))
8444               (clobber (reg:SI LR_REGNUM))])]
8445   "TARGET_EITHER"
8446   "
8447   {
8448     rtx callee, pat;
8449     
8450     /* In an untyped call, we can get NULL for operand 2.  */
8451     if (operands[2] == NULL_RTX)
8452       operands[2] = const0_rtx;
8453       
8454     /* Decide if we should generate indirect calls by loading the
8455        32-bit address of the callee into a register before performing the
8456        branch and link.  */
8457     callee = XEXP (operands[0], 0);
8458     if (GET_CODE (callee) == SYMBOL_REF
8459         ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8460         : !REG_P (callee))
8461       XEXP (operands[0], 0) = force_reg (Pmode, callee);
8462
8463     pat = gen_call_internal (operands[0], operands[1], operands[2]);
8464     arm_emit_call_insn (pat, XEXP (operands[0], 0));
8465     DONE;
8466   }"
8467 )
8468
8469 (define_expand "call_internal"
8470   [(parallel [(call (match_operand 0 "memory_operand" "")
8471                     (match_operand 1 "general_operand" ""))
8472               (use (match_operand 2 "" ""))
8473               (clobber (reg:SI LR_REGNUM))])])
8474
8475 (define_insn "*call_reg_armv5"
8476   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8477          (match_operand 1 "" ""))
8478    (use (match_operand 2 "" ""))
8479    (clobber (reg:SI LR_REGNUM))]
8480   "TARGET_ARM && arm_arch5"
8481   "blx%?\\t%0"
8482   [(set_attr "type" "call")]
8483 )
8484
8485 (define_insn "*call_reg_arm"
8486   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8487          (match_operand 1 "" ""))
8488    (use (match_operand 2 "" ""))
8489    (clobber (reg:SI LR_REGNUM))]
8490   "TARGET_ARM && !arm_arch5"
8491   "*
8492   return output_call (operands);
8493   "
8494   ;; length is worst case, normally it is only two
8495   [(set_attr "length" "12")
8496    (set_attr "type" "call")]
8497 )
8498
8499
8500 ;; Note: not used for armv5+ because the sequence used (ldr pc, ...) is not
8501 ;; considered a function call by the branch predictor of some cores (PR40887).
8502 ;; Falls back to blx rN (*call_reg_armv5).
8503
8504 (define_insn "*call_mem"
8505   [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
8506          (match_operand 1 "" ""))
8507    (use (match_operand 2 "" ""))
8508    (clobber (reg:SI LR_REGNUM))]
8509   "TARGET_ARM && !arm_arch5"
8510   "*
8511   return output_call_mem (operands);
8512   "
8513   [(set_attr "length" "12")
8514    (set_attr "type" "call")]
8515 )
8516
8517 (define_insn "*call_reg_thumb1_v5"
8518   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8519          (match_operand 1 "" ""))
8520    (use (match_operand 2 "" ""))
8521    (clobber (reg:SI LR_REGNUM))]
8522   "TARGET_THUMB1 && arm_arch5"
8523   "blx\\t%0"
8524   [(set_attr "length" "2")
8525    (set_attr "type" "call")]
8526 )
8527
8528 (define_insn "*call_reg_thumb1"
8529   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8530          (match_operand 1 "" ""))
8531    (use (match_operand 2 "" ""))
8532    (clobber (reg:SI LR_REGNUM))]
8533   "TARGET_THUMB1 && !arm_arch5"
8534   "*
8535   {
8536     if (!TARGET_CALLER_INTERWORKING)
8537       return thumb_call_via_reg (operands[0]);
8538     else if (operands[1] == const0_rtx)
8539       return \"bl\\t%__interwork_call_via_%0\";
8540     else if (frame_pointer_needed)
8541       return \"bl\\t%__interwork_r7_call_via_%0\";
8542     else
8543       return \"bl\\t%__interwork_r11_call_via_%0\";
8544   }"
8545   [(set_attr "type" "call")]
8546 )
8547
8548 (define_expand "call_value"
8549   [(parallel [(set (match_operand       0 "" "")
8550                    (call (match_operand 1 "memory_operand" "")
8551                          (match_operand 2 "general_operand" "")))
8552               (use (match_operand 3 "" ""))
8553               (clobber (reg:SI LR_REGNUM))])]
8554   "TARGET_EITHER"
8555   "
8556   {
8557     rtx pat, callee;
8558     
8559     /* In an untyped call, we can get NULL for operand 2.  */
8560     if (operands[3] == 0)
8561       operands[3] = const0_rtx;
8562       
8563     /* Decide if we should generate indirect calls by loading the
8564        32-bit address of the callee into a register before performing the
8565        branch and link.  */
8566     callee = XEXP (operands[1], 0);
8567     if (GET_CODE (callee) == SYMBOL_REF
8568         ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8569         : !REG_P (callee))
8570       XEXP (operands[1], 0) = force_reg (Pmode, callee);
8571
8572     pat = gen_call_value_internal (operands[0], operands[1],
8573                                    operands[2], operands[3]);
8574     arm_emit_call_insn (pat, XEXP (operands[1], 0));
8575     DONE;
8576   }"
8577 )
8578
8579 (define_expand "call_value_internal"
8580   [(parallel [(set (match_operand       0 "" "")
8581                    (call (match_operand 1 "memory_operand" "")
8582                          (match_operand 2 "general_operand" "")))
8583               (use (match_operand 3 "" ""))
8584               (clobber (reg:SI LR_REGNUM))])])
8585
8586 (define_insn "*call_value_reg_armv5"
8587   [(set (match_operand 0 "" "")
8588         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8589               (match_operand 2 "" "")))
8590    (use (match_operand 3 "" ""))
8591    (clobber (reg:SI LR_REGNUM))]
8592   "TARGET_ARM && arm_arch5"
8593   "blx%?\\t%1"
8594   [(set_attr "type" "call")]
8595 )
8596
8597 (define_insn "*call_value_reg_arm"
8598   [(set (match_operand 0 "" "")
8599         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8600               (match_operand 2 "" "")))
8601    (use (match_operand 3 "" ""))
8602    (clobber (reg:SI LR_REGNUM))]
8603   "TARGET_ARM && !arm_arch5"
8604   "*
8605   return output_call (&operands[1]);
8606   "
8607   [(set_attr "length" "12")
8608    (set_attr "type" "call")]
8609 )
8610
8611 ;; Note: see *call_mem
8612
8613 (define_insn "*call_value_mem"
8614   [(set (match_operand 0 "" "")
8615         (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
8616               (match_operand 2 "" "")))
8617    (use (match_operand 3 "" ""))
8618    (clobber (reg:SI LR_REGNUM))]
8619   "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
8620   "*
8621   return output_call_mem (&operands[1]);
8622   "
8623   [(set_attr "length" "12")
8624    (set_attr "type" "call")]
8625 )
8626
8627 (define_insn "*call_value_reg_thumb1_v5"
8628   [(set (match_operand 0 "" "")
8629         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8630               (match_operand 2 "" "")))
8631    (use (match_operand 3 "" ""))
8632    (clobber (reg:SI LR_REGNUM))]
8633   "TARGET_THUMB1 && arm_arch5"
8634   "blx\\t%1"
8635   [(set_attr "length" "2")
8636    (set_attr "type" "call")]
8637 )
8638
8639 (define_insn "*call_value_reg_thumb1"
8640   [(set (match_operand 0 "" "")
8641         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8642               (match_operand 2 "" "")))
8643    (use (match_operand 3 "" ""))
8644    (clobber (reg:SI LR_REGNUM))]
8645   "TARGET_THUMB1 && !arm_arch5"
8646   "*
8647   {
8648     if (!TARGET_CALLER_INTERWORKING)
8649       return thumb_call_via_reg (operands[1]);
8650     else if (operands[2] == const0_rtx)
8651       return \"bl\\t%__interwork_call_via_%1\";
8652     else if (frame_pointer_needed)
8653       return \"bl\\t%__interwork_r7_call_via_%1\";
8654     else
8655       return \"bl\\t%__interwork_r11_call_via_%1\";
8656   }"
8657   [(set_attr "type" "call")]
8658 )
8659
8660 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8661 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8662
8663 (define_insn "*call_symbol"
8664   [(call (mem:SI (match_operand:SI 0 "" ""))
8665          (match_operand 1 "" ""))
8666    (use (match_operand 2 "" ""))
8667    (clobber (reg:SI LR_REGNUM))]
8668   "TARGET_32BIT
8669    && (GET_CODE (operands[0]) == SYMBOL_REF)
8670    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
8671   "*
8672   {
8673     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
8674   }"
8675   [(set_attr "type" "call")]
8676 )
8677
8678 (define_insn "*call_value_symbol"
8679   [(set (match_operand 0 "" "")
8680         (call (mem:SI (match_operand:SI 1 "" ""))
8681         (match_operand:SI 2 "" "")))
8682    (use (match_operand 3 "" ""))
8683    (clobber (reg:SI LR_REGNUM))]
8684   "TARGET_32BIT
8685    && (GET_CODE (operands[1]) == SYMBOL_REF)
8686    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
8687   "*
8688   {
8689     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
8690   }"
8691   [(set_attr "type" "call")]
8692 )
8693
8694 (define_insn "*call_insn"
8695   [(call (mem:SI (match_operand:SI 0 "" ""))
8696          (match_operand:SI 1 "" ""))
8697    (use (match_operand 2 "" ""))
8698    (clobber (reg:SI LR_REGNUM))]
8699   "TARGET_THUMB1
8700    && GET_CODE (operands[0]) == SYMBOL_REF
8701    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
8702   "bl\\t%a0"
8703   [(set_attr "length" "4")
8704    (set_attr "type" "call")]
8705 )
8706
8707 (define_insn "*call_value_insn"
8708   [(set (match_operand 0 "" "")
8709         (call (mem:SI (match_operand 1 "" ""))
8710               (match_operand 2 "" "")))
8711    (use (match_operand 3 "" ""))
8712    (clobber (reg:SI LR_REGNUM))]
8713   "TARGET_THUMB1
8714    && GET_CODE (operands[1]) == SYMBOL_REF
8715    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
8716   "bl\\t%a1"
8717   [(set_attr "length" "4")
8718    (set_attr "type" "call")]
8719 )
8720
8721 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
8722 (define_expand "sibcall"
8723   [(parallel [(call (match_operand 0 "memory_operand" "")
8724                     (match_operand 1 "general_operand" ""))
8725               (return)
8726               (use (match_operand 2 "" ""))])]
8727   "TARGET_32BIT"
8728   "
8729   {
8730     if (operands[2] == NULL_RTX)
8731       operands[2] = const0_rtx;
8732   }"
8733 )
8734
8735 (define_expand "sibcall_value"
8736   [(parallel [(set (match_operand 0 "" "")
8737                    (call (match_operand 1 "memory_operand" "")
8738                          (match_operand 2 "general_operand" "")))
8739               (return)
8740               (use (match_operand 3 "" ""))])]
8741   "TARGET_32BIT"
8742   "
8743   {
8744     if (operands[3] == NULL_RTX)
8745       operands[3] = const0_rtx;
8746   }"
8747 )
8748
8749 (define_insn "*sibcall_insn"
8750  [(call (mem:SI (match_operand:SI 0 "" "X"))
8751         (match_operand 1 "" ""))
8752   (return)
8753   (use (match_operand 2 "" ""))]
8754   "TARGET_32BIT && GET_CODE (operands[0]) == SYMBOL_REF"
8755   "*
8756   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8757   "
8758   [(set_attr "type" "call")]
8759 )
8760
8761 (define_insn "*sibcall_value_insn"
8762  [(set (match_operand 0 "" "")
8763        (call (mem:SI (match_operand:SI 1 "" "X"))
8764              (match_operand 2 "" "")))
8765   (return)
8766   (use (match_operand 3 "" ""))]
8767   "TARGET_32BIT && GET_CODE (operands[1]) == SYMBOL_REF"
8768   "*
8769   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8770   "
8771   [(set_attr "type" "call")]
8772 )
8773
8774 (define_expand "return"
8775   [(return)]
8776   "TARGET_32BIT && USE_RETURN_INSN (FALSE)"
8777   "")
8778
8779 ;; Often the return insn will be the same as loading from memory, so set attr
8780 (define_insn "*arm_return"
8781   [(return)]
8782   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
8783   "*
8784   {
8785     if (arm_ccfsm_state == 2)
8786       {
8787         arm_ccfsm_state += 2;
8788         return \"\";
8789       }
8790     return output_return_instruction (const_true_rtx, TRUE, FALSE);
8791   }"
8792   [(set_attr "type" "load1")
8793    (set_attr "length" "12")
8794    (set_attr "predicable" "yes")]
8795 )
8796
8797 (define_insn "*cond_return"
8798   [(set (pc)
8799         (if_then_else (match_operator 0 "arm_comparison_operator"
8800                        [(match_operand 1 "cc_register" "") (const_int 0)])
8801                       (return)
8802                       (pc)))]
8803   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
8804   "*
8805   {
8806     if (arm_ccfsm_state == 2)
8807       {
8808         arm_ccfsm_state += 2;
8809         return \"\";
8810       }
8811     return output_return_instruction (operands[0], TRUE, FALSE);
8812   }"
8813   [(set_attr "conds" "use")
8814    (set_attr "length" "12")
8815    (set_attr "type" "load1")]
8816 )
8817
8818 (define_insn "*cond_return_inverted"
8819   [(set (pc)
8820         (if_then_else (match_operator 0 "arm_comparison_operator"
8821                        [(match_operand 1 "cc_register" "") (const_int 0)])
8822                       (pc)
8823                       (return)))]
8824   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
8825   "*
8826   {
8827     if (arm_ccfsm_state == 2)
8828       {
8829         arm_ccfsm_state += 2;
8830         return \"\";
8831       }
8832     return output_return_instruction (operands[0], TRUE, TRUE);
8833   }"
8834   [(set_attr "conds" "use")
8835    (set_attr "length" "12")
8836    (set_attr "type" "load1")]
8837 )
8838
8839 ;; Generate a sequence of instructions to determine if the processor is
8840 ;; in 26-bit or 32-bit mode, and return the appropriate return address
8841 ;; mask.
8842
8843 (define_expand "return_addr_mask"
8844   [(set (match_dup 1)
8845       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8846                        (const_int 0)))
8847    (set (match_operand:SI 0 "s_register_operand" "")
8848       (if_then_else:SI (eq (match_dup 1) (const_int 0))
8849                        (const_int -1)
8850                        (const_int 67108860)))] ; 0x03fffffc
8851   "TARGET_ARM"
8852   "
8853   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
8854   ")
8855
8856 (define_insn "*check_arch2"
8857   [(set (match_operand:CC_NOOV 0 "cc_register" "")
8858       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8859                        (const_int 0)))]
8860   "TARGET_ARM"
8861   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8862   [(set_attr "length" "8")
8863    (set_attr "conds" "set")]
8864 )
8865
8866 ;; Call subroutine returning any type.
8867
8868 (define_expand "untyped_call"
8869   [(parallel [(call (match_operand 0 "" "")
8870                     (const_int 0))
8871               (match_operand 1 "" "")
8872               (match_operand 2 "" "")])]
8873   "TARGET_EITHER"
8874   "
8875   {
8876     int i;
8877     rtx par = gen_rtx_PARALLEL (VOIDmode,
8878                                 rtvec_alloc (XVECLEN (operands[2], 0)));
8879     rtx addr = gen_reg_rtx (Pmode);
8880     rtx mem;
8881     int size = 0;
8882
8883     emit_move_insn (addr, XEXP (operands[1], 0));
8884     mem = change_address (operands[1], BLKmode, addr);
8885
8886     for (i = 0; i < XVECLEN (operands[2], 0); i++)
8887       {
8888         rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
8889
8890         /* Default code only uses r0 as a return value, but we could
8891            be using anything up to 4 registers.  */
8892         if (REGNO (src) == R0_REGNUM)
8893           src = gen_rtx_REG (TImode, R0_REGNUM);
8894
8895         XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8896                                                  GEN_INT (size));
8897         size += GET_MODE_SIZE (GET_MODE (src));
8898       }
8899
8900     emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8901                                     const0_rtx));
8902
8903     size = 0;
8904
8905     for (i = 0; i < XVECLEN (par, 0); i++)
8906       {
8907         HOST_WIDE_INT offset = 0;
8908         rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8909
8910         if (size != 0)
8911           emit_move_insn (addr, plus_constant (addr, size));
8912
8913         mem = change_address (mem, GET_MODE (reg), NULL);
8914         if (REGNO (reg) == R0_REGNUM)
8915           {
8916             /* On thumb we have to use a write-back instruction.  */
8917             emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
8918                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8919             size = TARGET_ARM ? 16 : 0;
8920           }
8921         else
8922           {
8923             emit_move_insn (mem, reg);
8924             size = GET_MODE_SIZE (GET_MODE (reg));
8925           }
8926       }
8927
8928     /* The optimizer does not know that the call sets the function value
8929        registers we stored in the result block.  We avoid problems by
8930        claiming that all hard registers are used and clobbered at this
8931        point.  */
8932     emit_insn (gen_blockage ());
8933
8934     DONE;
8935   }"
8936 )
8937
8938 (define_expand "untyped_return"
8939   [(match_operand:BLK 0 "memory_operand" "")
8940    (match_operand 1 "" "")]
8941   "TARGET_EITHER"
8942   "
8943   {
8944     int i;
8945     rtx addr = gen_reg_rtx (Pmode);
8946     rtx mem;
8947     int size = 0;
8948
8949     emit_move_insn (addr, XEXP (operands[0], 0));
8950     mem = change_address (operands[0], BLKmode, addr);
8951
8952     for (i = 0; i < XVECLEN (operands[1], 0); i++)
8953       {
8954         HOST_WIDE_INT offset = 0;
8955         rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8956
8957         if (size != 0)
8958           emit_move_insn (addr, plus_constant (addr, size));
8959
8960         mem = change_address (mem, GET_MODE (reg), NULL);
8961         if (REGNO (reg) == R0_REGNUM)
8962           {
8963             /* On thumb we have to use a write-back instruction.  */
8964             emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
8965                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8966             size = TARGET_ARM ? 16 : 0;
8967           }
8968         else
8969           {
8970             emit_move_insn (reg, mem);
8971             size = GET_MODE_SIZE (GET_MODE (reg));
8972           }
8973       }
8974
8975     /* Emit USE insns before the return.  */
8976     for (i = 0; i < XVECLEN (operands[1], 0); i++)
8977       emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
8978
8979     /* Construct the return.  */
8980     expand_naked_return ();
8981
8982     DONE;
8983   }"
8984 )
8985
8986 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8987 ;; all of memory.  This blocks insns from being moved across this point.
8988
8989 (define_insn "blockage"
8990   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
8991   "TARGET_EITHER"
8992   ""
8993   [(set_attr "length" "0")
8994    (set_attr "type" "block")]
8995 )
8996
8997 (define_expand "casesi"
8998   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
8999    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
9000    (match_operand:SI 2 "const_int_operand" "")  ; total range
9001    (match_operand:SI 3 "" "")                   ; table label
9002    (match_operand:SI 4 "" "")]                  ; Out of range label
9003   "TARGET_32BIT || optimize_size || flag_pic"
9004   "
9005   {
9006     enum insn_code code;
9007     if (operands[1] != const0_rtx)
9008       {
9009         rtx reg = gen_reg_rtx (SImode);
9010
9011         emit_insn (gen_addsi3 (reg, operands[0],
9012                                GEN_INT (-INTVAL (operands[1]))));
9013         operands[0] = reg;
9014       }
9015
9016     if (TARGET_ARM)
9017       code = CODE_FOR_arm_casesi_internal;
9018     else if (TARGET_THUMB1)
9019       code = CODE_FOR_thumb1_casesi_internal_pic;
9020     else if (flag_pic)
9021       code = CODE_FOR_thumb2_casesi_internal_pic;
9022     else
9023       code = CODE_FOR_thumb2_casesi_internal;
9024
9025     if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
9026       operands[2] = force_reg (SImode, operands[2]);
9027
9028     emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
9029                                           operands[3], operands[4]));
9030     DONE;
9031   }"
9032 )
9033
9034 ;; The USE in this pattern is needed to tell flow analysis that this is
9035 ;; a CASESI insn.  It has no other purpose.
9036 (define_insn "arm_casesi_internal"
9037   [(parallel [(set (pc)
9038                (if_then_else
9039                 (leu (match_operand:SI 0 "s_register_operand" "r")
9040                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
9041                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
9042                                  (label_ref (match_operand 2 "" ""))))
9043                 (label_ref (match_operand 3 "" ""))))
9044               (clobber (reg:CC CC_REGNUM))
9045               (use (label_ref (match_dup 2)))])]
9046   "TARGET_ARM"
9047   "*
9048     if (flag_pic)
9049       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
9050     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
9051   "
9052   [(set_attr "conds" "clob")
9053    (set_attr "length" "12")]
9054 )
9055
9056 (define_expand "thumb1_casesi_internal_pic"
9057   [(match_operand:SI 0 "s_register_operand" "")
9058    (match_operand:SI 1 "thumb1_cmp_operand" "")
9059    (match_operand 2 "" "")
9060    (match_operand 3 "" "")]
9061   "TARGET_THUMB1"
9062   {
9063     rtx reg0;
9064     rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[1]);
9065     emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[1],
9066                                     operands[3]));
9067     reg0 = gen_rtx_REG (SImode, 0);
9068     emit_move_insn (reg0, operands[0]);
9069     emit_jump_insn (gen_thumb1_casesi_dispatch (operands[2]/*, operands[3]*/));
9070     DONE;
9071   }
9072 )
9073
9074 (define_insn "thumb1_casesi_dispatch"
9075   [(parallel [(set (pc) (unspec [(reg:SI 0)
9076                                  (label_ref (match_operand 0 "" ""))
9077 ;;                               (label_ref (match_operand 1 "" ""))
9078 ]
9079                          UNSPEC_THUMB1_CASESI))
9080               (clobber (reg:SI IP_REGNUM))
9081               (clobber (reg:SI LR_REGNUM))])]
9082   "TARGET_THUMB1"
9083   "* return thumb1_output_casesi(operands);"
9084   [(set_attr "length" "4")]
9085 )
9086
9087 (define_expand "indirect_jump"
9088   [(set (pc)
9089         (match_operand:SI 0 "s_register_operand" ""))]
9090   "TARGET_EITHER"
9091   "
9092   /* Thumb-2 doesn't have mov pc, reg.  Explicitly set the low bit of the
9093      address and use bx.  */
9094   if (TARGET_THUMB2)
9095     {
9096       rtx tmp;
9097       tmp = gen_reg_rtx (SImode);
9098       emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
9099       operands[0] = tmp;
9100     }
9101   "
9102 )
9103
9104 ;; NB Never uses BX.
9105 (define_insn "*arm_indirect_jump"
9106   [(set (pc)
9107         (match_operand:SI 0 "s_register_operand" "r"))]
9108   "TARGET_ARM"
9109   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
9110   [(set_attr "predicable" "yes")]
9111 )
9112
9113 (define_insn "*load_indirect_jump"
9114   [(set (pc)
9115         (match_operand:SI 0 "memory_operand" "m"))]
9116   "TARGET_ARM"
9117   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
9118   [(set_attr "type" "load1")
9119    (set_attr "pool_range" "4096")
9120    (set_attr "neg_pool_range" "4084")
9121    (set_attr "predicable" "yes")]
9122 )
9123
9124 ;; NB Never uses BX.
9125 (define_insn "*thumb1_indirect_jump"
9126   [(set (pc)
9127         (match_operand:SI 0 "register_operand" "l*r"))]
9128   "TARGET_THUMB1"
9129   "mov\\tpc, %0"
9130   [(set_attr "conds" "clob")
9131    (set_attr "length" "2")]
9132 )
9133
9134 \f
9135 ;; Misc insns
9136
9137 (define_insn "nop"
9138   [(const_int 0)]
9139   "TARGET_EITHER"
9140   "*
9141   if (TARGET_UNIFIED_ASM)
9142     return \"nop\";
9143   if (TARGET_ARM)
9144     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
9145   return  \"mov\\tr8, r8\";
9146   "
9147   [(set (attr "length")
9148         (if_then_else (eq_attr "is_thumb" "yes")
9149                       (const_int 2)
9150                       (const_int 4)))]
9151 )
9152
9153 \f
9154 ;; Patterns to allow combination of arithmetic, cond code and shifts
9155
9156 (define_insn "*arith_shiftsi"
9157   [(set (match_operand:SI 0 "s_register_operand" "=r")
9158         (match_operator:SI 1 "shiftable_operator"
9159           [(match_operator:SI 3 "shift_operator"
9160              [(match_operand:SI 4 "s_register_operand" "r")
9161               (match_operand:SI 5 "reg_or_int_operand" "rI")])
9162            (match_operand:SI 2 "s_register_operand" "r")]))]
9163   "TARGET_ARM"
9164   "%i1%?\\t%0, %2, %4%S3"
9165   [(set_attr "predicable" "yes")
9166    (set_attr "shift" "4")
9167    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
9168                       (const_string "alu_shift")
9169                       (const_string "alu_shift_reg")))]
9170 )
9171
9172 (define_split
9173   [(set (match_operand:SI 0 "s_register_operand" "")
9174         (match_operator:SI 1 "shiftable_operator"
9175          [(match_operator:SI 2 "shiftable_operator"
9176            [(match_operator:SI 3 "shift_operator"
9177              [(match_operand:SI 4 "s_register_operand" "")
9178               (match_operand:SI 5 "reg_or_int_operand" "")])
9179             (match_operand:SI 6 "s_register_operand" "")])
9180           (match_operand:SI 7 "arm_rhs_operand" "")]))
9181    (clobber (match_operand:SI 8 "s_register_operand" ""))]
9182   "TARGET_ARM"
9183   [(set (match_dup 8)
9184         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9185                          (match_dup 6)]))
9186    (set (match_dup 0)
9187         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
9188   "")
9189
9190 (define_insn "*arith_shiftsi_compare0"
9191   [(set (reg:CC_NOOV CC_REGNUM)
9192         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
9193                           [(match_operator:SI 3 "shift_operator"
9194                             [(match_operand:SI 4 "s_register_operand" "r")
9195                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
9196                            (match_operand:SI 2 "s_register_operand" "r")])
9197                          (const_int 0)))
9198    (set (match_operand:SI 0 "s_register_operand" "=r")
9199         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9200                          (match_dup 2)]))]
9201   "TARGET_ARM"
9202   "%i1%.\\t%0, %2, %4%S3"
9203   [(set_attr "conds" "set")
9204    (set_attr "shift" "4")
9205    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
9206                       (const_string "alu_shift")
9207                       (const_string "alu_shift_reg")))]
9208 )
9209
9210 (define_insn "*arith_shiftsi_compare0_scratch"
9211   [(set (reg:CC_NOOV CC_REGNUM)
9212         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
9213                           [(match_operator:SI 3 "shift_operator"
9214                             [(match_operand:SI 4 "s_register_operand" "r")
9215                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
9216                            (match_operand:SI 2 "s_register_operand" "r")])
9217                          (const_int 0)))
9218    (clobber (match_scratch:SI 0 "=r"))]
9219   "TARGET_ARM"
9220   "%i1%.\\t%0, %2, %4%S3"
9221   [(set_attr "conds" "set")
9222    (set_attr "shift" "4")
9223    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
9224                       (const_string "alu_shift")
9225                       (const_string "alu_shift_reg")))]
9226 )
9227
9228 (define_insn "*sub_shiftsi"
9229   [(set (match_operand:SI 0 "s_register_operand" "=r")
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   "TARGET_ARM"
9235   "sub%?\\t%0, %1, %3%S2"
9236   [(set_attr "predicable" "yes")
9237    (set_attr "shift" "3")
9238    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
9239                       (const_string "alu_shift")
9240                       (const_string "alu_shift_reg")))]
9241 )
9242
9243 (define_insn "*sub_shiftsi_compare0"
9244   [(set (reg:CC_NOOV CC_REGNUM)
9245         (compare:CC_NOOV
9246          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
9247                    (match_operator:SI 2 "shift_operator"
9248                     [(match_operand:SI 3 "s_register_operand" "r")
9249                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
9250          (const_int 0)))
9251    (set (match_operand:SI 0 "s_register_operand" "=r")
9252         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9253                                                  (match_dup 4)])))]
9254   "TARGET_ARM"
9255   "sub%.\\t%0, %1, %3%S2"
9256   [(set_attr "conds" "set")
9257    (set_attr "shift" "3")
9258    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
9259                       (const_string "alu_shift")
9260                       (const_string "alu_shift_reg")))]
9261 )
9262
9263 (define_insn "*sub_shiftsi_compare0_scratch"
9264   [(set (reg:CC_NOOV CC_REGNUM)
9265         (compare:CC_NOOV
9266          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
9267                    (match_operator:SI 2 "shift_operator"
9268                     [(match_operand:SI 3 "s_register_operand" "r")
9269                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
9270          (const_int 0)))
9271    (clobber (match_scratch:SI 0 "=r"))]
9272   "TARGET_ARM"
9273   "sub%.\\t%0, %1, %3%S2"
9274   [(set_attr "conds" "set")
9275    (set_attr "shift" "3")
9276    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
9277                       (const_string "alu_shift")
9278                       (const_string "alu_shift_reg")))]
9279 )
9280
9281 \f
9282
9283 (define_insn "*and_scc"
9284   [(set (match_operand:SI 0 "s_register_operand" "=r")
9285         (and:SI (match_operator:SI 1 "arm_comparison_operator"
9286                  [(match_operand 3 "cc_register" "") (const_int 0)])
9287                 (match_operand:SI 2 "s_register_operand" "r")))]
9288   "TARGET_ARM"
9289   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
9290   [(set_attr "conds" "use")
9291    (set_attr "length" "8")]
9292 )
9293
9294 (define_insn "*ior_scc"
9295   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9296         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
9297                  [(match_operand 3 "cc_register" "") (const_int 0)])
9298                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
9299   "TARGET_ARM"
9300   "@
9301    orr%d2\\t%0, %1, #1
9302    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
9303   [(set_attr "conds" "use")
9304    (set_attr "length" "4,8")]
9305 )
9306
9307 (define_insn "*compare_scc"
9308   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9309         (match_operator:SI 1 "arm_comparison_operator"
9310          [(match_operand:SI 2 "s_register_operand" "r,r")
9311           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
9312    (clobber (reg:CC CC_REGNUM))]
9313   "TARGET_ARM"
9314   "*
9315     if (operands[3] == const0_rtx)
9316       {
9317         if (GET_CODE (operands[1]) == LT)
9318           return \"mov\\t%0, %2, lsr #31\";
9319
9320         if (GET_CODE (operands[1]) == GE)
9321           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
9322
9323         if (GET_CODE (operands[1]) == EQ)
9324           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
9325       }
9326
9327     if (GET_CODE (operands[1]) == NE)
9328       {
9329         if (which_alternative == 1)
9330           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
9331         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
9332       }
9333     if (which_alternative == 1)
9334       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9335     else
9336       output_asm_insn (\"cmp\\t%2, %3\", operands);
9337     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
9338   "
9339   [(set_attr "conds" "clob")
9340    (set_attr "length" "12")]
9341 )
9342
9343 (define_insn "*cond_move"
9344   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9345         (if_then_else:SI (match_operator 3 "equality_operator"
9346                           [(match_operator 4 "arm_comparison_operator"
9347                             [(match_operand 5 "cc_register" "") (const_int 0)])
9348                            (const_int 0)])
9349                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9350                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
9351   "TARGET_ARM"
9352   "*
9353     if (GET_CODE (operands[3]) == NE)
9354       {
9355         if (which_alternative != 1)
9356           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
9357         if (which_alternative != 0)
9358           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
9359         return \"\";
9360       }
9361     if (which_alternative != 0)
9362       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9363     if (which_alternative != 1)
9364       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
9365     return \"\";
9366   "
9367   [(set_attr "conds" "use")
9368    (set_attr "length" "4,4,8")]
9369 )
9370
9371 (define_insn "*cond_arith"
9372   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9373         (match_operator:SI 5 "shiftable_operator" 
9374          [(match_operator:SI 4 "arm_comparison_operator"
9375            [(match_operand:SI 2 "s_register_operand" "r,r")
9376             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9377           (match_operand:SI 1 "s_register_operand" "0,?r")]))
9378    (clobber (reg:CC CC_REGNUM))]
9379   "TARGET_ARM"
9380   "*
9381     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
9382       return \"%i5\\t%0, %1, %2, lsr #31\";
9383
9384     output_asm_insn (\"cmp\\t%2, %3\", operands);
9385     if (GET_CODE (operands[5]) == AND)
9386       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
9387     else if (GET_CODE (operands[5]) == MINUS)
9388       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
9389     else if (which_alternative != 0)
9390       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9391     return \"%i5%d4\\t%0, %1, #1\";
9392   "
9393   [(set_attr "conds" "clob")
9394    (set_attr "length" "12")]
9395 )
9396
9397 (define_insn "*cond_sub"
9398   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9399         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
9400                   (match_operator:SI 4 "arm_comparison_operator"
9401                    [(match_operand:SI 2 "s_register_operand" "r,r")
9402                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
9403    (clobber (reg:CC CC_REGNUM))]
9404   "TARGET_ARM"
9405   "*
9406     output_asm_insn (\"cmp\\t%2, %3\", operands);
9407     if (which_alternative != 0)
9408       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9409     return \"sub%d4\\t%0, %1, #1\";
9410   "
9411   [(set_attr "conds" "clob")
9412    (set_attr "length" "8,12")]
9413 )
9414
9415 ;; ??? Is it worth using these conditional patterns in Thumb-2 mode?
9416 (define_insn "*cmp_ite0"
9417   [(set (match_operand 6 "dominant_cc_register" "")
9418         (compare
9419          (if_then_else:SI
9420           (match_operator 4 "arm_comparison_operator"
9421            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9422             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9423           (match_operator:SI 5 "arm_comparison_operator"
9424            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9425             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
9426           (const_int 0))
9427          (const_int 0)))]
9428   "TARGET_ARM"
9429   "*
9430   {
9431     static const char * const opcodes[4][2] =
9432     {
9433       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9434        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9435       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9436        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9437       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9438        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9439       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9440        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9441     };
9442     int swap =
9443       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9444
9445     return opcodes[which_alternative][swap];
9446   }"
9447   [(set_attr "conds" "set")
9448    (set_attr "length" "8")]
9449 )
9450
9451 (define_insn "*cmp_ite1"
9452   [(set (match_operand 6 "dominant_cc_register" "")
9453         (compare
9454          (if_then_else:SI
9455           (match_operator 4 "arm_comparison_operator"
9456            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9457             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9458           (match_operator:SI 5 "arm_comparison_operator"
9459            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9460             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
9461           (const_int 1))
9462          (const_int 0)))]
9463   "TARGET_ARM"
9464   "*
9465   {
9466     static const char * const opcodes[4][2] =
9467     {
9468       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
9469        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9470       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
9471        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9472       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
9473        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9474       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
9475        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9476     };
9477     int swap =
9478       comparison_dominates_p (GET_CODE (operands[5]),
9479                               reverse_condition (GET_CODE (operands[4])));
9480
9481     return opcodes[which_alternative][swap];
9482   }"
9483   [(set_attr "conds" "set")
9484    (set_attr "length" "8")]
9485 )
9486
9487 (define_insn "*cmp_and"
9488   [(set (match_operand 6 "dominant_cc_register" "")
9489         (compare
9490          (and:SI
9491           (match_operator 4 "arm_comparison_operator"
9492            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9493             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9494           (match_operator:SI 5 "arm_comparison_operator"
9495            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9496             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9497          (const_int 0)))]
9498   "TARGET_ARM"
9499   "*
9500   {
9501     static const char *const opcodes[4][2] =
9502     {
9503       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9504        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9505       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9506        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9507       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9508        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9509       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9510        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9511     };
9512     int swap =
9513       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9514
9515     return opcodes[which_alternative][swap];
9516   }"
9517   [(set_attr "conds" "set")
9518    (set_attr "predicable" "no")
9519    (set_attr "length" "8")]
9520 )
9521
9522 (define_insn "*cmp_ior"
9523   [(set (match_operand 6 "dominant_cc_register" "")
9524         (compare
9525          (ior:SI
9526           (match_operator 4 "arm_comparison_operator"
9527            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9528             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9529           (match_operator:SI 5 "arm_comparison_operator"
9530            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9531             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9532          (const_int 0)))]
9533   "TARGET_ARM"
9534   "*
9535 {
9536   static const char *const opcodes[4][2] =
9537   {
9538     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
9539      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9540     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
9541      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9542     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
9543      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9544     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
9545      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9546   };
9547   int swap =
9548     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9549
9550   return opcodes[which_alternative][swap];
9551 }
9552 "
9553   [(set_attr "conds" "set")
9554    (set_attr "length" "8")]
9555 )
9556
9557 (define_insn_and_split "*ior_scc_scc"
9558   [(set (match_operand:SI 0 "s_register_operand" "=r")
9559         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9560                  [(match_operand:SI 1 "s_register_operand" "r")
9561                   (match_operand:SI 2 "arm_add_operand" "rIL")])
9562                 (match_operator:SI 6 "arm_comparison_operator"
9563                  [(match_operand:SI 4 "s_register_operand" "r")
9564                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
9565    (clobber (reg:CC CC_REGNUM))]
9566   "TARGET_ARM
9567    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9568        != CCmode)"
9569   "#"
9570   "TARGET_ARM && reload_completed"
9571   [(set (match_dup 7)
9572         (compare
9573          (ior:SI
9574           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9575           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9576          (const_int 0)))
9577    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9578   "operands[7]
9579      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9580                                                   DOM_CC_X_OR_Y),
9581                     CC_REGNUM);"
9582   [(set_attr "conds" "clob")
9583    (set_attr "length" "16")])
9584
9585 ; If the above pattern is followed by a CMP insn, then the compare is 
9586 ; redundant, since we can rework the conditional instruction that follows.
9587 (define_insn_and_split "*ior_scc_scc_cmp"
9588   [(set (match_operand 0 "dominant_cc_register" "")
9589         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9590                           [(match_operand:SI 1 "s_register_operand" "r")
9591                            (match_operand:SI 2 "arm_add_operand" "rIL")])
9592                          (match_operator:SI 6 "arm_comparison_operator"
9593                           [(match_operand:SI 4 "s_register_operand" "r")
9594                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
9595                  (const_int 0)))
9596    (set (match_operand:SI 7 "s_register_operand" "=r")
9597         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9598                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9599   "TARGET_ARM"
9600   "#"
9601   "TARGET_ARM && reload_completed"
9602   [(set (match_dup 0)
9603         (compare
9604          (ior:SI
9605           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9606           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9607          (const_int 0)))
9608    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9609   ""
9610   [(set_attr "conds" "set")
9611    (set_attr "length" "16")])
9612
9613 (define_insn_and_split "*and_scc_scc"
9614   [(set (match_operand:SI 0 "s_register_operand" "=r")
9615         (and:SI (match_operator:SI 3 "arm_comparison_operator"
9616                  [(match_operand:SI 1 "s_register_operand" "r")
9617                   (match_operand:SI 2 "arm_add_operand" "rIL")])
9618                 (match_operator:SI 6 "arm_comparison_operator"
9619                  [(match_operand:SI 4 "s_register_operand" "r")
9620                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
9621    (clobber (reg:CC CC_REGNUM))]
9622   "TARGET_ARM
9623    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9624        != CCmode)"
9625   "#"
9626   "TARGET_ARM && reload_completed
9627    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9628        != CCmode)"
9629   [(set (match_dup 7)
9630         (compare
9631          (and:SI
9632           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9633           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9634          (const_int 0)))
9635    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9636   "operands[7]
9637      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9638                                                   DOM_CC_X_AND_Y),
9639                     CC_REGNUM);"
9640   [(set_attr "conds" "clob")
9641    (set_attr "length" "16")])
9642
9643 ; If the above pattern is followed by a CMP insn, then the compare is 
9644 ; redundant, since we can rework the conditional instruction that follows.
9645 (define_insn_and_split "*and_scc_scc_cmp"
9646   [(set (match_operand 0 "dominant_cc_register" "")
9647         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9648                           [(match_operand:SI 1 "s_register_operand" "r")
9649                            (match_operand:SI 2 "arm_add_operand" "rIL")])
9650                          (match_operator:SI 6 "arm_comparison_operator"
9651                           [(match_operand:SI 4 "s_register_operand" "r")
9652                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
9653                  (const_int 0)))
9654    (set (match_operand:SI 7 "s_register_operand" "=r")
9655         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9656                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9657   "TARGET_ARM"
9658   "#"
9659   "TARGET_ARM && reload_completed"
9660   [(set (match_dup 0)
9661         (compare
9662          (and:SI
9663           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9664           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9665          (const_int 0)))
9666    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9667   ""
9668   [(set_attr "conds" "set")
9669    (set_attr "length" "16")])
9670
9671 ;; If there is no dominance in the comparison, then we can still save an
9672 ;; instruction in the AND case, since we can know that the second compare
9673 ;; need only zero the value if false (if true, then the value is already
9674 ;; correct).
9675 (define_insn_and_split "*and_scc_scc_nodom"
9676   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
9677         (and:SI (match_operator:SI 3 "arm_comparison_operator"
9678                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
9679                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9680                 (match_operator:SI 6 "arm_comparison_operator"
9681                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
9682                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9683    (clobber (reg:CC CC_REGNUM))]
9684   "TARGET_ARM
9685    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9686        == CCmode)"
9687   "#"
9688   "TARGET_ARM && reload_completed"
9689   [(parallel [(set (match_dup 0)
9690                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9691               (clobber (reg:CC CC_REGNUM))])
9692    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9693    (set (match_dup 0)
9694         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9695                          (match_dup 0)
9696                          (const_int 0)))]
9697   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9698                                               operands[4], operands[5]),
9699                               CC_REGNUM);
9700    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9701                                   operands[5]);"
9702   [(set_attr "conds" "clob")
9703    (set_attr "length" "20")])
9704
9705 (define_split
9706   [(set (reg:CC_NOOV CC_REGNUM)
9707         (compare:CC_NOOV (ior:SI
9708                           (and:SI (match_operand:SI 0 "s_register_operand" "")
9709                                   (const_int 1))
9710                           (match_operator:SI 1 "arm_comparison_operator"
9711                            [(match_operand:SI 2 "s_register_operand" "")
9712                             (match_operand:SI 3 "arm_add_operand" "")]))
9713                          (const_int 0)))
9714    (clobber (match_operand:SI 4 "s_register_operand" ""))]
9715   "TARGET_ARM"
9716   [(set (match_dup 4)
9717         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9718                 (match_dup 0)))
9719    (set (reg:CC_NOOV CC_REGNUM)
9720         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9721                          (const_int 0)))]
9722   "")
9723
9724 (define_split
9725   [(set (reg:CC_NOOV CC_REGNUM)
9726         (compare:CC_NOOV (ior:SI
9727                           (match_operator:SI 1 "arm_comparison_operator"
9728                            [(match_operand:SI 2 "s_register_operand" "")
9729                             (match_operand:SI 3 "arm_add_operand" "")])
9730                           (and:SI (match_operand:SI 0 "s_register_operand" "")
9731                                   (const_int 1)))
9732                          (const_int 0)))
9733    (clobber (match_operand:SI 4 "s_register_operand" ""))]
9734   "TARGET_ARM"
9735   [(set (match_dup 4)
9736         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9737                 (match_dup 0)))
9738    (set (reg:CC_NOOV CC_REGNUM)
9739         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9740                          (const_int 0)))]
9741   "")
9742 ;; ??? The conditional patterns above need checking for Thumb-2 usefulness
9743
9744 (define_insn "*negscc"
9745   [(set (match_operand:SI 0 "s_register_operand" "=r")
9746         (neg:SI (match_operator 3 "arm_comparison_operator"
9747                  [(match_operand:SI 1 "s_register_operand" "r")
9748                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
9749    (clobber (reg:CC CC_REGNUM))]
9750   "TARGET_ARM"
9751   "*
9752   if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
9753     return \"mov\\t%0, %1, asr #31\";
9754
9755   if (GET_CODE (operands[3]) == NE)
9756     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9757
9758   output_asm_insn (\"cmp\\t%1, %2\", operands);
9759   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9760   return \"mvn%d3\\t%0, #0\";
9761   "
9762   [(set_attr "conds" "clob")
9763    (set_attr "length" "12")]
9764 )
9765
9766 (define_insn "movcond"
9767   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9768         (if_then_else:SI
9769          (match_operator 5 "arm_comparison_operator"
9770           [(match_operand:SI 3 "s_register_operand" "r,r,r")
9771            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9772          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9773          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
9774    (clobber (reg:CC CC_REGNUM))]
9775   "TARGET_ARM"
9776   "*
9777   if (GET_CODE (operands[5]) == LT
9778       && (operands[4] == const0_rtx))
9779     {
9780       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9781         {
9782           if (operands[2] == const0_rtx)
9783             return \"and\\t%0, %1, %3, asr #31\";
9784           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9785         }
9786       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9787         {
9788           if (operands[1] == const0_rtx)
9789             return \"bic\\t%0, %2, %3, asr #31\";
9790           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9791         }
9792       /* The only case that falls through to here is when both ops 1 & 2
9793          are constants.  */
9794     }
9795
9796   if (GET_CODE (operands[5]) == GE
9797       && (operands[4] == const0_rtx))
9798     {
9799       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9800         {
9801           if (operands[2] == const0_rtx)
9802             return \"bic\\t%0, %1, %3, asr #31\";
9803           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9804         }
9805       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9806         {
9807           if (operands[1] == const0_rtx)
9808             return \"and\\t%0, %2, %3, asr #31\";
9809           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9810         }
9811       /* The only case that falls through to here is when both ops 1 & 2
9812          are constants.  */
9813     }
9814   if (GET_CODE (operands[4]) == CONST_INT
9815       && !const_ok_for_arm (INTVAL (operands[4])))
9816     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9817   else
9818     output_asm_insn (\"cmp\\t%3, %4\", operands);
9819   if (which_alternative != 0)
9820     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9821   if (which_alternative != 1)
9822     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9823   return \"\";
9824   "
9825   [(set_attr "conds" "clob")
9826    (set_attr "length" "8,8,12")]
9827 )
9828
9829 ;; ??? The patterns below need checking for Thumb-2 usefulness.
9830
9831 (define_insn "*ifcompare_plus_move"
9832   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9833         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9834                           [(match_operand:SI 4 "s_register_operand" "r,r")
9835                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9836                          (plus:SI
9837                           (match_operand:SI 2 "s_register_operand" "r,r")
9838                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
9839                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9840    (clobber (reg:CC CC_REGNUM))]
9841   "TARGET_ARM"
9842   "#"
9843   [(set_attr "conds" "clob")
9844    (set_attr "length" "8,12")]
9845 )
9846
9847 (define_insn "*if_plus_move"
9848   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9849         (if_then_else:SI
9850          (match_operator 4 "arm_comparison_operator"
9851           [(match_operand 5 "cc_register" "") (const_int 0)])
9852          (plus:SI
9853           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9854           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9855          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
9856   "TARGET_ARM"
9857   "@
9858    add%d4\\t%0, %2, %3
9859    sub%d4\\t%0, %2, #%n3
9860    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
9861    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
9862   [(set_attr "conds" "use")
9863    (set_attr "length" "4,4,8,8")
9864    (set_attr "type" "*,*,*,*")]
9865 )
9866
9867 (define_insn "*ifcompare_move_plus"
9868   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9869         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9870                           [(match_operand:SI 4 "s_register_operand" "r,r")
9871                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9872                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9873                          (plus:SI
9874                           (match_operand:SI 2 "s_register_operand" "r,r")
9875                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
9876    (clobber (reg:CC CC_REGNUM))]
9877   "TARGET_ARM"
9878   "#"
9879   [(set_attr "conds" "clob")
9880    (set_attr "length" "8,12")]
9881 )
9882
9883 (define_insn "*if_move_plus"
9884   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9885         (if_then_else:SI
9886          (match_operator 4 "arm_comparison_operator"
9887           [(match_operand 5 "cc_register" "") (const_int 0)])
9888          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
9889          (plus:SI
9890           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9891           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
9892   "TARGET_ARM"
9893   "@
9894    add%D4\\t%0, %2, %3
9895    sub%D4\\t%0, %2, #%n3
9896    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
9897    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
9898   [(set_attr "conds" "use")
9899    (set_attr "length" "4,4,8,8")
9900    (set_attr "type" "*,*,*,*")]
9901 )
9902
9903 (define_insn "*ifcompare_arith_arith"
9904   [(set (match_operand:SI 0 "s_register_operand" "=r")
9905         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
9906                           [(match_operand:SI 5 "s_register_operand" "r")
9907                            (match_operand:SI 6 "arm_add_operand" "rIL")])
9908                          (match_operator:SI 8 "shiftable_operator"
9909                           [(match_operand:SI 1 "s_register_operand" "r")
9910                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
9911                          (match_operator:SI 7 "shiftable_operator"
9912                           [(match_operand:SI 3 "s_register_operand" "r")
9913                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
9914    (clobber (reg:CC CC_REGNUM))]
9915   "TARGET_ARM"
9916   "#"
9917   [(set_attr "conds" "clob")
9918    (set_attr "length" "12")]
9919 )
9920
9921 (define_insn "*if_arith_arith"
9922   [(set (match_operand:SI 0 "s_register_operand" "=r")
9923         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
9924                           [(match_operand 8 "cc_register" "") (const_int 0)])
9925                          (match_operator:SI 6 "shiftable_operator"
9926                           [(match_operand:SI 1 "s_register_operand" "r")
9927                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
9928                          (match_operator:SI 7 "shiftable_operator"
9929                           [(match_operand:SI 3 "s_register_operand" "r")
9930                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
9931   "TARGET_ARM"
9932   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
9933   [(set_attr "conds" "use")
9934    (set_attr "length" "8")]
9935 )
9936
9937 (define_insn "*ifcompare_arith_move"
9938   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9939         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9940                           [(match_operand:SI 2 "s_register_operand" "r,r")
9941                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9942                          (match_operator:SI 7 "shiftable_operator"
9943                           [(match_operand:SI 4 "s_register_operand" "r,r")
9944                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
9945                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9946    (clobber (reg:CC CC_REGNUM))]
9947   "TARGET_ARM"
9948   "*
9949   /* If we have an operation where (op x 0) is the identity operation and
9950      the conditional operator is LT or GE and we are comparing against zero and
9951      everything is in registers then we can do this in two instructions.  */
9952   if (operands[3] == const0_rtx
9953       && GET_CODE (operands[7]) != AND
9954       && GET_CODE (operands[5]) == REG
9955       && GET_CODE (operands[1]) == REG 
9956       && REGNO (operands[1]) == REGNO (operands[4])
9957       && REGNO (operands[4]) != REGNO (operands[0]))
9958     {
9959       if (GET_CODE (operands[6]) == LT)
9960         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9961       else if (GET_CODE (operands[6]) == GE)
9962         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9963     }
9964   if (GET_CODE (operands[3]) == CONST_INT
9965       && !const_ok_for_arm (INTVAL (operands[3])))
9966     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9967   else
9968     output_asm_insn (\"cmp\\t%2, %3\", operands);
9969   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9970   if (which_alternative != 0)
9971     return \"mov%D6\\t%0, %1\";
9972   return \"\";
9973   "
9974   [(set_attr "conds" "clob")
9975    (set_attr "length" "8,12")]
9976 )
9977
9978 (define_insn "*if_arith_move"
9979   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9980         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9981                           [(match_operand 6 "cc_register" "") (const_int 0)])
9982                          (match_operator:SI 5 "shiftable_operator"
9983                           [(match_operand:SI 2 "s_register_operand" "r,r")
9984                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9985                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
9986   "TARGET_ARM"
9987   "@
9988    %I5%d4\\t%0, %2, %3
9989    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
9990   [(set_attr "conds" "use")
9991    (set_attr "length" "4,8")
9992    (set_attr "type" "*,*")]
9993 )
9994
9995 (define_insn "*ifcompare_move_arith"
9996   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9997         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9998                           [(match_operand:SI 4 "s_register_operand" "r,r")
9999                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10000                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10001                          (match_operator:SI 7 "shiftable_operator"
10002                           [(match_operand:SI 2 "s_register_operand" "r,r")
10003                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
10004    (clobber (reg:CC CC_REGNUM))]
10005   "TARGET_ARM"
10006   "*
10007   /* If we have an operation where (op x 0) is the identity operation and
10008      the conditional operator is LT or GE and we are comparing against zero and
10009      everything is in registers then we can do this in two instructions */
10010   if (operands[5] == const0_rtx
10011       && GET_CODE (operands[7]) != AND
10012       && GET_CODE (operands[3]) == REG
10013       && GET_CODE (operands[1]) == REG 
10014       && REGNO (operands[1]) == REGNO (operands[2])
10015       && REGNO (operands[2]) != REGNO (operands[0]))
10016     {
10017       if (GET_CODE (operands[6]) == GE)
10018         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
10019       else if (GET_CODE (operands[6]) == LT)
10020         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
10021     }
10022
10023   if (GET_CODE (operands[5]) == CONST_INT
10024       && !const_ok_for_arm (INTVAL (operands[5])))
10025     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
10026   else
10027     output_asm_insn (\"cmp\\t%4, %5\", operands);
10028
10029   if (which_alternative != 0)
10030     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
10031   return \"%I7%D6\\t%0, %2, %3\";
10032   "
10033   [(set_attr "conds" "clob")
10034    (set_attr "length" "8,12")]
10035 )
10036
10037 (define_insn "*if_move_arith"
10038   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10039         (if_then_else:SI
10040          (match_operator 4 "arm_comparison_operator"
10041           [(match_operand 6 "cc_register" "") (const_int 0)])
10042          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10043          (match_operator:SI 5 "shiftable_operator"
10044           [(match_operand:SI 2 "s_register_operand" "r,r")
10045            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
10046   "TARGET_ARM"
10047   "@
10048    %I5%D4\\t%0, %2, %3
10049    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
10050   [(set_attr "conds" "use")
10051    (set_attr "length" "4,8")
10052    (set_attr "type" "*,*")]
10053 )
10054
10055 (define_insn "*ifcompare_move_not"
10056   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10057         (if_then_else:SI
10058          (match_operator 5 "arm_comparison_operator"
10059           [(match_operand:SI 3 "s_register_operand" "r,r")
10060            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10061          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10062          (not:SI
10063           (match_operand:SI 2 "s_register_operand" "r,r"))))
10064    (clobber (reg:CC CC_REGNUM))]
10065   "TARGET_ARM"
10066   "#"
10067   [(set_attr "conds" "clob")
10068    (set_attr "length" "8,12")]
10069 )
10070
10071 (define_insn "*if_move_not"
10072   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10073         (if_then_else:SI
10074          (match_operator 4 "arm_comparison_operator"
10075           [(match_operand 3 "cc_register" "") (const_int 0)])
10076          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10077          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
10078   "TARGET_ARM"
10079   "@
10080    mvn%D4\\t%0, %2
10081    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
10082    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
10083   [(set_attr "conds" "use")
10084    (set_attr "length" "4,8,8")]
10085 )
10086
10087 (define_insn "*ifcompare_not_move"
10088   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10089         (if_then_else:SI 
10090          (match_operator 5 "arm_comparison_operator"
10091           [(match_operand:SI 3 "s_register_operand" "r,r")
10092            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10093          (not:SI
10094           (match_operand:SI 2 "s_register_operand" "r,r"))
10095          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
10096    (clobber (reg:CC CC_REGNUM))]
10097   "TARGET_ARM"
10098   "#"
10099   [(set_attr "conds" "clob")
10100    (set_attr "length" "8,12")]
10101 )
10102
10103 (define_insn "*if_not_move"
10104   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10105         (if_then_else:SI
10106          (match_operator 4 "arm_comparison_operator"
10107           [(match_operand 3 "cc_register" "") (const_int 0)])
10108          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10109          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
10110   "TARGET_ARM"
10111   "@
10112    mvn%d4\\t%0, %2
10113    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
10114    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
10115   [(set_attr "conds" "use")
10116    (set_attr "length" "4,8,8")]
10117 )
10118
10119 (define_insn "*ifcompare_shift_move"
10120   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10121         (if_then_else:SI
10122          (match_operator 6 "arm_comparison_operator"
10123           [(match_operand:SI 4 "s_register_operand" "r,r")
10124            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10125          (match_operator:SI 7 "shift_operator"
10126           [(match_operand:SI 2 "s_register_operand" "r,r")
10127            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
10128          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
10129    (clobber (reg:CC CC_REGNUM))]
10130   "TARGET_ARM"
10131   "#"
10132   [(set_attr "conds" "clob")
10133    (set_attr "length" "8,12")]
10134 )
10135
10136 (define_insn "*if_shift_move"
10137   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10138         (if_then_else:SI
10139          (match_operator 5 "arm_comparison_operator"
10140           [(match_operand 6 "cc_register" "") (const_int 0)])
10141          (match_operator:SI 4 "shift_operator"
10142           [(match_operand:SI 2 "s_register_operand" "r,r,r")
10143            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
10144          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
10145   "TARGET_ARM"
10146   "@
10147    mov%d5\\t%0, %2%S4
10148    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
10149    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
10150   [(set_attr "conds" "use")
10151    (set_attr "shift" "2")
10152    (set_attr "length" "4,8,8")
10153    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
10154                       (const_string "alu_shift")
10155                       (const_string "alu_shift_reg")))]
10156 )
10157
10158 (define_insn "*ifcompare_move_shift"
10159   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10160         (if_then_else:SI
10161          (match_operator 6 "arm_comparison_operator"
10162           [(match_operand:SI 4 "s_register_operand" "r,r")
10163            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10164          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10165          (match_operator:SI 7 "shift_operator"
10166           [(match_operand:SI 2 "s_register_operand" "r,r")
10167            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
10168    (clobber (reg:CC CC_REGNUM))]
10169   "TARGET_ARM"
10170   "#"
10171   [(set_attr "conds" "clob")
10172    (set_attr "length" "8,12")]
10173 )
10174
10175 (define_insn "*if_move_shift"
10176   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10177         (if_then_else:SI
10178          (match_operator 5 "arm_comparison_operator"
10179           [(match_operand 6 "cc_register" "") (const_int 0)])
10180          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10181          (match_operator:SI 4 "shift_operator"
10182           [(match_operand:SI 2 "s_register_operand" "r,r,r")
10183            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
10184   "TARGET_ARM"
10185   "@
10186    mov%D5\\t%0, %2%S4
10187    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
10188    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
10189   [(set_attr "conds" "use")
10190    (set_attr "shift" "2")
10191    (set_attr "length" "4,8,8")
10192    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
10193                       (const_string "alu_shift")
10194                       (const_string "alu_shift_reg")))]
10195 )
10196
10197 (define_insn "*ifcompare_shift_shift"
10198   [(set (match_operand:SI 0 "s_register_operand" "=r")
10199         (if_then_else:SI
10200          (match_operator 7 "arm_comparison_operator"
10201           [(match_operand:SI 5 "s_register_operand" "r")
10202            (match_operand:SI 6 "arm_add_operand" "rIL")])
10203          (match_operator:SI 8 "shift_operator"
10204           [(match_operand:SI 1 "s_register_operand" "r")
10205            (match_operand:SI 2 "arm_rhs_operand" "rM")])
10206          (match_operator:SI 9 "shift_operator"
10207           [(match_operand:SI 3 "s_register_operand" "r")
10208            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
10209    (clobber (reg:CC CC_REGNUM))]
10210   "TARGET_ARM"
10211   "#"
10212   [(set_attr "conds" "clob")
10213    (set_attr "length" "12")]
10214 )
10215
10216 (define_insn "*if_shift_shift"
10217   [(set (match_operand:SI 0 "s_register_operand" "=r")
10218         (if_then_else:SI
10219          (match_operator 5 "arm_comparison_operator"
10220           [(match_operand 8 "cc_register" "") (const_int 0)])
10221          (match_operator:SI 6 "shift_operator"
10222           [(match_operand:SI 1 "s_register_operand" "r")
10223            (match_operand:SI 2 "arm_rhs_operand" "rM")])
10224          (match_operator:SI 7 "shift_operator"
10225           [(match_operand:SI 3 "s_register_operand" "r")
10226            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
10227   "TARGET_ARM"
10228   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
10229   [(set_attr "conds" "use")
10230    (set_attr "shift" "1")
10231    (set_attr "length" "8")
10232    (set (attr "type") (if_then_else
10233                         (and (match_operand 2 "const_int_operand" "")
10234                              (match_operand 4 "const_int_operand" ""))
10235                       (const_string "alu_shift")
10236                       (const_string "alu_shift_reg")))]
10237 )
10238
10239 (define_insn "*ifcompare_not_arith"
10240   [(set (match_operand:SI 0 "s_register_operand" "=r")
10241         (if_then_else:SI
10242          (match_operator 6 "arm_comparison_operator"
10243           [(match_operand:SI 4 "s_register_operand" "r")
10244            (match_operand:SI 5 "arm_add_operand" "rIL")])
10245          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10246          (match_operator:SI 7 "shiftable_operator"
10247           [(match_operand:SI 2 "s_register_operand" "r")
10248            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
10249    (clobber (reg:CC CC_REGNUM))]
10250   "TARGET_ARM"
10251   "#"
10252   [(set_attr "conds" "clob")
10253    (set_attr "length" "12")]
10254 )
10255
10256 (define_insn "*if_not_arith"
10257   [(set (match_operand:SI 0 "s_register_operand" "=r")
10258         (if_then_else:SI
10259          (match_operator 5 "arm_comparison_operator"
10260           [(match_operand 4 "cc_register" "") (const_int 0)])
10261          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10262          (match_operator:SI 6 "shiftable_operator"
10263           [(match_operand:SI 2 "s_register_operand" "r")
10264            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
10265   "TARGET_ARM"
10266   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
10267   [(set_attr "conds" "use")
10268    (set_attr "length" "8")]
10269 )
10270
10271 (define_insn "*ifcompare_arith_not"
10272   [(set (match_operand:SI 0 "s_register_operand" "=r")
10273         (if_then_else:SI
10274          (match_operator 6 "arm_comparison_operator"
10275           [(match_operand:SI 4 "s_register_operand" "r")
10276            (match_operand:SI 5 "arm_add_operand" "rIL")])
10277          (match_operator:SI 7 "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    (clobber (reg:CC CC_REGNUM))]
10282   "TARGET_ARM"
10283   "#"
10284   [(set_attr "conds" "clob")
10285    (set_attr "length" "12")]
10286 )
10287
10288 (define_insn "*if_arith_not"
10289   [(set (match_operand:SI 0 "s_register_operand" "=r")
10290         (if_then_else:SI
10291          (match_operator 5 "arm_comparison_operator"
10292           [(match_operand 4 "cc_register" "") (const_int 0)])
10293          (match_operator:SI 6 "shiftable_operator"
10294           [(match_operand:SI 2 "s_register_operand" "r")
10295            (match_operand:SI 3 "arm_rhs_operand" "rI")])
10296          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
10297   "TARGET_ARM"
10298   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
10299   [(set_attr "conds" "use")
10300    (set_attr "length" "8")]
10301 )
10302
10303 (define_insn "*ifcompare_neg_move"
10304   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10305         (if_then_else:SI
10306          (match_operator 5 "arm_comparison_operator"
10307           [(match_operand:SI 3 "s_register_operand" "r,r")
10308            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10309          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10310          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
10311    (clobber (reg:CC CC_REGNUM))]
10312   "TARGET_ARM"
10313   "#"
10314   [(set_attr "conds" "clob")
10315    (set_attr "length" "8,12")]
10316 )
10317
10318 (define_insn "*if_neg_move"
10319   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10320         (if_then_else:SI
10321          (match_operator 4 "arm_comparison_operator"
10322           [(match_operand 3 "cc_register" "") (const_int 0)])
10323          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10324          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
10325   "TARGET_ARM"
10326   "@
10327    rsb%d4\\t%0, %2, #0
10328    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
10329    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
10330   [(set_attr "conds" "use")
10331    (set_attr "length" "4,8,8")]
10332 )
10333
10334 (define_insn "*ifcompare_move_neg"
10335   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10336         (if_then_else:SI
10337          (match_operator 5 "arm_comparison_operator"
10338           [(match_operand:SI 3 "s_register_operand" "r,r")
10339            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10340          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10341          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
10342    (clobber (reg:CC CC_REGNUM))]
10343   "TARGET_ARM"
10344   "#"
10345   [(set_attr "conds" "clob")
10346    (set_attr "length" "8,12")]
10347 )
10348
10349 (define_insn "*if_move_neg"
10350   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10351         (if_then_else:SI
10352          (match_operator 4 "arm_comparison_operator"
10353           [(match_operand 3 "cc_register" "") (const_int 0)])
10354          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10355          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
10356   "TARGET_ARM"
10357   "@
10358    rsb%D4\\t%0, %2, #0
10359    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
10360    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
10361   [(set_attr "conds" "use")
10362    (set_attr "length" "4,8,8")]
10363 )
10364
10365 (define_insn "*arith_adjacentmem"
10366   [(set (match_operand:SI 0 "s_register_operand" "=r")
10367         (match_operator:SI 1 "shiftable_operator"
10368          [(match_operand:SI 2 "memory_operand" "m")
10369           (match_operand:SI 3 "memory_operand" "m")]))
10370    (clobber (match_scratch:SI 4 "=r"))]
10371   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
10372   "*
10373   {
10374     rtx ldm[3];
10375     rtx arith[4];
10376     rtx base_reg;
10377     HOST_WIDE_INT val1 = 0, val2 = 0;
10378
10379     if (REGNO (operands[0]) > REGNO (operands[4]))
10380       {
10381         ldm[1] = operands[4];
10382         ldm[2] = operands[0];
10383       }
10384     else
10385       {
10386         ldm[1] = operands[0];
10387         ldm[2] = operands[4];
10388       }
10389
10390     base_reg = XEXP (operands[2], 0);
10391
10392     if (!REG_P (base_reg))
10393       {
10394         val1 = INTVAL (XEXP (base_reg, 1));
10395         base_reg = XEXP (base_reg, 0);
10396       }
10397
10398     if (!REG_P (XEXP (operands[3], 0)))
10399       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
10400
10401     arith[0] = operands[0];
10402     arith[3] = operands[1];
10403
10404     if (val1 < val2)
10405       {
10406         arith[1] = ldm[1];
10407         arith[2] = ldm[2];
10408       }
10409     else
10410       {
10411         arith[1] = ldm[2];
10412         arith[2] = ldm[1];
10413       }
10414
10415     ldm[0] = base_reg;
10416     if (val1 !=0 && val2 != 0)
10417       {
10418         rtx ops[3];
10419
10420         if (val1 == 4 || val2 == 4)
10421           /* Other val must be 8, since we know they are adjacent and neither
10422              is zero.  */
10423           output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
10424         else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
10425           {
10426             ldm[0] = ops[0] = operands[4];
10427             ops[1] = base_reg;
10428             ops[2] = GEN_INT (val1);
10429             output_add_immediate (ops);
10430             if (val1 < val2)
10431               output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
10432             else
10433               output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
10434           }
10435         else
10436           {
10437             /* Offset is out of range for a single add, so use two ldr.  */
10438             ops[0] = ldm[1];
10439             ops[1] = base_reg;
10440             ops[2] = GEN_INT (val1);
10441             output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10442             ops[0] = ldm[2];
10443             ops[2] = GEN_INT (val2);
10444             output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10445           }
10446       }
10447     else if (val1 != 0)
10448       {
10449         if (val1 < val2)
10450           output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
10451         else
10452           output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
10453       }
10454     else
10455       {
10456         if (val1 < val2)
10457           output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
10458         else
10459           output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
10460       }
10461     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10462     return \"\";
10463   }"
10464   [(set_attr "length" "12")
10465    (set_attr "predicable" "yes")
10466    (set_attr "type" "load1")]
10467 )
10468
10469 ; This pattern is never tried by combine, so do it as a peephole
10470
10471 (define_peephole2
10472   [(set (match_operand:SI 0 "arm_general_register_operand" "")
10473         (match_operand:SI 1 "arm_general_register_operand" ""))
10474    (set (reg:CC CC_REGNUM)
10475         (compare:CC (match_dup 1) (const_int 0)))]
10476   "TARGET_ARM"
10477   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10478               (set (match_dup 0) (match_dup 1))])]
10479   ""
10480 )
10481
10482 ; Peepholes to spot possible load- and store-multiples, if the ordering is
10483 ; reversed, check that the memory references aren't volatile.
10484
10485 (define_peephole
10486   [(set (match_operand:SI 0 "s_register_operand" "=rk")
10487         (match_operand:SI 4 "memory_operand" "m"))
10488    (set (match_operand:SI 1 "s_register_operand" "=rk")
10489         (match_operand:SI 5 "memory_operand" "m"))
10490    (set (match_operand:SI 2 "s_register_operand" "=rk")
10491         (match_operand:SI 6 "memory_operand" "m"))
10492    (set (match_operand:SI 3 "s_register_operand" "=rk")
10493         (match_operand:SI 7 "memory_operand" "m"))]
10494   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
10495   "*
10496   return emit_ldm_seq (operands, 4);
10497   "
10498 )
10499
10500 (define_peephole
10501   [(set (match_operand:SI 0 "s_register_operand" "=rk")
10502         (match_operand:SI 3 "memory_operand" "m"))
10503    (set (match_operand:SI 1 "s_register_operand" "=rk")
10504         (match_operand:SI 4 "memory_operand" "m"))
10505    (set (match_operand:SI 2 "s_register_operand" "=rk")
10506         (match_operand:SI 5 "memory_operand" "m"))]
10507   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
10508   "*
10509   return emit_ldm_seq (operands, 3);
10510   "
10511 )
10512
10513 (define_peephole
10514   [(set (match_operand:SI 0 "s_register_operand" "=rk")
10515         (match_operand:SI 2 "memory_operand" "m"))
10516    (set (match_operand:SI 1 "s_register_operand" "=rk")
10517         (match_operand:SI 3 "memory_operand" "m"))]
10518   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
10519   "*
10520   return emit_ldm_seq (operands, 2);
10521   "
10522 )
10523
10524 (define_peephole
10525   [(set (match_operand:SI 4 "memory_operand" "=m")
10526         (match_operand:SI 0 "s_register_operand" "rk"))
10527    (set (match_operand:SI 5 "memory_operand" "=m")
10528         (match_operand:SI 1 "s_register_operand" "rk"))
10529    (set (match_operand:SI 6 "memory_operand" "=m")
10530         (match_operand:SI 2 "s_register_operand" "rk"))
10531    (set (match_operand:SI 7 "memory_operand" "=m")
10532         (match_operand:SI 3 "s_register_operand" "rk"))]
10533   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
10534   "*
10535   return emit_stm_seq (operands, 4);
10536   "
10537 )
10538
10539 (define_peephole
10540   [(set (match_operand:SI 3 "memory_operand" "=m")
10541         (match_operand:SI 0 "s_register_operand" "rk"))
10542    (set (match_operand:SI 4 "memory_operand" "=m")
10543         (match_operand:SI 1 "s_register_operand" "rk"))
10544    (set (match_operand:SI 5 "memory_operand" "=m")
10545         (match_operand:SI 2 "s_register_operand" "rk"))]
10546   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
10547   "*
10548   return emit_stm_seq (operands, 3);
10549   "
10550 )
10551
10552 (define_peephole
10553   [(set (match_operand:SI 2 "memory_operand" "=m")
10554         (match_operand:SI 0 "s_register_operand" "rk"))
10555    (set (match_operand:SI 3 "memory_operand" "=m")
10556         (match_operand:SI 1 "s_register_operand" "rk"))]
10557   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
10558   "*
10559   return emit_stm_seq (operands, 2);
10560   "
10561 )
10562
10563 (define_split
10564   [(set (match_operand:SI 0 "s_register_operand" "")
10565         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10566                        (const_int 0))
10567                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
10568                          [(match_operand:SI 3 "s_register_operand" "")
10569                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
10570    (clobber (match_operand:SI 5 "s_register_operand" ""))]
10571   "TARGET_ARM"
10572   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10573    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10574                               (match_dup 5)))]
10575   ""
10576 )
10577
10578 ;; This split can be used because CC_Z mode implies that the following
10579 ;; branch will be an equality, or an unsigned inequality, so the sign
10580 ;; extension is not needed.
10581
10582 (define_split
10583   [(set (reg:CC_Z CC_REGNUM)
10584         (compare:CC_Z
10585          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
10586                     (const_int 24))
10587          (match_operand 1 "const_int_operand" "")))
10588    (clobber (match_scratch:SI 2 ""))]
10589   "TARGET_ARM
10590    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10591        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
10592   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
10593    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
10594   "
10595   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
10596   "
10597 )
10598 ;; ??? Check the patterns above for Thumb-2 usefulness
10599
10600 (define_expand "prologue"
10601   [(clobber (const_int 0))]
10602   "TARGET_EITHER"
10603   "if (TARGET_32BIT)
10604      arm_expand_prologue ();
10605    else
10606      thumb1_expand_prologue ();
10607   DONE;
10608   "
10609 )
10610
10611 (define_expand "epilogue"
10612   [(clobber (const_int 0))]
10613   "TARGET_EITHER"
10614   "
10615   if (crtl->calls_eh_return)
10616     emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
10617   if (TARGET_THUMB1)
10618     thumb1_expand_epilogue ();
10619   else if (USE_RETURN_INSN (FALSE))
10620     {
10621       emit_jump_insn (gen_return ());
10622       DONE;
10623     }
10624   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10625         gen_rtvec (1,
10626                 gen_rtx_RETURN (VOIDmode)),
10627         VUNSPEC_EPILOGUE));
10628   DONE;
10629   "
10630 )
10631
10632 ;; Note - although unspec_volatile's USE all hard registers,
10633 ;; USEs are ignored after relaod has completed.  Thus we need
10634 ;; to add an unspec of the link register to ensure that flow
10635 ;; does not think that it is unused by the sibcall branch that
10636 ;; will replace the standard function epilogue.
10637 (define_insn "sibcall_epilogue"
10638   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
10639               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10640   "TARGET_32BIT"
10641   "*
10642   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
10643     return output_return_instruction (const_true_rtx, FALSE, FALSE);
10644   return arm_output_epilogue (next_nonnote_insn (insn));
10645   "
10646 ;; Length is absolute worst case
10647   [(set_attr "length" "44")
10648    (set_attr "type" "block")
10649    ;; We don't clobber the conditions, but the potential length of this
10650    ;; operation is sufficient to make conditionalizing the sequence 
10651    ;; unlikely to be profitable.
10652    (set_attr "conds" "clob")]
10653 )
10654
10655 (define_insn "*epilogue_insns"
10656   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
10657   "TARGET_EITHER"
10658   "*
10659   if (TARGET_32BIT)
10660     return arm_output_epilogue (NULL);
10661   else /* TARGET_THUMB1 */
10662     return thumb_unexpanded_epilogue ();
10663   "
10664   ; Length is absolute worst case
10665   [(set_attr "length" "44")
10666    (set_attr "type" "block")
10667    ;; We don't clobber the conditions, but the potential length of this
10668    ;; operation is sufficient to make conditionalizing the sequence 
10669    ;; unlikely to be profitable.
10670    (set_attr "conds" "clob")]
10671 )
10672
10673 (define_expand "eh_epilogue"
10674   [(use (match_operand:SI 0 "register_operand" ""))
10675    (use (match_operand:SI 1 "register_operand" ""))
10676    (use (match_operand:SI 2 "register_operand" ""))]
10677   "TARGET_EITHER"
10678   "
10679   {
10680     cfun->machine->eh_epilogue_sp_ofs = operands[1];
10681     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10682       {
10683         rtx ra = gen_rtx_REG (Pmode, 2);
10684
10685         emit_move_insn (ra, operands[2]);
10686         operands[2] = ra;
10687       }
10688     /* This is a hack -- we may have crystalized the function type too
10689        early.  */
10690     cfun->machine->func_type = 0;
10691   }"
10692 )
10693
10694 ;; This split is only used during output to reduce the number of patterns
10695 ;; that need assembler instructions adding to them.  We allowed the setting
10696 ;; of the conditions to be implicit during rtl generation so that
10697 ;; the conditional compare patterns would work.  However this conflicts to
10698 ;; some extent with the conditional data operations, so we have to split them
10699 ;; up again here.
10700
10701 ;; ??? Need to audit these splitters for Thumb-2.  Why isn't normal
10702 ;; conditional execution sufficient?
10703
10704 (define_split
10705   [(set (match_operand:SI 0 "s_register_operand" "")
10706         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10707                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10708                          (match_dup 0)
10709                          (match_operand 4 "" "")))
10710    (clobber (reg:CC CC_REGNUM))]
10711   "TARGET_ARM && reload_completed"
10712   [(set (match_dup 5) (match_dup 6))
10713    (cond_exec (match_dup 7)
10714               (set (match_dup 0) (match_dup 4)))]
10715   "
10716   {
10717     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10718                                              operands[2], operands[3]);
10719     enum rtx_code rc = GET_CODE (operands[1]);
10720
10721     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10722     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10723     if (mode == CCFPmode || mode == CCFPEmode)
10724       rc = reverse_condition_maybe_unordered (rc);
10725     else
10726       rc = reverse_condition (rc);
10727
10728     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10729   }"
10730 )
10731
10732 (define_split
10733   [(set (match_operand:SI 0 "s_register_operand" "")
10734         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10735                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10736                          (match_operand 4 "" "")
10737                          (match_dup 0)))
10738    (clobber (reg:CC CC_REGNUM))]
10739   "TARGET_ARM && reload_completed"
10740   [(set (match_dup 5) (match_dup 6))
10741    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10742               (set (match_dup 0) (match_dup 4)))]
10743   "
10744   {
10745     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10746                                              operands[2], operands[3]);
10747
10748     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10749     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10750   }"
10751 )
10752
10753 (define_split
10754   [(set (match_operand:SI 0 "s_register_operand" "")
10755         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10756                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10757                          (match_operand 4 "" "")
10758                          (match_operand 5 "" "")))
10759    (clobber (reg:CC CC_REGNUM))]
10760   "TARGET_ARM && reload_completed"
10761   [(set (match_dup 6) (match_dup 7))
10762    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10763               (set (match_dup 0) (match_dup 4)))
10764    (cond_exec (match_dup 8)
10765               (set (match_dup 0) (match_dup 5)))]
10766   "
10767   {
10768     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10769                                              operands[2], operands[3]);
10770     enum rtx_code rc = GET_CODE (operands[1]);
10771
10772     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10773     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10774     if (mode == CCFPmode || mode == CCFPEmode)
10775       rc = reverse_condition_maybe_unordered (rc);
10776     else
10777       rc = reverse_condition (rc);
10778
10779     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10780   }"
10781 )
10782
10783 (define_split
10784   [(set (match_operand:SI 0 "s_register_operand" "")
10785         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10786                           [(match_operand:SI 2 "s_register_operand" "")
10787                            (match_operand:SI 3 "arm_add_operand" "")])
10788                          (match_operand:SI 4 "arm_rhs_operand" "")
10789                          (not:SI
10790                           (match_operand:SI 5 "s_register_operand" ""))))
10791    (clobber (reg:CC CC_REGNUM))]
10792   "TARGET_ARM && reload_completed"
10793   [(set (match_dup 6) (match_dup 7))
10794    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10795               (set (match_dup 0) (match_dup 4)))
10796    (cond_exec (match_dup 8)
10797               (set (match_dup 0) (not:SI (match_dup 5))))]
10798   "
10799   {
10800     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10801                                              operands[2], operands[3]);
10802     enum rtx_code rc = GET_CODE (operands[1]);
10803
10804     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10805     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10806     if (mode == CCFPmode || mode == CCFPEmode)
10807       rc = reverse_condition_maybe_unordered (rc);
10808     else
10809       rc = reverse_condition (rc);
10810
10811     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10812   }"
10813 )
10814
10815 (define_insn "*cond_move_not"
10816   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10817         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10818                           [(match_operand 3 "cc_register" "") (const_int 0)])
10819                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10820                          (not:SI
10821                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
10822   "TARGET_ARM"
10823   "@
10824    mvn%D4\\t%0, %2
10825    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
10826   [(set_attr "conds" "use")
10827    (set_attr "length" "4,8")]
10828 )
10829
10830 ;; The next two patterns occur when an AND operation is followed by a
10831 ;; scc insn sequence 
10832
10833 (define_insn "*sign_extract_onebit"
10834   [(set (match_operand:SI 0 "s_register_operand" "=r")
10835         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10836                          (const_int 1)
10837                          (match_operand:SI 2 "const_int_operand" "n")))
10838     (clobber (reg:CC CC_REGNUM))]
10839   "TARGET_ARM"
10840   "*
10841     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10842     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10843     return \"mvnne\\t%0, #0\";
10844   "
10845   [(set_attr "conds" "clob")
10846    (set_attr "length" "8")]
10847 )
10848
10849 (define_insn "*not_signextract_onebit"
10850   [(set (match_operand:SI 0 "s_register_operand" "=r")
10851         (not:SI
10852          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10853                           (const_int 1)
10854                           (match_operand:SI 2 "const_int_operand" "n"))))
10855    (clobber (reg:CC CC_REGNUM))]
10856   "TARGET_ARM"
10857   "*
10858     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10859     output_asm_insn (\"tst\\t%1, %2\", operands);
10860     output_asm_insn (\"mvneq\\t%0, #0\", operands);
10861     return \"movne\\t%0, #0\";
10862   "
10863   [(set_attr "conds" "clob")
10864    (set_attr "length" "12")]
10865 )
10866 ;; ??? The above patterns need auditing for Thumb-2
10867
10868 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
10869 ;; expressions.  For simplicity, the first register is also in the unspec
10870 ;; part.
10871 (define_insn "*push_multi"
10872   [(match_parallel 2 "multi_register_push"
10873     [(set (match_operand:BLK 0 "memory_operand" "=m")
10874           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
10875                       UNSPEC_PUSH_MULT))])]
10876   "TARGET_32BIT"
10877   "*
10878   {
10879     int num_saves = XVECLEN (operands[2], 0);
10880      
10881     /* For the StrongARM at least it is faster to
10882        use STR to store only a single register.
10883        In Thumb mode always use push, and the assembler will pick
10884        something appropriate.  */
10885     if (num_saves == 1 && TARGET_ARM)
10886       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10887     else
10888       {
10889         int i;
10890         char pattern[100];
10891
10892         if (TARGET_ARM)
10893             strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10894         else
10895             strcpy (pattern, \"push\\t{%1\");
10896
10897         for (i = 1; i < num_saves; i++)
10898           {
10899             strcat (pattern, \", %|\");
10900             strcat (pattern,
10901                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10902           }
10903
10904         strcat (pattern, \"}\");
10905         output_asm_insn (pattern, operands);
10906       }
10907
10908     return \"\";
10909   }"
10910   [(set_attr "type" "store4")]
10911 )
10912
10913 (define_insn "stack_tie"
10914   [(set (mem:BLK (scratch))
10915         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10916                      (match_operand:SI 1 "s_register_operand" "rk")]
10917                     UNSPEC_PRLG_STK))]
10918   ""
10919   ""
10920   [(set_attr "length" "0")]
10921 )
10922
10923 ;; Similarly for the floating point registers
10924 (define_insn "*push_fp_multi"
10925   [(match_parallel 2 "multi_register_push"
10926     [(set (match_operand:BLK 0 "memory_operand" "=m")
10927           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10928                       UNSPEC_PUSH_MULT))])]
10929   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
10930   "*
10931   {
10932     char pattern[100];
10933
10934     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10935     output_asm_insn (pattern, operands);
10936     return \"\";
10937   }"
10938   [(set_attr "type" "f_store")]
10939 )
10940
10941 ;; Special patterns for dealing with the constant pool
10942
10943 (define_insn "align_4"
10944   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10945   "TARGET_EITHER"
10946   "*
10947   assemble_align (32);
10948   return \"\";
10949   "
10950 )
10951
10952 (define_insn "align_8"
10953   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10954   "TARGET_EITHER"
10955   "*
10956   assemble_align (64);
10957   return \"\";
10958   "
10959 )
10960
10961 (define_insn "consttable_end"
10962   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10963   "TARGET_EITHER"
10964   "*
10965   making_const_table = FALSE;
10966   return \"\";
10967   "
10968 )
10969
10970 (define_insn "consttable_1"
10971   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10972   "TARGET_THUMB1"
10973   "*
10974   making_const_table = TRUE;
10975   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10976   assemble_zeros (3);
10977   return \"\";
10978   "
10979   [(set_attr "length" "4")]
10980 )
10981
10982 (define_insn "consttable_2"
10983   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10984   "TARGET_THUMB1"
10985   "*
10986   making_const_table = TRUE;
10987   gcc_assert (GET_MODE_CLASS (GET_MODE (operands[0])) != MODE_FLOAT);
10988   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10989   assemble_zeros (2);
10990   return \"\";
10991   "
10992   [(set_attr "length" "4")]
10993 )
10994
10995 (define_insn "consttable_4"
10996   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10997   "TARGET_EITHER"
10998   "*
10999   {
11000     rtx x = operands[0];
11001     making_const_table = TRUE;
11002     switch (GET_MODE_CLASS (GET_MODE (x)))
11003       {
11004       case MODE_FLOAT:
11005         if (GET_MODE (x) == HFmode)
11006           arm_emit_fp16_const (x);
11007         else
11008           {
11009             REAL_VALUE_TYPE r;
11010             REAL_VALUE_FROM_CONST_DOUBLE (r, x);
11011             assemble_real (r, GET_MODE (x), BITS_PER_WORD);
11012           }
11013         break;
11014       default:
11015         /* XXX: Sometimes gcc does something really dumb and ends up with
11016            a HIGH in a constant pool entry, usually because it's trying to
11017            load into a VFP register.  We know this will always be used in
11018            combination with a LO_SUM which ignores the high bits, so just
11019            strip off the HIGH.  */
11020         if (GET_CODE (x) == HIGH)
11021           x = XEXP (x, 0);
11022         assemble_integer (x, 4, BITS_PER_WORD, 1);
11023         mark_symbol_refs_as_used (x);
11024         break;
11025       }
11026     return \"\";
11027   }"
11028   [(set_attr "length" "4")]
11029 )
11030
11031 (define_insn "consttable_8"
11032   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
11033   "TARGET_EITHER"
11034   "*
11035   {
11036     making_const_table = TRUE;
11037     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
11038       {
11039        case MODE_FLOAT:
11040         {
11041           REAL_VALUE_TYPE r;
11042           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
11043           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
11044           break;
11045         }
11046       default:
11047         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
11048         break;
11049       }
11050     return \"\";
11051   }"
11052   [(set_attr "length" "8")]
11053 )
11054
11055 (define_insn "consttable_16"
11056   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
11057   "TARGET_EITHER"
11058   "*
11059   {
11060     making_const_table = TRUE;
11061     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
11062       {
11063        case MODE_FLOAT:
11064         {
11065           REAL_VALUE_TYPE r;
11066           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
11067           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
11068           break;
11069         }
11070       default:
11071         assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
11072         break;
11073       }
11074     return \"\";
11075   }"
11076   [(set_attr "length" "16")]
11077 )
11078
11079 ;; Miscellaneous Thumb patterns
11080
11081 (define_expand "tablejump"
11082   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
11083               (use (label_ref (match_operand 1 "" "")))])]
11084   "TARGET_THUMB1"
11085   "
11086   if (flag_pic)
11087     {
11088       /* Hopefully, CSE will eliminate this copy.  */
11089       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
11090       rtx reg2 = gen_reg_rtx (SImode);
11091
11092       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
11093       operands[0] = reg2;
11094     }
11095   "
11096 )
11097
11098 ;; NB never uses BX.
11099 (define_insn "*thumb1_tablejump"
11100   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
11101    (use (label_ref (match_operand 1 "" "")))]
11102   "TARGET_THUMB1"
11103   "mov\\t%|pc, %0"
11104   [(set_attr "length" "2")]
11105 )
11106
11107 ;; V5 Instructions,
11108
11109 (define_insn "clzsi2"
11110   [(set (match_operand:SI 0 "s_register_operand" "=r")
11111         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
11112   "TARGET_32BIT && arm_arch5"
11113   "clz%?\\t%0, %1"
11114   [(set_attr "predicable" "yes")
11115    (set_attr "insn" "clz")])
11116
11117 (define_insn "rbitsi2"
11118   [(set (match_operand:SI 0 "s_register_operand" "=r")
11119         (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
11120   "TARGET_32BIT && arm_arch_thumb2"
11121   "rbit%?\\t%0, %1"
11122   [(set_attr "predicable" "yes")
11123    (set_attr "insn" "clz")])
11124
11125 (define_expand "ctzsi2"
11126  [(set (match_operand:SI           0 "s_register_operand" "")
11127        (ctz:SI (match_operand:SI  1 "s_register_operand" "")))]
11128   "TARGET_32BIT && arm_arch_thumb2"
11129   "
11130    {
11131      rtx tmp = gen_reg_rtx (SImode); 
11132      emit_insn (gen_rbitsi2 (tmp, operands[1]));
11133      emit_insn (gen_clzsi2 (operands[0], tmp));
11134    }
11135    DONE;
11136   "
11137 )
11138
11139 ;; V5E instructions.
11140
11141 (define_insn "prefetch"
11142   [(prefetch (match_operand:SI 0 "address_operand" "p")
11143              (match_operand:SI 1 "" "")
11144              (match_operand:SI 2 "" ""))]
11145   "TARGET_32BIT && arm_arch5e"
11146   "pld\\t%a0")
11147
11148 ;; General predication pattern
11149
11150 (define_cond_exec
11151   [(match_operator 0 "arm_comparison_operator"
11152     [(match_operand 1 "cc_register" "")
11153      (const_int 0)])]
11154   "TARGET_32BIT"
11155   ""
11156 )
11157
11158 (define_insn "prologue_use"
11159   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
11160   ""
11161   "%@ %0 needed for prologue"
11162   [(set_attr "length" "0")]
11163 )
11164
11165
11166 ;; Patterns for exception handling
11167
11168 (define_expand "eh_return"
11169   [(use (match_operand 0 "general_operand" ""))]
11170   "TARGET_EITHER"
11171   "
11172   {
11173     if (TARGET_32BIT)
11174       emit_insn (gen_arm_eh_return (operands[0]));
11175     else
11176       emit_insn (gen_thumb_eh_return (operands[0]));
11177     DONE;
11178   }"
11179 )
11180                                    
11181 ;; We can't expand this before we know where the link register is stored.
11182 (define_insn_and_split "arm_eh_return"
11183   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
11184                     VUNSPEC_EH_RETURN)
11185    (clobber (match_scratch:SI 1 "=&r"))]
11186   "TARGET_ARM"
11187   "#"
11188   "&& reload_completed"
11189   [(const_int 0)]
11190   "
11191   {
11192     arm_set_return_address (operands[0], operands[1]);
11193     DONE;
11194   }"
11195 )
11196
11197 (define_insn_and_split "thumb_eh_return"
11198   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
11199                     VUNSPEC_EH_RETURN)
11200    (clobber (match_scratch:SI 1 "=&l"))]
11201   "TARGET_THUMB1"
11202   "#"
11203   "&& reload_completed"
11204   [(const_int 0)]
11205   "
11206   {
11207     thumb_set_return_address (operands[0], operands[1]);
11208     DONE;
11209   }"
11210 )
11211
11212 \f
11213 ;; TLS support
11214
11215 (define_insn "load_tp_hard"
11216   [(set (match_operand:SI 0 "register_operand" "=r")
11217         (unspec:SI [(const_int 0)] UNSPEC_TLS))]
11218   "TARGET_HARD_TP"
11219   "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
11220   [(set_attr "predicable" "yes")]
11221 )
11222
11223 ;; Doesn't clobber R1-R3.  Must use r0 for the first operand.
11224 (define_insn "load_tp_soft"
11225   [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
11226    (clobber (reg:SI LR_REGNUM))
11227    (clobber (reg:SI IP_REGNUM))
11228    (clobber (reg:CC CC_REGNUM))]
11229   "TARGET_SOFT_TP"
11230   "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
11231   [(set_attr "conds" "clob")]
11232 )
11233
11234 (define_insn "*arm_movtas_ze" 
11235   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
11236                    (const_int 16)
11237                    (const_int 16))
11238         (match_operand:SI 1 "const_int_operand" ""))]
11239   "TARGET_32BIT"
11240   "movt%?\t%0, %c1"
11241  [(set_attr "predicable" "yes")
11242    (set_attr "length" "4")]
11243 )
11244
11245 (define_insn "arm_rev"
11246   [(set (match_operand:SI 0 "s_register_operand" "=r")
11247         (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
11248   "TARGET_EITHER && arm_arch6"
11249   "rev\t%0, %1"
11250   [(set (attr "length")
11251         (if_then_else (eq_attr "is_thumb" "yes")
11252                       (const_int 2)
11253                       (const_int 4)))]
11254 )
11255
11256 (define_expand "arm_legacy_rev"
11257   [(set (match_operand:SI 2 "s_register_operand" "")
11258         (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
11259                              (const_int 16))
11260                 (match_dup 1)))
11261    (set (match_dup 2)
11262         (lshiftrt:SI (match_dup 2)
11263                      (const_int 8)))
11264    (set (match_operand:SI 3 "s_register_operand" "")
11265         (rotatert:SI (match_dup 1)
11266                      (const_int 8)))
11267    (set (match_dup 2)
11268         (and:SI (match_dup 2)
11269                 (const_int -65281)))
11270    (set (match_operand:SI 0 "s_register_operand" "")
11271         (xor:SI (match_dup 3)
11272                 (match_dup 2)))]
11273   "TARGET_32BIT"
11274   ""
11275 )
11276
11277 ;; Reuse temporaries to keep register pressure down.
11278 (define_expand "thumb_legacy_rev"
11279   [(set (match_operand:SI 2 "s_register_operand" "")
11280      (ashift:SI (match_operand:SI 1 "s_register_operand" "")
11281                 (const_int 24)))
11282    (set (match_operand:SI 3 "s_register_operand" "")
11283      (lshiftrt:SI (match_dup 1)
11284                   (const_int 24)))
11285    (set (match_dup 3)
11286      (ior:SI (match_dup 3)
11287              (match_dup 2)))
11288    (set (match_operand:SI 4 "s_register_operand" "")
11289      (const_int 16))
11290    (set (match_operand:SI 5 "s_register_operand" "")
11291      (rotatert:SI (match_dup 1)
11292                   (match_dup 4)))
11293    (set (match_dup 2)
11294      (ashift:SI (match_dup 5)
11295                 (const_int 24)))
11296    (set (match_dup 5)
11297      (lshiftrt:SI (match_dup 5)
11298                   (const_int 24)))
11299    (set (match_dup 5)
11300      (ior:SI (match_dup 5)
11301              (match_dup 2)))
11302    (set (match_dup 5)
11303      (rotatert:SI (match_dup 5)
11304                   (match_dup 4)))
11305    (set (match_operand:SI 0 "s_register_operand" "")
11306      (ior:SI (match_dup 5)
11307              (match_dup 3)))]
11308   "TARGET_THUMB"
11309   ""
11310 )
11311
11312 (define_expand "bswapsi2"
11313   [(set (match_operand:SI 0 "s_register_operand" "=r")
11314         (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
11315 "TARGET_EITHER"
11316 "
11317   if (!arm_arch6)
11318     {
11319       if (!optimize_size)
11320         {
11321           rtx op2 = gen_reg_rtx (SImode);
11322           rtx op3 = gen_reg_rtx (SImode);
11323
11324           if (TARGET_THUMB)
11325             {
11326               rtx op4 = gen_reg_rtx (SImode);
11327               rtx op5 = gen_reg_rtx (SImode);
11328
11329               emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
11330                                                op2, op3, op4, op5));
11331             }
11332           else
11333             {
11334               emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
11335                                              op2, op3));
11336             }
11337
11338           DONE;
11339         }
11340       else
11341         FAIL;
11342     }
11343   "
11344 )
11345
11346 ;; Load the FPA co-processor patterns
11347 (include "fpa.md")
11348 ;; Load the Maverick co-processor patterns
11349 (include "cirrus.md")
11350 ;; Vector bits common to IWMMXT and Neon
11351 (include "vec-common.md")
11352 ;; Load the Intel Wireless Multimedia Extension patterns
11353 (include "iwmmxt.md")
11354 ;; Load the VFP co-processor patterns
11355 (include "vfp.md")
11356 ;; Thumb-2 patterns
11357 (include "thumb2.md")
11358 ;; Neon patterns
11359 (include "neon.md")
11360