OSDN Git Service

PR rtl-optimization/44787
[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 ; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6.
152 (define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6")))
153
154 ;; Operand number of an input operand that is shifted.  Zero if the
155 ;; given instruction does not shift one of its input operands.
156 (define_attr "shift" "" (const_int 0))
157
158 ; Floating Point Unit.  If we only have floating point emulation, then there
159 ; is no point in scheduling the floating point insns.  (Well, for best
160 ; performance we should try and group them together).
161 (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
162   (const (symbol_ref "arm_fpu_attr")))
163
164 ; LENGTH of an instruction (in bytes)
165 (define_attr "length" "" (const_int 4))
166
167 ; POOL_RANGE is how far away from a constant pool entry that this insn
168 ; can be placed.  If the distance is zero, then this insn will never
169 ; reference the pool.
170 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
171 ; before its address.
172 (define_attr "pool_range" "" (const_int 0))
173 (define_attr "neg_pool_range" "" (const_int 0))
174
175 ; An assembler sequence may clobber the condition codes without us knowing.
176 ; If such an insn references the pool, then we have no way of knowing how,
177 ; so use the most conservative value for pool_range.
178 (define_asm_attributes
179  [(set_attr "conds" "clob")
180   (set_attr "length" "4")
181   (set_attr "pool_range" "250")])
182
183 ;; The instruction used to implement a particular pattern.  This
184 ;; information is used by pipeline descriptions to provide accurate
185 ;; scheduling information.
186
187 (define_attr "insn"
188         "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"
189         (const_string "other"))
190
191 ; TYPE attribute is used to detect floating point instructions which, if
192 ; running on a co-processor can run in parallel with other, basic instructions
193 ; If write-buffer scheduling is enabled then it can also be used in the
194 ; scheduling of writes.
195
196 ; Classification of each insn
197 ; Note: vfp.md has different meanings for some of these, and some further
198 ; types as well.  See that file for details.
199 ; alu           any alu  instruction that doesn't hit memory or fp
200 ;               regs or have a shifted source operand
201 ; alu_shift     any data instruction that doesn't hit memory or fp
202 ;               regs, but has a source operand shifted by a constant
203 ; alu_shift_reg any data instruction that doesn't hit memory or fp
204 ;               regs, but has a source operand shifted by a register value
205 ; mult          a multiply instruction
206 ; block         blockage insn, this blocks all functional units
207 ; float         a floating point arithmetic operation (subject to expansion)
208 ; fdivd         DFmode floating point division
209 ; fdivs         SFmode floating point division
210 ; fmul          Floating point multiply
211 ; ffmul         Fast floating point multiply
212 ; farith        Floating point arithmetic (4 cycle)
213 ; ffarith       Fast floating point arithmetic (2 cycle)
214 ; float_em      a floating point arithmetic operation that is normally emulated
215 ;               even on a machine with an fpa.
216 ; f_load        a floating point load from memory
217 ; f_store       a floating point store to memory
218 ; f_load[sd]    single/double load from memory
219 ; f_store[sd]   single/double store to memory
220 ; f_flag        a transfer of co-processor flags to the CPSR
221 ; f_mem_r       a transfer of a floating point register to a real reg via mem
222 ; r_mem_f       the reverse of f_mem_r
223 ; f_2_r         fast transfer float to arm (no memory needed)
224 ; r_2_f         fast transfer arm to float
225 ; f_cvt         convert floating<->integral
226 ; branch        a branch
227 ; call          a subroutine call
228 ; load_byte     load byte(s) from memory to arm registers
229 ; load1         load 1 word from memory to arm registers
230 ; load2         load 2 words from memory to arm registers
231 ; load3         load 3 words from memory to arm registers
232 ; load4         load 4 words from memory to arm registers
233 ; store         store 1 word to memory from arm registers
234 ; store2        store 2 words
235 ; store3        store 3 words
236 ; store4        store 4 (or more) words
237 ;  Additions for Cirrus Maverick co-processor:
238 ; mav_farith    Floating point arithmetic (4 cycle)
239 ; mav_dmult     Double multiplies (7 cycle)
240 ;
241
242 (define_attr "type"
243         "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"
244         (if_then_else 
245          (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
246          (const_string "mult")
247          (const_string "alu")))
248
249 ; Load scheduling, set from the arm_ld_sched variable
250 ; initialized by arm_override_options() 
251 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
252
253 ;; Classification of NEON instructions for scheduling purposes.
254 ;; Do not set this attribute and the "type" attribute together in
255 ;; any one instruction pattern.
256 (define_attr "neon_type"
257    "neon_int_1,\
258    neon_int_2,\
259    neon_int_3,\
260    neon_int_4,\
261    neon_int_5,\
262    neon_vqneg_vqabs,\
263    neon_vmov,\
264    neon_vaba,\
265    neon_vsma,\
266    neon_vaba_qqq,\
267    neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
268    neon_mul_qqq_8_16_32_ddd_32,\
269    neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,\
270    neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
271    neon_mla_qqq_8_16,\
272    neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,\
273    neon_mla_qqq_32_qqd_32_scalar,\
274    neon_mul_ddd_16_scalar_32_16_long_scalar,\
275    neon_mul_qqd_32_scalar,\
276    neon_mla_ddd_16_scalar_qdd_32_16_long_scalar,\
277    neon_shift_1,\
278    neon_shift_2,\
279    neon_shift_3,\
280    neon_vshl_ddd,\
281    neon_vqshl_vrshl_vqrshl_qqq,\
282    neon_vsra_vrsra,\
283    neon_fp_vadd_ddd_vabs_dd,\
284    neon_fp_vadd_qqq_vabs_qq,\
285    neon_fp_vsum,\
286    neon_fp_vmul_ddd,\
287    neon_fp_vmul_qqd,\
288    neon_fp_vmla_ddd,\
289    neon_fp_vmla_qqq,\
290    neon_fp_vmla_ddd_scalar,\
291    neon_fp_vmla_qqq_scalar,\
292    neon_fp_vrecps_vrsqrts_ddd,\
293    neon_fp_vrecps_vrsqrts_qqq,\
294    neon_bp_simple,\
295    neon_bp_2cycle,\
296    neon_bp_3cycle,\
297    neon_ldr,\
298    neon_str,\
299    neon_vld1_1_2_regs,\
300    neon_vld1_3_4_regs,\
301    neon_vld2_2_regs_vld1_vld2_all_lanes,\
302    neon_vld2_4_regs,\
303    neon_vld3_vld4,\
304    neon_vst1_1_2_regs_vst2_2_regs,\
305    neon_vst1_3_4_regs,\
306    neon_vst2_4_regs_vst3_vst4,\
307    neon_vst3_vst4,\
308    neon_vld1_vld2_lane,\
309    neon_vld3_vld4_lane,\
310    neon_vst1_vst2_lane,\
311    neon_vst3_vst4_lane,\
312    neon_vld3_vld4_all_lanes,\
313    neon_mcr,\
314    neon_mcr_2_mcrr,\
315    neon_mrc,\
316    neon_mrrc,\
317    neon_ldm_2,\
318    neon_stm_2,\
319    none"
320  (const_string "none"))
321
322 ; condition codes: this one is used by final_prescan_insn to speed up
323 ; conditionalizing instructions.  It saves having to scan the rtl to see if
324 ; it uses or alters the condition codes.
325
326 ; USE means that the condition codes are used by the insn in the process of
327 ;   outputting code, this means (at present) that we can't use the insn in
328 ;   inlined branches
329 ;
330 ; SET means that the purpose of the insn is to set the condition codes in a
331 ;   well defined manner.
332 ;
333 ; CLOB means that the condition codes are altered in an undefined manner, if
334 ;   they are altered at all
335 ;
336 ; UNCONDITIONAL means the instions can not be conditionally executed.
337 ;
338 ; NOCOND means that the condition codes are neither altered nor affect the
339 ;   output of this insn
340
341 (define_attr "conds" "use,set,clob,unconditional,nocond"
342         (if_then_else (eq_attr "type" "call")
343          (const_string "clob")
344          (if_then_else (eq_attr "neon_type" "none")
345           (const_string "nocond")
346           (const_string "unconditional"))))
347
348 ; Predicable means that the insn can be conditionally executed based on
349 ; an automatically added predicate (additional patterns are generated by 
350 ; gen...).  We default to 'no' because no Thumb patterns match this rule
351 ; and not all ARM patterns do.
352 (define_attr "predicable" "no,yes" (const_string "no"))
353
354 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
355 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
356 ; suffer blockages enough to warrant modelling this (and it can adversely
357 ; affect the schedule).
358 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
359
360 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
361 ; to stall the processor.  Used with model_wbuf above.
362 (define_attr "write_conflict" "no,yes"
363   (if_then_else (eq_attr "type"
364                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
365                 (const_string "yes")
366                 (const_string "no")))
367
368 ; Classify the insns into those that take one cycle and those that take more
369 ; than one on the main cpu execution unit.
370 (define_attr "core_cycles" "single,multi"
371   (if_then_else (eq_attr "type"
372                  "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
373                 (const_string "single")
374                 (const_string "multi")))
375
376 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
377 ;; distant label.  Only applicable to Thumb code.
378 (define_attr "far_jump" "yes,no" (const_string "no"))
379
380
381 ;; The number of machine instructions this pattern expands to.
382 ;; Used for Thumb-2 conditional execution.
383 (define_attr "ce_count" "" (const_int 1))
384
385 ;;---------------------------------------------------------------------------
386 ;; Mode iterators
387
388 ; A list of modes that are exactly 64 bits in size.  We use this to expand
389 ; some splits that are the same for all modes when operating on ARM 
390 ; registers.
391 (define_mode_iterator ANY64 [DI DF V8QI V4HI V2SI V2SF])
392
393 ;; The integer modes up to word size
394 (define_mode_iterator QHSI [QI HI SI])
395
396 ;;---------------------------------------------------------------------------
397 ;; Predicates
398
399 (include "predicates.md")
400 (include "constraints.md")
401
402 ;;---------------------------------------------------------------------------
403 ;; Pipeline descriptions
404
405 ;; Processor type.  This is created automatically from arm-cores.def.
406 (include "arm-tune.md")
407
408 (define_attr "tune_cortexr4" "yes,no"
409   (const (if_then_else
410           (eq_attr "tune" "cortexr4,cortexr4f")
411           (const_string "yes")
412           (const_string "no"))))
413
414 ;; True if the generic scheduling description should be used.
415
416 (define_attr "generic_sched" "yes,no"
417   (const (if_then_else 
418           (ior (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa8,cortexa9")
419               (eq_attr "tune_cortexr4" "yes"))
420           (const_string "no")
421           (const_string "yes"))))
422
423 (define_attr "generic_vfp" "yes,no"
424   (const (if_then_else
425           (and (eq_attr "fpu" "vfp")
426                (eq_attr "tune" "!arm1020e,arm1022e,cortexa8,cortexa9")
427                (eq_attr "tune_cortexr4" "no"))
428           (const_string "yes")
429           (const_string "no"))))
430
431 (include "arm-generic.md")
432 (include "arm926ejs.md")
433 (include "arm1020e.md")
434 (include "arm1026ejs.md")
435 (include "arm1136jfs.md")
436 (include "cortex-a8.md")
437 (include "cortex-a9.md")
438 (include "cortex-r4.md")
439 (include "cortex-r4f.md")
440 (include "vfp11.md")
441
442 \f
443 ;;---------------------------------------------------------------------------
444 ;; Insn patterns
445 ;;
446 ;; Addition insns.
447
448 ;; Note: For DImode insns, there is normally no reason why operands should
449 ;; not be in the same register, what we don't want is for something being
450 ;; written to partially overlap something that is an input.
451 ;; Cirrus 64bit additions should not be split because we have a native
452 ;; 64bit addition instructions.
453
454 (define_expand "adddi3"
455  [(parallel
456    [(set (match_operand:DI           0 "s_register_operand" "")
457           (plus:DI (match_operand:DI 1 "s_register_operand" "")
458                    (match_operand:DI 2 "s_register_operand" "")))
459     (clobber (reg:CC CC_REGNUM))])]
460   "TARGET_EITHER"
461   "
462   if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
463     {
464       if (!cirrus_fp_register (operands[0], DImode))
465         operands[0] = force_reg (DImode, operands[0]);
466       if (!cirrus_fp_register (operands[1], DImode))
467         operands[1] = force_reg (DImode, operands[1]);
468       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
469       DONE;
470     }
471
472   if (TARGET_THUMB1)
473     {
474       if (GET_CODE (operands[1]) != REG)
475         operands[1] = force_reg (DImode, operands[1]);
476       if (GET_CODE (operands[2]) != REG)
477         operands[2] = force_reg (DImode, operands[2]);
478      }
479   "
480 )
481
482 (define_insn "*thumb1_adddi3"
483   [(set (match_operand:DI          0 "register_operand" "=l")
484         (plus:DI (match_operand:DI 1 "register_operand" "%0")
485                  (match_operand:DI 2 "register_operand" "l")))
486    (clobber (reg:CC CC_REGNUM))
487   ]
488   "TARGET_THUMB1"
489   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
490   [(set_attr "length" "4")]
491 )
492
493 (define_insn_and_split "*arm_adddi3"
494   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
495         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
496                  (match_operand:DI 2 "s_register_operand" "r,  0")))
497    (clobber (reg:CC CC_REGNUM))]
498   "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK) && !TARGET_NEON"
499   "#"
500   "TARGET_32BIT && reload_completed
501    && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
502   [(parallel [(set (reg:CC_C CC_REGNUM)
503                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
504                                  (match_dup 1)))
505               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
506    (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
507                                (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
508   "
509   {
510     operands[3] = gen_highpart (SImode, operands[0]);
511     operands[0] = gen_lowpart (SImode, operands[0]);
512     operands[4] = gen_highpart (SImode, operands[1]);
513     operands[1] = gen_lowpart (SImode, operands[1]);
514     operands[5] = gen_highpart (SImode, operands[2]);
515     operands[2] = gen_lowpart (SImode, operands[2]);
516   }"
517   [(set_attr "conds" "clob")
518    (set_attr "length" "8")]
519 )
520
521 (define_insn_and_split "*adddi_sesidi_di"
522   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
523         (plus:DI (sign_extend:DI
524                   (match_operand:SI 2 "s_register_operand" "r,r"))
525                  (match_operand:DI 1 "s_register_operand" "0,r")))
526    (clobber (reg:CC CC_REGNUM))]
527   "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
528   "#"
529   "TARGET_32BIT && reload_completed"
530   [(parallel [(set (reg:CC_C CC_REGNUM)
531                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
532                                  (match_dup 1)))
533               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
534    (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
535                                                      (const_int 31))
536                                         (match_dup 4))
537                                (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
538   "
539   {
540     operands[3] = gen_highpart (SImode, operands[0]);
541     operands[0] = gen_lowpart (SImode, operands[0]);
542     operands[4] = gen_highpart (SImode, operands[1]);
543     operands[1] = gen_lowpart (SImode, operands[1]);
544     operands[2] = gen_lowpart (SImode, operands[2]);
545   }"
546   [(set_attr "conds" "clob")
547    (set_attr "length" "8")]
548 )
549
550 (define_insn_and_split "*adddi_zesidi_di"
551   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
552         (plus:DI (zero_extend:DI
553                   (match_operand:SI 2 "s_register_operand" "r,r"))
554                  (match_operand:DI 1 "s_register_operand" "0,r")))
555    (clobber (reg:CC CC_REGNUM))]
556   "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
557   "#"
558   "TARGET_32BIT && reload_completed"
559   [(parallel [(set (reg:CC_C CC_REGNUM)
560                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
561                                  (match_dup 1)))
562               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
563    (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
564                                (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
565   "
566   {
567     operands[3] = gen_highpart (SImode, operands[0]);
568     operands[0] = gen_lowpart (SImode, operands[0]);
569     operands[4] = gen_highpart (SImode, operands[1]);
570     operands[1] = gen_lowpart (SImode, operands[1]);
571     operands[2] = gen_lowpart (SImode, operands[2]);
572   }"
573   [(set_attr "conds" "clob")
574    (set_attr "length" "8")]
575 )
576
577 (define_expand "addsi3"
578   [(set (match_operand:SI          0 "s_register_operand" "")
579         (plus:SI (match_operand:SI 1 "s_register_operand" "")
580                  (match_operand:SI 2 "reg_or_int_operand" "")))]
581   "TARGET_EITHER"
582   "
583   if (TARGET_32BIT && GET_CODE (operands[2]) == CONST_INT)
584     {
585       arm_split_constant (PLUS, SImode, NULL_RTX,
586                           INTVAL (operands[2]), operands[0], operands[1],
587                           optimize && can_create_pseudo_p ());
588       DONE;
589     }
590   "
591 )
592
593 ; If there is a scratch available, this will be faster than synthesizing the
594 ; addition.
595 (define_peephole2
596   [(match_scratch:SI 3 "r")
597    (set (match_operand:SI          0 "arm_general_register_operand" "")
598         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
599                  (match_operand:SI 2 "const_int_operand"  "")))]
600   "TARGET_32BIT &&
601    !(const_ok_for_arm (INTVAL (operands[2]))
602      || const_ok_for_arm (-INTVAL (operands[2])))
603     && const_ok_for_arm (~INTVAL (operands[2]))"
604   [(set (match_dup 3) (match_dup 2))
605    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
606   ""
607 )
608
609 ;; The r/r/k alternative is required when reloading the address
610 ;;  (plus (reg rN) (reg sp)) into (reg rN).  In this case reload will
611 ;; put the duplicated register first, and not try the commutative version.
612 (define_insn_and_split "*arm_addsi3"
613   [(set (match_operand:SI          0 "s_register_operand" "=r, !k, r,r, !k,r")
614         (plus:SI (match_operand:SI 1 "s_register_operand" "%rk,!k, r,rk,!k,rk")
615                  (match_operand:SI 2 "reg_or_int_operand" "rI, rI,!k,L, L,?n")))]
616   "TARGET_32BIT"
617   "@
618    add%?\\t%0, %1, %2
619    add%?\\t%0, %1, %2
620    add%?\\t%0, %2, %1
621    sub%?\\t%0, %1, #%n2
622    sub%?\\t%0, %1, #%n2
623    #"
624   "TARGET_32BIT
625    && GET_CODE (operands[2]) == CONST_INT
626    && !(const_ok_for_arm (INTVAL (operands[2]))
627         || const_ok_for_arm (-INTVAL (operands[2])))
628    && (reload_completed || !arm_eliminable_register (operands[1]))"
629   [(clobber (const_int 0))]
630   "
631   arm_split_constant (PLUS, SImode, curr_insn,
632                       INTVAL (operands[2]), operands[0],
633                       operands[1], 0);
634   DONE;
635   "
636   [(set_attr "length" "4,4,4,4,4,16")
637    (set_attr "predicable" "yes")]
638 )
639
640 ;; Register group 'k' is a single register group containing only the stack
641 ;; register.  Trying to reload it will always fail catastrophically,
642 ;; so never allow those alternatives to match if reloading is needed.
643
644 (define_insn_and_split "*thumb1_addsi3"
645   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*rk,*hk,l,!k,l,l")
646         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k,0,l")
647                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,!M,!O,Pa,Pb")))]
648   "TARGET_THUMB1"
649   "*
650    static const char * const asms[] = 
651    {
652      \"add\\t%0, %0, %2\",
653      \"sub\\t%0, %0, #%n2\",
654      \"add\\t%0, %1, %2\",
655      \"add\\t%0, %0, %2\",
656      \"add\\t%0, %0, %2\",
657      \"add\\t%0, %1, %2\",
658      \"add\\t%0, %1, %2\",
659      \"#\",
660      \"#\"
661    };
662    if ((which_alternative == 2 || which_alternative == 6)
663        && GET_CODE (operands[2]) == CONST_INT
664        && INTVAL (operands[2]) < 0)
665      return \"sub\\t%0, %1, #%n2\";
666    return asms[which_alternative];
667   "
668   "&& reload_completed && CONST_INT_P (operands[2])
669    && operands[1] != stack_pointer_rtx
670    && (INTVAL (operands[2]) > 255 || INTVAL (operands[2]) < -255)"
671   [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
672    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
673   {
674     HOST_WIDE_INT offset = INTVAL (operands[2]);
675     if (offset > 255)
676       offset = 255;
677     else if (offset < -255)
678       offset = -255;
679     
680     operands[3] = GEN_INT (offset);
681     operands[2] = GEN_INT (INTVAL (operands[2]) - offset);
682   }
683   [(set_attr "length" "2,2,2,2,2,2,2,4,4")]
684 )
685
686 ;; Reloading and elimination of the frame pointer can
687 ;; sometimes cause this optimization to be missed.
688 (define_peephole2
689   [(set (match_operand:SI 0 "arm_general_register_operand" "")
690         (match_operand:SI 1 "const_int_operand" ""))
691    (set (match_dup 0)
692         (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
693   "TARGET_THUMB1
694    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
695    && (INTVAL (operands[1]) & 3) == 0"
696   [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
697   ""
698 )
699
700 (define_insn "*addsi3_compare0"
701   [(set (reg:CC_NOOV CC_REGNUM)
702         (compare:CC_NOOV
703          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
704                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
705          (const_int 0)))
706    (set (match_operand:SI 0 "s_register_operand" "=r,r")
707         (plus:SI (match_dup 1) (match_dup 2)))]
708   "TARGET_ARM"
709   "@
710    add%.\\t%0, %1, %2
711    sub%.\\t%0, %1, #%n2"
712   [(set_attr "conds" "set")]
713 )
714
715 (define_insn "*addsi3_compare0_scratch"
716   [(set (reg:CC_NOOV CC_REGNUM)
717         (compare:CC_NOOV
718          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
719                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
720          (const_int 0)))]
721   "TARGET_ARM"
722   "@
723    cmn%?\\t%0, %1
724    cmp%?\\t%0, #%n1"
725   [(set_attr "conds" "set")]
726 )
727
728 (define_insn "*compare_negsi_si"
729   [(set (reg:CC_Z CC_REGNUM)
730         (compare:CC_Z
731          (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
732          (match_operand:SI 1 "s_register_operand" "r")))]
733   "TARGET_32BIT"
734   "cmn%?\\t%1, %0"
735   [(set_attr "conds" "set")]
736 )
737
738 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
739 ;; addend is a constant.
740 (define_insn "*cmpsi2_addneg"
741   [(set (reg:CC CC_REGNUM)
742         (compare:CC
743          (match_operand:SI 1 "s_register_operand" "r,r")
744          (match_operand:SI 2 "arm_addimm_operand" "L,I")))
745    (set (match_operand:SI 0 "s_register_operand" "=r,r")
746         (plus:SI (match_dup 1)
747                  (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
748   "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
749   "@
750    add%.\\t%0, %1, %3
751    sub%.\\t%0, %1, #%n3"
752   [(set_attr "conds" "set")]
753 )
754
755 ;; Convert the sequence
756 ;;  sub  rd, rn, #1
757 ;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
758 ;;  bne  dest
759 ;; into
760 ;;  subs rd, rn, #1
761 ;;  bcs  dest   ((unsigned)rn >= 1)
762 ;; similarly for the beq variant using bcc.
763 ;; This is a common looping idiom (while (n--))
764 (define_peephole2
765   [(set (match_operand:SI 0 "arm_general_register_operand" "")
766         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
767                  (const_int -1)))
768    (set (match_operand 2 "cc_register" "")
769         (compare (match_dup 0) (const_int -1)))
770    (set (pc)
771         (if_then_else (match_operator 3 "equality_operator"
772                        [(match_dup 2) (const_int 0)])
773                       (match_operand 4 "" "")
774                       (match_operand 5 "" "")))]
775   "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
776   [(parallel[
777     (set (match_dup 2)
778          (compare:CC
779           (match_dup 1) (const_int 1)))
780     (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
781    (set (pc)
782         (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
783                       (match_dup 4)
784                       (match_dup 5)))]
785   "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
786    operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
787                                   ? GEU : LTU),
788                                  VOIDmode, 
789                                  operands[2], const0_rtx);"
790 )
791
792 ;; The next four insns work because they compare the result with one of
793 ;; the operands, and we know that the use of the condition code is
794 ;; either GEU or LTU, so we can use the carry flag from the addition
795 ;; instead of doing the compare a second time.
796 (define_insn "*addsi3_compare_op1"
797   [(set (reg:CC_C CC_REGNUM)
798         (compare:CC_C
799          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
800                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
801          (match_dup 1)))
802    (set (match_operand:SI 0 "s_register_operand" "=r,r")
803         (plus:SI (match_dup 1) (match_dup 2)))]
804   "TARGET_32BIT"
805   "@
806    add%.\\t%0, %1, %2
807    sub%.\\t%0, %1, #%n2"
808   [(set_attr "conds" "set")]
809 )
810
811 (define_insn "*addsi3_compare_op2"
812   [(set (reg:CC_C CC_REGNUM)
813         (compare:CC_C
814          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
815                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
816          (match_dup 2)))
817    (set (match_operand:SI 0 "s_register_operand" "=r,r")
818         (plus:SI (match_dup 1) (match_dup 2)))]
819   "TARGET_32BIT"
820   "@
821    add%.\\t%0, %1, %2
822    sub%.\\t%0, %1, #%n2"
823   [(set_attr "conds" "set")]
824 )
825
826 (define_insn "*compare_addsi2_op0"
827   [(set (reg:CC_C CC_REGNUM)
828         (compare:CC_C
829          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
830                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
831          (match_dup 0)))]
832   "TARGET_32BIT"
833   "@
834    cmn%?\\t%0, %1
835    cmp%?\\t%0, #%n1"
836   [(set_attr "conds" "set")]
837 )
838
839 (define_insn "*compare_addsi2_op1"
840   [(set (reg:CC_C CC_REGNUM)
841         (compare:CC_C
842          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
843                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
844          (match_dup 1)))]
845   "TARGET_32BIT"
846   "@
847    cmn%?\\t%0, %1
848    cmp%?\\t%0, #%n1"
849   [(set_attr "conds" "set")]
850 )
851
852 (define_code_iterator LTUGEU [ltu geu])
853 (define_code_attr cnb [(ltu "CC_C") (geu "CC")])
854 (define_code_attr optab [(ltu "ltu") (geu "geu")])
855
856 (define_insn "*addsi3_carryin_<optab>"
857   [(set (match_operand:SI 0 "s_register_operand" "=r")
858         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
859                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
860                  (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
861   "TARGET_32BIT"
862   "adc%?\\t%0, %1, %2"
863   [(set_attr "conds" "use")]
864 )
865
866 (define_insn "*addsi3_carryin_alt2_<optab>"
867   [(set (match_operand:SI 0 "s_register_operand" "=r")
868         (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
869                           (match_operand:SI 1 "s_register_operand" "%r"))
870                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
871   "TARGET_32BIT"
872   "adc%?\\t%0, %1, %2"
873   [(set_attr "conds" "use")]
874 )
875
876 (define_insn "*addsi3_carryin_shift_<optab>"
877   [(set (match_operand:SI 0 "s_register_operand" "=r")
878         (plus:SI (plus:SI
879                   (match_operator:SI 2 "shift_operator"
880                     [(match_operand:SI 3 "s_register_operand" "r")
881                      (match_operand:SI 4 "reg_or_int_operand" "rM")])
882                   (match_operand:SI 1 "s_register_operand" "r"))
883                  (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
884   "TARGET_32BIT"
885   "adc%?\\t%0, %1, %3%S2"
886   [(set_attr "conds" "use")
887    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
888                       (const_string "alu_shift")
889                       (const_string "alu_shift_reg")))]
890 )
891
892 (define_expand "incscc"
893   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
894         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
895                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
896                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
897   "TARGET_32BIT"
898   ""
899 )
900
901 (define_insn "*arm_incscc"
902   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
903         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
904                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
905                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
906   "TARGET_ARM"
907   "@
908   add%d2\\t%0, %1, #1
909   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
910   [(set_attr "conds" "use")
911    (set_attr "length" "4,8")]
912 )
913
914 ; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
915 (define_split
916   [(set (match_operand:SI 0 "s_register_operand" "")
917         (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
918                             (match_operand:SI 2 "s_register_operand" ""))
919                  (const_int -1)))
920    (clobber (match_operand:SI 3 "s_register_operand" ""))]
921   "TARGET_32BIT"
922   [(set (match_dup 3) (match_dup 1))
923    (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
924   "
925   operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
926 ")
927
928 (define_expand "addsf3"
929   [(set (match_operand:SF          0 "s_register_operand" "")
930         (plus:SF (match_operand:SF 1 "s_register_operand" "")
931                  (match_operand:SF 2 "arm_float_add_operand" "")))]
932   "TARGET_32BIT && TARGET_HARD_FLOAT"
933   "
934   if (TARGET_MAVERICK
935       && !cirrus_fp_register (operands[2], SFmode))
936     operands[2] = force_reg (SFmode, operands[2]);
937 ")
938
939 (define_expand "adddf3"
940   [(set (match_operand:DF          0 "s_register_operand" "")
941         (plus:DF (match_operand:DF 1 "s_register_operand" "")
942                  (match_operand:DF 2 "arm_float_add_operand" "")))]
943   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
944   "
945   if (TARGET_MAVERICK
946       && !cirrus_fp_register (operands[2], DFmode))
947     operands[2] = force_reg (DFmode, operands[2]);
948 ")
949
950 (define_expand "subdi3"
951  [(parallel
952    [(set (match_operand:DI            0 "s_register_operand" "")
953           (minus:DI (match_operand:DI 1 "s_register_operand" "")
954                     (match_operand:DI 2 "s_register_operand" "")))
955     (clobber (reg:CC CC_REGNUM))])]
956   "TARGET_EITHER"
957   "
958   if (TARGET_HARD_FLOAT && TARGET_MAVERICK
959       && TARGET_32BIT
960       && cirrus_fp_register (operands[0], DImode)
961       && cirrus_fp_register (operands[1], DImode))
962     {
963       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
964       DONE;
965     }
966
967   if (TARGET_THUMB1)
968     {
969       if (GET_CODE (operands[1]) != REG)
970         operands[1] = force_reg (DImode, operands[1]);
971       if (GET_CODE (operands[2]) != REG)
972         operands[2] = force_reg (DImode, operands[2]);
973      }  
974   "
975 )
976
977 (define_insn "*arm_subdi3"
978   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
979         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
980                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
981    (clobber (reg:CC CC_REGNUM))]
982   "TARGET_32BIT && !TARGET_NEON"
983   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
984   [(set_attr "conds" "clob")
985    (set_attr "length" "8")]
986 )
987
988 (define_insn "*thumb_subdi3"
989   [(set (match_operand:DI           0 "register_operand" "=l")
990         (minus:DI (match_operand:DI 1 "register_operand"  "0")
991                   (match_operand:DI 2 "register_operand"  "l")))
992    (clobber (reg:CC CC_REGNUM))]
993   "TARGET_THUMB1"
994   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
995   [(set_attr "length" "4")]
996 )
997
998 (define_insn "*subdi_di_zesidi"
999   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
1000         (minus:DI (match_operand:DI 1 "s_register_operand"  "0,r")
1001                   (zero_extend:DI
1002                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
1003    (clobber (reg:CC CC_REGNUM))]
1004   "TARGET_32BIT"
1005   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
1006   [(set_attr "conds" "clob")
1007    (set_attr "length" "8")]
1008 )
1009
1010 (define_insn "*subdi_di_sesidi"
1011   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
1012         (minus:DI (match_operand:DI  1 "s_register_operand"  "0,r")
1013                   (sign_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, %2, asr #31"
1018   [(set_attr "conds" "clob")
1019    (set_attr "length" "8")]
1020 )
1021
1022 (define_insn "*subdi_zesidi_di"
1023   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
1024         (minus:DI (zero_extend:DI
1025                    (match_operand:SI 2 "s_register_operand"  "r,r"))
1026                   (match_operand:DI  1 "s_register_operand" "0,r")))
1027    (clobber (reg:CC CC_REGNUM))]
1028   "TARGET_ARM"
1029   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
1030   [(set_attr "conds" "clob")
1031    (set_attr "length" "8")]
1032 )
1033
1034 (define_insn "*subdi_sesidi_di"
1035   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
1036         (minus:DI (sign_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, %2, asr #31"
1042   [(set_attr "conds" "clob")
1043    (set_attr "length" "8")]
1044 )
1045
1046 (define_insn "*subdi_zesidi_zesidi"
1047   [(set (match_operand:DI            0 "s_register_operand" "=r")
1048         (minus:DI (zero_extend:DI
1049                    (match_operand:SI 1 "s_register_operand"  "r"))
1050                   (zero_extend:DI
1051                    (match_operand:SI 2 "s_register_operand"  "r"))))
1052    (clobber (reg:CC CC_REGNUM))]
1053   "TARGET_32BIT"
1054   "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
1055   [(set_attr "conds" "clob")
1056    (set_attr "length" "8")]
1057 )
1058
1059 (define_expand "subsi3"
1060   [(set (match_operand:SI           0 "s_register_operand" "")
1061         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1062                   (match_operand:SI 2 "s_register_operand" "")))]
1063   "TARGET_EITHER"
1064   "
1065   if (GET_CODE (operands[1]) == CONST_INT)
1066     {
1067       if (TARGET_32BIT)
1068         {
1069           arm_split_constant (MINUS, SImode, NULL_RTX,
1070                               INTVAL (operands[1]), operands[0],
1071                               operands[2], optimize && can_create_pseudo_p ());
1072           DONE;
1073         }
1074       else /* TARGET_THUMB1 */
1075         operands[1] = force_reg (SImode, operands[1]);
1076     }
1077   "
1078 )
1079
1080 (define_insn "*thumb1_subsi3_insn"
1081   [(set (match_operand:SI           0 "register_operand" "=l")
1082         (minus:SI (match_operand:SI 1 "register_operand" "l")
1083                   (match_operand:SI 2 "register_operand" "l")))]
1084   "TARGET_THUMB1"
1085   "sub\\t%0, %1, %2"
1086   [(set_attr "length" "2")]
1087 )
1088
1089 ; ??? Check Thumb-2 split length
1090 (define_insn_and_split "*arm_subsi3_insn"
1091   [(set (match_operand:SI           0 "s_register_operand" "=r,r,rk,r,r")
1092         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,r,!k,?n,r")
1093                   (match_operand:SI 2 "reg_or_int_operand" "r,rI, r, r,?n")))]
1094   "TARGET_32BIT"
1095   "@
1096    rsb%?\\t%0, %2, %1
1097    sub%?\\t%0, %1, %2
1098    sub%?\\t%0, %1, %2
1099    #
1100    #"
1101   "&& ((GET_CODE (operands[1]) == CONST_INT
1102         && !const_ok_for_arm (INTVAL (operands[1])))
1103        || (GET_CODE (operands[2]) == CONST_INT
1104            && !const_ok_for_arm (INTVAL (operands[2]))))"
1105   [(clobber (const_int 0))]
1106   "
1107   arm_split_constant (MINUS, SImode, curr_insn,
1108                       INTVAL (operands[1]), operands[0], operands[2], 0);
1109   DONE;
1110   "
1111   [(set_attr "length" "4,4,4,16,16")
1112    (set_attr "predicable" "yes")]
1113 )
1114
1115 (define_peephole2
1116   [(match_scratch:SI 3 "r")
1117    (set (match_operand:SI 0 "arm_general_register_operand" "")
1118         (minus:SI (match_operand:SI 1 "const_int_operand" "")
1119                   (match_operand:SI 2 "arm_general_register_operand" "")))]
1120   "TARGET_32BIT
1121    && !const_ok_for_arm (INTVAL (operands[1]))
1122    && const_ok_for_arm (~INTVAL (operands[1]))"
1123   [(set (match_dup 3) (match_dup 1))
1124    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1125   ""
1126 )
1127
1128 (define_insn "*subsi3_compare0"
1129   [(set (reg:CC_NOOV CC_REGNUM)
1130         (compare:CC_NOOV
1131          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1132                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1133          (const_int 0)))
1134    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1135         (minus:SI (match_dup 1) (match_dup 2)))]
1136   "TARGET_32BIT"
1137   "@
1138    sub%.\\t%0, %1, %2
1139    rsb%.\\t%0, %2, %1"
1140   [(set_attr "conds" "set")]
1141 )
1142
1143 (define_insn "*subsi3_compare"
1144   [(set (reg:CC CC_REGNUM)
1145         (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,I")
1146                     (match_operand:SI 2 "arm_rhs_operand" "rI,r")))
1147    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1148         (minus:SI (match_dup 1) (match_dup 2)))]
1149   "TARGET_32BIT"
1150   "@
1151    sub%.\\t%0, %1, %2
1152    rsb%.\\t%0, %2, %1"
1153   [(set_attr "conds" "set")]
1154 )
1155
1156 (define_expand "decscc"
1157   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1158         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1159                   (match_operator:SI 2 "arm_comparison_operator"
1160                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1161   "TARGET_32BIT"
1162   ""
1163 )
1164
1165 (define_insn "*arm_decscc"
1166   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1167         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1168                   (match_operator:SI 2 "arm_comparison_operator"
1169                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1170   "TARGET_ARM"
1171   "@
1172    sub%d2\\t%0, %1, #1
1173    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1174   [(set_attr "conds" "use")
1175    (set_attr "length" "*,8")]
1176 )
1177
1178 (define_expand "subsf3"
1179   [(set (match_operand:SF           0 "s_register_operand" "")
1180         (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1181                   (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1182   "TARGET_32BIT && TARGET_HARD_FLOAT"
1183   "
1184   if (TARGET_MAVERICK)
1185     {
1186       if (!cirrus_fp_register (operands[1], SFmode))
1187         operands[1] = force_reg (SFmode, operands[1]);
1188       if (!cirrus_fp_register (operands[2], SFmode))
1189         operands[2] = force_reg (SFmode, operands[2]);
1190     }
1191 ")
1192
1193 (define_expand "subdf3"
1194   [(set (match_operand:DF           0 "s_register_operand" "")
1195         (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1196                   (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1197   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
1198   "
1199   if (TARGET_MAVERICK)
1200     {
1201        if (!cirrus_fp_register (operands[1], DFmode))
1202          operands[1] = force_reg (DFmode, operands[1]);
1203        if (!cirrus_fp_register (operands[2], DFmode))
1204          operands[2] = force_reg (DFmode, operands[2]);
1205     }
1206 ")
1207
1208 \f
1209 ;; Multiplication insns
1210
1211 (define_expand "mulsi3"
1212   [(set (match_operand:SI          0 "s_register_operand" "")
1213         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1214                  (match_operand:SI 1 "s_register_operand" "")))]
1215   "TARGET_EITHER"
1216   ""
1217 )
1218
1219 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1220 (define_insn "*arm_mulsi3"
1221   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1222         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1223                  (match_operand:SI 1 "s_register_operand" "%0,r")))]
1224   "TARGET_32BIT && !arm_arch6"
1225   "mul%?\\t%0, %2, %1"
1226   [(set_attr "insn" "mul")
1227    (set_attr "predicable" "yes")]
1228 )
1229
1230 (define_insn "*arm_mulsi3_v6"
1231   [(set (match_operand:SI          0 "s_register_operand" "=r")
1232         (mult:SI (match_operand:SI 1 "s_register_operand" "r")
1233                  (match_operand:SI 2 "s_register_operand" "r")))]
1234   "TARGET_32BIT && arm_arch6"
1235   "mul%?\\t%0, %1, %2"
1236   [(set_attr "insn" "mul")
1237    (set_attr "predicable" "yes")]
1238 )
1239
1240 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1241 ; 1 and 2; are the same, because reload will make operand 0 match 
1242 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1243 ; this by adding another alternative to match this case, and then `reload' 
1244 ; it ourselves.  This alternative must come first.
1245 (define_insn "*thumb_mulsi3"
1246   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1247         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1248                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1249   "TARGET_THUMB1 && !arm_arch6"
1250   "*
1251   if (which_alternative < 2)
1252     return \"mov\\t%0, %1\;mul\\t%0, %2\";
1253   else
1254     return \"mul\\t%0, %2\";
1255   "
1256   [(set_attr "length" "4,4,2")
1257    (set_attr "insn" "mul")]
1258 )
1259
1260 (define_insn "*thumb_mulsi3_v6"
1261   [(set (match_operand:SI          0 "register_operand" "=l,l,l")
1262         (mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
1263                  (match_operand:SI 2 "register_operand" "l,0,0")))]
1264   "TARGET_THUMB1 && arm_arch6"
1265   "@
1266    mul\\t%0, %2
1267    mul\\t%0, %1
1268    mul\\t%0, %1"
1269   [(set_attr "length" "2")
1270    (set_attr "insn" "mul")]
1271 )
1272
1273 (define_insn "*mulsi3_compare0"
1274   [(set (reg:CC_NOOV CC_REGNUM)
1275         (compare:CC_NOOV (mult:SI
1276                           (match_operand:SI 2 "s_register_operand" "r,r")
1277                           (match_operand:SI 1 "s_register_operand" "%0,r"))
1278                          (const_int 0)))
1279    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1280         (mult:SI (match_dup 2) (match_dup 1)))]
1281   "TARGET_ARM && !arm_arch6"
1282   "mul%.\\t%0, %2, %1"
1283   [(set_attr "conds" "set")
1284    (set_attr "insn" "muls")]
1285 )
1286
1287 (define_insn "*mulsi3_compare0_v6"
1288   [(set (reg:CC_NOOV CC_REGNUM)
1289         (compare:CC_NOOV (mult:SI
1290                           (match_operand:SI 2 "s_register_operand" "r")
1291                           (match_operand:SI 1 "s_register_operand" "r"))
1292                          (const_int 0)))
1293    (set (match_operand:SI 0 "s_register_operand" "=r")
1294         (mult:SI (match_dup 2) (match_dup 1)))]
1295   "TARGET_ARM && arm_arch6 && optimize_size"
1296   "mul%.\\t%0, %2, %1"
1297   [(set_attr "conds" "set")
1298    (set_attr "insn" "muls")]
1299 )
1300
1301 (define_insn "*mulsi_compare0_scratch"
1302   [(set (reg:CC_NOOV CC_REGNUM)
1303         (compare:CC_NOOV (mult:SI
1304                           (match_operand:SI 2 "s_register_operand" "r,r")
1305                           (match_operand:SI 1 "s_register_operand" "%0,r"))
1306                          (const_int 0)))
1307    (clobber (match_scratch:SI 0 "=&r,&r"))]
1308   "TARGET_ARM && !arm_arch6"
1309   "mul%.\\t%0, %2, %1"
1310   [(set_attr "conds" "set")
1311    (set_attr "insn" "muls")]
1312 )
1313
1314 (define_insn "*mulsi_compare0_scratch_v6"
1315   [(set (reg:CC_NOOV CC_REGNUM)
1316         (compare:CC_NOOV (mult:SI
1317                           (match_operand:SI 2 "s_register_operand" "r")
1318                           (match_operand:SI 1 "s_register_operand" "r"))
1319                          (const_int 0)))
1320    (clobber (match_scratch:SI 0 "=r"))]
1321   "TARGET_ARM && arm_arch6 && optimize_size"
1322   "mul%.\\t%0, %2, %1"
1323   [(set_attr "conds" "set")
1324    (set_attr "insn" "muls")]
1325 )
1326
1327 ;; Unnamed templates to match MLA instruction.
1328
1329 (define_insn "*mulsi3addsi"
1330   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1331         (plus:SI
1332           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1333                    (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1334           (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
1335   "TARGET_32BIT && !arm_arch6"
1336   "mla%?\\t%0, %2, %1, %3"
1337   [(set_attr "insn" "mla")
1338    (set_attr "predicable" "yes")]
1339 )
1340
1341 (define_insn "*mulsi3addsi_v6"
1342   [(set (match_operand:SI 0 "s_register_operand" "=r")
1343         (plus:SI
1344           (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1345                    (match_operand:SI 1 "s_register_operand" "r"))
1346           (match_operand:SI 3 "s_register_operand" "r")))]
1347   "TARGET_32BIT && arm_arch6"
1348   "mla%?\\t%0, %2, %1, %3"
1349   [(set_attr "insn" "mla")
1350    (set_attr "predicable" "yes")]
1351 )
1352
1353 (define_insn "*mulsi3addsi_compare0"
1354   [(set (reg:CC_NOOV CC_REGNUM)
1355         (compare:CC_NOOV
1356          (plus:SI (mult:SI
1357                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1358                    (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1359                   (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
1360          (const_int 0)))
1361    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1362         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1363                  (match_dup 3)))]
1364   "TARGET_ARM && arm_arch6"
1365   "mla%.\\t%0, %2, %1, %3"
1366   [(set_attr "conds" "set")
1367    (set_attr "insn" "mlas")]
1368 )
1369
1370 (define_insn "*mulsi3addsi_compare0_v6"
1371   [(set (reg:CC_NOOV CC_REGNUM)
1372         (compare:CC_NOOV
1373          (plus:SI (mult:SI
1374                    (match_operand:SI 2 "s_register_operand" "r")
1375                    (match_operand:SI 1 "s_register_operand" "r"))
1376                   (match_operand:SI 3 "s_register_operand" "r"))
1377          (const_int 0)))
1378    (set (match_operand:SI 0 "s_register_operand" "=r")
1379         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1380                  (match_dup 3)))]
1381   "TARGET_ARM && arm_arch6 && optimize_size"
1382   "mla%.\\t%0, %2, %1, %3"
1383   [(set_attr "conds" "set")
1384    (set_attr "insn" "mlas")]
1385 )
1386
1387 (define_insn "*mulsi3addsi_compare0_scratch"
1388   [(set (reg:CC_NOOV CC_REGNUM)
1389         (compare:CC_NOOV
1390          (plus:SI (mult:SI
1391                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1392                    (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1393                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1394          (const_int 0)))
1395    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1396   "TARGET_ARM && !arm_arch6"
1397   "mla%.\\t%0, %2, %1, %3"
1398   [(set_attr "conds" "set")
1399    (set_attr "insn" "mlas")]
1400 )
1401
1402 (define_insn "*mulsi3addsi_compare0_scratch_v6"
1403   [(set (reg:CC_NOOV CC_REGNUM)
1404         (compare:CC_NOOV
1405          (plus:SI (mult:SI
1406                    (match_operand:SI 2 "s_register_operand" "r")
1407                    (match_operand:SI 1 "s_register_operand" "r"))
1408                   (match_operand:SI 3 "s_register_operand" "r"))
1409          (const_int 0)))
1410    (clobber (match_scratch:SI 0 "=r"))]
1411   "TARGET_ARM && arm_arch6 && optimize_size"
1412   "mla%.\\t%0, %2, %1, %3"
1413   [(set_attr "conds" "set")
1414    (set_attr "insn" "mlas")]
1415 )
1416
1417 (define_insn "*mulsi3subsi"
1418   [(set (match_operand:SI 0 "s_register_operand" "=r")
1419         (minus:SI
1420           (match_operand:SI 3 "s_register_operand" "r")
1421           (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1422                    (match_operand:SI 1 "s_register_operand" "r"))))]
1423   "TARGET_32BIT && arm_arch_thumb2"
1424   "mls%?\\t%0, %2, %1, %3"
1425   [(set_attr "insn" "mla")
1426    (set_attr "predicable" "yes")]
1427 )
1428
1429 (define_expand "maddsidi4"
1430   [(set (match_operand:DI 0 "s_register_operand" "")
1431         (plus:DI
1432          (mult:DI
1433           (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1434           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1435          (match_operand:DI 3 "s_register_operand" "")))]
1436   "TARGET_32BIT && arm_arch3m"
1437   "")
1438
1439 (define_insn "*mulsidi3adddi"
1440   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1441         (plus:DI
1442          (mult:DI
1443           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1444           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1445          (match_operand:DI 1 "s_register_operand" "0")))]
1446   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1447   "smlal%?\\t%Q0, %R0, %3, %2"
1448   [(set_attr "insn" "smlal")
1449    (set_attr "predicable" "yes")]
1450 )
1451
1452 (define_insn "*mulsidi3adddi_v6"
1453   [(set (match_operand:DI 0 "s_register_operand" "=r")
1454         (plus:DI
1455          (mult:DI
1456           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1457           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1458          (match_operand:DI 1 "s_register_operand" "0")))]
1459   "TARGET_32BIT && arm_arch6"
1460   "smlal%?\\t%Q0, %R0, %3, %2"
1461   [(set_attr "insn" "smlal")
1462    (set_attr "predicable" "yes")]
1463 )
1464
1465 ;; 32x32->64 widening multiply.
1466 ;; As with mulsi3, the only difference between the v3-5 and v6+
1467 ;; versions of these patterns is the requirement that the output not
1468 ;; overlap the inputs, but that still means we have to have a named
1469 ;; expander and two different starred insns.
1470
1471 (define_expand "mulsidi3"
1472   [(set (match_operand:DI 0 "s_register_operand" "")
1473         (mult:DI
1474          (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1475          (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1476   "TARGET_32BIT && arm_arch3m"
1477   ""
1478 )
1479
1480 (define_insn "*mulsidi3_nov6"
1481   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1482         (mult:DI
1483          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1484          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1485   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1486   "smull%?\\t%Q0, %R0, %1, %2"
1487   [(set_attr "insn" "smull")
1488    (set_attr "predicable" "yes")]
1489 )
1490
1491 (define_insn "*mulsidi3_v6"
1492   [(set (match_operand:DI 0 "s_register_operand" "=r")
1493         (mult:DI
1494          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1495          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1496   "TARGET_32BIT && arm_arch6"
1497   "smull%?\\t%Q0, %R0, %1, %2"
1498   [(set_attr "insn" "smull")
1499    (set_attr "predicable" "yes")]
1500 )
1501
1502 (define_expand "umulsidi3"
1503   [(set (match_operand:DI 0 "s_register_operand" "")
1504         (mult:DI
1505          (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1506          (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1507   "TARGET_32BIT && arm_arch3m"
1508   ""
1509 )
1510
1511 (define_insn "*umulsidi3_nov6"
1512   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1513         (mult:DI
1514          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1515          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1516   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1517   "umull%?\\t%Q0, %R0, %1, %2"
1518   [(set_attr "insn" "umull")
1519    (set_attr "predicable" "yes")]
1520 )
1521
1522 (define_insn "*umulsidi3_v6"
1523   [(set (match_operand:DI 0 "s_register_operand" "=r")
1524         (mult:DI
1525          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1526          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1527   "TARGET_32BIT && arm_arch6"
1528   "umull%?\\t%Q0, %R0, %1, %2"
1529   [(set_attr "insn" "umull")
1530    (set_attr "predicable" "yes")]
1531 )
1532
1533 (define_expand "umaddsidi4"
1534   [(set (match_operand:DI 0 "s_register_operand" "")
1535         (plus:DI
1536          (mult:DI
1537           (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1538           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1539          (match_operand:DI 3 "s_register_operand" "")))]
1540   "TARGET_32BIT && arm_arch3m"
1541   "")
1542
1543 (define_insn "*umulsidi3adddi"
1544   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1545         (plus:DI
1546          (mult:DI
1547           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1548           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1549          (match_operand:DI 1 "s_register_operand" "0")))]
1550   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1551   "umlal%?\\t%Q0, %R0, %3, %2"
1552   [(set_attr "insn" "umlal")
1553    (set_attr "predicable" "yes")]
1554 )
1555
1556 (define_insn "*umulsidi3adddi_v6"
1557   [(set (match_operand:DI 0 "s_register_operand" "=r")
1558         (plus:DI
1559          (mult:DI
1560           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1561           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1562          (match_operand:DI 1 "s_register_operand" "0")))]
1563   "TARGET_32BIT && arm_arch6"
1564   "umlal%?\\t%Q0, %R0, %3, %2"
1565   [(set_attr "insn" "umlal")
1566    (set_attr "predicable" "yes")]
1567 )
1568
1569 (define_expand "smulsi3_highpart"
1570   [(parallel
1571     [(set (match_operand:SI 0 "s_register_operand" "")
1572           (truncate:SI
1573            (lshiftrt:DI
1574             (mult:DI
1575              (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1576              (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1577             (const_int 32))))
1578      (clobber (match_scratch:SI 3 ""))])]
1579   "TARGET_32BIT && arm_arch3m"
1580   ""
1581 )
1582
1583 (define_insn "*smulsi3_highpart_nov6"
1584   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1585         (truncate:SI
1586          (lshiftrt:DI
1587           (mult:DI
1588            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
1589            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1590           (const_int 32))))
1591    (clobber (match_scratch:SI 3 "=&r,&r"))]
1592   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1593   "smull%?\\t%3, %0, %2, %1"
1594   [(set_attr "insn" "smull")
1595    (set_attr "predicable" "yes")]
1596 )
1597
1598 (define_insn "*smulsi3_highpart_v6"
1599   [(set (match_operand:SI 0 "s_register_operand" "=r")
1600         (truncate:SI
1601          (lshiftrt:DI
1602           (mult:DI
1603            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1604            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1605           (const_int 32))))
1606    (clobber (match_scratch:SI 3 "=r"))]
1607   "TARGET_32BIT && arm_arch6"
1608   "smull%?\\t%3, %0, %2, %1"
1609   [(set_attr "insn" "smull")
1610    (set_attr "predicable" "yes")]
1611 )
1612
1613 (define_expand "umulsi3_highpart"
1614   [(parallel
1615     [(set (match_operand:SI 0 "s_register_operand" "")
1616           (truncate:SI
1617            (lshiftrt:DI
1618             (mult:DI
1619              (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1620               (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1621             (const_int 32))))
1622      (clobber (match_scratch:SI 3 ""))])]
1623   "TARGET_32BIT && arm_arch3m"
1624   ""
1625 )
1626
1627 (define_insn "*umulsi3_highpart_nov6"
1628   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1629         (truncate:SI
1630          (lshiftrt:DI
1631           (mult:DI
1632            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
1633            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1634           (const_int 32))))
1635    (clobber (match_scratch:SI 3 "=&r,&r"))]
1636   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1637   "umull%?\\t%3, %0, %2, %1"
1638   [(set_attr "insn" "umull")
1639    (set_attr "predicable" "yes")]
1640 )
1641
1642 (define_insn "*umulsi3_highpart_v6"
1643   [(set (match_operand:SI 0 "s_register_operand" "=r")
1644         (truncate:SI
1645          (lshiftrt:DI
1646           (mult:DI
1647            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1648            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1649           (const_int 32))))
1650    (clobber (match_scratch:SI 3 "=r"))]
1651   "TARGET_32BIT && arm_arch6"
1652   "umull%?\\t%3, %0, %2, %1"
1653   [(set_attr "insn" "umull")
1654    (set_attr "predicable" "yes")]
1655 )
1656
1657 (define_insn "mulhisi3"
1658   [(set (match_operand:SI 0 "s_register_operand" "=r")
1659         (mult:SI (sign_extend:SI
1660                   (match_operand:HI 1 "s_register_operand" "%r"))
1661                  (sign_extend:SI
1662                   (match_operand:HI 2 "s_register_operand" "r"))))]
1663   "TARGET_DSP_MULTIPLY"
1664   "smulbb%?\\t%0, %1, %2"
1665   [(set_attr "insn" "smulxy")
1666    (set_attr "predicable" "yes")]
1667 )
1668
1669 (define_insn "*mulhisi3tb"
1670   [(set (match_operand:SI 0 "s_register_operand" "=r")
1671         (mult:SI (ashiftrt:SI
1672                   (match_operand:SI 1 "s_register_operand" "r")
1673                   (const_int 16))
1674                  (sign_extend:SI
1675                   (match_operand:HI 2 "s_register_operand" "r"))))]
1676   "TARGET_DSP_MULTIPLY"
1677   "smultb%?\\t%0, %1, %2"
1678   [(set_attr "insn" "smulxy")
1679    (set_attr "predicable" "yes")]
1680 )
1681
1682 (define_insn "*mulhisi3bt"
1683   [(set (match_operand:SI 0 "s_register_operand" "=r")
1684         (mult:SI (sign_extend:SI
1685                   (match_operand:HI 1 "s_register_operand" "r"))
1686                  (ashiftrt:SI
1687                   (match_operand:SI 2 "s_register_operand" "r")
1688                   (const_int 16))))]
1689   "TARGET_DSP_MULTIPLY"
1690   "smulbt%?\\t%0, %1, %2"
1691   [(set_attr "insn" "smulxy")
1692    (set_attr "predicable" "yes")]
1693 )
1694
1695 (define_insn "*mulhisi3tt"
1696   [(set (match_operand:SI 0 "s_register_operand" "=r")
1697         (mult:SI (ashiftrt:SI
1698                   (match_operand:SI 1 "s_register_operand" "r")
1699                   (const_int 16))
1700                  (ashiftrt:SI
1701                   (match_operand:SI 2 "s_register_operand" "r")
1702                   (const_int 16))))]
1703   "TARGET_DSP_MULTIPLY"
1704   "smultt%?\\t%0, %1, %2"
1705   [(set_attr "insn" "smulxy")
1706    (set_attr "predicable" "yes")]
1707 )
1708
1709 (define_insn "maddhisi4"
1710   [(set (match_operand:SI 0 "s_register_operand" "=r")
1711         (plus:SI (match_operand:SI 3 "s_register_operand" "r")
1712                  (mult:SI (sign_extend:SI
1713                            (match_operand:HI 1 "s_register_operand" "%r"))
1714                           (sign_extend:SI
1715                            (match_operand:HI 2 "s_register_operand" "r")))))]
1716   "TARGET_DSP_MULTIPLY"
1717   "smlabb%?\\t%0, %1, %2, %3"
1718   [(set_attr "insn" "smlaxy")
1719    (set_attr "predicable" "yes")]
1720 )
1721
1722 (define_insn "*maddhidi4"
1723   [(set (match_operand:DI 0 "s_register_operand" "=r")
1724         (plus:DI
1725           (match_operand:DI 3 "s_register_operand" "0")
1726           (mult:DI (sign_extend:DI
1727                     (match_operand:HI 1 "s_register_operand" "%r"))
1728                    (sign_extend:DI
1729                     (match_operand:HI 2 "s_register_operand" "r")))))]
1730   "TARGET_DSP_MULTIPLY"
1731   "smlalbb%?\\t%Q0, %R0, %1, %2"
1732   [(set_attr "insn" "smlalxy")
1733    (set_attr "predicable" "yes")])
1734
1735 (define_expand "mulsf3"
1736   [(set (match_operand:SF          0 "s_register_operand" "")
1737         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1738                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1739   "TARGET_32BIT && TARGET_HARD_FLOAT"
1740   "
1741   if (TARGET_MAVERICK
1742       && !cirrus_fp_register (operands[2], SFmode))
1743     operands[2] = force_reg (SFmode, operands[2]);
1744 ")
1745
1746 (define_expand "muldf3"
1747   [(set (match_operand:DF          0 "s_register_operand" "")
1748         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1749                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1750   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
1751   "
1752   if (TARGET_MAVERICK
1753       && !cirrus_fp_register (operands[2], DFmode))
1754     operands[2] = force_reg (DFmode, operands[2]);
1755 ")
1756 \f
1757 ;; Division insns
1758
1759 (define_expand "divsf3"
1760   [(set (match_operand:SF 0 "s_register_operand" "")
1761         (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1762                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1763   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1764   "")
1765
1766 (define_expand "divdf3"
1767   [(set (match_operand:DF 0 "s_register_operand" "")
1768         (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1769                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1770   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
1771   "")
1772 \f
1773 ;; Modulo insns
1774
1775 (define_expand "modsf3"
1776   [(set (match_operand:SF 0 "s_register_operand" "")
1777         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1778                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1779   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
1780   "")
1781
1782 (define_expand "moddf3"
1783   [(set (match_operand:DF 0 "s_register_operand" "")
1784         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1785                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1786   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
1787   "")
1788 \f
1789 ;; Boolean and,ior,xor insns
1790
1791 ;; Split up double word logical operations
1792
1793 ;; Split up simple DImode logical operations.  Simply perform the logical
1794 ;; operation on the upper and lower halves of the registers.
1795 (define_split
1796   [(set (match_operand:DI 0 "s_register_operand" "")
1797         (match_operator:DI 6 "logical_binary_operator"
1798           [(match_operand:DI 1 "s_register_operand" "")
1799            (match_operand:DI 2 "s_register_operand" "")]))]
1800   "TARGET_32BIT && reload_completed
1801    && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
1802    && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1803   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1804    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1805   "
1806   {
1807     operands[3] = gen_highpart (SImode, operands[0]);
1808     operands[0] = gen_lowpart (SImode, operands[0]);
1809     operands[4] = gen_highpart (SImode, operands[1]);
1810     operands[1] = gen_lowpart (SImode, operands[1]);
1811     operands[5] = gen_highpart (SImode, operands[2]);
1812     operands[2] = gen_lowpart (SImode, operands[2]);
1813   }"
1814 )
1815
1816 (define_split
1817   [(set (match_operand:DI 0 "s_register_operand" "")
1818         (match_operator:DI 6 "logical_binary_operator"
1819           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1820            (match_operand:DI 1 "s_register_operand" "")]))]
1821   "TARGET_32BIT && reload_completed"
1822   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1823    (set (match_dup 3) (match_op_dup:SI 6
1824                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1825                          (match_dup 4)]))]
1826   "
1827   {
1828     operands[3] = gen_highpart (SImode, operands[0]);
1829     operands[0] = gen_lowpart (SImode, operands[0]);
1830     operands[4] = gen_highpart (SImode, operands[1]);
1831     operands[1] = gen_lowpart (SImode, operands[1]);
1832     operands[5] = gen_highpart (SImode, operands[2]);
1833     operands[2] = gen_lowpart (SImode, operands[2]);
1834   }"
1835 )
1836
1837 ;; The zero extend of operand 2 means we can just copy the high part of
1838 ;; operand1 into operand0.
1839 (define_split
1840   [(set (match_operand:DI 0 "s_register_operand" "")
1841         (ior:DI
1842           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1843           (match_operand:DI 1 "s_register_operand" "")))]
1844   "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
1845   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1846    (set (match_dup 3) (match_dup 4))]
1847   "
1848   {
1849     operands[4] = gen_highpart (SImode, operands[1]);
1850     operands[3] = gen_highpart (SImode, operands[0]);
1851     operands[0] = gen_lowpart (SImode, operands[0]);
1852     operands[1] = gen_lowpart (SImode, operands[1]);
1853   }"
1854 )
1855
1856 ;; The zero extend of operand 2 means we can just copy the high part of
1857 ;; operand1 into operand0.
1858 (define_split
1859   [(set (match_operand:DI 0 "s_register_operand" "")
1860         (xor:DI
1861           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1862           (match_operand:DI 1 "s_register_operand" "")))]
1863   "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
1864   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1865    (set (match_dup 3) (match_dup 4))]
1866   "
1867   {
1868     operands[4] = gen_highpart (SImode, operands[1]);
1869     operands[3] = gen_highpart (SImode, operands[0]);
1870     operands[0] = gen_lowpart (SImode, operands[0]);
1871     operands[1] = gen_lowpart (SImode, operands[1]);
1872   }"
1873 )
1874
1875 (define_expand "anddi3"
1876   [(set (match_operand:DI         0 "s_register_operand" "")
1877         (and:DI (match_operand:DI 1 "s_register_operand" "")
1878                 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
1879   "TARGET_32BIT"
1880   ""
1881 )
1882
1883 (define_insn "*anddi3_insn"
1884   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1885         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1886                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1887   "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
1888   "#"
1889   [(set_attr "length" "8")]
1890 )
1891
1892 (define_insn_and_split "*anddi_zesidi_di"
1893   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1894         (and:DI (zero_extend:DI
1895                  (match_operand:SI 2 "s_register_operand" "r,r"))
1896                 (match_operand:DI 1 "s_register_operand" "0,r")))]
1897   "TARGET_32BIT"
1898   "#"
1899   "TARGET_32BIT && reload_completed"
1900   ; The zero extend of operand 2 clears the high word of the output
1901   ; operand.
1902   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1903    (set (match_dup 3) (const_int 0))]
1904   "
1905   {
1906     operands[3] = gen_highpart (SImode, operands[0]);
1907     operands[0] = gen_lowpart (SImode, operands[0]);
1908     operands[1] = gen_lowpart (SImode, operands[1]);
1909   }"
1910   [(set_attr "length" "8")]
1911 )
1912
1913 (define_insn "*anddi_sesdi_di"
1914   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1915         (and:DI (sign_extend:DI
1916                  (match_operand:SI 2 "s_register_operand" "r,r"))
1917                 (match_operand:DI  1 "s_register_operand" "0,r")))]
1918   "TARGET_32BIT"
1919   "#"
1920   [(set_attr "length" "8")]
1921 )
1922
1923 (define_expand "andsi3"
1924   [(set (match_operand:SI         0 "s_register_operand" "")
1925         (and:SI (match_operand:SI 1 "s_register_operand" "")
1926                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1927   "TARGET_EITHER"
1928   "
1929   if (TARGET_32BIT)
1930     {
1931       if (GET_CODE (operands[2]) == CONST_INT)
1932         {
1933           arm_split_constant (AND, SImode, NULL_RTX,
1934                               INTVAL (operands[2]), operands[0],
1935                               operands[1], optimize && can_create_pseudo_p ());
1936
1937           DONE;
1938         }
1939     }
1940   else /* TARGET_THUMB1 */
1941     {
1942       if (GET_CODE (operands[2]) != CONST_INT)
1943         {
1944           rtx tmp = force_reg (SImode, operands[2]);
1945           if (rtx_equal_p (operands[0], operands[1]))
1946             operands[2] = tmp;
1947           else
1948             {
1949               operands[2] = operands[1];
1950               operands[1] = tmp;
1951             }
1952         }
1953       else
1954         {
1955           int i;
1956           
1957           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1958             {
1959               operands[2] = force_reg (SImode,
1960                                        GEN_INT (~INTVAL (operands[2])));
1961               
1962               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1963               
1964               DONE;
1965             }
1966
1967           for (i = 9; i <= 31; i++)
1968             {
1969               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1970                 {
1971                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1972                                         const0_rtx));
1973                   DONE;
1974                 }
1975               else if ((((HOST_WIDE_INT) 1) << i) - 1
1976                        == ~INTVAL (operands[2]))
1977                 {
1978                   rtx shift = GEN_INT (i);
1979                   rtx reg = gen_reg_rtx (SImode);
1980                 
1981                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1982                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1983                   
1984                   DONE;
1985                 }
1986             }
1987
1988           operands[2] = force_reg (SImode, operands[2]);
1989         }
1990     }
1991   "
1992 )
1993
1994 ; ??? Check split length for Thumb-2
1995 (define_insn_and_split "*arm_andsi3_insn"
1996   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1997         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1998                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1999   "TARGET_32BIT"
2000   "@
2001    and%?\\t%0, %1, %2
2002    bic%?\\t%0, %1, #%B2
2003    #"
2004   "TARGET_32BIT
2005    && GET_CODE (operands[2]) == CONST_INT
2006    && !(const_ok_for_arm (INTVAL (operands[2]))
2007         || const_ok_for_arm (~INTVAL (operands[2])))"
2008   [(clobber (const_int 0))]
2009   "
2010   arm_split_constant  (AND, SImode, curr_insn, 
2011                        INTVAL (operands[2]), operands[0], operands[1], 0);
2012   DONE;
2013   "
2014   [(set_attr "length" "4,4,16")
2015    (set_attr "predicable" "yes")]
2016 )
2017
2018 (define_insn "*thumb1_andsi3_insn"
2019   [(set (match_operand:SI         0 "register_operand" "=l")
2020         (and:SI (match_operand:SI 1 "register_operand" "%0")
2021                 (match_operand:SI 2 "register_operand" "l")))]
2022   "TARGET_THUMB1"
2023   "and\\t%0, %0, %2"
2024   [(set_attr "length" "2")]
2025 )
2026
2027 (define_insn "*andsi3_compare0"
2028   [(set (reg:CC_NOOV CC_REGNUM)
2029         (compare:CC_NOOV
2030          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
2031                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
2032          (const_int 0)))
2033    (set (match_operand:SI          0 "s_register_operand" "=r,r")
2034         (and:SI (match_dup 1) (match_dup 2)))]
2035   "TARGET_32BIT"
2036   "@
2037    and%.\\t%0, %1, %2
2038    bic%.\\t%0, %1, #%B2"
2039   [(set_attr "conds" "set")]
2040 )
2041
2042 (define_insn "*andsi3_compare0_scratch"
2043   [(set (reg:CC_NOOV CC_REGNUM)
2044         (compare:CC_NOOV
2045          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
2046                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
2047          (const_int 0)))
2048    (clobber (match_scratch:SI 2 "=X,r"))]
2049   "TARGET_32BIT"
2050   "@
2051    tst%?\\t%0, %1
2052    bic%.\\t%2, %0, #%B1"
2053   [(set_attr "conds" "set")]
2054 )
2055
2056 (define_insn "*zeroextractsi_compare0_scratch"
2057   [(set (reg:CC_NOOV CC_REGNUM)
2058         (compare:CC_NOOV (zero_extract:SI
2059                           (match_operand:SI 0 "s_register_operand" "r")
2060                           (match_operand 1 "const_int_operand" "n")
2061                           (match_operand 2 "const_int_operand" "n"))
2062                          (const_int 0)))]
2063   "TARGET_32BIT
2064   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2065       && INTVAL (operands[1]) > 0 
2066       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2067       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
2068   "*
2069   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2070                          << INTVAL (operands[2]));
2071   output_asm_insn (\"tst%?\\t%0, %1\", operands);
2072   return \"\";
2073   "
2074   [(set_attr "conds" "set")]
2075 )
2076
2077 (define_insn_and_split "*ne_zeroextractsi"
2078   [(set (match_operand:SI 0 "s_register_operand" "=r")
2079         (ne:SI (zero_extract:SI
2080                 (match_operand:SI 1 "s_register_operand" "r")
2081                 (match_operand:SI 2 "const_int_operand" "n")
2082                 (match_operand:SI 3 "const_int_operand" "n"))
2083                (const_int 0)))
2084    (clobber (reg:CC CC_REGNUM))]
2085   "TARGET_32BIT
2086    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2087        && INTVAL (operands[2]) > 0 
2088        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2089        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2090   "#"
2091   "TARGET_32BIT
2092    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2093        && INTVAL (operands[2]) > 0 
2094        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2095        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2096   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2097                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2098                                     (const_int 0)))
2099               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2100    (set (match_dup 0)
2101         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2102                          (match_dup 0) (const_int 1)))]
2103   "
2104   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2105                          << INTVAL (operands[3])); 
2106   "
2107   [(set_attr "conds" "clob")
2108    (set (attr "length")
2109         (if_then_else (eq_attr "is_thumb" "yes")
2110                       (const_int 12)
2111                       (const_int 8)))]
2112 )
2113
2114 (define_insn_and_split "*ne_zeroextractsi_shifted"
2115   [(set (match_operand:SI 0 "s_register_operand" "=r")
2116         (ne:SI (zero_extract:SI
2117                 (match_operand:SI 1 "s_register_operand" "r")
2118                 (match_operand:SI 2 "const_int_operand" "n")
2119                 (const_int 0))
2120                (const_int 0)))
2121    (clobber (reg:CC CC_REGNUM))]
2122   "TARGET_ARM"
2123   "#"
2124   "TARGET_ARM"
2125   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2126                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2127                                     (const_int 0)))
2128               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2129    (set (match_dup 0)
2130         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2131                          (match_dup 0) (const_int 1)))]
2132   "
2133   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2134   "
2135   [(set_attr "conds" "clob")
2136    (set_attr "length" "8")]
2137 )
2138
2139 (define_insn_and_split "*ite_ne_zeroextractsi"
2140   [(set (match_operand:SI 0 "s_register_operand" "=r")
2141         (if_then_else:SI (ne (zero_extract:SI
2142                               (match_operand:SI 1 "s_register_operand" "r")
2143                               (match_operand:SI 2 "const_int_operand" "n")
2144                               (match_operand:SI 3 "const_int_operand" "n"))
2145                              (const_int 0))
2146                          (match_operand:SI 4 "arm_not_operand" "rIK")
2147                          (const_int 0)))
2148    (clobber (reg:CC CC_REGNUM))]
2149   "TARGET_ARM
2150    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2151        && INTVAL (operands[2]) > 0 
2152        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2153        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2154    && !reg_overlap_mentioned_p (operands[0], operands[4])"
2155   "#"
2156   "TARGET_ARM
2157    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2158        && INTVAL (operands[2]) > 0 
2159        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2160        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2161    && !reg_overlap_mentioned_p (operands[0], operands[4])"
2162   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2163                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2164                                     (const_int 0)))
2165               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2166    (set (match_dup 0)
2167         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2168                          (match_dup 0) (match_dup 4)))]
2169   "
2170   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2171                          << INTVAL (operands[3])); 
2172   "
2173   [(set_attr "conds" "clob")
2174    (set_attr "length" "8")]
2175 )
2176
2177 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2178   [(set (match_operand:SI 0 "s_register_operand" "=r")
2179         (if_then_else:SI (ne (zero_extract:SI
2180                               (match_operand:SI 1 "s_register_operand" "r")
2181                               (match_operand:SI 2 "const_int_operand" "n")
2182                               (const_int 0))
2183                              (const_int 0))
2184                          (match_operand:SI 3 "arm_not_operand" "rIK")
2185                          (const_int 0)))
2186    (clobber (reg:CC CC_REGNUM))]
2187   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2188   "#"
2189   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2190   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2191                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2192                                     (const_int 0)))
2193               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2194    (set (match_dup 0)
2195         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2196                          (match_dup 0) (match_dup 3)))]
2197   "
2198   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2199   "
2200   [(set_attr "conds" "clob")
2201    (set_attr "length" "8")]
2202 )
2203
2204 (define_split
2205   [(set (match_operand:SI 0 "s_register_operand" "")
2206         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
2207                          (match_operand:SI 2 "const_int_operand" "")
2208                          (match_operand:SI 3 "const_int_operand" "")))
2209    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2210   "TARGET_THUMB1"
2211   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
2212    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
2213   "{
2214      HOST_WIDE_INT temp = INTVAL (operands[2]);
2215
2216      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2217      operands[3] = GEN_INT (32 - temp);
2218    }"
2219 )
2220
2221 ;; ??? Use Thumb-2 has bitfield insert/extract instructions.
2222 (define_split
2223   [(set (match_operand:SI 0 "s_register_operand" "")
2224         (match_operator:SI 1 "shiftable_operator"
2225          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2226                            (match_operand:SI 3 "const_int_operand" "")
2227                            (match_operand:SI 4 "const_int_operand" ""))
2228           (match_operand:SI 5 "s_register_operand" "")]))
2229    (clobber (match_operand:SI 6 "s_register_operand" ""))]
2230   "TARGET_ARM"
2231   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2232    (set (match_dup 0)
2233         (match_op_dup 1
2234          [(lshiftrt:SI (match_dup 6) (match_dup 4))
2235           (match_dup 5)]))]
2236   "{
2237      HOST_WIDE_INT temp = INTVAL (operands[3]);
2238
2239      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2240      operands[4] = GEN_INT (32 - temp);
2241    }"
2242 )
2243   
2244 (define_split
2245   [(set (match_operand:SI 0 "s_register_operand" "")
2246         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2247                          (match_operand:SI 2 "const_int_operand" "")
2248                          (match_operand:SI 3 "const_int_operand" "")))]
2249   "TARGET_THUMB1"
2250   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2251    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2252   "{
2253      HOST_WIDE_INT temp = INTVAL (operands[2]);
2254
2255      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2256      operands[3] = GEN_INT (32 - temp);
2257    }"
2258 )
2259
2260 (define_split
2261   [(set (match_operand:SI 0 "s_register_operand" "")
2262         (match_operator:SI 1 "shiftable_operator"
2263          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2264                            (match_operand:SI 3 "const_int_operand" "")
2265                            (match_operand:SI 4 "const_int_operand" ""))
2266           (match_operand:SI 5 "s_register_operand" "")]))
2267    (clobber (match_operand:SI 6 "s_register_operand" ""))]
2268   "TARGET_ARM"
2269   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2270    (set (match_dup 0)
2271         (match_op_dup 1
2272          [(ashiftrt:SI (match_dup 6) (match_dup 4))
2273           (match_dup 5)]))]
2274   "{
2275      HOST_WIDE_INT temp = INTVAL (operands[3]);
2276
2277      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2278      operands[4] = GEN_INT (32 - temp);
2279    }"
2280 )
2281   
2282 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
2283 ;;; represented by the bitfield, then this will produce incorrect results.
2284 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
2285 ;;; which have a real bit-field insert instruction, the truncation happens
2286 ;;; in the bit-field insert instruction itself.  Since arm does not have a
2287 ;;; bit-field insert instruction, we would have to emit code here to truncate
2288 ;;; the value before we insert.  This loses some of the advantage of having
2289 ;;; this insv pattern, so this pattern needs to be reevalutated.
2290
2291 (define_expand "insv"
2292   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
2293                          (match_operand:SI 1 "general_operand" "")
2294                          (match_operand:SI 2 "general_operand" ""))
2295         (match_operand:SI 3 "reg_or_int_operand" ""))]
2296   "TARGET_ARM || arm_arch_thumb2"
2297   "
2298   {
2299     int start_bit = INTVAL (operands[2]);
2300     int width = INTVAL (operands[1]);
2301     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2302     rtx target, subtarget;
2303
2304     if (arm_arch_thumb2)
2305       {
2306         bool use_bfi = TRUE;
2307
2308         if (GET_CODE (operands[3]) == CONST_INT)
2309           {
2310             HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2311
2312             if (val == 0)
2313               {
2314                 emit_insn (gen_insv_zero (operands[0], operands[1],
2315                                           operands[2]));
2316                 DONE;
2317               }
2318
2319             /* See if the set can be done with a single orr instruction.  */
2320             if (val == mask && const_ok_for_arm (val << start_bit))
2321               use_bfi = FALSE;
2322           }
2323           
2324         if (use_bfi)
2325           {
2326             if (GET_CODE (operands[3]) != REG)
2327               operands[3] = force_reg (SImode, operands[3]);
2328
2329             emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2330                                     operands[3]));
2331             DONE;
2332           }
2333       }
2334
2335     target = copy_rtx (operands[0]);
2336     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
2337        subreg as the final target.  */
2338     if (GET_CODE (target) == SUBREG)
2339       {
2340         subtarget = gen_reg_rtx (SImode);
2341         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2342             < GET_MODE_SIZE (SImode))
2343           target = SUBREG_REG (target);
2344       }
2345     else
2346       subtarget = target;    
2347
2348     if (GET_CODE (operands[3]) == CONST_INT)
2349       {
2350         /* Since we are inserting a known constant, we may be able to
2351            reduce the number of bits that we have to clear so that
2352            the mask becomes simple.  */
2353         /* ??? This code does not check to see if the new mask is actually
2354            simpler.  It may not be.  */
2355         rtx op1 = gen_reg_rtx (SImode);
2356         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
2357            start of this pattern.  */
2358         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2359         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2360
2361         emit_insn (gen_andsi3 (op1, operands[0],
2362                                gen_int_mode (~mask2, SImode)));
2363         emit_insn (gen_iorsi3 (subtarget, op1,
2364                                gen_int_mode (op3_value << start_bit, SImode)));
2365       }
2366     else if (start_bit == 0
2367              && !(const_ok_for_arm (mask)
2368                   || const_ok_for_arm (~mask)))
2369       {
2370         /* A Trick, since we are setting the bottom bits in the word,
2371            we can shift operand[3] up, operand[0] down, OR them together
2372            and rotate the result back again.  This takes 3 insns, and
2373            the third might be mergeable into another op.  */
2374         /* The shift up copes with the possibility that operand[3] is
2375            wider than the bitfield.  */
2376         rtx op0 = gen_reg_rtx (SImode);
2377         rtx op1 = gen_reg_rtx (SImode);
2378
2379         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2380         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2381         emit_insn (gen_iorsi3  (op1, op1, op0));
2382         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2383       }
2384     else if ((width + start_bit == 32)
2385              && !(const_ok_for_arm (mask)
2386                   || const_ok_for_arm (~mask)))
2387       {
2388         /* Similar trick, but slightly less efficient.  */
2389
2390         rtx op0 = gen_reg_rtx (SImode);
2391         rtx op1 = gen_reg_rtx (SImode);
2392
2393         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2394         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2395         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2396         emit_insn (gen_iorsi3 (subtarget, op1, op0));
2397       }
2398     else
2399       {
2400         rtx op0 = gen_int_mode (mask, SImode);
2401         rtx op1 = gen_reg_rtx (SImode);
2402         rtx op2 = gen_reg_rtx (SImode);
2403
2404         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2405           {
2406             rtx tmp = gen_reg_rtx (SImode);
2407
2408             emit_insn (gen_movsi (tmp, op0));
2409             op0 = tmp;
2410           }
2411
2412         /* Mask out any bits in operand[3] that are not needed.  */
2413            emit_insn (gen_andsi3 (op1, operands[3], op0));
2414
2415         if (GET_CODE (op0) == CONST_INT
2416             && (const_ok_for_arm (mask << start_bit)
2417                 || const_ok_for_arm (~(mask << start_bit))))
2418           {
2419             op0 = gen_int_mode (~(mask << start_bit), SImode);
2420             emit_insn (gen_andsi3 (op2, operands[0], op0));
2421           }
2422         else
2423           {
2424             if (GET_CODE (op0) == CONST_INT)
2425               {
2426                 rtx tmp = gen_reg_rtx (SImode);
2427
2428                 emit_insn (gen_movsi (tmp, op0));
2429                 op0 = tmp;
2430               }
2431
2432             if (start_bit != 0)
2433               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
2434             
2435             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2436           }
2437
2438         if (start_bit != 0)
2439           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
2440
2441         emit_insn (gen_iorsi3 (subtarget, op1, op2));
2442       }
2443
2444     if (subtarget != target)
2445       {
2446         /* If TARGET is still a SUBREG, then it must be wider than a word,
2447            so we must be careful only to set the subword we were asked to.  */
2448         if (GET_CODE (target) == SUBREG)
2449           emit_move_insn (target, subtarget);
2450         else
2451           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2452       }
2453
2454     DONE;
2455   }"
2456 )
2457
2458 (define_insn "insv_zero"
2459   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2460                          (match_operand:SI 1 "const_int_operand" "M")
2461                          (match_operand:SI 2 "const_int_operand" "M"))
2462         (const_int 0))]
2463   "arm_arch_thumb2"
2464   "bfc%?\t%0, %2, %1"
2465   [(set_attr "length" "4")
2466    (set_attr "predicable" "yes")]
2467 )
2468
2469 (define_insn "insv_t2"
2470   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2471                          (match_operand:SI 1 "const_int_operand" "M")
2472                          (match_operand:SI 2 "const_int_operand" "M"))
2473         (match_operand:SI 3 "s_register_operand" "r"))]
2474   "arm_arch_thumb2"
2475   "bfi%?\t%0, %3, %2, %1"
2476   [(set_attr "length" "4")
2477    (set_attr "predicable" "yes")]
2478 )
2479
2480 ; constants for op 2 will never be given to these patterns.
2481 (define_insn_and_split "*anddi_notdi_di"
2482   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2483         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2484                 (match_operand:DI 2 "s_register_operand" "r,0")))]
2485   "TARGET_32BIT"
2486   "#"
2487   "TARGET_32BIT && reload_completed
2488    && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2489    && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2490   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2491    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2492   "
2493   {
2494     operands[3] = gen_highpart (SImode, operands[0]);
2495     operands[0] = gen_lowpart (SImode, operands[0]);
2496     operands[4] = gen_highpart (SImode, operands[1]);
2497     operands[1] = gen_lowpart (SImode, operands[1]);
2498     operands[5] = gen_highpart (SImode, operands[2]);
2499     operands[2] = gen_lowpart (SImode, operands[2]);
2500   }"
2501   [(set_attr "length" "8")
2502    (set_attr "predicable" "yes")]
2503 )
2504   
2505 (define_insn_and_split "*anddi_notzesidi_di"
2506   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2507         (and:DI (not:DI (zero_extend:DI
2508                          (match_operand:SI 2 "s_register_operand" "r,r")))
2509                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2510   "TARGET_32BIT"
2511   "@
2512    bic%?\\t%Q0, %Q1, %2
2513    #"
2514   ; (not (zero_extend ...)) allows us to just copy the high word from
2515   ; operand1 to operand0.
2516   "TARGET_32BIT
2517    && reload_completed
2518    && operands[0] != operands[1]"
2519   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2520    (set (match_dup 3) (match_dup 4))]
2521   "
2522   {
2523     operands[3] = gen_highpart (SImode, operands[0]);
2524     operands[0] = gen_lowpart (SImode, operands[0]);
2525     operands[4] = gen_highpart (SImode, operands[1]);
2526     operands[1] = gen_lowpart (SImode, operands[1]);
2527   }"
2528   [(set_attr "length" "4,8")
2529    (set_attr "predicable" "yes")]
2530 )
2531   
2532 (define_insn_and_split "*anddi_notsesidi_di"
2533   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2534         (and:DI (not:DI (sign_extend:DI
2535                          (match_operand:SI 2 "s_register_operand" "r,r")))
2536                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2537   "TARGET_32BIT"
2538   "#"
2539   "TARGET_32BIT && reload_completed"
2540   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2541    (set (match_dup 3) (and:SI (not:SI
2542                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2543                                (match_dup 4)))]
2544   "
2545   {
2546     operands[3] = gen_highpart (SImode, operands[0]);
2547     operands[0] = gen_lowpart (SImode, operands[0]);
2548     operands[4] = gen_highpart (SImode, operands[1]);
2549     operands[1] = gen_lowpart (SImode, operands[1]);
2550   }"
2551   [(set_attr "length" "8")
2552    (set_attr "predicable" "yes")]
2553 )
2554   
2555 (define_insn "andsi_notsi_si"
2556   [(set (match_operand:SI 0 "s_register_operand" "=r")
2557         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2558                 (match_operand:SI 1 "s_register_operand" "r")))]
2559   "TARGET_32BIT"
2560   "bic%?\\t%0, %1, %2"
2561   [(set_attr "predicable" "yes")]
2562 )
2563
2564 (define_insn "bicsi3"
2565   [(set (match_operand:SI                 0 "register_operand" "=l")
2566         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2567                 (match_operand:SI         2 "register_operand" "0")))]
2568   "TARGET_THUMB1"
2569   "bic\\t%0, %0, %1"
2570   [(set_attr "length" "2")]
2571 )
2572
2573 (define_insn "andsi_not_shiftsi_si"
2574   [(set (match_operand:SI 0 "s_register_operand" "=r")
2575         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2576                          [(match_operand:SI 2 "s_register_operand" "r")
2577                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2578                 (match_operand:SI 1 "s_register_operand" "r")))]
2579   "TARGET_ARM"
2580   "bic%?\\t%0, %1, %2%S4"
2581   [(set_attr "predicable" "yes")
2582    (set_attr "shift" "2")
2583    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2584                       (const_string "alu_shift")
2585                       (const_string "alu_shift_reg")))]
2586 )
2587
2588 (define_insn "*andsi_notsi_si_compare0"
2589   [(set (reg:CC_NOOV CC_REGNUM)
2590         (compare:CC_NOOV
2591          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2592                  (match_operand:SI 1 "s_register_operand" "r"))
2593          (const_int 0)))
2594    (set (match_operand:SI 0 "s_register_operand" "=r")
2595         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2596   "TARGET_32BIT"
2597   "bic%.\\t%0, %1, %2"
2598   [(set_attr "conds" "set")]
2599 )
2600
2601 (define_insn "*andsi_notsi_si_compare0_scratch"
2602   [(set (reg:CC_NOOV CC_REGNUM)
2603         (compare:CC_NOOV
2604          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2605                  (match_operand:SI 1 "s_register_operand" "r"))
2606          (const_int 0)))
2607    (clobber (match_scratch:SI 0 "=r"))]
2608   "TARGET_32BIT"
2609   "bic%.\\t%0, %1, %2"
2610   [(set_attr "conds" "set")]
2611 )
2612
2613 (define_expand "iordi3"
2614   [(set (match_operand:DI         0 "s_register_operand" "")
2615         (ior:DI (match_operand:DI 1 "s_register_operand" "")
2616                 (match_operand:DI 2 "neon_logic_op2" "")))]
2617   "TARGET_32BIT"
2618   ""
2619 )
2620
2621 (define_insn "*iordi3_insn"
2622   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2623         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2624                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2625   "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
2626   "#"
2627   [(set_attr "length" "8")
2628    (set_attr "predicable" "yes")]
2629 )
2630
2631 (define_insn "*iordi_zesidi_di"
2632   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2633         (ior:DI (zero_extend:DI
2634                  (match_operand:SI 2 "s_register_operand" "r,r"))
2635                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2636   "TARGET_32BIT"
2637   "@
2638    orr%?\\t%Q0, %Q1, %2
2639    #"
2640   [(set_attr "length" "4,8")
2641    (set_attr "predicable" "yes")]
2642 )
2643
2644 (define_insn "*iordi_sesidi_di"
2645   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2646         (ior:DI (sign_extend:DI
2647                  (match_operand:SI 2 "s_register_operand" "r,r"))
2648                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2649   "TARGET_32BIT"
2650   "#"
2651   [(set_attr "length" "8")
2652    (set_attr "predicable" "yes")]
2653 )
2654
2655 (define_expand "iorsi3"
2656   [(set (match_operand:SI         0 "s_register_operand" "")
2657         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2658                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2659   "TARGET_EITHER"
2660   "
2661   if (GET_CODE (operands[2]) == CONST_INT)
2662     {
2663       if (TARGET_32BIT)
2664         {
2665           arm_split_constant (IOR, SImode, NULL_RTX,
2666                               INTVAL (operands[2]), operands[0], operands[1],
2667                               optimize && can_create_pseudo_p ());
2668           DONE;
2669         }
2670       else /* TARGET_THUMB1 */
2671         {
2672           rtx tmp = force_reg (SImode, operands[2]);
2673           if (rtx_equal_p (operands[0], operands[1]))
2674             operands[2] = tmp;
2675           else
2676             {
2677               operands[2] = operands[1];
2678               operands[1] = tmp;
2679             }
2680         }
2681     }
2682   "
2683 )
2684
2685 (define_insn_and_split "*arm_iorsi3"
2686   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2687         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2688                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2689   "TARGET_ARM"
2690   "@
2691    orr%?\\t%0, %1, %2
2692    #"
2693   "TARGET_ARM
2694    && GET_CODE (operands[2]) == CONST_INT
2695    && !const_ok_for_arm (INTVAL (operands[2]))"
2696   [(clobber (const_int 0))]
2697   "
2698   arm_split_constant (IOR, SImode, curr_insn, 
2699                       INTVAL (operands[2]), operands[0], operands[1], 0);
2700   DONE;
2701   "
2702   [(set_attr "length" "4,16")
2703    (set_attr "predicable" "yes")]
2704 )
2705
2706 (define_insn "*thumb1_iorsi3"
2707   [(set (match_operand:SI         0 "register_operand" "=l")
2708         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2709                 (match_operand:SI 2 "register_operand" "l")))]
2710   "TARGET_THUMB1"
2711   "orr\\t%0, %0, %2"
2712   [(set_attr "length" "2")]
2713 )
2714
2715 (define_peephole2
2716   [(match_scratch:SI 3 "r")
2717    (set (match_operand:SI 0 "arm_general_register_operand" "")
2718         (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2719                 (match_operand:SI 2 "const_int_operand" "")))]
2720   "TARGET_ARM
2721    && !const_ok_for_arm (INTVAL (operands[2]))
2722    && const_ok_for_arm (~INTVAL (operands[2]))"
2723   [(set (match_dup 3) (match_dup 2))
2724    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2725   ""
2726 )
2727
2728 (define_insn "*iorsi3_compare0"
2729   [(set (reg:CC_NOOV CC_REGNUM)
2730         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2731                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2732                          (const_int 0)))
2733    (set (match_operand:SI 0 "s_register_operand" "=r")
2734         (ior:SI (match_dup 1) (match_dup 2)))]
2735   "TARGET_32BIT"
2736   "orr%.\\t%0, %1, %2"
2737   [(set_attr "conds" "set")]
2738 )
2739
2740 (define_insn "*iorsi3_compare0_scratch"
2741   [(set (reg:CC_NOOV CC_REGNUM)
2742         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2743                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2744                          (const_int 0)))
2745    (clobber (match_scratch:SI 0 "=r"))]
2746   "TARGET_32BIT"
2747   "orr%.\\t%0, %1, %2"
2748   [(set_attr "conds" "set")]
2749 )
2750
2751 (define_expand "xordi3"
2752   [(set (match_operand:DI         0 "s_register_operand" "")
2753         (xor:DI (match_operand:DI 1 "s_register_operand" "")
2754                 (match_operand:DI 2 "s_register_operand" "")))]
2755   "TARGET_32BIT"
2756   ""
2757 )
2758
2759 (define_insn "*xordi3_insn"
2760   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2761         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2762                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2763   "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
2764   "#"
2765   [(set_attr "length" "8")
2766    (set_attr "predicable" "yes")]
2767 )
2768
2769 (define_insn "*xordi_zesidi_di"
2770   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2771         (xor:DI (zero_extend:DI
2772                  (match_operand:SI 2 "s_register_operand" "r,r"))
2773                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2774   "TARGET_32BIT"
2775   "@
2776    eor%?\\t%Q0, %Q1, %2
2777    #"
2778   [(set_attr "length" "4,8")
2779    (set_attr "predicable" "yes")]
2780 )
2781
2782 (define_insn "*xordi_sesidi_di"
2783   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2784         (xor:DI (sign_extend:DI
2785                  (match_operand:SI 2 "s_register_operand" "r,r"))
2786                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2787   "TARGET_32BIT"
2788   "#"
2789   [(set_attr "length" "8")
2790    (set_attr "predicable" "yes")]
2791 )
2792
2793 (define_expand "xorsi3"
2794   [(set (match_operand:SI         0 "s_register_operand" "")
2795         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2796                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2797   "TARGET_EITHER"
2798   "if (GET_CODE (operands[2]) == CONST_INT)
2799     {
2800       if (TARGET_32BIT)
2801         {
2802           arm_split_constant (XOR, SImode, NULL_RTX,
2803                               INTVAL (operands[2]), operands[0], operands[1],
2804                               optimize && can_create_pseudo_p ());
2805           DONE;
2806         }
2807       else /* TARGET_THUMB1 */
2808         {
2809           rtx tmp = force_reg (SImode, operands[2]);
2810           if (rtx_equal_p (operands[0], operands[1]))
2811             operands[2] = tmp;
2812           else
2813             {
2814               operands[2] = operands[1];
2815               operands[1] = tmp;
2816             }
2817         }
2818     }"
2819 )
2820
2821 (define_insn "*arm_xorsi3"
2822   [(set (match_operand:SI         0 "s_register_operand" "=r")
2823         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2824                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2825   "TARGET_32BIT"
2826   "eor%?\\t%0, %1, %2"
2827   [(set_attr "predicable" "yes")]
2828 )
2829
2830 (define_insn "*thumb1_xorsi3"
2831   [(set (match_operand:SI         0 "register_operand" "=l")
2832         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2833                 (match_operand:SI 2 "register_operand" "l")))]
2834   "TARGET_THUMB1"
2835   "eor\\t%0, %0, %2"
2836   [(set_attr "length" "2")]
2837 )
2838
2839 (define_insn "*xorsi3_compare0"
2840   [(set (reg:CC_NOOV CC_REGNUM)
2841         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2842                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2843                          (const_int 0)))
2844    (set (match_operand:SI 0 "s_register_operand" "=r")
2845         (xor:SI (match_dup 1) (match_dup 2)))]
2846   "TARGET_32BIT"
2847   "eor%.\\t%0, %1, %2"
2848   [(set_attr "conds" "set")]
2849 )
2850
2851 (define_insn "*xorsi3_compare0_scratch"
2852   [(set (reg:CC_NOOV CC_REGNUM)
2853         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2854                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2855                          (const_int 0)))]
2856   "TARGET_32BIT"
2857   "teq%?\\t%0, %1"
2858   [(set_attr "conds" "set")]
2859 )
2860
2861 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2862 ; (NOT D) we can sometimes merge the final NOT into one of the following
2863 ; insns.
2864
2865 (define_split
2866   [(set (match_operand:SI 0 "s_register_operand" "")
2867         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2868                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2869                 (match_operand:SI 3 "arm_rhs_operand" "")))
2870    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2871   "TARGET_32BIT"
2872   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2873                               (not:SI (match_dup 3))))
2874    (set (match_dup 0) (not:SI (match_dup 4)))]
2875   ""
2876 )
2877
2878 (define_insn "*andsi_iorsi3_notsi"
2879   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2880         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
2881                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2882                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2883   "TARGET_32BIT"
2884   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2885   [(set_attr "length" "8")
2886    (set_attr "ce_count" "2")
2887    (set_attr "predicable" "yes")]
2888 )
2889
2890 ; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
2891 ; insns are available?
2892 (define_split
2893   [(set (match_operand:SI 0 "s_register_operand" "")
2894         (match_operator:SI 1 "logical_binary_operator"
2895          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2896                            (match_operand:SI 3 "const_int_operand" "")
2897                            (match_operand:SI 4 "const_int_operand" ""))
2898           (match_operator:SI 9 "logical_binary_operator"
2899            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2900                          (match_operand:SI 6 "const_int_operand" ""))
2901             (match_operand:SI 7 "s_register_operand" "")])]))
2902    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2903   "TARGET_32BIT
2904    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2905    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2906   [(set (match_dup 8)
2907         (match_op_dup 1
2908          [(ashift:SI (match_dup 2) (match_dup 4))
2909           (match_dup 5)]))
2910    (set (match_dup 0)
2911         (match_op_dup 1
2912          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2913           (match_dup 7)]))]
2914   "
2915   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2916 ")
2917
2918 (define_split
2919   [(set (match_operand:SI 0 "s_register_operand" "")
2920         (match_operator:SI 1 "logical_binary_operator"
2921          [(match_operator:SI 9 "logical_binary_operator"
2922            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2923                          (match_operand:SI 6 "const_int_operand" ""))
2924             (match_operand:SI 7 "s_register_operand" "")])
2925           (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2926                            (match_operand:SI 3 "const_int_operand" "")
2927                            (match_operand:SI 4 "const_int_operand" ""))]))
2928    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2929   "TARGET_32BIT
2930    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2931    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2932   [(set (match_dup 8)
2933         (match_op_dup 1
2934          [(ashift:SI (match_dup 2) (match_dup 4))
2935           (match_dup 5)]))
2936    (set (match_dup 0)
2937         (match_op_dup 1
2938          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2939           (match_dup 7)]))]
2940   "
2941   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2942 ")
2943
2944 (define_split
2945   [(set (match_operand:SI 0 "s_register_operand" "")
2946         (match_operator:SI 1 "logical_binary_operator"
2947          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2948                            (match_operand:SI 3 "const_int_operand" "")
2949                            (match_operand:SI 4 "const_int_operand" ""))
2950           (match_operator:SI 9 "logical_binary_operator"
2951            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2952                          (match_operand:SI 6 "const_int_operand" ""))
2953             (match_operand:SI 7 "s_register_operand" "")])]))
2954    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2955   "TARGET_32BIT
2956    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2957    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2958   [(set (match_dup 8)
2959         (match_op_dup 1
2960          [(ashift:SI (match_dup 2) (match_dup 4))
2961           (match_dup 5)]))
2962    (set (match_dup 0)
2963         (match_op_dup 1
2964          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2965           (match_dup 7)]))]
2966   "
2967   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2968 ")
2969
2970 (define_split
2971   [(set (match_operand:SI 0 "s_register_operand" "")
2972         (match_operator:SI 1 "logical_binary_operator"
2973          [(match_operator:SI 9 "logical_binary_operator"
2974            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2975                          (match_operand:SI 6 "const_int_operand" ""))
2976             (match_operand:SI 7 "s_register_operand" "")])
2977           (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2978                            (match_operand:SI 3 "const_int_operand" "")
2979                            (match_operand:SI 4 "const_int_operand" ""))]))
2980    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2981   "TARGET_32BIT
2982    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2983    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2984   [(set (match_dup 8)
2985         (match_op_dup 1
2986          [(ashift:SI (match_dup 2) (match_dup 4))
2987           (match_dup 5)]))
2988    (set (match_dup 0)
2989         (match_op_dup 1
2990          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2991           (match_dup 7)]))]
2992   "
2993   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2994 ")
2995 \f
2996
2997 ;; Minimum and maximum insns
2998
2999 (define_expand "smaxsi3"
3000   [(parallel [
3001     (set (match_operand:SI 0 "s_register_operand" "")
3002          (smax:SI (match_operand:SI 1 "s_register_operand" "")
3003                   (match_operand:SI 2 "arm_rhs_operand" "")))
3004     (clobber (reg:CC CC_REGNUM))])]
3005   "TARGET_32BIT"
3006   "
3007   if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
3008     {
3009       /* No need for a clobber of the condition code register here.  */
3010       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3011                               gen_rtx_SMAX (SImode, operands[1],
3012                                             operands[2])));
3013       DONE;
3014     }
3015 ")
3016
3017 (define_insn "*smax_0"
3018   [(set (match_operand:SI 0 "s_register_operand" "=r")
3019         (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3020                  (const_int 0)))]
3021   "TARGET_32BIT"
3022   "bic%?\\t%0, %1, %1, asr #31"
3023   [(set_attr "predicable" "yes")]
3024 )
3025
3026 (define_insn "*smax_m1"
3027   [(set (match_operand:SI 0 "s_register_operand" "=r")
3028         (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3029                  (const_int -1)))]
3030   "TARGET_32BIT"
3031   "orr%?\\t%0, %1, %1, asr #31"
3032   [(set_attr "predicable" "yes")]
3033 )
3034
3035 (define_insn "*arm_smax_insn"
3036   [(set (match_operand:SI          0 "s_register_operand" "=r,r")
3037         (smax:SI (match_operand:SI 1 "s_register_operand"  "%0,?r")
3038                  (match_operand:SI 2 "arm_rhs_operand"    "rI,rI")))
3039    (clobber (reg:CC CC_REGNUM))]
3040   "TARGET_ARM"
3041   "@
3042    cmp\\t%1, %2\;movlt\\t%0, %2
3043    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
3044   [(set_attr "conds" "clob")
3045    (set_attr "length" "8,12")]
3046 )
3047
3048 (define_expand "sminsi3"
3049   [(parallel [
3050     (set (match_operand:SI 0 "s_register_operand" "")
3051          (smin:SI (match_operand:SI 1 "s_register_operand" "")
3052                   (match_operand:SI 2 "arm_rhs_operand" "")))
3053     (clobber (reg:CC CC_REGNUM))])]
3054   "TARGET_32BIT"
3055   "
3056   if (operands[2] == const0_rtx)
3057     {
3058       /* No need for a clobber of the condition code register here.  */
3059       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3060                               gen_rtx_SMIN (SImode, operands[1],
3061                                             operands[2])));
3062       DONE;
3063     }
3064 ")
3065
3066 (define_insn "*smin_0"
3067   [(set (match_operand:SI 0 "s_register_operand" "=r")
3068         (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3069                  (const_int 0)))]
3070   "TARGET_32BIT"
3071   "and%?\\t%0, %1, %1, asr #31"
3072   [(set_attr "predicable" "yes")]
3073 )
3074
3075 (define_insn "*arm_smin_insn"
3076   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3077         (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3078                  (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
3079    (clobber (reg:CC CC_REGNUM))]
3080   "TARGET_ARM"
3081   "@
3082    cmp\\t%1, %2\;movge\\t%0, %2
3083    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
3084   [(set_attr "conds" "clob")
3085    (set_attr "length" "8,12")]
3086 )
3087
3088 (define_expand "umaxsi3"
3089   [(parallel [
3090     (set (match_operand:SI 0 "s_register_operand" "")
3091          (umax:SI (match_operand:SI 1 "s_register_operand" "")
3092                   (match_operand:SI 2 "arm_rhs_operand" "")))
3093     (clobber (reg:CC CC_REGNUM))])]
3094   "TARGET_32BIT"
3095   ""
3096 )
3097
3098 (define_insn "*arm_umaxsi3"
3099   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3100         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3101                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
3102    (clobber (reg:CC CC_REGNUM))]
3103   "TARGET_ARM"
3104   "@
3105    cmp\\t%1, %2\;movcc\\t%0, %2
3106    cmp\\t%1, %2\;movcs\\t%0, %1
3107    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
3108   [(set_attr "conds" "clob")
3109    (set_attr "length" "8,8,12")]
3110 )
3111
3112 (define_expand "uminsi3"
3113   [(parallel [
3114     (set (match_operand:SI 0 "s_register_operand" "")
3115          (umin:SI (match_operand:SI 1 "s_register_operand" "")
3116                   (match_operand:SI 2 "arm_rhs_operand" "")))
3117     (clobber (reg:CC CC_REGNUM))])]
3118   "TARGET_32BIT"
3119   ""
3120 )
3121
3122 (define_insn "*arm_uminsi3"
3123   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3124         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3125                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
3126    (clobber (reg:CC CC_REGNUM))]
3127   "TARGET_ARM"
3128   "@
3129    cmp\\t%1, %2\;movcs\\t%0, %2
3130    cmp\\t%1, %2\;movcc\\t%0, %1
3131    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
3132   [(set_attr "conds" "clob")
3133    (set_attr "length" "8,8,12")]
3134 )
3135
3136 (define_insn "*store_minmaxsi"
3137   [(set (match_operand:SI 0 "memory_operand" "=m")
3138         (match_operator:SI 3 "minmax_operator"
3139          [(match_operand:SI 1 "s_register_operand" "r")
3140           (match_operand:SI 2 "s_register_operand" "r")]))
3141    (clobber (reg:CC CC_REGNUM))]
3142   "TARGET_32BIT"
3143   "*
3144   operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3145                                 operands[1], operands[2]);
3146   output_asm_insn (\"cmp\\t%1, %2\", operands);
3147   if (TARGET_THUMB2)
3148     output_asm_insn (\"ite\t%d3\", operands);
3149   output_asm_insn (\"str%d3\\t%1, %0\", operands);
3150   output_asm_insn (\"str%D3\\t%2, %0\", operands);
3151   return \"\";
3152   "
3153   [(set_attr "conds" "clob")
3154    (set (attr "length")
3155         (if_then_else (eq_attr "is_thumb" "yes")
3156                       (const_int 14)
3157                       (const_int 12)))
3158    (set_attr "type" "store1")]
3159 )
3160
3161 ; Reject the frame pointer in operand[1], since reloading this after
3162 ; it has been eliminated can cause carnage.
3163 (define_insn "*minmax_arithsi"
3164   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3165         (match_operator:SI 4 "shiftable_operator"
3166          [(match_operator:SI 5 "minmax_operator"
3167            [(match_operand:SI 2 "s_register_operand" "r,r")
3168             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3169           (match_operand:SI 1 "s_register_operand" "0,?r")]))
3170    (clobber (reg:CC CC_REGNUM))]
3171   "TARGET_32BIT && !arm_eliminable_register (operands[1])"
3172   "*
3173   {
3174     enum rtx_code code = GET_CODE (operands[4]);
3175     bool need_else;
3176
3177     if (which_alternative != 0 || operands[3] != const0_rtx
3178         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
3179       need_else = true;
3180     else
3181       need_else = false;
3182
3183     operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3184                                   operands[2], operands[3]);
3185     output_asm_insn (\"cmp\\t%2, %3\", operands);
3186     if (TARGET_THUMB2)
3187       {
3188         if (need_else)
3189           output_asm_insn (\"ite\\t%d5\", operands);
3190         else
3191           output_asm_insn (\"it\\t%d5\", operands);
3192       }
3193     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
3194     if (need_else)
3195       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3196     return \"\";
3197   }"
3198   [(set_attr "conds" "clob")
3199    (set (attr "length")
3200         (if_then_else (eq_attr "is_thumb" "yes")
3201                       (const_int 14)
3202                       (const_int 12)))]
3203 )
3204
3205 \f
3206 ;; Shift and rotation insns
3207
3208 (define_expand "ashldi3"
3209   [(set (match_operand:DI            0 "s_register_operand" "")
3210         (ashift:DI (match_operand:DI 1 "s_register_operand" "")
3211                    (match_operand:SI 2 "reg_or_int_operand" "")))]
3212   "TARGET_32BIT"
3213   "
3214   if (GET_CODE (operands[2]) == CONST_INT)
3215     {
3216       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3217         {
3218           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3219           DONE;
3220         }
3221         /* Ideally we shouldn't fail here if we could know that operands[1] 
3222            ends up already living in an iwmmxt register. Otherwise it's
3223            cheaper to have the alternate code being generated than moving
3224            values to iwmmxt regs and back.  */
3225         FAIL;
3226     }
3227   else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
3228     FAIL;
3229   "
3230 )
3231
3232 (define_insn "arm_ashldi3_1bit"
3233   [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
3234         (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
3235                    (const_int 1)))
3236    (clobber (reg:CC CC_REGNUM))]
3237   "TARGET_32BIT"
3238   "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
3239   [(set_attr "conds" "clob")
3240    (set_attr "length" "8")]
3241 )
3242
3243 (define_expand "ashlsi3"
3244   [(set (match_operand:SI            0 "s_register_operand" "")
3245         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3246                    (match_operand:SI 2 "arm_rhs_operand" "")))]
3247   "TARGET_EITHER"
3248   "
3249   if (GET_CODE (operands[2]) == CONST_INT
3250       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3251     {
3252       emit_insn (gen_movsi (operands[0], const0_rtx));
3253       DONE;
3254     }
3255   "
3256 )
3257
3258 (define_insn "*thumb1_ashlsi3"
3259   [(set (match_operand:SI            0 "register_operand" "=l,l")
3260         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
3261                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
3262   "TARGET_THUMB1"
3263   "lsl\\t%0, %1, %2"
3264   [(set_attr "length" "2")]
3265 )
3266
3267 (define_expand "ashrdi3"
3268   [(set (match_operand:DI              0 "s_register_operand" "")
3269         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3270                      (match_operand:SI 2 "reg_or_int_operand" "")))]
3271   "TARGET_32BIT"
3272   "
3273   if (GET_CODE (operands[2]) == CONST_INT)
3274     {
3275       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3276         {
3277           emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3278           DONE;
3279         }
3280         /* Ideally we shouldn't fail here if we could know that operands[1] 
3281            ends up already living in an iwmmxt register. Otherwise it's
3282            cheaper to have the alternate code being generated than moving
3283            values to iwmmxt regs and back.  */
3284         FAIL;
3285     }
3286   else if (!TARGET_REALLY_IWMMXT)
3287     FAIL;
3288   "
3289 )
3290
3291 (define_insn "arm_ashrdi3_1bit"
3292   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
3293         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
3294                      (const_int 1)))
3295    (clobber (reg:CC CC_REGNUM))]
3296   "TARGET_32BIT"
3297   "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
3298   [(set_attr "conds" "clob")
3299    (set_attr "length" "8")]
3300 )
3301
3302 (define_expand "ashrsi3"
3303   [(set (match_operand:SI              0 "s_register_operand" "")
3304         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3305                      (match_operand:SI 2 "arm_rhs_operand" "")))]
3306   "TARGET_EITHER"
3307   "
3308   if (GET_CODE (operands[2]) == CONST_INT
3309       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3310     operands[2] = GEN_INT (31);
3311   "
3312 )
3313
3314 (define_insn "*thumb1_ashrsi3"
3315   [(set (match_operand:SI              0 "register_operand" "=l,l")
3316         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3317                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
3318   "TARGET_THUMB1"
3319   "asr\\t%0, %1, %2"
3320   [(set_attr "length" "2")]
3321 )
3322
3323 (define_expand "lshrdi3"
3324   [(set (match_operand:DI              0 "s_register_operand" "")
3325         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3326                      (match_operand:SI 2 "reg_or_int_operand" "")))]
3327   "TARGET_32BIT"
3328   "
3329   if (GET_CODE (operands[2]) == CONST_INT)
3330     {
3331       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3332         {
3333           emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3334           DONE;
3335         }
3336         /* Ideally we shouldn't fail here if we could know that operands[1] 
3337            ends up already living in an iwmmxt register. Otherwise it's
3338            cheaper to have the alternate code being generated than moving
3339            values to iwmmxt regs and back.  */
3340         FAIL;
3341     }
3342   else if (!TARGET_REALLY_IWMMXT)
3343     FAIL;
3344   "
3345 )
3346
3347 (define_insn "arm_lshrdi3_1bit"
3348   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
3349         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
3350                      (const_int 1)))
3351    (clobber (reg:CC CC_REGNUM))]
3352   "TARGET_32BIT"
3353   "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
3354   [(set_attr "conds" "clob")
3355    (set_attr "length" "8")]
3356 )
3357
3358 (define_expand "lshrsi3"
3359   [(set (match_operand:SI              0 "s_register_operand" "")
3360         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3361                      (match_operand:SI 2 "arm_rhs_operand" "")))]
3362   "TARGET_EITHER"
3363   "
3364   if (GET_CODE (operands[2]) == CONST_INT
3365       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3366     {
3367       emit_insn (gen_movsi (operands[0], const0_rtx));
3368       DONE;
3369     }
3370   "
3371 )
3372
3373 (define_insn "*thumb1_lshrsi3"
3374   [(set (match_operand:SI              0 "register_operand" "=l,l")
3375         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3376                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
3377   "TARGET_THUMB1"
3378   "lsr\\t%0, %1, %2"
3379   [(set_attr "length" "2")]
3380 )
3381
3382 (define_expand "rotlsi3"
3383   [(set (match_operand:SI              0 "s_register_operand" "")
3384         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3385                      (match_operand:SI 2 "reg_or_int_operand" "")))]
3386   "TARGET_32BIT"
3387   "
3388   if (GET_CODE (operands[2]) == CONST_INT)
3389     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3390   else
3391     {
3392       rtx reg = gen_reg_rtx (SImode);
3393       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3394       operands[2] = reg;
3395     }
3396   "
3397 )
3398
3399 (define_expand "rotrsi3"
3400   [(set (match_operand:SI              0 "s_register_operand" "")
3401         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3402                      (match_operand:SI 2 "arm_rhs_operand" "")))]
3403   "TARGET_EITHER"
3404   "
3405   if (TARGET_32BIT)
3406     {
3407       if (GET_CODE (operands[2]) == CONST_INT
3408           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3409         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3410     }
3411   else /* TARGET_THUMB1 */
3412     {
3413       if (GET_CODE (operands [2]) == CONST_INT)
3414         operands [2] = force_reg (SImode, operands[2]);
3415     }
3416   "
3417 )
3418
3419 (define_insn "*thumb1_rotrsi3"
3420   [(set (match_operand:SI              0 "register_operand" "=l")
3421         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
3422                      (match_operand:SI 2 "register_operand" "l")))]
3423   "TARGET_THUMB1"
3424   "ror\\t%0, %0, %2"
3425   [(set_attr "length" "2")]
3426 )
3427
3428 (define_insn "*arm_shiftsi3"
3429   [(set (match_operand:SI   0 "s_register_operand" "=r")
3430         (match_operator:SI  3 "shift_operator"
3431          [(match_operand:SI 1 "s_register_operand"  "r")
3432           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
3433   "TARGET_32BIT"
3434   "* return arm_output_shift(operands, 0);"
3435   [(set_attr "predicable" "yes")
3436    (set_attr "shift" "1")
3437    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3438                       (const_string "alu_shift")
3439                       (const_string "alu_shift_reg")))]
3440 )
3441
3442 (define_insn "*shiftsi3_compare0"
3443   [(set (reg:CC_NOOV CC_REGNUM)
3444         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3445                           [(match_operand:SI 1 "s_register_operand" "r")
3446                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
3447                          (const_int 0)))
3448    (set (match_operand:SI 0 "s_register_operand" "=r")
3449         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
3450   "TARGET_32BIT"
3451   "* return arm_output_shift(operands, 1);"
3452   [(set_attr "conds" "set")
3453    (set_attr "shift" "1")
3454    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3455                       (const_string "alu_shift")
3456                       (const_string "alu_shift_reg")))]
3457 )
3458
3459 (define_insn "*shiftsi3_compare0_scratch"
3460   [(set (reg:CC_NOOV CC_REGNUM)
3461         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3462                           [(match_operand:SI 1 "s_register_operand" "r")
3463                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
3464                          (const_int 0)))
3465    (clobber (match_scratch:SI 0 "=r"))]
3466   "TARGET_32BIT"
3467   "* return arm_output_shift(operands, 1);"
3468   [(set_attr "conds" "set")
3469    (set_attr "shift" "1")]
3470 )
3471
3472 (define_insn "*arm_notsi_shiftsi"
3473   [(set (match_operand:SI 0 "s_register_operand" "=r")
3474         (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   "TARGET_ARM"
3478   "mvn%?\\t%0, %1%S3"
3479   [(set_attr "predicable" "yes")
3480    (set_attr "shift" "1")
3481    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3482                       (const_string "alu_shift")
3483                       (const_string "alu_shift_reg")))]
3484 )
3485
3486 (define_insn "*arm_notsi_shiftsi_compare0"
3487   [(set (reg:CC_NOOV CC_REGNUM)
3488         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
3489                           [(match_operand:SI 1 "s_register_operand" "r")
3490                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
3491                          (const_int 0)))
3492    (set (match_operand:SI 0 "s_register_operand" "=r")
3493         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
3494   "TARGET_ARM"
3495   "mvn%.\\t%0, %1%S3"
3496   [(set_attr "conds" "set")
3497    (set_attr "shift" "1")
3498    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3499                       (const_string "alu_shift")
3500                       (const_string "alu_shift_reg")))]
3501 )
3502
3503 (define_insn "*arm_not_shiftsi_compare0_scratch"
3504   [(set (reg:CC_NOOV CC_REGNUM)
3505         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
3506                           [(match_operand:SI 1 "s_register_operand" "r")
3507                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
3508                          (const_int 0)))
3509    (clobber (match_scratch:SI 0 "=r"))]
3510   "TARGET_ARM"
3511   "mvn%.\\t%0, %1%S3"
3512   [(set_attr "conds" "set")
3513    (set_attr "shift" "1")
3514    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3515                       (const_string "alu_shift")
3516                       (const_string "alu_shift_reg")))]
3517 )
3518
3519 ;; We don't really have extzv, but defining this using shifts helps
3520 ;; to reduce register pressure later on.
3521
3522 (define_expand "extzv"
3523   [(set (match_dup 4)
3524         (ashift:SI (match_operand:SI   1 "register_operand" "")
3525                    (match_operand:SI   2 "const_int_operand" "")))
3526    (set (match_operand:SI              0 "register_operand" "")
3527         (lshiftrt:SI (match_dup 4)
3528                      (match_operand:SI 3 "const_int_operand" "")))]
3529   "TARGET_THUMB1 || arm_arch_thumb2"
3530   "
3531   {
3532     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3533     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3534     
3535     if (arm_arch_thumb2)
3536       {
3537         emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
3538                                  operands[3]));
3539         DONE;
3540       }
3541
3542     operands[3] = GEN_INT (rshift);
3543     
3544     if (lshift == 0)
3545       {
3546         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3547         DONE;
3548       }
3549       
3550     operands[2] = GEN_INT (lshift);
3551     operands[4] = gen_reg_rtx (SImode);
3552   }"
3553 )
3554
3555 (define_insn "extv"
3556   [(set (match_operand:SI 0 "s_register_operand" "=r")
3557         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3558                          (match_operand:SI 2 "const_int_operand" "M")
3559                          (match_operand:SI 3 "const_int_operand" "M")))]
3560   "arm_arch_thumb2"
3561   "sbfx%?\t%0, %1, %3, %2"
3562   [(set_attr "length" "4")
3563    (set_attr "predicable" "yes")]
3564 )
3565
3566 (define_insn "extzv_t2"
3567   [(set (match_operand:SI 0 "s_register_operand" "=r")
3568         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3569                          (match_operand:SI 2 "const_int_operand" "M")
3570                          (match_operand:SI 3 "const_int_operand" "M")))]
3571   "arm_arch_thumb2"
3572   "ubfx%?\t%0, %1, %3, %2"
3573   [(set_attr "length" "4")
3574    (set_attr "predicable" "yes")]
3575 )
3576
3577 \f
3578 ;; Unary arithmetic insns
3579
3580 (define_expand "negdi2"
3581  [(parallel
3582    [(set (match_operand:DI 0 "s_register_operand" "")
3583          (neg:DI (match_operand:DI 1 "s_register_operand" "")))
3584     (clobber (reg:CC CC_REGNUM))])]
3585   "TARGET_EITHER"
3586   ""
3587 )
3588
3589 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
3590 ;; The first alternative allows the common case of a *full* overlap.
3591 (define_insn "*arm_negdi2"
3592   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
3593         (neg:DI (match_operand:DI 1 "s_register_operand"  "0,r")))
3594    (clobber (reg:CC CC_REGNUM))]
3595   "TARGET_ARM"
3596   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
3597   [(set_attr "conds" "clob")
3598    (set_attr "length" "8")]
3599 )
3600
3601 (define_insn "*thumb1_negdi2"
3602   [(set (match_operand:DI 0 "register_operand" "=&l")
3603         (neg:DI (match_operand:DI 1 "register_operand" "l")))
3604    (clobber (reg:CC CC_REGNUM))]
3605   "TARGET_THUMB1"
3606   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
3607   [(set_attr "length" "6")]
3608 )
3609
3610 (define_expand "negsi2"
3611   [(set (match_operand:SI         0 "s_register_operand" "")
3612         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
3613   "TARGET_EITHER"
3614   ""
3615 )
3616
3617 (define_insn "*arm_negsi2"
3618   [(set (match_operand:SI         0 "s_register_operand" "=r")
3619         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
3620   "TARGET_32BIT"
3621   "rsb%?\\t%0, %1, #0"
3622   [(set_attr "predicable" "yes")]
3623 )
3624
3625 (define_insn "*thumb1_negsi2"
3626   [(set (match_operand:SI         0 "register_operand" "=l")
3627         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
3628   "TARGET_THUMB1"
3629   "neg\\t%0, %1"
3630   [(set_attr "length" "2")]
3631 )
3632
3633 (define_expand "negsf2"
3634   [(set (match_operand:SF         0 "s_register_operand" "")
3635         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
3636   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3637   ""
3638 )
3639
3640 (define_expand "negdf2"
3641   [(set (match_operand:DF         0 "s_register_operand" "")
3642         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
3643   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
3644   "")
3645
3646 ;; abssi2 doesn't really clobber the condition codes if a different register
3647 ;; is being set.  To keep things simple, assume during rtl manipulations that
3648 ;; it does, but tell the final scan operator the truth.  Similarly for
3649 ;; (neg (abs...))
3650
3651 (define_expand "abssi2"
3652   [(parallel
3653     [(set (match_operand:SI         0 "s_register_operand" "")
3654           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3655      (clobber (match_dup 2))])]
3656   "TARGET_EITHER"
3657   "
3658   if (TARGET_THUMB1)
3659     operands[2] = gen_rtx_SCRATCH (SImode);
3660   else
3661     operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
3662 ")
3663
3664 (define_insn "*arm_abssi2"
3665   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3666         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3667    (clobber (reg:CC CC_REGNUM))]
3668   "TARGET_ARM"
3669   "@
3670    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3671    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3672   [(set_attr "conds" "clob,*")
3673    (set_attr "shift" "1")
3674    ;; predicable can't be set based on the variant, so left as no
3675    (set_attr "length" "8")]
3676 )
3677
3678 (define_insn_and_split "*thumb1_abssi2"
3679   [(set (match_operand:SI 0 "s_register_operand" "=l")
3680         (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
3681    (clobber (match_scratch:SI 2 "=&l"))]
3682   "TARGET_THUMB1"
3683   "#"
3684   "TARGET_THUMB1 && reload_completed"
3685   [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3686    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
3687    (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3688   ""
3689   [(set_attr "length" "6")]
3690 )
3691
3692 (define_insn "*arm_neg_abssi2"
3693   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3694         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3695    (clobber (reg:CC CC_REGNUM))]
3696   "TARGET_ARM"
3697   "@
3698    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3699    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3700   [(set_attr "conds" "clob,*")
3701    (set_attr "shift" "1")
3702    ;; predicable can't be set based on the variant, so left as no
3703    (set_attr "length" "8")]
3704 )
3705
3706 (define_insn_and_split "*thumb1_neg_abssi2"
3707   [(set (match_operand:SI 0 "s_register_operand" "=l")
3708         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
3709    (clobber (match_scratch:SI 2 "=&l"))]
3710   "TARGET_THUMB1"
3711   "#"
3712   "TARGET_THUMB1 && reload_completed"
3713   [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3714    (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
3715    (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3716   ""
3717   [(set_attr "length" "6")]
3718 )
3719
3720 (define_expand "abssf2"
3721   [(set (match_operand:SF         0 "s_register_operand" "")
3722         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3723   "TARGET_32BIT && TARGET_HARD_FLOAT"
3724   "")
3725
3726 (define_expand "absdf2"
3727   [(set (match_operand:DF         0 "s_register_operand" "")
3728         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3729   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
3730   "")
3731
3732 (define_expand "sqrtsf2"
3733   [(set (match_operand:SF 0 "s_register_operand" "")
3734         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3735   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3736   "")
3737
3738 (define_expand "sqrtdf2"
3739   [(set (match_operand:DF 0 "s_register_operand" "")
3740         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3741   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
3742   "")
3743
3744 (define_insn_and_split "one_cmpldi2"
3745   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3746         (not:DI (match_operand:DI 1 "s_register_operand" "0,r")))]
3747   "TARGET_32BIT"
3748   "#"
3749   "TARGET_32BIT && reload_completed"
3750   [(set (match_dup 0) (not:SI (match_dup 1)))
3751    (set (match_dup 2) (not:SI (match_dup 3)))]
3752   "
3753   {
3754     operands[2] = gen_highpart (SImode, operands[0]);
3755     operands[0] = gen_lowpart (SImode, operands[0]);
3756     operands[3] = gen_highpart (SImode, operands[1]);
3757     operands[1] = gen_lowpart (SImode, operands[1]);
3758   }"
3759   [(set_attr "length" "8")
3760    (set_attr "predicable" "yes")]
3761 )
3762
3763 (define_expand "one_cmplsi2"
3764   [(set (match_operand:SI         0 "s_register_operand" "")
3765         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3766   "TARGET_EITHER"
3767   ""
3768 )
3769
3770 (define_insn "*arm_one_cmplsi2"
3771   [(set (match_operand:SI         0 "s_register_operand" "=r")
3772         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3773   "TARGET_32BIT"
3774   "mvn%?\\t%0, %1"
3775   [(set_attr "predicable" "yes")]
3776 )
3777
3778 (define_insn "*thumb1_one_cmplsi2"
3779   [(set (match_operand:SI         0 "register_operand" "=l")
3780         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3781   "TARGET_THUMB1"
3782   "mvn\\t%0, %1"
3783   [(set_attr "length" "2")]
3784 )
3785
3786 (define_insn "*notsi_compare0"
3787   [(set (reg:CC_NOOV CC_REGNUM)
3788         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3789                          (const_int 0)))
3790    (set (match_operand:SI 0 "s_register_operand" "=r")
3791         (not:SI (match_dup 1)))]
3792   "TARGET_32BIT"
3793   "mvn%.\\t%0, %1"
3794   [(set_attr "conds" "set")]
3795 )
3796
3797 (define_insn "*notsi_compare0_scratch"
3798   [(set (reg:CC_NOOV CC_REGNUM)
3799         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3800                          (const_int 0)))
3801    (clobber (match_scratch:SI 0 "=r"))]
3802   "TARGET_32BIT"
3803   "mvn%.\\t%0, %1"
3804   [(set_attr "conds" "set")]
3805 )
3806 \f
3807 ;; Fixed <--> Floating conversion insns
3808
3809 (define_expand "floatsihf2"
3810   [(set (match_operand:HF           0 "general_operand" "")
3811         (float:HF (match_operand:SI 1 "general_operand" "")))]
3812   "TARGET_EITHER"
3813   "
3814   {
3815     rtx op1 = gen_reg_rtx (SFmode);
3816     expand_float (op1, operands[1], 0);
3817     op1 = convert_to_mode (HFmode, op1, 0);
3818     emit_move_insn (operands[0], op1);
3819     DONE;
3820   }"
3821 )
3822
3823 (define_expand "floatdihf2"
3824   [(set (match_operand:HF           0 "general_operand" "")
3825         (float:HF (match_operand:DI 1 "general_operand" "")))]
3826   "TARGET_EITHER"
3827   "
3828   {
3829     rtx op1 = gen_reg_rtx (SFmode);
3830     expand_float (op1, operands[1], 0);
3831     op1 = convert_to_mode (HFmode, op1, 0);
3832     emit_move_insn (operands[0], op1);
3833     DONE;
3834   }"
3835 )
3836
3837 (define_expand "floatsisf2"
3838   [(set (match_operand:SF           0 "s_register_operand" "")
3839         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3840   "TARGET_32BIT && TARGET_HARD_FLOAT"
3841   "
3842   if (TARGET_MAVERICK)
3843     {
3844       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3845       DONE;
3846     }
3847 ")
3848
3849 (define_expand "floatsidf2"
3850   [(set (match_operand:DF           0 "s_register_operand" "")
3851         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3852   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
3853   "
3854   if (TARGET_MAVERICK)
3855     {
3856       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3857       DONE;
3858     }
3859 ")
3860
3861 (define_expand "fix_trunchfsi2"
3862   [(set (match_operand:SI         0 "general_operand" "")
3863         (fix:SI (fix:HF (match_operand:HF 1 "general_operand"  ""))))]
3864   "TARGET_EITHER"
3865   "
3866   {
3867     rtx op1 = convert_to_mode (SFmode, operands[1], 0);
3868     expand_fix (operands[0], op1, 0);
3869     DONE;
3870   }"
3871 )
3872
3873 (define_expand "fix_trunchfdi2"
3874   [(set (match_operand:DI         0 "general_operand" "")
3875         (fix:DI (fix:HF (match_operand:HF 1 "general_operand"  ""))))]
3876   "TARGET_EITHER"
3877   "
3878   {
3879     rtx op1 = convert_to_mode (SFmode, operands[1], 0);
3880     expand_fix (operands[0], op1, 0);
3881     DONE;
3882   }"
3883 )
3884
3885 (define_expand "fix_truncsfsi2"
3886   [(set (match_operand:SI         0 "s_register_operand" "")
3887         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3888   "TARGET_32BIT && TARGET_HARD_FLOAT"
3889   "
3890   if (TARGET_MAVERICK)
3891     {
3892       if (!cirrus_fp_register (operands[0], SImode))
3893         operands[0] = force_reg (SImode, operands[0]);
3894       if (!cirrus_fp_register (operands[1], SFmode))
3895         operands[1] = force_reg (SFmode, operands[0]);
3896       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3897       DONE;
3898     }
3899 ")
3900
3901 (define_expand "fix_truncdfsi2"
3902   [(set (match_operand:SI         0 "s_register_operand" "")
3903         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3904   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
3905   "
3906   if (TARGET_MAVERICK)
3907     {
3908       if (!cirrus_fp_register (operands[1], DFmode))
3909         operands[1] = force_reg (DFmode, operands[0]);
3910       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3911       DONE;
3912     }
3913 ")
3914
3915 ;; Truncation insns
3916
3917 (define_expand "truncdfsf2"
3918   [(set (match_operand:SF  0 "s_register_operand" "")
3919         (float_truncate:SF
3920          (match_operand:DF 1 "s_register_operand" "")))]
3921   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
3922   ""
3923 )
3924
3925 /* DFmode -> HFmode conversions have to go through SFmode.  */
3926 (define_expand "truncdfhf2"
3927   [(set (match_operand:HF  0 "general_operand" "")
3928         (float_truncate:HF
3929          (match_operand:DF 1 "general_operand" "")))]
3930   "TARGET_EITHER"
3931   "
3932   {
3933     rtx op1;
3934     op1 = convert_to_mode (SFmode, operands[1], 0);
3935     op1 = convert_to_mode (HFmode, op1, 0);
3936     emit_move_insn (operands[0], op1);
3937     DONE;
3938   }"
3939 )
3940 \f
3941 ;; Zero and sign extension instructions.
3942
3943 (define_expand "zero_extendsidi2"
3944   [(set (match_operand:DI 0 "s_register_operand" "")
3945         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
3946   "TARGET_32BIT"
3947   ""
3948 )
3949
3950 (define_insn "*arm_zero_extendsidi2"
3951   [(set (match_operand:DI 0 "s_register_operand" "=r")
3952         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3953   "TARGET_ARM"
3954   "*
3955     if (REGNO (operands[1])
3956         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3957       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3958     return \"mov%?\\t%R0, #0\";
3959   "
3960   [(set_attr "length" "8")
3961    (set_attr "predicable" "yes")]
3962 )
3963
3964 (define_expand "zero_extendqidi2"
3965   [(set (match_operand:DI                 0 "s_register_operand"  "")
3966         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))]
3967   "TARGET_32BIT"
3968   ""
3969 )
3970
3971 (define_insn "*arm_zero_extendqidi2"
3972   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3973         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3974   "TARGET_ARM"
3975   "@
3976    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3977    ldr%(b%)\\t%Q0, %1\;mov%?\\t%R0, #0"
3978   [(set_attr "length" "8")
3979    (set_attr "predicable" "yes")
3980    (set_attr "type" "*,load_byte")
3981    (set_attr "pool_range" "*,4092")
3982    (set_attr "neg_pool_range" "*,4084")]
3983 )
3984
3985 (define_expand "extendsidi2"
3986   [(set (match_operand:DI 0 "s_register_operand" "")
3987         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
3988   "TARGET_32BIT"
3989   ""
3990 )
3991
3992 (define_insn "*arm_extendsidi2"
3993   [(set (match_operand:DI 0 "s_register_operand" "=r")
3994         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3995   "TARGET_ARM"
3996   "*
3997     if (REGNO (operands[1])
3998         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3999       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
4000     return \"mov%?\\t%R0, %Q0, asr #31\";
4001   "
4002   [(set_attr "length" "8")
4003    (set_attr "shift" "1")
4004    (set_attr "predicable" "yes")]
4005 )
4006
4007 (define_expand "zero_extendhisi2"
4008   [(set (match_operand:SI 0 "s_register_operand" "")
4009         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
4010   "TARGET_EITHER"
4011 {
4012   if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
4013     {
4014       emit_insn (gen_movhi_bytes (operands[0], operands[1]));
4015       DONE;
4016     }
4017   if (!arm_arch6 && !MEM_P (operands[1]))
4018     {
4019       rtx t = gen_lowpart (SImode, operands[1]);
4020       rtx tmp = gen_reg_rtx (SImode);
4021       emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4022       emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
4023       DONE;
4024     }
4025 })
4026
4027 (define_split
4028   [(set (match_operand:SI 0 "register_operand" "")
4029         (zero_extend:SI (match_operand:HI 1 "register_operand" "l,m")))]
4030   "!TARGET_THUMB2 && !arm_arch6"
4031   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4032    (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4033 {
4034   operands[2] = gen_lowpart (SImode, operands[1]);
4035 })
4036
4037 (define_insn "*thumb1_zero_extendhisi2"
4038   [(set (match_operand:SI 0 "register_operand" "=l,l")
4039         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
4040   "TARGET_THUMB1"
4041   "*
4042   rtx mem;
4043
4044   if (which_alternative == 0 && arm_arch6)
4045     return \"uxth\\t%0, %1\";
4046   if (which_alternative == 0)
4047     return \"#\";
4048
4049   mem = XEXP (operands[1], 0);
4050
4051   if (GET_CODE (mem) == CONST)
4052     mem = XEXP (mem, 0);
4053     
4054   if (GET_CODE (mem) == LABEL_REF)
4055     return \"ldr\\t%0, %1\";
4056     
4057   if (GET_CODE (mem) == PLUS)
4058     {
4059       rtx a = XEXP (mem, 0);
4060       rtx b = XEXP (mem, 1);
4061
4062       /* This can happen due to bugs in reload.  */
4063       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
4064         {
4065           rtx ops[2];
4066           ops[0] = operands[0];
4067           ops[1] = a;
4068       
4069           output_asm_insn (\"mov        %0, %1\", ops);
4070
4071           XEXP (mem, 0) = operands[0];
4072        }
4073
4074       else if (   GET_CODE (a) == LABEL_REF
4075                && GET_CODE (b) == CONST_INT)
4076         return \"ldr\\t%0, %1\";
4077     }
4078     
4079   return \"ldrh\\t%0, %1\";
4080   "
4081   [(set_attr_alternative "length"
4082                          [(if_then_else (eq_attr "is_arch6" "yes")
4083                                        (const_int 2) (const_int 4))
4084                          (const_int 4)])
4085    (set_attr "type" "alu_shift,load_byte")
4086    (set_attr "pool_range" "*,60")]
4087 )
4088
4089 (define_insn "*arm_zero_extendhisi2"
4090   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4091         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4092   "TARGET_ARM && arm_arch4 && !arm_arch6"
4093   "@
4094    #
4095    ldr%(h%)\\t%0, %1"
4096   [(set_attr "type" "alu_shift,load_byte")
4097    (set_attr "predicable" "yes")
4098    (set_attr "pool_range" "*,256")
4099    (set_attr "neg_pool_range" "*,244")]
4100 )
4101
4102 (define_insn "*arm_zero_extendhisi2_v6"
4103   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4104         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4105   "TARGET_ARM && arm_arch6"
4106   "@
4107    uxth%?\\t%0, %1
4108    ldr%(h%)\\t%0, %1"
4109   [(set_attr "type" "alu_shift,load_byte")
4110    (set_attr "predicable" "yes")
4111    (set_attr "pool_range" "*,256")
4112    (set_attr "neg_pool_range" "*,244")]
4113 )
4114
4115 (define_insn "*arm_zero_extendhisi2addsi"
4116   [(set (match_operand:SI 0 "s_register_operand" "=r")
4117         (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4118                  (match_operand:SI 2 "s_register_operand" "r")))]
4119   "TARGET_INT_SIMD"
4120   "uxtah%?\\t%0, %2, %1"
4121   [(set_attr "type" "alu_shift")
4122    (set_attr "predicable" "yes")]
4123 )
4124
4125 (define_expand "zero_extendqisi2"
4126   [(set (match_operand:SI 0 "s_register_operand" "")
4127         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
4128   "TARGET_EITHER"
4129 {
4130   if (TARGET_ARM && !arm_arch6 && GET_CODE (operands[1]) != MEM)
4131     {
4132       emit_insn (gen_andsi3 (operands[0],
4133                              gen_lowpart (SImode, operands[1]),
4134                                           GEN_INT (255)));
4135       DONE;
4136     }
4137   if (!arm_arch6 && !MEM_P (operands[1]))
4138     {
4139       rtx t = gen_lowpart (SImode, operands[1]);
4140       rtx tmp = gen_reg_rtx (SImode);
4141       emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4142       emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
4143       DONE;
4144     }
4145 })
4146
4147 (define_split
4148   [(set (match_operand:SI 0 "register_operand" "")
4149         (zero_extend:SI (match_operand:QI 1 "register_operand" "")))]
4150   "!arm_arch6"
4151   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4152    (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
4153 {
4154   operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4155   if (TARGET_ARM)
4156     {
4157       emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
4158       DONE;
4159     }
4160 })
4161
4162 (define_insn "*thumb1_zero_extendqisi2"
4163   [(set (match_operand:SI 0 "register_operand" "=l,l")
4164         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
4165   "TARGET_THUMB1 && !arm_arch6"
4166   "@
4167    #
4168    ldrb\\t%0, %1"
4169   [(set_attr "length" "4,2")
4170    (set_attr "type" "alu_shift,load_byte")
4171    (set_attr "pool_range" "*,32")]
4172 )
4173
4174 (define_insn "*thumb1_zero_extendqisi2_v6"
4175   [(set (match_operand:SI 0 "register_operand" "=l,l")
4176         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
4177   "TARGET_THUMB1 && arm_arch6"
4178   "@
4179    uxtb\\t%0, %1
4180    ldrb\\t%0, %1"
4181   [(set_attr "length" "2,2")
4182    (set_attr "type" "alu_shift,load_byte")
4183    (set_attr "pool_range" "*,32")]
4184 )
4185
4186 (define_insn "*arm_zero_extendqisi2"
4187   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4188         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4189   "TARGET_ARM && !arm_arch6"
4190   "@
4191    #
4192    ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
4193   [(set_attr "length" "8,4")
4194    (set_attr "type" "alu_shift,load_byte")
4195    (set_attr "predicable" "yes")
4196    (set_attr "pool_range" "*,4096")
4197    (set_attr "neg_pool_range" "*,4084")]
4198 )
4199
4200 (define_insn "*arm_zero_extendqisi2_v6"
4201   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4202         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4203   "TARGET_ARM && arm_arch6"
4204   "@
4205    uxtb%(%)\\t%0, %1
4206    ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
4207   [(set_attr "type" "alu_shift,load_byte")
4208    (set_attr "predicable" "yes")
4209    (set_attr "pool_range" "*,4096")
4210    (set_attr "neg_pool_range" "*,4084")]
4211 )
4212
4213 (define_insn "*arm_zero_extendqisi2addsi"
4214   [(set (match_operand:SI 0 "s_register_operand" "=r")
4215         (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4216                  (match_operand:SI 2 "s_register_operand" "r")))]
4217   "TARGET_INT_SIMD"
4218   "uxtab%?\\t%0, %2, %1"
4219   [(set_attr "predicable" "yes")
4220    (set_attr "insn" "xtab")
4221    (set_attr "type" "alu_shift")]
4222 )
4223
4224 (define_split
4225   [(set (match_operand:SI 0 "s_register_operand" "")
4226         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
4227    (clobber (match_operand:SI 2 "s_register_operand" ""))]
4228   "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
4229   [(set (match_dup 2) (match_dup 1))
4230    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4231   ""
4232 )
4233
4234 (define_split
4235   [(set (match_operand:SI 0 "s_register_operand" "")
4236         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
4237    (clobber (match_operand:SI 2 "s_register_operand" ""))]
4238   "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
4239   [(set (match_dup 2) (match_dup 1))
4240    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4241   ""
4242 )
4243
4244 (define_code_iterator ior_xor [ior xor])
4245
4246 (define_split
4247   [(set (match_operand:SI 0 "s_register_operand" "")
4248         (ior_xor:SI (and:SI (ashift:SI
4249                              (match_operand:SI 1 "s_register_operand" "")
4250                              (match_operand:SI 2 "const_int_operand" ""))
4251                             (match_operand:SI 3 "const_int_operand" ""))
4252                     (zero_extend:SI
4253                      (match_operator 5 "subreg_lowpart_operator"
4254                       [(match_operand:SI 4 "s_register_operand" "")]))))]
4255   "TARGET_32BIT
4256    && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
4257        == (GET_MODE_MASK (GET_MODE (operands[5]))
4258            & (GET_MODE_MASK (GET_MODE (operands[5]))
4259               << (INTVAL (operands[2])))))"
4260   [(set (match_dup 0) (ior_xor:SI (ashift:SI (match_dup 1) (match_dup 2))
4261                                   (match_dup 4)))
4262    (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
4263   "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
4264 )
4265
4266 (define_insn "*compareqi_eq0"
4267   [(set (reg:CC_Z CC_REGNUM)
4268         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
4269                          (const_int 0)))]
4270   "TARGET_32BIT"
4271   "tst\\t%0, #255"
4272   [(set_attr "conds" "set")]
4273 )
4274
4275 (define_expand "extendhisi2"
4276   [(set (match_operand:SI 0 "s_register_operand" "")
4277         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
4278   "TARGET_EITHER"
4279 {
4280   if (TARGET_THUMB1)
4281     {
4282       emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
4283       DONE;
4284     }
4285   if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
4286     {
4287       emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
4288       DONE;
4289     }
4290
4291   if (!arm_arch6 && !MEM_P (operands[1]))
4292     {
4293       rtx t = gen_lowpart (SImode, operands[1]);
4294       rtx tmp = gen_reg_rtx (SImode);
4295       emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4296       emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
4297       DONE;
4298     }
4299 })
4300
4301 (define_split
4302   [(parallel
4303     [(set (match_operand:SI 0 "register_operand" "")
4304           (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
4305      (clobber (match_scratch:SI 2 ""))])]
4306   "!arm_arch6"
4307   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4308    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4309 {
4310   operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4311 })
4312
4313 ;; We used to have an early-clobber on the scratch register here.
4314 ;; However, there's a bug somewhere in reload which means that this
4315 ;; can be partially ignored during spill allocation if the memory
4316 ;; address also needs reloading; this causes us to die later on when
4317 ;; we try to verify the operands.  Fortunately, we don't really need
4318 ;; the early-clobber: we can always use operand 0 if operand 2
4319 ;; overlaps the address.
4320 (define_insn "thumb1_extendhisi2"
4321   [(set (match_operand:SI 0 "register_operand" "=l,l")
4322         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
4323    (clobber (match_scratch:SI 2 "=X,l"))]
4324   "TARGET_THUMB1"
4325   "*
4326   {
4327     rtx ops[4];
4328     rtx mem;
4329
4330     if (which_alternative == 0 && !arm_arch6)
4331       return \"#\";
4332     if (which_alternative == 0)
4333       return \"sxth\\t%0, %1\";
4334
4335     mem = XEXP (operands[1], 0);
4336
4337     /* This code used to try to use 'V', and fix the address only if it was
4338        offsettable, but this fails for e.g. REG+48 because 48 is outside the
4339        range of QImode offsets, and offsettable_address_p does a QImode
4340        address check.  */
4341        
4342     if (GET_CODE (mem) == CONST)
4343       mem = XEXP (mem, 0);
4344     
4345     if (GET_CODE (mem) == LABEL_REF)
4346       return \"ldr\\t%0, %1\";
4347     
4348     if (GET_CODE (mem) == PLUS)
4349       {
4350         rtx a = XEXP (mem, 0);
4351         rtx b = XEXP (mem, 1);
4352
4353         if (GET_CODE (a) == LABEL_REF
4354             && GET_CODE (b) == CONST_INT)
4355           return \"ldr\\t%0, %1\";
4356
4357         if (GET_CODE (b) == REG)
4358           return \"ldrsh\\t%0, %1\";
4359           
4360         ops[1] = a;
4361         ops[2] = b;
4362       }
4363     else
4364       {
4365         ops[1] = mem;
4366         ops[2] = const0_rtx;
4367       }
4368       
4369     gcc_assert (GET_CODE (ops[1]) == REG);
4370
4371     ops[0] = operands[0];
4372     if (reg_mentioned_p (operands[2], ops[1]))
4373       ops[3] = ops[0];
4374     else
4375       ops[3] = operands[2];
4376     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4377     return \"\";
4378   }"
4379   [(set_attr_alternative "length"
4380                          [(if_then_else (eq_attr "is_arch6" "yes")
4381                                         (const_int 2) (const_int 4))
4382                           (const_int 4)])
4383    (set_attr "type" "alu_shift,load_byte")
4384    (set_attr "pool_range" "*,1020")]
4385 )
4386
4387 ;; This pattern will only be used when ldsh is not available
4388 (define_expand "extendhisi2_mem"
4389   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4390    (set (match_dup 3)
4391         (zero_extend:SI (match_dup 7)))
4392    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4393    (set (match_operand:SI 0 "" "")
4394         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
4395   "TARGET_ARM"
4396   "
4397   {
4398     rtx mem1, mem2;
4399     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4400
4401     mem1 = change_address (operands[1], QImode, addr);
4402     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
4403     operands[0] = gen_lowpart (SImode, operands[0]);
4404     operands[1] = mem1;
4405     operands[2] = gen_reg_rtx (SImode);
4406     operands[3] = gen_reg_rtx (SImode);
4407     operands[6] = gen_reg_rtx (SImode);
4408     operands[7] = mem2;
4409
4410     if (BYTES_BIG_ENDIAN)
4411       {
4412         operands[4] = operands[2];
4413         operands[5] = operands[3];
4414       }
4415     else
4416       {
4417         operands[4] = operands[3];
4418         operands[5] = operands[2];
4419       }
4420   }"
4421 )
4422
4423 (define_split
4424   [(set (match_operand:SI 0 "register_operand" "")
4425         (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
4426   "!arm_arch6"
4427   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4428    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4429 {
4430   operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4431 })
4432
4433 (define_insn "*arm_extendhisi2"
4434   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4435         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4436   "TARGET_ARM && arm_arch4 && !arm_arch6"
4437   "@
4438    #
4439    ldr%(sh%)\\t%0, %1"
4440   [(set_attr "length" "8,4")
4441    (set_attr "type" "alu_shift,load_byte")
4442    (set_attr "predicable" "yes")
4443    (set_attr "pool_range" "*,256")
4444    (set_attr "neg_pool_range" "*,244")]
4445 )
4446
4447 ;; ??? Check Thumb-2 pool range
4448 (define_insn "*arm_extendhisi2_v6"
4449   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4450         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4451   "TARGET_32BIT && arm_arch6"
4452   "@
4453    sxth%?\\t%0, %1
4454    ldr%(sh%)\\t%0, %1"
4455   [(set_attr "type" "alu_shift,load_byte")
4456    (set_attr "predicable" "yes")
4457    (set_attr "pool_range" "*,256")
4458    (set_attr "neg_pool_range" "*,244")]
4459 )
4460
4461 (define_insn "*arm_extendhisi2addsi"
4462   [(set (match_operand:SI 0 "s_register_operand" "=r")
4463         (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4464                  (match_operand:SI 2 "s_register_operand" "r")))]
4465   "TARGET_INT_SIMD"
4466   "sxtah%?\\t%0, %2, %1"
4467 )
4468
4469 (define_expand "extendqihi2"
4470   [(set (match_dup 2)
4471         (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
4472                    (const_int 24)))
4473    (set (match_operand:HI 0 "s_register_operand" "")
4474         (ashiftrt:SI (match_dup 2)
4475                      (const_int 24)))]
4476   "TARGET_ARM"
4477   "
4478   {
4479     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
4480       {
4481         emit_insn (gen_rtx_SET (VOIDmode,
4482                                 operands[0],
4483                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
4484         DONE;
4485       }
4486     if (!s_register_operand (operands[1], QImode))
4487       operands[1] = copy_to_mode_reg (QImode, operands[1]);
4488     operands[0] = gen_lowpart (SImode, operands[0]);
4489     operands[1] = gen_lowpart (SImode, operands[1]);
4490     operands[2] = gen_reg_rtx (SImode);
4491   }"
4492 )
4493
4494 (define_insn "*arm_extendqihi_insn"
4495   [(set (match_operand:HI 0 "s_register_operand" "=r")
4496         (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
4497   "TARGET_ARM && arm_arch4"
4498   "ldr%(sb%)\\t%0, %1"
4499   [(set_attr "type" "load_byte")
4500    (set_attr "predicable" "yes")
4501    (set_attr "pool_range" "256")
4502    (set_attr "neg_pool_range" "244")]
4503 )
4504
4505 (define_expand "extendqisi2"
4506   [(set (match_operand:SI 0 "s_register_operand" "")
4507         (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
4508   "TARGET_EITHER"
4509 {
4510   if (!arm_arch4 && MEM_P (operands[1]))
4511     operands[1] = copy_to_mode_reg (QImode, operands[1]);
4512
4513   if (!arm_arch6 && !MEM_P (operands[1]))
4514     {
4515       rtx t = gen_lowpart (SImode, operands[1]);
4516       rtx tmp = gen_reg_rtx (SImode);
4517       emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4518       emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
4519       DONE;
4520     }
4521 })
4522
4523 (define_split
4524   [(set (match_operand:SI 0 "register_operand" "")
4525         (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
4526   "!arm_arch6"
4527   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4528    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
4529 {
4530   operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4531 })
4532
4533 (define_insn "*arm_extendqisi"
4534   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4535         (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
4536   "TARGET_ARM && arm_arch4 && !arm_arch6"
4537   "@
4538    #
4539    ldr%(sb%)\\t%0, %1"
4540   [(set_attr "length" "8,4")
4541    (set_attr "type" "alu_shift,load_byte")
4542    (set_attr "predicable" "yes")
4543    (set_attr "pool_range" "*,256")
4544    (set_attr "neg_pool_range" "*,244")]
4545 )
4546
4547 (define_insn "*arm_extendqisi_v6"
4548   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4549         (sign_extend:SI
4550          (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
4551   "TARGET_ARM && arm_arch6"
4552   "@
4553    sxtb%?\\t%0, %1
4554    ldr%(sb%)\\t%0, %1"
4555   [(set_attr "type" "alu_shift,load_byte")
4556    (set_attr "predicable" "yes")
4557    (set_attr "pool_range" "*,256")
4558    (set_attr "neg_pool_range" "*,244")]
4559 )
4560
4561 (define_insn "*arm_extendqisi2addsi"
4562   [(set (match_operand:SI 0 "s_register_operand" "=r")
4563         (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4564                  (match_operand:SI 2 "s_register_operand" "r")))]
4565   "TARGET_INT_SIMD"
4566   "sxtab%?\\t%0, %2, %1"
4567   [(set_attr "type" "alu_shift")
4568    (set_attr "insn" "xtab")
4569    (set_attr "predicable" "yes")]
4570 )
4571
4572 (define_split
4573   [(set (match_operand:SI 0 "register_operand" "")
4574         (sign_extend:SI (match_operand:QI 1 "memory_operand" "")))]
4575   "TARGET_THUMB1 && reload_completed"
4576   [(set (match_dup 0) (match_dup 2))
4577    (set (match_dup 0) (sign_extend:SI (match_dup 3)))]
4578 {
4579   rtx addr = XEXP (operands[1], 0);
4580
4581   if (GET_CODE (addr) == CONST)
4582     addr = XEXP (addr, 0);
4583
4584   if (GET_CODE (addr) == PLUS
4585       && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
4586     /* No split necessary.  */
4587     FAIL;
4588
4589   if (GET_CODE (addr) == PLUS
4590       && !REG_P (XEXP (addr, 0)) && !REG_P (XEXP (addr, 1)))
4591     FAIL;
4592
4593   if (reg_overlap_mentioned_p (operands[0], addr))
4594     {
4595       rtx t = gen_lowpart (QImode, operands[0]);
4596       emit_move_insn (t, operands[1]);
4597       emit_insn (gen_thumb1_extendqisi2 (operands[0], t));
4598       DONE;
4599     }
4600
4601   if (REG_P (addr))
4602     {
4603       addr = gen_rtx_PLUS (Pmode, addr, operands[0]);
4604       operands[2] = const0_rtx;
4605     }
4606   else if (GET_CODE (addr) != PLUS)
4607     FAIL;
4608   else if (REG_P (XEXP (addr, 0)))
4609     {
4610       operands[2] = XEXP (addr, 1);
4611       addr = gen_rtx_PLUS (Pmode, XEXP (addr, 0), operands[0]);
4612     }
4613   else
4614     {
4615       operands[2] = XEXP (addr, 0);
4616       addr = gen_rtx_PLUS (Pmode, XEXP (addr, 1), operands[0]);
4617     }
4618
4619   operands[3] = change_address (operands[1], QImode, addr);
4620 })
4621
4622 (define_insn "thumb1_extendqisi2"
4623   [(set (match_operand:SI 0 "register_operand" "=l,l,l")
4624         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
4625   "TARGET_THUMB1"
4626 {
4627   rtx addr;
4628
4629   if (which_alternative == 0 && arm_arch6)
4630     return "sxtb\\t%0, %1";
4631   if (which_alternative == 0)
4632     return "#";
4633
4634   addr = XEXP (operands[1], 0);
4635   if (GET_CODE (addr) == PLUS
4636       && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
4637     return "ldrsb\\t%0, %1";
4638       
4639   return "#";
4640 }
4641   [(set_attr_alternative "length"
4642                          [(if_then_else (eq_attr "is_arch6" "yes")
4643                                         (const_int 2) (const_int 4))
4644                           (const_int 2)
4645                           (if_then_else (eq_attr "is_arch6" "yes")
4646                                         (const_int 4) (const_int 6))])
4647    (set_attr "type" "alu_shift,load_byte,load_byte")]
4648 )
4649
4650 (define_expand "extendsfdf2"
4651   [(set (match_operand:DF                  0 "s_register_operand" "")
4652         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
4653   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
4654   ""
4655 )
4656
4657 /* HFmode -> DFmode conversions have to go through SFmode.  */
4658 (define_expand "extendhfdf2"
4659   [(set (match_operand:DF                  0 "general_operand" "")
4660         (float_extend:DF (match_operand:HF 1 "general_operand"  "")))]
4661   "TARGET_EITHER"
4662   "
4663   {
4664     rtx op1;
4665     op1 = convert_to_mode (SFmode, operands[1], 0);
4666     op1 = convert_to_mode (DFmode, op1, 0);
4667     emit_insn (gen_movdf (operands[0], op1));
4668     DONE;
4669   }"
4670 )
4671 \f
4672 ;; Move insns (including loads and stores)
4673
4674 ;; XXX Just some ideas about movti.
4675 ;; I don't think these are a good idea on the arm, there just aren't enough
4676 ;; registers
4677 ;;(define_expand "loadti"
4678 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
4679 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
4680 ;;  "" "")
4681
4682 ;;(define_expand "storeti"
4683 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4684 ;;      (match_operand:TI 1 "s_register_operand" ""))]
4685 ;;  "" "")
4686
4687 ;;(define_expand "movti"
4688 ;;  [(set (match_operand:TI 0 "general_operand" "")
4689 ;;      (match_operand:TI 1 "general_operand" ""))]
4690 ;;  ""
4691 ;;  "
4692 ;;{
4693 ;;  rtx insn;
4694 ;;
4695 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4696 ;;    operands[1] = copy_to_reg (operands[1]);
4697 ;;  if (GET_CODE (operands[0]) == MEM)
4698 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4699 ;;  else if (GET_CODE (operands[1]) == MEM)
4700 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4701 ;;  else
4702 ;;    FAIL;
4703 ;;
4704 ;;  emit_insn (insn);
4705 ;;  DONE;
4706 ;;}")
4707
4708 ;; Recognize garbage generated above.
4709
4710 ;;(define_insn ""
4711 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4712 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4713 ;;  ""
4714 ;;  "*
4715 ;;  {
4716 ;;    register mem = (which_alternative < 3);
4717 ;;    register const char *template;
4718 ;;
4719 ;;    operands[mem] = XEXP (operands[mem], 0);
4720 ;;    switch (which_alternative)
4721 ;;      {
4722 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4723 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
4724 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
4725 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
4726 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
4727 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
4728 ;;      }
4729 ;;    output_asm_insn (template, operands);
4730 ;;    return \"\";
4731 ;;  }")
4732
4733 (define_expand "movdi"
4734   [(set (match_operand:DI 0 "general_operand" "")
4735         (match_operand:DI 1 "general_operand" ""))]
4736   "TARGET_EITHER"
4737   "
4738   if (can_create_pseudo_p ())
4739     {
4740       if (GET_CODE (operands[0]) != REG)
4741         operands[1] = force_reg (DImode, operands[1]);
4742     }
4743   "
4744 )
4745
4746 (define_insn "*arm_movdi"
4747   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4748         (match_operand:DI 1 "di_operand"              "rDa,Db,Dc,mi,r"))]
4749   "TARGET_ARM
4750    && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4751    && !TARGET_IWMMXT
4752    && (   register_operand (operands[0], DImode)
4753        || register_operand (operands[1], DImode))"
4754   "*
4755   switch (which_alternative)
4756     {
4757     case 0:
4758     case 1:
4759     case 2:
4760       return \"#\";
4761     default:
4762       return output_move_double (operands);
4763     }
4764   "
4765   [(set_attr "length" "8,12,16,8,8")
4766    (set_attr "type" "*,*,*,load2,store2")
4767    (set_attr "pool_range" "*,*,*,1020,*")
4768    (set_attr "neg_pool_range" "*,*,*,1008,*")]
4769 )
4770
4771 (define_split
4772   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4773         (match_operand:ANY64 1 "const_double_operand" ""))]
4774   "TARGET_32BIT
4775    && reload_completed
4776    && (arm_const_double_inline_cost (operands[1])
4777        <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4778   [(const_int 0)]
4779   "
4780   arm_split_constant (SET, SImode, curr_insn,
4781                       INTVAL (gen_lowpart (SImode, operands[1])),
4782                       gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4783   arm_split_constant (SET, SImode, curr_insn,
4784                       INTVAL (gen_highpart_mode (SImode,
4785                                                  GET_MODE (operands[0]),
4786                                                  operands[1])),
4787                       gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4788   DONE;
4789   "
4790 )
4791
4792 ; If optimizing for size, or if we have load delay slots, then 
4793 ; we want to split the constant into two separate operations. 
4794 ; In both cases this may split a trivial part into a single data op
4795 ; leaving a single complex constant to load.  We can also get longer
4796 ; offsets in a LDR which means we get better chances of sharing the pool
4797 ; entries.  Finally, we can normally do a better job of scheduling
4798 ; LDR instructions than we can with LDM.
4799 ; This pattern will only match if the one above did not.
4800 (define_split
4801   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4802         (match_operand:ANY64 1 "const_double_operand" ""))]
4803   "TARGET_ARM && reload_completed
4804    && arm_const_double_by_parts (operands[1])"
4805   [(set (match_dup 0) (match_dup 1))
4806    (set (match_dup 2) (match_dup 3))]
4807   "
4808   operands[2] = gen_highpart (SImode, operands[0]);
4809   operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4810                                    operands[1]);
4811   operands[0] = gen_lowpart (SImode, operands[0]);
4812   operands[1] = gen_lowpart (SImode, operands[1]);
4813   "
4814 )
4815
4816 (define_split
4817   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4818         (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4819   "TARGET_EITHER && reload_completed"
4820   [(set (match_dup 0) (match_dup 1))
4821    (set (match_dup 2) (match_dup 3))]
4822   "
4823   operands[2] = gen_highpart (SImode, operands[0]);
4824   operands[3] = gen_highpart (SImode, operands[1]);
4825   operands[0] = gen_lowpart (SImode, operands[0]);
4826   operands[1] = gen_lowpart (SImode, operands[1]);
4827
4828   /* Handle a partial overlap.  */
4829   if (rtx_equal_p (operands[0], operands[3]))
4830     {
4831       rtx tmp0 = operands[0];
4832       rtx tmp1 = operands[1];
4833
4834       operands[0] = operands[2];
4835       operands[1] = operands[3];
4836       operands[2] = tmp0;
4837       operands[3] = tmp1;
4838     }
4839   "
4840 )
4841
4842 ;; We can't actually do base+index doubleword loads if the index and
4843 ;; destination overlap.  Split here so that we at least have chance to
4844 ;; schedule.
4845 (define_split
4846   [(set (match_operand:DI 0 "s_register_operand" "")
4847         (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4848                          (match_operand:SI 2 "s_register_operand" ""))))]
4849   "TARGET_LDRD
4850   && reg_overlap_mentioned_p (operands[0], operands[1])
4851   && reg_overlap_mentioned_p (operands[0], operands[2])"
4852   [(set (match_dup 4)
4853         (plus:SI (match_dup 1)
4854                  (match_dup 2)))
4855    (set (match_dup 0)
4856         (mem:DI (match_dup 4)))]
4857   "
4858   operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4859   "
4860 )
4861
4862 ;;; ??? This should have alternatives for constants.
4863 ;;; ??? This was originally identical to the movdf_insn pattern.
4864 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4865 ;;; thumb_reorg with a memory reference.
4866 (define_insn "*thumb1_movdi_insn"
4867   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4868         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
4869   "TARGET_THUMB1
4870    && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4871    && (   register_operand (operands[0], DImode)
4872        || register_operand (operands[1], DImode))"
4873   "*
4874   {
4875   switch (which_alternative)
4876     {
4877     default:
4878     case 0:
4879       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4880         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
4881       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
4882     case 1:
4883       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4884     case 2:
4885       operands[1] = GEN_INT (- INTVAL (operands[1]));
4886       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4887     case 3:
4888       return \"ldmia\\t%1, {%0, %H0}\";
4889     case 4:
4890       return \"stmia\\t%0, {%1, %H1}\";
4891     case 5:
4892       return thumb_load_double_from_address (operands);
4893     case 6:
4894       operands[2] = gen_rtx_MEM (SImode,
4895                              plus_constant (XEXP (operands[0], 0), 4));
4896       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4897       return \"\";
4898     case 7:
4899       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4900         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4901       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4902     }
4903   }"
4904   [(set_attr "length" "4,4,6,2,2,6,4,4")
4905    (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4906    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4907 )
4908
4909 (define_expand "movsi"
4910   [(set (match_operand:SI 0 "general_operand" "")
4911         (match_operand:SI 1 "general_operand" ""))]
4912   "TARGET_EITHER"
4913   "
4914   {
4915   rtx base, offset, tmp;
4916
4917   if (TARGET_32BIT)
4918     {
4919       /* Everything except mem = const or mem = mem can be done easily.  */
4920       if (GET_CODE (operands[0]) == MEM)
4921         operands[1] = force_reg (SImode, operands[1]);
4922       if (arm_general_register_operand (operands[0], SImode)
4923           && GET_CODE (operands[1]) == CONST_INT
4924           && !(const_ok_for_arm (INTVAL (operands[1]))
4925                || const_ok_for_arm (~INTVAL (operands[1]))))
4926         {
4927            arm_split_constant (SET, SImode, NULL_RTX,
4928                                INTVAL (operands[1]), operands[0], NULL_RTX,
4929                                optimize && can_create_pseudo_p ());
4930           DONE;
4931         }
4932
4933       if (TARGET_USE_MOVT && !target_word_relocations
4934           && GET_CODE (operands[1]) == SYMBOL_REF
4935           && !flag_pic && !arm_tls_referenced_p (operands[1]))
4936         {
4937           arm_emit_movpair (operands[0], operands[1]);
4938           DONE;
4939         }
4940     }
4941   else /* TARGET_THUMB1...  */
4942     {
4943       if (can_create_pseudo_p ())
4944         {
4945           if (GET_CODE (operands[0]) != REG)
4946             operands[1] = force_reg (SImode, operands[1]);
4947         }
4948     }
4949
4950   if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
4951     {
4952       split_const (operands[1], &base, &offset);
4953       if (GET_CODE (base) == SYMBOL_REF
4954           && !offset_within_block_p (base, INTVAL (offset)))
4955         {
4956           tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
4957           emit_move_insn (tmp, base);
4958           emit_insn (gen_addsi3 (operands[0], tmp, offset));
4959           DONE;
4960         }
4961     }
4962
4963   /* Recognize the case where operand[1] is a reference to thread-local
4964      data and load its address to a register.  */
4965   if (arm_tls_referenced_p (operands[1]))
4966     {
4967       rtx tmp = operands[1];
4968       rtx addend = NULL;
4969
4970       if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
4971         {
4972           addend = XEXP (XEXP (tmp, 0), 1);
4973           tmp = XEXP (XEXP (tmp, 0), 0);
4974         }
4975
4976       gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
4977       gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
4978
4979       tmp = legitimize_tls_address (tmp,
4980                                     !can_create_pseudo_p () ? operands[0] : 0);
4981       if (addend)
4982         {
4983           tmp = gen_rtx_PLUS (SImode, tmp, addend);
4984           tmp = force_operand (tmp, operands[0]);
4985         }
4986       operands[1] = tmp;
4987     }
4988   else if (flag_pic
4989            && (CONSTANT_P (operands[1])
4990                || symbol_mentioned_p (operands[1])
4991                || label_mentioned_p (operands[1])))
4992       operands[1] = legitimize_pic_address (operands[1], SImode,
4993                                             (!can_create_pseudo_p ()
4994                                              ? operands[0]
4995                                              : 0));
4996   }
4997   "
4998 )
4999
5000 ;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5001 ;; LO_SUM adds in the high bits.  Fortunately these are opaque operations
5002 ;; so this does not matter.
5003 (define_insn "*arm_movt"
5004   [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5005         (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5006                    (match_operand:SI 2 "general_operand"      "i")))]
5007   "TARGET_32BIT"
5008   "movt%?\t%0, #:upper16:%c2"
5009   [(set_attr "predicable" "yes")
5010    (set_attr "length" "4")]
5011 )
5012
5013 (define_insn "*arm_movsi_insn"
5014   [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
5015         (match_operand:SI 1 "general_operand"      "rk, I,K,j,mi,rk"))]
5016   "TARGET_ARM && ! TARGET_IWMMXT
5017    && !(TARGET_HARD_FLOAT && TARGET_VFP)
5018    && (   register_operand (operands[0], SImode)
5019        || register_operand (operands[1], SImode))"
5020   "@
5021    mov%?\\t%0, %1
5022    mov%?\\t%0, %1
5023    mvn%?\\t%0, #%B1
5024    movw%?\\t%0, %1
5025    ldr%?\\t%0, %1
5026    str%?\\t%1, %0"
5027   [(set_attr "type" "*,*,*,*,load1,store1")
5028    (set_attr "predicable" "yes")
5029    (set_attr "pool_range" "*,*,*,*,4096,*")
5030    (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
5031 )
5032
5033 (define_split
5034   [(set (match_operand:SI 0 "arm_general_register_operand" "")
5035         (match_operand:SI 1 "const_int_operand" ""))]
5036   "TARGET_32BIT
5037   && (!(const_ok_for_arm (INTVAL (operands[1]))
5038         || const_ok_for_arm (~INTVAL (operands[1]))))"
5039   [(clobber (const_int 0))]
5040   "
5041   arm_split_constant (SET, SImode, NULL_RTX, 
5042                       INTVAL (operands[1]), operands[0], NULL_RTX, 0);
5043   DONE;
5044   "
5045 )
5046
5047 (define_insn "*thumb1_movsi_insn"
5048   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lhk")
5049         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lhk"))]
5050   "TARGET_THUMB1
5051    && (   register_operand (operands[0], SImode) 
5052        || register_operand (operands[1], SImode))"
5053   "@
5054    mov  %0, %1
5055    mov  %0, %1
5056    #
5057    #
5058    ldmia\\t%1, {%0}
5059    stmia\\t%0, {%1}
5060    ldr\\t%0, %1
5061    str\\t%1, %0
5062    mov\\t%0, %1"
5063   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
5064    (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
5065    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
5066 )
5067
5068 (define_split 
5069   [(set (match_operand:SI 0 "register_operand" "")
5070         (match_operand:SI 1 "const_int_operand" ""))]
5071   "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
5072   [(set (match_dup 0) (match_dup 1))
5073    (set (match_dup 0) (neg:SI (match_dup 0)))]
5074   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
5075 )
5076
5077 (define_split 
5078   [(set (match_operand:SI 0 "register_operand" "")
5079         (match_operand:SI 1 "const_int_operand" ""))]
5080   "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
5081   [(set (match_dup 0) (match_dup 1))
5082    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
5083   "
5084   {
5085     unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu;
5086     unsigned HOST_WIDE_INT mask = 0xff;
5087     int i;
5088     
5089     for (i = 0; i < 25; i++)
5090       if ((val & (mask << i)) == val)
5091         break;
5092
5093     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
5094     if (i == 0)
5095       FAIL;
5096
5097     operands[1] = GEN_INT (val >> i);
5098     operands[2] = GEN_INT (i);
5099   }"
5100 )
5101
5102 ;; When generating pic, we need to load the symbol offset into a register.
5103 ;; So that the optimizer does not confuse this with a normal symbol load
5104 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
5105 ;; since that is the only type of relocation we can use.
5106
5107 ;; The rather odd constraints on the following are to force reload to leave
5108 ;; the insn alone, and to force the minipool generation pass to then move
5109 ;; the GOT symbol to memory.
5110
5111 (define_insn "pic_load_addr_32bit"
5112   [(set (match_operand:SI 0 "s_register_operand" "=r")
5113         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
5114   "TARGET_32BIT && flag_pic"
5115   "ldr%?\\t%0, %1"
5116   [(set_attr "type" "load1")
5117    (set_attr "pool_range" "4096")
5118    (set (attr "neg_pool_range")
5119         (if_then_else (eq_attr "is_thumb" "no")
5120                       (const_int 4084)
5121                       (const_int 0)))]
5122 )
5123
5124 (define_insn "pic_load_addr_thumb1"
5125   [(set (match_operand:SI 0 "s_register_operand" "=l")
5126         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
5127   "TARGET_THUMB1 && flag_pic"
5128   "ldr\\t%0, %1"
5129   [(set_attr "type" "load1")
5130    (set (attr "pool_range") (const_int 1024))]
5131 )
5132
5133 (define_insn "pic_add_dot_plus_four"
5134   [(set (match_operand:SI 0 "register_operand" "=r")
5135         (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5136                     (const_int 4)
5137                     (match_operand 2 "" "")]
5138                    UNSPEC_PIC_BASE))]
5139   "TARGET_THUMB"
5140   "*
5141   (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5142                                      INTVAL (operands[2]));
5143   return \"add\\t%0, %|pc\";
5144   "
5145   [(set_attr "length" "2")]
5146 )
5147
5148 (define_insn "pic_add_dot_plus_eight"
5149   [(set (match_operand:SI 0 "register_operand" "=r")
5150         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5151                     (const_int 8)
5152                     (match_operand 2 "" "")]
5153                    UNSPEC_PIC_BASE))]
5154   "TARGET_ARM"
5155   "*
5156     (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5157                                        INTVAL (operands[2]));
5158     return \"add%?\\t%0, %|pc, %1\";
5159   "
5160   [(set_attr "predicable" "yes")]
5161 )
5162
5163 (define_insn "tls_load_dot_plus_eight"
5164   [(set (match_operand:SI 0 "register_operand" "=r")
5165         (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5166                             (const_int 8)
5167                             (match_operand 2 "" "")]
5168                            UNSPEC_PIC_BASE)))]
5169   "TARGET_ARM"
5170   "*
5171     (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5172                                        INTVAL (operands[2]));
5173     return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5174   "
5175   [(set_attr "predicable" "yes")]
5176 )
5177
5178 ;; PIC references to local variables can generate pic_add_dot_plus_eight
5179 ;; followed by a load.  These sequences can be crunched down to
5180 ;; tls_load_dot_plus_eight by a peephole.
5181
5182 (define_peephole2
5183   [(set (match_operand:SI 0 "register_operand" "")
5184         (unspec:SI [(match_operand:SI 3 "register_operand" "")
5185                     (const_int 8)
5186                     (match_operand 1 "" "")]
5187                    UNSPEC_PIC_BASE))
5188    (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
5189   "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
5190   [(set (match_dup 2)
5191         (mem:SI (unspec:SI [(match_dup 3)
5192                             (const_int 8)
5193                             (match_dup 1)]
5194                            UNSPEC_PIC_BASE)))]
5195   ""
5196 )
5197
5198 (define_insn "pic_offset_arm"
5199   [(set (match_operand:SI 0 "register_operand" "=r")
5200         (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5201                          (unspec:SI [(match_operand:SI 2 "" "X")]
5202                                     UNSPEC_PIC_OFFSET))))]
5203   "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5204   "ldr%?\\t%0, [%1,%2]"
5205   [(set_attr "type" "load1")]
5206 )
5207
5208 (define_expand "builtin_setjmp_receiver"
5209   [(label_ref (match_operand 0 "" ""))]
5210   "flag_pic"
5211   "
5212 {
5213   /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5214      register.  */
5215   if (arm_pic_register != INVALID_REGNUM)
5216     arm_load_pic_register (1UL << 3);
5217   DONE;
5218 }")
5219
5220 ;; If copying one reg to another we can set the condition codes according to
5221 ;; its value.  Such a move is common after a return from subroutine and the
5222 ;; result is being tested against zero.
5223
5224 (define_insn "*movsi_compare0"
5225   [(set (reg:CC CC_REGNUM)
5226         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5227                     (const_int 0)))
5228    (set (match_operand:SI 0 "s_register_operand" "=r,r")
5229         (match_dup 1))]
5230   "TARGET_32BIT"
5231   "@
5232    cmp%?\\t%0, #0
5233    sub%.\\t%0, %1, #0"
5234   [(set_attr "conds" "set")]
5235 )
5236
5237 ;; Subroutine to store a half word from a register into memory.
5238 ;; Operand 0 is the source register (HImode)
5239 ;; Operand 1 is the destination address in a register (SImode)
5240
5241 ;; In both this routine and the next, we must be careful not to spill
5242 ;; a memory address of reg+large_const into a separate PLUS insn, since this
5243 ;; can generate unrecognizable rtl.
5244
5245 (define_expand "storehi"
5246   [;; store the low byte
5247    (set (match_operand 1 "" "") (match_dup 3))
5248    ;; extract the high byte
5249    (set (match_dup 2)
5250         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
5251    ;; store the high byte
5252    (set (match_dup 4) (match_dup 5))]
5253   "TARGET_ARM"
5254   "
5255   {
5256     rtx op1 = operands[1];
5257     rtx addr = XEXP (op1, 0);
5258     enum rtx_code code = GET_CODE (addr);
5259
5260     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5261         || code == MINUS)
5262       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
5263
5264     operands[4] = adjust_address (op1, QImode, 1);
5265     operands[1] = adjust_address (operands[1], QImode, 0);
5266     operands[3] = gen_lowpart (QImode, operands[0]);
5267     operands[0] = gen_lowpart (SImode, operands[0]);
5268     operands[2] = gen_reg_rtx (SImode);
5269     operands[5] = gen_lowpart (QImode, operands[2]);
5270   }"
5271 )
5272
5273 (define_expand "storehi_bigend"
5274   [(set (match_dup 4) (match_dup 3))
5275    (set (match_dup 2)
5276         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
5277    (set (match_operand 1 "" "") (match_dup 5))]
5278   "TARGET_ARM"
5279   "
5280   {
5281     rtx op1 = operands[1];
5282     rtx addr = XEXP (op1, 0);
5283     enum rtx_code code = GET_CODE (addr);
5284
5285     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5286         || code == MINUS)
5287       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
5288
5289     operands[4] = adjust_address (op1, QImode, 1);
5290     operands[1] = adjust_address (operands[1], QImode, 0);
5291     operands[3] = gen_lowpart (QImode, operands[0]);
5292     operands[0] = gen_lowpart (SImode, operands[0]);
5293     operands[2] = gen_reg_rtx (SImode);
5294     operands[5] = gen_lowpart (QImode, operands[2]);
5295   }"
5296 )
5297
5298 ;; Subroutine to store a half word integer constant into memory.
5299 (define_expand "storeinthi"
5300   [(set (match_operand 0 "" "")
5301         (match_operand 1 "" ""))
5302    (set (match_dup 3) (match_dup 2))]
5303   "TARGET_ARM"
5304   "
5305   {
5306     HOST_WIDE_INT value = INTVAL (operands[1]);
5307     rtx addr = XEXP (operands[0], 0);
5308     rtx op0 = operands[0];
5309     enum rtx_code code = GET_CODE (addr);
5310
5311     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5312         || code == MINUS)
5313       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
5314
5315     operands[1] = gen_reg_rtx (SImode);
5316     if (BYTES_BIG_ENDIAN)
5317       {
5318         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5319         if ((value & 255) == ((value >> 8) & 255))
5320           operands[2] = operands[1];
5321         else
5322           {
5323             operands[2] = gen_reg_rtx (SImode);
5324             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5325           }
5326       }
5327     else
5328       {
5329         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5330         if ((value & 255) == ((value >> 8) & 255))
5331           operands[2] = operands[1];
5332         else
5333           {
5334             operands[2] = gen_reg_rtx (SImode);
5335             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5336           }
5337       }
5338
5339     operands[3] = adjust_address (op0, QImode, 1);
5340     operands[0] = adjust_address (operands[0], QImode, 0);
5341     operands[2] = gen_lowpart (QImode, operands[2]);
5342     operands[1] = gen_lowpart (QImode, operands[1]);
5343   }"
5344 )
5345
5346 (define_expand "storehi_single_op"
5347   [(set (match_operand:HI 0 "memory_operand" "")
5348         (match_operand:HI 1 "general_operand" ""))]
5349   "TARGET_32BIT && arm_arch4"
5350   "
5351   if (!s_register_operand (operands[1], HImode))
5352     operands[1] = copy_to_mode_reg (HImode, operands[1]);
5353   "
5354 )
5355
5356 (define_expand "movhi"
5357   [(set (match_operand:HI 0 "general_operand" "")
5358         (match_operand:HI 1 "general_operand" ""))]
5359   "TARGET_EITHER"
5360   "
5361   if (TARGET_ARM)
5362     {
5363       if (can_create_pseudo_p ())
5364         {
5365           if (GET_CODE (operands[0]) == MEM)
5366             {
5367               if (arm_arch4)
5368                 {
5369                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5370                   DONE;
5371                 }
5372               if (GET_CODE (operands[1]) == CONST_INT)
5373                 emit_insn (gen_storeinthi (operands[0], operands[1]));
5374               else
5375                 {
5376                   if (GET_CODE (operands[1]) == MEM)
5377                     operands[1] = force_reg (HImode, operands[1]);
5378                   if (BYTES_BIG_ENDIAN)
5379                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
5380                   else
5381                    emit_insn (gen_storehi (operands[1], operands[0]));
5382                 }
5383               DONE;
5384             }
5385           /* Sign extend a constant, and keep it in an SImode reg.  */
5386           else if (GET_CODE (operands[1]) == CONST_INT)
5387             {
5388               rtx reg = gen_reg_rtx (SImode);
5389               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5390
5391               /* If the constant is already valid, leave it alone.  */
5392               if (!const_ok_for_arm (val))
5393                 {
5394                   /* If setting all the top bits will make the constant 
5395                      loadable in a single instruction, then set them.  
5396                      Otherwise, sign extend the number.  */
5397
5398                   if (const_ok_for_arm (~(val | ~0xffff)))
5399                     val |= ~0xffff;
5400                   else if (val & 0x8000)
5401                     val |= ~0xffff;
5402                 }
5403
5404               emit_insn (gen_movsi (reg, GEN_INT (val)));
5405               operands[1] = gen_lowpart (HImode, reg);
5406             }
5407           else if (arm_arch4 && optimize && can_create_pseudo_p ()
5408                    && GET_CODE (operands[1]) == MEM)
5409             {
5410               rtx reg = gen_reg_rtx (SImode);
5411
5412               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5413               operands[1] = gen_lowpart (HImode, reg);
5414             }
5415           else if (!arm_arch4)
5416             {
5417               if (GET_CODE (operands[1]) == MEM)
5418                 {
5419                   rtx base;
5420                   rtx offset = const0_rtx;
5421                   rtx reg = gen_reg_rtx (SImode);
5422
5423                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
5424                        || (GET_CODE (base) == PLUS
5425                            && (GET_CODE (offset = XEXP (base, 1))
5426                                == CONST_INT)
5427                            && ((INTVAL(offset) & 1) != 1)
5428                            && GET_CODE (base = XEXP (base, 0)) == REG))
5429                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
5430                     {
5431                       rtx new_rtx;
5432
5433                       new_rtx = widen_memory_access (operands[1], SImode,
5434                                                      ((INTVAL (offset) & ~3)
5435                                                       - INTVAL (offset)));
5436                       emit_insn (gen_movsi (reg, new_rtx));
5437                       if (((INTVAL (offset) & 2) != 0)
5438                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
5439                         {
5440                           rtx reg2 = gen_reg_rtx (SImode);
5441
5442                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
5443                           reg = reg2;
5444                         }
5445                     }
5446                   else
5447                     emit_insn (gen_movhi_bytes (reg, operands[1]));
5448
5449                   operands[1] = gen_lowpart (HImode, reg);
5450                }
5451            }
5452         }
5453       /* Handle loading a large integer during reload.  */
5454       else if (GET_CODE (operands[1]) == CONST_INT
5455                && !const_ok_for_arm (INTVAL (operands[1]))
5456                && !const_ok_for_arm (~INTVAL (operands[1])))
5457         {
5458           /* Writing a constant to memory needs a scratch, which should
5459              be handled with SECONDARY_RELOADs.  */
5460           gcc_assert (GET_CODE (operands[0]) == REG);
5461
5462           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5463           emit_insn (gen_movsi (operands[0], operands[1]));
5464           DONE;
5465        }
5466     }
5467   else if (TARGET_THUMB2)
5468     {
5469       /* Thumb-2 can do everything except mem=mem and mem=const easily.  */
5470       if (can_create_pseudo_p ())
5471         {
5472           if (GET_CODE (operands[0]) != REG)
5473             operands[1] = force_reg (HImode, operands[1]);
5474           /* Zero extend a constant, and keep it in an SImode reg.  */
5475           else if (GET_CODE (operands[1]) == CONST_INT)
5476             {
5477               rtx reg = gen_reg_rtx (SImode);
5478               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5479
5480               emit_insn (gen_movsi (reg, GEN_INT (val)));
5481               operands[1] = gen_lowpart (HImode, reg);
5482             }
5483         }
5484     }
5485   else /* TARGET_THUMB1 */
5486     {
5487       if (can_create_pseudo_p ())
5488         {
5489           if (GET_CODE (operands[1]) == CONST_INT)
5490             {
5491               rtx reg = gen_reg_rtx (SImode);
5492
5493               emit_insn (gen_movsi (reg, operands[1]));
5494               operands[1] = gen_lowpart (HImode, reg);
5495             }
5496
5497           /* ??? We shouldn't really get invalid addresses here, but this can
5498              happen if we are passed a SP (never OK for HImode/QImode) or 
5499              virtual register (also rejected as illegitimate for HImode/QImode)
5500              relative address.  */
5501           /* ??? This should perhaps be fixed elsewhere, for instance, in
5502              fixup_stack_1, by checking for other kinds of invalid addresses,
5503              e.g. a bare reference to a virtual register.  This may confuse the
5504              alpha though, which must handle this case differently.  */
5505           if (GET_CODE (operands[0]) == MEM
5506               && !memory_address_p (GET_MODE (operands[0]),
5507                                     XEXP (operands[0], 0)))
5508             operands[0]
5509               = replace_equiv_address (operands[0],
5510                                        copy_to_reg (XEXP (operands[0], 0)));
5511    
5512           if (GET_CODE (operands[1]) == MEM
5513               && !memory_address_p (GET_MODE (operands[1]),
5514                                     XEXP (operands[1], 0)))
5515             operands[1]
5516               = replace_equiv_address (operands[1],
5517                                        copy_to_reg (XEXP (operands[1], 0)));
5518
5519           if (GET_CODE (operands[1]) == MEM && optimize > 0)
5520             {
5521               rtx reg = gen_reg_rtx (SImode);
5522
5523               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5524               operands[1] = gen_lowpart (HImode, reg);
5525             }
5526
5527           if (GET_CODE (operands[0]) == MEM)
5528             operands[1] = force_reg (HImode, operands[1]);
5529         }
5530       else if (GET_CODE (operands[1]) == CONST_INT
5531                 && !satisfies_constraint_I (operands[1]))
5532         {
5533           /* Handle loading a large integer during reload.  */
5534
5535           /* Writing a constant to memory needs a scratch, which should
5536              be handled with SECONDARY_RELOADs.  */
5537           gcc_assert (GET_CODE (operands[0]) == REG);
5538
5539           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5540           emit_insn (gen_movsi (operands[0], operands[1]));
5541           DONE;
5542         }
5543     }
5544   "
5545 )
5546
5547 (define_insn "*thumb1_movhi_insn"
5548   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5549         (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
5550   "TARGET_THUMB1
5551    && (   register_operand (operands[0], HImode)
5552        || register_operand (operands[1], HImode))"
5553   "*
5554   switch (which_alternative)
5555     {
5556     case 0: return \"add        %0, %1, #0\";
5557     case 2: return \"strh       %1, %0\";
5558     case 3: return \"mov        %0, %1\";
5559     case 4: return \"mov        %0, %1\";
5560     case 5: return \"mov        %0, %1\";
5561     default: gcc_unreachable ();
5562     case 1:
5563       /* The stack pointer can end up being taken as an index register.
5564           Catch this case here and deal with it.  */
5565       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
5566           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
5567           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
5568         {
5569           rtx ops[2];
5570           ops[0] = operands[0];
5571           ops[1] = XEXP (XEXP (operands[1], 0), 0);
5572       
5573           output_asm_insn (\"mov        %0, %1\", ops);
5574
5575           XEXP (XEXP (operands[1], 0), 0) = operands[0];
5576     
5577         }
5578       return \"ldrh     %0, %1\";
5579     }"
5580   [(set_attr "length" "2,4,2,2,2,2")
5581    (set_attr "type" "*,load1,store1,*,*,*")]
5582 )
5583
5584
5585 (define_expand "movhi_bytes"
5586   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
5587    (set (match_dup 3)
5588         (zero_extend:SI (match_dup 6)))
5589    (set (match_operand:SI 0 "" "")
5590          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
5591   "TARGET_ARM"
5592   "
5593   {
5594     rtx mem1, mem2;
5595     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5596
5597     mem1 = change_address (operands[1], QImode, addr);
5598     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
5599     operands[0] = gen_lowpart (SImode, operands[0]);
5600     operands[1] = mem1;
5601     operands[2] = gen_reg_rtx (SImode);
5602     operands[3] = gen_reg_rtx (SImode);
5603     operands[6] = mem2;
5604
5605     if (BYTES_BIG_ENDIAN)
5606       {
5607         operands[4] = operands[2];
5608         operands[5] = operands[3];
5609       }
5610     else
5611       {
5612         operands[4] = operands[3];
5613         operands[5] = operands[2];
5614       }
5615   }"
5616 )
5617
5618 (define_expand "movhi_bigend"
5619   [(set (match_dup 2)
5620         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
5621                    (const_int 16)))
5622    (set (match_dup 3)
5623         (ashiftrt:SI (match_dup 2) (const_int 16)))
5624    (set (match_operand:HI 0 "s_register_operand" "")
5625         (match_dup 4))]
5626   "TARGET_ARM"
5627   "
5628   operands[2] = gen_reg_rtx (SImode);
5629   operands[3] = gen_reg_rtx (SImode);
5630   operands[4] = gen_lowpart (HImode, operands[3]);
5631   "
5632 )
5633
5634 ;; Pattern to recognize insn generated default case above
5635 (define_insn "*movhi_insn_arch4"
5636   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
5637         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
5638   "TARGET_ARM
5639    && arm_arch4
5640    && (GET_CODE (operands[1]) != CONST_INT
5641        || const_ok_for_arm (INTVAL (operands[1]))
5642        || const_ok_for_arm (~INTVAL (operands[1])))"
5643   "@
5644    mov%?\\t%0, %1\\t%@ movhi
5645    mvn%?\\t%0, #%B1\\t%@ movhi
5646    str%(h%)\\t%1, %0\\t%@ movhi
5647    ldr%(h%)\\t%0, %1\\t%@ movhi"
5648   [(set_attr "type" "*,*,store1,load1")
5649    (set_attr "predicable" "yes")
5650    (set_attr "pool_range" "*,*,*,256")
5651    (set_attr "neg_pool_range" "*,*,*,244")]
5652 )
5653
5654 (define_insn "*movhi_bytes"
5655   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
5656         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
5657   "TARGET_ARM"
5658   "@
5659    mov%?\\t%0, %1\\t%@ movhi
5660    mvn%?\\t%0, #%B1\\t%@ movhi"
5661   [(set_attr "predicable" "yes")]
5662 )
5663
5664 (define_expand "thumb_movhi_clobber"
5665   [(set (match_operand:HI     0 "memory_operand"   "")
5666         (match_operand:HI     1 "register_operand" ""))
5667    (clobber (match_operand:DI 2 "register_operand" ""))]
5668   "TARGET_THUMB1"
5669   "
5670   if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
5671       && REGNO (operands[1]) <= LAST_LO_REGNUM)
5672     {
5673       emit_insn (gen_movhi (operands[0], operands[1]));
5674       DONE;
5675     }
5676   /* XXX Fixme, need to handle other cases here as well.  */
5677   gcc_unreachable ();
5678   "
5679 )
5680         
5681 ;; We use a DImode scratch because we may occasionally need an additional
5682 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
5683 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
5684 (define_expand "reload_outhi"
5685   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
5686               (match_operand:HI 1 "s_register_operand"        "r")
5687               (match_operand:DI 2 "s_register_operand"        "=&l")])]
5688   "TARGET_EITHER"
5689   "if (TARGET_ARM)
5690      arm_reload_out_hi (operands);
5691    else
5692      thumb_reload_out_hi (operands);
5693   DONE;
5694   "
5695 )
5696
5697 (define_expand "reload_inhi"
5698   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
5699               (match_operand:HI 1 "arm_reload_memory_operand" "o")
5700               (match_operand:DI 2 "s_register_operand" "=&r")])]
5701   "TARGET_EITHER"
5702   "
5703   if (TARGET_ARM)
5704     arm_reload_in_hi (operands);
5705   else
5706     thumb_reload_out_hi (operands);
5707   DONE;
5708 ")
5709
5710 (define_expand "movqi"
5711   [(set (match_operand:QI 0 "general_operand" "")
5712         (match_operand:QI 1 "general_operand" ""))]
5713   "TARGET_EITHER"
5714   "
5715   /* Everything except mem = const or mem = mem can be done easily */
5716
5717   if (can_create_pseudo_p ())
5718     {
5719       if (GET_CODE (operands[1]) == CONST_INT)
5720         {
5721           rtx reg = gen_reg_rtx (SImode);
5722
5723           /* For thumb we want an unsigned immediate, then we are more likely 
5724              to be able to use a movs insn.  */
5725           if (TARGET_THUMB)
5726             operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
5727
5728           emit_insn (gen_movsi (reg, operands[1]));
5729           operands[1] = gen_lowpart (QImode, reg);
5730         }
5731
5732       if (TARGET_THUMB)
5733         {
5734           /* ??? We shouldn't really get invalid addresses here, but this can
5735              happen if we are passed a SP (never OK for HImode/QImode) or
5736              virtual register (also rejected as illegitimate for HImode/QImode)
5737              relative address.  */
5738           /* ??? This should perhaps be fixed elsewhere, for instance, in
5739              fixup_stack_1, by checking for other kinds of invalid addresses,
5740              e.g. a bare reference to a virtual register.  This may confuse the
5741              alpha though, which must handle this case differently.  */
5742           if (GET_CODE (operands[0]) == MEM
5743               && !memory_address_p (GET_MODE (operands[0]),
5744                                      XEXP (operands[0], 0)))
5745             operands[0]
5746               = replace_equiv_address (operands[0],
5747                                        copy_to_reg (XEXP (operands[0], 0)));
5748           if (GET_CODE (operands[1]) == MEM
5749               && !memory_address_p (GET_MODE (operands[1]),
5750                                     XEXP (operands[1], 0)))
5751              operands[1]
5752                = replace_equiv_address (operands[1],
5753                                         copy_to_reg (XEXP (operands[1], 0)));
5754         }
5755
5756       if (GET_CODE (operands[1]) == MEM && optimize > 0)
5757         {
5758           rtx reg = gen_reg_rtx (SImode);
5759
5760           emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5761           operands[1] = gen_lowpart (QImode, reg);
5762         }
5763
5764       if (GET_CODE (operands[0]) == MEM)
5765         operands[1] = force_reg (QImode, operands[1]);
5766     }
5767   else if (TARGET_THUMB
5768            && GET_CODE (operands[1]) == CONST_INT
5769            && !satisfies_constraint_I (operands[1]))
5770     {
5771       /* Handle loading a large integer during reload.  */
5772
5773       /* Writing a constant to memory needs a scratch, which should
5774          be handled with SECONDARY_RELOADs.  */
5775       gcc_assert (GET_CODE (operands[0]) == REG);
5776
5777       operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5778       emit_insn (gen_movsi (operands[0], operands[1]));
5779       DONE;
5780     }
5781   "
5782 )
5783
5784
5785 (define_insn "*arm_movqi_insn"
5786   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5787         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5788   "TARGET_32BIT
5789    && (   register_operand (operands[0], QImode)
5790        || register_operand (operands[1], QImode))"
5791   "@
5792    mov%?\\t%0, %1
5793    mvn%?\\t%0, #%B1
5794    ldr%(b%)\\t%0, %1
5795    str%(b%)\\t%1, %0"
5796   [(set_attr "type" "*,*,load1,store1")
5797    (set_attr "predicable" "yes")]
5798 )
5799
5800 (define_insn "*thumb1_movqi_insn"
5801   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5802         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
5803   "TARGET_THUMB1
5804    && (   register_operand (operands[0], QImode)
5805        || register_operand (operands[1], QImode))"
5806   "@
5807    add\\t%0, %1, #0
5808    ldrb\\t%0, %1
5809    strb\\t%1, %0
5810    mov\\t%0, %1
5811    mov\\t%0, %1
5812    mov\\t%0, %1"
5813   [(set_attr "length" "2")
5814    (set_attr "type" "*,load1,store1,*,*,*")
5815    (set_attr "pool_range" "*,32,*,*,*,*")]
5816 )
5817
5818 ;; HFmode moves
5819 (define_expand "movhf"
5820   [(set (match_operand:HF 0 "general_operand" "")
5821         (match_operand:HF 1 "general_operand" ""))]
5822   "TARGET_EITHER"
5823   "
5824   if (TARGET_32BIT)
5825     {
5826       if (GET_CODE (operands[0]) == MEM)
5827         operands[1] = force_reg (HFmode, operands[1]);
5828     }
5829   else /* TARGET_THUMB1 */
5830     {
5831       if (can_create_pseudo_p ())
5832         {
5833            if (GET_CODE (operands[0]) != REG)
5834              operands[1] = force_reg (HFmode, operands[1]);
5835         }
5836     }
5837   "
5838 )
5839
5840 (define_insn "*arm32_movhf"
5841   [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
5842         (match_operand:HF 1 "general_operand"      " m,r,r,F"))]
5843   "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16)
5844    && (   s_register_operand (operands[0], HFmode)
5845        || s_register_operand (operands[1], HFmode))"
5846   "*
5847   switch (which_alternative)
5848     {
5849     case 0:     /* ARM register from memory */
5850       return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
5851     case 1:     /* memory from ARM register */
5852       return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
5853     case 2:     /* ARM register from ARM register */
5854       return \"mov%?\\t%0, %1\\t%@ __fp16\";
5855     case 3:     /* ARM register from constant */
5856       {
5857         REAL_VALUE_TYPE r;
5858         long bits;
5859         rtx ops[4];
5860
5861         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
5862         bits = real_to_target (NULL, &r, HFmode);
5863         ops[0] = operands[0];
5864         ops[1] = GEN_INT (bits);
5865         ops[2] = GEN_INT (bits & 0xff00);
5866         ops[3] = GEN_INT (bits & 0x00ff);
5867
5868         if (arm_arch_thumb2)
5869           output_asm_insn (\"movw%?\\t%0, %1\", ops);
5870         else
5871           output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
5872         return \"\";
5873        }
5874     default:
5875       gcc_unreachable ();
5876     }
5877   "
5878   [(set_attr "conds" "unconditional")
5879    (set_attr "type" "load1,store1,*,*")
5880    (set_attr "length" "4,4,4,8")
5881    (set_attr "predicable" "yes")
5882    ]
5883 )
5884
5885 (define_insn "*thumb1_movhf"
5886   [(set (match_operand:HF     0 "nonimmediate_operand" "=l,l,m,*r,*h")
5887         (match_operand:HF     1 "general_operand"      "l,mF,l,*h,*r"))]
5888   "TARGET_THUMB1
5889    && (   s_register_operand (operands[0], HFmode) 
5890        || s_register_operand (operands[1], HFmode))"
5891   "*
5892   switch (which_alternative)
5893     {
5894     case 1:
5895       {
5896         rtx addr;
5897         gcc_assert (GET_CODE(operands[1]) == MEM);
5898         addr = XEXP (operands[1], 0);
5899         if (GET_CODE (addr) == LABEL_REF
5900             || (GET_CODE (addr) == CONST
5901                 && GET_CODE (XEXP (addr, 0)) == PLUS
5902                 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF
5903                 && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT))
5904           {
5905             /* Constant pool entry.  */
5906             return \"ldr\\t%0, %1\";
5907           }
5908         return \"ldrh\\t%0, %1\";
5909       }
5910     case 2: return \"strh\\t%1, %0\";
5911     default: return \"mov\\t%0, %1\";
5912     }
5913   "
5914   [(set_attr "length" "2")
5915    (set_attr "type" "*,load1,store1,*,*")
5916    (set_attr "pool_range" "*,1020,*,*,*")]
5917 )
5918
5919 (define_expand "movsf"
5920   [(set (match_operand:SF 0 "general_operand" "")
5921         (match_operand:SF 1 "general_operand" ""))]
5922   "TARGET_EITHER"
5923   "
5924   if (TARGET_32BIT)
5925     {
5926       if (GET_CODE (operands[0]) == MEM)
5927         operands[1] = force_reg (SFmode, operands[1]);
5928     }
5929   else /* TARGET_THUMB1 */
5930     {
5931       if (can_create_pseudo_p ())
5932         {
5933            if (GET_CODE (operands[0]) != REG)
5934              operands[1] = force_reg (SFmode, operands[1]);
5935         }
5936     }
5937   "
5938 )
5939
5940 ;; Transform a floating-point move of a constant into a core register into
5941 ;; an SImode operation.
5942 (define_split
5943   [(set (match_operand:SF 0 "arm_general_register_operand" "")
5944         (match_operand:SF 1 "immediate_operand" ""))]
5945   "TARGET_EITHER
5946    && reload_completed
5947    && GET_CODE (operands[1]) == CONST_DOUBLE"
5948   [(set (match_dup 2) (match_dup 3))]
5949   "
5950   operands[2] = gen_lowpart (SImode, operands[0]);
5951   operands[3] = gen_lowpart (SImode, operands[1]);
5952   if (operands[2] == 0 || operands[3] == 0)
5953     FAIL;
5954   "
5955 )
5956
5957 (define_insn "*arm_movsf_soft_insn"
5958   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5959         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
5960   "TARGET_ARM
5961    && TARGET_SOFT_FLOAT
5962    && (GET_CODE (operands[0]) != MEM
5963        || register_operand (operands[1], SFmode))"
5964   "@
5965    mov%?\\t%0, %1
5966    ldr%?\\t%0, %1\\t%@ float
5967    str%?\\t%1, %0\\t%@ float"
5968   [(set_attr "length" "4,4,4")
5969    (set_attr "predicable" "yes")
5970    (set_attr "type" "*,load1,store1")
5971    (set_attr "pool_range" "*,4096,*")
5972    (set_attr "neg_pool_range" "*,4084,*")]
5973 )
5974
5975 ;;; ??? This should have alternatives for constants.
5976 (define_insn "*thumb1_movsf_insn"
5977   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5978         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5979   "TARGET_THUMB1
5980    && (   register_operand (operands[0], SFmode) 
5981        || register_operand (operands[1], SFmode))"
5982   "@
5983    add\\t%0, %1, #0
5984    ldmia\\t%1, {%0}
5985    stmia\\t%0, {%1}
5986    ldr\\t%0, %1
5987    str\\t%1, %0
5988    mov\\t%0, %1
5989    mov\\t%0, %1"
5990   [(set_attr "length" "2")
5991    (set_attr "type" "*,load1,store1,load1,store1,*,*")
5992    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5993 )
5994
5995 (define_expand "movdf"
5996   [(set (match_operand:DF 0 "general_operand" "")
5997         (match_operand:DF 1 "general_operand" ""))]
5998   "TARGET_EITHER"
5999   "
6000   if (TARGET_32BIT)
6001     {
6002       if (GET_CODE (operands[0]) == MEM)
6003         operands[1] = force_reg (DFmode, operands[1]);
6004     }
6005   else /* TARGET_THUMB */
6006     {
6007       if (can_create_pseudo_p ())
6008         {
6009           if (GET_CODE (operands[0]) != REG)
6010             operands[1] = force_reg (DFmode, operands[1]);
6011         }
6012     }
6013   "
6014 )
6015
6016 ;; Reloading a df mode value stored in integer regs to memory can require a
6017 ;; scratch reg.
6018 (define_expand "reload_outdf"
6019   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
6020    (match_operand:DF 1 "s_register_operand" "r")
6021    (match_operand:SI 2 "s_register_operand" "=&r")]
6022   "TARGET_32BIT"
6023   "
6024   {
6025     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
6026
6027     if (code == REG)
6028       operands[2] = XEXP (operands[0], 0);
6029     else if (code == POST_INC || code == PRE_DEC)
6030       {
6031         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6032         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6033         emit_insn (gen_movdi (operands[0], operands[1]));
6034         DONE;
6035       }
6036     else if (code == PRE_INC)
6037       {
6038         rtx reg = XEXP (XEXP (operands[0], 0), 0);
6039
6040         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6041         operands[2] = reg;
6042       }
6043     else if (code == POST_DEC)
6044       operands[2] = XEXP (XEXP (operands[0], 0), 0);
6045     else
6046       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6047                              XEXP (XEXP (operands[0], 0), 1)));
6048
6049     emit_insn (gen_rtx_SET (VOIDmode,
6050                             replace_equiv_address (operands[0], operands[2]),
6051                             operands[1]));
6052
6053     if (code == POST_DEC)
6054       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6055
6056     DONE;
6057   }"
6058 )
6059
6060 (define_insn "*movdf_soft_insn"
6061   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
6062         (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
6063   "TARGET_ARM && TARGET_SOFT_FLOAT
6064    && (   register_operand (operands[0], DFmode)
6065        || register_operand (operands[1], DFmode))"
6066   "*
6067   switch (which_alternative)
6068     {
6069     case 0:
6070     case 1:
6071     case 2:
6072       return \"#\";
6073     default:
6074       return output_move_double (operands);
6075     }
6076   "
6077   [(set_attr "length" "8,12,16,8,8")
6078    (set_attr "type" "*,*,*,load2,store2")
6079    (set_attr "pool_range" "1020")
6080    (set_attr "neg_pool_range" "1008")]
6081 )
6082
6083 ;;; ??? This should have alternatives for constants.
6084 ;;; ??? This was originally identical to the movdi_insn pattern.
6085 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
6086 ;;; thumb_reorg with a memory reference.
6087 (define_insn "*thumb_movdf_insn"
6088   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
6089         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
6090   "TARGET_THUMB1
6091    && (   register_operand (operands[0], DFmode)
6092        || register_operand (operands[1], DFmode))"
6093   "*
6094   switch (which_alternative)
6095     {
6096     default:
6097     case 0:
6098       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6099         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
6100       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
6101     case 1:
6102       return \"ldmia\\t%1, {%0, %H0}\";
6103     case 2:
6104       return \"stmia\\t%0, {%1, %H1}\";
6105     case 3:
6106       return thumb_load_double_from_address (operands);
6107     case 4:
6108       operands[2] = gen_rtx_MEM (SImode,
6109                                  plus_constant (XEXP (operands[0], 0), 4));
6110       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
6111       return \"\";
6112     case 5:
6113       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6114         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
6115       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
6116     }
6117   "
6118   [(set_attr "length" "4,2,2,6,4,4")
6119    (set_attr "type" "*,load2,store2,load2,store2,*")
6120    (set_attr "pool_range" "*,*,*,1020,*,*")]
6121 )
6122
6123 (define_expand "movxf"
6124   [(set (match_operand:XF 0 "general_operand" "")
6125         (match_operand:XF 1 "general_operand" ""))]
6126   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
6127   "
6128   if (GET_CODE (operands[0]) == MEM)
6129     operands[1] = force_reg (XFmode, operands[1]);
6130   "
6131 )
6132
6133 \f
6134
6135 ;; load- and store-multiple insns
6136 ;; The arm can load/store any set of registers, provided that they are in
6137 ;; ascending order; but that is beyond GCC so stick with what it knows.
6138
6139 (define_expand "load_multiple"
6140   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6141                           (match_operand:SI 1 "" ""))
6142                      (use (match_operand:SI 2 "" ""))])]
6143   "TARGET_32BIT"
6144 {
6145   HOST_WIDE_INT offset = 0;
6146
6147   /* Support only fixed point registers.  */
6148   if (GET_CODE (operands[2]) != CONST_INT
6149       || INTVAL (operands[2]) > 14
6150       || INTVAL (operands[2]) < 2
6151       || GET_CODE (operands[1]) != MEM
6152       || GET_CODE (operands[0]) != REG
6153       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6154       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
6155     FAIL;
6156
6157   operands[3]
6158     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
6159                              force_reg (SImode, XEXP (operands[1], 0)),
6160                              TRUE, FALSE, operands[1], &offset);
6161 })
6162
6163 ;; Load multiple with write-back
6164
6165 (define_insn "*ldmsi_postinc4"
6166   [(match_parallel 0 "load_multiple_operation"
6167     [(set (match_operand:SI 1 "s_register_operand" "=r")
6168           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6169                    (const_int 16)))
6170      (set (match_operand:SI 3 "arm_hard_register_operand" "")
6171           (mem:SI (match_dup 2)))
6172      (set (match_operand:SI 4 "arm_hard_register_operand" "")
6173           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
6174      (set (match_operand:SI 5 "arm_hard_register_operand" "")
6175           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
6176      (set (match_operand:SI 6 "arm_hard_register_operand" "")
6177           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
6178   "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
6179   "ldm%(ia%)\\t%1!, {%3, %4, %5, %6}"
6180   [(set_attr "type" "load4")
6181    (set_attr "predicable" "yes")]
6182 )
6183
6184 (define_insn "*ldmsi_postinc4_thumb1"
6185   [(match_parallel 0 "load_multiple_operation"
6186     [(set (match_operand:SI 1 "s_register_operand" "=l")
6187           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6188                    (const_int 16)))
6189      (set (match_operand:SI 3 "arm_hard_register_operand" "")
6190           (mem:SI (match_dup 2)))
6191      (set (match_operand:SI 4 "arm_hard_register_operand" "")
6192           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
6193      (set (match_operand:SI 5 "arm_hard_register_operand" "")
6194           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
6195      (set (match_operand:SI 6 "arm_hard_register_operand" "")
6196           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
6197   "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
6198   "ldmia\\t%1!, {%3, %4, %5, %6}"
6199   [(set_attr "type" "load4")]
6200 )
6201
6202 (define_insn "*ldmsi_postinc3"
6203   [(match_parallel 0 "load_multiple_operation"
6204     [(set (match_operand:SI 1 "s_register_operand" "=r")
6205           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6206                    (const_int 12)))
6207      (set (match_operand:SI 3 "arm_hard_register_operand" "")
6208           (mem:SI (match_dup 2)))
6209      (set (match_operand:SI 4 "arm_hard_register_operand" "")
6210           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
6211      (set (match_operand:SI 5 "arm_hard_register_operand" "")
6212           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
6213   "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6214   "ldm%(ia%)\\t%1!, {%3, %4, %5}"
6215   [(set_attr "type" "load3")
6216    (set_attr "predicable" "yes")]
6217 )
6218
6219 (define_insn "*ldmsi_postinc2"
6220   [(match_parallel 0 "load_multiple_operation"
6221     [(set (match_operand:SI 1 "s_register_operand" "=r")
6222           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6223                    (const_int 8)))
6224      (set (match_operand:SI 3 "arm_hard_register_operand" "")
6225           (mem:SI (match_dup 2)))
6226      (set (match_operand:SI 4 "arm_hard_register_operand" "")
6227           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
6228   "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6229   "ldm%(ia%)\\t%1!, {%3, %4}"
6230   [(set_attr "type" "load2")
6231    (set_attr "predicable" "yes")]
6232 )
6233
6234 ;; Ordinary load multiple
6235
6236 (define_insn "*ldmsi4"
6237   [(match_parallel 0 "load_multiple_operation"
6238     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
6239           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
6240      (set (match_operand:SI 3 "arm_hard_register_operand" "")
6241           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
6242      (set (match_operand:SI 4 "arm_hard_register_operand" "")
6243           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
6244      (set (match_operand:SI 5 "arm_hard_register_operand" "")
6245           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
6246   "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6247   "ldm%(ia%)\\t%1, {%2, %3, %4, %5}"
6248   [(set_attr "type" "load4")
6249    (set_attr "predicable" "yes")]
6250 )
6251
6252 (define_insn "*ldmsi3"
6253   [(match_parallel 0 "load_multiple_operation"
6254     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
6255           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
6256      (set (match_operand:SI 3 "arm_hard_register_operand" "")
6257           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
6258      (set (match_operand:SI 4 "arm_hard_register_operand" "")
6259           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
6260   "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6261   "ldm%(ia%)\\t%1, {%2, %3, %4}"
6262   [(set_attr "type" "load3")
6263    (set_attr "predicable" "yes")]
6264 )
6265
6266 (define_insn "*ldmsi2"
6267   [(match_parallel 0 "load_multiple_operation"
6268     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
6269           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
6270      (set (match_operand:SI 3 "arm_hard_register_operand" "")
6271           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
6272   "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
6273   "ldm%(ia%)\\t%1, {%2, %3}"
6274   [(set_attr "type" "load2")
6275    (set_attr "predicable" "yes")]
6276 )
6277
6278 (define_expand "store_multiple"
6279   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6280                           (match_operand:SI 1 "" ""))
6281                      (use (match_operand:SI 2 "" ""))])]
6282   "TARGET_32BIT"
6283 {
6284   HOST_WIDE_INT offset = 0;
6285
6286   /* Support only fixed point registers.  */
6287   if (GET_CODE (operands[2]) != CONST_INT
6288       || INTVAL (operands[2]) > 14
6289       || INTVAL (operands[2]) < 2
6290       || GET_CODE (operands[1]) != REG
6291       || GET_CODE (operands[0]) != MEM
6292       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6293       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
6294     FAIL;
6295
6296   operands[3]
6297     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
6298                               force_reg (SImode, XEXP (operands[0], 0)),
6299                               TRUE, FALSE, operands[0], &offset);
6300 })
6301
6302 ;; Store multiple with write-back
6303
6304 (define_insn "*stmsi_postinc4"
6305   [(match_parallel 0 "store_multiple_operation"
6306     [(set (match_operand:SI 1 "s_register_operand" "=r")
6307           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6308                    (const_int 16)))
6309      (set (mem:SI (match_dup 2))
6310           (match_operand:SI 3 "arm_hard_register_operand" ""))
6311      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6312           (match_operand:SI 4 "arm_hard_register_operand" ""))
6313      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6314           (match_operand:SI 5 "arm_hard_register_operand" ""))
6315      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
6316           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
6317   "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
6318   "stm%(ia%)\\t%1!, {%3, %4, %5, %6}"
6319   [(set_attr "predicable" "yes")
6320    (set_attr "type" "store4")]
6321 )
6322
6323 (define_insn "*stmsi_postinc4_thumb1"
6324   [(match_parallel 0 "store_multiple_operation"
6325     [(set (match_operand:SI 1 "s_register_operand" "=l")
6326           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6327                    (const_int 16)))
6328      (set (mem:SI (match_dup 2))
6329           (match_operand:SI 3 "arm_hard_register_operand" ""))
6330      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6331           (match_operand:SI 4 "arm_hard_register_operand" ""))
6332      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6333           (match_operand:SI 5 "arm_hard_register_operand" ""))
6334      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
6335           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
6336   "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
6337   "stmia\\t%1!, {%3, %4, %5, %6}"
6338   [(set_attr "type" "store4")]
6339 )
6340
6341 (define_insn "*stmsi_postinc3"
6342   [(match_parallel 0 "store_multiple_operation"
6343     [(set (match_operand:SI 1 "s_register_operand" "=r")
6344           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6345                    (const_int 12)))
6346      (set (mem:SI (match_dup 2))
6347           (match_operand:SI 3 "arm_hard_register_operand" ""))
6348      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6349           (match_operand:SI 4 "arm_hard_register_operand" ""))
6350      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6351           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
6352   "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6353   "stm%(ia%)\\t%1!, {%3, %4, %5}"
6354   [(set_attr "predicable" "yes")
6355    (set_attr "type" "store3")]
6356 )
6357
6358 (define_insn "*stmsi_postinc2"
6359   [(match_parallel 0 "store_multiple_operation"
6360     [(set (match_operand:SI 1 "s_register_operand" "=r")
6361           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6362                    (const_int 8)))
6363      (set (mem:SI (match_dup 2))
6364           (match_operand:SI 3 "arm_hard_register_operand" ""))
6365      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6366           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
6367   "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6368   "stm%(ia%)\\t%1!, {%3, %4}"
6369   [(set_attr "predicable" "yes")
6370    (set_attr "type" "store2")]
6371 )
6372
6373 ;; Ordinary store multiple
6374
6375 (define_insn "*stmsi4"
6376   [(match_parallel 0 "store_multiple_operation"
6377     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6378           (match_operand:SI 2 "arm_hard_register_operand" ""))
6379      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6380           (match_operand:SI 3 "arm_hard_register_operand" ""))
6381      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
6382           (match_operand:SI 4 "arm_hard_register_operand" ""))
6383      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
6384           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
6385   "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6386   "stm%(ia%)\\t%1, {%2, %3, %4, %5}"
6387   [(set_attr "predicable" "yes")
6388    (set_attr "type" "store4")]
6389 )
6390
6391 (define_insn "*stmsi3"
6392   [(match_parallel 0 "store_multiple_operation"
6393     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6394           (match_operand:SI 2 "arm_hard_register_operand" ""))
6395      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6396           (match_operand:SI 3 "arm_hard_register_operand" ""))
6397      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
6398           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
6399   "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6400   "stm%(ia%)\\t%1, {%2, %3, %4}"
6401   [(set_attr "predicable" "yes")
6402    (set_attr "type" "store3")]
6403 )
6404
6405 (define_insn "*stmsi2"
6406   [(match_parallel 0 "store_multiple_operation"
6407     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6408           (match_operand:SI 2 "arm_hard_register_operand" ""))
6409      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6410           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
6411   "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
6412   "stm%(ia%)\\t%1, {%2, %3}"
6413   [(set_attr "predicable" "yes")
6414    (set_attr "type" "store2")]
6415 )
6416
6417 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
6418 ;; We could let this apply for blocks of less than this, but it clobbers so
6419 ;; many registers that there is then probably a better way.
6420
6421 (define_expand "movmemqi"
6422   [(match_operand:BLK 0 "general_operand" "")
6423    (match_operand:BLK 1 "general_operand" "")
6424    (match_operand:SI 2 "const_int_operand" "")
6425    (match_operand:SI 3 "const_int_operand" "")]
6426   "TARGET_EITHER"
6427   "
6428   if (TARGET_32BIT)
6429     {
6430       if (arm_gen_movmemqi (operands))
6431         DONE;
6432       FAIL;
6433     }
6434   else /* TARGET_THUMB1 */
6435     {
6436       if (   INTVAL (operands[3]) != 4
6437           || INTVAL (operands[2]) > 48)
6438         FAIL;
6439
6440       thumb_expand_movmemqi (operands);
6441       DONE;
6442     }
6443   "
6444 )
6445
6446 ;; Thumb block-move insns
6447
6448 (define_insn "movmem12b"
6449   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6450         (mem:SI (match_operand:SI 3 "register_operand" "1")))
6451    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6452         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6453    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6454         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
6455    (set (match_operand:SI 0 "register_operand" "=l")
6456         (plus:SI (match_dup 2) (const_int 12)))
6457    (set (match_operand:SI 1 "register_operand" "=l")
6458         (plus:SI (match_dup 3) (const_int 12)))
6459    (clobber (match_scratch:SI 4 "=&l"))
6460    (clobber (match_scratch:SI 5 "=&l"))
6461    (clobber (match_scratch:SI 6 "=&l"))]
6462   "TARGET_THUMB1"
6463   "* return thumb_output_move_mem_multiple (3, operands);"
6464   [(set_attr "length" "4")
6465    ; This isn't entirely accurate...  It loads as well, but in terms of
6466    ; scheduling the following insn it is better to consider it as a store
6467    (set_attr "type" "store3")]
6468 )
6469
6470 (define_insn "movmem8b"
6471   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6472         (mem:SI (match_operand:SI 3 "register_operand" "1")))
6473    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6474         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6475    (set (match_operand:SI 0 "register_operand" "=l")
6476         (plus:SI (match_dup 2) (const_int 8)))
6477    (set (match_operand:SI 1 "register_operand" "=l")
6478         (plus:SI (match_dup 3) (const_int 8)))
6479    (clobber (match_scratch:SI 4 "=&l"))
6480    (clobber (match_scratch:SI 5 "=&l"))]
6481   "TARGET_THUMB1"
6482   "* return thumb_output_move_mem_multiple (2, operands);"
6483   [(set_attr "length" "4")
6484    ; This isn't entirely accurate...  It loads as well, but in terms of
6485    ; scheduling the following insn it is better to consider it as a store
6486    (set_attr "type" "store2")]
6487 )
6488
6489 \f
6490
6491 ;; Compare & branch insns
6492 ;; The range calculations are based as follows:
6493 ;; For forward branches, the address calculation returns the address of
6494 ;; the next instruction.  This is 2 beyond the branch instruction.
6495 ;; For backward branches, the address calculation returns the address of
6496 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
6497 ;; instruction for the shortest sequence, and 4 before the branch instruction
6498 ;; if we have to jump around an unconditional branch.
6499 ;; To the basic branch range the PC offset must be added (this is +4).
6500 ;; So for forward branches we have 
6501 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6502 ;; And for backward branches we have 
6503 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6504 ;;
6505 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6506 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
6507
6508 (define_expand "cbranchsi4"
6509   [(set (pc) (if_then_else
6510               (match_operator 0 "arm_comparison_operator"
6511                [(match_operand:SI 1 "s_register_operand" "")
6512                 (match_operand:SI 2 "nonmemory_operand" "")])
6513               (label_ref (match_operand 3 "" ""))
6514               (pc)))]
6515   "TARGET_THUMB1 || TARGET_32BIT"
6516   "
6517   if (!TARGET_THUMB1)
6518     {
6519       if (!arm_add_operand (operands[2], SImode))
6520         operands[2] = force_reg (SImode, operands[2]);
6521       emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6522                                       operands[3]));
6523       DONE;
6524     }
6525   if (thumb1_cmpneg_operand (operands[2], SImode))
6526     {
6527       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6528                                               operands[3], operands[0]));
6529       DONE;
6530     }
6531   if (!thumb1_cmp_operand (operands[2], SImode))
6532     operands[2] = force_reg (SImode, operands[2]);
6533   ")
6534
6535 ;; A pattern to recognize a special situation and optimize for it.
6536 ;; On the thumb, zero-extension from memory is preferrable to sign-extension
6537 ;; due to the available addressing modes.  Hence, convert a signed comparison
6538 ;; with zero into an unsigned comparison with 127 if possible.
6539 (define_expand "cbranchqi4"
6540   [(set (pc) (if_then_else
6541               (match_operator 0 "lt_ge_comparison_operator"
6542                [(match_operand:QI 1 "memory_operand" "")
6543                 (match_operand:QI 2 "const0_operand" "")])
6544               (label_ref (match_operand 3 "" ""))
6545               (pc)))]
6546   "TARGET_THUMB1"
6547 {
6548   rtx xops[3];
6549   xops[1] = gen_reg_rtx (SImode);
6550   emit_insn (gen_zero_extendqisi2 (xops[1], operands[1]));
6551   xops[2] = GEN_INT (127);
6552   xops[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]) == GE ? LEU : GTU,
6553                             VOIDmode, xops[1], xops[2]);
6554   xops[3] = operands[3];
6555   emit_insn (gen_cbranchsi4 (xops[0], xops[1], xops[2], xops[3]));
6556   DONE;
6557 })
6558
6559 (define_expand "cbranchsf4"
6560   [(set (pc) (if_then_else
6561               (match_operator 0 "arm_comparison_operator"
6562                [(match_operand:SF 1 "s_register_operand" "")
6563                 (match_operand:SF 2 "arm_float_compare_operand" "")])
6564               (label_ref (match_operand 3 "" ""))
6565               (pc)))]
6566   "TARGET_32BIT && TARGET_HARD_FLOAT"
6567   "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6568                                    operands[3])); DONE;"
6569 )
6570
6571 (define_expand "cbranchdf4"
6572   [(set (pc) (if_then_else
6573               (match_operator 0 "arm_comparison_operator"
6574                [(match_operand:DF 1 "s_register_operand" "")
6575                 (match_operand:DF 2 "arm_float_compare_operand" "")])
6576               (label_ref (match_operand 3 "" ""))
6577               (pc)))]
6578   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
6579   "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6580                                    operands[3])); DONE;"
6581 )
6582
6583 (define_expand "cbranchdi4"
6584   [(set (pc) (if_then_else
6585               (match_operator 0 "arm_comparison_operator"
6586                [(match_operand:DI 1 "cmpdi_operand" "")
6587                 (match_operand:DI 2 "cmpdi_operand" "")])
6588               (label_ref (match_operand 3 "" ""))
6589               (pc)))]
6590   "TARGET_32BIT"
6591   "{
6592      rtx swap = NULL_RTX;
6593      enum rtx_code code = GET_CODE (operands[0]);
6594
6595      /* We should not have two constants.  */
6596      gcc_assert (GET_MODE (operands[1]) == DImode
6597                  || GET_MODE (operands[2]) == DImode);
6598
6599     /* Flip unimplemented DImode comparisons to a form that
6600        arm_gen_compare_reg can handle.  */
6601      switch (code)
6602      {
6603      case GT:
6604        swap = gen_rtx_LT (VOIDmode, operands[2], operands[1]); break;
6605      case LE:
6606        swap = gen_rtx_GE (VOIDmode, operands[2], operands[1]); break;
6607      case GTU:
6608        swap = gen_rtx_LTU (VOIDmode, operands[2], operands[1]); break;
6609      case LEU:
6610        swap = gen_rtx_GEU (VOIDmode, operands[2], operands[1]); break;
6611      default:
6612        break;
6613      }
6614      if (swap)
6615        emit_jump_insn (gen_cbranch_cc (swap, operands[2], operands[1],
6616                                        operands[3]));
6617      else
6618        emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6619                                        operands[3]));
6620      DONE;
6621    }"
6622 )
6623
6624 (define_insn "cbranchsi4_insn"
6625   [(set (pc) (if_then_else
6626               (match_operator 0 "arm_comparison_operator"
6627                [(match_operand:SI 1 "s_register_operand" "l,*h")
6628                 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
6629               (label_ref (match_operand 3 "" ""))
6630               (pc)))]
6631   "TARGET_THUMB1"
6632   "*
6633   rtx t = prev_nonnote_insn (insn);
6634   if (t != NULL_RTX
6635       && INSN_P (t)
6636       && INSN_CODE (t) == CODE_FOR_cbranchsi4_insn)
6637     {
6638       t = XEXP (SET_SRC (PATTERN (t)), 0);
6639       if (!rtx_equal_p (XEXP (t, 0), operands[1])
6640           || !rtx_equal_p (XEXP (t, 1), operands[2]))
6641         t = NULL_RTX;
6642     }
6643   else
6644     t = NULL_RTX;
6645   if (t == NULL_RTX)
6646     output_asm_insn (\"cmp\\t%1, %2\", operands);
6647
6648   switch (get_attr_length (insn))
6649     {
6650     case 4:  return \"b%d0\\t%l3\";
6651     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6652     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6653     }
6654   "
6655   [(set (attr "far_jump")
6656         (if_then_else
6657             (eq_attr "length" "8")
6658             (const_string "yes")
6659             (const_string "no")))
6660    (set (attr "length") 
6661         (if_then_else
6662             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6663                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6664             (const_int 4)
6665             (if_then_else
6666                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6667                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6668                 (const_int 6)
6669                 (const_int 8))))]
6670 )
6671
6672 (define_insn "cbranchsi4_scratch"
6673   [(set (pc) (if_then_else
6674               (match_operator 4 "arm_comparison_operator"
6675                [(match_operand:SI 1 "s_register_operand" "l,0")
6676                 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
6677               (label_ref (match_operand 3 "" ""))
6678               (pc)))
6679    (clobber (match_scratch:SI 0 "=l,l"))]
6680   "TARGET_THUMB1"
6681   "*
6682   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
6683
6684   switch (get_attr_length (insn))
6685     {
6686     case 4:  return \"b%d4\\t%l3\";
6687     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6688     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6689     }
6690   "
6691   [(set (attr "far_jump")
6692         (if_then_else
6693             (eq_attr "length" "8")
6694             (const_string "yes")
6695             (const_string "no")))
6696    (set (attr "length") 
6697         (if_then_else
6698             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6699                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6700             (const_int 4)
6701             (if_then_else
6702                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6703                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6704                 (const_int 6)
6705                 (const_int 8))))]
6706 )
6707
6708 (define_insn "*movsi_cbranchsi4"
6709   [(set (pc)
6710         (if_then_else
6711          (match_operator 3 "arm_comparison_operator"
6712           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
6713            (const_int 0)])
6714          (label_ref (match_operand 2 "" ""))
6715          (pc)))
6716    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
6717         (match_dup 1))]
6718   "TARGET_THUMB1"
6719   "*{
6720   if (which_alternative == 0)
6721     output_asm_insn (\"cmp\t%0, #0\", operands);
6722   else if (which_alternative == 1)
6723     output_asm_insn (\"sub\t%0, %1, #0\", operands);
6724   else
6725     {
6726       output_asm_insn (\"cmp\t%1, #0\", operands);
6727       if (which_alternative == 2)
6728         output_asm_insn (\"mov\t%0, %1\", operands);
6729       else
6730         output_asm_insn (\"str\t%1, %0\", operands);
6731     }
6732   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
6733     {
6734     case 4:  return \"b%d3\\t%l2\";
6735     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6736     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
6737     }
6738   }"
6739   [(set (attr "far_jump")
6740         (if_then_else
6741             (ior (and (gt (symbol_ref ("which_alternative"))
6742                           (const_int 1))
6743                       (eq_attr "length" "8"))
6744                  (eq_attr "length" "10"))
6745             (const_string "yes")
6746             (const_string "no")))
6747    (set (attr "length")
6748      (if_then_else
6749        (le (symbol_ref ("which_alternative"))
6750                        (const_int 1))
6751        (if_then_else
6752          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6753               (le (minus (match_dup 2) (pc)) (const_int 256)))
6754          (const_int 4)
6755          (if_then_else
6756            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6757                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6758            (const_int 6)
6759            (const_int 8)))
6760        (if_then_else
6761          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
6762               (le (minus (match_dup 2) (pc)) (const_int 256)))
6763          (const_int 6)
6764          (if_then_else
6765            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
6766                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6767            (const_int 8)
6768            (const_int 10)))))]
6769 )
6770
6771 (define_peephole2
6772   [(set (match_operand:SI 0 "low_register_operand" "")
6773         (match_operand:SI 1 "low_register_operand" ""))
6774    (set (pc)
6775         (if_then_else (match_operator 2 "arm_comparison_operator"
6776                        [(match_dup 1) (const_int 0)])
6777                       (label_ref (match_operand 3 "" ""))
6778                       (pc)))]
6779   "TARGET_THUMB1"
6780   [(parallel
6781     [(set (pc)
6782         (if_then_else (match_op_dup 2 [(match_dup 1) (const_int 0)])
6783                       (label_ref (match_dup 3))
6784                       (pc)))
6785      (set (match_dup 0) (match_dup 1))])]
6786   ""
6787 )
6788
6789 ;; Sigh!  This variant shouldn't be needed, but combine often fails to
6790 ;; merge cases like this because the op1 is a hard register in
6791 ;; CLASS_LIKELY_SPILLED_P.
6792 (define_peephole2
6793   [(set (match_operand:SI 0 "low_register_operand" "")
6794         (match_operand:SI 1 "low_register_operand" ""))
6795    (set (pc)
6796         (if_then_else (match_operator 2 "arm_comparison_operator"
6797                        [(match_dup 0) (const_int 0)])
6798                       (label_ref (match_operand 3 "" ""))
6799                       (pc)))]
6800   "TARGET_THUMB1"
6801   [(parallel
6802     [(set (pc)
6803         (if_then_else (match_op_dup 2 [(match_dup 1) (const_int 0)])
6804                       (label_ref (match_dup 3))
6805                       (pc)))
6806      (set (match_dup 0) (match_dup 1))])]
6807   ""
6808 )
6809
6810 (define_insn "*negated_cbranchsi4"
6811   [(set (pc)
6812         (if_then_else
6813          (match_operator 0 "equality_operator"
6814           [(match_operand:SI 1 "s_register_operand" "l")
6815            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
6816          (label_ref (match_operand 3 "" ""))
6817          (pc)))]
6818   "TARGET_THUMB1"
6819   "*
6820   output_asm_insn (\"cmn\\t%1, %2\", operands);
6821   switch (get_attr_length (insn))
6822     {
6823     case 4:  return \"b%d0\\t%l3\";
6824     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6825     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6826     }
6827   "
6828   [(set (attr "far_jump")
6829         (if_then_else
6830             (eq_attr "length" "8")
6831             (const_string "yes")
6832             (const_string "no")))
6833    (set (attr "length") 
6834         (if_then_else
6835             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6836                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6837             (const_int 4)
6838             (if_then_else
6839                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6840                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6841                 (const_int 6)
6842                 (const_int 8))))]
6843 )
6844
6845 (define_insn "*tbit_cbranch"
6846   [(set (pc)
6847         (if_then_else
6848          (match_operator 0 "equality_operator"
6849           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6850                             (const_int 1)
6851                             (match_operand:SI 2 "const_int_operand" "i"))
6852            (const_int 0)])
6853          (label_ref (match_operand 3 "" ""))
6854          (pc)))
6855    (clobber (match_scratch:SI 4 "=l"))]
6856   "TARGET_THUMB1"
6857   "*
6858   {
6859   rtx op[3];
6860   op[0] = operands[4];
6861   op[1] = operands[1];
6862   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
6863
6864   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6865   switch (get_attr_length (insn))
6866     {
6867     case 4:  return \"b%d0\\t%l3\";
6868     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6869     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6870     }
6871   }"
6872   [(set (attr "far_jump")
6873         (if_then_else
6874             (eq_attr "length" "8")
6875             (const_string "yes")
6876             (const_string "no")))
6877    (set (attr "length") 
6878         (if_then_else
6879             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6880                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6881             (const_int 4)
6882             (if_then_else
6883                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6884                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6885                 (const_int 6)
6886                 (const_int 8))))]
6887 )
6888   
6889 (define_insn "*tlobits_cbranch"
6890   [(set (pc)
6891         (if_then_else
6892          (match_operator 0 "equality_operator"
6893           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6894                             (match_operand:SI 2 "const_int_operand" "i")
6895                             (const_int 0))
6896            (const_int 0)])
6897          (label_ref (match_operand 3 "" ""))
6898          (pc)))
6899    (clobber (match_scratch:SI 4 "=l"))]
6900   "TARGET_THUMB1"
6901   "*
6902   {
6903   rtx op[3];
6904   op[0] = operands[4];
6905   op[1] = operands[1];
6906   op[2] = GEN_INT (32 - INTVAL (operands[2]));
6907
6908   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6909   switch (get_attr_length (insn))
6910     {
6911     case 4:  return \"b%d0\\t%l3\";
6912     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6913     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6914     }
6915   }"
6916   [(set (attr "far_jump")
6917         (if_then_else
6918             (eq_attr "length" "8")
6919             (const_string "yes")
6920             (const_string "no")))
6921    (set (attr "length") 
6922         (if_then_else
6923             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6924                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6925             (const_int 4)
6926             (if_then_else
6927                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6928                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6929                 (const_int 6)
6930                 (const_int 8))))]
6931 )
6932   
6933 (define_insn "*tstsi3_cbranch"
6934   [(set (pc)
6935         (if_then_else
6936          (match_operator 3 "equality_operator"
6937           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
6938                    (match_operand:SI 1 "s_register_operand" "l"))
6939            (const_int 0)])
6940          (label_ref (match_operand 2 "" ""))
6941          (pc)))]
6942   "TARGET_THUMB1"
6943   "*
6944   {
6945   output_asm_insn (\"tst\\t%0, %1\", operands);
6946   switch (get_attr_length (insn))
6947     {
6948     case 4:  return \"b%d3\\t%l2\";
6949     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6950     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
6951     }
6952   }"
6953   [(set (attr "far_jump")
6954         (if_then_else
6955             (eq_attr "length" "8")
6956             (const_string "yes")
6957             (const_string "no")))
6958    (set (attr "length") 
6959         (if_then_else
6960             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6961                  (le (minus (match_dup 2) (pc)) (const_int 256)))
6962             (const_int 4)
6963             (if_then_else
6964                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6965                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
6966                 (const_int 6)
6967                 (const_int 8))))]
6968 )
6969   
6970 (define_insn "*andsi3_cbranch"
6971   [(set (pc)
6972         (if_then_else
6973          (match_operator 5 "equality_operator"
6974           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6975                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6976            (const_int 0)])
6977          (label_ref (match_operand 4 "" ""))
6978          (pc)))
6979    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6980         (and:SI (match_dup 2) (match_dup 3)))
6981    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6982   "TARGET_THUMB1"
6983   "*
6984   {
6985   if (which_alternative == 0)
6986     output_asm_insn (\"and\\t%0, %3\", operands);
6987   else if (which_alternative == 1)
6988     {
6989       output_asm_insn (\"and\\t%1, %3\", operands);
6990       output_asm_insn (\"mov\\t%0, %1\", operands);
6991     }
6992   else
6993     {
6994       output_asm_insn (\"and\\t%1, %3\", operands);
6995       output_asm_insn (\"str\\t%1, %0\", operands);
6996     }
6997
6998   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6999     {
7000     case 4:  return \"b%d5\\t%l4\";
7001     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7002     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7003     }
7004   }"
7005   [(set (attr "far_jump")
7006         (if_then_else
7007             (ior (and (eq (symbol_ref ("which_alternative"))
7008                           (const_int 0))
7009                       (eq_attr "length" "8"))
7010                  (eq_attr "length" "10"))
7011             (const_string "yes")
7012             (const_string "no")))
7013    (set (attr "length")
7014      (if_then_else
7015        (eq (symbol_ref ("which_alternative"))
7016                        (const_int 0))
7017        (if_then_else
7018          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7019               (le (minus (match_dup 4) (pc)) (const_int 256)))
7020          (const_int 4)
7021          (if_then_else
7022            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7023                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7024            (const_int 6)
7025            (const_int 8)))
7026        (if_then_else
7027          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7028               (le (minus (match_dup 4) (pc)) (const_int 256)))
7029          (const_int 6)
7030          (if_then_else
7031            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7032                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7033            (const_int 8)
7034            (const_int 10)))))]
7035 )
7036
7037 (define_insn "*orrsi3_cbranch_scratch"
7038   [(set (pc)
7039         (if_then_else
7040          (match_operator 4 "equality_operator"
7041           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
7042                    (match_operand:SI 2 "s_register_operand" "l"))
7043            (const_int 0)])
7044          (label_ref (match_operand 3 "" ""))
7045          (pc)))
7046    (clobber (match_scratch:SI 0 "=l"))]
7047   "TARGET_THUMB1"
7048   "*
7049   {
7050   output_asm_insn (\"orr\\t%0, %2\", operands);
7051   switch (get_attr_length (insn))
7052     {
7053     case 4:  return \"b%d4\\t%l3\";
7054     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7055     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7056     }
7057   }"
7058   [(set (attr "far_jump")
7059         (if_then_else
7060             (eq_attr "length" "8")
7061             (const_string "yes")
7062             (const_string "no")))
7063    (set (attr "length") 
7064         (if_then_else
7065             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7066                  (le (minus (match_dup 3) (pc)) (const_int 256)))
7067             (const_int 4)
7068             (if_then_else
7069                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7070                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
7071                 (const_int 6)
7072                 (const_int 8))))]
7073 )
7074   
7075 (define_insn "*orrsi3_cbranch"
7076   [(set (pc)
7077         (if_then_else
7078          (match_operator 5 "equality_operator"
7079           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
7080                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7081            (const_int 0)])
7082          (label_ref (match_operand 4 "" ""))
7083          (pc)))
7084    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
7085         (ior:SI (match_dup 2) (match_dup 3)))
7086    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
7087   "TARGET_THUMB1"
7088   "*
7089   {
7090   if (which_alternative == 0)
7091     output_asm_insn (\"orr\\t%0, %3\", operands);
7092   else if (which_alternative == 1)
7093     {
7094       output_asm_insn (\"orr\\t%1, %3\", operands);
7095       output_asm_insn (\"mov\\t%0, %1\", operands);
7096     }
7097   else
7098     {
7099       output_asm_insn (\"orr\\t%1, %3\", operands);
7100       output_asm_insn (\"str\\t%1, %0\", operands);
7101     }
7102
7103   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7104     {
7105     case 4:  return \"b%d5\\t%l4\";
7106     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7107     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7108     }
7109   }"
7110   [(set (attr "far_jump")
7111         (if_then_else
7112             (ior (and (eq (symbol_ref ("which_alternative"))
7113                           (const_int 0))
7114                       (eq_attr "length" "8"))
7115                  (eq_attr "length" "10"))
7116             (const_string "yes")
7117             (const_string "no")))
7118    (set (attr "length")
7119      (if_then_else
7120        (eq (symbol_ref ("which_alternative"))
7121                        (const_int 0))
7122        (if_then_else
7123          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7124               (le (minus (match_dup 4) (pc)) (const_int 256)))
7125          (const_int 4)
7126          (if_then_else
7127            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7128                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7129            (const_int 6)
7130            (const_int 8)))
7131        (if_then_else
7132          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7133               (le (minus (match_dup 4) (pc)) (const_int 256)))
7134          (const_int 6)
7135          (if_then_else
7136            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7137                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7138            (const_int 8)
7139            (const_int 10)))))]
7140 )
7141
7142 (define_insn "*xorsi3_cbranch_scratch"
7143   [(set (pc)
7144         (if_then_else
7145          (match_operator 4 "equality_operator"
7146           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
7147                    (match_operand:SI 2 "s_register_operand" "l"))
7148            (const_int 0)])
7149          (label_ref (match_operand 3 "" ""))
7150          (pc)))
7151    (clobber (match_scratch:SI 0 "=l"))]
7152   "TARGET_THUMB1"
7153   "*
7154   {
7155   output_asm_insn (\"eor\\t%0, %2\", operands);
7156   switch (get_attr_length (insn))
7157     {
7158     case 4:  return \"b%d4\\t%l3\";
7159     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7160     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7161     }
7162   }"
7163   [(set (attr "far_jump")
7164         (if_then_else
7165             (eq_attr "length" "8")
7166             (const_string "yes")
7167             (const_string "no")))
7168    (set (attr "length") 
7169         (if_then_else
7170             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7171                  (le (minus (match_dup 3) (pc)) (const_int 256)))
7172             (const_int 4)
7173             (if_then_else
7174                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7175                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
7176                 (const_int 6)
7177                 (const_int 8))))]
7178 )
7179   
7180 (define_insn "*xorsi3_cbranch"
7181   [(set (pc)
7182         (if_then_else
7183          (match_operator 5 "equality_operator"
7184           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
7185                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7186            (const_int 0)])
7187          (label_ref (match_operand 4 "" ""))
7188          (pc)))
7189    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
7190         (xor:SI (match_dup 2) (match_dup 3)))
7191    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
7192   "TARGET_THUMB1"
7193   "*
7194   {
7195   if (which_alternative == 0)
7196     output_asm_insn (\"eor\\t%0, %3\", operands);
7197   else if (which_alternative == 1)
7198     {
7199       output_asm_insn (\"eor\\t%1, %3\", operands);
7200       output_asm_insn (\"mov\\t%0, %1\", operands);
7201     }
7202   else
7203     {
7204       output_asm_insn (\"eor\\t%1, %3\", operands);
7205       output_asm_insn (\"str\\t%1, %0\", operands);
7206     }
7207
7208   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7209     {
7210     case 4:  return \"b%d5\\t%l4\";
7211     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7212     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7213     }
7214   }"
7215   [(set (attr "far_jump")
7216         (if_then_else
7217             (ior (and (eq (symbol_ref ("which_alternative"))
7218                           (const_int 0))
7219                       (eq_attr "length" "8"))
7220                  (eq_attr "length" "10"))
7221             (const_string "yes")
7222             (const_string "no")))
7223    (set (attr "length")
7224      (if_then_else
7225        (eq (symbol_ref ("which_alternative"))
7226                        (const_int 0))
7227        (if_then_else
7228          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7229               (le (minus (match_dup 4) (pc)) (const_int 256)))
7230          (const_int 4)
7231          (if_then_else
7232            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7233                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7234            (const_int 6)
7235            (const_int 8)))
7236        (if_then_else
7237          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7238               (le (minus (match_dup 4) (pc)) (const_int 256)))
7239          (const_int 6)
7240          (if_then_else
7241            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7242                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7243            (const_int 8)
7244            (const_int 10)))))]
7245 )
7246
7247 (define_insn "*bicsi3_cbranch_scratch"
7248   [(set (pc)
7249         (if_then_else
7250          (match_operator 4 "equality_operator"
7251           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
7252                    (match_operand:SI 1 "s_register_operand" "0"))
7253            (const_int 0)])
7254          (label_ref (match_operand 3 "" ""))
7255          (pc)))
7256    (clobber (match_scratch:SI 0 "=l"))]
7257   "TARGET_THUMB1"
7258   "*
7259   {
7260   output_asm_insn (\"bic\\t%0, %2\", operands);
7261   switch (get_attr_length (insn))
7262     {
7263     case 4:  return \"b%d4\\t%l3\";
7264     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7265     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7266     }
7267   }"
7268   [(set (attr "far_jump")
7269         (if_then_else
7270             (eq_attr "length" "8")
7271             (const_string "yes")
7272             (const_string "no")))
7273    (set (attr "length") 
7274         (if_then_else
7275             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7276                  (le (minus (match_dup 3) (pc)) (const_int 256)))
7277             (const_int 4)
7278             (if_then_else
7279                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7280                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
7281                 (const_int 6)
7282                 (const_int 8))))]
7283 )
7284   
7285 (define_insn "*bicsi3_cbranch"
7286   [(set (pc)
7287         (if_then_else
7288          (match_operator 5 "equality_operator"
7289           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
7290                    (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
7291            (const_int 0)])
7292          (label_ref (match_operand 4 "" ""))
7293          (pc)))
7294    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
7295         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
7296    (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
7297   "TARGET_THUMB1"
7298   "*
7299   {
7300   if (which_alternative == 0)
7301     output_asm_insn (\"bic\\t%0, %3\", operands);
7302   else if (which_alternative <= 2)
7303     {
7304       output_asm_insn (\"bic\\t%1, %3\", operands);
7305       /* It's ok if OP0 is a lo-reg, even though the mov will set the
7306          conditions again, since we're only testing for equality.  */
7307       output_asm_insn (\"mov\\t%0, %1\", operands);
7308     }
7309   else
7310     {
7311       output_asm_insn (\"bic\\t%1, %3\", operands);
7312       output_asm_insn (\"str\\t%1, %0\", operands);
7313     }
7314
7315   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7316     {
7317     case 4:  return \"b%d5\\t%l4\";
7318     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7319     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7320     }
7321   }"
7322   [(set (attr "far_jump")
7323         (if_then_else
7324             (ior (and (eq (symbol_ref ("which_alternative"))
7325                           (const_int 0))
7326                       (eq_attr "length" "8"))
7327                  (eq_attr "length" "10"))
7328             (const_string "yes")
7329             (const_string "no")))
7330    (set (attr "length")
7331      (if_then_else
7332        (eq (symbol_ref ("which_alternative"))
7333                        (const_int 0))
7334        (if_then_else
7335          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7336               (le (minus (match_dup 4) (pc)) (const_int 256)))
7337          (const_int 4)
7338          (if_then_else
7339            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7340                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7341            (const_int 6)
7342            (const_int 8)))
7343        (if_then_else
7344          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7345               (le (minus (match_dup 4) (pc)) (const_int 256)))
7346          (const_int 6)
7347          (if_then_else
7348            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7349                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7350            (const_int 8)
7351            (const_int 10)))))]
7352 )
7353
7354 (define_insn "*cbranchne_decr1"
7355   [(set (pc)
7356         (if_then_else (match_operator 3 "equality_operator"
7357                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
7358                         (const_int 0)])
7359                       (label_ref (match_operand 4 "" ""))
7360                       (pc)))
7361    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
7362         (plus:SI (match_dup 2) (const_int -1)))
7363    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
7364   "TARGET_THUMB1"
7365   "*
7366    {
7367      rtx cond[2];
7368      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
7369                                 ? GEU : LTU),
7370                                VOIDmode, operands[2], const1_rtx);
7371      cond[1] = operands[4];
7372
7373      if (which_alternative == 0)
7374        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
7375      else if (which_alternative == 1)
7376        {
7377          /* We must provide an alternative for a hi reg because reload 
7378             cannot handle output reloads on a jump instruction, but we
7379             can't subtract into that.  Fortunately a mov from lo to hi
7380             does not clobber the condition codes.  */
7381          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7382          output_asm_insn (\"mov\\t%0, %1\", operands);
7383        }
7384      else
7385        {
7386          /* Similarly, but the target is memory.  */
7387          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7388          output_asm_insn (\"str\\t%1, %0\", operands);
7389        }
7390
7391      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7392        {
7393          case 4:
7394            output_asm_insn (\"b%d0\\t%l1\", cond);
7395            return \"\";
7396          case 6:
7397            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
7398            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
7399          default:
7400            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
7401            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7402        }
7403    }
7404   "
7405   [(set (attr "far_jump")
7406         (if_then_else
7407             (ior (and (eq (symbol_ref ("which_alternative"))
7408                           (const_int 0))
7409                       (eq_attr "length" "8"))
7410                  (eq_attr "length" "10"))
7411             (const_string "yes")
7412             (const_string "no")))
7413    (set_attr_alternative "length"
7414       [
7415        ;; Alternative 0
7416        (if_then_else
7417          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7418               (le (minus (match_dup 4) (pc)) (const_int 256)))
7419          (const_int 4)
7420          (if_then_else
7421            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7422                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7423            (const_int 6)
7424            (const_int 8)))
7425        ;; Alternative 1
7426        (if_then_else
7427          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7428               (le (minus (match_dup 4) (pc)) (const_int 256)))
7429          (const_int 6)
7430          (if_then_else
7431            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7432                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7433            (const_int 8)
7434            (const_int 10)))
7435        ;; Alternative 2
7436        (if_then_else
7437          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7438               (le (minus (match_dup 4) (pc)) (const_int 256)))
7439          (const_int 6)
7440          (if_then_else
7441            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7442                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7443            (const_int 8)
7444            (const_int 10)))
7445        ;; Alternative 3
7446        (if_then_else
7447          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7448               (le (minus (match_dup 4) (pc)) (const_int 256)))
7449          (const_int 6)
7450          (if_then_else
7451            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7452                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7453            (const_int 8)
7454            (const_int 10)))])]
7455 )
7456
7457 (define_insn "*addsi3_cbranch"
7458   [(set (pc)
7459         (if_then_else
7460          (match_operator 4 "arm_comparison_operator"
7461           [(plus:SI
7462             (match_operand:SI 2 "s_register_operand" "%l,0,*l,1,1,1")
7463             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*l,lIJ,lIJ,lIJ"))
7464            (const_int 0)])
7465          (label_ref (match_operand 5 "" ""))
7466          (pc)))
7467    (set
7468     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
7469     (plus:SI (match_dup 2) (match_dup 3)))
7470    (clobber (match_scratch:SI 1 "=X,X,l,l,&l,&l"))]
7471   "TARGET_THUMB1
7472    && (GET_CODE (operands[4]) == EQ
7473        || GET_CODE (operands[4]) == NE
7474        || GET_CODE (operands[4]) == GE
7475        || GET_CODE (operands[4]) == LT)"
7476   "*
7477    {
7478      rtx cond[3];
7479
7480      cond[0] = (which_alternative < 2) ? operands[0] : operands[1];
7481      cond[1] = operands[2];
7482      cond[2] = operands[3];
7483
7484      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
7485        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
7486      else
7487        output_asm_insn (\"add\\t%0, %1, %2\", cond);
7488
7489      if (which_alternative >= 2
7490          && which_alternative < 4)
7491        output_asm_insn (\"mov\\t%0, %1\", operands);
7492      else if (which_alternative >= 4)
7493        output_asm_insn (\"str\\t%1, %0\", operands);
7494
7495      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
7496        {
7497          case 4:
7498            return \"b%d4\\t%l5\";
7499          case 6:
7500            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7501          default:
7502            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7503        }
7504    }
7505   "
7506   [(set (attr "far_jump")
7507         (if_then_else
7508             (ior (and (lt (symbol_ref ("which_alternative"))
7509                           (const_int 3))
7510                       (eq_attr "length" "8"))
7511                  (eq_attr "length" "10"))
7512             (const_string "yes")
7513             (const_string "no")))
7514    (set (attr "length")
7515      (if_then_else
7516        (lt (symbol_ref ("which_alternative"))
7517                        (const_int 3))
7518        (if_then_else
7519          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7520               (le (minus (match_dup 5) (pc)) (const_int 256)))
7521          (const_int 4)
7522          (if_then_else
7523            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7524                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7525            (const_int 6)
7526            (const_int 8)))
7527        (if_then_else
7528          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7529               (le (minus (match_dup 5) (pc)) (const_int 256)))
7530          (const_int 6)
7531          (if_then_else
7532            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7533                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7534            (const_int 8)
7535            (const_int 10)))))]
7536 )
7537
7538 (define_insn "*addsi3_cbranch_scratch"
7539   [(set (pc)
7540         (if_then_else
7541          (match_operator 3 "arm_comparison_operator"
7542           [(plus:SI
7543             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
7544             (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
7545            (const_int 0)])
7546          (label_ref (match_operand 4 "" ""))
7547          (pc)))
7548    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
7549   "TARGET_THUMB1
7550    && (GET_CODE (operands[3]) == EQ
7551        || GET_CODE (operands[3]) == NE
7552        || GET_CODE (operands[3]) == GE
7553        || GET_CODE (operands[3]) == LT)"
7554   "*
7555    {
7556      switch (which_alternative)
7557        {
7558        case 0:
7559          output_asm_insn (\"cmp\t%1, #%n2\", operands);
7560          break;
7561        case 1:
7562          output_asm_insn (\"cmn\t%1, %2\", operands);
7563          break;
7564        case 2:
7565          if (INTVAL (operands[2]) < 0)
7566            output_asm_insn (\"sub\t%0, %1, %2\", operands);
7567          else
7568            output_asm_insn (\"add\t%0, %1, %2\", operands);
7569          break;
7570        case 3:
7571          if (INTVAL (operands[2]) < 0)
7572            output_asm_insn (\"sub\t%0, %0, %2\", operands);
7573          else
7574            output_asm_insn (\"add\t%0, %0, %2\", operands);
7575          break;
7576        }
7577
7578      switch (get_attr_length (insn))
7579        {
7580          case 4:
7581            return \"b%d3\\t%l4\";
7582          case 6:
7583            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7584          default:
7585            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7586        }
7587    }
7588   "
7589   [(set (attr "far_jump")
7590         (if_then_else
7591             (eq_attr "length" "8")
7592             (const_string "yes")
7593             (const_string "no")))
7594    (set (attr "length")
7595        (if_then_else
7596          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7597               (le (minus (match_dup 4) (pc)) (const_int 256)))
7598          (const_int 4)
7599          (if_then_else
7600            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7601                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7602            (const_int 6)
7603            (const_int 8))))]
7604 )
7605
7606 (define_insn "*subsi3_cbranch"
7607   [(set (pc)
7608         (if_then_else
7609          (match_operator 4 "arm_comparison_operator"
7610           [(minus:SI
7611             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
7612             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7613            (const_int 0)])
7614          (label_ref (match_operand 5 "" ""))
7615          (pc)))
7616    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
7617         (minus:SI (match_dup 2) (match_dup 3)))
7618    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
7619   "TARGET_THUMB1
7620    && (GET_CODE (operands[4]) == EQ
7621        || GET_CODE (operands[4]) == NE
7622        || GET_CODE (operands[4]) == GE
7623        || GET_CODE (operands[4]) == LT)"
7624   "*
7625    {
7626      if (which_alternative == 0)
7627        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
7628      else if (which_alternative == 1)
7629        {
7630          /* We must provide an alternative for a hi reg because reload 
7631             cannot handle output reloads on a jump instruction, but we
7632             can't subtract into that.  Fortunately a mov from lo to hi
7633             does not clobber the condition codes.  */
7634          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
7635          output_asm_insn (\"mov\\t%0, %1\", operands);
7636        }
7637      else
7638        {
7639          /* Similarly, but the target is memory.  */
7640          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
7641          output_asm_insn (\"str\\t%1, %0\", operands);
7642        }
7643
7644      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
7645        {
7646          case 4:
7647            return \"b%d4\\t%l5\";
7648          case 6:
7649            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7650          default:
7651            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7652        }
7653    }
7654   "
7655   [(set (attr "far_jump")
7656         (if_then_else
7657             (ior (and (eq (symbol_ref ("which_alternative"))
7658                           (const_int 0))
7659                       (eq_attr "length" "8"))
7660                  (eq_attr "length" "10"))
7661             (const_string "yes")
7662             (const_string "no")))
7663    (set (attr "length")
7664      (if_then_else
7665        (eq (symbol_ref ("which_alternative"))
7666                        (const_int 0))
7667        (if_then_else
7668          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7669               (le (minus (match_dup 5) (pc)) (const_int 256)))
7670          (const_int 4)
7671          (if_then_else
7672            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7673                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7674            (const_int 6)
7675            (const_int 8)))
7676        (if_then_else
7677          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7678               (le (minus (match_dup 5) (pc)) (const_int 256)))
7679          (const_int 6)
7680          (if_then_else
7681            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7682                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7683            (const_int 8)
7684            (const_int 10)))))]
7685 )
7686
7687 (define_insn "*subsi3_cbranch_scratch"
7688   [(set (pc)
7689         (if_then_else
7690          (match_operator 0 "arm_comparison_operator"
7691           [(minus:SI (match_operand:SI 1 "register_operand" "l")
7692                      (match_operand:SI 2 "nonmemory_operand" "l"))
7693            (const_int 0)])
7694          (label_ref (match_operand 3 "" ""))
7695          (pc)))]
7696   "TARGET_THUMB1
7697    && (GET_CODE (operands[0]) == EQ
7698        || GET_CODE (operands[0]) == NE
7699        || GET_CODE (operands[0]) == GE
7700        || GET_CODE (operands[0]) == LT)"
7701   "*
7702   output_asm_insn (\"cmp\\t%1, %2\", operands);
7703   switch (get_attr_length (insn))
7704     {
7705     case 4:  return \"b%d0\\t%l3\";
7706     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7707     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7708     }
7709   "
7710   [(set (attr "far_jump")
7711         (if_then_else
7712             (eq_attr "length" "8")
7713             (const_string "yes")
7714             (const_string "no")))
7715    (set (attr "length") 
7716         (if_then_else
7717             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7718                  (le (minus (match_dup 3) (pc)) (const_int 256)))
7719             (const_int 4)
7720             (if_then_else
7721                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7722                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
7723                 (const_int 6)
7724                 (const_int 8))))]
7725 )
7726
7727 ;; Comparison and test insns
7728
7729 (define_insn "*arm_cmpsi_insn"
7730   [(set (reg:CC CC_REGNUM)
7731         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
7732                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
7733   "TARGET_32BIT"
7734   "@
7735    cmp%?\\t%0, %1
7736    cmn%?\\t%0, #%n1"
7737   [(set_attr "conds" "set")]
7738 )
7739
7740 (define_insn "*arm_cmpsi_shiftsi"
7741   [(set (reg:CC CC_REGNUM)
7742         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
7743                     (match_operator:SI  3 "shift_operator"
7744                      [(match_operand:SI 1 "s_register_operand" "r")
7745                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
7746   "TARGET_ARM"
7747   "cmp%?\\t%0, %1%S3"
7748   [(set_attr "conds" "set")
7749    (set_attr "shift" "1")
7750    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
7751                       (const_string "alu_shift")
7752                       (const_string "alu_shift_reg")))]
7753 )
7754
7755 (define_insn "*arm_cmpsi_shiftsi_swp"
7756   [(set (reg:CC_SWP CC_REGNUM)
7757         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
7758                          [(match_operand:SI 1 "s_register_operand" "r")
7759                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
7760                         (match_operand:SI 0 "s_register_operand" "r")))]
7761   "TARGET_ARM"
7762   "cmp%?\\t%0, %1%S3"
7763   [(set_attr "conds" "set")
7764    (set_attr "shift" "1")
7765    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
7766                       (const_string "alu_shift")
7767                       (const_string "alu_shift_reg")))]
7768 )
7769
7770 (define_insn "*arm_cmpsi_negshiftsi_si"
7771   [(set (reg:CC_Z CC_REGNUM)
7772         (compare:CC_Z
7773          (neg:SI (match_operator:SI 1 "shift_operator"
7774                     [(match_operand:SI 2 "s_register_operand" "r")
7775                      (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7776          (match_operand:SI 0 "s_register_operand" "r")))]
7777   "TARGET_ARM"
7778   "cmn%?\\t%0, %2%S1"
7779   [(set_attr "conds" "set")
7780    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7781                                     (const_string "alu_shift")
7782                                     (const_string "alu_shift_reg")))]
7783 )
7784
7785 ;; DImode comparisons.  The generic code generates branches that
7786 ;; if-conversion can not reduce to a conditional compare, so we do
7787 ;; that directly.
7788
7789 (define_insn "*arm_cmpdi_insn"
7790   [(set (reg:CC_NCV CC_REGNUM)
7791         (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
7792                         (match_operand:DI 1 "arm_di_operand"       "rDi")))
7793    (clobber (match_scratch:SI 2 "=r"))]
7794   "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
7795   "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
7796   [(set_attr "conds" "set")
7797    (set_attr "length" "8")]
7798 )
7799
7800 (define_insn "*arm_cmpdi_unsigned"
7801   [(set (reg:CC_CZ CC_REGNUM)
7802         (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "r")
7803                        (match_operand:DI 1 "arm_di_operand"     "rDi")))]
7804   "TARGET_ARM"
7805   "cmp%?\\t%R0, %R1\;cmpeq\\t%Q0, %Q1"
7806   [(set_attr "conds" "set")
7807    (set_attr "length" "8")]
7808 )
7809
7810 (define_insn "*arm_cmpdi_zero"
7811   [(set (reg:CC_Z CC_REGNUM)
7812         (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
7813                       (const_int 0)))
7814    (clobber (match_scratch:SI 1 "=r"))]
7815   "TARGET_32BIT"
7816   "orr%.\\t%1, %Q0, %R0"
7817   [(set_attr "conds" "set")]
7818 )
7819
7820 (define_insn "*thumb_cmpdi_zero"
7821   [(set (reg:CC_Z CC_REGNUM)
7822         (compare:CC_Z (match_operand:DI 0 "s_register_operand" "l")
7823                       (const_int 0)))
7824    (clobber (match_scratch:SI 1 "=l"))]
7825   "TARGET_THUMB1"
7826   "orr\\t%1, %Q0, %R0"
7827   [(set_attr "conds" "set")
7828    (set_attr "length" "2")]
7829 )
7830
7831 ;; Cirrus SF compare instruction
7832 (define_insn "*cirrus_cmpsf"
7833   [(set (reg:CCFP CC_REGNUM)
7834         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
7835                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
7836   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7837   "cfcmps%?\\tr15, %V0, %V1"
7838   [(set_attr "type"   "mav_farith")
7839    (set_attr "cirrus" "compare")]
7840 )
7841
7842 ;; Cirrus DF compare instruction
7843 (define_insn "*cirrus_cmpdf"
7844   [(set (reg:CCFP CC_REGNUM)
7845         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
7846                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
7847   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7848   "cfcmpd%?\\tr15, %V0, %V1"
7849   [(set_attr "type"   "mav_farith")
7850    (set_attr "cirrus" "compare")]
7851 )
7852
7853 (define_insn "*cirrus_cmpdi"
7854   [(set (reg:CC CC_REGNUM)
7855         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
7856                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
7857   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7858   "cfcmp64%?\\tr15, %V0, %V1"
7859   [(set_attr "type"   "mav_farith")
7860    (set_attr "cirrus" "compare")]
7861 )
7862
7863 ; This insn allows redundant compares to be removed by cse, nothing should
7864 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7865 ; is deleted later on. The match_dup will match the mode here, so that
7866 ; mode changes of the condition codes aren't lost by this even though we don't
7867 ; specify what they are.
7868
7869 (define_insn "*deleted_compare"
7870   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
7871   "TARGET_32BIT"
7872   "\\t%@ deleted compare"
7873   [(set_attr "conds" "set")
7874    (set_attr "length" "0")]
7875 )
7876
7877 \f
7878 ;; Conditional branch insns
7879
7880 (define_expand "cbranch_cc"
7881   [(set (pc)
7882         (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7883                                             (match_operand 2 "" "")])
7884                       (label_ref (match_operand 3 "" ""))
7885                       (pc)))]
7886   "TARGET_32BIT"
7887   "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
7888                                       operands[1], operands[2]);
7889    operands[2] = const0_rtx;"
7890 )
7891
7892 ;;
7893 ;; Patterns to match conditional branch insns.
7894 ;;
7895
7896 (define_insn "*arm_cond_branch"
7897   [(set (pc)
7898         (if_then_else (match_operator 1 "arm_comparison_operator"
7899                        [(match_operand 2 "cc_register" "") (const_int 0)])
7900                       (label_ref (match_operand 0 "" ""))
7901                       (pc)))]
7902   "TARGET_32BIT"
7903   "*
7904   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7905     {
7906       arm_ccfsm_state += 2;
7907       return \"\";
7908     }
7909   return \"b%d1\\t%l0\";
7910   "
7911   [(set_attr "conds" "use")
7912    (set_attr "type" "branch")]
7913 )
7914
7915 (define_insn "*arm_cond_branch_reversed"
7916   [(set (pc)
7917         (if_then_else (match_operator 1 "arm_comparison_operator"
7918                        [(match_operand 2 "cc_register" "") (const_int 0)])
7919                       (pc)
7920                       (label_ref (match_operand 0 "" ""))))]
7921   "TARGET_32BIT"
7922   "*
7923   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7924     {
7925       arm_ccfsm_state += 2;
7926       return \"\";
7927     }
7928   return \"b%D1\\t%l0\";
7929   "
7930   [(set_attr "conds" "use")
7931    (set_attr "type" "branch")]
7932 )
7933
7934 \f
7935
7936 ; scc insns
7937
7938 (define_expand "cstore_cc"
7939   [(set (match_operand:SI 0 "s_register_operand" "")
7940         (match_operator:SI 1 "" [(match_operand 2 "" "")
7941                                  (match_operand 3 "" "")]))]
7942   "TARGET_32BIT"
7943   "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
7944                                       operands[2], operands[3]);
7945    operands[3] = const0_rtx;"
7946 )
7947
7948 (define_insn "*mov_scc"
7949   [(set (match_operand:SI 0 "s_register_operand" "=r")
7950         (match_operator:SI 1 "arm_comparison_operator"
7951          [(match_operand 2 "cc_register" "") (const_int 0)]))]
7952   "TARGET_ARM"
7953   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7954   [(set_attr "conds" "use")
7955    (set_attr "length" "8")]
7956 )
7957
7958 (define_insn "*mov_negscc"
7959   [(set (match_operand:SI 0 "s_register_operand" "=r")
7960         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7961                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7962   "TARGET_ARM"
7963   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7964   [(set_attr "conds" "use")
7965    (set_attr "length" "8")]
7966 )
7967
7968 (define_insn "*mov_notscc"
7969   [(set (match_operand:SI 0 "s_register_operand" "=r")
7970         (not:SI (match_operator:SI 1 "arm_comparison_operator"
7971                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7972   "TARGET_ARM"
7973   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7974   [(set_attr "conds" "use")
7975    (set_attr "length" "8")]
7976 )
7977
7978 (define_expand "cstoresi4"
7979   [(set (match_operand:SI 0 "s_register_operand" "")
7980         (match_operator:SI 1 "arm_comparison_operator"
7981          [(match_operand:SI 2 "s_register_operand" "")
7982           (match_operand:SI 3 "reg_or_int_operand" "")]))]
7983   "TARGET_32BIT || TARGET_THUMB1"
7984   "{
7985   rtx op3, scratch, scratch2;
7986
7987   if (!TARGET_THUMB1)
7988     {
7989       if (!arm_add_operand (operands[3], SImode))
7990         operands[3] = force_reg (SImode, operands[3]);
7991       emit_insn (gen_cstore_cc (operands[0], operands[1],
7992                                 operands[2], operands[3]));
7993       DONE;
7994     }
7995
7996   if (operands[3] == const0_rtx)
7997     {
7998       switch (GET_CODE (operands[1]))
7999         {
8000         case EQ:
8001           emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
8002           break;
8003
8004         case NE:
8005           emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
8006           break;
8007
8008         case LE:
8009           scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
8010                                   NULL_RTX, 0, OPTAB_WIDEN);
8011           scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
8012                                   NULL_RTX, 0, OPTAB_WIDEN);
8013           expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
8014                         operands[0], 1, OPTAB_WIDEN);
8015           break;
8016
8017         case GE:
8018           scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
8019                                  NULL_RTX, 1);
8020           expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
8021                         NULL_RTX, 1, OPTAB_WIDEN);
8022           break;
8023
8024         case GT:
8025           scratch = expand_binop (SImode, ashr_optab, operands[2],
8026                                   GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
8027           scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
8028                                   NULL_RTX, 0, OPTAB_WIDEN);
8029           expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
8030                         0, OPTAB_WIDEN);
8031           break;
8032
8033         /* LT is handled by generic code.  No need for unsigned with 0.  */
8034         default:
8035           FAIL;
8036         }
8037       DONE;
8038     }
8039
8040   switch (GET_CODE (operands[1]))
8041     {
8042     case EQ:
8043       scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
8044                               NULL_RTX, 0, OPTAB_WIDEN);
8045       emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
8046       break;
8047
8048     case NE:
8049       scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
8050                               NULL_RTX, 0, OPTAB_WIDEN);
8051       emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
8052       break;
8053
8054     case LE:
8055       op3 = force_reg (SImode, operands[3]);
8056
8057       scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
8058                               NULL_RTX, 1, OPTAB_WIDEN);
8059       scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
8060                               NULL_RTX, 0, OPTAB_WIDEN);
8061       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
8062                                           op3, operands[2]));
8063       break;
8064
8065     case GE:
8066       op3 = operands[3];
8067       if (!thumb1_cmp_operand (op3, SImode))
8068         op3 = force_reg (SImode, op3);
8069       scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
8070                               NULL_RTX, 0, OPTAB_WIDEN);
8071       scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
8072                                NULL_RTX, 1, OPTAB_WIDEN);
8073       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
8074                                           operands[2], op3));
8075       break;
8076
8077     case LEU:
8078       op3 = force_reg (SImode, operands[3]);
8079       scratch = force_reg (SImode, const0_rtx);
8080       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
8081                                           op3, operands[2]));
8082       break;
8083
8084     case GEU:
8085       op3 = operands[3];
8086       if (!thumb1_cmp_operand (op3, SImode))
8087         op3 = force_reg (SImode, op3);
8088       scratch = force_reg (SImode, const0_rtx);
8089       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
8090                                           operands[2], op3));
8091       break;
8092
8093     case LTU:
8094       op3 = operands[3];
8095       if (!thumb1_cmp_operand (op3, SImode))
8096         op3 = force_reg (SImode, op3);
8097       scratch = gen_reg_rtx (SImode);
8098       emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
8099       break;
8100
8101     case GTU:
8102       op3 = force_reg (SImode, operands[3]);
8103       scratch = gen_reg_rtx (SImode);
8104       emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
8105       break;
8106
8107     /* No good sequences for GT, LT.  */
8108     default:
8109       FAIL;
8110     }
8111   DONE;
8112 }")
8113
8114 (define_expand "cstoresf4"
8115   [(set (match_operand:SI 0 "s_register_operand" "")
8116         (match_operator:SI 1 "arm_comparison_operator"
8117          [(match_operand:SF 2 "s_register_operand" "")
8118           (match_operand:SF 3 "arm_float_compare_operand" "")]))]
8119   "TARGET_32BIT && TARGET_HARD_FLOAT"
8120   "emit_insn (gen_cstore_cc (operands[0], operands[1],
8121                              operands[2], operands[3])); DONE;"
8122 )
8123
8124 (define_expand "cstoredf4"
8125   [(set (match_operand:SI 0 "s_register_operand" "")
8126         (match_operator:SI 1 "arm_comparison_operator"
8127          [(match_operand:DF 2 "s_register_operand" "")
8128           (match_operand:DF 3 "arm_float_compare_operand" "")]))]
8129   "TARGET_32BIT && TARGET_HARD_FLOAT"
8130   "emit_insn (gen_cstore_cc (operands[0], operands[1],
8131                              operands[2], operands[3])); DONE;"
8132 )
8133
8134 (define_expand "cstoredi4"
8135   [(set (match_operand:SI 0 "s_register_operand" "")
8136         (match_operator:SI 1 "arm_comparison_operator"
8137          [(match_operand:DI 2 "cmpdi_operand" "")
8138           (match_operand:DI 3 "cmpdi_operand" "")]))]
8139   "TARGET_32BIT"
8140   "{
8141      rtx swap = NULL_RTX;
8142      enum rtx_code code = GET_CODE (operands[1]);
8143
8144      /* We should not have two constants.  */
8145      gcc_assert (GET_MODE (operands[2]) == DImode
8146                  || GET_MODE (operands[3]) == DImode);
8147
8148     /* Flip unimplemented DImode comparisons to a form that
8149        arm_gen_compare_reg can handle.  */
8150      switch (code)
8151      {
8152      case GT:
8153        swap = gen_rtx_LT (VOIDmode, operands[3], operands[2]); break;
8154      case LE:
8155        swap = gen_rtx_GE (VOIDmode, operands[3], operands[2]); break;
8156      case GTU:
8157        swap = gen_rtx_LTU (VOIDmode, operands[3], operands[2]); break;
8158      case LEU:
8159        swap = gen_rtx_GEU (VOIDmode, operands[3], operands[2]); break;
8160      default:
8161        break;
8162      }
8163      if (swap)
8164        emit_insn (gen_cstore_cc (operands[0], swap, operands[3],
8165                                  operands[2]));
8166      else
8167        emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
8168                                  operands[3]));
8169      DONE;
8170    }"
8171 )
8172
8173 (define_expand "cstoresi_eq0_thumb1"
8174   [(parallel
8175     [(set (match_operand:SI 0 "s_register_operand" "")
8176           (eq:SI (match_operand:SI 1 "s_register_operand" "")
8177                  (const_int 0)))
8178      (clobber (match_dup:SI 2))])]
8179   "TARGET_THUMB1"
8180   "operands[2] = gen_reg_rtx (SImode);"
8181 )
8182
8183 (define_expand "cstoresi_ne0_thumb1"
8184   [(parallel
8185     [(set (match_operand:SI 0 "s_register_operand" "")
8186           (ne:SI (match_operand:SI 1 "s_register_operand" "")
8187                  (const_int 0)))
8188      (clobber (match_dup:SI 2))])]
8189   "TARGET_THUMB1"
8190   "operands[2] = gen_reg_rtx (SImode);"
8191 )
8192
8193 (define_insn "*cstoresi_eq0_thumb1_insn"
8194   [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
8195         (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
8196                (const_int 0)))
8197    (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
8198   "TARGET_THUMB1"
8199   "@
8200    neg\\t%0, %1\;adc\\t%0, %0, %1
8201    neg\\t%2, %1\;adc\\t%0, %1, %2"
8202   [(set_attr "length" "4")]
8203 )
8204
8205 (define_insn "*cstoresi_ne0_thumb1_insn"
8206   [(set (match_operand:SI 0 "s_register_operand" "=l")
8207         (ne:SI (match_operand:SI 1 "s_register_operand" "0")
8208                (const_int 0)))
8209    (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
8210   "TARGET_THUMB1"
8211   "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
8212   [(set_attr "length" "4")]
8213 )
8214
8215 ;; Used as part of the expansion of thumb ltu and gtu sequences
8216 (define_insn "cstoresi_nltu_thumb1"
8217   [(set (match_operand:SI 0 "s_register_operand" "=l,l")
8218         (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
8219                         (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
8220   "TARGET_THUMB1"
8221   "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
8222   [(set_attr "length" "4")]
8223 )
8224
8225 (define_insn_and_split "cstoresi_ltu_thumb1"
8226   [(set (match_operand:SI 0 "s_register_operand" "=l,l")
8227         (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
8228                 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")))]
8229   "TARGET_THUMB1"
8230   "#"
8231   "TARGET_THUMB1"
8232   [(set (match_dup 3)
8233         (neg:SI (ltu:SI (match_dup 1) (match_dup 2))))
8234    (set (match_dup 0) (neg:SI (match_dup 3)))]
8235   "operands[3] = gen_reg_rtx (SImode);"
8236   [(set_attr "length" "4")]
8237 )
8238
8239 ;; Used as part of the expansion of thumb les sequence.
8240 (define_insn "thumb1_addsi3_addgeu"
8241   [(set (match_operand:SI 0 "s_register_operand" "=l")
8242         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8243                           (match_operand:SI 2 "s_register_operand" "l"))
8244                  (geu:SI (match_operand:SI 3 "s_register_operand" "l")
8245                          (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
8246   "TARGET_THUMB1"
8247   "cmp\\t%3, %4\;adc\\t%0, %1, %2"
8248   [(set_attr "length" "4")]
8249 )
8250
8251 \f
8252 ;; Conditional move insns
8253
8254 (define_expand "movsicc"
8255   [(set (match_operand:SI 0 "s_register_operand" "")
8256         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
8257                          (match_operand:SI 2 "arm_not_operand" "")
8258                          (match_operand:SI 3 "arm_not_operand" "")))]
8259   "TARGET_32BIT"
8260   "
8261   {
8262     enum rtx_code code = GET_CODE (operands[1]);
8263     rtx ccreg;
8264
8265     if (code == UNEQ || code == LTGT)
8266       FAIL;
8267
8268     ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8269                                  XEXP (operands[1], 1));
8270     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
8271   }"
8272 )
8273
8274 (define_expand "movsfcc"
8275   [(set (match_operand:SF 0 "s_register_operand" "")
8276         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
8277                          (match_operand:SF 2 "s_register_operand" "")
8278                          (match_operand:SF 3 "nonmemory_operand" "")))]
8279   "TARGET_32BIT && TARGET_HARD_FLOAT"
8280   "
8281   {
8282     enum rtx_code code = GET_CODE (operands[1]);
8283     rtx ccreg;
8284
8285     if (code == UNEQ || code == LTGT)
8286       FAIL;
8287
8288     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
8289        Otherwise, ensure it is a valid FP add operand */
8290     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
8291         || (!arm_float_add_operand (operands[3], SFmode)))
8292       operands[3] = force_reg (SFmode, operands[3]);
8293
8294     ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8295                                  XEXP (operands[1], 1));
8296     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
8297   }"
8298 )
8299
8300 (define_expand "movdfcc"
8301   [(set (match_operand:DF 0 "s_register_operand" "")
8302         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
8303                          (match_operand:DF 2 "s_register_operand" "")
8304                          (match_operand:DF 3 "arm_float_add_operand" "")))]
8305   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
8306   "
8307   {
8308     enum rtx_code code = GET_CODE (operands[1]);
8309     rtx ccreg;
8310
8311     if (code == UNEQ || code == LTGT)
8312       FAIL;
8313
8314     ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8315                                  XEXP (operands[1], 1));
8316     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
8317   }"
8318 )
8319
8320 (define_insn "*movsicc_insn"
8321   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8322         (if_then_else:SI
8323          (match_operator 3 "arm_comparison_operator"
8324           [(match_operand 4 "cc_register" "") (const_int 0)])
8325          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
8326          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
8327   "TARGET_ARM"
8328   "@
8329    mov%D3\\t%0, %2
8330    mvn%D3\\t%0, #%B2
8331    mov%d3\\t%0, %1
8332    mvn%d3\\t%0, #%B1
8333    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
8334    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
8335    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
8336    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
8337   [(set_attr "length" "4,4,4,4,8,8,8,8")
8338    (set_attr "conds" "use")]
8339 )
8340
8341 (define_insn "*movsfcc_soft_insn"
8342   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8343         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8344                           [(match_operand 4 "cc_register" "") (const_int 0)])
8345                          (match_operand:SF 1 "s_register_operand" "0,r")
8346                          (match_operand:SF 2 "s_register_operand" "r,0")))]
8347   "TARGET_ARM && TARGET_SOFT_FLOAT"
8348   "@
8349    mov%D3\\t%0, %2
8350    mov%d3\\t%0, %1"
8351   [(set_attr "conds" "use")]
8352 )
8353
8354 \f
8355 ;; Jump and linkage insns
8356
8357 (define_expand "jump"
8358   [(set (pc)
8359         (label_ref (match_operand 0 "" "")))]
8360   "TARGET_EITHER"
8361   ""
8362 )
8363
8364 (define_insn "*arm_jump"
8365   [(set (pc)
8366         (label_ref (match_operand 0 "" "")))]
8367   "TARGET_32BIT"
8368   "*
8369   {
8370     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
8371       {
8372         arm_ccfsm_state += 2;
8373         return \"\";
8374       }
8375     return \"b%?\\t%l0\";
8376   }
8377   "
8378   [(set_attr "predicable" "yes")]
8379 )
8380
8381 (define_insn "*thumb_jump"
8382   [(set (pc)
8383         (label_ref (match_operand 0 "" "")))]
8384   "TARGET_THUMB1"
8385   "*
8386   if (get_attr_length (insn) == 2)
8387     return \"b\\t%l0\";
8388   return \"bl\\t%l0\\t%@ far jump\";
8389   "
8390   [(set (attr "far_jump")
8391         (if_then_else
8392             (eq_attr "length" "4")
8393             (const_string "yes")
8394             (const_string "no")))
8395    (set (attr "length") 
8396         (if_then_else
8397             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8398                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
8399             (const_int 2)
8400             (const_int 4)))]
8401 )
8402
8403 (define_expand "call"
8404   [(parallel [(call (match_operand 0 "memory_operand" "")
8405                     (match_operand 1 "general_operand" ""))
8406               (use (match_operand 2 "" ""))
8407               (clobber (reg:SI LR_REGNUM))])]
8408   "TARGET_EITHER"
8409   "
8410   {
8411     rtx callee, pat;
8412     
8413     /* In an untyped call, we can get NULL for operand 2.  */
8414     if (operands[2] == NULL_RTX)
8415       operands[2] = const0_rtx;
8416       
8417     /* Decide if we should generate indirect calls by loading the
8418        32-bit address of the callee into a register before performing the
8419        branch and link.  */
8420     callee = XEXP (operands[0], 0);
8421     if (GET_CODE (callee) == SYMBOL_REF
8422         ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8423         : !REG_P (callee))
8424       XEXP (operands[0], 0) = force_reg (Pmode, callee);
8425
8426     pat = gen_call_internal (operands[0], operands[1], operands[2]);
8427     arm_emit_call_insn (pat, XEXP (operands[0], 0));
8428     DONE;
8429   }"
8430 )
8431
8432 (define_expand "call_internal"
8433   [(parallel [(call (match_operand 0 "memory_operand" "")
8434                     (match_operand 1 "general_operand" ""))
8435               (use (match_operand 2 "" ""))
8436               (clobber (reg:SI LR_REGNUM))])])
8437
8438 (define_insn "*call_reg_armv5"
8439   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8440          (match_operand 1 "" ""))
8441    (use (match_operand 2 "" ""))
8442    (clobber (reg:SI LR_REGNUM))]
8443   "TARGET_ARM && arm_arch5"
8444   "blx%?\\t%0"
8445   [(set_attr "type" "call")]
8446 )
8447
8448 (define_insn "*call_reg_arm"
8449   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8450          (match_operand 1 "" ""))
8451    (use (match_operand 2 "" ""))
8452    (clobber (reg:SI LR_REGNUM))]
8453   "TARGET_ARM && !arm_arch5"
8454   "*
8455   return output_call (operands);
8456   "
8457   ;; length is worst case, normally it is only two
8458   [(set_attr "length" "12")
8459    (set_attr "type" "call")]
8460 )
8461
8462
8463 ;; Note: not used for armv5+ because the sequence used (ldr pc, ...) is not
8464 ;; considered a function call by the branch predictor of some cores (PR40887).
8465 ;; Falls back to blx rN (*call_reg_armv5).
8466
8467 (define_insn "*call_mem"
8468   [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
8469          (match_operand 1 "" ""))
8470    (use (match_operand 2 "" ""))
8471    (clobber (reg:SI LR_REGNUM))]
8472   "TARGET_ARM && !arm_arch5"
8473   "*
8474   return output_call_mem (operands);
8475   "
8476   [(set_attr "length" "12")
8477    (set_attr "type" "call")]
8478 )
8479
8480 (define_insn "*call_reg_thumb1_v5"
8481   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8482          (match_operand 1 "" ""))
8483    (use (match_operand 2 "" ""))
8484    (clobber (reg:SI LR_REGNUM))]
8485   "TARGET_THUMB1 && arm_arch5"
8486   "blx\\t%0"
8487   [(set_attr "length" "2")
8488    (set_attr "type" "call")]
8489 )
8490
8491 (define_insn "*call_reg_thumb1"
8492   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8493          (match_operand 1 "" ""))
8494    (use (match_operand 2 "" ""))
8495    (clobber (reg:SI LR_REGNUM))]
8496   "TARGET_THUMB1 && !arm_arch5"
8497   "*
8498   {
8499     if (!TARGET_CALLER_INTERWORKING)
8500       return thumb_call_via_reg (operands[0]);
8501     else if (operands[1] == const0_rtx)
8502       return \"bl\\t%__interwork_call_via_%0\";
8503     else if (frame_pointer_needed)
8504       return \"bl\\t%__interwork_r7_call_via_%0\";
8505     else
8506       return \"bl\\t%__interwork_r11_call_via_%0\";
8507   }"
8508   [(set_attr "type" "call")]
8509 )
8510
8511 (define_expand "call_value"
8512   [(parallel [(set (match_operand       0 "" "")
8513                    (call (match_operand 1 "memory_operand" "")
8514                          (match_operand 2 "general_operand" "")))
8515               (use (match_operand 3 "" ""))
8516               (clobber (reg:SI LR_REGNUM))])]
8517   "TARGET_EITHER"
8518   "
8519   {
8520     rtx pat, callee;
8521     
8522     /* In an untyped call, we can get NULL for operand 2.  */
8523     if (operands[3] == 0)
8524       operands[3] = const0_rtx;
8525       
8526     /* Decide if we should generate indirect calls by loading the
8527        32-bit address of the callee into a register before performing the
8528        branch and link.  */
8529     callee = XEXP (operands[1], 0);
8530     if (GET_CODE (callee) == SYMBOL_REF
8531         ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8532         : !REG_P (callee))
8533       XEXP (operands[1], 0) = force_reg (Pmode, callee);
8534
8535     pat = gen_call_value_internal (operands[0], operands[1],
8536                                    operands[2], operands[3]);
8537     arm_emit_call_insn (pat, XEXP (operands[1], 0));
8538     DONE;
8539   }"
8540 )
8541
8542 (define_expand "call_value_internal"
8543   [(parallel [(set (match_operand       0 "" "")
8544                    (call (match_operand 1 "memory_operand" "")
8545                          (match_operand 2 "general_operand" "")))
8546               (use (match_operand 3 "" ""))
8547               (clobber (reg:SI LR_REGNUM))])])
8548
8549 (define_insn "*call_value_reg_armv5"
8550   [(set (match_operand 0 "" "")
8551         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8552               (match_operand 2 "" "")))
8553    (use (match_operand 3 "" ""))
8554    (clobber (reg:SI LR_REGNUM))]
8555   "TARGET_ARM && arm_arch5"
8556   "blx%?\\t%1"
8557   [(set_attr "type" "call")]
8558 )
8559
8560 (define_insn "*call_value_reg_arm"
8561   [(set (match_operand 0 "" "")
8562         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8563               (match_operand 2 "" "")))
8564    (use (match_operand 3 "" ""))
8565    (clobber (reg:SI LR_REGNUM))]
8566   "TARGET_ARM && !arm_arch5"
8567   "*
8568   return output_call (&operands[1]);
8569   "
8570   [(set_attr "length" "12")
8571    (set_attr "type" "call")]
8572 )
8573
8574 ;; Note: see *call_mem
8575
8576 (define_insn "*call_value_mem"
8577   [(set (match_operand 0 "" "")
8578         (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
8579               (match_operand 2 "" "")))
8580    (use (match_operand 3 "" ""))
8581    (clobber (reg:SI LR_REGNUM))]
8582   "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
8583   "*
8584   return output_call_mem (&operands[1]);
8585   "
8586   [(set_attr "length" "12")
8587    (set_attr "type" "call")]
8588 )
8589
8590 (define_insn "*call_value_reg_thumb1_v5"
8591   [(set (match_operand 0 "" "")
8592         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8593               (match_operand 2 "" "")))
8594    (use (match_operand 3 "" ""))
8595    (clobber (reg:SI LR_REGNUM))]
8596   "TARGET_THUMB1 && arm_arch5"
8597   "blx\\t%1"
8598   [(set_attr "length" "2")
8599    (set_attr "type" "call")]
8600 )
8601
8602 (define_insn "*call_value_reg_thumb1"
8603   [(set (match_operand 0 "" "")
8604         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8605               (match_operand 2 "" "")))
8606    (use (match_operand 3 "" ""))
8607    (clobber (reg:SI LR_REGNUM))]
8608   "TARGET_THUMB1 && !arm_arch5"
8609   "*
8610   {
8611     if (!TARGET_CALLER_INTERWORKING)
8612       return thumb_call_via_reg (operands[1]);
8613     else if (operands[2] == const0_rtx)
8614       return \"bl\\t%__interwork_call_via_%1\";
8615     else if (frame_pointer_needed)
8616       return \"bl\\t%__interwork_r7_call_via_%1\";
8617     else
8618       return \"bl\\t%__interwork_r11_call_via_%1\";
8619   }"
8620   [(set_attr "type" "call")]
8621 )
8622
8623 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8624 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8625
8626 (define_insn "*call_symbol"
8627   [(call (mem:SI (match_operand:SI 0 "" ""))
8628          (match_operand 1 "" ""))
8629    (use (match_operand 2 "" ""))
8630    (clobber (reg:SI LR_REGNUM))]
8631   "TARGET_32BIT
8632    && (GET_CODE (operands[0]) == SYMBOL_REF)
8633    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
8634   "*
8635   {
8636     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
8637   }"
8638   [(set_attr "type" "call")]
8639 )
8640
8641 (define_insn "*call_value_symbol"
8642   [(set (match_operand 0 "" "")
8643         (call (mem:SI (match_operand:SI 1 "" ""))
8644         (match_operand:SI 2 "" "")))
8645    (use (match_operand 3 "" ""))
8646    (clobber (reg:SI LR_REGNUM))]
8647   "TARGET_32BIT
8648    && (GET_CODE (operands[1]) == SYMBOL_REF)
8649    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
8650   "*
8651   {
8652     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
8653   }"
8654   [(set_attr "type" "call")]
8655 )
8656
8657 (define_insn "*call_insn"
8658   [(call (mem:SI (match_operand:SI 0 "" ""))
8659          (match_operand:SI 1 "" ""))
8660    (use (match_operand 2 "" ""))
8661    (clobber (reg:SI LR_REGNUM))]
8662   "TARGET_THUMB1
8663    && GET_CODE (operands[0]) == SYMBOL_REF
8664    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
8665   "bl\\t%a0"
8666   [(set_attr "length" "4")
8667    (set_attr "type" "call")]
8668 )
8669
8670 (define_insn "*call_value_insn"
8671   [(set (match_operand 0 "" "")
8672         (call (mem:SI (match_operand 1 "" ""))
8673               (match_operand 2 "" "")))
8674    (use (match_operand 3 "" ""))
8675    (clobber (reg:SI LR_REGNUM))]
8676   "TARGET_THUMB1
8677    && GET_CODE (operands[1]) == SYMBOL_REF
8678    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
8679   "bl\\t%a1"
8680   [(set_attr "length" "4")
8681    (set_attr "type" "call")]
8682 )
8683
8684 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
8685 (define_expand "sibcall"
8686   [(parallel [(call (match_operand 0 "memory_operand" "")
8687                     (match_operand 1 "general_operand" ""))
8688               (return)
8689               (use (match_operand 2 "" ""))])]
8690   "TARGET_32BIT"
8691   "
8692   {
8693     if (operands[2] == NULL_RTX)
8694       operands[2] = const0_rtx;
8695   }"
8696 )
8697
8698 (define_expand "sibcall_value"
8699   [(parallel [(set (match_operand 0 "" "")
8700                    (call (match_operand 1 "memory_operand" "")
8701                          (match_operand 2 "general_operand" "")))
8702               (return)
8703               (use (match_operand 3 "" ""))])]
8704   "TARGET_32BIT"
8705   "
8706   {
8707     if (operands[3] == NULL_RTX)
8708       operands[3] = const0_rtx;
8709   }"
8710 )
8711
8712 (define_insn "*sibcall_insn"
8713  [(call (mem:SI (match_operand:SI 0 "" "X"))
8714         (match_operand 1 "" ""))
8715   (return)
8716   (use (match_operand 2 "" ""))]
8717   "TARGET_32BIT && GET_CODE (operands[0]) == SYMBOL_REF"
8718   "*
8719   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8720   "
8721   [(set_attr "type" "call")]
8722 )
8723
8724 (define_insn "*sibcall_value_insn"
8725  [(set (match_operand 0 "" "")
8726        (call (mem:SI (match_operand:SI 1 "" "X"))
8727              (match_operand 2 "" "")))
8728   (return)
8729   (use (match_operand 3 "" ""))]
8730   "TARGET_32BIT && GET_CODE (operands[1]) == SYMBOL_REF"
8731   "*
8732   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8733   "
8734   [(set_attr "type" "call")]
8735 )
8736
8737 (define_expand "return"
8738   [(return)]
8739   "TARGET_32BIT && USE_RETURN_INSN (FALSE)"
8740   "")
8741
8742 ;; Often the return insn will be the same as loading from memory, so set attr
8743 (define_insn "*arm_return"
8744   [(return)]
8745   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
8746   "*
8747   {
8748     if (arm_ccfsm_state == 2)
8749       {
8750         arm_ccfsm_state += 2;
8751         return \"\";
8752       }
8753     return output_return_instruction (const_true_rtx, TRUE, FALSE);
8754   }"
8755   [(set_attr "type" "load1")
8756    (set_attr "length" "12")
8757    (set_attr "predicable" "yes")]
8758 )
8759
8760 (define_insn "*cond_return"
8761   [(set (pc)
8762         (if_then_else (match_operator 0 "arm_comparison_operator"
8763                        [(match_operand 1 "cc_register" "") (const_int 0)])
8764                       (return)
8765                       (pc)))]
8766   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
8767   "*
8768   {
8769     if (arm_ccfsm_state == 2)
8770       {
8771         arm_ccfsm_state += 2;
8772         return \"\";
8773       }
8774     return output_return_instruction (operands[0], TRUE, FALSE);
8775   }"
8776   [(set_attr "conds" "use")
8777    (set_attr "length" "12")
8778    (set_attr "type" "load1")]
8779 )
8780
8781 (define_insn "*cond_return_inverted"
8782   [(set (pc)
8783         (if_then_else (match_operator 0 "arm_comparison_operator"
8784                        [(match_operand 1 "cc_register" "") (const_int 0)])
8785                       (pc)
8786                       (return)))]
8787   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
8788   "*
8789   {
8790     if (arm_ccfsm_state == 2)
8791       {
8792         arm_ccfsm_state += 2;
8793         return \"\";
8794       }
8795     return output_return_instruction (operands[0], TRUE, TRUE);
8796   }"
8797   [(set_attr "conds" "use")
8798    (set_attr "length" "12")
8799    (set_attr "type" "load1")]
8800 )
8801
8802 ;; Generate a sequence of instructions to determine if the processor is
8803 ;; in 26-bit or 32-bit mode, and return the appropriate return address
8804 ;; mask.
8805
8806 (define_expand "return_addr_mask"
8807   [(set (match_dup 1)
8808       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8809                        (const_int 0)))
8810    (set (match_operand:SI 0 "s_register_operand" "")
8811       (if_then_else:SI (eq (match_dup 1) (const_int 0))
8812                        (const_int -1)
8813                        (const_int 67108860)))] ; 0x03fffffc
8814   "TARGET_ARM"
8815   "
8816   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
8817   ")
8818
8819 (define_insn "*check_arch2"
8820   [(set (match_operand:CC_NOOV 0 "cc_register" "")
8821       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8822                        (const_int 0)))]
8823   "TARGET_ARM"
8824   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8825   [(set_attr "length" "8")
8826    (set_attr "conds" "set")]
8827 )
8828
8829 ;; Call subroutine returning any type.
8830
8831 (define_expand "untyped_call"
8832   [(parallel [(call (match_operand 0 "" "")
8833                     (const_int 0))
8834               (match_operand 1 "" "")
8835               (match_operand 2 "" "")])]
8836   "TARGET_EITHER"
8837   "
8838   {
8839     int i;
8840     rtx par = gen_rtx_PARALLEL (VOIDmode,
8841                                 rtvec_alloc (XVECLEN (operands[2], 0)));
8842     rtx addr = gen_reg_rtx (Pmode);
8843     rtx mem;
8844     int size = 0;
8845
8846     emit_move_insn (addr, XEXP (operands[1], 0));
8847     mem = change_address (operands[1], BLKmode, addr);
8848
8849     for (i = 0; i < XVECLEN (operands[2], 0); i++)
8850       {
8851         rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
8852
8853         /* Default code only uses r0 as a return value, but we could
8854            be using anything up to 4 registers.  */
8855         if (REGNO (src) == R0_REGNUM)
8856           src = gen_rtx_REG (TImode, R0_REGNUM);
8857
8858         XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8859                                                  GEN_INT (size));
8860         size += GET_MODE_SIZE (GET_MODE (src));
8861       }
8862
8863     emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8864                                     const0_rtx));
8865
8866     size = 0;
8867
8868     for (i = 0; i < XVECLEN (par, 0); i++)
8869       {
8870         HOST_WIDE_INT offset = 0;
8871         rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8872
8873         if (size != 0)
8874           emit_move_insn (addr, plus_constant (addr, size));
8875
8876         mem = change_address (mem, GET_MODE (reg), NULL);
8877         if (REGNO (reg) == R0_REGNUM)
8878           {
8879             /* On thumb we have to use a write-back instruction.  */
8880             emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
8881                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8882             size = TARGET_ARM ? 16 : 0;
8883           }
8884         else
8885           {
8886             emit_move_insn (mem, reg);
8887             size = GET_MODE_SIZE (GET_MODE (reg));
8888           }
8889       }
8890
8891     /* The optimizer does not know that the call sets the function value
8892        registers we stored in the result block.  We avoid problems by
8893        claiming that all hard registers are used and clobbered at this
8894        point.  */
8895     emit_insn (gen_blockage ());
8896
8897     DONE;
8898   }"
8899 )
8900
8901 (define_expand "untyped_return"
8902   [(match_operand:BLK 0 "memory_operand" "")
8903    (match_operand 1 "" "")]
8904   "TARGET_EITHER"
8905   "
8906   {
8907     int i;
8908     rtx addr = gen_reg_rtx (Pmode);
8909     rtx mem;
8910     int size = 0;
8911
8912     emit_move_insn (addr, XEXP (operands[0], 0));
8913     mem = change_address (operands[0], BLKmode, addr);
8914
8915     for (i = 0; i < XVECLEN (operands[1], 0); i++)
8916       {
8917         HOST_WIDE_INT offset = 0;
8918         rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8919
8920         if (size != 0)
8921           emit_move_insn (addr, plus_constant (addr, size));
8922
8923         mem = change_address (mem, GET_MODE (reg), NULL);
8924         if (REGNO (reg) == R0_REGNUM)
8925           {
8926             /* On thumb we have to use a write-back instruction.  */
8927             emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
8928                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8929             size = TARGET_ARM ? 16 : 0;
8930           }
8931         else
8932           {
8933             emit_move_insn (reg, mem);
8934             size = GET_MODE_SIZE (GET_MODE (reg));
8935           }
8936       }
8937
8938     /* Emit USE insns before the return.  */
8939     for (i = 0; i < XVECLEN (operands[1], 0); i++)
8940       emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
8941
8942     /* Construct the return.  */
8943     expand_naked_return ();
8944
8945     DONE;
8946   }"
8947 )
8948
8949 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8950 ;; all of memory.  This blocks insns from being moved across this point.
8951
8952 (define_insn "blockage"
8953   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
8954   "TARGET_EITHER"
8955   ""
8956   [(set_attr "length" "0")
8957    (set_attr "type" "block")]
8958 )
8959
8960 (define_expand "casesi"
8961   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
8962    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
8963    (match_operand:SI 2 "const_int_operand" "")  ; total range
8964    (match_operand:SI 3 "" "")                   ; table label
8965    (match_operand:SI 4 "" "")]                  ; Out of range label
8966   "TARGET_32BIT || optimize_size || flag_pic"
8967   "
8968   {
8969     enum insn_code code;
8970     if (operands[1] != const0_rtx)
8971       {
8972         rtx reg = gen_reg_rtx (SImode);
8973
8974         emit_insn (gen_addsi3 (reg, operands[0],
8975                                GEN_INT (-INTVAL (operands[1]))));
8976         operands[0] = reg;
8977       }
8978
8979     if (TARGET_ARM)
8980       code = CODE_FOR_arm_casesi_internal;
8981     else if (TARGET_THUMB1)
8982       code = CODE_FOR_thumb1_casesi_internal_pic;
8983     else if (flag_pic)
8984       code = CODE_FOR_thumb2_casesi_internal_pic;
8985     else
8986       code = CODE_FOR_thumb2_casesi_internal;
8987
8988     if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8989       operands[2] = force_reg (SImode, operands[2]);
8990
8991     emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8992                                           operands[3], operands[4]));
8993     DONE;
8994   }"
8995 )
8996
8997 ;; The USE in this pattern is needed to tell flow analysis that this is
8998 ;; a CASESI insn.  It has no other purpose.
8999 (define_insn "arm_casesi_internal"
9000   [(parallel [(set (pc)
9001                (if_then_else
9002                 (leu (match_operand:SI 0 "s_register_operand" "r")
9003                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
9004                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
9005                                  (label_ref (match_operand 2 "" ""))))
9006                 (label_ref (match_operand 3 "" ""))))
9007               (clobber (reg:CC CC_REGNUM))
9008               (use (label_ref (match_dup 2)))])]
9009   "TARGET_ARM"
9010   "*
9011     if (flag_pic)
9012       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
9013     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
9014   "
9015   [(set_attr "conds" "clob")
9016    (set_attr "length" "12")]
9017 )
9018
9019 (define_expand "thumb1_casesi_internal_pic"
9020   [(match_operand:SI 0 "s_register_operand" "")
9021    (match_operand:SI 1 "thumb1_cmp_operand" "")
9022    (match_operand 2 "" "")
9023    (match_operand 3 "" "")]
9024   "TARGET_THUMB1"
9025   {
9026     rtx reg0;
9027     rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[1]);
9028     emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[1],
9029                                     operands[3]));
9030     reg0 = gen_rtx_REG (SImode, 0);
9031     emit_move_insn (reg0, operands[0]);
9032     emit_jump_insn (gen_thumb1_casesi_dispatch (operands[2]/*, operands[3]*/));
9033     DONE;
9034   }
9035 )
9036
9037 (define_insn "thumb1_casesi_dispatch"
9038   [(parallel [(set (pc) (unspec [(reg:SI 0)
9039                                  (label_ref (match_operand 0 "" ""))
9040 ;;                               (label_ref (match_operand 1 "" ""))
9041 ]
9042                          UNSPEC_THUMB1_CASESI))
9043               (clobber (reg:SI IP_REGNUM))
9044               (clobber (reg:SI LR_REGNUM))])]
9045   "TARGET_THUMB1"
9046   "* return thumb1_output_casesi(operands);"
9047   [(set_attr "length" "4")]
9048 )
9049
9050 (define_expand "indirect_jump"
9051   [(set (pc)
9052         (match_operand:SI 0 "s_register_operand" ""))]
9053   "TARGET_EITHER"
9054   "
9055   /* Thumb-2 doesn't have mov pc, reg.  Explicitly set the low bit of the
9056      address and use bx.  */
9057   if (TARGET_THUMB2)
9058     {
9059       rtx tmp;
9060       tmp = gen_reg_rtx (SImode);
9061       emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
9062       operands[0] = tmp;
9063     }
9064   "
9065 )
9066
9067 ;; NB Never uses BX.
9068 (define_insn "*arm_indirect_jump"
9069   [(set (pc)
9070         (match_operand:SI 0 "s_register_operand" "r"))]
9071   "TARGET_ARM"
9072   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
9073   [(set_attr "predicable" "yes")]
9074 )
9075
9076 (define_insn "*load_indirect_jump"
9077   [(set (pc)
9078         (match_operand:SI 0 "memory_operand" "m"))]
9079   "TARGET_ARM"
9080   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
9081   [(set_attr "type" "load1")
9082    (set_attr "pool_range" "4096")
9083    (set_attr "neg_pool_range" "4084")
9084    (set_attr "predicable" "yes")]
9085 )
9086
9087 ;; NB Never uses BX.
9088 (define_insn "*thumb1_indirect_jump"
9089   [(set (pc)
9090         (match_operand:SI 0 "register_operand" "l*r"))]
9091   "TARGET_THUMB1"
9092   "mov\\tpc, %0"
9093   [(set_attr "conds" "clob")
9094    (set_attr "length" "2")]
9095 )
9096
9097 \f
9098 ;; Misc insns
9099
9100 (define_insn "nop"
9101   [(const_int 0)]
9102   "TARGET_EITHER"
9103   "*
9104   if (TARGET_UNIFIED_ASM)
9105     return \"nop\";
9106   if (TARGET_ARM)
9107     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
9108   return  \"mov\\tr8, r8\";
9109   "
9110   [(set (attr "length")
9111         (if_then_else (eq_attr "is_thumb" "yes")
9112                       (const_int 2)
9113                       (const_int 4)))]
9114 )
9115
9116 \f
9117 ;; Patterns to allow combination of arithmetic, cond code and shifts
9118
9119 (define_insn "*arith_shiftsi"
9120   [(set (match_operand:SI 0 "s_register_operand" "=r")
9121         (match_operator:SI 1 "shiftable_operator"
9122           [(match_operator:SI 3 "shift_operator"
9123              [(match_operand:SI 4 "s_register_operand" "r")
9124               (match_operand:SI 5 "reg_or_int_operand" "rI")])
9125            (match_operand:SI 2 "s_register_operand" "rk")]))]
9126   "TARGET_ARM"
9127   "%i1%?\\t%0, %2, %4%S3"
9128   [(set_attr "predicable" "yes")
9129    (set_attr "shift" "4")
9130    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
9131                       (const_string "alu_shift")
9132                       (const_string "alu_shift_reg")))]
9133 )
9134
9135 (define_split
9136   [(set (match_operand:SI 0 "s_register_operand" "")
9137         (match_operator:SI 1 "shiftable_operator"
9138          [(match_operator:SI 2 "shiftable_operator"
9139            [(match_operator:SI 3 "shift_operator"
9140              [(match_operand:SI 4 "s_register_operand" "")
9141               (match_operand:SI 5 "reg_or_int_operand" "")])
9142             (match_operand:SI 6 "s_register_operand" "")])
9143           (match_operand:SI 7 "arm_rhs_operand" "")]))
9144    (clobber (match_operand:SI 8 "s_register_operand" ""))]
9145   "TARGET_ARM"
9146   [(set (match_dup 8)
9147         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9148                          (match_dup 6)]))
9149    (set (match_dup 0)
9150         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
9151   "")
9152
9153 (define_insn "*arith_shiftsi_compare0"
9154   [(set (reg:CC_NOOV CC_REGNUM)
9155         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
9156                           [(match_operator:SI 3 "shift_operator"
9157                             [(match_operand:SI 4 "s_register_operand" "r")
9158                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
9159                            (match_operand:SI 2 "s_register_operand" "r")])
9160                          (const_int 0)))
9161    (set (match_operand:SI 0 "s_register_operand" "=r")
9162         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9163                          (match_dup 2)]))]
9164   "TARGET_ARM"
9165   "%i1%.\\t%0, %2, %4%S3"
9166   [(set_attr "conds" "set")
9167    (set_attr "shift" "4")
9168    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
9169                       (const_string "alu_shift")
9170                       (const_string "alu_shift_reg")))]
9171 )
9172
9173 (define_insn "*arith_shiftsi_compare0_scratch"
9174   [(set (reg:CC_NOOV CC_REGNUM)
9175         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
9176                           [(match_operator:SI 3 "shift_operator"
9177                             [(match_operand:SI 4 "s_register_operand" "r")
9178                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
9179                            (match_operand:SI 2 "s_register_operand" "r")])
9180                          (const_int 0)))
9181    (clobber (match_scratch:SI 0 "=r"))]
9182   "TARGET_ARM"
9183   "%i1%.\\t%0, %2, %4%S3"
9184   [(set_attr "conds" "set")
9185    (set_attr "shift" "4")
9186    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
9187                       (const_string "alu_shift")
9188                       (const_string "alu_shift_reg")))]
9189 )
9190
9191 (define_insn "*sub_shiftsi"
9192   [(set (match_operand:SI 0 "s_register_operand" "=r")
9193         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
9194                   (match_operator:SI 2 "shift_operator"
9195                    [(match_operand:SI 3 "s_register_operand" "r")
9196                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
9197   "TARGET_ARM"
9198   "sub%?\\t%0, %1, %3%S2"
9199   [(set_attr "predicable" "yes")
9200    (set_attr "shift" "3")
9201    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
9202                       (const_string "alu_shift")
9203                       (const_string "alu_shift_reg")))]
9204 )
9205
9206 (define_insn "*sub_shiftsi_compare0"
9207   [(set (reg:CC_NOOV CC_REGNUM)
9208         (compare:CC_NOOV
9209          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
9210                    (match_operator:SI 2 "shift_operator"
9211                     [(match_operand:SI 3 "s_register_operand" "r")
9212                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
9213          (const_int 0)))
9214    (set (match_operand:SI 0 "s_register_operand" "=r")
9215         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9216                                                  (match_dup 4)])))]
9217   "TARGET_ARM"
9218   "sub%.\\t%0, %1, %3%S2"
9219   [(set_attr "conds" "set")
9220    (set_attr "shift" "3")
9221    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
9222                       (const_string "alu_shift")
9223                       (const_string "alu_shift_reg")))]
9224 )
9225
9226 (define_insn "*sub_shiftsi_compare0_scratch"
9227   [(set (reg:CC_NOOV CC_REGNUM)
9228         (compare:CC_NOOV
9229          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
9230                    (match_operator:SI 2 "shift_operator"
9231                     [(match_operand:SI 3 "s_register_operand" "r")
9232                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
9233          (const_int 0)))
9234    (clobber (match_scratch:SI 0 "=r"))]
9235   "TARGET_ARM"
9236   "sub%.\\t%0, %1, %3%S2"
9237   [(set_attr "conds" "set")
9238    (set_attr "shift" "3")
9239    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
9240                       (const_string "alu_shift")
9241                       (const_string "alu_shift_reg")))]
9242 )
9243
9244 \f
9245
9246 (define_insn "*and_scc"
9247   [(set (match_operand:SI 0 "s_register_operand" "=r")
9248         (and:SI (match_operator:SI 1 "arm_comparison_operator"
9249                  [(match_operand 3 "cc_register" "") (const_int 0)])
9250                 (match_operand:SI 2 "s_register_operand" "r")))]
9251   "TARGET_ARM"
9252   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
9253   [(set_attr "conds" "use")
9254    (set_attr "length" "8")]
9255 )
9256
9257 (define_insn "*ior_scc"
9258   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9259         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
9260                  [(match_operand 3 "cc_register" "") (const_int 0)])
9261                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
9262   "TARGET_ARM"
9263   "@
9264    orr%d2\\t%0, %1, #1
9265    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
9266   [(set_attr "conds" "use")
9267    (set_attr "length" "4,8")]
9268 )
9269
9270 ; A series of splitters for the compare_scc pattern below.  Note that
9271 ; order is important.
9272 (define_split
9273   [(set (match_operand:SI 0 "s_register_operand" "")
9274         (lt:SI (match_operand:SI 1 "s_register_operand" "")
9275                (const_int 0)))
9276    (clobber (reg:CC CC_REGNUM))]
9277   "TARGET_32BIT && reload_completed"
9278   [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
9279
9280 (define_split
9281   [(set (match_operand:SI 0 "s_register_operand" "")
9282         (ge:SI (match_operand:SI 1 "s_register_operand" "")
9283                (const_int 0)))
9284    (clobber (reg:CC CC_REGNUM))]
9285   "TARGET_32BIT && reload_completed"
9286   [(set (match_dup 0) (not:SI (match_dup 1)))
9287    (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
9288
9289 (define_split
9290   [(set (match_operand:SI 0 "s_register_operand" "")
9291         (eq:SI (match_operand:SI 1 "s_register_operand" "")
9292                (const_int 0)))
9293    (clobber (reg:CC CC_REGNUM))]
9294   "TARGET_32BIT && reload_completed"
9295   [(parallel
9296     [(set (reg:CC CC_REGNUM)
9297           (compare:CC (const_int 1) (match_dup 1)))
9298      (set (match_dup 0)
9299           (minus:SI (const_int 1) (match_dup 1)))])
9300    (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
9301               (set (match_dup 0) (const_int 0)))])
9302
9303 (define_split
9304   [(set (match_operand:SI 0 "s_register_operand" "")
9305         (ne:SI (match_operand:SI 1 "s_register_operand" "")
9306                (match_operand:SI 2 "const_int_operand" "")))
9307    (clobber (reg:CC CC_REGNUM))]
9308   "TARGET_32BIT && reload_completed"
9309   [(parallel
9310     [(set (reg:CC CC_REGNUM)
9311           (compare:CC (match_dup 1) (match_dup 2)))
9312      (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
9313    (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
9314               (set (match_dup 0) (const_int 1)))]
9315 {
9316   operands[3] = GEN_INT (-INTVAL (operands[2]));
9317 })
9318
9319 (define_split
9320   [(set (match_operand:SI 0 "s_register_operand" "")
9321         (ne:SI (match_operand:SI 1 "s_register_operand" "")
9322                (match_operand:SI 2 "arm_add_operand" "")))
9323    (clobber (reg:CC CC_REGNUM))]
9324   "TARGET_32BIT && reload_completed"
9325   [(parallel
9326     [(set (reg:CC_NOOV CC_REGNUM)
9327           (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
9328                            (const_int 0)))
9329      (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
9330    (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
9331               (set (match_dup 0) (const_int 1)))])
9332
9333 (define_insn_and_split "*compare_scc"
9334   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9335         (match_operator:SI 1 "arm_comparison_operator"
9336          [(match_operand:SI 2 "s_register_operand" "r,r")
9337           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
9338    (clobber (reg:CC CC_REGNUM))]
9339   "TARGET_32BIT"
9340   "#"
9341   "&& reload_completed"
9342   [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
9343    (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
9344    (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
9345 {
9346   rtx tmp1;
9347   enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9348                                            operands[2], operands[3]);
9349   enum rtx_code rc = GET_CODE (operands[1]);
9350
9351   tmp1 = gen_rtx_REG (mode, CC_REGNUM);
9352
9353   operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
9354   if (mode == CCFPmode || mode == CCFPEmode)
9355     rc = reverse_condition_maybe_unordered (rc);
9356   else
9357     rc = reverse_condition (rc);
9358   operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
9359 })
9360
9361 ;; Attempt to improve the sequence generated by the compare_scc splitters
9362 ;; not to use conditional execution.
9363 (define_peephole2
9364   [(set (reg:CC CC_REGNUM)
9365         (compare:CC (match_operand:SI 1 "register_operand" "")
9366                     (match_operand:SI 2 "arm_rhs_operand" "")))
9367    (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9368               (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9369    (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9370               (set (match_dup 0) (const_int 1)))
9371    (match_scratch:SI 3 "r")]
9372   "TARGET_32BIT"
9373   [(set (match_dup 3) (minus:SI (match_dup 1) (match_dup 2)))
9374    (parallel
9375     [(set (reg:CC CC_REGNUM)
9376           (compare:CC (const_int 0) (match_dup 3)))
9377      (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
9378    (set (match_dup 0)
9379         (plus:SI (plus:SI (match_dup 0) (match_dup 3))
9380                  (geu:SI (reg:CC CC_REGNUM) (const_int 0))))])
9381
9382 (define_insn "*cond_move"
9383   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9384         (if_then_else:SI (match_operator 3 "equality_operator"
9385                           [(match_operator 4 "arm_comparison_operator"
9386                             [(match_operand 5 "cc_register" "") (const_int 0)])
9387                            (const_int 0)])
9388                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9389                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
9390   "TARGET_ARM"
9391   "*
9392     if (GET_CODE (operands[3]) == NE)
9393       {
9394         if (which_alternative != 1)
9395           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
9396         if (which_alternative != 0)
9397           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
9398         return \"\";
9399       }
9400     if (which_alternative != 0)
9401       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9402     if (which_alternative != 1)
9403       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
9404     return \"\";
9405   "
9406   [(set_attr "conds" "use")
9407    (set_attr "length" "4,4,8")]
9408 )
9409
9410 (define_insn "*cond_arith"
9411   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9412         (match_operator:SI 5 "shiftable_operator" 
9413          [(match_operator:SI 4 "arm_comparison_operator"
9414            [(match_operand:SI 2 "s_register_operand" "r,r")
9415             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9416           (match_operand:SI 1 "s_register_operand" "0,?r")]))
9417    (clobber (reg:CC CC_REGNUM))]
9418   "TARGET_ARM"
9419   "*
9420     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
9421       return \"%i5\\t%0, %1, %2, lsr #31\";
9422
9423     output_asm_insn (\"cmp\\t%2, %3\", operands);
9424     if (GET_CODE (operands[5]) == AND)
9425       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
9426     else if (GET_CODE (operands[5]) == MINUS)
9427       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
9428     else if (which_alternative != 0)
9429       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9430     return \"%i5%d4\\t%0, %1, #1\";
9431   "
9432   [(set_attr "conds" "clob")
9433    (set_attr "length" "12")]
9434 )
9435
9436 (define_insn "*cond_sub"
9437   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9438         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
9439                   (match_operator:SI 4 "arm_comparison_operator"
9440                    [(match_operand:SI 2 "s_register_operand" "r,r")
9441                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
9442    (clobber (reg:CC CC_REGNUM))]
9443   "TARGET_ARM"
9444   "*
9445     output_asm_insn (\"cmp\\t%2, %3\", operands);
9446     if (which_alternative != 0)
9447       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9448     return \"sub%d4\\t%0, %1, #1\";
9449   "
9450   [(set_attr "conds" "clob")
9451    (set_attr "length" "8,12")]
9452 )
9453
9454 ;; ??? Is it worth using these conditional patterns in Thumb-2 mode?
9455 (define_insn "*cmp_ite0"
9456   [(set (match_operand 6 "dominant_cc_register" "")
9457         (compare
9458          (if_then_else:SI
9459           (match_operator 4 "arm_comparison_operator"
9460            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9461             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9462           (match_operator:SI 5 "arm_comparison_operator"
9463            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9464             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
9465           (const_int 0))
9466          (const_int 0)))]
9467   "TARGET_ARM"
9468   "*
9469   {
9470     static const char * const opcodes[4][2] =
9471     {
9472       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9473        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9474       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9475        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9476       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9477        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9478       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9479        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9480     };
9481     int swap =
9482       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9483
9484     return opcodes[which_alternative][swap];
9485   }"
9486   [(set_attr "conds" "set")
9487    (set_attr "length" "8")]
9488 )
9489
9490 (define_insn "*cmp_ite1"
9491   [(set (match_operand 6 "dominant_cc_register" "")
9492         (compare
9493          (if_then_else:SI
9494           (match_operator 4 "arm_comparison_operator"
9495            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9496             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9497           (match_operator:SI 5 "arm_comparison_operator"
9498            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9499             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
9500           (const_int 1))
9501          (const_int 0)))]
9502   "TARGET_ARM"
9503   "*
9504   {
9505     static const char * const opcodes[4][2] =
9506     {
9507       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
9508        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9509       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
9510        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9511       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
9512        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9513       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
9514        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9515     };
9516     int swap =
9517       comparison_dominates_p (GET_CODE (operands[5]),
9518                               reverse_condition (GET_CODE (operands[4])));
9519
9520     return opcodes[which_alternative][swap];
9521   }"
9522   [(set_attr "conds" "set")
9523    (set_attr "length" "8")]
9524 )
9525
9526 (define_insn "*cmp_and"
9527   [(set (match_operand 6 "dominant_cc_register" "")
9528         (compare
9529          (and:SI
9530           (match_operator 4 "arm_comparison_operator"
9531            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9532             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9533           (match_operator:SI 5 "arm_comparison_operator"
9534            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9535             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9536          (const_int 0)))]
9537   "TARGET_ARM"
9538   "*
9539   {
9540     static const char *const opcodes[4][2] =
9541     {
9542       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9543        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9544       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9545        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9546       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9547        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9548       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9549        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9550     };
9551     int swap =
9552       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9553
9554     return opcodes[which_alternative][swap];
9555   }"
9556   [(set_attr "conds" "set")
9557    (set_attr "predicable" "no")
9558    (set_attr "length" "8")]
9559 )
9560
9561 (define_insn "*cmp_ior"
9562   [(set (match_operand 6 "dominant_cc_register" "")
9563         (compare
9564          (ior:SI
9565           (match_operator 4 "arm_comparison_operator"
9566            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9567             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9568           (match_operator:SI 5 "arm_comparison_operator"
9569            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9570             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9571          (const_int 0)))]
9572   "TARGET_ARM"
9573   "*
9574 {
9575   static const char *const opcodes[4][2] =
9576   {
9577     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
9578      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9579     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
9580      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9581     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
9582      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9583     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
9584      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9585   };
9586   int swap =
9587     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9588
9589   return opcodes[which_alternative][swap];
9590 }
9591 "
9592   [(set_attr "conds" "set")
9593    (set_attr "length" "8")]
9594 )
9595
9596 (define_insn_and_split "*ior_scc_scc"
9597   [(set (match_operand:SI 0 "s_register_operand" "=r")
9598         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9599                  [(match_operand:SI 1 "s_register_operand" "r")
9600                   (match_operand:SI 2 "arm_add_operand" "rIL")])
9601                 (match_operator:SI 6 "arm_comparison_operator"
9602                  [(match_operand:SI 4 "s_register_operand" "r")
9603                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
9604    (clobber (reg:CC CC_REGNUM))]
9605   "TARGET_ARM
9606    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9607        != CCmode)"
9608   "#"
9609   "TARGET_ARM && reload_completed"
9610   [(set (match_dup 7)
9611         (compare
9612          (ior:SI
9613           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9614           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9615          (const_int 0)))
9616    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9617   "operands[7]
9618      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9619                                                   DOM_CC_X_OR_Y),
9620                     CC_REGNUM);"
9621   [(set_attr "conds" "clob")
9622    (set_attr "length" "16")])
9623
9624 ; If the above pattern is followed by a CMP insn, then the compare is 
9625 ; redundant, since we can rework the conditional instruction that follows.
9626 (define_insn_and_split "*ior_scc_scc_cmp"
9627   [(set (match_operand 0 "dominant_cc_register" "")
9628         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9629                           [(match_operand:SI 1 "s_register_operand" "r")
9630                            (match_operand:SI 2 "arm_add_operand" "rIL")])
9631                          (match_operator:SI 6 "arm_comparison_operator"
9632                           [(match_operand:SI 4 "s_register_operand" "r")
9633                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
9634                  (const_int 0)))
9635    (set (match_operand:SI 7 "s_register_operand" "=r")
9636         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9637                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9638   "TARGET_ARM"
9639   "#"
9640   "TARGET_ARM && reload_completed"
9641   [(set (match_dup 0)
9642         (compare
9643          (ior:SI
9644           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9645           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9646          (const_int 0)))
9647    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9648   ""
9649   [(set_attr "conds" "set")
9650    (set_attr "length" "16")])
9651
9652 (define_insn_and_split "*and_scc_scc"
9653   [(set (match_operand:SI 0 "s_register_operand" "=r")
9654         (and:SI (match_operator:SI 3 "arm_comparison_operator"
9655                  [(match_operand:SI 1 "s_register_operand" "r")
9656                   (match_operand:SI 2 "arm_add_operand" "rIL")])
9657                 (match_operator:SI 6 "arm_comparison_operator"
9658                  [(match_operand:SI 4 "s_register_operand" "r")
9659                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
9660    (clobber (reg:CC CC_REGNUM))]
9661   "TARGET_ARM
9662    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9663        != CCmode)"
9664   "#"
9665   "TARGET_ARM && reload_completed
9666    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9667        != CCmode)"
9668   [(set (match_dup 7)
9669         (compare
9670          (and:SI
9671           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9672           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9673          (const_int 0)))
9674    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9675   "operands[7]
9676      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9677                                                   DOM_CC_X_AND_Y),
9678                     CC_REGNUM);"
9679   [(set_attr "conds" "clob")
9680    (set_attr "length" "16")])
9681
9682 ; If the above pattern is followed by a CMP insn, then the compare is 
9683 ; redundant, since we can rework the conditional instruction that follows.
9684 (define_insn_and_split "*and_scc_scc_cmp"
9685   [(set (match_operand 0 "dominant_cc_register" "")
9686         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9687                           [(match_operand:SI 1 "s_register_operand" "r")
9688                            (match_operand:SI 2 "arm_add_operand" "rIL")])
9689                          (match_operator:SI 6 "arm_comparison_operator"
9690                           [(match_operand:SI 4 "s_register_operand" "r")
9691                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
9692                  (const_int 0)))
9693    (set (match_operand:SI 7 "s_register_operand" "=r")
9694         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9695                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9696   "TARGET_ARM"
9697   "#"
9698   "TARGET_ARM && reload_completed"
9699   [(set (match_dup 0)
9700         (compare
9701          (and:SI
9702           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9703           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9704          (const_int 0)))
9705    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9706   ""
9707   [(set_attr "conds" "set")
9708    (set_attr "length" "16")])
9709
9710 ;; If there is no dominance in the comparison, then we can still save an
9711 ;; instruction in the AND case, since we can know that the second compare
9712 ;; need only zero the value if false (if true, then the value is already
9713 ;; correct).
9714 (define_insn_and_split "*and_scc_scc_nodom"
9715   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
9716         (and:SI (match_operator:SI 3 "arm_comparison_operator"
9717                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
9718                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9719                 (match_operator:SI 6 "arm_comparison_operator"
9720                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
9721                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9722    (clobber (reg:CC CC_REGNUM))]
9723   "TARGET_ARM
9724    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9725        == CCmode)"
9726   "#"
9727   "TARGET_ARM && reload_completed"
9728   [(parallel [(set (match_dup 0)
9729                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9730               (clobber (reg:CC CC_REGNUM))])
9731    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9732    (set (match_dup 0)
9733         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9734                          (match_dup 0)
9735                          (const_int 0)))]
9736   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9737                                               operands[4], operands[5]),
9738                               CC_REGNUM);
9739    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9740                                   operands[5]);"
9741   [(set_attr "conds" "clob")
9742    (set_attr "length" "20")])
9743
9744 (define_split
9745   [(set (reg:CC_NOOV CC_REGNUM)
9746         (compare:CC_NOOV (ior:SI
9747                           (and:SI (match_operand:SI 0 "s_register_operand" "")
9748                                   (const_int 1))
9749                           (match_operator:SI 1 "arm_comparison_operator"
9750                            [(match_operand:SI 2 "s_register_operand" "")
9751                             (match_operand:SI 3 "arm_add_operand" "")]))
9752                          (const_int 0)))
9753    (clobber (match_operand:SI 4 "s_register_operand" ""))]
9754   "TARGET_ARM"
9755   [(set (match_dup 4)
9756         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9757                 (match_dup 0)))
9758    (set (reg:CC_NOOV CC_REGNUM)
9759         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9760                          (const_int 0)))]
9761   "")
9762
9763 (define_split
9764   [(set (reg:CC_NOOV CC_REGNUM)
9765         (compare:CC_NOOV (ior:SI
9766                           (match_operator:SI 1 "arm_comparison_operator"
9767                            [(match_operand:SI 2 "s_register_operand" "")
9768                             (match_operand:SI 3 "arm_add_operand" "")])
9769                           (and:SI (match_operand:SI 0 "s_register_operand" "")
9770                                   (const_int 1)))
9771                          (const_int 0)))
9772    (clobber (match_operand:SI 4 "s_register_operand" ""))]
9773   "TARGET_ARM"
9774   [(set (match_dup 4)
9775         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9776                 (match_dup 0)))
9777    (set (reg:CC_NOOV CC_REGNUM)
9778         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9779                          (const_int 0)))]
9780   "")
9781 ;; ??? The conditional patterns above need checking for Thumb-2 usefulness
9782
9783 (define_insn "*negscc"
9784   [(set (match_operand:SI 0 "s_register_operand" "=r")
9785         (neg:SI (match_operator 3 "arm_comparison_operator"
9786                  [(match_operand:SI 1 "s_register_operand" "r")
9787                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
9788    (clobber (reg:CC CC_REGNUM))]
9789   "TARGET_ARM"
9790   "*
9791   if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
9792     return \"mov\\t%0, %1, asr #31\";
9793
9794   if (GET_CODE (operands[3]) == NE)
9795     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9796
9797   output_asm_insn (\"cmp\\t%1, %2\", operands);
9798   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9799   return \"mvn%d3\\t%0, #0\";
9800   "
9801   [(set_attr "conds" "clob")
9802    (set_attr "length" "12")]
9803 )
9804
9805 (define_insn "movcond"
9806   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9807         (if_then_else:SI
9808          (match_operator 5 "arm_comparison_operator"
9809           [(match_operand:SI 3 "s_register_operand" "r,r,r")
9810            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9811          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9812          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
9813    (clobber (reg:CC CC_REGNUM))]
9814   "TARGET_ARM"
9815   "*
9816   if (GET_CODE (operands[5]) == LT
9817       && (operands[4] == const0_rtx))
9818     {
9819       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9820         {
9821           if (operands[2] == const0_rtx)
9822             return \"and\\t%0, %1, %3, asr #31\";
9823           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9824         }
9825       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9826         {
9827           if (operands[1] == const0_rtx)
9828             return \"bic\\t%0, %2, %3, asr #31\";
9829           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9830         }
9831       /* The only case that falls through to here is when both ops 1 & 2
9832          are constants.  */
9833     }
9834
9835   if (GET_CODE (operands[5]) == GE
9836       && (operands[4] == const0_rtx))
9837     {
9838       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9839         {
9840           if (operands[2] == const0_rtx)
9841             return \"bic\\t%0, %1, %3, asr #31\";
9842           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9843         }
9844       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9845         {
9846           if (operands[1] == const0_rtx)
9847             return \"and\\t%0, %2, %3, asr #31\";
9848           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9849         }
9850       /* The only case that falls through to here is when both ops 1 & 2
9851          are constants.  */
9852     }
9853   if (GET_CODE (operands[4]) == CONST_INT
9854       && !const_ok_for_arm (INTVAL (operands[4])))
9855     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9856   else
9857     output_asm_insn (\"cmp\\t%3, %4\", operands);
9858   if (which_alternative != 0)
9859     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9860   if (which_alternative != 1)
9861     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9862   return \"\";
9863   "
9864   [(set_attr "conds" "clob")
9865    (set_attr "length" "8,8,12")]
9866 )
9867
9868 ;; ??? The patterns below need checking for Thumb-2 usefulness.
9869
9870 (define_insn "*ifcompare_plus_move"
9871   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9872         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9873                           [(match_operand:SI 4 "s_register_operand" "r,r")
9874                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9875                          (plus:SI
9876                           (match_operand:SI 2 "s_register_operand" "r,r")
9877                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
9878                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9879    (clobber (reg:CC CC_REGNUM))]
9880   "TARGET_ARM"
9881   "#"
9882   [(set_attr "conds" "clob")
9883    (set_attr "length" "8,12")]
9884 )
9885
9886 (define_insn "*if_plus_move"
9887   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9888         (if_then_else:SI
9889          (match_operator 4 "arm_comparison_operator"
9890           [(match_operand 5 "cc_register" "") (const_int 0)])
9891          (plus:SI
9892           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9893           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9894          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
9895   "TARGET_ARM"
9896   "@
9897    add%d4\\t%0, %2, %3
9898    sub%d4\\t%0, %2, #%n3
9899    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
9900    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
9901   [(set_attr "conds" "use")
9902    (set_attr "length" "4,4,8,8")
9903    (set_attr "type" "*,*,*,*")]
9904 )
9905
9906 (define_insn "*ifcompare_move_plus"
9907   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9908         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9909                           [(match_operand:SI 4 "s_register_operand" "r,r")
9910                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9911                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9912                          (plus:SI
9913                           (match_operand:SI 2 "s_register_operand" "r,r")
9914                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
9915    (clobber (reg:CC CC_REGNUM))]
9916   "TARGET_ARM"
9917   "#"
9918   [(set_attr "conds" "clob")
9919    (set_attr "length" "8,12")]
9920 )
9921
9922 (define_insn "*if_move_plus"
9923   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9924         (if_then_else:SI
9925          (match_operator 4 "arm_comparison_operator"
9926           [(match_operand 5 "cc_register" "") (const_int 0)])
9927          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
9928          (plus:SI
9929           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9930           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
9931   "TARGET_ARM"
9932   "@
9933    add%D4\\t%0, %2, %3
9934    sub%D4\\t%0, %2, #%n3
9935    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
9936    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
9937   [(set_attr "conds" "use")
9938    (set_attr "length" "4,4,8,8")
9939    (set_attr "type" "*,*,*,*")]
9940 )
9941
9942 (define_insn "*ifcompare_arith_arith"
9943   [(set (match_operand:SI 0 "s_register_operand" "=r")
9944         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
9945                           [(match_operand:SI 5 "s_register_operand" "r")
9946                            (match_operand:SI 6 "arm_add_operand" "rIL")])
9947                          (match_operator:SI 8 "shiftable_operator"
9948                           [(match_operand:SI 1 "s_register_operand" "r")
9949                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
9950                          (match_operator:SI 7 "shiftable_operator"
9951                           [(match_operand:SI 3 "s_register_operand" "r")
9952                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
9953    (clobber (reg:CC CC_REGNUM))]
9954   "TARGET_ARM"
9955   "#"
9956   [(set_attr "conds" "clob")
9957    (set_attr "length" "12")]
9958 )
9959
9960 (define_insn "*if_arith_arith"
9961   [(set (match_operand:SI 0 "s_register_operand" "=r")
9962         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
9963                           [(match_operand 8 "cc_register" "") (const_int 0)])
9964                          (match_operator:SI 6 "shiftable_operator"
9965                           [(match_operand:SI 1 "s_register_operand" "r")
9966                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
9967                          (match_operator:SI 7 "shiftable_operator"
9968                           [(match_operand:SI 3 "s_register_operand" "r")
9969                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
9970   "TARGET_ARM"
9971   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
9972   [(set_attr "conds" "use")
9973    (set_attr "length" "8")]
9974 )
9975
9976 (define_insn "*ifcompare_arith_move"
9977   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9978         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9979                           [(match_operand:SI 2 "s_register_operand" "r,r")
9980                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9981                          (match_operator:SI 7 "shiftable_operator"
9982                           [(match_operand:SI 4 "s_register_operand" "r,r")
9983                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
9984                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9985    (clobber (reg:CC CC_REGNUM))]
9986   "TARGET_ARM"
9987   "*
9988   /* If we have an operation where (op x 0) is the identity operation and
9989      the conditional operator is LT or GE and we are comparing against zero and
9990      everything is in registers then we can do this in two instructions.  */
9991   if (operands[3] == const0_rtx
9992       && GET_CODE (operands[7]) != AND
9993       && GET_CODE (operands[5]) == REG
9994       && GET_CODE (operands[1]) == REG 
9995       && REGNO (operands[1]) == REGNO (operands[4])
9996       && REGNO (operands[4]) != REGNO (operands[0]))
9997     {
9998       if (GET_CODE (operands[6]) == LT)
9999         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
10000       else if (GET_CODE (operands[6]) == GE)
10001         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
10002     }
10003   if (GET_CODE (operands[3]) == CONST_INT
10004       && !const_ok_for_arm (INTVAL (operands[3])))
10005     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
10006   else
10007     output_asm_insn (\"cmp\\t%2, %3\", operands);
10008   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
10009   if (which_alternative != 0)
10010     return \"mov%D6\\t%0, %1\";
10011   return \"\";
10012   "
10013   [(set_attr "conds" "clob")
10014    (set_attr "length" "8,12")]
10015 )
10016
10017 (define_insn "*if_arith_move"
10018   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10019         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10020                           [(match_operand 6 "cc_register" "") (const_int 0)])
10021                          (match_operator:SI 5 "shiftable_operator"
10022                           [(match_operand:SI 2 "s_register_operand" "r,r")
10023                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
10024                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
10025   "TARGET_ARM"
10026   "@
10027    %I5%d4\\t%0, %2, %3
10028    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
10029   [(set_attr "conds" "use")
10030    (set_attr "length" "4,8")
10031    (set_attr "type" "*,*")]
10032 )
10033
10034 (define_insn "*ifcompare_move_arith"
10035   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10036         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
10037                           [(match_operand:SI 4 "s_register_operand" "r,r")
10038                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10039                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10040                          (match_operator:SI 7 "shiftable_operator"
10041                           [(match_operand:SI 2 "s_register_operand" "r,r")
10042                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
10043    (clobber (reg:CC CC_REGNUM))]
10044   "TARGET_ARM"
10045   "*
10046   /* If we have an operation where (op x 0) is the identity operation and
10047      the conditional operator is LT or GE and we are comparing against zero and
10048      everything is in registers then we can do this in two instructions */
10049   if (operands[5] == const0_rtx
10050       && GET_CODE (operands[7]) != AND
10051       && GET_CODE (operands[3]) == REG
10052       && GET_CODE (operands[1]) == REG 
10053       && REGNO (operands[1]) == REGNO (operands[2])
10054       && REGNO (operands[2]) != REGNO (operands[0]))
10055     {
10056       if (GET_CODE (operands[6]) == GE)
10057         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
10058       else if (GET_CODE (operands[6]) == LT)
10059         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
10060     }
10061
10062   if (GET_CODE (operands[5]) == CONST_INT
10063       && !const_ok_for_arm (INTVAL (operands[5])))
10064     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
10065   else
10066     output_asm_insn (\"cmp\\t%4, %5\", operands);
10067
10068   if (which_alternative != 0)
10069     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
10070   return \"%I7%D6\\t%0, %2, %3\";
10071   "
10072   [(set_attr "conds" "clob")
10073    (set_attr "length" "8,12")]
10074 )
10075
10076 (define_insn "*if_move_arith"
10077   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10078         (if_then_else:SI
10079          (match_operator 4 "arm_comparison_operator"
10080           [(match_operand 6 "cc_register" "") (const_int 0)])
10081          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10082          (match_operator:SI 5 "shiftable_operator"
10083           [(match_operand:SI 2 "s_register_operand" "r,r")
10084            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
10085   "TARGET_ARM"
10086   "@
10087    %I5%D4\\t%0, %2, %3
10088    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
10089   [(set_attr "conds" "use")
10090    (set_attr "length" "4,8")
10091    (set_attr "type" "*,*")]
10092 )
10093
10094 (define_insn "*ifcompare_move_not"
10095   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10096         (if_then_else:SI
10097          (match_operator 5 "arm_comparison_operator"
10098           [(match_operand:SI 3 "s_register_operand" "r,r")
10099            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10100          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10101          (not:SI
10102           (match_operand:SI 2 "s_register_operand" "r,r"))))
10103    (clobber (reg:CC CC_REGNUM))]
10104   "TARGET_ARM"
10105   "#"
10106   [(set_attr "conds" "clob")
10107    (set_attr "length" "8,12")]
10108 )
10109
10110 (define_insn "*if_move_not"
10111   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10112         (if_then_else:SI
10113          (match_operator 4 "arm_comparison_operator"
10114           [(match_operand 3 "cc_register" "") (const_int 0)])
10115          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10116          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
10117   "TARGET_ARM"
10118   "@
10119    mvn%D4\\t%0, %2
10120    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
10121    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
10122   [(set_attr "conds" "use")
10123    (set_attr "length" "4,8,8")]
10124 )
10125
10126 (define_insn "*ifcompare_not_move"
10127   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10128         (if_then_else:SI 
10129          (match_operator 5 "arm_comparison_operator"
10130           [(match_operand:SI 3 "s_register_operand" "r,r")
10131            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10132          (not:SI
10133           (match_operand:SI 2 "s_register_operand" "r,r"))
10134          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
10135    (clobber (reg:CC CC_REGNUM))]
10136   "TARGET_ARM"
10137   "#"
10138   [(set_attr "conds" "clob")
10139    (set_attr "length" "8,12")]
10140 )
10141
10142 (define_insn "*if_not_move"
10143   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10144         (if_then_else:SI
10145          (match_operator 4 "arm_comparison_operator"
10146           [(match_operand 3 "cc_register" "") (const_int 0)])
10147          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10148          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
10149   "TARGET_ARM"
10150   "@
10151    mvn%d4\\t%0, %2
10152    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
10153    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
10154   [(set_attr "conds" "use")
10155    (set_attr "length" "4,8,8")]
10156 )
10157
10158 (define_insn "*ifcompare_shift_move"
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_operator:SI 7 "shift_operator"
10165           [(match_operand:SI 2 "s_register_operand" "r,r")
10166            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
10167          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
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_shift_move"
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_operator:SI 4 "shift_operator"
10181           [(match_operand:SI 2 "s_register_operand" "r,r,r")
10182            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
10183          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
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_move_shift"
10198   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10199         (if_then_else:SI
10200          (match_operator 6 "arm_comparison_operator"
10201           [(match_operand:SI 4 "s_register_operand" "r,r")
10202            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10203          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10204          (match_operator:SI 7 "shift_operator"
10205           [(match_operand:SI 2 "s_register_operand" "r,r")
10206            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
10207    (clobber (reg:CC CC_REGNUM))]
10208   "TARGET_ARM"
10209   "#"
10210   [(set_attr "conds" "clob")
10211    (set_attr "length" "8,12")]
10212 )
10213
10214 (define_insn "*if_move_shift"
10215   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10216         (if_then_else:SI
10217          (match_operator 5 "arm_comparison_operator"
10218           [(match_operand 6 "cc_register" "") (const_int 0)])
10219          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10220          (match_operator:SI 4 "shift_operator"
10221           [(match_operand:SI 2 "s_register_operand" "r,r,r")
10222            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
10223   "TARGET_ARM"
10224   "@
10225    mov%D5\\t%0, %2%S4
10226    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
10227    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
10228   [(set_attr "conds" "use")
10229    (set_attr "shift" "2")
10230    (set_attr "length" "4,8,8")
10231    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
10232                       (const_string "alu_shift")
10233                       (const_string "alu_shift_reg")))]
10234 )
10235
10236 (define_insn "*ifcompare_shift_shift"
10237   [(set (match_operand:SI 0 "s_register_operand" "=r")
10238         (if_then_else:SI
10239          (match_operator 7 "arm_comparison_operator"
10240           [(match_operand:SI 5 "s_register_operand" "r")
10241            (match_operand:SI 6 "arm_add_operand" "rIL")])
10242          (match_operator:SI 8 "shift_operator"
10243           [(match_operand:SI 1 "s_register_operand" "r")
10244            (match_operand:SI 2 "arm_rhs_operand" "rM")])
10245          (match_operator:SI 9 "shift_operator"
10246           [(match_operand:SI 3 "s_register_operand" "r")
10247            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
10248    (clobber (reg:CC CC_REGNUM))]
10249   "TARGET_ARM"
10250   "#"
10251   [(set_attr "conds" "clob")
10252    (set_attr "length" "12")]
10253 )
10254
10255 (define_insn "*if_shift_shift"
10256   [(set (match_operand:SI 0 "s_register_operand" "=r")
10257         (if_then_else:SI
10258          (match_operator 5 "arm_comparison_operator"
10259           [(match_operand 8 "cc_register" "") (const_int 0)])
10260          (match_operator:SI 6 "shift_operator"
10261           [(match_operand:SI 1 "s_register_operand" "r")
10262            (match_operand:SI 2 "arm_rhs_operand" "rM")])
10263          (match_operator:SI 7 "shift_operator"
10264           [(match_operand:SI 3 "s_register_operand" "r")
10265            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
10266   "TARGET_ARM"
10267   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
10268   [(set_attr "conds" "use")
10269    (set_attr "shift" "1")
10270    (set_attr "length" "8")
10271    (set (attr "type") (if_then_else
10272                         (and (match_operand 2 "const_int_operand" "")
10273                              (match_operand 4 "const_int_operand" ""))
10274                       (const_string "alu_shift")
10275                       (const_string "alu_shift_reg")))]
10276 )
10277
10278 (define_insn "*ifcompare_not_arith"
10279   [(set (match_operand:SI 0 "s_register_operand" "=r")
10280         (if_then_else:SI
10281          (match_operator 6 "arm_comparison_operator"
10282           [(match_operand:SI 4 "s_register_operand" "r")
10283            (match_operand:SI 5 "arm_add_operand" "rIL")])
10284          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10285          (match_operator:SI 7 "shiftable_operator"
10286           [(match_operand:SI 2 "s_register_operand" "r")
10287            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
10288    (clobber (reg:CC CC_REGNUM))]
10289   "TARGET_ARM"
10290   "#"
10291   [(set_attr "conds" "clob")
10292    (set_attr "length" "12")]
10293 )
10294
10295 (define_insn "*if_not_arith"
10296   [(set (match_operand:SI 0 "s_register_operand" "=r")
10297         (if_then_else:SI
10298          (match_operator 5 "arm_comparison_operator"
10299           [(match_operand 4 "cc_register" "") (const_int 0)])
10300          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10301          (match_operator:SI 6 "shiftable_operator"
10302           [(match_operand:SI 2 "s_register_operand" "r")
10303            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
10304   "TARGET_ARM"
10305   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
10306   [(set_attr "conds" "use")
10307    (set_attr "length" "8")]
10308 )
10309
10310 (define_insn "*ifcompare_arith_not"
10311   [(set (match_operand:SI 0 "s_register_operand" "=r")
10312         (if_then_else:SI
10313          (match_operator 6 "arm_comparison_operator"
10314           [(match_operand:SI 4 "s_register_operand" "r")
10315            (match_operand:SI 5 "arm_add_operand" "rIL")])
10316          (match_operator:SI 7 "shiftable_operator"
10317           [(match_operand:SI 2 "s_register_operand" "r")
10318            (match_operand:SI 3 "arm_rhs_operand" "rI")])
10319          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
10320    (clobber (reg:CC CC_REGNUM))]
10321   "TARGET_ARM"
10322   "#"
10323   [(set_attr "conds" "clob")
10324    (set_attr "length" "12")]
10325 )
10326
10327 (define_insn "*if_arith_not"
10328   [(set (match_operand:SI 0 "s_register_operand" "=r")
10329         (if_then_else:SI
10330          (match_operator 5 "arm_comparison_operator"
10331           [(match_operand 4 "cc_register" "") (const_int 0)])
10332          (match_operator:SI 6 "shiftable_operator"
10333           [(match_operand:SI 2 "s_register_operand" "r")
10334            (match_operand:SI 3 "arm_rhs_operand" "rI")])
10335          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
10336   "TARGET_ARM"
10337   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
10338   [(set_attr "conds" "use")
10339    (set_attr "length" "8")]
10340 )
10341
10342 (define_insn "*ifcompare_neg_move"
10343   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10344         (if_then_else:SI
10345          (match_operator 5 "arm_comparison_operator"
10346           [(match_operand:SI 3 "s_register_operand" "r,r")
10347            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10348          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10349          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
10350    (clobber (reg:CC CC_REGNUM))]
10351   "TARGET_ARM"
10352   "#"
10353   [(set_attr "conds" "clob")
10354    (set_attr "length" "8,12")]
10355 )
10356
10357 (define_insn "*if_neg_move"
10358   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10359         (if_then_else:SI
10360          (match_operator 4 "arm_comparison_operator"
10361           [(match_operand 3 "cc_register" "") (const_int 0)])
10362          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10363          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
10364   "TARGET_ARM"
10365   "@
10366    rsb%d4\\t%0, %2, #0
10367    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
10368    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
10369   [(set_attr "conds" "use")
10370    (set_attr "length" "4,8,8")]
10371 )
10372
10373 (define_insn "*ifcompare_move_neg"
10374   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10375         (if_then_else:SI
10376          (match_operator 5 "arm_comparison_operator"
10377           [(match_operand:SI 3 "s_register_operand" "r,r")
10378            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10379          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10380          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
10381    (clobber (reg:CC CC_REGNUM))]
10382   "TARGET_ARM"
10383   "#"
10384   [(set_attr "conds" "clob")
10385    (set_attr "length" "8,12")]
10386 )
10387
10388 (define_insn "*if_move_neg"
10389   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10390         (if_then_else:SI
10391          (match_operator 4 "arm_comparison_operator"
10392           [(match_operand 3 "cc_register" "") (const_int 0)])
10393          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10394          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
10395   "TARGET_ARM"
10396   "@
10397    rsb%D4\\t%0, %2, #0
10398    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
10399    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
10400   [(set_attr "conds" "use")
10401    (set_attr "length" "4,8,8")]
10402 )
10403
10404 (define_insn "*arith_adjacentmem"
10405   [(set (match_operand:SI 0 "s_register_operand" "=r")
10406         (match_operator:SI 1 "shiftable_operator"
10407          [(match_operand:SI 2 "memory_operand" "m")
10408           (match_operand:SI 3 "memory_operand" "m")]))
10409    (clobber (match_scratch:SI 4 "=r"))]
10410   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
10411   "*
10412   {
10413     rtx ldm[3];
10414     rtx arith[4];
10415     rtx base_reg;
10416     HOST_WIDE_INT val1 = 0, val2 = 0;
10417
10418     if (REGNO (operands[0]) > REGNO (operands[4]))
10419       {
10420         ldm[1] = operands[4];
10421         ldm[2] = operands[0];
10422       }
10423     else
10424       {
10425         ldm[1] = operands[0];
10426         ldm[2] = operands[4];
10427       }
10428
10429     base_reg = XEXP (operands[2], 0);
10430
10431     if (!REG_P (base_reg))
10432       {
10433         val1 = INTVAL (XEXP (base_reg, 1));
10434         base_reg = XEXP (base_reg, 0);
10435       }
10436
10437     if (!REG_P (XEXP (operands[3], 0)))
10438       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
10439
10440     arith[0] = operands[0];
10441     arith[3] = operands[1];
10442
10443     if (val1 < val2)
10444       {
10445         arith[1] = ldm[1];
10446         arith[2] = ldm[2];
10447       }
10448     else
10449       {
10450         arith[1] = ldm[2];
10451         arith[2] = ldm[1];
10452       }
10453
10454     ldm[0] = base_reg;
10455     if (val1 !=0 && val2 != 0)
10456       {
10457         rtx ops[3];
10458
10459         if (val1 == 4 || val2 == 4)
10460           /* Other val must be 8, since we know they are adjacent and neither
10461              is zero.  */
10462           output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
10463         else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
10464           {
10465             ldm[0] = ops[0] = operands[4];
10466             ops[1] = base_reg;
10467             ops[2] = GEN_INT (val1);
10468             output_add_immediate (ops);
10469             if (val1 < val2)
10470               output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
10471             else
10472               output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
10473           }
10474         else
10475           {
10476             /* Offset is out of range for a single add, so use two ldr.  */
10477             ops[0] = ldm[1];
10478             ops[1] = base_reg;
10479             ops[2] = GEN_INT (val1);
10480             output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10481             ops[0] = ldm[2];
10482             ops[2] = GEN_INT (val2);
10483             output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10484           }
10485       }
10486     else if (val1 != 0)
10487       {
10488         if (val1 < val2)
10489           output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
10490         else
10491           output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
10492       }
10493     else
10494       {
10495         if (val1 < val2)
10496           output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
10497         else
10498           output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
10499       }
10500     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10501     return \"\";
10502   }"
10503   [(set_attr "length" "12")
10504    (set_attr "predicable" "yes")
10505    (set_attr "type" "load1")]
10506 )
10507
10508 ; This pattern is never tried by combine, so do it as a peephole
10509
10510 (define_peephole2
10511   [(set (match_operand:SI 0 "arm_general_register_operand" "")
10512         (match_operand:SI 1 "arm_general_register_operand" ""))
10513    (set (reg:CC CC_REGNUM)
10514         (compare:CC (match_dup 1) (const_int 0)))]
10515   "TARGET_ARM"
10516   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10517               (set (match_dup 0) (match_dup 1))])]
10518   ""
10519 )
10520
10521 ; Peepholes to spot possible load- and store-multiples, if the ordering is
10522 ; reversed, check that the memory references aren't volatile.
10523
10524 (define_peephole
10525   [(set (match_operand:SI 0 "s_register_operand" "=rk")
10526         (match_operand:SI 4 "memory_operand" "m"))
10527    (set (match_operand:SI 1 "s_register_operand" "=rk")
10528         (match_operand:SI 5 "memory_operand" "m"))
10529    (set (match_operand:SI 2 "s_register_operand" "=rk")
10530         (match_operand:SI 6 "memory_operand" "m"))
10531    (set (match_operand:SI 3 "s_register_operand" "=rk")
10532         (match_operand:SI 7 "memory_operand" "m"))]
10533   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
10534   "*
10535   return emit_ldm_seq (operands, 4);
10536   "
10537 )
10538
10539 (define_peephole
10540   [(set (match_operand:SI 0 "s_register_operand" "=rk")
10541         (match_operand:SI 3 "memory_operand" "m"))
10542    (set (match_operand:SI 1 "s_register_operand" "=rk")
10543         (match_operand:SI 4 "memory_operand" "m"))
10544    (set (match_operand:SI 2 "s_register_operand" "=rk")
10545         (match_operand:SI 5 "memory_operand" "m"))]
10546   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
10547   "*
10548   return emit_ldm_seq (operands, 3);
10549   "
10550 )
10551
10552 (define_peephole
10553   [(set (match_operand:SI 0 "s_register_operand" "=rk")
10554         (match_operand:SI 2 "memory_operand" "m"))
10555    (set (match_operand:SI 1 "s_register_operand" "=rk")
10556         (match_operand:SI 3 "memory_operand" "m"))]
10557   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
10558   "*
10559   return emit_ldm_seq (operands, 2);
10560   "
10561 )
10562
10563 (define_peephole
10564   [(set (match_operand:SI 4 "memory_operand" "=m")
10565         (match_operand:SI 0 "s_register_operand" "rk"))
10566    (set (match_operand:SI 5 "memory_operand" "=m")
10567         (match_operand:SI 1 "s_register_operand" "rk"))
10568    (set (match_operand:SI 6 "memory_operand" "=m")
10569         (match_operand:SI 2 "s_register_operand" "rk"))
10570    (set (match_operand:SI 7 "memory_operand" "=m")
10571         (match_operand:SI 3 "s_register_operand" "rk"))]
10572   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
10573   "*
10574   return emit_stm_seq (operands, 4);
10575   "
10576 )
10577
10578 (define_peephole
10579   [(set (match_operand:SI 3 "memory_operand" "=m")
10580         (match_operand:SI 0 "s_register_operand" "rk"))
10581    (set (match_operand:SI 4 "memory_operand" "=m")
10582         (match_operand:SI 1 "s_register_operand" "rk"))
10583    (set (match_operand:SI 5 "memory_operand" "=m")
10584         (match_operand:SI 2 "s_register_operand" "rk"))]
10585   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
10586   "*
10587   return emit_stm_seq (operands, 3);
10588   "
10589 )
10590
10591 (define_peephole
10592   [(set (match_operand:SI 2 "memory_operand" "=m")
10593         (match_operand:SI 0 "s_register_operand" "rk"))
10594    (set (match_operand:SI 3 "memory_operand" "=m")
10595         (match_operand:SI 1 "s_register_operand" "rk"))]
10596   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
10597   "*
10598   return emit_stm_seq (operands, 2);
10599   "
10600 )
10601
10602 (define_split
10603   [(set (match_operand:SI 0 "s_register_operand" "")
10604         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10605                        (const_int 0))
10606                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
10607                          [(match_operand:SI 3 "s_register_operand" "")
10608                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
10609    (clobber (match_operand:SI 5 "s_register_operand" ""))]
10610   "TARGET_ARM"
10611   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10612    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10613                               (match_dup 5)))]
10614   ""
10615 )
10616
10617 ;; This split can be used because CC_Z mode implies that the following
10618 ;; branch will be an equality, or an unsigned inequality, so the sign
10619 ;; extension is not needed.
10620
10621 (define_split
10622   [(set (reg:CC_Z CC_REGNUM)
10623         (compare:CC_Z
10624          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
10625                     (const_int 24))
10626          (match_operand 1 "const_int_operand" "")))
10627    (clobber (match_scratch:SI 2 ""))]
10628   "TARGET_ARM
10629    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10630        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
10631   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
10632    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
10633   "
10634   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
10635   "
10636 )
10637 ;; ??? Check the patterns above for Thumb-2 usefulness
10638
10639 (define_expand "prologue"
10640   [(clobber (const_int 0))]
10641   "TARGET_EITHER"
10642   "if (TARGET_32BIT)
10643      arm_expand_prologue ();
10644    else
10645      thumb1_expand_prologue ();
10646   DONE;
10647   "
10648 )
10649
10650 (define_expand "epilogue"
10651   [(clobber (const_int 0))]
10652   "TARGET_EITHER"
10653   "
10654   if (crtl->calls_eh_return)
10655     emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
10656   if (TARGET_THUMB1)
10657     thumb1_expand_epilogue ();
10658   else if (USE_RETURN_INSN (FALSE))
10659     {
10660       emit_jump_insn (gen_return ());
10661       DONE;
10662     }
10663   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10664         gen_rtvec (1,
10665                 gen_rtx_RETURN (VOIDmode)),
10666         VUNSPEC_EPILOGUE));
10667   DONE;
10668   "
10669 )
10670
10671 ;; Note - although unspec_volatile's USE all hard registers,
10672 ;; USEs are ignored after relaod has completed.  Thus we need
10673 ;; to add an unspec of the link register to ensure that flow
10674 ;; does not think that it is unused by the sibcall branch that
10675 ;; will replace the standard function epilogue.
10676 (define_insn "sibcall_epilogue"
10677   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
10678               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10679   "TARGET_32BIT"
10680   "*
10681   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
10682     return output_return_instruction (const_true_rtx, FALSE, FALSE);
10683   return arm_output_epilogue (next_nonnote_insn (insn));
10684   "
10685 ;; Length is absolute worst case
10686   [(set_attr "length" "44")
10687    (set_attr "type" "block")
10688    ;; We don't clobber the conditions, but the potential length of this
10689    ;; operation is sufficient to make conditionalizing the sequence 
10690    ;; unlikely to be profitable.
10691    (set_attr "conds" "clob")]
10692 )
10693
10694 (define_insn "*epilogue_insns"
10695   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
10696   "TARGET_EITHER"
10697   "*
10698   if (TARGET_32BIT)
10699     return arm_output_epilogue (NULL);
10700   else /* TARGET_THUMB1 */
10701     return thumb_unexpanded_epilogue ();
10702   "
10703   ; Length is absolute worst case
10704   [(set_attr "length" "44")
10705    (set_attr "type" "block")
10706    ;; We don't clobber the conditions, but the potential length of this
10707    ;; operation is sufficient to make conditionalizing the sequence 
10708    ;; unlikely to be profitable.
10709    (set_attr "conds" "clob")]
10710 )
10711
10712 (define_expand "eh_epilogue"
10713   [(use (match_operand:SI 0 "register_operand" ""))
10714    (use (match_operand:SI 1 "register_operand" ""))
10715    (use (match_operand:SI 2 "register_operand" ""))]
10716   "TARGET_EITHER"
10717   "
10718   {
10719     cfun->machine->eh_epilogue_sp_ofs = operands[1];
10720     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10721       {
10722         rtx ra = gen_rtx_REG (Pmode, 2);
10723
10724         emit_move_insn (ra, operands[2]);
10725         operands[2] = ra;
10726       }
10727     /* This is a hack -- we may have crystalized the function type too
10728        early.  */
10729     cfun->machine->func_type = 0;
10730   }"
10731 )
10732
10733 ;; This split is only used during output to reduce the number of patterns
10734 ;; that need assembler instructions adding to them.  We allowed the setting
10735 ;; of the conditions to be implicit during rtl generation so that
10736 ;; the conditional compare patterns would work.  However this conflicts to
10737 ;; some extent with the conditional data operations, so we have to split them
10738 ;; up again here.
10739
10740 ;; ??? Need to audit these splitters for Thumb-2.  Why isn't normal
10741 ;; conditional execution sufficient?
10742
10743 (define_split
10744   [(set (match_operand:SI 0 "s_register_operand" "")
10745         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10746                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10747                          (match_dup 0)
10748                          (match_operand 4 "" "")))
10749    (clobber (reg:CC CC_REGNUM))]
10750   "TARGET_ARM && reload_completed"
10751   [(set (match_dup 5) (match_dup 6))
10752    (cond_exec (match_dup 7)
10753               (set (match_dup 0) (match_dup 4)))]
10754   "
10755   {
10756     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10757                                              operands[2], operands[3]);
10758     enum rtx_code rc = GET_CODE (operands[1]);
10759
10760     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10761     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10762     if (mode == CCFPmode || mode == CCFPEmode)
10763       rc = reverse_condition_maybe_unordered (rc);
10764     else
10765       rc = reverse_condition (rc);
10766
10767     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10768   }"
10769 )
10770
10771 (define_split
10772   [(set (match_operand:SI 0 "s_register_operand" "")
10773         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10774                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10775                          (match_operand 4 "" "")
10776                          (match_dup 0)))
10777    (clobber (reg:CC CC_REGNUM))]
10778   "TARGET_ARM && reload_completed"
10779   [(set (match_dup 5) (match_dup 6))
10780    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10781               (set (match_dup 0) (match_dup 4)))]
10782   "
10783   {
10784     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10785                                              operands[2], operands[3]);
10786
10787     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10788     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10789   }"
10790 )
10791
10792 (define_split
10793   [(set (match_operand:SI 0 "s_register_operand" "")
10794         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10795                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10796                          (match_operand 4 "" "")
10797                          (match_operand 5 "" "")))
10798    (clobber (reg:CC CC_REGNUM))]
10799   "TARGET_ARM && reload_completed"
10800   [(set (match_dup 6) (match_dup 7))
10801    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10802               (set (match_dup 0) (match_dup 4)))
10803    (cond_exec (match_dup 8)
10804               (set (match_dup 0) (match_dup 5)))]
10805   "
10806   {
10807     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10808                                              operands[2], operands[3]);
10809     enum rtx_code rc = GET_CODE (operands[1]);
10810
10811     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10812     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10813     if (mode == CCFPmode || mode == CCFPEmode)
10814       rc = reverse_condition_maybe_unordered (rc);
10815     else
10816       rc = reverse_condition (rc);
10817
10818     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10819   }"
10820 )
10821
10822 (define_split
10823   [(set (match_operand:SI 0 "s_register_operand" "")
10824         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10825                           [(match_operand:SI 2 "s_register_operand" "")
10826                            (match_operand:SI 3 "arm_add_operand" "")])
10827                          (match_operand:SI 4 "arm_rhs_operand" "")
10828                          (not:SI
10829                           (match_operand:SI 5 "s_register_operand" ""))))
10830    (clobber (reg:CC CC_REGNUM))]
10831   "TARGET_ARM && reload_completed"
10832   [(set (match_dup 6) (match_dup 7))
10833    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10834               (set (match_dup 0) (match_dup 4)))
10835    (cond_exec (match_dup 8)
10836               (set (match_dup 0) (not:SI (match_dup 5))))]
10837   "
10838   {
10839     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10840                                              operands[2], operands[3]);
10841     enum rtx_code rc = GET_CODE (operands[1]);
10842
10843     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10844     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10845     if (mode == CCFPmode || mode == CCFPEmode)
10846       rc = reverse_condition_maybe_unordered (rc);
10847     else
10848       rc = reverse_condition (rc);
10849
10850     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10851   }"
10852 )
10853
10854 (define_insn "*cond_move_not"
10855   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10856         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10857                           [(match_operand 3 "cc_register" "") (const_int 0)])
10858                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10859                          (not:SI
10860                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
10861   "TARGET_ARM"
10862   "@
10863    mvn%D4\\t%0, %2
10864    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
10865   [(set_attr "conds" "use")
10866    (set_attr "length" "4,8")]
10867 )
10868
10869 ;; The next two patterns occur when an AND operation is followed by a
10870 ;; scc insn sequence 
10871
10872 (define_insn "*sign_extract_onebit"
10873   [(set (match_operand:SI 0 "s_register_operand" "=r")
10874         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10875                          (const_int 1)
10876                          (match_operand:SI 2 "const_int_operand" "n")))
10877     (clobber (reg:CC CC_REGNUM))]
10878   "TARGET_ARM"
10879   "*
10880     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10881     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10882     return \"mvnne\\t%0, #0\";
10883   "
10884   [(set_attr "conds" "clob")
10885    (set_attr "length" "8")]
10886 )
10887
10888 (define_insn "*not_signextract_onebit"
10889   [(set (match_operand:SI 0 "s_register_operand" "=r")
10890         (not:SI
10891          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10892                           (const_int 1)
10893                           (match_operand:SI 2 "const_int_operand" "n"))))
10894    (clobber (reg:CC CC_REGNUM))]
10895   "TARGET_ARM"
10896   "*
10897     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10898     output_asm_insn (\"tst\\t%1, %2\", operands);
10899     output_asm_insn (\"mvneq\\t%0, #0\", operands);
10900     return \"movne\\t%0, #0\";
10901   "
10902   [(set_attr "conds" "clob")
10903    (set_attr "length" "12")]
10904 )
10905 ;; ??? The above patterns need auditing for Thumb-2
10906
10907 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
10908 ;; expressions.  For simplicity, the first register is also in the unspec
10909 ;; part.
10910 (define_insn "*push_multi"
10911   [(match_parallel 2 "multi_register_push"
10912     [(set (match_operand:BLK 0 "memory_operand" "=m")
10913           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
10914                       UNSPEC_PUSH_MULT))])]
10915   "TARGET_32BIT"
10916   "*
10917   {
10918     int num_saves = XVECLEN (operands[2], 0);
10919      
10920     /* For the StrongARM at least it is faster to
10921        use STR to store only a single register.
10922        In Thumb mode always use push, and the assembler will pick
10923        something appropriate.  */
10924     if (num_saves == 1 && TARGET_ARM)
10925       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10926     else
10927       {
10928         int i;
10929         char pattern[100];
10930
10931         if (TARGET_ARM)
10932             strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10933         else
10934             strcpy (pattern, \"push\\t{%1\");
10935
10936         for (i = 1; i < num_saves; i++)
10937           {
10938             strcat (pattern, \", %|\");
10939             strcat (pattern,
10940                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10941           }
10942
10943         strcat (pattern, \"}\");
10944         output_asm_insn (pattern, operands);
10945       }
10946
10947     return \"\";
10948   }"
10949   [(set_attr "type" "store4")]
10950 )
10951
10952 (define_insn "stack_tie"
10953   [(set (mem:BLK (scratch))
10954         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10955                      (match_operand:SI 1 "s_register_operand" "rk")]
10956                     UNSPEC_PRLG_STK))]
10957   ""
10958   ""
10959   [(set_attr "length" "0")]
10960 )
10961
10962 ;; Similarly for the floating point registers
10963 (define_insn "*push_fp_multi"
10964   [(match_parallel 2 "multi_register_push"
10965     [(set (match_operand:BLK 0 "memory_operand" "=m")
10966           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "")]
10967                       UNSPEC_PUSH_MULT))])]
10968   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
10969   "*
10970   {
10971     char pattern[100];
10972
10973     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10974     output_asm_insn (pattern, operands);
10975     return \"\";
10976   }"
10977   [(set_attr "type" "f_store")]
10978 )
10979
10980 ;; Special patterns for dealing with the constant pool
10981
10982 (define_insn "align_4"
10983   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10984   "TARGET_EITHER"
10985   "*
10986   assemble_align (32);
10987   return \"\";
10988   "
10989 )
10990
10991 (define_insn "align_8"
10992   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10993   "TARGET_EITHER"
10994   "*
10995   assemble_align (64);
10996   return \"\";
10997   "
10998 )
10999
11000 (define_insn "consttable_end"
11001   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
11002   "TARGET_EITHER"
11003   "*
11004   making_const_table = FALSE;
11005   return \"\";
11006   "
11007 )
11008
11009 (define_insn "consttable_1"
11010   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
11011   "TARGET_THUMB1"
11012   "*
11013   making_const_table = TRUE;
11014   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
11015   assemble_zeros (3);
11016   return \"\";
11017   "
11018   [(set_attr "length" "4")]
11019 )
11020
11021 (define_insn "consttable_2"
11022   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
11023   "TARGET_THUMB1"
11024   "*
11025   making_const_table = TRUE;
11026   gcc_assert (GET_MODE_CLASS (GET_MODE (operands[0])) != MODE_FLOAT);
11027   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
11028   assemble_zeros (2);
11029   return \"\";
11030   "
11031   [(set_attr "length" "4")]
11032 )
11033
11034 (define_insn "consttable_4"
11035   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
11036   "TARGET_EITHER"
11037   "*
11038   {
11039     rtx x = operands[0];
11040     making_const_table = TRUE;
11041     switch (GET_MODE_CLASS (GET_MODE (x)))
11042       {
11043       case MODE_FLOAT:
11044         if (GET_MODE (x) == HFmode)
11045           arm_emit_fp16_const (x);
11046         else
11047           {
11048             REAL_VALUE_TYPE r;
11049             REAL_VALUE_FROM_CONST_DOUBLE (r, x);
11050             assemble_real (r, GET_MODE (x), BITS_PER_WORD);
11051           }
11052         break;
11053       default:
11054         /* XXX: Sometimes gcc does something really dumb and ends up with
11055            a HIGH in a constant pool entry, usually because it's trying to
11056            load into a VFP register.  We know this will always be used in
11057            combination with a LO_SUM which ignores the high bits, so just
11058            strip off the HIGH.  */
11059         if (GET_CODE (x) == HIGH)
11060           x = XEXP (x, 0);
11061         assemble_integer (x, 4, BITS_PER_WORD, 1);
11062         mark_symbol_refs_as_used (x);
11063         break;
11064       }
11065     return \"\";
11066   }"
11067   [(set_attr "length" "4")]
11068 )
11069
11070 (define_insn "consttable_8"
11071   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
11072   "TARGET_EITHER"
11073   "*
11074   {
11075     making_const_table = TRUE;
11076     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
11077       {
11078        case MODE_FLOAT:
11079         {
11080           REAL_VALUE_TYPE r;
11081           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
11082           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
11083           break;
11084         }
11085       default:
11086         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
11087         break;
11088       }
11089     return \"\";
11090   }"
11091   [(set_attr "length" "8")]
11092 )
11093
11094 (define_insn "consttable_16"
11095   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
11096   "TARGET_EITHER"
11097   "*
11098   {
11099     making_const_table = TRUE;
11100     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
11101       {
11102        case MODE_FLOAT:
11103         {
11104           REAL_VALUE_TYPE r;
11105           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
11106           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
11107           break;
11108         }
11109       default:
11110         assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
11111         break;
11112       }
11113     return \"\";
11114   }"
11115   [(set_attr "length" "16")]
11116 )
11117
11118 ;; Miscellaneous Thumb patterns
11119
11120 (define_expand "tablejump"
11121   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
11122               (use (label_ref (match_operand 1 "" "")))])]
11123   "TARGET_THUMB1"
11124   "
11125   if (flag_pic)
11126     {
11127       /* Hopefully, CSE will eliminate this copy.  */
11128       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
11129       rtx reg2 = gen_reg_rtx (SImode);
11130
11131       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
11132       operands[0] = reg2;
11133     }
11134   "
11135 )
11136
11137 ;; NB never uses BX.
11138 (define_insn "*thumb1_tablejump"
11139   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
11140    (use (label_ref (match_operand 1 "" "")))]
11141   "TARGET_THUMB1"
11142   "mov\\t%|pc, %0"
11143   [(set_attr "length" "2")]
11144 )
11145
11146 ;; V5 Instructions,
11147
11148 (define_insn "clzsi2"
11149   [(set (match_operand:SI 0 "s_register_operand" "=r")
11150         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
11151   "TARGET_32BIT && arm_arch5"
11152   "clz%?\\t%0, %1"
11153   [(set_attr "predicable" "yes")
11154    (set_attr "insn" "clz")])
11155
11156 (define_insn "rbitsi2"
11157   [(set (match_operand:SI 0 "s_register_operand" "=r")
11158         (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
11159   "TARGET_32BIT && arm_arch_thumb2"
11160   "rbit%?\\t%0, %1"
11161   [(set_attr "predicable" "yes")
11162    (set_attr "insn" "clz")])
11163
11164 (define_expand "ctzsi2"
11165  [(set (match_operand:SI           0 "s_register_operand" "")
11166        (ctz:SI (match_operand:SI  1 "s_register_operand" "")))]
11167   "TARGET_32BIT && arm_arch_thumb2"
11168   "
11169    {
11170      rtx tmp = gen_reg_rtx (SImode); 
11171      emit_insn (gen_rbitsi2 (tmp, operands[1]));
11172      emit_insn (gen_clzsi2 (operands[0], tmp));
11173    }
11174    DONE;
11175   "
11176 )
11177
11178 ;; V5E instructions.
11179
11180 (define_insn "prefetch"
11181   [(prefetch (match_operand:SI 0 "address_operand" "p")
11182              (match_operand:SI 1 "" "")
11183              (match_operand:SI 2 "" ""))]
11184   "TARGET_32BIT && arm_arch5e"
11185   "pld\\t%a0")
11186
11187 ;; General predication pattern
11188
11189 (define_cond_exec
11190   [(match_operator 0 "arm_comparison_operator"
11191     [(match_operand 1 "cc_register" "")
11192      (const_int 0)])]
11193   "TARGET_32BIT"
11194   ""
11195 )
11196
11197 (define_insn "prologue_use"
11198   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
11199   ""
11200   "%@ %0 needed for prologue"
11201   [(set_attr "length" "0")]
11202 )
11203
11204
11205 ;; Patterns for exception handling
11206
11207 (define_expand "eh_return"
11208   [(use (match_operand 0 "general_operand" ""))]
11209   "TARGET_EITHER"
11210   "
11211   {
11212     if (TARGET_32BIT)
11213       emit_insn (gen_arm_eh_return (operands[0]));
11214     else
11215       emit_insn (gen_thumb_eh_return (operands[0]));
11216     DONE;
11217   }"
11218 )
11219                                    
11220 ;; We can't expand this before we know where the link register is stored.
11221 (define_insn_and_split "arm_eh_return"
11222   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
11223                     VUNSPEC_EH_RETURN)
11224    (clobber (match_scratch:SI 1 "=&r"))]
11225   "TARGET_ARM"
11226   "#"
11227   "&& reload_completed"
11228   [(const_int 0)]
11229   "
11230   {
11231     arm_set_return_address (operands[0], operands[1]);
11232     DONE;
11233   }"
11234 )
11235
11236 (define_insn_and_split "thumb_eh_return"
11237   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
11238                     VUNSPEC_EH_RETURN)
11239    (clobber (match_scratch:SI 1 "=&l"))]
11240   "TARGET_THUMB1"
11241   "#"
11242   "&& reload_completed"
11243   [(const_int 0)]
11244   "
11245   {
11246     thumb_set_return_address (operands[0], operands[1]);
11247     DONE;
11248   }"
11249 )
11250
11251 \f
11252 ;; TLS support
11253
11254 (define_insn "load_tp_hard"
11255   [(set (match_operand:SI 0 "register_operand" "=r")
11256         (unspec:SI [(const_int 0)] UNSPEC_TLS))]
11257   "TARGET_HARD_TP"
11258   "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
11259   [(set_attr "predicable" "yes")]
11260 )
11261
11262 ;; Doesn't clobber R1-R3.  Must use r0 for the first operand.
11263 (define_insn "load_tp_soft"
11264   [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
11265    (clobber (reg:SI LR_REGNUM))
11266    (clobber (reg:SI IP_REGNUM))
11267    (clobber (reg:CC CC_REGNUM))]
11268   "TARGET_SOFT_TP"
11269   "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
11270   [(set_attr "conds" "clob")]
11271 )
11272
11273 (define_insn "*arm_movtas_ze" 
11274   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
11275                    (const_int 16)
11276                    (const_int 16))
11277         (match_operand:SI 1 "const_int_operand" ""))]
11278   "TARGET_32BIT"
11279   "movt%?\t%0, %c1"
11280  [(set_attr "predicable" "yes")
11281    (set_attr "length" "4")]
11282 )
11283
11284 (define_insn "arm_rev"
11285   [(set (match_operand:SI 0 "s_register_operand" "=r")
11286         (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
11287   "TARGET_EITHER && arm_arch6"
11288   "rev\t%0, %1"
11289   [(set (attr "length")
11290         (if_then_else (eq_attr "is_thumb" "yes")
11291                       (const_int 2)
11292                       (const_int 4)))]
11293 )
11294
11295 (define_expand "arm_legacy_rev"
11296   [(set (match_operand:SI 2 "s_register_operand" "")
11297         (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
11298                              (const_int 16))
11299                 (match_dup 1)))
11300    (set (match_dup 2)
11301         (lshiftrt:SI (match_dup 2)
11302                      (const_int 8)))
11303    (set (match_operand:SI 3 "s_register_operand" "")
11304         (rotatert:SI (match_dup 1)
11305                      (const_int 8)))
11306    (set (match_dup 2)
11307         (and:SI (match_dup 2)
11308                 (const_int -65281)))
11309    (set (match_operand:SI 0 "s_register_operand" "")
11310         (xor:SI (match_dup 3)
11311                 (match_dup 2)))]
11312   "TARGET_32BIT"
11313   ""
11314 )
11315
11316 ;; Reuse temporaries to keep register pressure down.
11317 (define_expand "thumb_legacy_rev"
11318   [(set (match_operand:SI 2 "s_register_operand" "")
11319      (ashift:SI (match_operand:SI 1 "s_register_operand" "")
11320                 (const_int 24)))
11321    (set (match_operand:SI 3 "s_register_operand" "")
11322      (lshiftrt:SI (match_dup 1)
11323                   (const_int 24)))
11324    (set (match_dup 3)
11325      (ior:SI (match_dup 3)
11326              (match_dup 2)))
11327    (set (match_operand:SI 4 "s_register_operand" "")
11328      (const_int 16))
11329    (set (match_operand:SI 5 "s_register_operand" "")
11330      (rotatert:SI (match_dup 1)
11331                   (match_dup 4)))
11332    (set (match_dup 2)
11333      (ashift:SI (match_dup 5)
11334                 (const_int 24)))
11335    (set (match_dup 5)
11336      (lshiftrt:SI (match_dup 5)
11337                   (const_int 24)))
11338    (set (match_dup 5)
11339      (ior:SI (match_dup 5)
11340              (match_dup 2)))
11341    (set (match_dup 5)
11342      (rotatert:SI (match_dup 5)
11343                   (match_dup 4)))
11344    (set (match_operand:SI 0 "s_register_operand" "")
11345      (ior:SI (match_dup 5)
11346              (match_dup 3)))]
11347   "TARGET_THUMB"
11348   ""
11349 )
11350
11351 (define_expand "bswapsi2"
11352   [(set (match_operand:SI 0 "s_register_operand" "=r")
11353         (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
11354 "TARGET_EITHER"
11355 "
11356   if (!arm_arch6)
11357     {
11358       if (!optimize_size)
11359         {
11360           rtx op2 = gen_reg_rtx (SImode);
11361           rtx op3 = gen_reg_rtx (SImode);
11362
11363           if (TARGET_THUMB)
11364             {
11365               rtx op4 = gen_reg_rtx (SImode);
11366               rtx op5 = gen_reg_rtx (SImode);
11367
11368               emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
11369                                                op2, op3, op4, op5));
11370             }
11371           else
11372             {
11373               emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
11374                                              op2, op3));
11375             }
11376
11377           DONE;
11378         }
11379       else
11380         FAIL;
11381     }
11382   "
11383 )
11384
11385 ;; Load the FPA co-processor patterns
11386 (include "fpa.md")
11387 ;; Load the Maverick co-processor patterns
11388 (include "cirrus.md")
11389 ;; Vector bits common to IWMMXT and Neon
11390 (include "vec-common.md")
11391 ;; Load the Intel Wireless Multimedia Extension patterns
11392 (include "iwmmxt.md")
11393 ;; Load the VFP co-processor patterns
11394 (include "vfp.md")
11395 ;; Thumb-2 patterns
11396 (include "thumb2.md")
11397 ;; Neon patterns
11398 (include "neon.md")
11399