OSDN Git Service

* config/arm/arm.md (Thumb-1 ldrsb peephole): New.
[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 (define_insn_and_split "*thumb1_addsi3"
641   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*rk,*hk,l,k,l,l")
642         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,k,k,0,l")
643                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,M,O,Pa,Pb")))]
644   "TARGET_THUMB1"
645   "*
646    static const char * const asms[] = 
647    {
648      \"add\\t%0, %0, %2\",
649      \"sub\\t%0, %0, #%n2\",
650      \"add\\t%0, %1, %2\",
651      \"add\\t%0, %0, %2\",
652      \"add\\t%0, %0, %2\",
653      \"add\\t%0, %1, %2\",
654      \"add\\t%0, %1, %2\",
655      \"#\",
656      \"#\"
657    };
658    if ((which_alternative == 2 || which_alternative == 6)
659        && GET_CODE (operands[2]) == CONST_INT
660        && INTVAL (operands[2]) < 0)
661      return \"sub\\t%0, %1, #%n2\";
662    return asms[which_alternative];
663   "
664   "&& reload_completed && CONST_INT_P (operands[2])
665    && operands[1] != stack_pointer_rtx
666    && (INTVAL (operands[2]) > 255 || INTVAL (operands[2]) < -255)"
667   [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
668    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
669   {
670     HOST_WIDE_INT offset = INTVAL (operands[2]);
671     if (offset > 255)
672       offset = 255;
673     else if (offset < -255)
674       offset = -255;
675     
676     operands[3] = GEN_INT (offset);
677     operands[2] = GEN_INT (INTVAL (operands[2]) - offset);
678   }
679   [(set_attr "length" "2,2,2,2,2,2,2,4,4")]
680 )
681
682 ;; Reloading and elimination of the frame pointer can
683 ;; sometimes cause this optimization to be missed.
684 (define_peephole2
685   [(set (match_operand:SI 0 "arm_general_register_operand" "")
686         (match_operand:SI 1 "const_int_operand" ""))
687    (set (match_dup 0)
688         (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
689   "TARGET_THUMB1
690    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
691    && (INTVAL (operands[1]) & 3) == 0"
692   [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
693   ""
694 )
695
696 (define_insn "*addsi3_compare0"
697   [(set (reg:CC_NOOV CC_REGNUM)
698         (compare:CC_NOOV
699          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
700                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
701          (const_int 0)))
702    (set (match_operand:SI 0 "s_register_operand" "=r,r")
703         (plus:SI (match_dup 1) (match_dup 2)))]
704   "TARGET_ARM"
705   "@
706    add%.\\t%0, %1, %2
707    sub%.\\t%0, %1, #%n2"
708   [(set_attr "conds" "set")]
709 )
710
711 (define_insn "*addsi3_compare0_scratch"
712   [(set (reg:CC_NOOV CC_REGNUM)
713         (compare:CC_NOOV
714          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
715                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
716          (const_int 0)))]
717   "TARGET_ARM"
718   "@
719    cmn%?\\t%0, %1
720    cmp%?\\t%0, #%n1"
721   [(set_attr "conds" "set")]
722 )
723
724 (define_insn "*compare_negsi_si"
725   [(set (reg:CC_Z CC_REGNUM)
726         (compare:CC_Z
727          (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
728          (match_operand:SI 1 "s_register_operand" "r")))]
729   "TARGET_32BIT"
730   "cmn%?\\t%1, %0"
731   [(set_attr "conds" "set")]
732 )
733
734 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
735 ;; addend is a constant.
736 (define_insn "*cmpsi2_addneg"
737   [(set (reg:CC CC_REGNUM)
738         (compare:CC
739          (match_operand:SI 1 "s_register_operand" "r,r")
740          (match_operand:SI 2 "arm_addimm_operand" "L,I")))
741    (set (match_operand:SI 0 "s_register_operand" "=r,r")
742         (plus:SI (match_dup 1)
743                  (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
744   "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
745   "@
746    add%.\\t%0, %1, %3
747    sub%.\\t%0, %1, #%n3"
748   [(set_attr "conds" "set")]
749 )
750
751 ;; Convert the sequence
752 ;;  sub  rd, rn, #1
753 ;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
754 ;;  bne  dest
755 ;; into
756 ;;  subs rd, rn, #1
757 ;;  bcs  dest   ((unsigned)rn >= 1)
758 ;; similarly for the beq variant using bcc.
759 ;; This is a common looping idiom (while (n--))
760 (define_peephole2
761   [(set (match_operand:SI 0 "arm_general_register_operand" "")
762         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
763                  (const_int -1)))
764    (set (match_operand 2 "cc_register" "")
765         (compare (match_dup 0) (const_int -1)))
766    (set (pc)
767         (if_then_else (match_operator 3 "equality_operator"
768                        [(match_dup 2) (const_int 0)])
769                       (match_operand 4 "" "")
770                       (match_operand 5 "" "")))]
771   "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
772   [(parallel[
773     (set (match_dup 2)
774          (compare:CC
775           (match_dup 1) (const_int 1)))
776     (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
777    (set (pc)
778         (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
779                       (match_dup 4)
780                       (match_dup 5)))]
781   "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
782    operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
783                                   ? GEU : LTU),
784                                  VOIDmode, 
785                                  operands[2], const0_rtx);"
786 )
787
788 ;; The next four insns work because they compare the result with one of
789 ;; the operands, and we know that the use of the condition code is
790 ;; either GEU or LTU, so we can use the carry flag from the addition
791 ;; instead of doing the compare a second time.
792 (define_insn "*addsi3_compare_op1"
793   [(set (reg:CC_C CC_REGNUM)
794         (compare:CC_C
795          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
796                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
797          (match_dup 1)))
798    (set (match_operand:SI 0 "s_register_operand" "=r,r")
799         (plus:SI (match_dup 1) (match_dup 2)))]
800   "TARGET_32BIT"
801   "@
802    add%.\\t%0, %1, %2
803    sub%.\\t%0, %1, #%n2"
804   [(set_attr "conds" "set")]
805 )
806
807 (define_insn "*addsi3_compare_op2"
808   [(set (reg:CC_C CC_REGNUM)
809         (compare:CC_C
810          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
811                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
812          (match_dup 2)))
813    (set (match_operand:SI 0 "s_register_operand" "=r,r")
814         (plus:SI (match_dup 1) (match_dup 2)))]
815   "TARGET_32BIT"
816   "@
817    add%.\\t%0, %1, %2
818    sub%.\\t%0, %1, #%n2"
819   [(set_attr "conds" "set")]
820 )
821
822 (define_insn "*compare_addsi2_op0"
823   [(set (reg:CC_C CC_REGNUM)
824         (compare:CC_C
825          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
826                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
827          (match_dup 0)))]
828   "TARGET_32BIT"
829   "@
830    cmn%?\\t%0, %1
831    cmp%?\\t%0, #%n1"
832   [(set_attr "conds" "set")]
833 )
834
835 (define_insn "*compare_addsi2_op1"
836   [(set (reg:CC_C CC_REGNUM)
837         (compare:CC_C
838          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
839                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
840          (match_dup 1)))]
841   "TARGET_32BIT"
842   "@
843    cmn%?\\t%0, %1
844    cmp%?\\t%0, #%n1"
845   [(set_attr "conds" "set")]
846 )
847
848 (define_code_iterator LTUGEU [ltu geu])
849 (define_code_attr cnb [(ltu "CC_C") (geu "CC")])
850 (define_code_attr optab [(ltu "ltu") (geu "geu")])
851
852 (define_insn "*addsi3_carryin_<optab>"
853   [(set (match_operand:SI 0 "s_register_operand" "=r")
854         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
855                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
856                  (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
857   "TARGET_32BIT"
858   "adc%?\\t%0, %1, %2"
859   [(set_attr "conds" "use")]
860 )
861
862 (define_insn "*addsi3_carryin_alt2_<optab>"
863   [(set (match_operand:SI 0 "s_register_operand" "=r")
864         (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
865                           (match_operand:SI 1 "s_register_operand" "%r"))
866                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
867   "TARGET_32BIT"
868   "adc%?\\t%0, %1, %2"
869   [(set_attr "conds" "use")]
870 )
871
872 (define_insn "*addsi3_carryin_shift_<optab>"
873   [(set (match_operand:SI 0 "s_register_operand" "=r")
874         (plus:SI (plus:SI
875                   (match_operator:SI 2 "shift_operator"
876                     [(match_operand:SI 3 "s_register_operand" "r")
877                      (match_operand:SI 4 "reg_or_int_operand" "rM")])
878                   (match_operand:SI 1 "s_register_operand" "r"))
879                  (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
880   "TARGET_32BIT"
881   "adc%?\\t%0, %1, %3%S2"
882   [(set_attr "conds" "use")
883    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
884                       (const_string "alu_shift")
885                       (const_string "alu_shift_reg")))]
886 )
887
888 (define_expand "incscc"
889   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
890         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
891                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
892                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
893   "TARGET_32BIT"
894   ""
895 )
896
897 (define_insn "*arm_incscc"
898   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
899         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
900                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
901                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
902   "TARGET_ARM"
903   "@
904   add%d2\\t%0, %1, #1
905   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
906   [(set_attr "conds" "use")
907    (set_attr "length" "4,8")]
908 )
909
910 ; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
911 (define_split
912   [(set (match_operand:SI 0 "s_register_operand" "")
913         (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
914                             (match_operand:SI 2 "s_register_operand" ""))
915                  (const_int -1)))
916    (clobber (match_operand:SI 3 "s_register_operand" ""))]
917   "TARGET_32BIT"
918   [(set (match_dup 3) (match_dup 1))
919    (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
920   "
921   operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
922 ")
923
924 (define_expand "addsf3"
925   [(set (match_operand:SF          0 "s_register_operand" "")
926         (plus:SF (match_operand:SF 1 "s_register_operand" "")
927                  (match_operand:SF 2 "arm_float_add_operand" "")))]
928   "TARGET_32BIT && TARGET_HARD_FLOAT"
929   "
930   if (TARGET_MAVERICK
931       && !cirrus_fp_register (operands[2], SFmode))
932     operands[2] = force_reg (SFmode, operands[2]);
933 ")
934
935 (define_expand "adddf3"
936   [(set (match_operand:DF          0 "s_register_operand" "")
937         (plus:DF (match_operand:DF 1 "s_register_operand" "")
938                  (match_operand:DF 2 "arm_float_add_operand" "")))]
939   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
940   "
941   if (TARGET_MAVERICK
942       && !cirrus_fp_register (operands[2], DFmode))
943     operands[2] = force_reg (DFmode, operands[2]);
944 ")
945
946 (define_expand "subdi3"
947  [(parallel
948    [(set (match_operand:DI            0 "s_register_operand" "")
949           (minus:DI (match_operand:DI 1 "s_register_operand" "")
950                     (match_operand:DI 2 "s_register_operand" "")))
951     (clobber (reg:CC CC_REGNUM))])]
952   "TARGET_EITHER"
953   "
954   if (TARGET_HARD_FLOAT && TARGET_MAVERICK
955       && TARGET_32BIT
956       && cirrus_fp_register (operands[0], DImode)
957       && cirrus_fp_register (operands[1], DImode))
958     {
959       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
960       DONE;
961     }
962
963   if (TARGET_THUMB1)
964     {
965       if (GET_CODE (operands[1]) != REG)
966         operands[1] = force_reg (DImode, operands[1]);
967       if (GET_CODE (operands[2]) != REG)
968         operands[2] = force_reg (DImode, operands[2]);
969      }  
970   "
971 )
972
973 (define_insn "*arm_subdi3"
974   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
975         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
976                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
977    (clobber (reg:CC CC_REGNUM))]
978   "TARGET_32BIT && !TARGET_NEON"
979   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
980   [(set_attr "conds" "clob")
981    (set_attr "length" "8")]
982 )
983
984 (define_insn "*thumb_subdi3"
985   [(set (match_operand:DI           0 "register_operand" "=l")
986         (minus:DI (match_operand:DI 1 "register_operand"  "0")
987                   (match_operand:DI 2 "register_operand"  "l")))
988    (clobber (reg:CC CC_REGNUM))]
989   "TARGET_THUMB1"
990   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
991   [(set_attr "length" "4")]
992 )
993
994 (define_insn "*subdi_di_zesidi"
995   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
996         (minus:DI (match_operand:DI 1 "s_register_operand"  "0,r")
997                   (zero_extend:DI
998                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
999    (clobber (reg:CC CC_REGNUM))]
1000   "TARGET_32BIT"
1001   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
1002   [(set_attr "conds" "clob")
1003    (set_attr "length" "8")]
1004 )
1005
1006 (define_insn "*subdi_di_sesidi"
1007   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
1008         (minus:DI (match_operand:DI  1 "s_register_operand"  "0,r")
1009                   (sign_extend:DI
1010                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
1011    (clobber (reg:CC CC_REGNUM))]
1012   "TARGET_32BIT"
1013   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
1014   [(set_attr "conds" "clob")
1015    (set_attr "length" "8")]
1016 )
1017
1018 (define_insn "*subdi_zesidi_di"
1019   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
1020         (minus:DI (zero_extend:DI
1021                    (match_operand:SI 2 "s_register_operand"  "r,r"))
1022                   (match_operand:DI  1 "s_register_operand" "0,r")))
1023    (clobber (reg:CC CC_REGNUM))]
1024   "TARGET_ARM"
1025   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
1026   [(set_attr "conds" "clob")
1027    (set_attr "length" "8")]
1028 )
1029
1030 (define_insn "*subdi_sesidi_di"
1031   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
1032         (minus:DI (sign_extend:DI
1033                    (match_operand:SI 2 "s_register_operand"   "r,r"))
1034                   (match_operand:DI  1 "s_register_operand"  "0,r")))
1035    (clobber (reg:CC CC_REGNUM))]
1036   "TARGET_ARM"
1037   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
1038   [(set_attr "conds" "clob")
1039    (set_attr "length" "8")]
1040 )
1041
1042 (define_insn "*subdi_zesidi_zesidi"
1043   [(set (match_operand:DI            0 "s_register_operand" "=r")
1044         (minus:DI (zero_extend:DI
1045                    (match_operand:SI 1 "s_register_operand"  "r"))
1046                   (zero_extend:DI
1047                    (match_operand:SI 2 "s_register_operand"  "r"))))
1048    (clobber (reg:CC CC_REGNUM))]
1049   "TARGET_32BIT"
1050   "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
1051   [(set_attr "conds" "clob")
1052    (set_attr "length" "8")]
1053 )
1054
1055 (define_expand "subsi3"
1056   [(set (match_operand:SI           0 "s_register_operand" "")
1057         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1058                   (match_operand:SI 2 "s_register_operand" "")))]
1059   "TARGET_EITHER"
1060   "
1061   if (GET_CODE (operands[1]) == CONST_INT)
1062     {
1063       if (TARGET_32BIT)
1064         {
1065           arm_split_constant (MINUS, SImode, NULL_RTX,
1066                               INTVAL (operands[1]), operands[0],
1067                               operands[2], optimize && can_create_pseudo_p ());
1068           DONE;
1069         }
1070       else /* TARGET_THUMB1 */
1071         operands[1] = force_reg (SImode, operands[1]);
1072     }
1073   "
1074 )
1075
1076 (define_insn "*thumb1_subsi3_insn"
1077   [(set (match_operand:SI           0 "register_operand" "=l")
1078         (minus:SI (match_operand:SI 1 "register_operand" "l")
1079                   (match_operand:SI 2 "register_operand" "l")))]
1080   "TARGET_THUMB1"
1081   "sub\\t%0, %1, %2"
1082   [(set_attr "length" "2")]
1083 )
1084
1085 ; ??? Check Thumb-2 split length
1086 (define_insn_and_split "*arm_subsi3_insn"
1087   [(set (match_operand:SI           0 "s_register_operand" "=r,r,rk,r,r")
1088         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,r,k,?n,r")
1089                   (match_operand:SI 2 "reg_or_int_operand" "r,rI,r, r,?n")))]
1090   "TARGET_32BIT"
1091   "@
1092    rsb%?\\t%0, %2, %1
1093    sub%?\\t%0, %1, %2
1094    sub%?\\t%0, %1, %2
1095    #
1096    #"
1097   "&& ((GET_CODE (operands[1]) == CONST_INT
1098         && !const_ok_for_arm (INTVAL (operands[1])))
1099        || (GET_CODE (operands[2]) == CONST_INT
1100            && !const_ok_for_arm (INTVAL (operands[2]))))"
1101   [(clobber (const_int 0))]
1102   "
1103   arm_split_constant (MINUS, SImode, curr_insn,
1104                       INTVAL (operands[1]), operands[0], operands[2], 0);
1105   DONE;
1106   "
1107   [(set_attr "length" "4,4,4,16,16")
1108    (set_attr "predicable" "yes")]
1109 )
1110
1111 (define_peephole2
1112   [(match_scratch:SI 3 "r")
1113    (set (match_operand:SI 0 "arm_general_register_operand" "")
1114         (minus:SI (match_operand:SI 1 "const_int_operand" "")
1115                   (match_operand:SI 2 "arm_general_register_operand" "")))]
1116   "TARGET_32BIT
1117    && !const_ok_for_arm (INTVAL (operands[1]))
1118    && const_ok_for_arm (~INTVAL (operands[1]))"
1119   [(set (match_dup 3) (match_dup 1))
1120    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1121   ""
1122 )
1123
1124 (define_insn "*subsi3_compare0"
1125   [(set (reg:CC_NOOV CC_REGNUM)
1126         (compare:CC_NOOV
1127          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1128                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1129          (const_int 0)))
1130    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1131         (minus:SI (match_dup 1) (match_dup 2)))]
1132   "TARGET_32BIT"
1133   "@
1134    sub%.\\t%0, %1, %2
1135    rsb%.\\t%0, %2, %1"
1136   [(set_attr "conds" "set")]
1137 )
1138
1139 (define_insn "*subsi3_compare"
1140   [(set (reg:CC CC_REGNUM)
1141         (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,I")
1142                     (match_operand:SI 2 "arm_rhs_operand" "rI,r")))
1143    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1144         (minus:SI (match_dup 1) (match_dup 2)))]
1145   "TARGET_32BIT"
1146   "@
1147    sub%.\\t%0, %1, %2
1148    rsb%.\\t%0, %2, %1"
1149   [(set_attr "conds" "set")]
1150 )
1151
1152 (define_expand "decscc"
1153   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1154         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1155                   (match_operator:SI 2 "arm_comparison_operator"
1156                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1157   "TARGET_32BIT"
1158   ""
1159 )
1160
1161 (define_insn "*arm_decscc"
1162   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1163         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1164                   (match_operator:SI 2 "arm_comparison_operator"
1165                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1166   "TARGET_ARM"
1167   "@
1168    sub%d2\\t%0, %1, #1
1169    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1170   [(set_attr "conds" "use")
1171    (set_attr "length" "*,8")]
1172 )
1173
1174 (define_expand "subsf3"
1175   [(set (match_operand:SF           0 "s_register_operand" "")
1176         (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1177                   (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1178   "TARGET_32BIT && TARGET_HARD_FLOAT"
1179   "
1180   if (TARGET_MAVERICK)
1181     {
1182       if (!cirrus_fp_register (operands[1], SFmode))
1183         operands[1] = force_reg (SFmode, operands[1]);
1184       if (!cirrus_fp_register (operands[2], SFmode))
1185         operands[2] = force_reg (SFmode, operands[2]);
1186     }
1187 ")
1188
1189 (define_expand "subdf3"
1190   [(set (match_operand:DF           0 "s_register_operand" "")
1191         (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1192                   (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1193   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
1194   "
1195   if (TARGET_MAVERICK)
1196     {
1197        if (!cirrus_fp_register (operands[1], DFmode))
1198          operands[1] = force_reg (DFmode, operands[1]);
1199        if (!cirrus_fp_register (operands[2], DFmode))
1200          operands[2] = force_reg (DFmode, operands[2]);
1201     }
1202 ")
1203
1204 \f
1205 ;; Multiplication insns
1206
1207 (define_expand "mulsi3"
1208   [(set (match_operand:SI          0 "s_register_operand" "")
1209         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1210                  (match_operand:SI 1 "s_register_operand" "")))]
1211   "TARGET_EITHER"
1212   ""
1213 )
1214
1215 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1216 (define_insn "*arm_mulsi3"
1217   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1218         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1219                  (match_operand:SI 1 "s_register_operand" "%0,r")))]
1220   "TARGET_32BIT && !arm_arch6"
1221   "mul%?\\t%0, %2, %1"
1222   [(set_attr "insn" "mul")
1223    (set_attr "predicable" "yes")]
1224 )
1225
1226 (define_insn "*arm_mulsi3_v6"
1227   [(set (match_operand:SI          0 "s_register_operand" "=r")
1228         (mult:SI (match_operand:SI 1 "s_register_operand" "r")
1229                  (match_operand:SI 2 "s_register_operand" "r")))]
1230   "TARGET_32BIT && arm_arch6"
1231   "mul%?\\t%0, %1, %2"
1232   [(set_attr "insn" "mul")
1233    (set_attr "predicable" "yes")]
1234 )
1235
1236 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1237 ; 1 and 2; are the same, because reload will make operand 0 match 
1238 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1239 ; this by adding another alternative to match this case, and then `reload' 
1240 ; it ourselves.  This alternative must come first.
1241 (define_insn "*thumb_mulsi3"
1242   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1243         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1244                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1245   "TARGET_THUMB1 && !arm_arch6"
1246   "*
1247   if (which_alternative < 2)
1248     return \"mov\\t%0, %1\;mul\\t%0, %2\";
1249   else
1250     return \"mul\\t%0, %2\";
1251   "
1252   [(set_attr "length" "4,4,2")
1253    (set_attr "insn" "mul")]
1254 )
1255
1256 (define_insn "*thumb_mulsi3_v6"
1257   [(set (match_operand:SI          0 "register_operand" "=l,l,l")
1258         (mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
1259                  (match_operand:SI 2 "register_operand" "l,0,0")))]
1260   "TARGET_THUMB1 && arm_arch6"
1261   "@
1262    mul\\t%0, %2
1263    mul\\t%0, %1
1264    mul\\t%0, %1"
1265   [(set_attr "length" "2")
1266    (set_attr "insn" "mul")]
1267 )
1268
1269 (define_insn "*mulsi3_compare0"
1270   [(set (reg:CC_NOOV CC_REGNUM)
1271         (compare:CC_NOOV (mult:SI
1272                           (match_operand:SI 2 "s_register_operand" "r,r")
1273                           (match_operand:SI 1 "s_register_operand" "%0,r"))
1274                          (const_int 0)))
1275    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1276         (mult:SI (match_dup 2) (match_dup 1)))]
1277   "TARGET_ARM && !arm_arch6"
1278   "mul%.\\t%0, %2, %1"
1279   [(set_attr "conds" "set")
1280    (set_attr "insn" "muls")]
1281 )
1282
1283 (define_insn "*mulsi3_compare0_v6"
1284   [(set (reg:CC_NOOV CC_REGNUM)
1285         (compare:CC_NOOV (mult:SI
1286                           (match_operand:SI 2 "s_register_operand" "r")
1287                           (match_operand:SI 1 "s_register_operand" "r"))
1288                          (const_int 0)))
1289    (set (match_operand:SI 0 "s_register_operand" "=r")
1290         (mult:SI (match_dup 2) (match_dup 1)))]
1291   "TARGET_ARM && arm_arch6 && optimize_size"
1292   "mul%.\\t%0, %2, %1"
1293   [(set_attr "conds" "set")
1294    (set_attr "insn" "muls")]
1295 )
1296
1297 (define_insn "*mulsi_compare0_scratch"
1298   [(set (reg:CC_NOOV CC_REGNUM)
1299         (compare:CC_NOOV (mult:SI
1300                           (match_operand:SI 2 "s_register_operand" "r,r")
1301                           (match_operand:SI 1 "s_register_operand" "%0,r"))
1302                          (const_int 0)))
1303    (clobber (match_scratch:SI 0 "=&r,&r"))]
1304   "TARGET_ARM && !arm_arch6"
1305   "mul%.\\t%0, %2, %1"
1306   [(set_attr "conds" "set")
1307    (set_attr "insn" "muls")]
1308 )
1309
1310 (define_insn "*mulsi_compare0_scratch_v6"
1311   [(set (reg:CC_NOOV CC_REGNUM)
1312         (compare:CC_NOOV (mult:SI
1313                           (match_operand:SI 2 "s_register_operand" "r")
1314                           (match_operand:SI 1 "s_register_operand" "r"))
1315                          (const_int 0)))
1316    (clobber (match_scratch:SI 0 "=r"))]
1317   "TARGET_ARM && arm_arch6 && optimize_size"
1318   "mul%.\\t%0, %2, %1"
1319   [(set_attr "conds" "set")
1320    (set_attr "insn" "muls")]
1321 )
1322
1323 ;; Unnamed templates to match MLA instruction.
1324
1325 (define_insn "*mulsi3addsi"
1326   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1327         (plus:SI
1328           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1329                    (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1330           (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
1331   "TARGET_32BIT && !arm_arch6"
1332   "mla%?\\t%0, %2, %1, %3"
1333   [(set_attr "insn" "mla")
1334    (set_attr "predicable" "yes")]
1335 )
1336
1337 (define_insn "*mulsi3addsi_v6"
1338   [(set (match_operand:SI 0 "s_register_operand" "=r")
1339         (plus:SI
1340           (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1341                    (match_operand:SI 1 "s_register_operand" "r"))
1342           (match_operand:SI 3 "s_register_operand" "r")))]
1343   "TARGET_32BIT && arm_arch6"
1344   "mla%?\\t%0, %2, %1, %3"
1345   [(set_attr "insn" "mla")
1346    (set_attr "predicable" "yes")]
1347 )
1348
1349 (define_insn "*mulsi3addsi_compare0"
1350   [(set (reg:CC_NOOV CC_REGNUM)
1351         (compare:CC_NOOV
1352          (plus:SI (mult:SI
1353                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1354                    (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1355                   (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
1356          (const_int 0)))
1357    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1358         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1359                  (match_dup 3)))]
1360   "TARGET_ARM && arm_arch6"
1361   "mla%.\\t%0, %2, %1, %3"
1362   [(set_attr "conds" "set")
1363    (set_attr "insn" "mlas")]
1364 )
1365
1366 (define_insn "*mulsi3addsi_compare0_v6"
1367   [(set (reg:CC_NOOV CC_REGNUM)
1368         (compare:CC_NOOV
1369          (plus:SI (mult:SI
1370                    (match_operand:SI 2 "s_register_operand" "r")
1371                    (match_operand:SI 1 "s_register_operand" "r"))
1372                   (match_operand:SI 3 "s_register_operand" "r"))
1373          (const_int 0)))
1374    (set (match_operand:SI 0 "s_register_operand" "=r")
1375         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1376                  (match_dup 3)))]
1377   "TARGET_ARM && arm_arch6 && optimize_size"
1378   "mla%.\\t%0, %2, %1, %3"
1379   [(set_attr "conds" "set")
1380    (set_attr "insn" "mlas")]
1381 )
1382
1383 (define_insn "*mulsi3addsi_compare0_scratch"
1384   [(set (reg:CC_NOOV CC_REGNUM)
1385         (compare:CC_NOOV
1386          (plus:SI (mult:SI
1387                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1388                    (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1389                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1390          (const_int 0)))
1391    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1392   "TARGET_ARM && !arm_arch6"
1393   "mla%.\\t%0, %2, %1, %3"
1394   [(set_attr "conds" "set")
1395    (set_attr "insn" "mlas")]
1396 )
1397
1398 (define_insn "*mulsi3addsi_compare0_scratch_v6"
1399   [(set (reg:CC_NOOV CC_REGNUM)
1400         (compare:CC_NOOV
1401          (plus:SI (mult:SI
1402                    (match_operand:SI 2 "s_register_operand" "r")
1403                    (match_operand:SI 1 "s_register_operand" "r"))
1404                   (match_operand:SI 3 "s_register_operand" "r"))
1405          (const_int 0)))
1406    (clobber (match_scratch:SI 0 "=r"))]
1407   "TARGET_ARM && arm_arch6 && optimize_size"
1408   "mla%.\\t%0, %2, %1, %3"
1409   [(set_attr "conds" "set")
1410    (set_attr "insn" "mlas")]
1411 )
1412
1413 (define_insn "*mulsi3subsi"
1414   [(set (match_operand:SI 0 "s_register_operand" "=r")
1415         (minus:SI
1416           (match_operand:SI 3 "s_register_operand" "r")
1417           (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1418                    (match_operand:SI 1 "s_register_operand" "r"))))]
1419   "TARGET_32BIT && arm_arch_thumb2"
1420   "mls%?\\t%0, %2, %1, %3"
1421   [(set_attr "insn" "mla")
1422    (set_attr "predicable" "yes")]
1423 )
1424
1425 (define_expand "maddsidi4"
1426   [(set (match_operand:DI 0 "s_register_operand" "")
1427         (plus:DI
1428          (mult:DI
1429           (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1430           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1431          (match_operand:DI 3 "s_register_operand" "")))]
1432   "TARGET_32BIT && arm_arch3m"
1433   "")
1434
1435 (define_insn "*mulsidi3adddi"
1436   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1437         (plus:DI
1438          (mult:DI
1439           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1440           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1441          (match_operand:DI 1 "s_register_operand" "0")))]
1442   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1443   "smlal%?\\t%Q0, %R0, %3, %2"
1444   [(set_attr "insn" "smlal")
1445    (set_attr "predicable" "yes")]
1446 )
1447
1448 (define_insn "*mulsidi3adddi_v6"
1449   [(set (match_operand:DI 0 "s_register_operand" "=r")
1450         (plus:DI
1451          (mult:DI
1452           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1453           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1454          (match_operand:DI 1 "s_register_operand" "0")))]
1455   "TARGET_32BIT && arm_arch6"
1456   "smlal%?\\t%Q0, %R0, %3, %2"
1457   [(set_attr "insn" "smlal")
1458    (set_attr "predicable" "yes")]
1459 )
1460
1461 ;; 32x32->64 widening multiply.
1462 ;; As with mulsi3, the only difference between the v3-5 and v6+
1463 ;; versions of these patterns is the requirement that the output not
1464 ;; overlap the inputs, but that still means we have to have a named
1465 ;; expander and two different starred insns.
1466
1467 (define_expand "mulsidi3"
1468   [(set (match_operand:DI 0 "s_register_operand" "")
1469         (mult:DI
1470          (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1471          (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1472   "TARGET_32BIT && arm_arch3m"
1473   ""
1474 )
1475
1476 (define_insn "*mulsidi3_nov6"
1477   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1478         (mult:DI
1479          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1480          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1481   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1482   "smull%?\\t%Q0, %R0, %1, %2"
1483   [(set_attr "insn" "smull")
1484    (set_attr "predicable" "yes")]
1485 )
1486
1487 (define_insn "*mulsidi3_v6"
1488   [(set (match_operand:DI 0 "s_register_operand" "=r")
1489         (mult:DI
1490          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1491          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1492   "TARGET_32BIT && arm_arch6"
1493   "smull%?\\t%Q0, %R0, %1, %2"
1494   [(set_attr "insn" "smull")
1495    (set_attr "predicable" "yes")]
1496 )
1497
1498 (define_expand "umulsidi3"
1499   [(set (match_operand:DI 0 "s_register_operand" "")
1500         (mult:DI
1501          (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1502          (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1503   "TARGET_32BIT && arm_arch3m"
1504   ""
1505 )
1506
1507 (define_insn "*umulsidi3_nov6"
1508   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1509         (mult:DI
1510          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1511          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1512   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1513   "umull%?\\t%Q0, %R0, %1, %2"
1514   [(set_attr "insn" "umull")
1515    (set_attr "predicable" "yes")]
1516 )
1517
1518 (define_insn "*umulsidi3_v6"
1519   [(set (match_operand:DI 0 "s_register_operand" "=r")
1520         (mult:DI
1521          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1522          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1523   "TARGET_32BIT && arm_arch6"
1524   "umull%?\\t%Q0, %R0, %1, %2"
1525   [(set_attr "insn" "umull")
1526    (set_attr "predicable" "yes")]
1527 )
1528
1529 (define_expand "umaddsidi4"
1530   [(set (match_operand:DI 0 "s_register_operand" "")
1531         (plus:DI
1532          (mult:DI
1533           (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1534           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1535          (match_operand:DI 3 "s_register_operand" "")))]
1536   "TARGET_32BIT && arm_arch3m"
1537   "")
1538
1539 (define_insn "*umulsidi3adddi"
1540   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1541         (plus:DI
1542          (mult:DI
1543           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1544           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1545          (match_operand:DI 1 "s_register_operand" "0")))]
1546   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1547   "umlal%?\\t%Q0, %R0, %3, %2"
1548   [(set_attr "insn" "umlal")
1549    (set_attr "predicable" "yes")]
1550 )
1551
1552 (define_insn "*umulsidi3adddi_v6"
1553   [(set (match_operand:DI 0 "s_register_operand" "=r")
1554         (plus:DI
1555          (mult:DI
1556           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1557           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1558          (match_operand:DI 1 "s_register_operand" "0")))]
1559   "TARGET_32BIT && arm_arch6"
1560   "umlal%?\\t%Q0, %R0, %3, %2"
1561   [(set_attr "insn" "umlal")
1562    (set_attr "predicable" "yes")]
1563 )
1564
1565 (define_expand "smulsi3_highpart"
1566   [(parallel
1567     [(set (match_operand:SI 0 "s_register_operand" "")
1568           (truncate:SI
1569            (lshiftrt:DI
1570             (mult:DI
1571              (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1572              (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1573             (const_int 32))))
1574      (clobber (match_scratch:SI 3 ""))])]
1575   "TARGET_32BIT && arm_arch3m"
1576   ""
1577 )
1578
1579 (define_insn "*smulsi3_highpart_nov6"
1580   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1581         (truncate:SI
1582          (lshiftrt:DI
1583           (mult:DI
1584            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
1585            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1586           (const_int 32))))
1587    (clobber (match_scratch:SI 3 "=&r,&r"))]
1588   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1589   "smull%?\\t%3, %0, %2, %1"
1590   [(set_attr "insn" "smull")
1591    (set_attr "predicable" "yes")]
1592 )
1593
1594 (define_insn "*smulsi3_highpart_v6"
1595   [(set (match_operand:SI 0 "s_register_operand" "=r")
1596         (truncate:SI
1597          (lshiftrt:DI
1598           (mult:DI
1599            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1600            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1601           (const_int 32))))
1602    (clobber (match_scratch:SI 3 "=r"))]
1603   "TARGET_32BIT && arm_arch6"
1604   "smull%?\\t%3, %0, %2, %1"
1605   [(set_attr "insn" "smull")
1606    (set_attr "predicable" "yes")]
1607 )
1608
1609 (define_expand "umulsi3_highpart"
1610   [(parallel
1611     [(set (match_operand:SI 0 "s_register_operand" "")
1612           (truncate:SI
1613            (lshiftrt:DI
1614             (mult:DI
1615              (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1616               (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1617             (const_int 32))))
1618      (clobber (match_scratch:SI 3 ""))])]
1619   "TARGET_32BIT && arm_arch3m"
1620   ""
1621 )
1622
1623 (define_insn "*umulsi3_highpart_nov6"
1624   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1625         (truncate:SI
1626          (lshiftrt:DI
1627           (mult:DI
1628            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
1629            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1630           (const_int 32))))
1631    (clobber (match_scratch:SI 3 "=&r,&r"))]
1632   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1633   "umull%?\\t%3, %0, %2, %1"
1634   [(set_attr "insn" "umull")
1635    (set_attr "predicable" "yes")]
1636 )
1637
1638 (define_insn "*umulsi3_highpart_v6"
1639   [(set (match_operand:SI 0 "s_register_operand" "=r")
1640         (truncate:SI
1641          (lshiftrt:DI
1642           (mult:DI
1643            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1644            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1645           (const_int 32))))
1646    (clobber (match_scratch:SI 3 "=r"))]
1647   "TARGET_32BIT && arm_arch6"
1648   "umull%?\\t%3, %0, %2, %1"
1649   [(set_attr "insn" "umull")
1650    (set_attr "predicable" "yes")]
1651 )
1652
1653 (define_insn "mulhisi3"
1654   [(set (match_operand:SI 0 "s_register_operand" "=r")
1655         (mult:SI (sign_extend:SI
1656                   (match_operand:HI 1 "s_register_operand" "%r"))
1657                  (sign_extend:SI
1658                   (match_operand:HI 2 "s_register_operand" "r"))))]
1659   "TARGET_DSP_MULTIPLY"
1660   "smulbb%?\\t%0, %1, %2"
1661   [(set_attr "insn" "smulxy")
1662    (set_attr "predicable" "yes")]
1663 )
1664
1665 (define_insn "*mulhisi3tb"
1666   [(set (match_operand:SI 0 "s_register_operand" "=r")
1667         (mult:SI (ashiftrt:SI
1668                   (match_operand:SI 1 "s_register_operand" "r")
1669                   (const_int 16))
1670                  (sign_extend:SI
1671                   (match_operand:HI 2 "s_register_operand" "r"))))]
1672   "TARGET_DSP_MULTIPLY"
1673   "smultb%?\\t%0, %1, %2"
1674   [(set_attr "insn" "smulxy")
1675    (set_attr "predicable" "yes")]
1676 )
1677
1678 (define_insn "*mulhisi3bt"
1679   [(set (match_operand:SI 0 "s_register_operand" "=r")
1680         (mult:SI (sign_extend:SI
1681                   (match_operand:HI 1 "s_register_operand" "r"))
1682                  (ashiftrt:SI
1683                   (match_operand:SI 2 "s_register_operand" "r")
1684                   (const_int 16))))]
1685   "TARGET_DSP_MULTIPLY"
1686   "smulbt%?\\t%0, %1, %2"
1687   [(set_attr "insn" "smulxy")
1688    (set_attr "predicable" "yes")]
1689 )
1690
1691 (define_insn "*mulhisi3tt"
1692   [(set (match_operand:SI 0 "s_register_operand" "=r")
1693         (mult:SI (ashiftrt:SI
1694                   (match_operand:SI 1 "s_register_operand" "r")
1695                   (const_int 16))
1696                  (ashiftrt:SI
1697                   (match_operand:SI 2 "s_register_operand" "r")
1698                   (const_int 16))))]
1699   "TARGET_DSP_MULTIPLY"
1700   "smultt%?\\t%0, %1, %2"
1701   [(set_attr "insn" "smulxy")
1702    (set_attr "predicable" "yes")]
1703 )
1704
1705 (define_insn "maddhisi4"
1706   [(set (match_operand:SI 0 "s_register_operand" "=r")
1707         (plus:SI (match_operand:SI 3 "s_register_operand" "r")
1708                  (mult:SI (sign_extend:SI
1709                            (match_operand:HI 1 "s_register_operand" "%r"))
1710                           (sign_extend:SI
1711                            (match_operand:HI 2 "s_register_operand" "r")))))]
1712   "TARGET_DSP_MULTIPLY"
1713   "smlabb%?\\t%0, %1, %2, %3"
1714   [(set_attr "insn" "smlaxy")
1715    (set_attr "predicable" "yes")]
1716 )
1717
1718 (define_insn "*maddhidi4"
1719   [(set (match_operand:DI 0 "s_register_operand" "=r")
1720         (plus:DI
1721           (match_operand:DI 3 "s_register_operand" "0")
1722           (mult:DI (sign_extend:DI
1723                     (match_operand:HI 1 "s_register_operand" "%r"))
1724                    (sign_extend:DI
1725                     (match_operand:HI 2 "s_register_operand" "r")))))]
1726   "TARGET_DSP_MULTIPLY"
1727   "smlalbb%?\\t%Q0, %R0, %1, %2"
1728   [(set_attr "insn" "smlalxy")
1729    (set_attr "predicable" "yes")])
1730
1731 (define_expand "mulsf3"
1732   [(set (match_operand:SF          0 "s_register_operand" "")
1733         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1734                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1735   "TARGET_32BIT && TARGET_HARD_FLOAT"
1736   "
1737   if (TARGET_MAVERICK
1738       && !cirrus_fp_register (operands[2], SFmode))
1739     operands[2] = force_reg (SFmode, operands[2]);
1740 ")
1741
1742 (define_expand "muldf3"
1743   [(set (match_operand:DF          0 "s_register_operand" "")
1744         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1745                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1746   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
1747   "
1748   if (TARGET_MAVERICK
1749       && !cirrus_fp_register (operands[2], DFmode))
1750     operands[2] = force_reg (DFmode, operands[2]);
1751 ")
1752 \f
1753 ;; Division insns
1754
1755 (define_expand "divsf3"
1756   [(set (match_operand:SF 0 "s_register_operand" "")
1757         (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1758                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1759   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1760   "")
1761
1762 (define_expand "divdf3"
1763   [(set (match_operand:DF 0 "s_register_operand" "")
1764         (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1765                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1766   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
1767   "")
1768 \f
1769 ;; Modulo insns
1770
1771 (define_expand "modsf3"
1772   [(set (match_operand:SF 0 "s_register_operand" "")
1773         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1774                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1775   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
1776   "")
1777
1778 (define_expand "moddf3"
1779   [(set (match_operand:DF 0 "s_register_operand" "")
1780         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1781                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1782   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
1783   "")
1784 \f
1785 ;; Boolean and,ior,xor insns
1786
1787 ;; Split up double word logical operations
1788
1789 ;; Split up simple DImode logical operations.  Simply perform the logical
1790 ;; operation on the upper and lower halves of the registers.
1791 (define_split
1792   [(set (match_operand:DI 0 "s_register_operand" "")
1793         (match_operator:DI 6 "logical_binary_operator"
1794           [(match_operand:DI 1 "s_register_operand" "")
1795            (match_operand:DI 2 "s_register_operand" "")]))]
1796   "TARGET_32BIT && reload_completed
1797    && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
1798    && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1799   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1800    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1801   "
1802   {
1803     operands[3] = gen_highpart (SImode, operands[0]);
1804     operands[0] = gen_lowpart (SImode, operands[0]);
1805     operands[4] = gen_highpart (SImode, operands[1]);
1806     operands[1] = gen_lowpart (SImode, operands[1]);
1807     operands[5] = gen_highpart (SImode, operands[2]);
1808     operands[2] = gen_lowpart (SImode, operands[2]);
1809   }"
1810 )
1811
1812 (define_split
1813   [(set (match_operand:DI 0 "s_register_operand" "")
1814         (match_operator:DI 6 "logical_binary_operator"
1815           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1816            (match_operand:DI 1 "s_register_operand" "")]))]
1817   "TARGET_32BIT && reload_completed"
1818   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1819    (set (match_dup 3) (match_op_dup:SI 6
1820                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1821                          (match_dup 4)]))]
1822   "
1823   {
1824     operands[3] = gen_highpart (SImode, operands[0]);
1825     operands[0] = gen_lowpart (SImode, operands[0]);
1826     operands[4] = gen_highpart (SImode, operands[1]);
1827     operands[1] = gen_lowpart (SImode, operands[1]);
1828     operands[5] = gen_highpart (SImode, operands[2]);
1829     operands[2] = gen_lowpart (SImode, operands[2]);
1830   }"
1831 )
1832
1833 ;; The zero extend of operand 2 means we can just copy the high part of
1834 ;; operand1 into operand0.
1835 (define_split
1836   [(set (match_operand:DI 0 "s_register_operand" "")
1837         (ior:DI
1838           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1839           (match_operand:DI 1 "s_register_operand" "")))]
1840   "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
1841   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1842    (set (match_dup 3) (match_dup 4))]
1843   "
1844   {
1845     operands[4] = gen_highpart (SImode, operands[1]);
1846     operands[3] = gen_highpart (SImode, operands[0]);
1847     operands[0] = gen_lowpart (SImode, operands[0]);
1848     operands[1] = gen_lowpart (SImode, operands[1]);
1849   }"
1850 )
1851
1852 ;; The zero extend of operand 2 means we can just copy the high part of
1853 ;; operand1 into operand0.
1854 (define_split
1855   [(set (match_operand:DI 0 "s_register_operand" "")
1856         (xor:DI
1857           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1858           (match_operand:DI 1 "s_register_operand" "")))]
1859   "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
1860   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1861    (set (match_dup 3) (match_dup 4))]
1862   "
1863   {
1864     operands[4] = gen_highpart (SImode, operands[1]);
1865     operands[3] = gen_highpart (SImode, operands[0]);
1866     operands[0] = gen_lowpart (SImode, operands[0]);
1867     operands[1] = gen_lowpart (SImode, operands[1]);
1868   }"
1869 )
1870
1871 (define_expand "anddi3"
1872   [(set (match_operand:DI         0 "s_register_operand" "")
1873         (and:DI (match_operand:DI 1 "s_register_operand" "")
1874                 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
1875   "TARGET_32BIT"
1876   ""
1877 )
1878
1879 (define_insn "*anddi3_insn"
1880   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1881         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1882                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1883   "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
1884   "#"
1885   [(set_attr "length" "8")]
1886 )
1887
1888 (define_insn_and_split "*anddi_zesidi_di"
1889   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1890         (and:DI (zero_extend:DI
1891                  (match_operand:SI 2 "s_register_operand" "r,r"))
1892                 (match_operand:DI 1 "s_register_operand" "0,r")))]
1893   "TARGET_32BIT"
1894   "#"
1895   "TARGET_32BIT && reload_completed"
1896   ; The zero extend of operand 2 clears the high word of the output
1897   ; operand.
1898   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1899    (set (match_dup 3) (const_int 0))]
1900   "
1901   {
1902     operands[3] = gen_highpart (SImode, operands[0]);
1903     operands[0] = gen_lowpart (SImode, operands[0]);
1904     operands[1] = gen_lowpart (SImode, operands[1]);
1905   }"
1906   [(set_attr "length" "8")]
1907 )
1908
1909 (define_insn "*anddi_sesdi_di"
1910   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1911         (and:DI (sign_extend:DI
1912                  (match_operand:SI 2 "s_register_operand" "r,r"))
1913                 (match_operand:DI  1 "s_register_operand" "0,r")))]
1914   "TARGET_32BIT"
1915   "#"
1916   [(set_attr "length" "8")]
1917 )
1918
1919 (define_expand "andsi3"
1920   [(set (match_operand:SI         0 "s_register_operand" "")
1921         (and:SI (match_operand:SI 1 "s_register_operand" "")
1922                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1923   "TARGET_EITHER"
1924   "
1925   if (TARGET_32BIT)
1926     {
1927       if (GET_CODE (operands[2]) == CONST_INT)
1928         {
1929           arm_split_constant (AND, SImode, NULL_RTX,
1930                               INTVAL (operands[2]), operands[0],
1931                               operands[1], optimize && can_create_pseudo_p ());
1932
1933           DONE;
1934         }
1935     }
1936   else /* TARGET_THUMB1 */
1937     {
1938       if (GET_CODE (operands[2]) != CONST_INT)
1939         {
1940           rtx tmp = force_reg (SImode, operands[2]);
1941           if (rtx_equal_p (operands[0], operands[1]))
1942             operands[2] = tmp;
1943           else
1944             {
1945               operands[2] = operands[1];
1946               operands[1] = tmp;
1947             }
1948         }
1949       else
1950         {
1951           int i;
1952           
1953           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1954             {
1955               operands[2] = force_reg (SImode,
1956                                        GEN_INT (~INTVAL (operands[2])));
1957               
1958               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1959               
1960               DONE;
1961             }
1962
1963           for (i = 9; i <= 31; i++)
1964             {
1965               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1966                 {
1967                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1968                                         const0_rtx));
1969                   DONE;
1970                 }
1971               else if ((((HOST_WIDE_INT) 1) << i) - 1
1972                        == ~INTVAL (operands[2]))
1973                 {
1974                   rtx shift = GEN_INT (i);
1975                   rtx reg = gen_reg_rtx (SImode);
1976                 
1977                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1978                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1979                   
1980                   DONE;
1981                 }
1982             }
1983
1984           operands[2] = force_reg (SImode, operands[2]);
1985         }
1986     }
1987   "
1988 )
1989
1990 ; ??? Check split length for Thumb-2
1991 (define_insn_and_split "*arm_andsi3_insn"
1992   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1993         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1994                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1995   "TARGET_32BIT"
1996   "@
1997    and%?\\t%0, %1, %2
1998    bic%?\\t%0, %1, #%B2
1999    #"
2000   "TARGET_32BIT
2001    && GET_CODE (operands[2]) == CONST_INT
2002    && !(const_ok_for_arm (INTVAL (operands[2]))
2003         || const_ok_for_arm (~INTVAL (operands[2])))"
2004   [(clobber (const_int 0))]
2005   "
2006   arm_split_constant  (AND, SImode, curr_insn, 
2007                        INTVAL (operands[2]), operands[0], operands[1], 0);
2008   DONE;
2009   "
2010   [(set_attr "length" "4,4,16")
2011    (set_attr "predicable" "yes")]
2012 )
2013
2014 (define_insn "*thumb1_andsi3_insn"
2015   [(set (match_operand:SI         0 "register_operand" "=l")
2016         (and:SI (match_operand:SI 1 "register_operand" "%0")
2017                 (match_operand:SI 2 "register_operand" "l")))]
2018   "TARGET_THUMB1"
2019   "and\\t%0, %0, %2"
2020   [(set_attr "length" "2")]
2021 )
2022
2023 (define_insn "*andsi3_compare0"
2024   [(set (reg:CC_NOOV CC_REGNUM)
2025         (compare:CC_NOOV
2026          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
2027                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
2028          (const_int 0)))
2029    (set (match_operand:SI          0 "s_register_operand" "=r,r")
2030         (and:SI (match_dup 1) (match_dup 2)))]
2031   "TARGET_32BIT"
2032   "@
2033    and%.\\t%0, %1, %2
2034    bic%.\\t%0, %1, #%B2"
2035   [(set_attr "conds" "set")]
2036 )
2037
2038 (define_insn "*andsi3_compare0_scratch"
2039   [(set (reg:CC_NOOV CC_REGNUM)
2040         (compare:CC_NOOV
2041          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
2042                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
2043          (const_int 0)))
2044    (clobber (match_scratch:SI 2 "=X,r"))]
2045   "TARGET_32BIT"
2046   "@
2047    tst%?\\t%0, %1
2048    bic%.\\t%2, %0, #%B1"
2049   [(set_attr "conds" "set")]
2050 )
2051
2052 (define_insn "*zeroextractsi_compare0_scratch"
2053   [(set (reg:CC_NOOV CC_REGNUM)
2054         (compare:CC_NOOV (zero_extract:SI
2055                           (match_operand:SI 0 "s_register_operand" "r")
2056                           (match_operand 1 "const_int_operand" "n")
2057                           (match_operand 2 "const_int_operand" "n"))
2058                          (const_int 0)))]
2059   "TARGET_32BIT
2060   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2061       && INTVAL (operands[1]) > 0 
2062       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2063       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
2064   "*
2065   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2066                          << INTVAL (operands[2]));
2067   output_asm_insn (\"tst%?\\t%0, %1\", operands);
2068   return \"\";
2069   "
2070   [(set_attr "conds" "set")]
2071 )
2072
2073 (define_insn_and_split "*ne_zeroextractsi"
2074   [(set (match_operand:SI 0 "s_register_operand" "=r")
2075         (ne:SI (zero_extract:SI
2076                 (match_operand:SI 1 "s_register_operand" "r")
2077                 (match_operand:SI 2 "const_int_operand" "n")
2078                 (match_operand:SI 3 "const_int_operand" "n"))
2079                (const_int 0)))
2080    (clobber (reg:CC CC_REGNUM))]
2081   "TARGET_32BIT
2082    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2083        && INTVAL (operands[2]) > 0 
2084        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2085        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2086   "#"
2087   "TARGET_32BIT
2088    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2089        && INTVAL (operands[2]) > 0 
2090        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2091        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2092   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2093                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2094                                     (const_int 0)))
2095               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2096    (set (match_dup 0)
2097         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2098                          (match_dup 0) (const_int 1)))]
2099   "
2100   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2101                          << INTVAL (operands[3])); 
2102   "
2103   [(set_attr "conds" "clob")
2104    (set (attr "length")
2105         (if_then_else (eq_attr "is_thumb" "yes")
2106                       (const_int 12)
2107                       (const_int 8)))]
2108 )
2109
2110 (define_insn_and_split "*ne_zeroextractsi_shifted"
2111   [(set (match_operand:SI 0 "s_register_operand" "=r")
2112         (ne:SI (zero_extract:SI
2113                 (match_operand:SI 1 "s_register_operand" "r")
2114                 (match_operand:SI 2 "const_int_operand" "n")
2115                 (const_int 0))
2116                (const_int 0)))
2117    (clobber (reg:CC CC_REGNUM))]
2118   "TARGET_ARM"
2119   "#"
2120   "TARGET_ARM"
2121   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2122                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2123                                     (const_int 0)))
2124               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2125    (set (match_dup 0)
2126         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2127                          (match_dup 0) (const_int 1)))]
2128   "
2129   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2130   "
2131   [(set_attr "conds" "clob")
2132    (set_attr "length" "8")]
2133 )
2134
2135 (define_insn_and_split "*ite_ne_zeroextractsi"
2136   [(set (match_operand:SI 0 "s_register_operand" "=r")
2137         (if_then_else:SI (ne (zero_extract:SI
2138                               (match_operand:SI 1 "s_register_operand" "r")
2139                               (match_operand:SI 2 "const_int_operand" "n")
2140                               (match_operand:SI 3 "const_int_operand" "n"))
2141                              (const_int 0))
2142                          (match_operand:SI 4 "arm_not_operand" "rIK")
2143                          (const_int 0)))
2144    (clobber (reg:CC CC_REGNUM))]
2145   "TARGET_ARM
2146    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2147        && INTVAL (operands[2]) > 0 
2148        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2149        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2150    && !reg_overlap_mentioned_p (operands[0], operands[4])"
2151   "#"
2152   "TARGET_ARM
2153    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2154        && INTVAL (operands[2]) > 0 
2155        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2156        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2157    && !reg_overlap_mentioned_p (operands[0], operands[4])"
2158   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2159                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2160                                     (const_int 0)))
2161               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2162    (set (match_dup 0)
2163         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2164                          (match_dup 0) (match_dup 4)))]
2165   "
2166   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2167                          << INTVAL (operands[3])); 
2168   "
2169   [(set_attr "conds" "clob")
2170    (set_attr "length" "8")]
2171 )
2172
2173 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2174   [(set (match_operand:SI 0 "s_register_operand" "=r")
2175         (if_then_else:SI (ne (zero_extract:SI
2176                               (match_operand:SI 1 "s_register_operand" "r")
2177                               (match_operand:SI 2 "const_int_operand" "n")
2178                               (const_int 0))
2179                              (const_int 0))
2180                          (match_operand:SI 3 "arm_not_operand" "rIK")
2181                          (const_int 0)))
2182    (clobber (reg:CC CC_REGNUM))]
2183   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2184   "#"
2185   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2186   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2187                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2188                                     (const_int 0)))
2189               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2190    (set (match_dup 0)
2191         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2192                          (match_dup 0) (match_dup 3)))]
2193   "
2194   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2195   "
2196   [(set_attr "conds" "clob")
2197    (set_attr "length" "8")]
2198 )
2199
2200 (define_split
2201   [(set (match_operand:SI 0 "s_register_operand" "")
2202         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
2203                          (match_operand:SI 2 "const_int_operand" "")
2204                          (match_operand:SI 3 "const_int_operand" "")))
2205    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2206   "TARGET_THUMB1"
2207   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
2208    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
2209   "{
2210      HOST_WIDE_INT temp = INTVAL (operands[2]);
2211
2212      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2213      operands[3] = GEN_INT (32 - temp);
2214    }"
2215 )
2216
2217 ;; ??? Use Thumb-2 has bitfield insert/extract instructions.
2218 (define_split
2219   [(set (match_operand:SI 0 "s_register_operand" "")
2220         (match_operator:SI 1 "shiftable_operator"
2221          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2222                            (match_operand:SI 3 "const_int_operand" "")
2223                            (match_operand:SI 4 "const_int_operand" ""))
2224           (match_operand:SI 5 "s_register_operand" "")]))
2225    (clobber (match_operand:SI 6 "s_register_operand" ""))]
2226   "TARGET_ARM"
2227   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2228    (set (match_dup 0)
2229         (match_op_dup 1
2230          [(lshiftrt:SI (match_dup 6) (match_dup 4))
2231           (match_dup 5)]))]
2232   "{
2233      HOST_WIDE_INT temp = INTVAL (operands[3]);
2234
2235      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2236      operands[4] = GEN_INT (32 - temp);
2237    }"
2238 )
2239   
2240 (define_split
2241   [(set (match_operand:SI 0 "s_register_operand" "")
2242         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2243                          (match_operand:SI 2 "const_int_operand" "")
2244                          (match_operand:SI 3 "const_int_operand" "")))]
2245   "TARGET_THUMB1"
2246   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2247    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2248   "{
2249      HOST_WIDE_INT temp = INTVAL (operands[2]);
2250
2251      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2252      operands[3] = GEN_INT (32 - temp);
2253    }"
2254 )
2255
2256 (define_split
2257   [(set (match_operand:SI 0 "s_register_operand" "")
2258         (match_operator:SI 1 "shiftable_operator"
2259          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2260                            (match_operand:SI 3 "const_int_operand" "")
2261                            (match_operand:SI 4 "const_int_operand" ""))
2262           (match_operand:SI 5 "s_register_operand" "")]))
2263    (clobber (match_operand:SI 6 "s_register_operand" ""))]
2264   "TARGET_ARM"
2265   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2266    (set (match_dup 0)
2267         (match_op_dup 1
2268          [(ashiftrt:SI (match_dup 6) (match_dup 4))
2269           (match_dup 5)]))]
2270   "{
2271      HOST_WIDE_INT temp = INTVAL (operands[3]);
2272
2273      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2274      operands[4] = GEN_INT (32 - temp);
2275    }"
2276 )
2277   
2278 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
2279 ;;; represented by the bitfield, then this will produce incorrect results.
2280 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
2281 ;;; which have a real bit-field insert instruction, the truncation happens
2282 ;;; in the bit-field insert instruction itself.  Since arm does not have a
2283 ;;; bit-field insert instruction, we would have to emit code here to truncate
2284 ;;; the value before we insert.  This loses some of the advantage of having
2285 ;;; this insv pattern, so this pattern needs to be reevalutated.
2286
2287 (define_expand "insv"
2288   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
2289                          (match_operand:SI 1 "general_operand" "")
2290                          (match_operand:SI 2 "general_operand" ""))
2291         (match_operand:SI 3 "reg_or_int_operand" ""))]
2292   "TARGET_ARM || arm_arch_thumb2"
2293   "
2294   {
2295     int start_bit = INTVAL (operands[2]);
2296     int width = INTVAL (operands[1]);
2297     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2298     rtx target, subtarget;
2299
2300     if (arm_arch_thumb2)
2301       {
2302         bool use_bfi = TRUE;
2303
2304         if (GET_CODE (operands[3]) == CONST_INT)
2305           {
2306             HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2307
2308             if (val == 0)
2309               {
2310                 emit_insn (gen_insv_zero (operands[0], operands[1],
2311                                           operands[2]));
2312                 DONE;
2313               }
2314
2315             /* See if the set can be done with a single orr instruction.  */
2316             if (val == mask && const_ok_for_arm (val << start_bit))
2317               use_bfi = FALSE;
2318           }
2319           
2320         if (use_bfi)
2321           {
2322             if (GET_CODE (operands[3]) != REG)
2323               operands[3] = force_reg (SImode, operands[3]);
2324
2325             emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2326                                     operands[3]));
2327             DONE;
2328           }
2329       }
2330
2331     target = copy_rtx (operands[0]);
2332     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
2333        subreg as the final target.  */
2334     if (GET_CODE (target) == SUBREG)
2335       {
2336         subtarget = gen_reg_rtx (SImode);
2337         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2338             < GET_MODE_SIZE (SImode))
2339           target = SUBREG_REG (target);
2340       }
2341     else
2342       subtarget = target;    
2343
2344     if (GET_CODE (operands[3]) == CONST_INT)
2345       {
2346         /* Since we are inserting a known constant, we may be able to
2347            reduce the number of bits that we have to clear so that
2348            the mask becomes simple.  */
2349         /* ??? This code does not check to see if the new mask is actually
2350            simpler.  It may not be.  */
2351         rtx op1 = gen_reg_rtx (SImode);
2352         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
2353            start of this pattern.  */
2354         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2355         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2356
2357         emit_insn (gen_andsi3 (op1, operands[0],
2358                                gen_int_mode (~mask2, SImode)));
2359         emit_insn (gen_iorsi3 (subtarget, op1,
2360                                gen_int_mode (op3_value << start_bit, SImode)));
2361       }
2362     else if (start_bit == 0
2363              && !(const_ok_for_arm (mask)
2364                   || const_ok_for_arm (~mask)))
2365       {
2366         /* A Trick, since we are setting the bottom bits in the word,
2367            we can shift operand[3] up, operand[0] down, OR them together
2368            and rotate the result back again.  This takes 3 insns, and
2369            the third might be mergeable into another op.  */
2370         /* The shift up copes with the possibility that operand[3] is
2371            wider than the bitfield.  */
2372         rtx op0 = gen_reg_rtx (SImode);
2373         rtx op1 = gen_reg_rtx (SImode);
2374
2375         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2376         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2377         emit_insn (gen_iorsi3  (op1, op1, op0));
2378         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2379       }
2380     else if ((width + start_bit == 32)
2381              && !(const_ok_for_arm (mask)
2382                   || const_ok_for_arm (~mask)))
2383       {
2384         /* Similar trick, but slightly less efficient.  */
2385
2386         rtx op0 = gen_reg_rtx (SImode);
2387         rtx op1 = gen_reg_rtx (SImode);
2388
2389         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2390         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2391         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2392         emit_insn (gen_iorsi3 (subtarget, op1, op0));
2393       }
2394     else
2395       {
2396         rtx op0 = gen_int_mode (mask, SImode);
2397         rtx op1 = gen_reg_rtx (SImode);
2398         rtx op2 = gen_reg_rtx (SImode);
2399
2400         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2401           {
2402             rtx tmp = gen_reg_rtx (SImode);
2403
2404             emit_insn (gen_movsi (tmp, op0));
2405             op0 = tmp;
2406           }
2407
2408         /* Mask out any bits in operand[3] that are not needed.  */
2409            emit_insn (gen_andsi3 (op1, operands[3], op0));
2410
2411         if (GET_CODE (op0) == CONST_INT
2412             && (const_ok_for_arm (mask << start_bit)
2413                 || const_ok_for_arm (~(mask << start_bit))))
2414           {
2415             op0 = gen_int_mode (~(mask << start_bit), SImode);
2416             emit_insn (gen_andsi3 (op2, operands[0], op0));
2417           }
2418         else
2419           {
2420             if (GET_CODE (op0) == CONST_INT)
2421               {
2422                 rtx tmp = gen_reg_rtx (SImode);
2423
2424                 emit_insn (gen_movsi (tmp, op0));
2425                 op0 = tmp;
2426               }
2427
2428             if (start_bit != 0)
2429               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
2430             
2431             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2432           }
2433
2434         if (start_bit != 0)
2435           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
2436
2437         emit_insn (gen_iorsi3 (subtarget, op1, op2));
2438       }
2439
2440     if (subtarget != target)
2441       {
2442         /* If TARGET is still a SUBREG, then it must be wider than a word,
2443            so we must be careful only to set the subword we were asked to.  */
2444         if (GET_CODE (target) == SUBREG)
2445           emit_move_insn (target, subtarget);
2446         else
2447           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2448       }
2449
2450     DONE;
2451   }"
2452 )
2453
2454 (define_insn "insv_zero"
2455   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2456                          (match_operand:SI 1 "const_int_operand" "M")
2457                          (match_operand:SI 2 "const_int_operand" "M"))
2458         (const_int 0))]
2459   "arm_arch_thumb2"
2460   "bfc%?\t%0, %2, %1"
2461   [(set_attr "length" "4")
2462    (set_attr "predicable" "yes")]
2463 )
2464
2465 (define_insn "insv_t2"
2466   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2467                          (match_operand:SI 1 "const_int_operand" "M")
2468                          (match_operand:SI 2 "const_int_operand" "M"))
2469         (match_operand:SI 3 "s_register_operand" "r"))]
2470   "arm_arch_thumb2"
2471   "bfi%?\t%0, %3, %2, %1"
2472   [(set_attr "length" "4")
2473    (set_attr "predicable" "yes")]
2474 )
2475
2476 ; constants for op 2 will never be given to these patterns.
2477 (define_insn_and_split "*anddi_notdi_di"
2478   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2479         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2480                 (match_operand:DI 2 "s_register_operand" "r,0")))]
2481   "TARGET_32BIT"
2482   "#"
2483   "TARGET_32BIT && reload_completed
2484    && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2485    && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2486   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2487    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2488   "
2489   {
2490     operands[3] = gen_highpart (SImode, operands[0]);
2491     operands[0] = gen_lowpart (SImode, operands[0]);
2492     operands[4] = gen_highpart (SImode, operands[1]);
2493     operands[1] = gen_lowpart (SImode, operands[1]);
2494     operands[5] = gen_highpart (SImode, operands[2]);
2495     operands[2] = gen_lowpart (SImode, operands[2]);
2496   }"
2497   [(set_attr "length" "8")
2498    (set_attr "predicable" "yes")]
2499 )
2500   
2501 (define_insn_and_split "*anddi_notzesidi_di"
2502   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2503         (and:DI (not:DI (zero_extend:DI
2504                          (match_operand:SI 2 "s_register_operand" "r,r")))
2505                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2506   "TARGET_32BIT"
2507   "@
2508    bic%?\\t%Q0, %Q1, %2
2509    #"
2510   ; (not (zero_extend ...)) allows us to just copy the high word from
2511   ; operand1 to operand0.
2512   "TARGET_32BIT
2513    && reload_completed
2514    && operands[0] != operands[1]"
2515   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2516    (set (match_dup 3) (match_dup 4))]
2517   "
2518   {
2519     operands[3] = gen_highpart (SImode, operands[0]);
2520     operands[0] = gen_lowpart (SImode, operands[0]);
2521     operands[4] = gen_highpart (SImode, operands[1]);
2522     operands[1] = gen_lowpart (SImode, operands[1]);
2523   }"
2524   [(set_attr "length" "4,8")
2525    (set_attr "predicable" "yes")]
2526 )
2527   
2528 (define_insn_and_split "*anddi_notsesidi_di"
2529   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2530         (and:DI (not:DI (sign_extend:DI
2531                          (match_operand:SI 2 "s_register_operand" "r,r")))
2532                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2533   "TARGET_32BIT"
2534   "#"
2535   "TARGET_32BIT && reload_completed"
2536   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2537    (set (match_dup 3) (and:SI (not:SI
2538                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2539                                (match_dup 4)))]
2540   "
2541   {
2542     operands[3] = gen_highpart (SImode, operands[0]);
2543     operands[0] = gen_lowpart (SImode, operands[0]);
2544     operands[4] = gen_highpart (SImode, operands[1]);
2545     operands[1] = gen_lowpart (SImode, operands[1]);
2546   }"
2547   [(set_attr "length" "8")
2548    (set_attr "predicable" "yes")]
2549 )
2550   
2551 (define_insn "andsi_notsi_si"
2552   [(set (match_operand:SI 0 "s_register_operand" "=r")
2553         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2554                 (match_operand:SI 1 "s_register_operand" "r")))]
2555   "TARGET_32BIT"
2556   "bic%?\\t%0, %1, %2"
2557   [(set_attr "predicable" "yes")]
2558 )
2559
2560 (define_insn "bicsi3"
2561   [(set (match_operand:SI                 0 "register_operand" "=l")
2562         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2563                 (match_operand:SI         2 "register_operand" "0")))]
2564   "TARGET_THUMB1"
2565   "bic\\t%0, %0, %1"
2566   [(set_attr "length" "2")]
2567 )
2568
2569 (define_insn "andsi_not_shiftsi_si"
2570   [(set (match_operand:SI 0 "s_register_operand" "=r")
2571         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2572                          [(match_operand:SI 2 "s_register_operand" "r")
2573                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2574                 (match_operand:SI 1 "s_register_operand" "r")))]
2575   "TARGET_ARM"
2576   "bic%?\\t%0, %1, %2%S4"
2577   [(set_attr "predicable" "yes")
2578    (set_attr "shift" "2")
2579    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2580                       (const_string "alu_shift")
2581                       (const_string "alu_shift_reg")))]
2582 )
2583
2584 (define_insn "*andsi_notsi_si_compare0"
2585   [(set (reg:CC_NOOV CC_REGNUM)
2586         (compare:CC_NOOV
2587          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2588                  (match_operand:SI 1 "s_register_operand" "r"))
2589          (const_int 0)))
2590    (set (match_operand:SI 0 "s_register_operand" "=r")
2591         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2592   "TARGET_32BIT"
2593   "bic%.\\t%0, %1, %2"
2594   [(set_attr "conds" "set")]
2595 )
2596
2597 (define_insn "*andsi_notsi_si_compare0_scratch"
2598   [(set (reg:CC_NOOV CC_REGNUM)
2599         (compare:CC_NOOV
2600          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2601                  (match_operand:SI 1 "s_register_operand" "r"))
2602          (const_int 0)))
2603    (clobber (match_scratch:SI 0 "=r"))]
2604   "TARGET_32BIT"
2605   "bic%.\\t%0, %1, %2"
2606   [(set_attr "conds" "set")]
2607 )
2608
2609 (define_expand "iordi3"
2610   [(set (match_operand:DI         0 "s_register_operand" "")
2611         (ior:DI (match_operand:DI 1 "s_register_operand" "")
2612                 (match_operand:DI 2 "neon_logic_op2" "")))]
2613   "TARGET_32BIT"
2614   ""
2615 )
2616
2617 (define_insn "*iordi3_insn"
2618   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2619         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2620                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2621   "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
2622   "#"
2623   [(set_attr "length" "8")
2624    (set_attr "predicable" "yes")]
2625 )
2626
2627 (define_insn "*iordi_zesidi_di"
2628   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2629         (ior:DI (zero_extend:DI
2630                  (match_operand:SI 2 "s_register_operand" "r,r"))
2631                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2632   "TARGET_32BIT"
2633   "@
2634    orr%?\\t%Q0, %Q1, %2
2635    #"
2636   [(set_attr "length" "4,8")
2637    (set_attr "predicable" "yes")]
2638 )
2639
2640 (define_insn "*iordi_sesidi_di"
2641   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2642         (ior:DI (sign_extend:DI
2643                  (match_operand:SI 2 "s_register_operand" "r,r"))
2644                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2645   "TARGET_32BIT"
2646   "#"
2647   [(set_attr "length" "8")
2648    (set_attr "predicable" "yes")]
2649 )
2650
2651 (define_expand "iorsi3"
2652   [(set (match_operand:SI         0 "s_register_operand" "")
2653         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2654                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2655   "TARGET_EITHER"
2656   "
2657   if (GET_CODE (operands[2]) == CONST_INT)
2658     {
2659       if (TARGET_32BIT)
2660         {
2661           arm_split_constant (IOR, SImode, NULL_RTX,
2662                               INTVAL (operands[2]), operands[0], operands[1],
2663                               optimize && can_create_pseudo_p ());
2664           DONE;
2665         }
2666       else /* TARGET_THUMB1 */
2667         {
2668           rtx tmp = force_reg (SImode, operands[2]);
2669           if (rtx_equal_p (operands[0], operands[1]))
2670             operands[2] = tmp;
2671           else
2672             {
2673               operands[2] = operands[1];
2674               operands[1] = tmp;
2675             }
2676         }
2677     }
2678   "
2679 )
2680
2681 (define_insn_and_split "*arm_iorsi3"
2682   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2683         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2684                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2685   "TARGET_ARM"
2686   "@
2687    orr%?\\t%0, %1, %2
2688    #"
2689   "TARGET_ARM
2690    && GET_CODE (operands[2]) == CONST_INT
2691    && !const_ok_for_arm (INTVAL (operands[2]))"
2692   [(clobber (const_int 0))]
2693   "
2694   arm_split_constant (IOR, SImode, curr_insn, 
2695                       INTVAL (operands[2]), operands[0], operands[1], 0);
2696   DONE;
2697   "
2698   [(set_attr "length" "4,16")
2699    (set_attr "predicable" "yes")]
2700 )
2701
2702 (define_insn "*thumb1_iorsi3"
2703   [(set (match_operand:SI         0 "register_operand" "=l")
2704         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2705                 (match_operand:SI 2 "register_operand" "l")))]
2706   "TARGET_THUMB1"
2707   "orr\\t%0, %0, %2"
2708   [(set_attr "length" "2")]
2709 )
2710
2711 (define_peephole2
2712   [(match_scratch:SI 3 "r")
2713    (set (match_operand:SI 0 "arm_general_register_operand" "")
2714         (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2715                 (match_operand:SI 2 "const_int_operand" "")))]
2716   "TARGET_ARM
2717    && !const_ok_for_arm (INTVAL (operands[2]))
2718    && const_ok_for_arm (~INTVAL (operands[2]))"
2719   [(set (match_dup 3) (match_dup 2))
2720    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2721   ""
2722 )
2723
2724 (define_insn "*iorsi3_compare0"
2725   [(set (reg:CC_NOOV CC_REGNUM)
2726         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2727                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2728                          (const_int 0)))
2729    (set (match_operand:SI 0 "s_register_operand" "=r")
2730         (ior:SI (match_dup 1) (match_dup 2)))]
2731   "TARGET_32BIT"
2732   "orr%.\\t%0, %1, %2"
2733   [(set_attr "conds" "set")]
2734 )
2735
2736 (define_insn "*iorsi3_compare0_scratch"
2737   [(set (reg:CC_NOOV CC_REGNUM)
2738         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2739                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2740                          (const_int 0)))
2741    (clobber (match_scratch:SI 0 "=r"))]
2742   "TARGET_32BIT"
2743   "orr%.\\t%0, %1, %2"
2744   [(set_attr "conds" "set")]
2745 )
2746
2747 (define_expand "xordi3"
2748   [(set (match_operand:DI         0 "s_register_operand" "")
2749         (xor:DI (match_operand:DI 1 "s_register_operand" "")
2750                 (match_operand:DI 2 "s_register_operand" "")))]
2751   "TARGET_32BIT"
2752   ""
2753 )
2754
2755 (define_insn "*xordi3_insn"
2756   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2757         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2758                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2759   "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
2760   "#"
2761   [(set_attr "length" "8")
2762    (set_attr "predicable" "yes")]
2763 )
2764
2765 (define_insn "*xordi_zesidi_di"
2766   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2767         (xor:DI (zero_extend:DI
2768                  (match_operand:SI 2 "s_register_operand" "r,r"))
2769                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2770   "TARGET_32BIT"
2771   "@
2772    eor%?\\t%Q0, %Q1, %2
2773    #"
2774   [(set_attr "length" "4,8")
2775    (set_attr "predicable" "yes")]
2776 )
2777
2778 (define_insn "*xordi_sesidi_di"
2779   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2780         (xor:DI (sign_extend:DI
2781                  (match_operand:SI 2 "s_register_operand" "r,r"))
2782                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2783   "TARGET_32BIT"
2784   "#"
2785   [(set_attr "length" "8")
2786    (set_attr "predicable" "yes")]
2787 )
2788
2789 (define_expand "xorsi3"
2790   [(set (match_operand:SI         0 "s_register_operand" "")
2791         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2792                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2793   "TARGET_EITHER"
2794   "if (GET_CODE (operands[2]) == CONST_INT)
2795     {
2796       if (TARGET_32BIT)
2797         {
2798           arm_split_constant (XOR, SImode, NULL_RTX,
2799                               INTVAL (operands[2]), operands[0], operands[1],
2800                               optimize && can_create_pseudo_p ());
2801           DONE;
2802         }
2803       else /* TARGET_THUMB1 */
2804         {
2805           rtx tmp = force_reg (SImode, operands[2]);
2806           if (rtx_equal_p (operands[0], operands[1]))
2807             operands[2] = tmp;
2808           else
2809             {
2810               operands[2] = operands[1];
2811               operands[1] = tmp;
2812             }
2813         }
2814     }"
2815 )
2816
2817 (define_insn "*arm_xorsi3"
2818   [(set (match_operand:SI         0 "s_register_operand" "=r")
2819         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2820                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2821   "TARGET_32BIT"
2822   "eor%?\\t%0, %1, %2"
2823   [(set_attr "predicable" "yes")]
2824 )
2825
2826 (define_insn "*thumb1_xorsi3"
2827   [(set (match_operand:SI         0 "register_operand" "=l")
2828         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2829                 (match_operand:SI 2 "register_operand" "l")))]
2830   "TARGET_THUMB1"
2831   "eor\\t%0, %0, %2"
2832   [(set_attr "length" "2")]
2833 )
2834
2835 (define_insn "*xorsi3_compare0"
2836   [(set (reg:CC_NOOV CC_REGNUM)
2837         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2838                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2839                          (const_int 0)))
2840    (set (match_operand:SI 0 "s_register_operand" "=r")
2841         (xor:SI (match_dup 1) (match_dup 2)))]
2842   "TARGET_32BIT"
2843   "eor%.\\t%0, %1, %2"
2844   [(set_attr "conds" "set")]
2845 )
2846
2847 (define_insn "*xorsi3_compare0_scratch"
2848   [(set (reg:CC_NOOV CC_REGNUM)
2849         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2850                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2851                          (const_int 0)))]
2852   "TARGET_32BIT"
2853   "teq%?\\t%0, %1"
2854   [(set_attr "conds" "set")]
2855 )
2856
2857 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2858 ; (NOT D) we can sometimes merge the final NOT into one of the following
2859 ; insns.
2860
2861 (define_split
2862   [(set (match_operand:SI 0 "s_register_operand" "")
2863         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2864                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2865                 (match_operand:SI 3 "arm_rhs_operand" "")))
2866    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2867   "TARGET_32BIT"
2868   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2869                               (not:SI (match_dup 3))))
2870    (set (match_dup 0) (not:SI (match_dup 4)))]
2871   ""
2872 )
2873
2874 (define_insn "*andsi_iorsi3_notsi"
2875   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2876         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
2877                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2878                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2879   "TARGET_32BIT"
2880   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2881   [(set_attr "length" "8")
2882    (set_attr "ce_count" "2")
2883    (set_attr "predicable" "yes")]
2884 )
2885
2886 ; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
2887 ; insns are available?
2888 (define_split
2889   [(set (match_operand:SI 0 "s_register_operand" "")
2890         (match_operator:SI 1 "logical_binary_operator"
2891          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2892                            (match_operand:SI 3 "const_int_operand" "")
2893                            (match_operand:SI 4 "const_int_operand" ""))
2894           (match_operator:SI 9 "logical_binary_operator"
2895            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2896                          (match_operand:SI 6 "const_int_operand" ""))
2897             (match_operand:SI 7 "s_register_operand" "")])]))
2898    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2899   "TARGET_32BIT
2900    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2901    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2902   [(set (match_dup 8)
2903         (match_op_dup 1
2904          [(ashift:SI (match_dup 2) (match_dup 4))
2905           (match_dup 5)]))
2906    (set (match_dup 0)
2907         (match_op_dup 1
2908          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2909           (match_dup 7)]))]
2910   "
2911   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2912 ")
2913
2914 (define_split
2915   [(set (match_operand:SI 0 "s_register_operand" "")
2916         (match_operator:SI 1 "logical_binary_operator"
2917          [(match_operator:SI 9 "logical_binary_operator"
2918            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2919                          (match_operand:SI 6 "const_int_operand" ""))
2920             (match_operand:SI 7 "s_register_operand" "")])
2921           (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2922                            (match_operand:SI 3 "const_int_operand" "")
2923                            (match_operand:SI 4 "const_int_operand" ""))]))
2924    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2925   "TARGET_32BIT
2926    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2927    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2928   [(set (match_dup 8)
2929         (match_op_dup 1
2930          [(ashift:SI (match_dup 2) (match_dup 4))
2931           (match_dup 5)]))
2932    (set (match_dup 0)
2933         (match_op_dup 1
2934          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2935           (match_dup 7)]))]
2936   "
2937   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2938 ")
2939
2940 (define_split
2941   [(set (match_operand:SI 0 "s_register_operand" "")
2942         (match_operator:SI 1 "logical_binary_operator"
2943          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2944                            (match_operand:SI 3 "const_int_operand" "")
2945                            (match_operand:SI 4 "const_int_operand" ""))
2946           (match_operator:SI 9 "logical_binary_operator"
2947            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2948                          (match_operand:SI 6 "const_int_operand" ""))
2949             (match_operand:SI 7 "s_register_operand" "")])]))
2950    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2951   "TARGET_32BIT
2952    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2953    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2954   [(set (match_dup 8)
2955         (match_op_dup 1
2956          [(ashift:SI (match_dup 2) (match_dup 4))
2957           (match_dup 5)]))
2958    (set (match_dup 0)
2959         (match_op_dup 1
2960          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2961           (match_dup 7)]))]
2962   "
2963   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2964 ")
2965
2966 (define_split
2967   [(set (match_operand:SI 0 "s_register_operand" "")
2968         (match_operator:SI 1 "logical_binary_operator"
2969          [(match_operator:SI 9 "logical_binary_operator"
2970            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2971                          (match_operand:SI 6 "const_int_operand" ""))
2972             (match_operand:SI 7 "s_register_operand" "")])
2973           (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2974                            (match_operand:SI 3 "const_int_operand" "")
2975                            (match_operand:SI 4 "const_int_operand" ""))]))
2976    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2977   "TARGET_32BIT
2978    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2979    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2980   [(set (match_dup 8)
2981         (match_op_dup 1
2982          [(ashift:SI (match_dup 2) (match_dup 4))
2983           (match_dup 5)]))
2984    (set (match_dup 0)
2985         (match_op_dup 1
2986          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2987           (match_dup 7)]))]
2988   "
2989   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2990 ")
2991 \f
2992
2993 ;; Minimum and maximum insns
2994
2995 (define_expand "smaxsi3"
2996   [(parallel [
2997     (set (match_operand:SI 0 "s_register_operand" "")
2998          (smax:SI (match_operand:SI 1 "s_register_operand" "")
2999                   (match_operand:SI 2 "arm_rhs_operand" "")))
3000     (clobber (reg:CC CC_REGNUM))])]
3001   "TARGET_32BIT"
3002   "
3003   if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
3004     {
3005       /* No need for a clobber of the condition code register here.  */
3006       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3007                               gen_rtx_SMAX (SImode, operands[1],
3008                                             operands[2])));
3009       DONE;
3010     }
3011 ")
3012
3013 (define_insn "*smax_0"
3014   [(set (match_operand:SI 0 "s_register_operand" "=r")
3015         (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3016                  (const_int 0)))]
3017   "TARGET_32BIT"
3018   "bic%?\\t%0, %1, %1, asr #31"
3019   [(set_attr "predicable" "yes")]
3020 )
3021
3022 (define_insn "*smax_m1"
3023   [(set (match_operand:SI 0 "s_register_operand" "=r")
3024         (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3025                  (const_int -1)))]
3026   "TARGET_32BIT"
3027   "orr%?\\t%0, %1, %1, asr #31"
3028   [(set_attr "predicable" "yes")]
3029 )
3030
3031 (define_insn "*arm_smax_insn"
3032   [(set (match_operand:SI          0 "s_register_operand" "=r,r")
3033         (smax:SI (match_operand:SI 1 "s_register_operand"  "%0,?r")
3034                  (match_operand:SI 2 "arm_rhs_operand"    "rI,rI")))
3035    (clobber (reg:CC CC_REGNUM))]
3036   "TARGET_ARM"
3037   "@
3038    cmp\\t%1, %2\;movlt\\t%0, %2
3039    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
3040   [(set_attr "conds" "clob")
3041    (set_attr "length" "8,12")]
3042 )
3043
3044 (define_expand "sminsi3"
3045   [(parallel [
3046     (set (match_operand:SI 0 "s_register_operand" "")
3047          (smin:SI (match_operand:SI 1 "s_register_operand" "")
3048                   (match_operand:SI 2 "arm_rhs_operand" "")))
3049     (clobber (reg:CC CC_REGNUM))])]
3050   "TARGET_32BIT"
3051   "
3052   if (operands[2] == const0_rtx)
3053     {
3054       /* No need for a clobber of the condition code register here.  */
3055       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3056                               gen_rtx_SMIN (SImode, operands[1],
3057                                             operands[2])));
3058       DONE;
3059     }
3060 ")
3061
3062 (define_insn "*smin_0"
3063   [(set (match_operand:SI 0 "s_register_operand" "=r")
3064         (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3065                  (const_int 0)))]
3066   "TARGET_32BIT"
3067   "and%?\\t%0, %1, %1, asr #31"
3068   [(set_attr "predicable" "yes")]
3069 )
3070
3071 (define_insn "*arm_smin_insn"
3072   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3073         (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3074                  (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
3075    (clobber (reg:CC CC_REGNUM))]
3076   "TARGET_ARM"
3077   "@
3078    cmp\\t%1, %2\;movge\\t%0, %2
3079    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
3080   [(set_attr "conds" "clob")
3081    (set_attr "length" "8,12")]
3082 )
3083
3084 (define_expand "umaxsi3"
3085   [(parallel [
3086     (set (match_operand:SI 0 "s_register_operand" "")
3087          (umax:SI (match_operand:SI 1 "s_register_operand" "")
3088                   (match_operand:SI 2 "arm_rhs_operand" "")))
3089     (clobber (reg:CC CC_REGNUM))])]
3090   "TARGET_32BIT"
3091   ""
3092 )
3093
3094 (define_insn "*arm_umaxsi3"
3095   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3096         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3097                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
3098    (clobber (reg:CC CC_REGNUM))]
3099   "TARGET_ARM"
3100   "@
3101    cmp\\t%1, %2\;movcc\\t%0, %2
3102    cmp\\t%1, %2\;movcs\\t%0, %1
3103    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
3104   [(set_attr "conds" "clob")
3105    (set_attr "length" "8,8,12")]
3106 )
3107
3108 (define_expand "uminsi3"
3109   [(parallel [
3110     (set (match_operand:SI 0 "s_register_operand" "")
3111          (umin:SI (match_operand:SI 1 "s_register_operand" "")
3112                   (match_operand:SI 2 "arm_rhs_operand" "")))
3113     (clobber (reg:CC CC_REGNUM))])]
3114   "TARGET_32BIT"
3115   ""
3116 )
3117
3118 (define_insn "*arm_uminsi3"
3119   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3120         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3121                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
3122    (clobber (reg:CC CC_REGNUM))]
3123   "TARGET_ARM"
3124   "@
3125    cmp\\t%1, %2\;movcs\\t%0, %2
3126    cmp\\t%1, %2\;movcc\\t%0, %1
3127    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
3128   [(set_attr "conds" "clob")
3129    (set_attr "length" "8,8,12")]
3130 )
3131
3132 (define_insn "*store_minmaxsi"
3133   [(set (match_operand:SI 0 "memory_operand" "=m")
3134         (match_operator:SI 3 "minmax_operator"
3135          [(match_operand:SI 1 "s_register_operand" "r")
3136           (match_operand:SI 2 "s_register_operand" "r")]))
3137    (clobber (reg:CC CC_REGNUM))]
3138   "TARGET_32BIT"
3139   "*
3140   operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3141                                 operands[1], operands[2]);
3142   output_asm_insn (\"cmp\\t%1, %2\", operands);
3143   if (TARGET_THUMB2)
3144     output_asm_insn (\"ite\t%d3\", operands);
3145   output_asm_insn (\"str%d3\\t%1, %0\", operands);
3146   output_asm_insn (\"str%D3\\t%2, %0\", operands);
3147   return \"\";
3148   "
3149   [(set_attr "conds" "clob")
3150    (set (attr "length")
3151         (if_then_else (eq_attr "is_thumb" "yes")
3152                       (const_int 14)
3153                       (const_int 12)))
3154    (set_attr "type" "store1")]
3155 )
3156
3157 ; Reject the frame pointer in operand[1], since reloading this after
3158 ; it has been eliminated can cause carnage.
3159 (define_insn "*minmax_arithsi"
3160   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3161         (match_operator:SI 4 "shiftable_operator"
3162          [(match_operator:SI 5 "minmax_operator"
3163            [(match_operand:SI 2 "s_register_operand" "r,r")
3164             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3165           (match_operand:SI 1 "s_register_operand" "0,?r")]))
3166    (clobber (reg:CC CC_REGNUM))]
3167   "TARGET_32BIT && !arm_eliminable_register (operands[1])"
3168   "*
3169   {
3170     enum rtx_code code = GET_CODE (operands[4]);
3171     bool need_else;
3172
3173     if (which_alternative != 0 || operands[3] != const0_rtx
3174         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
3175       need_else = true;
3176     else
3177       need_else = false;
3178
3179     operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3180                                   operands[2], operands[3]);
3181     output_asm_insn (\"cmp\\t%2, %3\", operands);
3182     if (TARGET_THUMB2)
3183       {
3184         if (need_else)
3185           output_asm_insn (\"ite\\t%d5\", operands);
3186         else
3187           output_asm_insn (\"it\\t%d5\", operands);
3188       }
3189     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
3190     if (need_else)
3191       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3192     return \"\";
3193   }"
3194   [(set_attr "conds" "clob")
3195    (set (attr "length")
3196         (if_then_else (eq_attr "is_thumb" "yes")
3197                       (const_int 14)
3198                       (const_int 12)))]
3199 )
3200
3201 \f
3202 ;; Shift and rotation insns
3203
3204 (define_expand "ashldi3"
3205   [(set (match_operand:DI            0 "s_register_operand" "")
3206         (ashift:DI (match_operand:DI 1 "s_register_operand" "")
3207                    (match_operand:SI 2 "reg_or_int_operand" "")))]
3208   "TARGET_32BIT"
3209   "
3210   if (GET_CODE (operands[2]) == CONST_INT)
3211     {
3212       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3213         {
3214           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3215           DONE;
3216         }
3217         /* Ideally we shouldn't fail here if we could know that operands[1] 
3218            ends up already living in an iwmmxt register. Otherwise it's
3219            cheaper to have the alternate code being generated than moving
3220            values to iwmmxt regs and back.  */
3221         FAIL;
3222     }
3223   else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
3224     FAIL;
3225   "
3226 )
3227
3228 (define_insn "arm_ashldi3_1bit"
3229   [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
3230         (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
3231                    (const_int 1)))
3232    (clobber (reg:CC CC_REGNUM))]
3233   "TARGET_32BIT"
3234   "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
3235   [(set_attr "conds" "clob")
3236    (set_attr "length" "8")]
3237 )
3238
3239 (define_expand "ashlsi3"
3240   [(set (match_operand:SI            0 "s_register_operand" "")
3241         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3242                    (match_operand:SI 2 "arm_rhs_operand" "")))]
3243   "TARGET_EITHER"
3244   "
3245   if (GET_CODE (operands[2]) == CONST_INT
3246       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3247     {
3248       emit_insn (gen_movsi (operands[0], const0_rtx));
3249       DONE;
3250     }
3251   "
3252 )
3253
3254 (define_insn "*thumb1_ashlsi3"
3255   [(set (match_operand:SI            0 "register_operand" "=l,l")
3256         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
3257                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
3258   "TARGET_THUMB1"
3259   "lsl\\t%0, %1, %2"
3260   [(set_attr "length" "2")]
3261 )
3262
3263 (define_expand "ashrdi3"
3264   [(set (match_operand:DI              0 "s_register_operand" "")
3265         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3266                      (match_operand:SI 2 "reg_or_int_operand" "")))]
3267   "TARGET_32BIT"
3268   "
3269   if (GET_CODE (operands[2]) == CONST_INT)
3270     {
3271       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3272         {
3273           emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3274           DONE;
3275         }
3276         /* Ideally we shouldn't fail here if we could know that operands[1] 
3277            ends up already living in an iwmmxt register. Otherwise it's
3278            cheaper to have the alternate code being generated than moving
3279            values to iwmmxt regs and back.  */
3280         FAIL;
3281     }
3282   else if (!TARGET_REALLY_IWMMXT)
3283     FAIL;
3284   "
3285 )
3286
3287 (define_insn "arm_ashrdi3_1bit"
3288   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
3289         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
3290                      (const_int 1)))
3291    (clobber (reg:CC CC_REGNUM))]
3292   "TARGET_32BIT"
3293   "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
3294   [(set_attr "conds" "clob")
3295    (set_attr "length" "8")]
3296 )
3297
3298 (define_expand "ashrsi3"
3299   [(set (match_operand:SI              0 "s_register_operand" "")
3300         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3301                      (match_operand:SI 2 "arm_rhs_operand" "")))]
3302   "TARGET_EITHER"
3303   "
3304   if (GET_CODE (operands[2]) == CONST_INT
3305       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3306     operands[2] = GEN_INT (31);
3307   "
3308 )
3309
3310 (define_insn "*thumb1_ashrsi3"
3311   [(set (match_operand:SI              0 "register_operand" "=l,l")
3312         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3313                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
3314   "TARGET_THUMB1"
3315   "asr\\t%0, %1, %2"
3316   [(set_attr "length" "2")]
3317 )
3318
3319 (define_expand "lshrdi3"
3320   [(set (match_operand:DI              0 "s_register_operand" "")
3321         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3322                      (match_operand:SI 2 "reg_or_int_operand" "")))]
3323   "TARGET_32BIT"
3324   "
3325   if (GET_CODE (operands[2]) == CONST_INT)
3326     {
3327       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3328         {
3329           emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3330           DONE;
3331         }
3332         /* Ideally we shouldn't fail here if we could know that operands[1] 
3333            ends up already living in an iwmmxt register. Otherwise it's
3334            cheaper to have the alternate code being generated than moving
3335            values to iwmmxt regs and back.  */
3336         FAIL;
3337     }
3338   else if (!TARGET_REALLY_IWMMXT)
3339     FAIL;
3340   "
3341 )
3342
3343 (define_insn "arm_lshrdi3_1bit"
3344   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
3345         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
3346                      (const_int 1)))
3347    (clobber (reg:CC CC_REGNUM))]
3348   "TARGET_32BIT"
3349   "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
3350   [(set_attr "conds" "clob")
3351    (set_attr "length" "8")]
3352 )
3353
3354 (define_expand "lshrsi3"
3355   [(set (match_operand:SI              0 "s_register_operand" "")
3356         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3357                      (match_operand:SI 2 "arm_rhs_operand" "")))]
3358   "TARGET_EITHER"
3359   "
3360   if (GET_CODE (operands[2]) == CONST_INT
3361       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3362     {
3363       emit_insn (gen_movsi (operands[0], const0_rtx));
3364       DONE;
3365     }
3366   "
3367 )
3368
3369 (define_insn "*thumb1_lshrsi3"
3370   [(set (match_operand:SI              0 "register_operand" "=l,l")
3371         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3372                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
3373   "TARGET_THUMB1"
3374   "lsr\\t%0, %1, %2"
3375   [(set_attr "length" "2")]
3376 )
3377
3378 (define_expand "rotlsi3"
3379   [(set (match_operand:SI              0 "s_register_operand" "")
3380         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3381                      (match_operand:SI 2 "reg_or_int_operand" "")))]
3382   "TARGET_32BIT"
3383   "
3384   if (GET_CODE (operands[2]) == CONST_INT)
3385     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3386   else
3387     {
3388       rtx reg = gen_reg_rtx (SImode);
3389       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3390       operands[2] = reg;
3391     }
3392   "
3393 )
3394
3395 (define_expand "rotrsi3"
3396   [(set (match_operand:SI              0 "s_register_operand" "")
3397         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3398                      (match_operand:SI 2 "arm_rhs_operand" "")))]
3399   "TARGET_EITHER"
3400   "
3401   if (TARGET_32BIT)
3402     {
3403       if (GET_CODE (operands[2]) == CONST_INT
3404           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3405         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3406     }
3407   else /* TARGET_THUMB1 */
3408     {
3409       if (GET_CODE (operands [2]) == CONST_INT)
3410         operands [2] = force_reg (SImode, operands[2]);
3411     }
3412   "
3413 )
3414
3415 (define_insn "*thumb1_rotrsi3"
3416   [(set (match_operand:SI              0 "register_operand" "=l")
3417         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
3418                      (match_operand:SI 2 "register_operand" "l")))]
3419   "TARGET_THUMB1"
3420   "ror\\t%0, %0, %2"
3421   [(set_attr "length" "2")]
3422 )
3423
3424 (define_insn "*arm_shiftsi3"
3425   [(set (match_operand:SI   0 "s_register_operand" "=r")
3426         (match_operator:SI  3 "shift_operator"
3427          [(match_operand:SI 1 "s_register_operand"  "r")
3428           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
3429   "TARGET_32BIT"
3430   "* return arm_output_shift(operands, 0);"
3431   [(set_attr "predicable" "yes")
3432    (set_attr "shift" "1")
3433    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3434                       (const_string "alu_shift")
3435                       (const_string "alu_shift_reg")))]
3436 )
3437
3438 (define_insn "*shiftsi3_compare0"
3439   [(set (reg:CC_NOOV CC_REGNUM)
3440         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3441                           [(match_operand:SI 1 "s_register_operand" "r")
3442                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
3443                          (const_int 0)))
3444    (set (match_operand:SI 0 "s_register_operand" "=r")
3445         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
3446   "TARGET_32BIT"
3447   "* return arm_output_shift(operands, 1);"
3448   [(set_attr "conds" "set")
3449    (set_attr "shift" "1")
3450    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3451                       (const_string "alu_shift")
3452                       (const_string "alu_shift_reg")))]
3453 )
3454
3455 (define_insn "*shiftsi3_compare0_scratch"
3456   [(set (reg:CC_NOOV CC_REGNUM)
3457         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3458                           [(match_operand:SI 1 "s_register_operand" "r")
3459                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
3460                          (const_int 0)))
3461    (clobber (match_scratch:SI 0 "=r"))]
3462   "TARGET_32BIT"
3463   "* return arm_output_shift(operands, 1);"
3464   [(set_attr "conds" "set")
3465    (set_attr "shift" "1")]
3466 )
3467
3468 (define_insn "*arm_notsi_shiftsi"
3469   [(set (match_operand:SI 0 "s_register_operand" "=r")
3470         (not:SI (match_operator:SI 3 "shift_operator"
3471                  [(match_operand:SI 1 "s_register_operand" "r")
3472                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
3473   "TARGET_ARM"
3474   "mvn%?\\t%0, %1%S3"
3475   [(set_attr "predicable" "yes")
3476    (set_attr "shift" "1")
3477    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3478                       (const_string "alu_shift")
3479                       (const_string "alu_shift_reg")))]
3480 )
3481
3482 (define_insn "*arm_notsi_shiftsi_compare0"
3483   [(set (reg:CC_NOOV CC_REGNUM)
3484         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
3485                           [(match_operand:SI 1 "s_register_operand" "r")
3486                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
3487                          (const_int 0)))
3488    (set (match_operand:SI 0 "s_register_operand" "=r")
3489         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
3490   "TARGET_ARM"
3491   "mvn%.\\t%0, %1%S3"
3492   [(set_attr "conds" "set")
3493    (set_attr "shift" "1")
3494    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3495                       (const_string "alu_shift")
3496                       (const_string "alu_shift_reg")))]
3497 )
3498
3499 (define_insn "*arm_not_shiftsi_compare0_scratch"
3500   [(set (reg:CC_NOOV CC_REGNUM)
3501         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
3502                           [(match_operand:SI 1 "s_register_operand" "r")
3503                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
3504                          (const_int 0)))
3505    (clobber (match_scratch:SI 0 "=r"))]
3506   "TARGET_ARM"
3507   "mvn%.\\t%0, %1%S3"
3508   [(set_attr "conds" "set")
3509    (set_attr "shift" "1")
3510    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3511                       (const_string "alu_shift")
3512                       (const_string "alu_shift_reg")))]
3513 )
3514
3515 ;; We don't really have extzv, but defining this using shifts helps
3516 ;; to reduce register pressure later on.
3517
3518 (define_expand "extzv"
3519   [(set (match_dup 4)
3520         (ashift:SI (match_operand:SI   1 "register_operand" "")
3521                    (match_operand:SI   2 "const_int_operand" "")))
3522    (set (match_operand:SI              0 "register_operand" "")
3523         (lshiftrt:SI (match_dup 4)
3524                      (match_operand:SI 3 "const_int_operand" "")))]
3525   "TARGET_THUMB1 || arm_arch_thumb2"
3526   "
3527   {
3528     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3529     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3530     
3531     if (arm_arch_thumb2)
3532       {
3533         emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
3534                                  operands[3]));
3535         DONE;
3536       }
3537
3538     operands[3] = GEN_INT (rshift);
3539     
3540     if (lshift == 0)
3541       {
3542         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3543         DONE;
3544       }
3545       
3546     operands[2] = GEN_INT (lshift);
3547     operands[4] = gen_reg_rtx (SImode);
3548   }"
3549 )
3550
3551 (define_insn "extv"
3552   [(set (match_operand:SI 0 "s_register_operand" "=r")
3553         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3554                          (match_operand:SI 2 "const_int_operand" "M")
3555                          (match_operand:SI 3 "const_int_operand" "M")))]
3556   "arm_arch_thumb2"
3557   "sbfx%?\t%0, %1, %3, %2"
3558   [(set_attr "length" "4")
3559    (set_attr "predicable" "yes")]
3560 )
3561
3562 (define_insn "extzv_t2"
3563   [(set (match_operand:SI 0 "s_register_operand" "=r")
3564         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3565                          (match_operand:SI 2 "const_int_operand" "M")
3566                          (match_operand:SI 3 "const_int_operand" "M")))]
3567   "arm_arch_thumb2"
3568   "ubfx%?\t%0, %1, %3, %2"
3569   [(set_attr "length" "4")
3570    (set_attr "predicable" "yes")]
3571 )
3572
3573 \f
3574 ;; Unary arithmetic insns
3575
3576 (define_expand "negdi2"
3577  [(parallel
3578    [(set (match_operand:DI 0 "s_register_operand" "")
3579          (neg:DI (match_operand:DI 1 "s_register_operand" "")))
3580     (clobber (reg:CC CC_REGNUM))])]
3581   "TARGET_EITHER"
3582   ""
3583 )
3584
3585 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
3586 ;; The first alternative allows the common case of a *full* overlap.
3587 (define_insn "*arm_negdi2"
3588   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
3589         (neg:DI (match_operand:DI 1 "s_register_operand"  "0,r")))
3590    (clobber (reg:CC CC_REGNUM))]
3591   "TARGET_ARM"
3592   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
3593   [(set_attr "conds" "clob")
3594    (set_attr "length" "8")]
3595 )
3596
3597 (define_insn "*thumb1_negdi2"
3598   [(set (match_operand:DI 0 "register_operand" "=&l")
3599         (neg:DI (match_operand:DI 1 "register_operand" "l")))
3600    (clobber (reg:CC CC_REGNUM))]
3601   "TARGET_THUMB1"
3602   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
3603   [(set_attr "length" "6")]
3604 )
3605
3606 (define_expand "negsi2"
3607   [(set (match_operand:SI         0 "s_register_operand" "")
3608         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
3609   "TARGET_EITHER"
3610   ""
3611 )
3612
3613 (define_insn "*arm_negsi2"
3614   [(set (match_operand:SI         0 "s_register_operand" "=r")
3615         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
3616   "TARGET_32BIT"
3617   "rsb%?\\t%0, %1, #0"
3618   [(set_attr "predicable" "yes")]
3619 )
3620
3621 (define_insn "*thumb1_negsi2"
3622   [(set (match_operand:SI         0 "register_operand" "=l")
3623         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
3624   "TARGET_THUMB1"
3625   "neg\\t%0, %1"
3626   [(set_attr "length" "2")]
3627 )
3628
3629 (define_expand "negsf2"
3630   [(set (match_operand:SF         0 "s_register_operand" "")
3631         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
3632   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3633   ""
3634 )
3635
3636 (define_expand "negdf2"
3637   [(set (match_operand:DF         0 "s_register_operand" "")
3638         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
3639   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
3640   "")
3641
3642 ;; abssi2 doesn't really clobber the condition codes if a different register
3643 ;; is being set.  To keep things simple, assume during rtl manipulations that
3644 ;; it does, but tell the final scan operator the truth.  Similarly for
3645 ;; (neg (abs...))
3646
3647 (define_expand "abssi2"
3648   [(parallel
3649     [(set (match_operand:SI         0 "s_register_operand" "")
3650           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3651      (clobber (match_dup 2))])]
3652   "TARGET_EITHER"
3653   "
3654   if (TARGET_THUMB1)
3655     operands[2] = gen_rtx_SCRATCH (SImode);
3656   else
3657     operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
3658 ")
3659
3660 (define_insn "*arm_abssi2"
3661   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3662         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3663    (clobber (reg:CC CC_REGNUM))]
3664   "TARGET_ARM"
3665   "@
3666    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3667    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3668   [(set_attr "conds" "clob,*")
3669    (set_attr "shift" "1")
3670    ;; predicable can't be set based on the variant, so left as no
3671    (set_attr "length" "8")]
3672 )
3673
3674 (define_insn_and_split "*thumb1_abssi2"
3675   [(set (match_operand:SI 0 "s_register_operand" "=l")
3676         (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
3677    (clobber (match_scratch:SI 2 "=&l"))]
3678   "TARGET_THUMB1"
3679   "#"
3680   "TARGET_THUMB1 && reload_completed"
3681   [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3682    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
3683    (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3684   ""
3685   [(set_attr "length" "6")]
3686 )
3687
3688 (define_insn "*arm_neg_abssi2"
3689   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3690         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3691    (clobber (reg:CC CC_REGNUM))]
3692   "TARGET_ARM"
3693   "@
3694    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3695    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3696   [(set_attr "conds" "clob,*")
3697    (set_attr "shift" "1")
3698    ;; predicable can't be set based on the variant, so left as no
3699    (set_attr "length" "8")]
3700 )
3701
3702 (define_insn_and_split "*thumb1_neg_abssi2"
3703   [(set (match_operand:SI 0 "s_register_operand" "=l")
3704         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
3705    (clobber (match_scratch:SI 2 "=&l"))]
3706   "TARGET_THUMB1"
3707   "#"
3708   "TARGET_THUMB1 && reload_completed"
3709   [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3710    (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
3711    (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3712   ""
3713   [(set_attr "length" "6")]
3714 )
3715
3716 (define_expand "abssf2"
3717   [(set (match_operand:SF         0 "s_register_operand" "")
3718         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3719   "TARGET_32BIT && TARGET_HARD_FLOAT"
3720   "")
3721
3722 (define_expand "absdf2"
3723   [(set (match_operand:DF         0 "s_register_operand" "")
3724         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3725   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
3726   "")
3727
3728 (define_expand "sqrtsf2"
3729   [(set (match_operand:SF 0 "s_register_operand" "")
3730         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3731   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3732   "")
3733
3734 (define_expand "sqrtdf2"
3735   [(set (match_operand:DF 0 "s_register_operand" "")
3736         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3737   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
3738   "")
3739
3740 (define_insn_and_split "one_cmpldi2"
3741   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3742         (not:DI (match_operand:DI 1 "s_register_operand" "0,r")))]
3743   "TARGET_32BIT"
3744   "#"
3745   "TARGET_32BIT && reload_completed"
3746   [(set (match_dup 0) (not:SI (match_dup 1)))
3747    (set (match_dup 2) (not:SI (match_dup 3)))]
3748   "
3749   {
3750     operands[2] = gen_highpart (SImode, operands[0]);
3751     operands[0] = gen_lowpart (SImode, operands[0]);
3752     operands[3] = gen_highpart (SImode, operands[1]);
3753     operands[1] = gen_lowpart (SImode, operands[1]);
3754   }"
3755   [(set_attr "length" "8")
3756    (set_attr "predicable" "yes")]
3757 )
3758
3759 (define_expand "one_cmplsi2"
3760   [(set (match_operand:SI         0 "s_register_operand" "")
3761         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3762   "TARGET_EITHER"
3763   ""
3764 )
3765
3766 (define_insn "*arm_one_cmplsi2"
3767   [(set (match_operand:SI         0 "s_register_operand" "=r")
3768         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3769   "TARGET_32BIT"
3770   "mvn%?\\t%0, %1"
3771   [(set_attr "predicable" "yes")]
3772 )
3773
3774 (define_insn "*thumb1_one_cmplsi2"
3775   [(set (match_operand:SI         0 "register_operand" "=l")
3776         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3777   "TARGET_THUMB1"
3778   "mvn\\t%0, %1"
3779   [(set_attr "length" "2")]
3780 )
3781
3782 (define_insn "*notsi_compare0"
3783   [(set (reg:CC_NOOV CC_REGNUM)
3784         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3785                          (const_int 0)))
3786    (set (match_operand:SI 0 "s_register_operand" "=r")
3787         (not:SI (match_dup 1)))]
3788   "TARGET_32BIT"
3789   "mvn%.\\t%0, %1"
3790   [(set_attr "conds" "set")]
3791 )
3792
3793 (define_insn "*notsi_compare0_scratch"
3794   [(set (reg:CC_NOOV CC_REGNUM)
3795         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3796                          (const_int 0)))
3797    (clobber (match_scratch:SI 0 "=r"))]
3798   "TARGET_32BIT"
3799   "mvn%.\\t%0, %1"
3800   [(set_attr "conds" "set")]
3801 )
3802 \f
3803 ;; Fixed <--> Floating conversion insns
3804
3805 (define_expand "floatsihf2"
3806   [(set (match_operand:HF           0 "general_operand" "")
3807         (float:HF (match_operand:SI 1 "general_operand" "")))]
3808   "TARGET_EITHER"
3809   "
3810   {
3811     rtx op1 = gen_reg_rtx (SFmode);
3812     expand_float (op1, operands[1], 0);
3813     op1 = convert_to_mode (HFmode, op1, 0);
3814     emit_move_insn (operands[0], op1);
3815     DONE;
3816   }"
3817 )
3818
3819 (define_expand "floatdihf2"
3820   [(set (match_operand:HF           0 "general_operand" "")
3821         (float:HF (match_operand:DI 1 "general_operand" "")))]
3822   "TARGET_EITHER"
3823   "
3824   {
3825     rtx op1 = gen_reg_rtx (SFmode);
3826     expand_float (op1, operands[1], 0);
3827     op1 = convert_to_mode (HFmode, op1, 0);
3828     emit_move_insn (operands[0], op1);
3829     DONE;
3830   }"
3831 )
3832
3833 (define_expand "floatsisf2"
3834   [(set (match_operand:SF           0 "s_register_operand" "")
3835         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3836   "TARGET_32BIT && TARGET_HARD_FLOAT"
3837   "
3838   if (TARGET_MAVERICK)
3839     {
3840       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3841       DONE;
3842     }
3843 ")
3844
3845 (define_expand "floatsidf2"
3846   [(set (match_operand:DF           0 "s_register_operand" "")
3847         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3848   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
3849   "
3850   if (TARGET_MAVERICK)
3851     {
3852       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3853       DONE;
3854     }
3855 ")
3856
3857 (define_expand "fix_trunchfsi2"
3858   [(set (match_operand:SI         0 "general_operand" "")
3859         (fix:SI (fix:HF (match_operand:HF 1 "general_operand"  ""))))]
3860   "TARGET_EITHER"
3861   "
3862   {
3863     rtx op1 = convert_to_mode (SFmode, operands[1], 0);
3864     expand_fix (operands[0], op1, 0);
3865     DONE;
3866   }"
3867 )
3868
3869 (define_expand "fix_trunchfdi2"
3870   [(set (match_operand:DI         0 "general_operand" "")
3871         (fix:DI (fix:HF (match_operand:HF 1 "general_operand"  ""))))]
3872   "TARGET_EITHER"
3873   "
3874   {
3875     rtx op1 = convert_to_mode (SFmode, operands[1], 0);
3876     expand_fix (operands[0], op1, 0);
3877     DONE;
3878   }"
3879 )
3880
3881 (define_expand "fix_truncsfsi2"
3882   [(set (match_operand:SI         0 "s_register_operand" "")
3883         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3884   "TARGET_32BIT && TARGET_HARD_FLOAT"
3885   "
3886   if (TARGET_MAVERICK)
3887     {
3888       if (!cirrus_fp_register (operands[0], SImode))
3889         operands[0] = force_reg (SImode, operands[0]);
3890       if (!cirrus_fp_register (operands[1], SFmode))
3891         operands[1] = force_reg (SFmode, operands[0]);
3892       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3893       DONE;
3894     }
3895 ")
3896
3897 (define_expand "fix_truncdfsi2"
3898   [(set (match_operand:SI         0 "s_register_operand" "")
3899         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3900   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
3901   "
3902   if (TARGET_MAVERICK)
3903     {
3904       if (!cirrus_fp_register (operands[1], DFmode))
3905         operands[1] = force_reg (DFmode, operands[0]);
3906       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3907       DONE;
3908     }
3909 ")
3910
3911 ;; Truncation insns
3912
3913 (define_expand "truncdfsf2"
3914   [(set (match_operand:SF  0 "s_register_operand" "")
3915         (float_truncate:SF
3916          (match_operand:DF 1 "s_register_operand" "")))]
3917   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
3918   ""
3919 )
3920
3921 /* DFmode -> HFmode conversions have to go through SFmode.  */
3922 (define_expand "truncdfhf2"
3923   [(set (match_operand:HF  0 "general_operand" "")
3924         (float_truncate:HF
3925          (match_operand:DF 1 "general_operand" "")))]
3926   "TARGET_EITHER"
3927   "
3928   {
3929     rtx op1;
3930     op1 = convert_to_mode (SFmode, operands[1], 0);
3931     op1 = convert_to_mode (HFmode, op1, 0);
3932     emit_move_insn (operands[0], op1);
3933     DONE;
3934   }"
3935 )
3936 \f
3937 ;; Zero and sign extension instructions.
3938
3939 (define_expand "zero_extendsidi2"
3940   [(set (match_operand:DI 0 "s_register_operand" "")
3941         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
3942   "TARGET_32BIT"
3943   ""
3944 )
3945
3946 (define_insn "*arm_zero_extendsidi2"
3947   [(set (match_operand:DI 0 "s_register_operand" "=r")
3948         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3949   "TARGET_ARM"
3950   "*
3951     if (REGNO (operands[1])
3952         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3953       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3954     return \"mov%?\\t%R0, #0\";
3955   "
3956   [(set_attr "length" "8")
3957    (set_attr "predicable" "yes")]
3958 )
3959
3960 (define_expand "zero_extendqidi2"
3961   [(set (match_operand:DI                 0 "s_register_operand"  "")
3962         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))]
3963   "TARGET_32BIT"
3964   ""
3965 )
3966
3967 (define_insn "*arm_zero_extendqidi2"
3968   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3969         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3970   "TARGET_ARM"
3971   "@
3972    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3973    ldr%(b%)\\t%Q0, %1\;mov%?\\t%R0, #0"
3974   [(set_attr "length" "8")
3975    (set_attr "predicable" "yes")
3976    (set_attr "type" "*,load_byte")
3977    (set_attr "pool_range" "*,4092")
3978    (set_attr "neg_pool_range" "*,4084")]
3979 )
3980
3981 (define_expand "extendsidi2"
3982   [(set (match_operand:DI 0 "s_register_operand" "")
3983         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
3984   "TARGET_32BIT"
3985   ""
3986 )
3987
3988 (define_insn "*arm_extendsidi2"
3989   [(set (match_operand:DI 0 "s_register_operand" "=r")
3990         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3991   "TARGET_ARM"
3992   "*
3993     if (REGNO (operands[1])
3994         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3995       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3996     return \"mov%?\\t%R0, %Q0, asr #31\";
3997   "
3998   [(set_attr "length" "8")
3999    (set_attr "shift" "1")
4000    (set_attr "predicable" "yes")]
4001 )
4002
4003 (define_expand "zero_extendhisi2"
4004   [(set (match_operand:SI 0 "s_register_operand" "")
4005         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
4006   "TARGET_EITHER"
4007 {
4008   if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
4009     {
4010       emit_insn (gen_movhi_bytes (operands[0], operands[1]));
4011       DONE;
4012     }
4013   if (!arm_arch6 && !MEM_P (operands[1]))
4014     {
4015       rtx t = gen_lowpart (SImode, operands[1]);
4016       rtx tmp = gen_reg_rtx (SImode);
4017       emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4018       emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
4019       DONE;
4020     }
4021 })
4022
4023 (define_split
4024   [(set (match_operand:SI 0 "register_operand" "")
4025         (zero_extend:SI (match_operand:HI 1 "register_operand" "l,m")))]
4026   "!TARGET_THUMB2 && !arm_arch6"
4027   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4028    (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4029 {
4030   operands[2] = gen_lowpart (SImode, operands[1]);
4031 })
4032
4033 (define_insn "*thumb1_zero_extendhisi2"
4034   [(set (match_operand:SI 0 "register_operand" "=l,l")
4035         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
4036   "TARGET_THUMB1"
4037   "*
4038   rtx mem;
4039
4040   if (which_alternative == 0 && arm_arch6)
4041     return \"uxth\\t%0, %1\";
4042   if (which_alternative == 0)
4043     return \"#\";
4044
4045   mem = XEXP (operands[1], 0);
4046
4047   if (GET_CODE (mem) == CONST)
4048     mem = XEXP (mem, 0);
4049     
4050   if (GET_CODE (mem) == LABEL_REF)
4051     return \"ldr\\t%0, %1\";
4052     
4053   if (GET_CODE (mem) == PLUS)
4054     {
4055       rtx a = XEXP (mem, 0);
4056       rtx b = XEXP (mem, 1);
4057
4058       /* This can happen due to bugs in reload.  */
4059       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
4060         {
4061           rtx ops[2];
4062           ops[0] = operands[0];
4063           ops[1] = a;
4064       
4065           output_asm_insn (\"mov        %0, %1\", ops);
4066
4067           XEXP (mem, 0) = operands[0];
4068        }
4069
4070       else if (   GET_CODE (a) == LABEL_REF
4071                && GET_CODE (b) == CONST_INT)
4072         return \"ldr\\t%0, %1\";
4073     }
4074     
4075   return \"ldrh\\t%0, %1\";
4076   "
4077   [(set_attr_alternative "length"
4078                          [(if_then_else (eq_attr "is_arch6" "yes")
4079                                        (const_int 2) (const_int 4))
4080                          (const_int 4)])
4081    (set_attr "type" "alu_shift,load_byte")
4082    (set_attr "pool_range" "*,60")]
4083 )
4084
4085 (define_insn "*arm_zero_extendhisi2"
4086   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4087         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4088   "TARGET_ARM && arm_arch4 && !arm_arch6"
4089   "@
4090    #
4091    ldr%(h%)\\t%0, %1"
4092   [(set_attr "type" "alu_shift,load_byte")
4093    (set_attr "predicable" "yes")
4094    (set_attr "pool_range" "*,256")
4095    (set_attr "neg_pool_range" "*,244")]
4096 )
4097
4098 (define_insn "*arm_zero_extendhisi2_v6"
4099   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4100         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4101   "TARGET_ARM && arm_arch6"
4102   "@
4103    uxth%?\\t%0, %1
4104    ldr%(h%)\\t%0, %1"
4105   [(set_attr "type" "alu_shift,load_byte")
4106    (set_attr "predicable" "yes")
4107    (set_attr "pool_range" "*,256")
4108    (set_attr "neg_pool_range" "*,244")]
4109 )
4110
4111 (define_insn "*arm_zero_extendhisi2addsi"
4112   [(set (match_operand:SI 0 "s_register_operand" "=r")
4113         (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4114                  (match_operand:SI 2 "s_register_operand" "r")))]
4115   "TARGET_INT_SIMD"
4116   "uxtah%?\\t%0, %2, %1"
4117   [(set_attr "type" "alu_shift")
4118    (set_attr "predicable" "yes")]
4119 )
4120
4121 (define_expand "zero_extendqisi2"
4122   [(set (match_operand:SI 0 "s_register_operand" "")
4123         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
4124   "TARGET_EITHER"
4125 {
4126   if (TARGET_ARM && !arm_arch6 && GET_CODE (operands[1]) != MEM)
4127     {
4128       emit_insn (gen_andsi3 (operands[0],
4129                              gen_lowpart (SImode, operands[1]),
4130                                           GEN_INT (255)));
4131       DONE;
4132     }
4133   if (!arm_arch6 && !MEM_P (operands[1]))
4134     {
4135       rtx t = gen_lowpart (SImode, operands[1]);
4136       rtx tmp = gen_reg_rtx (SImode);
4137       emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4138       emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
4139       DONE;
4140     }
4141 })
4142
4143 (define_split
4144   [(set (match_operand:SI 0 "register_operand" "")
4145         (zero_extend:SI (match_operand:QI 1 "register_operand" "")))]
4146   "!arm_arch6"
4147   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4148    (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
4149 {
4150   operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4151   if (TARGET_ARM)
4152     {
4153       emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
4154       DONE;
4155     }
4156 })
4157
4158 (define_insn "*thumb1_zero_extendqisi2"
4159   [(set (match_operand:SI 0 "register_operand" "=l,l")
4160         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
4161   "TARGET_THUMB1 && !arm_arch6"
4162   "@
4163    #
4164    ldrb\\t%0, %1"
4165   [(set_attr "length" "4,2")
4166    (set_attr "type" "alu_shift,load_byte")
4167    (set_attr "pool_range" "*,32")]
4168 )
4169
4170 (define_insn "*thumb1_zero_extendqisi2_v6"
4171   [(set (match_operand:SI 0 "register_operand" "=l,l")
4172         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
4173   "TARGET_THUMB1 && arm_arch6"
4174   "@
4175    uxtb\\t%0, %1
4176    ldrb\\t%0, %1"
4177   [(set_attr "length" "2,2")
4178    (set_attr "type" "alu_shift,load_byte")
4179    (set_attr "pool_range" "*,32")]
4180 )
4181
4182 (define_insn "*arm_zero_extendqisi2"
4183   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4184         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4185   "TARGET_ARM && !arm_arch6"
4186   "@
4187    #
4188    ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
4189   [(set_attr "length" "8,4")
4190    (set_attr "type" "alu_shift,load_byte")
4191    (set_attr "predicable" "yes")
4192    (set_attr "pool_range" "*,4096")
4193    (set_attr "neg_pool_range" "*,4084")]
4194 )
4195
4196 (define_insn "*arm_zero_extendqisi2_v6"
4197   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4198         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4199   "TARGET_ARM && arm_arch6"
4200   "@
4201    uxtb%(%)\\t%0, %1
4202    ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
4203   [(set_attr "type" "alu_shift,load_byte")
4204    (set_attr "predicable" "yes")
4205    (set_attr "pool_range" "*,4096")
4206    (set_attr "neg_pool_range" "*,4084")]
4207 )
4208
4209 (define_insn "*arm_zero_extendqisi2addsi"
4210   [(set (match_operand:SI 0 "s_register_operand" "=r")
4211         (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4212                  (match_operand:SI 2 "s_register_operand" "r")))]
4213   "TARGET_INT_SIMD"
4214   "uxtab%?\\t%0, %2, %1"
4215   [(set_attr "predicable" "yes")
4216    (set_attr "insn" "xtab")
4217    (set_attr "type" "alu_shift")]
4218 )
4219
4220 (define_split
4221   [(set (match_operand:SI 0 "s_register_operand" "")
4222         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
4223    (clobber (match_operand:SI 2 "s_register_operand" ""))]
4224   "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
4225   [(set (match_dup 2) (match_dup 1))
4226    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4227   ""
4228 )
4229
4230 (define_split
4231   [(set (match_operand:SI 0 "s_register_operand" "")
4232         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
4233    (clobber (match_operand:SI 2 "s_register_operand" ""))]
4234   "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
4235   [(set (match_dup 2) (match_dup 1))
4236    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4237   ""
4238 )
4239
4240 (define_code_iterator ior_xor [ior xor])
4241
4242 (define_split
4243   [(set (match_operand:SI 0 "s_register_operand" "")
4244         (ior_xor:SI (and:SI (ashift:SI
4245                              (match_operand:SI 1 "s_register_operand" "")
4246                              (match_operand:SI 2 "const_int_operand" ""))
4247                             (match_operand:SI 3 "const_int_operand" ""))
4248                     (zero_extend:SI
4249                      (match_operator 5 "subreg_lowpart_operator"
4250                       [(match_operand:SI 4 "s_register_operand" "")]))))]
4251   "TARGET_32BIT
4252    && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
4253        == (GET_MODE_MASK (GET_MODE (operands[5]))
4254            & (GET_MODE_MASK (GET_MODE (operands[5]))
4255               << (INTVAL (operands[2])))))"
4256   [(set (match_dup 0) (ior_xor:SI (ashift:SI (match_dup 1) (match_dup 2))
4257                                   (match_dup 4)))
4258    (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
4259   "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
4260 )
4261
4262 (define_insn "*compareqi_eq0"
4263   [(set (reg:CC_Z CC_REGNUM)
4264         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
4265                          (const_int 0)))]
4266   "TARGET_32BIT"
4267   "tst\\t%0, #255"
4268   [(set_attr "conds" "set")]
4269 )
4270
4271 (define_expand "extendhisi2"
4272   [(set (match_operand:SI 0 "s_register_operand" "")
4273         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
4274   "TARGET_EITHER"
4275 {
4276   if (TARGET_THUMB1)
4277     {
4278       emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
4279       DONE;
4280     }
4281   if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
4282     {
4283       emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
4284       DONE;
4285     }
4286
4287   if (!arm_arch6 && !MEM_P (operands[1]))
4288     {
4289       rtx t = gen_lowpart (SImode, operands[1]);
4290       rtx tmp = gen_reg_rtx (SImode);
4291       emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4292       emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
4293       DONE;
4294     }
4295 })
4296
4297 (define_split
4298   [(parallel
4299     [(set (match_operand:SI 0 "register_operand" "")
4300           (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
4301      (clobber (match_scratch:SI 2 ""))])]
4302   "!arm_arch6"
4303   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4304    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4305 {
4306   operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4307 })
4308
4309 ;; We used to have an early-clobber on the scratch register here.
4310 ;; However, there's a bug somewhere in reload which means that this
4311 ;; can be partially ignored during spill allocation if the memory
4312 ;; address also needs reloading; this causes us to die later on when
4313 ;; we try to verify the operands.  Fortunately, we don't really need
4314 ;; the early-clobber: we can always use operand 0 if operand 2
4315 ;; overlaps the address.
4316 (define_insn "thumb1_extendhisi2"
4317   [(set (match_operand:SI 0 "register_operand" "=l,l")
4318         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
4319    (clobber (match_scratch:SI 2 "=X,l"))]
4320   "TARGET_THUMB1"
4321   "*
4322   {
4323     rtx ops[4];
4324     rtx mem;
4325
4326     if (which_alternative == 0 && !arm_arch6)
4327       return \"#\";
4328     if (which_alternative == 0)
4329       return \"sxth\\t%0, %1\";
4330
4331     mem = XEXP (operands[1], 0);
4332
4333     /* This code used to try to use 'V', and fix the address only if it was
4334        offsettable, but this fails for e.g. REG+48 because 48 is outside the
4335        range of QImode offsets, and offsettable_address_p does a QImode
4336        address check.  */
4337        
4338     if (GET_CODE (mem) == CONST)
4339       mem = XEXP (mem, 0);
4340     
4341     if (GET_CODE (mem) == LABEL_REF)
4342       return \"ldr\\t%0, %1\";
4343     
4344     if (GET_CODE (mem) == PLUS)
4345       {
4346         rtx a = XEXP (mem, 0);
4347         rtx b = XEXP (mem, 1);
4348
4349         if (GET_CODE (a) == LABEL_REF
4350             && GET_CODE (b) == CONST_INT)
4351           return \"ldr\\t%0, %1\";
4352
4353         if (GET_CODE (b) == REG)
4354           return \"ldrsh\\t%0, %1\";
4355           
4356         ops[1] = a;
4357         ops[2] = b;
4358       }
4359     else
4360       {
4361         ops[1] = mem;
4362         ops[2] = const0_rtx;
4363       }
4364       
4365     gcc_assert (GET_CODE (ops[1]) == REG);
4366
4367     ops[0] = operands[0];
4368     if (reg_mentioned_p (operands[2], ops[1]))
4369       ops[3] = ops[0];
4370     else
4371       ops[3] = operands[2];
4372     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4373     return \"\";
4374   }"
4375   [(set_attr_alternative "length"
4376                          [(if_then_else (eq_attr "is_arch6" "yes")
4377                                         (const_int 2) (const_int 4))
4378                           (const_int 4)])
4379    (set_attr "type" "alu_shift,load_byte")
4380    (set_attr "pool_range" "*,1020")]
4381 )
4382
4383 ;; This pattern will only be used when ldsh is not available
4384 (define_expand "extendhisi2_mem"
4385   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4386    (set (match_dup 3)
4387         (zero_extend:SI (match_dup 7)))
4388    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4389    (set (match_operand:SI 0 "" "")
4390         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
4391   "TARGET_ARM"
4392   "
4393   {
4394     rtx mem1, mem2;
4395     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4396
4397     mem1 = change_address (operands[1], QImode, addr);
4398     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
4399     operands[0] = gen_lowpart (SImode, operands[0]);
4400     operands[1] = mem1;
4401     operands[2] = gen_reg_rtx (SImode);
4402     operands[3] = gen_reg_rtx (SImode);
4403     operands[6] = gen_reg_rtx (SImode);
4404     operands[7] = mem2;
4405
4406     if (BYTES_BIG_ENDIAN)
4407       {
4408         operands[4] = operands[2];
4409         operands[5] = operands[3];
4410       }
4411     else
4412       {
4413         operands[4] = operands[3];
4414         operands[5] = operands[2];
4415       }
4416   }"
4417 )
4418
4419 (define_split
4420   [(set (match_operand:SI 0 "register_operand" "")
4421         (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
4422   "!arm_arch6"
4423   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4424    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4425 {
4426   operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4427 })
4428
4429 (define_insn "*arm_extendhisi2"
4430   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4431         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4432   "TARGET_ARM && arm_arch4 && !arm_arch6"
4433   "@
4434    #
4435    ldr%(sh%)\\t%0, %1"
4436   [(set_attr "length" "8,4")
4437    (set_attr "type" "alu_shift,load_byte")
4438    (set_attr "predicable" "yes")
4439    (set_attr "pool_range" "*,256")
4440    (set_attr "neg_pool_range" "*,244")]
4441 )
4442
4443 ;; ??? Check Thumb-2 pool range
4444 (define_insn "*arm_extendhisi2_v6"
4445   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4446         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4447   "TARGET_32BIT && arm_arch6"
4448   "@
4449    sxth%?\\t%0, %1
4450    ldr%(sh%)\\t%0, %1"
4451   [(set_attr "type" "alu_shift,load_byte")
4452    (set_attr "predicable" "yes")
4453    (set_attr "pool_range" "*,256")
4454    (set_attr "neg_pool_range" "*,244")]
4455 )
4456
4457 (define_insn "*arm_extendhisi2addsi"
4458   [(set (match_operand:SI 0 "s_register_operand" "=r")
4459         (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4460                  (match_operand:SI 2 "s_register_operand" "r")))]
4461   "TARGET_INT_SIMD"
4462   "sxtah%?\\t%0, %2, %1"
4463 )
4464
4465 (define_expand "extendqihi2"
4466   [(set (match_dup 2)
4467         (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
4468                    (const_int 24)))
4469    (set (match_operand:HI 0 "s_register_operand" "")
4470         (ashiftrt:SI (match_dup 2)
4471                      (const_int 24)))]
4472   "TARGET_ARM"
4473   "
4474   {
4475     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
4476       {
4477         emit_insn (gen_rtx_SET (VOIDmode,
4478                                 operands[0],
4479                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
4480         DONE;
4481       }
4482     if (!s_register_operand (operands[1], QImode))
4483       operands[1] = copy_to_mode_reg (QImode, operands[1]);
4484     operands[0] = gen_lowpart (SImode, operands[0]);
4485     operands[1] = gen_lowpart (SImode, operands[1]);
4486     operands[2] = gen_reg_rtx (SImode);
4487   }"
4488 )
4489
4490 (define_insn "*arm_extendqihi_insn"
4491   [(set (match_operand:HI 0 "s_register_operand" "=r")
4492         (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
4493   "TARGET_ARM && arm_arch4"
4494   "ldr%(sb%)\\t%0, %1"
4495   [(set_attr "type" "load_byte")
4496    (set_attr "predicable" "yes")
4497    (set_attr "pool_range" "256")
4498    (set_attr "neg_pool_range" "244")]
4499 )
4500
4501 (define_expand "extendqisi2"
4502   [(set (match_operand:SI 0 "s_register_operand" "")
4503         (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
4504   "TARGET_EITHER"
4505 {
4506   if (!arm_arch4 && MEM_P (operands[1]))
4507     operands[1] = copy_to_mode_reg (QImode, operands[1]);
4508
4509   if (!arm_arch6 && !MEM_P (operands[1]))
4510     {
4511       rtx t = gen_lowpart (SImode, operands[1]);
4512       rtx tmp = gen_reg_rtx (SImode);
4513       emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4514       emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
4515       DONE;
4516     }
4517 })
4518
4519 (define_split
4520   [(set (match_operand:SI 0 "register_operand" "")
4521         (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
4522   "!arm_arch6"
4523   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4524    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
4525 {
4526   operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4527 })
4528
4529 (define_insn "*arm_extendqisi"
4530   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4531         (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
4532   "TARGET_ARM && arm_arch4 && !arm_arch6"
4533   "@
4534    #
4535    ldr%(sb%)\\t%0, %1"
4536   [(set_attr "length" "8,4")
4537    (set_attr "type" "alu_shift,load_byte")
4538    (set_attr "predicable" "yes")
4539    (set_attr "pool_range" "*,256")
4540    (set_attr "neg_pool_range" "*,244")]
4541 )
4542
4543 (define_insn "*arm_extendqisi_v6"
4544   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4545         (sign_extend:SI
4546          (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
4547   "TARGET_ARM && arm_arch6"
4548   "@
4549    sxtb%?\\t%0, %1
4550    ldr%(sb%)\\t%0, %1"
4551   [(set_attr "type" "alu_shift,load_byte")
4552    (set_attr "predicable" "yes")
4553    (set_attr "pool_range" "*,256")
4554    (set_attr "neg_pool_range" "*,244")]
4555 )
4556
4557 (define_insn "*arm_extendqisi2addsi"
4558   [(set (match_operand:SI 0 "s_register_operand" "=r")
4559         (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4560                  (match_operand:SI 2 "s_register_operand" "r")))]
4561   "TARGET_INT_SIMD"
4562   "sxtab%?\\t%0, %2, %1"
4563   [(set_attr "type" "alu_shift")
4564    (set_attr "insn" "xtab")
4565    (set_attr "predicable" "yes")]
4566 )
4567
4568 (define_split
4569   [(set (match_operand:SI 0 "register_operand" "")
4570         (sign_extend:SI (match_operand:QI 1 "memory_operand" "")))]
4571   "TARGET_THUMB1 && reload_completed"
4572   [(set (match_dup 0) (match_dup 2))
4573    (set (match_dup 0) (sign_extend:SI (match_dup 3)))]
4574 {
4575   rtx addr = XEXP (operands[1], 0);
4576
4577   if (GET_CODE (addr) == CONST)
4578     addr = XEXP (addr, 0);
4579
4580   if (GET_CODE (addr) == PLUS
4581       && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
4582     /* No split necessary.  */
4583     FAIL;
4584
4585   if (GET_CODE (addr) == PLUS
4586       && !REG_P (XEXP (addr, 0)) && !REG_P (XEXP (addr, 1)))
4587     FAIL;
4588
4589   if (reg_overlap_mentioned_p (operands[0], addr))
4590     {
4591       rtx t = gen_lowpart (QImode, operands[0]);
4592       emit_move_insn (t, operands[1]);
4593       emit_insn (gen_thumb1_extendqisi2 (operands[0], t));
4594       DONE;
4595     }
4596
4597   if (REG_P (addr))
4598     {
4599       addr = gen_rtx_PLUS (Pmode, addr, operands[0]);
4600       operands[2] = const0_rtx;
4601     }
4602   else if (GET_CODE (addr) != PLUS)
4603     FAIL;
4604   else if (REG_P (XEXP (addr, 0)))
4605     {
4606       operands[2] = XEXP (addr, 1);
4607       addr = gen_rtx_PLUS (Pmode, XEXP (addr, 0), operands[0]);
4608     }
4609   else
4610     {
4611       operands[2] = XEXP (addr, 0);
4612       addr = gen_rtx_PLUS (Pmode, XEXP (addr, 1), operands[0]);
4613     }
4614
4615   operands[3] = change_address (operands[1], QImode, addr);
4616 })
4617
4618 (define_peephole2
4619   [(set (match_operand:SI 0 "register_operand" "")
4620         (plus:SI (match_dup 0) (match_operand 1 "const_int_operand")))
4621    (set (match_operand:SI 2 "register_operand" "") (const_int 0))
4622    (set (match_operand:SI 3 "register_operand" "")
4623         (sign_extend:SI (match_operand:QI 4 "memory_operand" "")))]
4624   "TARGET_THUMB1
4625    && GET_CODE (XEXP (operands[4], 0)) == PLUS
4626    && rtx_equal_p (operands[0], XEXP (XEXP (operands[4], 0), 0))
4627    && rtx_equal_p (operands[2], XEXP (XEXP (operands[4], 0), 1))
4628    && (peep2_reg_dead_p (3, operands[0])
4629        || rtx_equal_p (operands[0], operands[3]))
4630    && (peep2_reg_dead_p (3, operands[2])
4631        || rtx_equal_p (operands[2], operands[3]))"
4632   [(set (match_dup 2) (match_dup 1))
4633    (set (match_dup 3) (sign_extend:SI (match_dup 4)))]
4634 {
4635   rtx addr = gen_rtx_PLUS (Pmode, operands[0], operands[2]);
4636   operands[4] = change_address (operands[4], QImode, addr);
4637 })
4638
4639 (define_insn "thumb1_extendqisi2"
4640   [(set (match_operand:SI 0 "register_operand" "=l,l,l")
4641         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
4642   "TARGET_THUMB1"
4643 {
4644   rtx addr;
4645
4646   if (which_alternative == 0 && arm_arch6)
4647     return "sxtb\\t%0, %1";
4648   if (which_alternative == 0)
4649     return "#";
4650
4651   addr = XEXP (operands[1], 0);
4652   if (GET_CODE (addr) == PLUS
4653       && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
4654     return "ldrsb\\t%0, %1";
4655       
4656   return "#";
4657 }
4658   [(set_attr_alternative "length"
4659                          [(if_then_else (eq_attr "is_arch6" "yes")
4660                                         (const_int 2) (const_int 4))
4661                           (const_int 2)
4662                           (if_then_else (eq_attr "is_arch6" "yes")
4663                                         (const_int 4) (const_int 6))])
4664    (set_attr "type" "alu_shift,load_byte,load_byte")]
4665 )
4666
4667 (define_expand "extendsfdf2"
4668   [(set (match_operand:DF                  0 "s_register_operand" "")
4669         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
4670   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
4671   ""
4672 )
4673
4674 /* HFmode -> DFmode conversions have to go through SFmode.  */
4675 (define_expand "extendhfdf2"
4676   [(set (match_operand:DF                  0 "general_operand" "")
4677         (float_extend:DF (match_operand:HF 1 "general_operand"  "")))]
4678   "TARGET_EITHER"
4679   "
4680   {
4681     rtx op1;
4682     op1 = convert_to_mode (SFmode, operands[1], 0);
4683     op1 = convert_to_mode (DFmode, op1, 0);
4684     emit_insn (gen_movdf (operands[0], op1));
4685     DONE;
4686   }"
4687 )
4688 \f
4689 ;; Move insns (including loads and stores)
4690
4691 ;; XXX Just some ideas about movti.
4692 ;; I don't think these are a good idea on the arm, there just aren't enough
4693 ;; registers
4694 ;;(define_expand "loadti"
4695 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
4696 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
4697 ;;  "" "")
4698
4699 ;;(define_expand "storeti"
4700 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4701 ;;      (match_operand:TI 1 "s_register_operand" ""))]
4702 ;;  "" "")
4703
4704 ;;(define_expand "movti"
4705 ;;  [(set (match_operand:TI 0 "general_operand" "")
4706 ;;      (match_operand:TI 1 "general_operand" ""))]
4707 ;;  ""
4708 ;;  "
4709 ;;{
4710 ;;  rtx insn;
4711 ;;
4712 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4713 ;;    operands[1] = copy_to_reg (operands[1]);
4714 ;;  if (GET_CODE (operands[0]) == MEM)
4715 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4716 ;;  else if (GET_CODE (operands[1]) == MEM)
4717 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4718 ;;  else
4719 ;;    FAIL;
4720 ;;
4721 ;;  emit_insn (insn);
4722 ;;  DONE;
4723 ;;}")
4724
4725 ;; Recognize garbage generated above.
4726
4727 ;;(define_insn ""
4728 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4729 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4730 ;;  ""
4731 ;;  "*
4732 ;;  {
4733 ;;    register mem = (which_alternative < 3);
4734 ;;    register const char *template;
4735 ;;
4736 ;;    operands[mem] = XEXP (operands[mem], 0);
4737 ;;    switch (which_alternative)
4738 ;;      {
4739 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4740 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
4741 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
4742 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
4743 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
4744 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
4745 ;;      }
4746 ;;    output_asm_insn (template, operands);
4747 ;;    return \"\";
4748 ;;  }")
4749
4750 (define_expand "movdi"
4751   [(set (match_operand:DI 0 "general_operand" "")
4752         (match_operand:DI 1 "general_operand" ""))]
4753   "TARGET_EITHER"
4754   "
4755   if (can_create_pseudo_p ())
4756     {
4757       if (GET_CODE (operands[0]) != REG)
4758         operands[1] = force_reg (DImode, operands[1]);
4759     }
4760   "
4761 )
4762
4763 (define_insn "*arm_movdi"
4764   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4765         (match_operand:DI 1 "di_operand"              "rDa,Db,Dc,mi,r"))]
4766   "TARGET_ARM
4767    && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4768    && !TARGET_IWMMXT
4769    && (   register_operand (operands[0], DImode)
4770        || register_operand (operands[1], DImode))"
4771   "*
4772   switch (which_alternative)
4773     {
4774     case 0:
4775     case 1:
4776     case 2:
4777       return \"#\";
4778     default:
4779       return output_move_double (operands);
4780     }
4781   "
4782   [(set_attr "length" "8,12,16,8,8")
4783    (set_attr "type" "*,*,*,load2,store2")
4784    (set_attr "pool_range" "*,*,*,1020,*")
4785    (set_attr "neg_pool_range" "*,*,*,1008,*")]
4786 )
4787
4788 (define_split
4789   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4790         (match_operand:ANY64 1 "const_double_operand" ""))]
4791   "TARGET_32BIT
4792    && reload_completed
4793    && (arm_const_double_inline_cost (operands[1])
4794        <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4795   [(const_int 0)]
4796   "
4797   arm_split_constant (SET, SImode, curr_insn,
4798                       INTVAL (gen_lowpart (SImode, operands[1])),
4799                       gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4800   arm_split_constant (SET, SImode, curr_insn,
4801                       INTVAL (gen_highpart_mode (SImode,
4802                                                  GET_MODE (operands[0]),
4803                                                  operands[1])),
4804                       gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4805   DONE;
4806   "
4807 )
4808
4809 ; If optimizing for size, or if we have load delay slots, then 
4810 ; we want to split the constant into two separate operations. 
4811 ; In both cases this may split a trivial part into a single data op
4812 ; leaving a single complex constant to load.  We can also get longer
4813 ; offsets in a LDR which means we get better chances of sharing the pool
4814 ; entries.  Finally, we can normally do a better job of scheduling
4815 ; LDR instructions than we can with LDM.
4816 ; This pattern will only match if the one above did not.
4817 (define_split
4818   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4819         (match_operand:ANY64 1 "const_double_operand" ""))]
4820   "TARGET_ARM && reload_completed
4821    && arm_const_double_by_parts (operands[1])"
4822   [(set (match_dup 0) (match_dup 1))
4823    (set (match_dup 2) (match_dup 3))]
4824   "
4825   operands[2] = gen_highpart (SImode, operands[0]);
4826   operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4827                                    operands[1]);
4828   operands[0] = gen_lowpart (SImode, operands[0]);
4829   operands[1] = gen_lowpart (SImode, operands[1]);
4830   "
4831 )
4832
4833 (define_split
4834   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4835         (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4836   "TARGET_EITHER && reload_completed"
4837   [(set (match_dup 0) (match_dup 1))
4838    (set (match_dup 2) (match_dup 3))]
4839   "
4840   operands[2] = gen_highpart (SImode, operands[0]);
4841   operands[3] = gen_highpart (SImode, operands[1]);
4842   operands[0] = gen_lowpart (SImode, operands[0]);
4843   operands[1] = gen_lowpart (SImode, operands[1]);
4844
4845   /* Handle a partial overlap.  */
4846   if (rtx_equal_p (operands[0], operands[3]))
4847     {
4848       rtx tmp0 = operands[0];
4849       rtx tmp1 = operands[1];
4850
4851       operands[0] = operands[2];
4852       operands[1] = operands[3];
4853       operands[2] = tmp0;
4854       operands[3] = tmp1;
4855     }
4856   "
4857 )
4858
4859 ;; We can't actually do base+index doubleword loads if the index and
4860 ;; destination overlap.  Split here so that we at least have chance to
4861 ;; schedule.
4862 (define_split
4863   [(set (match_operand:DI 0 "s_register_operand" "")
4864         (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4865                          (match_operand:SI 2 "s_register_operand" ""))))]
4866   "TARGET_LDRD
4867   && reg_overlap_mentioned_p (operands[0], operands[1])
4868   && reg_overlap_mentioned_p (operands[0], operands[2])"
4869   [(set (match_dup 4)
4870         (plus:SI (match_dup 1)
4871                  (match_dup 2)))
4872    (set (match_dup 0)
4873         (mem:DI (match_dup 4)))]
4874   "
4875   operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4876   "
4877 )
4878
4879 ;;; ??? This should have alternatives for constants.
4880 ;;; ??? This was originally identical to the movdf_insn pattern.
4881 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4882 ;;; thumb_reorg with a memory reference.
4883 (define_insn "*thumb1_movdi_insn"
4884   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4885         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
4886   "TARGET_THUMB1
4887    && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4888    && (   register_operand (operands[0], DImode)
4889        || register_operand (operands[1], DImode))"
4890   "*
4891   {
4892   switch (which_alternative)
4893     {
4894     default:
4895     case 0:
4896       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4897         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
4898       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
4899     case 1:
4900       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4901     case 2:
4902       operands[1] = GEN_INT (- INTVAL (operands[1]));
4903       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4904     case 3:
4905       return \"ldmia\\t%1, {%0, %H0}\";
4906     case 4:
4907       return \"stmia\\t%0, {%1, %H1}\";
4908     case 5:
4909       return thumb_load_double_from_address (operands);
4910     case 6:
4911       operands[2] = gen_rtx_MEM (SImode,
4912                              plus_constant (XEXP (operands[0], 0), 4));
4913       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4914       return \"\";
4915     case 7:
4916       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4917         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4918       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4919     }
4920   }"
4921   [(set_attr "length" "4,4,6,2,2,6,4,4")
4922    (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4923    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4924 )
4925
4926 (define_expand "movsi"
4927   [(set (match_operand:SI 0 "general_operand" "")
4928         (match_operand:SI 1 "general_operand" ""))]
4929   "TARGET_EITHER"
4930   "
4931   {
4932   rtx base, offset, tmp;
4933
4934   if (TARGET_32BIT)
4935     {
4936       /* Everything except mem = const or mem = mem can be done easily.  */
4937       if (GET_CODE (operands[0]) == MEM)
4938         operands[1] = force_reg (SImode, operands[1]);
4939       if (arm_general_register_operand (operands[0], SImode)
4940           && GET_CODE (operands[1]) == CONST_INT
4941           && !(const_ok_for_arm (INTVAL (operands[1]))
4942                || const_ok_for_arm (~INTVAL (operands[1]))))
4943         {
4944            arm_split_constant (SET, SImode, NULL_RTX,
4945                                INTVAL (operands[1]), operands[0], NULL_RTX,
4946                                optimize && can_create_pseudo_p ());
4947           DONE;
4948         }
4949
4950       if (TARGET_USE_MOVT && !target_word_relocations
4951           && GET_CODE (operands[1]) == SYMBOL_REF
4952           && !flag_pic && !arm_tls_referenced_p (operands[1]))
4953         {
4954           arm_emit_movpair (operands[0], operands[1]);
4955           DONE;
4956         }
4957     }
4958   else /* TARGET_THUMB1...  */
4959     {
4960       if (can_create_pseudo_p ())
4961         {
4962           if (GET_CODE (operands[0]) != REG)
4963             operands[1] = force_reg (SImode, operands[1]);
4964         }
4965     }
4966
4967   if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
4968     {
4969       split_const (operands[1], &base, &offset);
4970       if (GET_CODE (base) == SYMBOL_REF
4971           && !offset_within_block_p (base, INTVAL (offset)))
4972         {
4973           tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
4974           emit_move_insn (tmp, base);
4975           emit_insn (gen_addsi3 (operands[0], tmp, offset));
4976           DONE;
4977         }
4978     }
4979
4980   /* Recognize the case where operand[1] is a reference to thread-local
4981      data and load its address to a register.  */
4982   if (arm_tls_referenced_p (operands[1]))
4983     {
4984       rtx tmp = operands[1];
4985       rtx addend = NULL;
4986
4987       if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
4988         {
4989           addend = XEXP (XEXP (tmp, 0), 1);
4990           tmp = XEXP (XEXP (tmp, 0), 0);
4991         }
4992
4993       gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
4994       gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
4995
4996       tmp = legitimize_tls_address (tmp,
4997                                     !can_create_pseudo_p () ? operands[0] : 0);
4998       if (addend)
4999         {
5000           tmp = gen_rtx_PLUS (SImode, tmp, addend);
5001           tmp = force_operand (tmp, operands[0]);
5002         }
5003       operands[1] = tmp;
5004     }
5005   else if (flag_pic
5006            && (CONSTANT_P (operands[1])
5007                || symbol_mentioned_p (operands[1])
5008                || label_mentioned_p (operands[1])))
5009       operands[1] = legitimize_pic_address (operands[1], SImode,
5010                                             (!can_create_pseudo_p ()
5011                                              ? operands[0]
5012                                              : 0));
5013   }
5014   "
5015 )
5016
5017 ;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5018 ;; LO_SUM adds in the high bits.  Fortunately these are opaque operations
5019 ;; so this does not matter.
5020 (define_insn "*arm_movt"
5021   [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5022         (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5023                    (match_operand:SI 2 "general_operand"      "i")))]
5024   "TARGET_32BIT"
5025   "movt%?\t%0, #:upper16:%c2"
5026   [(set_attr "predicable" "yes")
5027    (set_attr "length" "4")]
5028 )
5029
5030 (define_insn "*arm_movsi_insn"
5031   [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
5032         (match_operand:SI 1 "general_operand"      "rk, I,K,j,mi,rk"))]
5033   "TARGET_ARM && ! TARGET_IWMMXT
5034    && !(TARGET_HARD_FLOAT && TARGET_VFP)
5035    && (   register_operand (operands[0], SImode)
5036        || register_operand (operands[1], SImode))"
5037   "@
5038    mov%?\\t%0, %1
5039    mov%?\\t%0, %1
5040    mvn%?\\t%0, #%B1
5041    movw%?\\t%0, %1
5042    ldr%?\\t%0, %1
5043    str%?\\t%1, %0"
5044   [(set_attr "type" "*,*,*,*,load1,store1")
5045    (set_attr "predicable" "yes")
5046    (set_attr "pool_range" "*,*,*,*,4096,*")
5047    (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
5048 )
5049
5050 (define_split
5051   [(set (match_operand:SI 0 "arm_general_register_operand" "")
5052         (match_operand:SI 1 "const_int_operand" ""))]
5053   "TARGET_32BIT
5054   && (!(const_ok_for_arm (INTVAL (operands[1]))
5055         || const_ok_for_arm (~INTVAL (operands[1]))))"
5056   [(clobber (const_int 0))]
5057   "
5058   arm_split_constant (SET, SImode, NULL_RTX, 
5059                       INTVAL (operands[1]), operands[0], NULL_RTX, 0);
5060   DONE;
5061   "
5062 )
5063
5064 (define_insn "*thumb1_movsi_insn"
5065   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lhk")
5066         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lhk"))]
5067   "TARGET_THUMB1
5068    && (   register_operand (operands[0], SImode) 
5069        || register_operand (operands[1], SImode))"
5070   "@
5071    mov  %0, %1
5072    mov  %0, %1
5073    #
5074    #
5075    ldmia\\t%1, {%0}
5076    stmia\\t%0, {%1}
5077    ldr\\t%0, %1
5078    str\\t%1, %0
5079    mov\\t%0, %1"
5080   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
5081    (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
5082    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
5083 )
5084
5085 (define_split 
5086   [(set (match_operand:SI 0 "register_operand" "")
5087         (match_operand:SI 1 "const_int_operand" ""))]
5088   "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
5089   [(set (match_dup 0) (match_dup 1))
5090    (set (match_dup 0) (neg:SI (match_dup 0)))]
5091   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
5092 )
5093
5094 (define_split 
5095   [(set (match_operand:SI 0 "register_operand" "")
5096         (match_operand:SI 1 "const_int_operand" ""))]
5097   "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
5098   [(set (match_dup 0) (match_dup 1))
5099    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
5100   "
5101   {
5102     unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu;
5103     unsigned HOST_WIDE_INT mask = 0xff;
5104     int i;
5105     
5106     for (i = 0; i < 25; i++)
5107       if ((val & (mask << i)) == val)
5108         break;
5109
5110     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
5111     if (i == 0)
5112       FAIL;
5113
5114     operands[1] = GEN_INT (val >> i);
5115     operands[2] = GEN_INT (i);
5116   }"
5117 )
5118
5119 ;; When generating pic, we need to load the symbol offset into a register.
5120 ;; So that the optimizer does not confuse this with a normal symbol load
5121 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
5122 ;; since that is the only type of relocation we can use.
5123
5124 ;; The rather odd constraints on the following are to force reload to leave
5125 ;; the insn alone, and to force the minipool generation pass to then move
5126 ;; the GOT symbol to memory.
5127
5128 (define_insn "pic_load_addr_32bit"
5129   [(set (match_operand:SI 0 "s_register_operand" "=r")
5130         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
5131   "TARGET_32BIT && flag_pic"
5132   "ldr%?\\t%0, %1"
5133   [(set_attr "type" "load1")
5134    (set_attr "pool_range" "4096")
5135    (set (attr "neg_pool_range")
5136         (if_then_else (eq_attr "is_thumb" "no")
5137                       (const_int 4084)
5138                       (const_int 0)))]
5139 )
5140
5141 (define_insn "pic_load_addr_thumb1"
5142   [(set (match_operand:SI 0 "s_register_operand" "=l")
5143         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
5144   "TARGET_THUMB1 && flag_pic"
5145   "ldr\\t%0, %1"
5146   [(set_attr "type" "load1")
5147    (set (attr "pool_range") (const_int 1024))]
5148 )
5149
5150 (define_insn "pic_add_dot_plus_four"
5151   [(set (match_operand:SI 0 "register_operand" "=r")
5152         (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5153                     (const_int 4)
5154                     (match_operand 2 "" "")]
5155                    UNSPEC_PIC_BASE))]
5156   "TARGET_THUMB"
5157   "*
5158   (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5159                                      INTVAL (operands[2]));
5160   return \"add\\t%0, %|pc\";
5161   "
5162   [(set_attr "length" "2")]
5163 )
5164
5165 (define_insn "pic_add_dot_plus_eight"
5166   [(set (match_operand:SI 0 "register_operand" "=r")
5167         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5168                     (const_int 8)
5169                     (match_operand 2 "" "")]
5170                    UNSPEC_PIC_BASE))]
5171   "TARGET_ARM"
5172   "*
5173     (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5174                                        INTVAL (operands[2]));
5175     return \"add%?\\t%0, %|pc, %1\";
5176   "
5177   [(set_attr "predicable" "yes")]
5178 )
5179
5180 (define_insn "tls_load_dot_plus_eight"
5181   [(set (match_operand:SI 0 "register_operand" "=r")
5182         (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5183                             (const_int 8)
5184                             (match_operand 2 "" "")]
5185                            UNSPEC_PIC_BASE)))]
5186   "TARGET_ARM"
5187   "*
5188     (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5189                                        INTVAL (operands[2]));
5190     return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5191   "
5192   [(set_attr "predicable" "yes")]
5193 )
5194
5195 ;; PIC references to local variables can generate pic_add_dot_plus_eight
5196 ;; followed by a load.  These sequences can be crunched down to
5197 ;; tls_load_dot_plus_eight by a peephole.
5198
5199 (define_peephole2
5200   [(set (match_operand:SI 0 "register_operand" "")
5201         (unspec:SI [(match_operand:SI 3 "register_operand" "")
5202                     (const_int 8)
5203                     (match_operand 1 "" "")]
5204                    UNSPEC_PIC_BASE))
5205    (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
5206   "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
5207   [(set (match_dup 2)
5208         (mem:SI (unspec:SI [(match_dup 3)
5209                             (const_int 8)
5210                             (match_dup 1)]
5211                            UNSPEC_PIC_BASE)))]
5212   ""
5213 )
5214
5215 (define_insn "pic_offset_arm"
5216   [(set (match_operand:SI 0 "register_operand" "=r")
5217         (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5218                          (unspec:SI [(match_operand:SI 2 "" "X")]
5219                                     UNSPEC_PIC_OFFSET))))]
5220   "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5221   "ldr%?\\t%0, [%1,%2]"
5222   [(set_attr "type" "load1")]
5223 )
5224
5225 (define_expand "builtin_setjmp_receiver"
5226   [(label_ref (match_operand 0 "" ""))]
5227   "flag_pic"
5228   "
5229 {
5230   /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5231      register.  */
5232   if (arm_pic_register != INVALID_REGNUM)
5233     arm_load_pic_register (1UL << 3);
5234   DONE;
5235 }")
5236
5237 ;; If copying one reg to another we can set the condition codes according to
5238 ;; its value.  Such a move is common after a return from subroutine and the
5239 ;; result is being tested against zero.
5240
5241 (define_insn "*movsi_compare0"
5242   [(set (reg:CC CC_REGNUM)
5243         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5244                     (const_int 0)))
5245    (set (match_operand:SI 0 "s_register_operand" "=r,r")
5246         (match_dup 1))]
5247   "TARGET_32BIT"
5248   "@
5249    cmp%?\\t%0, #0
5250    sub%.\\t%0, %1, #0"
5251   [(set_attr "conds" "set")]
5252 )
5253
5254 ;; Subroutine to store a half word from a register into memory.
5255 ;; Operand 0 is the source register (HImode)
5256 ;; Operand 1 is the destination address in a register (SImode)
5257
5258 ;; In both this routine and the next, we must be careful not to spill
5259 ;; a memory address of reg+large_const into a separate PLUS insn, since this
5260 ;; can generate unrecognizable rtl.
5261
5262 (define_expand "storehi"
5263   [;; store the low byte
5264    (set (match_operand 1 "" "") (match_dup 3))
5265    ;; extract the high byte
5266    (set (match_dup 2)
5267         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
5268    ;; store the high byte
5269    (set (match_dup 4) (match_dup 5))]
5270   "TARGET_ARM"
5271   "
5272   {
5273     rtx op1 = operands[1];
5274     rtx addr = XEXP (op1, 0);
5275     enum rtx_code code = GET_CODE (addr);
5276
5277     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5278         || code == MINUS)
5279       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
5280
5281     operands[4] = adjust_address (op1, QImode, 1);
5282     operands[1] = adjust_address (operands[1], QImode, 0);
5283     operands[3] = gen_lowpart (QImode, operands[0]);
5284     operands[0] = gen_lowpart (SImode, operands[0]);
5285     operands[2] = gen_reg_rtx (SImode);
5286     operands[5] = gen_lowpart (QImode, operands[2]);
5287   }"
5288 )
5289
5290 (define_expand "storehi_bigend"
5291   [(set (match_dup 4) (match_dup 3))
5292    (set (match_dup 2)
5293         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
5294    (set (match_operand 1 "" "") (match_dup 5))]
5295   "TARGET_ARM"
5296   "
5297   {
5298     rtx op1 = operands[1];
5299     rtx addr = XEXP (op1, 0);
5300     enum rtx_code code = GET_CODE (addr);
5301
5302     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5303         || code == MINUS)
5304       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
5305
5306     operands[4] = adjust_address (op1, QImode, 1);
5307     operands[1] = adjust_address (operands[1], QImode, 0);
5308     operands[3] = gen_lowpart (QImode, operands[0]);
5309     operands[0] = gen_lowpart (SImode, operands[0]);
5310     operands[2] = gen_reg_rtx (SImode);
5311     operands[5] = gen_lowpart (QImode, operands[2]);
5312   }"
5313 )
5314
5315 ;; Subroutine to store a half word integer constant into memory.
5316 (define_expand "storeinthi"
5317   [(set (match_operand 0 "" "")
5318         (match_operand 1 "" ""))
5319    (set (match_dup 3) (match_dup 2))]
5320   "TARGET_ARM"
5321   "
5322   {
5323     HOST_WIDE_INT value = INTVAL (operands[1]);
5324     rtx addr = XEXP (operands[0], 0);
5325     rtx op0 = operands[0];
5326     enum rtx_code code = GET_CODE (addr);
5327
5328     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5329         || code == MINUS)
5330       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
5331
5332     operands[1] = gen_reg_rtx (SImode);
5333     if (BYTES_BIG_ENDIAN)
5334       {
5335         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5336         if ((value & 255) == ((value >> 8) & 255))
5337           operands[2] = operands[1];
5338         else
5339           {
5340             operands[2] = gen_reg_rtx (SImode);
5341             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5342           }
5343       }
5344     else
5345       {
5346         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5347         if ((value & 255) == ((value >> 8) & 255))
5348           operands[2] = operands[1];
5349         else
5350           {
5351             operands[2] = gen_reg_rtx (SImode);
5352             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5353           }
5354       }
5355
5356     operands[3] = adjust_address (op0, QImode, 1);
5357     operands[0] = adjust_address (operands[0], QImode, 0);
5358     operands[2] = gen_lowpart (QImode, operands[2]);
5359     operands[1] = gen_lowpart (QImode, operands[1]);
5360   }"
5361 )
5362
5363 (define_expand "storehi_single_op"
5364   [(set (match_operand:HI 0 "memory_operand" "")
5365         (match_operand:HI 1 "general_operand" ""))]
5366   "TARGET_32BIT && arm_arch4"
5367   "
5368   if (!s_register_operand (operands[1], HImode))
5369     operands[1] = copy_to_mode_reg (HImode, operands[1]);
5370   "
5371 )
5372
5373 (define_expand "movhi"
5374   [(set (match_operand:HI 0 "general_operand" "")
5375         (match_operand:HI 1 "general_operand" ""))]
5376   "TARGET_EITHER"
5377   "
5378   if (TARGET_ARM)
5379     {
5380       if (can_create_pseudo_p ())
5381         {
5382           if (GET_CODE (operands[0]) == MEM)
5383             {
5384               if (arm_arch4)
5385                 {
5386                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5387                   DONE;
5388                 }
5389               if (GET_CODE (operands[1]) == CONST_INT)
5390                 emit_insn (gen_storeinthi (operands[0], operands[1]));
5391               else
5392                 {
5393                   if (GET_CODE (operands[1]) == MEM)
5394                     operands[1] = force_reg (HImode, operands[1]);
5395                   if (BYTES_BIG_ENDIAN)
5396                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
5397                   else
5398                    emit_insn (gen_storehi (operands[1], operands[0]));
5399                 }
5400               DONE;
5401             }
5402           /* Sign extend a constant, and keep it in an SImode reg.  */
5403           else if (GET_CODE (operands[1]) == CONST_INT)
5404             {
5405               rtx reg = gen_reg_rtx (SImode);
5406               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5407
5408               /* If the constant is already valid, leave it alone.  */
5409               if (!const_ok_for_arm (val))
5410                 {
5411                   /* If setting all the top bits will make the constant 
5412                      loadable in a single instruction, then set them.  
5413                      Otherwise, sign extend the number.  */
5414
5415                   if (const_ok_for_arm (~(val | ~0xffff)))
5416                     val |= ~0xffff;
5417                   else if (val & 0x8000)
5418                     val |= ~0xffff;
5419                 }
5420
5421               emit_insn (gen_movsi (reg, GEN_INT (val)));
5422               operands[1] = gen_lowpart (HImode, reg);
5423             }
5424           else if (arm_arch4 && optimize && can_create_pseudo_p ()
5425                    && GET_CODE (operands[1]) == MEM)
5426             {
5427               rtx reg = gen_reg_rtx (SImode);
5428
5429               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5430               operands[1] = gen_lowpart (HImode, reg);
5431             }
5432           else if (!arm_arch4)
5433             {
5434               if (GET_CODE (operands[1]) == MEM)
5435                 {
5436                   rtx base;
5437                   rtx offset = const0_rtx;
5438                   rtx reg = gen_reg_rtx (SImode);
5439
5440                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
5441                        || (GET_CODE (base) == PLUS
5442                            && (GET_CODE (offset = XEXP (base, 1))
5443                                == CONST_INT)
5444                            && ((INTVAL(offset) & 1) != 1)
5445                            && GET_CODE (base = XEXP (base, 0)) == REG))
5446                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
5447                     {
5448                       rtx new_rtx;
5449
5450                       new_rtx = widen_memory_access (operands[1], SImode,
5451                                                      ((INTVAL (offset) & ~3)
5452                                                       - INTVAL (offset)));
5453                       emit_insn (gen_movsi (reg, new_rtx));
5454                       if (((INTVAL (offset) & 2) != 0)
5455                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
5456                         {
5457                           rtx reg2 = gen_reg_rtx (SImode);
5458
5459                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
5460                           reg = reg2;
5461                         }
5462                     }
5463                   else
5464                     emit_insn (gen_movhi_bytes (reg, operands[1]));
5465
5466                   operands[1] = gen_lowpart (HImode, reg);
5467                }
5468            }
5469         }
5470       /* Handle loading a large integer during reload.  */
5471       else if (GET_CODE (operands[1]) == CONST_INT
5472                && !const_ok_for_arm (INTVAL (operands[1]))
5473                && !const_ok_for_arm (~INTVAL (operands[1])))
5474         {
5475           /* Writing a constant to memory needs a scratch, which should
5476              be handled with SECONDARY_RELOADs.  */
5477           gcc_assert (GET_CODE (operands[0]) == REG);
5478
5479           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5480           emit_insn (gen_movsi (operands[0], operands[1]));
5481           DONE;
5482        }
5483     }
5484   else if (TARGET_THUMB2)
5485     {
5486       /* Thumb-2 can do everything except mem=mem and mem=const easily.  */
5487       if (can_create_pseudo_p ())
5488         {
5489           if (GET_CODE (operands[0]) != REG)
5490             operands[1] = force_reg (HImode, operands[1]);
5491           /* Zero extend a constant, and keep it in an SImode reg.  */
5492           else if (GET_CODE (operands[1]) == CONST_INT)
5493             {
5494               rtx reg = gen_reg_rtx (SImode);
5495               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5496
5497               emit_insn (gen_movsi (reg, GEN_INT (val)));
5498               operands[1] = gen_lowpart (HImode, reg);
5499             }
5500         }
5501     }
5502   else /* TARGET_THUMB1 */
5503     {
5504       if (can_create_pseudo_p ())
5505         {
5506           if (GET_CODE (operands[1]) == CONST_INT)
5507             {
5508               rtx reg = gen_reg_rtx (SImode);
5509
5510               emit_insn (gen_movsi (reg, operands[1]));
5511               operands[1] = gen_lowpart (HImode, reg);
5512             }
5513
5514           /* ??? We shouldn't really get invalid addresses here, but this can
5515              happen if we are passed a SP (never OK for HImode/QImode) or 
5516              virtual register (also rejected as illegitimate for HImode/QImode)
5517              relative address.  */
5518           /* ??? This should perhaps be fixed elsewhere, for instance, in
5519              fixup_stack_1, by checking for other kinds of invalid addresses,
5520              e.g. a bare reference to a virtual register.  This may confuse the
5521              alpha though, which must handle this case differently.  */
5522           if (GET_CODE (operands[0]) == MEM
5523               && !memory_address_p (GET_MODE (operands[0]),
5524                                     XEXP (operands[0], 0)))
5525             operands[0]
5526               = replace_equiv_address (operands[0],
5527                                        copy_to_reg (XEXP (operands[0], 0)));
5528    
5529           if (GET_CODE (operands[1]) == MEM
5530               && !memory_address_p (GET_MODE (operands[1]),
5531                                     XEXP (operands[1], 0)))
5532             operands[1]
5533               = replace_equiv_address (operands[1],
5534                                        copy_to_reg (XEXP (operands[1], 0)));
5535
5536           if (GET_CODE (operands[1]) == MEM && optimize > 0)
5537             {
5538               rtx reg = gen_reg_rtx (SImode);
5539
5540               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5541               operands[1] = gen_lowpart (HImode, reg);
5542             }
5543
5544           if (GET_CODE (operands[0]) == MEM)
5545             operands[1] = force_reg (HImode, operands[1]);
5546         }
5547       else if (GET_CODE (operands[1]) == CONST_INT
5548                 && !satisfies_constraint_I (operands[1]))
5549         {
5550           /* Handle loading a large integer during reload.  */
5551
5552           /* Writing a constant to memory needs a scratch, which should
5553              be handled with SECONDARY_RELOADs.  */
5554           gcc_assert (GET_CODE (operands[0]) == REG);
5555
5556           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5557           emit_insn (gen_movsi (operands[0], operands[1]));
5558           DONE;
5559         }
5560     }
5561   "
5562 )
5563
5564 (define_insn "*thumb1_movhi_insn"
5565   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5566         (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
5567   "TARGET_THUMB1
5568    && (   register_operand (operands[0], HImode)
5569        || register_operand (operands[1], HImode))"
5570   "*
5571   switch (which_alternative)
5572     {
5573     case 0: return \"add        %0, %1, #0\";
5574     case 2: return \"strh       %1, %0\";
5575     case 3: return \"mov        %0, %1\";
5576     case 4: return \"mov        %0, %1\";
5577     case 5: return \"mov        %0, %1\";
5578     default: gcc_unreachable ();
5579     case 1:
5580       /* The stack pointer can end up being taken as an index register.
5581           Catch this case here and deal with it.  */
5582       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
5583           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
5584           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
5585         {
5586           rtx ops[2];
5587           ops[0] = operands[0];
5588           ops[1] = XEXP (XEXP (operands[1], 0), 0);
5589       
5590           output_asm_insn (\"mov        %0, %1\", ops);
5591
5592           XEXP (XEXP (operands[1], 0), 0) = operands[0];
5593     
5594         }
5595       return \"ldrh     %0, %1\";
5596     }"
5597   [(set_attr "length" "2,4,2,2,2,2")
5598    (set_attr "type" "*,load1,store1,*,*,*")]
5599 )
5600
5601
5602 (define_expand "movhi_bytes"
5603   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
5604    (set (match_dup 3)
5605         (zero_extend:SI (match_dup 6)))
5606    (set (match_operand:SI 0 "" "")
5607          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
5608   "TARGET_ARM"
5609   "
5610   {
5611     rtx mem1, mem2;
5612     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5613
5614     mem1 = change_address (operands[1], QImode, addr);
5615     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
5616     operands[0] = gen_lowpart (SImode, operands[0]);
5617     operands[1] = mem1;
5618     operands[2] = gen_reg_rtx (SImode);
5619     operands[3] = gen_reg_rtx (SImode);
5620     operands[6] = mem2;
5621
5622     if (BYTES_BIG_ENDIAN)
5623       {
5624         operands[4] = operands[2];
5625         operands[5] = operands[3];
5626       }
5627     else
5628       {
5629         operands[4] = operands[3];
5630         operands[5] = operands[2];
5631       }
5632   }"
5633 )
5634
5635 (define_expand "movhi_bigend"
5636   [(set (match_dup 2)
5637         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
5638                    (const_int 16)))
5639    (set (match_dup 3)
5640         (ashiftrt:SI (match_dup 2) (const_int 16)))
5641    (set (match_operand:HI 0 "s_register_operand" "")
5642         (match_dup 4))]
5643   "TARGET_ARM"
5644   "
5645   operands[2] = gen_reg_rtx (SImode);
5646   operands[3] = gen_reg_rtx (SImode);
5647   operands[4] = gen_lowpart (HImode, operands[3]);
5648   "
5649 )
5650
5651 ;; Pattern to recognize insn generated default case above
5652 (define_insn "*movhi_insn_arch4"
5653   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
5654         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
5655   "TARGET_ARM
5656    && arm_arch4
5657    && (GET_CODE (operands[1]) != CONST_INT
5658        || const_ok_for_arm (INTVAL (operands[1]))
5659        || const_ok_for_arm (~INTVAL (operands[1])))"
5660   "@
5661    mov%?\\t%0, %1\\t%@ movhi
5662    mvn%?\\t%0, #%B1\\t%@ movhi
5663    str%(h%)\\t%1, %0\\t%@ movhi
5664    ldr%(h%)\\t%0, %1\\t%@ movhi"
5665   [(set_attr "type" "*,*,store1,load1")
5666    (set_attr "predicable" "yes")
5667    (set_attr "pool_range" "*,*,*,256")
5668    (set_attr "neg_pool_range" "*,*,*,244")]
5669 )
5670
5671 (define_insn "*movhi_bytes"
5672   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
5673         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
5674   "TARGET_ARM"
5675   "@
5676    mov%?\\t%0, %1\\t%@ movhi
5677    mvn%?\\t%0, #%B1\\t%@ movhi"
5678   [(set_attr "predicable" "yes")]
5679 )
5680
5681 (define_expand "thumb_movhi_clobber"
5682   [(set (match_operand:HI     0 "memory_operand"   "")
5683         (match_operand:HI     1 "register_operand" ""))
5684    (clobber (match_operand:DI 2 "register_operand" ""))]
5685   "TARGET_THUMB1"
5686   "
5687   if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
5688       && REGNO (operands[1]) <= LAST_LO_REGNUM)
5689     {
5690       emit_insn (gen_movhi (operands[0], operands[1]));
5691       DONE;
5692     }
5693   /* XXX Fixme, need to handle other cases here as well.  */
5694   gcc_unreachable ();
5695   "
5696 )
5697         
5698 ;; We use a DImode scratch because we may occasionally need an additional
5699 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
5700 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
5701 (define_expand "reload_outhi"
5702   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
5703               (match_operand:HI 1 "s_register_operand"        "r")
5704               (match_operand:DI 2 "s_register_operand"        "=&l")])]
5705   "TARGET_EITHER"
5706   "if (TARGET_ARM)
5707      arm_reload_out_hi (operands);
5708    else
5709      thumb_reload_out_hi (operands);
5710   DONE;
5711   "
5712 )
5713
5714 (define_expand "reload_inhi"
5715   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
5716               (match_operand:HI 1 "arm_reload_memory_operand" "o")
5717               (match_operand:DI 2 "s_register_operand" "=&r")])]
5718   "TARGET_EITHER"
5719   "
5720   if (TARGET_ARM)
5721     arm_reload_in_hi (operands);
5722   else
5723     thumb_reload_out_hi (operands);
5724   DONE;
5725 ")
5726
5727 (define_expand "movqi"
5728   [(set (match_operand:QI 0 "general_operand" "")
5729         (match_operand:QI 1 "general_operand" ""))]
5730   "TARGET_EITHER"
5731   "
5732   /* Everything except mem = const or mem = mem can be done easily */
5733
5734   if (can_create_pseudo_p ())
5735     {
5736       if (GET_CODE (operands[1]) == CONST_INT)
5737         {
5738           rtx reg = gen_reg_rtx (SImode);
5739
5740           /* For thumb we want an unsigned immediate, then we are more likely 
5741              to be able to use a movs insn.  */
5742           if (TARGET_THUMB)
5743             operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
5744
5745           emit_insn (gen_movsi (reg, operands[1]));
5746           operands[1] = gen_lowpart (QImode, reg);
5747         }
5748
5749       if (TARGET_THUMB)
5750         {
5751           /* ??? We shouldn't really get invalid addresses here, but this can
5752              happen if we are passed a SP (never OK for HImode/QImode) or
5753              virtual register (also rejected as illegitimate for HImode/QImode)
5754              relative address.  */
5755           /* ??? This should perhaps be fixed elsewhere, for instance, in
5756              fixup_stack_1, by checking for other kinds of invalid addresses,
5757              e.g. a bare reference to a virtual register.  This may confuse the
5758              alpha though, which must handle this case differently.  */
5759           if (GET_CODE (operands[0]) == MEM
5760               && !memory_address_p (GET_MODE (operands[0]),
5761                                      XEXP (operands[0], 0)))
5762             operands[0]
5763               = replace_equiv_address (operands[0],
5764                                        copy_to_reg (XEXP (operands[0], 0)));
5765           if (GET_CODE (operands[1]) == MEM
5766               && !memory_address_p (GET_MODE (operands[1]),
5767                                     XEXP (operands[1], 0)))
5768              operands[1]
5769                = replace_equiv_address (operands[1],
5770                                         copy_to_reg (XEXP (operands[1], 0)));
5771         }
5772
5773       if (GET_CODE (operands[1]) == MEM && optimize > 0)
5774         {
5775           rtx reg = gen_reg_rtx (SImode);
5776
5777           emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5778           operands[1] = gen_lowpart (QImode, reg);
5779         }
5780
5781       if (GET_CODE (operands[0]) == MEM)
5782         operands[1] = force_reg (QImode, operands[1]);
5783     }
5784   else if (TARGET_THUMB
5785            && GET_CODE (operands[1]) == CONST_INT
5786            && !satisfies_constraint_I (operands[1]))
5787     {
5788       /* Handle loading a large integer during reload.  */
5789
5790       /* Writing a constant to memory needs a scratch, which should
5791          be handled with SECONDARY_RELOADs.  */
5792       gcc_assert (GET_CODE (operands[0]) == REG);
5793
5794       operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5795       emit_insn (gen_movsi (operands[0], operands[1]));
5796       DONE;
5797     }
5798   "
5799 )
5800
5801
5802 (define_insn "*arm_movqi_insn"
5803   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5804         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5805   "TARGET_32BIT
5806    && (   register_operand (operands[0], QImode)
5807        || register_operand (operands[1], QImode))"
5808   "@
5809    mov%?\\t%0, %1
5810    mvn%?\\t%0, #%B1
5811    ldr%(b%)\\t%0, %1
5812    str%(b%)\\t%1, %0"
5813   [(set_attr "type" "*,*,load1,store1")
5814    (set_attr "predicable" "yes")]
5815 )
5816
5817 (define_insn "*thumb1_movqi_insn"
5818   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5819         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
5820   "TARGET_THUMB1
5821    && (   register_operand (operands[0], QImode)
5822        || register_operand (operands[1], QImode))"
5823   "@
5824    add\\t%0, %1, #0
5825    ldrb\\t%0, %1
5826    strb\\t%1, %0
5827    mov\\t%0, %1
5828    mov\\t%0, %1
5829    mov\\t%0, %1"
5830   [(set_attr "length" "2")
5831    (set_attr "type" "*,load1,store1,*,*,*")
5832    (set_attr "pool_range" "*,32,*,*,*,*")]
5833 )
5834
5835 ;; HFmode moves
5836 (define_expand "movhf"
5837   [(set (match_operand:HF 0 "general_operand" "")
5838         (match_operand:HF 1 "general_operand" ""))]
5839   "TARGET_EITHER"
5840   "
5841   if (TARGET_32BIT)
5842     {
5843       if (GET_CODE (operands[0]) == MEM)
5844         operands[1] = force_reg (HFmode, operands[1]);
5845     }
5846   else /* TARGET_THUMB1 */
5847     {
5848       if (can_create_pseudo_p ())
5849         {
5850            if (GET_CODE (operands[0]) != REG)
5851              operands[1] = force_reg (HFmode, operands[1]);
5852         }
5853     }
5854   "
5855 )
5856
5857 (define_insn "*arm32_movhf"
5858   [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
5859         (match_operand:HF 1 "general_operand"      " m,r,r,F"))]
5860   "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16)
5861    && (   s_register_operand (operands[0], HFmode)
5862        || s_register_operand (operands[1], HFmode))"
5863   "*
5864   switch (which_alternative)
5865     {
5866     case 0:     /* ARM register from memory */
5867       return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
5868     case 1:     /* memory from ARM register */
5869       return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
5870     case 2:     /* ARM register from ARM register */
5871       return \"mov%?\\t%0, %1\\t%@ __fp16\";
5872     case 3:     /* ARM register from constant */
5873       {
5874         REAL_VALUE_TYPE r;
5875         long bits;
5876         rtx ops[4];
5877
5878         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
5879         bits = real_to_target (NULL, &r, HFmode);
5880         ops[0] = operands[0];
5881         ops[1] = GEN_INT (bits);
5882         ops[2] = GEN_INT (bits & 0xff00);
5883         ops[3] = GEN_INT (bits & 0x00ff);
5884
5885         if (arm_arch_thumb2)
5886           output_asm_insn (\"movw%?\\t%0, %1\", ops);
5887         else
5888           output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
5889         return \"\";
5890        }
5891     default:
5892       gcc_unreachable ();
5893     }
5894   "
5895   [(set_attr "conds" "unconditional")
5896    (set_attr "type" "load1,store1,*,*")
5897    (set_attr "length" "4,4,4,8")
5898    (set_attr "predicable" "yes")
5899    ]
5900 )
5901
5902 (define_insn "*thumb1_movhf"
5903   [(set (match_operand:HF     0 "nonimmediate_operand" "=l,l,m,*r,*h")
5904         (match_operand:HF     1 "general_operand"      "l,mF,l,*h,*r"))]
5905   "TARGET_THUMB1
5906    && (   s_register_operand (operands[0], HFmode) 
5907        || s_register_operand (operands[1], HFmode))"
5908   "*
5909   switch (which_alternative)
5910     {
5911     case 1:
5912       {
5913         rtx addr;
5914         gcc_assert (GET_CODE(operands[1]) == MEM);
5915         addr = XEXP (operands[1], 0);
5916         if (GET_CODE (addr) == LABEL_REF
5917             || (GET_CODE (addr) == CONST
5918                 && GET_CODE (XEXP (addr, 0)) == PLUS
5919                 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF
5920                 && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT))
5921           {
5922             /* Constant pool entry.  */
5923             return \"ldr\\t%0, %1\";
5924           }
5925         return \"ldrh\\t%0, %1\";
5926       }
5927     case 2: return \"strh\\t%1, %0\";
5928     default: return \"mov\\t%0, %1\";
5929     }
5930   "
5931   [(set_attr "length" "2")
5932    (set_attr "type" "*,load1,store1,*,*")
5933    (set_attr "pool_range" "*,1020,*,*,*")]
5934 )
5935
5936 (define_expand "movsf"
5937   [(set (match_operand:SF 0 "general_operand" "")
5938         (match_operand:SF 1 "general_operand" ""))]
5939   "TARGET_EITHER"
5940   "
5941   if (TARGET_32BIT)
5942     {
5943       if (GET_CODE (operands[0]) == MEM)
5944         operands[1] = force_reg (SFmode, operands[1]);
5945     }
5946   else /* TARGET_THUMB1 */
5947     {
5948       if (can_create_pseudo_p ())
5949         {
5950            if (GET_CODE (operands[0]) != REG)
5951              operands[1] = force_reg (SFmode, operands[1]);
5952         }
5953     }
5954   "
5955 )
5956
5957 ;; Transform a floating-point move of a constant into a core register into
5958 ;; an SImode operation.
5959 (define_split
5960   [(set (match_operand:SF 0 "arm_general_register_operand" "")
5961         (match_operand:SF 1 "immediate_operand" ""))]
5962   "TARGET_EITHER
5963    && reload_completed
5964    && GET_CODE (operands[1]) == CONST_DOUBLE"
5965   [(set (match_dup 2) (match_dup 3))]
5966   "
5967   operands[2] = gen_lowpart (SImode, operands[0]);
5968   operands[3] = gen_lowpart (SImode, operands[1]);
5969   if (operands[2] == 0 || operands[3] == 0)
5970     FAIL;
5971   "
5972 )
5973
5974 (define_insn "*arm_movsf_soft_insn"
5975   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5976         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
5977   "TARGET_ARM
5978    && TARGET_SOFT_FLOAT
5979    && (GET_CODE (operands[0]) != MEM
5980        || register_operand (operands[1], SFmode))"
5981   "@
5982    mov%?\\t%0, %1
5983    ldr%?\\t%0, %1\\t%@ float
5984    str%?\\t%1, %0\\t%@ float"
5985   [(set_attr "length" "4,4,4")
5986    (set_attr "predicable" "yes")
5987    (set_attr "type" "*,load1,store1")
5988    (set_attr "pool_range" "*,4096,*")
5989    (set_attr "neg_pool_range" "*,4084,*")]
5990 )
5991
5992 ;;; ??? This should have alternatives for constants.
5993 (define_insn "*thumb1_movsf_insn"
5994   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5995         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5996   "TARGET_THUMB1
5997    && (   register_operand (operands[0], SFmode) 
5998        || register_operand (operands[1], SFmode))"
5999   "@
6000    add\\t%0, %1, #0
6001    ldmia\\t%1, {%0}
6002    stmia\\t%0, {%1}
6003    ldr\\t%0, %1
6004    str\\t%1, %0
6005    mov\\t%0, %1
6006    mov\\t%0, %1"
6007   [(set_attr "length" "2")
6008    (set_attr "type" "*,load1,store1,load1,store1,*,*")
6009    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
6010 )
6011
6012 (define_expand "movdf"
6013   [(set (match_operand:DF 0 "general_operand" "")
6014         (match_operand:DF 1 "general_operand" ""))]
6015   "TARGET_EITHER"
6016   "
6017   if (TARGET_32BIT)
6018     {
6019       if (GET_CODE (operands[0]) == MEM)
6020         operands[1] = force_reg (DFmode, operands[1]);
6021     }
6022   else /* TARGET_THUMB */
6023     {
6024       if (can_create_pseudo_p ())
6025         {
6026           if (GET_CODE (operands[0]) != REG)
6027             operands[1] = force_reg (DFmode, operands[1]);
6028         }
6029     }
6030   "
6031 )
6032
6033 ;; Reloading a df mode value stored in integer regs to memory can require a
6034 ;; scratch reg.
6035 (define_expand "reload_outdf"
6036   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
6037    (match_operand:DF 1 "s_register_operand" "r")
6038    (match_operand:SI 2 "s_register_operand" "=&r")]
6039   "TARGET_32BIT"
6040   "
6041   {
6042     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
6043
6044     if (code == REG)
6045       operands[2] = XEXP (operands[0], 0);
6046     else if (code == POST_INC || code == PRE_DEC)
6047       {
6048         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6049         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6050         emit_insn (gen_movdi (operands[0], operands[1]));
6051         DONE;
6052       }
6053     else if (code == PRE_INC)
6054       {
6055         rtx reg = XEXP (XEXP (operands[0], 0), 0);
6056
6057         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6058         operands[2] = reg;
6059       }
6060     else if (code == POST_DEC)
6061       operands[2] = XEXP (XEXP (operands[0], 0), 0);
6062     else
6063       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6064                              XEXP (XEXP (operands[0], 0), 1)));
6065
6066     emit_insn (gen_rtx_SET (VOIDmode,
6067                             replace_equiv_address (operands[0], operands[2]),
6068                             operands[1]));
6069
6070     if (code == POST_DEC)
6071       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6072
6073     DONE;
6074   }"
6075 )
6076
6077 (define_insn "*movdf_soft_insn"
6078   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
6079         (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
6080   "TARGET_ARM && TARGET_SOFT_FLOAT
6081    && (   register_operand (operands[0], DFmode)
6082        || register_operand (operands[1], DFmode))"
6083   "*
6084   switch (which_alternative)
6085     {
6086     case 0:
6087     case 1:
6088     case 2:
6089       return \"#\";
6090     default:
6091       return output_move_double (operands);
6092     }
6093   "
6094   [(set_attr "length" "8,12,16,8,8")
6095    (set_attr "type" "*,*,*,load2,store2")
6096    (set_attr "pool_range" "1020")
6097    (set_attr "neg_pool_range" "1008")]
6098 )
6099
6100 ;;; ??? This should have alternatives for constants.
6101 ;;; ??? This was originally identical to the movdi_insn pattern.
6102 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
6103 ;;; thumb_reorg with a memory reference.
6104 (define_insn "*thumb_movdf_insn"
6105   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
6106         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
6107   "TARGET_THUMB1
6108    && (   register_operand (operands[0], DFmode)
6109        || register_operand (operands[1], DFmode))"
6110   "*
6111   switch (which_alternative)
6112     {
6113     default:
6114     case 0:
6115       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6116         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
6117       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
6118     case 1:
6119       return \"ldmia\\t%1, {%0, %H0}\";
6120     case 2:
6121       return \"stmia\\t%0, {%1, %H1}\";
6122     case 3:
6123       return thumb_load_double_from_address (operands);
6124     case 4:
6125       operands[2] = gen_rtx_MEM (SImode,
6126                                  plus_constant (XEXP (operands[0], 0), 4));
6127       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
6128       return \"\";
6129     case 5:
6130       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6131         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
6132       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
6133     }
6134   "
6135   [(set_attr "length" "4,2,2,6,4,4")
6136    (set_attr "type" "*,load2,store2,load2,store2,*")
6137    (set_attr "pool_range" "*,*,*,1020,*,*")]
6138 )
6139
6140 (define_expand "movxf"
6141   [(set (match_operand:XF 0 "general_operand" "")
6142         (match_operand:XF 1 "general_operand" ""))]
6143   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
6144   "
6145   if (GET_CODE (operands[0]) == MEM)
6146     operands[1] = force_reg (XFmode, operands[1]);
6147   "
6148 )
6149
6150 \f
6151
6152 ;; load- and store-multiple insns
6153 ;; The arm can load/store any set of registers, provided that they are in
6154 ;; ascending order; but that is beyond GCC so stick with what it knows.
6155
6156 (define_expand "load_multiple"
6157   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6158                           (match_operand:SI 1 "" ""))
6159                      (use (match_operand:SI 2 "" ""))])]
6160   "TARGET_32BIT"
6161 {
6162   HOST_WIDE_INT offset = 0;
6163
6164   /* Support only fixed point registers.  */
6165   if (GET_CODE (operands[2]) != CONST_INT
6166       || INTVAL (operands[2]) > 14
6167       || INTVAL (operands[2]) < 2
6168       || GET_CODE (operands[1]) != MEM
6169       || GET_CODE (operands[0]) != REG
6170       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6171       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
6172     FAIL;
6173
6174   operands[3]
6175     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
6176                              force_reg (SImode, XEXP (operands[1], 0)),
6177                              TRUE, FALSE, operands[1], &offset);
6178 })
6179
6180 ;; Load multiple with write-back
6181
6182 (define_insn "*ldmsi_postinc4"
6183   [(match_parallel 0 "load_multiple_operation"
6184     [(set (match_operand:SI 1 "s_register_operand" "=r")
6185           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6186                    (const_int 16)))
6187      (set (match_operand:SI 3 "arm_hard_register_operand" "")
6188           (mem:SI (match_dup 2)))
6189      (set (match_operand:SI 4 "arm_hard_register_operand" "")
6190           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
6191      (set (match_operand:SI 5 "arm_hard_register_operand" "")
6192           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
6193      (set (match_operand:SI 6 "arm_hard_register_operand" "")
6194           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
6195   "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
6196   "ldm%(ia%)\\t%1!, {%3, %4, %5, %6}"
6197   [(set_attr "type" "load4")
6198    (set_attr "predicable" "yes")]
6199 )
6200
6201 (define_insn "*ldmsi_postinc4_thumb1"
6202   [(match_parallel 0 "load_multiple_operation"
6203     [(set (match_operand:SI 1 "s_register_operand" "=l")
6204           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6205                    (const_int 16)))
6206      (set (match_operand:SI 3 "arm_hard_register_operand" "")
6207           (mem:SI (match_dup 2)))
6208      (set (match_operand:SI 4 "arm_hard_register_operand" "")
6209           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
6210      (set (match_operand:SI 5 "arm_hard_register_operand" "")
6211           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
6212      (set (match_operand:SI 6 "arm_hard_register_operand" "")
6213           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
6214   "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
6215   "ldmia\\t%1!, {%3, %4, %5, %6}"
6216   [(set_attr "type" "load4")]
6217 )
6218
6219 (define_insn "*ldmsi_postinc3"
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 12)))
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      (set (match_operand:SI 5 "arm_hard_register_operand" "")
6229           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
6230   "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6231   "ldm%(ia%)\\t%1!, {%3, %4, %5}"
6232   [(set_attr "type" "load3")
6233    (set_attr "predicable" "yes")]
6234 )
6235
6236 (define_insn "*ldmsi_postinc2"
6237   [(match_parallel 0 "load_multiple_operation"
6238     [(set (match_operand:SI 1 "s_register_operand" "=r")
6239           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6240                    (const_int 8)))
6241      (set (match_operand:SI 3 "arm_hard_register_operand" "")
6242           (mem:SI (match_dup 2)))
6243      (set (match_operand:SI 4 "arm_hard_register_operand" "")
6244           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
6245   "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6246   "ldm%(ia%)\\t%1!, {%3, %4}"
6247   [(set_attr "type" "load2")
6248    (set_attr "predicable" "yes")]
6249 )
6250
6251 ;; Ordinary load multiple
6252
6253 (define_insn "*ldmsi4"
6254   [(match_parallel 0 "load_multiple_operation"
6255     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
6256           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
6257      (set (match_operand:SI 3 "arm_hard_register_operand" "")
6258           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
6259      (set (match_operand:SI 4 "arm_hard_register_operand" "")
6260           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
6261      (set (match_operand:SI 5 "arm_hard_register_operand" "")
6262           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
6263   "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6264   "ldm%(ia%)\\t%1, {%2, %3, %4, %5}"
6265   [(set_attr "type" "load4")
6266    (set_attr "predicable" "yes")]
6267 )
6268
6269 (define_insn "*ldmsi3"
6270   [(match_parallel 0 "load_multiple_operation"
6271     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
6272           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
6273      (set (match_operand:SI 3 "arm_hard_register_operand" "")
6274           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
6275      (set (match_operand:SI 4 "arm_hard_register_operand" "")
6276           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
6277   "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6278   "ldm%(ia%)\\t%1, {%2, %3, %4}"
6279   [(set_attr "type" "load3")
6280    (set_attr "predicable" "yes")]
6281 )
6282
6283 (define_insn "*ldmsi2"
6284   [(match_parallel 0 "load_multiple_operation"
6285     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
6286           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
6287      (set (match_operand:SI 3 "arm_hard_register_operand" "")
6288           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
6289   "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
6290   "ldm%(ia%)\\t%1, {%2, %3}"
6291   [(set_attr "type" "load2")
6292    (set_attr "predicable" "yes")]
6293 )
6294
6295 (define_expand "store_multiple"
6296   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6297                           (match_operand:SI 1 "" ""))
6298                      (use (match_operand:SI 2 "" ""))])]
6299   "TARGET_32BIT"
6300 {
6301   HOST_WIDE_INT offset = 0;
6302
6303   /* Support only fixed point registers.  */
6304   if (GET_CODE (operands[2]) != CONST_INT
6305       || INTVAL (operands[2]) > 14
6306       || INTVAL (operands[2]) < 2
6307       || GET_CODE (operands[1]) != REG
6308       || GET_CODE (operands[0]) != MEM
6309       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6310       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
6311     FAIL;
6312
6313   operands[3]
6314     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
6315                               force_reg (SImode, XEXP (operands[0], 0)),
6316                               TRUE, FALSE, operands[0], &offset);
6317 })
6318
6319 ;; Store multiple with write-back
6320
6321 (define_insn "*stmsi_postinc4"
6322   [(match_parallel 0 "store_multiple_operation"
6323     [(set (match_operand:SI 1 "s_register_operand" "=r")
6324           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6325                    (const_int 16)))
6326      (set (mem:SI (match_dup 2))
6327           (match_operand:SI 3 "arm_hard_register_operand" ""))
6328      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6329           (match_operand:SI 4 "arm_hard_register_operand" ""))
6330      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6331           (match_operand:SI 5 "arm_hard_register_operand" ""))
6332      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
6333           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
6334   "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
6335   "stm%(ia%)\\t%1!, {%3, %4, %5, %6}"
6336   [(set_attr "predicable" "yes")
6337    (set_attr "type" "store4")]
6338 )
6339
6340 (define_insn "*stmsi_postinc4_thumb1"
6341   [(match_parallel 0 "store_multiple_operation"
6342     [(set (match_operand:SI 1 "s_register_operand" "=l")
6343           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6344                    (const_int 16)))
6345      (set (mem:SI (match_dup 2))
6346           (match_operand:SI 3 "arm_hard_register_operand" ""))
6347      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6348           (match_operand:SI 4 "arm_hard_register_operand" ""))
6349      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6350           (match_operand:SI 5 "arm_hard_register_operand" ""))
6351      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
6352           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
6353   "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
6354   "stmia\\t%1!, {%3, %4, %5, %6}"
6355   [(set_attr "type" "store4")]
6356 )
6357
6358 (define_insn "*stmsi_postinc3"
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 12)))
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      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6368           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
6369   "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6370   "stm%(ia%)\\t%1!, {%3, %4, %5}"
6371   [(set_attr "predicable" "yes")
6372    (set_attr "type" "store3")]
6373 )
6374
6375 (define_insn "*stmsi_postinc2"
6376   [(match_parallel 0 "store_multiple_operation"
6377     [(set (match_operand:SI 1 "s_register_operand" "=r")
6378           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6379                    (const_int 8)))
6380      (set (mem:SI (match_dup 2))
6381           (match_operand:SI 3 "arm_hard_register_operand" ""))
6382      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6383           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
6384   "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6385   "stm%(ia%)\\t%1!, {%3, %4}"
6386   [(set_attr "predicable" "yes")
6387    (set_attr "type" "store2")]
6388 )
6389
6390 ;; Ordinary store multiple
6391
6392 (define_insn "*stmsi4"
6393   [(match_parallel 0 "store_multiple_operation"
6394     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6395           (match_operand:SI 2 "arm_hard_register_operand" ""))
6396      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6397           (match_operand:SI 3 "arm_hard_register_operand" ""))
6398      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
6399           (match_operand:SI 4 "arm_hard_register_operand" ""))
6400      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
6401           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
6402   "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6403   "stm%(ia%)\\t%1, {%2, %3, %4, %5}"
6404   [(set_attr "predicable" "yes")
6405    (set_attr "type" "store4")]
6406 )
6407
6408 (define_insn "*stmsi3"
6409   [(match_parallel 0 "store_multiple_operation"
6410     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6411           (match_operand:SI 2 "arm_hard_register_operand" ""))
6412      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6413           (match_operand:SI 3 "arm_hard_register_operand" ""))
6414      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
6415           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
6416   "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6417   "stm%(ia%)\\t%1, {%2, %3, %4}"
6418   [(set_attr "predicable" "yes")
6419    (set_attr "type" "store3")]
6420 )
6421
6422 (define_insn "*stmsi2"
6423   [(match_parallel 0 "store_multiple_operation"
6424     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6425           (match_operand:SI 2 "arm_hard_register_operand" ""))
6426      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6427           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
6428   "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
6429   "stm%(ia%)\\t%1, {%2, %3}"
6430   [(set_attr "predicable" "yes")
6431    (set_attr "type" "store2")]
6432 )
6433
6434 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
6435 ;; We could let this apply for blocks of less than this, but it clobbers so
6436 ;; many registers that there is then probably a better way.
6437
6438 (define_expand "movmemqi"
6439   [(match_operand:BLK 0 "general_operand" "")
6440    (match_operand:BLK 1 "general_operand" "")
6441    (match_operand:SI 2 "const_int_operand" "")
6442    (match_operand:SI 3 "const_int_operand" "")]
6443   "TARGET_EITHER"
6444   "
6445   if (TARGET_32BIT)
6446     {
6447       if (arm_gen_movmemqi (operands))
6448         DONE;
6449       FAIL;
6450     }
6451   else /* TARGET_THUMB1 */
6452     {
6453       if (   INTVAL (operands[3]) != 4
6454           || INTVAL (operands[2]) > 48)
6455         FAIL;
6456
6457       thumb_expand_movmemqi (operands);
6458       DONE;
6459     }
6460   "
6461 )
6462
6463 ;; Thumb block-move insns
6464
6465 (define_insn "movmem12b"
6466   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6467         (mem:SI (match_operand:SI 3 "register_operand" "1")))
6468    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6469         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6470    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6471         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
6472    (set (match_operand:SI 0 "register_operand" "=l")
6473         (plus:SI (match_dup 2) (const_int 12)))
6474    (set (match_operand:SI 1 "register_operand" "=l")
6475         (plus:SI (match_dup 3) (const_int 12)))
6476    (clobber (match_scratch:SI 4 "=&l"))
6477    (clobber (match_scratch:SI 5 "=&l"))
6478    (clobber (match_scratch:SI 6 "=&l"))]
6479   "TARGET_THUMB1"
6480   "* return thumb_output_move_mem_multiple (3, operands);"
6481   [(set_attr "length" "4")
6482    ; This isn't entirely accurate...  It loads as well, but in terms of
6483    ; scheduling the following insn it is better to consider it as a store
6484    (set_attr "type" "store3")]
6485 )
6486
6487 (define_insn "movmem8b"
6488   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6489         (mem:SI (match_operand:SI 3 "register_operand" "1")))
6490    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6491         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6492    (set (match_operand:SI 0 "register_operand" "=l")
6493         (plus:SI (match_dup 2) (const_int 8)))
6494    (set (match_operand:SI 1 "register_operand" "=l")
6495         (plus:SI (match_dup 3) (const_int 8)))
6496    (clobber (match_scratch:SI 4 "=&l"))
6497    (clobber (match_scratch:SI 5 "=&l"))]
6498   "TARGET_THUMB1"
6499   "* return thumb_output_move_mem_multiple (2, operands);"
6500   [(set_attr "length" "4")
6501    ; This isn't entirely accurate...  It loads as well, but in terms of
6502    ; scheduling the following insn it is better to consider it as a store
6503    (set_attr "type" "store2")]
6504 )
6505
6506 \f
6507
6508 ;; Compare & branch insns
6509 ;; The range calculations are based as follows:
6510 ;; For forward branches, the address calculation returns the address of
6511 ;; the next instruction.  This is 2 beyond the branch instruction.
6512 ;; For backward branches, the address calculation returns the address of
6513 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
6514 ;; instruction for the shortest sequence, and 4 before the branch instruction
6515 ;; if we have to jump around an unconditional branch.
6516 ;; To the basic branch range the PC offset must be added (this is +4).
6517 ;; So for forward branches we have 
6518 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6519 ;; And for backward branches we have 
6520 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6521 ;;
6522 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6523 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
6524
6525 (define_expand "cbranchsi4"
6526   [(set (pc) (if_then_else
6527               (match_operator 0 "arm_comparison_operator"
6528                [(match_operand:SI 1 "s_register_operand" "")
6529                 (match_operand:SI 2 "nonmemory_operand" "")])
6530               (label_ref (match_operand 3 "" ""))
6531               (pc)))]
6532   "TARGET_THUMB1 || TARGET_32BIT"
6533   "
6534   if (!TARGET_THUMB1)
6535     {
6536       if (!arm_add_operand (operands[2], SImode))
6537         operands[2] = force_reg (SImode, operands[2]);
6538       emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6539                                       operands[3]));
6540       DONE;
6541     }
6542   if (thumb1_cmpneg_operand (operands[2], SImode))
6543     {
6544       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6545                                               operands[3], operands[0]));
6546       DONE;
6547     }
6548   if (!thumb1_cmp_operand (operands[2], SImode))
6549     operands[2] = force_reg (SImode, operands[2]);
6550   ")
6551
6552 ;; A pattern to recognize a special situation and optimize for it.
6553 ;; On the thumb, zero-extension from memory is preferrable to sign-extension
6554 ;; due to the available addressing modes.  Hence, convert a signed comparison
6555 ;; with zero into an unsigned comparison with 127 if possible.
6556 (define_expand "cbranchqi4"
6557   [(set (pc) (if_then_else
6558               (match_operator 0 "lt_ge_comparison_operator"
6559                [(match_operand:QI 1 "memory_operand" "")
6560                 (match_operand:QI 2 "const0_operand" "")])
6561               (label_ref (match_operand 3 "" ""))
6562               (pc)))]
6563   "TARGET_THUMB1"
6564 {
6565   rtx xops[3];
6566   xops[1] = gen_reg_rtx (SImode);
6567   emit_insn (gen_zero_extendqisi2 (xops[1], operands[1]));
6568   xops[2] = GEN_INT (127);
6569   xops[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]) == GE ? LEU : GTU,
6570                             VOIDmode, xops[1], xops[2]);
6571   xops[3] = operands[3];
6572   emit_insn (gen_cbranchsi4 (xops[0], xops[1], xops[2], xops[3]));
6573   DONE;
6574 })
6575
6576 (define_expand "cbranchsf4"
6577   [(set (pc) (if_then_else
6578               (match_operator 0 "arm_comparison_operator"
6579                [(match_operand:SF 1 "s_register_operand" "")
6580                 (match_operand:SF 2 "arm_float_compare_operand" "")])
6581               (label_ref (match_operand 3 "" ""))
6582               (pc)))]
6583   "TARGET_32BIT && TARGET_HARD_FLOAT"
6584   "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6585                                    operands[3])); DONE;"
6586 )
6587
6588 (define_expand "cbranchdf4"
6589   [(set (pc) (if_then_else
6590               (match_operator 0 "arm_comparison_operator"
6591                [(match_operand:DF 1 "s_register_operand" "")
6592                 (match_operand:DF 2 "arm_float_compare_operand" "")])
6593               (label_ref (match_operand 3 "" ""))
6594               (pc)))]
6595   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
6596   "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6597                                    operands[3])); DONE;"
6598 )
6599
6600 (define_expand "cbranchdi4"
6601   [(set (pc) (if_then_else
6602               (match_operator 0 "arm_comparison_operator"
6603                [(match_operand:DI 1 "cmpdi_operand" "")
6604                 (match_operand:DI 2 "cmpdi_operand" "")])
6605               (label_ref (match_operand 3 "" ""))
6606               (pc)))]
6607   "TARGET_32BIT"
6608   "{
6609      rtx swap = NULL_RTX;
6610      enum rtx_code code = GET_CODE (operands[0]);
6611
6612      /* We should not have two constants.  */
6613      gcc_assert (GET_MODE (operands[1]) == DImode
6614                  || GET_MODE (operands[2]) == DImode);
6615
6616     /* Flip unimplemented DImode comparisons to a form that
6617        arm_gen_compare_reg can handle.  */
6618      switch (code)
6619      {
6620      case GT:
6621        swap = gen_rtx_LT (VOIDmode, operands[2], operands[1]); break;
6622      case LE:
6623        swap = gen_rtx_GE (VOIDmode, operands[2], operands[1]); break;
6624      case GTU:
6625        swap = gen_rtx_LTU (VOIDmode, operands[2], operands[1]); break;
6626      case LEU:
6627        swap = gen_rtx_GEU (VOIDmode, operands[2], operands[1]); break;
6628      default:
6629        break;
6630      }
6631      if (swap)
6632        emit_jump_insn (gen_cbranch_cc (swap, operands[2], operands[1],
6633                                        operands[3]));
6634      else
6635        emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6636                                        operands[3]));
6637      DONE;
6638    }"
6639 )
6640
6641 (define_insn "cbranchsi4_insn"
6642   [(set (pc) (if_then_else
6643               (match_operator 0 "arm_comparison_operator"
6644                [(match_operand:SI 1 "s_register_operand" "l,*h")
6645                 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
6646               (label_ref (match_operand 3 "" ""))
6647               (pc)))]
6648   "TARGET_THUMB1"
6649   "*
6650   rtx t = prev_nonnote_insn (insn);
6651   if (t != NULL_RTX
6652       && INSN_P (t)
6653       && INSN_CODE (t) == CODE_FOR_cbranchsi4_insn)
6654     {
6655       t = XEXP (SET_SRC (PATTERN (t)), 0);
6656       if (!rtx_equal_p (XEXP (t, 0), operands[1])
6657           || !rtx_equal_p (XEXP (t, 1), operands[2]))
6658         t = NULL_RTX;
6659     }
6660   else
6661     t = NULL_RTX;
6662   if (t == NULL_RTX)
6663     output_asm_insn (\"cmp\\t%1, %2\", operands);
6664
6665   switch (get_attr_length (insn))
6666     {
6667     case 4:  return \"b%d0\\t%l3\";
6668     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6669     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6670     }
6671   "
6672   [(set (attr "far_jump")
6673         (if_then_else
6674             (eq_attr "length" "8")
6675             (const_string "yes")
6676             (const_string "no")))
6677    (set (attr "length") 
6678         (if_then_else
6679             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6680                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6681             (const_int 4)
6682             (if_then_else
6683                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6684                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6685                 (const_int 6)
6686                 (const_int 8))))]
6687 )
6688
6689 (define_insn "cbranchsi4_scratch"
6690   [(set (pc) (if_then_else
6691               (match_operator 4 "arm_comparison_operator"
6692                [(match_operand:SI 1 "s_register_operand" "l,0")
6693                 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
6694               (label_ref (match_operand 3 "" ""))
6695               (pc)))
6696    (clobber (match_scratch:SI 0 "=l,l"))]
6697   "TARGET_THUMB1"
6698   "*
6699   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
6700
6701   switch (get_attr_length (insn))
6702     {
6703     case 4:  return \"b%d4\\t%l3\";
6704     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6705     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6706     }
6707   "
6708   [(set (attr "far_jump")
6709         (if_then_else
6710             (eq_attr "length" "8")
6711             (const_string "yes")
6712             (const_string "no")))
6713    (set (attr "length") 
6714         (if_then_else
6715             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6716                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6717             (const_int 4)
6718             (if_then_else
6719                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6720                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6721                 (const_int 6)
6722                 (const_int 8))))]
6723 )
6724
6725 (define_insn "*movsi_cbranchsi4"
6726   [(set (pc)
6727         (if_then_else
6728          (match_operator 3 "arm_comparison_operator"
6729           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
6730            (const_int 0)])
6731          (label_ref (match_operand 2 "" ""))
6732          (pc)))
6733    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
6734         (match_dup 1))]
6735   "TARGET_THUMB1"
6736   "*{
6737   if (which_alternative == 0)
6738     output_asm_insn (\"cmp\t%0, #0\", operands);
6739   else if (which_alternative == 1)
6740     output_asm_insn (\"sub\t%0, %1, #0\", operands);
6741   else
6742     {
6743       output_asm_insn (\"cmp\t%1, #0\", operands);
6744       if (which_alternative == 2)
6745         output_asm_insn (\"mov\t%0, %1\", operands);
6746       else
6747         output_asm_insn (\"str\t%1, %0\", operands);
6748     }
6749   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
6750     {
6751     case 4:  return \"b%d3\\t%l2\";
6752     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6753     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
6754     }
6755   }"
6756   [(set (attr "far_jump")
6757         (if_then_else
6758             (ior (and (gt (symbol_ref ("which_alternative"))
6759                           (const_int 1))
6760                       (eq_attr "length" "8"))
6761                  (eq_attr "length" "10"))
6762             (const_string "yes")
6763             (const_string "no")))
6764    (set (attr "length")
6765      (if_then_else
6766        (le (symbol_ref ("which_alternative"))
6767                        (const_int 1))
6768        (if_then_else
6769          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6770               (le (minus (match_dup 2) (pc)) (const_int 256)))
6771          (const_int 4)
6772          (if_then_else
6773            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6774                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6775            (const_int 6)
6776            (const_int 8)))
6777        (if_then_else
6778          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
6779               (le (minus (match_dup 2) (pc)) (const_int 256)))
6780          (const_int 6)
6781          (if_then_else
6782            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
6783                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6784            (const_int 8)
6785            (const_int 10)))))]
6786 )
6787
6788 (define_peephole2
6789   [(set (match_operand:SI 0 "low_register_operand" "")
6790         (match_operand:SI 1 "low_register_operand" ""))
6791    (set (pc)
6792         (if_then_else (match_operator 2 "arm_comparison_operator"
6793                        [(match_dup 1) (const_int 0)])
6794                       (label_ref (match_operand 3 "" ""))
6795                       (pc)))]
6796   "TARGET_THUMB1"
6797   [(parallel
6798     [(set (pc)
6799         (if_then_else (match_op_dup 2 [(match_dup 1) (const_int 0)])
6800                       (label_ref (match_dup 3))
6801                       (pc)))
6802      (set (match_dup 0) (match_dup 1))])]
6803   ""
6804 )
6805
6806 ;; Sigh!  This variant shouldn't be needed, but combine often fails to
6807 ;; merge cases like this because the op1 is a hard register in
6808 ;; CLASS_LIKELY_SPILLED_P.
6809 (define_peephole2
6810   [(set (match_operand:SI 0 "low_register_operand" "")
6811         (match_operand:SI 1 "low_register_operand" ""))
6812    (set (pc)
6813         (if_then_else (match_operator 2 "arm_comparison_operator"
6814                        [(match_dup 0) (const_int 0)])
6815                       (label_ref (match_operand 3 "" ""))
6816                       (pc)))]
6817   "TARGET_THUMB1"
6818   [(parallel
6819     [(set (pc)
6820         (if_then_else (match_op_dup 2 [(match_dup 1) (const_int 0)])
6821                       (label_ref (match_dup 3))
6822                       (pc)))
6823      (set (match_dup 0) (match_dup 1))])]
6824   ""
6825 )
6826
6827 (define_insn "*negated_cbranchsi4"
6828   [(set (pc)
6829         (if_then_else
6830          (match_operator 0 "equality_operator"
6831           [(match_operand:SI 1 "s_register_operand" "l")
6832            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
6833          (label_ref (match_operand 3 "" ""))
6834          (pc)))]
6835   "TARGET_THUMB1"
6836   "*
6837   output_asm_insn (\"cmn\\t%1, %2\", operands);
6838   switch (get_attr_length (insn))
6839     {
6840     case 4:  return \"b%d0\\t%l3\";
6841     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6842     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6843     }
6844   "
6845   [(set (attr "far_jump")
6846         (if_then_else
6847             (eq_attr "length" "8")
6848             (const_string "yes")
6849             (const_string "no")))
6850    (set (attr "length") 
6851         (if_then_else
6852             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6853                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6854             (const_int 4)
6855             (if_then_else
6856                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6857                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6858                 (const_int 6)
6859                 (const_int 8))))]
6860 )
6861
6862 (define_insn "*tbit_cbranch"
6863   [(set (pc)
6864         (if_then_else
6865          (match_operator 0 "equality_operator"
6866           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6867                             (const_int 1)
6868                             (match_operand:SI 2 "const_int_operand" "i"))
6869            (const_int 0)])
6870          (label_ref (match_operand 3 "" ""))
6871          (pc)))
6872    (clobber (match_scratch:SI 4 "=l"))]
6873   "TARGET_THUMB1"
6874   "*
6875   {
6876   rtx op[3];
6877   op[0] = operands[4];
6878   op[1] = operands[1];
6879   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
6880
6881   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6882   switch (get_attr_length (insn))
6883     {
6884     case 4:  return \"b%d0\\t%l3\";
6885     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6886     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6887     }
6888   }"
6889   [(set (attr "far_jump")
6890         (if_then_else
6891             (eq_attr "length" "8")
6892             (const_string "yes")
6893             (const_string "no")))
6894    (set (attr "length") 
6895         (if_then_else
6896             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6897                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6898             (const_int 4)
6899             (if_then_else
6900                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6901                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6902                 (const_int 6)
6903                 (const_int 8))))]
6904 )
6905   
6906 (define_insn "*tlobits_cbranch"
6907   [(set (pc)
6908         (if_then_else
6909          (match_operator 0 "equality_operator"
6910           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6911                             (match_operand:SI 2 "const_int_operand" "i")
6912                             (const_int 0))
6913            (const_int 0)])
6914          (label_ref (match_operand 3 "" ""))
6915          (pc)))
6916    (clobber (match_scratch:SI 4 "=l"))]
6917   "TARGET_THUMB1"
6918   "*
6919   {
6920   rtx op[3];
6921   op[0] = operands[4];
6922   op[1] = operands[1];
6923   op[2] = GEN_INT (32 - INTVAL (operands[2]));
6924
6925   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6926   switch (get_attr_length (insn))
6927     {
6928     case 4:  return \"b%d0\\t%l3\";
6929     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6930     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6931     }
6932   }"
6933   [(set (attr "far_jump")
6934         (if_then_else
6935             (eq_attr "length" "8")
6936             (const_string "yes")
6937             (const_string "no")))
6938    (set (attr "length") 
6939         (if_then_else
6940             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6941                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6942             (const_int 4)
6943             (if_then_else
6944                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6945                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6946                 (const_int 6)
6947                 (const_int 8))))]
6948 )
6949   
6950 (define_insn "*tstsi3_cbranch"
6951   [(set (pc)
6952         (if_then_else
6953          (match_operator 3 "equality_operator"
6954           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
6955                    (match_operand:SI 1 "s_register_operand" "l"))
6956            (const_int 0)])
6957          (label_ref (match_operand 2 "" ""))
6958          (pc)))]
6959   "TARGET_THUMB1"
6960   "*
6961   {
6962   output_asm_insn (\"tst\\t%0, %1\", operands);
6963   switch (get_attr_length (insn))
6964     {
6965     case 4:  return \"b%d3\\t%l2\";
6966     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6967     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
6968     }
6969   }"
6970   [(set (attr "far_jump")
6971         (if_then_else
6972             (eq_attr "length" "8")
6973             (const_string "yes")
6974             (const_string "no")))
6975    (set (attr "length") 
6976         (if_then_else
6977             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6978                  (le (minus (match_dup 2) (pc)) (const_int 256)))
6979             (const_int 4)
6980             (if_then_else
6981                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6982                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
6983                 (const_int 6)
6984                 (const_int 8))))]
6985 )
6986   
6987 (define_insn "*andsi3_cbranch"
6988   [(set (pc)
6989         (if_then_else
6990          (match_operator 5 "equality_operator"
6991           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6992                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6993            (const_int 0)])
6994          (label_ref (match_operand 4 "" ""))
6995          (pc)))
6996    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6997         (and:SI (match_dup 2) (match_dup 3)))
6998    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6999   "TARGET_THUMB1"
7000   "*
7001   {
7002   if (which_alternative == 0)
7003     output_asm_insn (\"and\\t%0, %3\", operands);
7004   else if (which_alternative == 1)
7005     {
7006       output_asm_insn (\"and\\t%1, %3\", operands);
7007       output_asm_insn (\"mov\\t%0, %1\", operands);
7008     }
7009   else
7010     {
7011       output_asm_insn (\"and\\t%1, %3\", operands);
7012       output_asm_insn (\"str\\t%1, %0\", operands);
7013     }
7014
7015   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7016     {
7017     case 4:  return \"b%d5\\t%l4\";
7018     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7019     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7020     }
7021   }"
7022   [(set (attr "far_jump")
7023         (if_then_else
7024             (ior (and (eq (symbol_ref ("which_alternative"))
7025                           (const_int 0))
7026                       (eq_attr "length" "8"))
7027                  (eq_attr "length" "10"))
7028             (const_string "yes")
7029             (const_string "no")))
7030    (set (attr "length")
7031      (if_then_else
7032        (eq (symbol_ref ("which_alternative"))
7033                        (const_int 0))
7034        (if_then_else
7035          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7036               (le (minus (match_dup 4) (pc)) (const_int 256)))
7037          (const_int 4)
7038          (if_then_else
7039            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7040                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7041            (const_int 6)
7042            (const_int 8)))
7043        (if_then_else
7044          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7045               (le (minus (match_dup 4) (pc)) (const_int 256)))
7046          (const_int 6)
7047          (if_then_else
7048            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7049                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7050            (const_int 8)
7051            (const_int 10)))))]
7052 )
7053
7054 (define_insn "*orrsi3_cbranch_scratch"
7055   [(set (pc)
7056         (if_then_else
7057          (match_operator 4 "equality_operator"
7058           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
7059                    (match_operand:SI 2 "s_register_operand" "l"))
7060            (const_int 0)])
7061          (label_ref (match_operand 3 "" ""))
7062          (pc)))
7063    (clobber (match_scratch:SI 0 "=l"))]
7064   "TARGET_THUMB1"
7065   "*
7066   {
7067   output_asm_insn (\"orr\\t%0, %2\", operands);
7068   switch (get_attr_length (insn))
7069     {
7070     case 4:  return \"b%d4\\t%l3\";
7071     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7072     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7073     }
7074   }"
7075   [(set (attr "far_jump")
7076         (if_then_else
7077             (eq_attr "length" "8")
7078             (const_string "yes")
7079             (const_string "no")))
7080    (set (attr "length") 
7081         (if_then_else
7082             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7083                  (le (minus (match_dup 3) (pc)) (const_int 256)))
7084             (const_int 4)
7085             (if_then_else
7086                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7087                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
7088                 (const_int 6)
7089                 (const_int 8))))]
7090 )
7091   
7092 (define_insn "*orrsi3_cbranch"
7093   [(set (pc)
7094         (if_then_else
7095          (match_operator 5 "equality_operator"
7096           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
7097                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7098            (const_int 0)])
7099          (label_ref (match_operand 4 "" ""))
7100          (pc)))
7101    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
7102         (ior:SI (match_dup 2) (match_dup 3)))
7103    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
7104   "TARGET_THUMB1"
7105   "*
7106   {
7107   if (which_alternative == 0)
7108     output_asm_insn (\"orr\\t%0, %3\", operands);
7109   else if (which_alternative == 1)
7110     {
7111       output_asm_insn (\"orr\\t%1, %3\", operands);
7112       output_asm_insn (\"mov\\t%0, %1\", operands);
7113     }
7114   else
7115     {
7116       output_asm_insn (\"orr\\t%1, %3\", operands);
7117       output_asm_insn (\"str\\t%1, %0\", operands);
7118     }
7119
7120   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7121     {
7122     case 4:  return \"b%d5\\t%l4\";
7123     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7124     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7125     }
7126   }"
7127   [(set (attr "far_jump")
7128         (if_then_else
7129             (ior (and (eq (symbol_ref ("which_alternative"))
7130                           (const_int 0))
7131                       (eq_attr "length" "8"))
7132                  (eq_attr "length" "10"))
7133             (const_string "yes")
7134             (const_string "no")))
7135    (set (attr "length")
7136      (if_then_else
7137        (eq (symbol_ref ("which_alternative"))
7138                        (const_int 0))
7139        (if_then_else
7140          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7141               (le (minus (match_dup 4) (pc)) (const_int 256)))
7142          (const_int 4)
7143          (if_then_else
7144            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7145                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7146            (const_int 6)
7147            (const_int 8)))
7148        (if_then_else
7149          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7150               (le (minus (match_dup 4) (pc)) (const_int 256)))
7151          (const_int 6)
7152          (if_then_else
7153            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7154                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7155            (const_int 8)
7156            (const_int 10)))))]
7157 )
7158
7159 (define_insn "*xorsi3_cbranch_scratch"
7160   [(set (pc)
7161         (if_then_else
7162          (match_operator 4 "equality_operator"
7163           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
7164                    (match_operand:SI 2 "s_register_operand" "l"))
7165            (const_int 0)])
7166          (label_ref (match_operand 3 "" ""))
7167          (pc)))
7168    (clobber (match_scratch:SI 0 "=l"))]
7169   "TARGET_THUMB1"
7170   "*
7171   {
7172   output_asm_insn (\"eor\\t%0, %2\", operands);
7173   switch (get_attr_length (insn))
7174     {
7175     case 4:  return \"b%d4\\t%l3\";
7176     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7177     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7178     }
7179   }"
7180   [(set (attr "far_jump")
7181         (if_then_else
7182             (eq_attr "length" "8")
7183             (const_string "yes")
7184             (const_string "no")))
7185    (set (attr "length") 
7186         (if_then_else
7187             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7188                  (le (minus (match_dup 3) (pc)) (const_int 256)))
7189             (const_int 4)
7190             (if_then_else
7191                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7192                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
7193                 (const_int 6)
7194                 (const_int 8))))]
7195 )
7196   
7197 (define_insn "*xorsi3_cbranch"
7198   [(set (pc)
7199         (if_then_else
7200          (match_operator 5 "equality_operator"
7201           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
7202                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7203            (const_int 0)])
7204          (label_ref (match_operand 4 "" ""))
7205          (pc)))
7206    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
7207         (xor:SI (match_dup 2) (match_dup 3)))
7208    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
7209   "TARGET_THUMB1"
7210   "*
7211   {
7212   if (which_alternative == 0)
7213     output_asm_insn (\"eor\\t%0, %3\", operands);
7214   else if (which_alternative == 1)
7215     {
7216       output_asm_insn (\"eor\\t%1, %3\", operands);
7217       output_asm_insn (\"mov\\t%0, %1\", operands);
7218     }
7219   else
7220     {
7221       output_asm_insn (\"eor\\t%1, %3\", operands);
7222       output_asm_insn (\"str\\t%1, %0\", operands);
7223     }
7224
7225   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7226     {
7227     case 4:  return \"b%d5\\t%l4\";
7228     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7229     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7230     }
7231   }"
7232   [(set (attr "far_jump")
7233         (if_then_else
7234             (ior (and (eq (symbol_ref ("which_alternative"))
7235                           (const_int 0))
7236                       (eq_attr "length" "8"))
7237                  (eq_attr "length" "10"))
7238             (const_string "yes")
7239             (const_string "no")))
7240    (set (attr "length")
7241      (if_then_else
7242        (eq (symbol_ref ("which_alternative"))
7243                        (const_int 0))
7244        (if_then_else
7245          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7246               (le (minus (match_dup 4) (pc)) (const_int 256)))
7247          (const_int 4)
7248          (if_then_else
7249            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7250                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7251            (const_int 6)
7252            (const_int 8)))
7253        (if_then_else
7254          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7255               (le (minus (match_dup 4) (pc)) (const_int 256)))
7256          (const_int 6)
7257          (if_then_else
7258            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7259                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7260            (const_int 8)
7261            (const_int 10)))))]
7262 )
7263
7264 (define_insn "*bicsi3_cbranch_scratch"
7265   [(set (pc)
7266         (if_then_else
7267          (match_operator 4 "equality_operator"
7268           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
7269                    (match_operand:SI 1 "s_register_operand" "0"))
7270            (const_int 0)])
7271          (label_ref (match_operand 3 "" ""))
7272          (pc)))
7273    (clobber (match_scratch:SI 0 "=l"))]
7274   "TARGET_THUMB1"
7275   "*
7276   {
7277   output_asm_insn (\"bic\\t%0, %2\", operands);
7278   switch (get_attr_length (insn))
7279     {
7280     case 4:  return \"b%d4\\t%l3\";
7281     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7282     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7283     }
7284   }"
7285   [(set (attr "far_jump")
7286         (if_then_else
7287             (eq_attr "length" "8")
7288             (const_string "yes")
7289             (const_string "no")))
7290    (set (attr "length") 
7291         (if_then_else
7292             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7293                  (le (minus (match_dup 3) (pc)) (const_int 256)))
7294             (const_int 4)
7295             (if_then_else
7296                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7297                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
7298                 (const_int 6)
7299                 (const_int 8))))]
7300 )
7301   
7302 (define_insn "*bicsi3_cbranch"
7303   [(set (pc)
7304         (if_then_else
7305          (match_operator 5 "equality_operator"
7306           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
7307                    (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
7308            (const_int 0)])
7309          (label_ref (match_operand 4 "" ""))
7310          (pc)))
7311    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
7312         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
7313    (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
7314   "TARGET_THUMB1"
7315   "*
7316   {
7317   if (which_alternative == 0)
7318     output_asm_insn (\"bic\\t%0, %3\", operands);
7319   else if (which_alternative <= 2)
7320     {
7321       output_asm_insn (\"bic\\t%1, %3\", operands);
7322       /* It's ok if OP0 is a lo-reg, even though the mov will set the
7323          conditions again, since we're only testing for equality.  */
7324       output_asm_insn (\"mov\\t%0, %1\", operands);
7325     }
7326   else
7327     {
7328       output_asm_insn (\"bic\\t%1, %3\", operands);
7329       output_asm_insn (\"str\\t%1, %0\", operands);
7330     }
7331
7332   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7333     {
7334     case 4:  return \"b%d5\\t%l4\";
7335     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7336     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7337     }
7338   }"
7339   [(set (attr "far_jump")
7340         (if_then_else
7341             (ior (and (eq (symbol_ref ("which_alternative"))
7342                           (const_int 0))
7343                       (eq_attr "length" "8"))
7344                  (eq_attr "length" "10"))
7345             (const_string "yes")
7346             (const_string "no")))
7347    (set (attr "length")
7348      (if_then_else
7349        (eq (symbol_ref ("which_alternative"))
7350                        (const_int 0))
7351        (if_then_else
7352          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7353               (le (minus (match_dup 4) (pc)) (const_int 256)))
7354          (const_int 4)
7355          (if_then_else
7356            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7357                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7358            (const_int 6)
7359            (const_int 8)))
7360        (if_then_else
7361          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7362               (le (minus (match_dup 4) (pc)) (const_int 256)))
7363          (const_int 6)
7364          (if_then_else
7365            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7366                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7367            (const_int 8)
7368            (const_int 10)))))]
7369 )
7370
7371 (define_insn "*cbranchne_decr1"
7372   [(set (pc)
7373         (if_then_else (match_operator 3 "equality_operator"
7374                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
7375                         (const_int 0)])
7376                       (label_ref (match_operand 4 "" ""))
7377                       (pc)))
7378    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
7379         (plus:SI (match_dup 2) (const_int -1)))
7380    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
7381   "TARGET_THUMB1"
7382   "*
7383    {
7384      rtx cond[2];
7385      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
7386                                 ? GEU : LTU),
7387                                VOIDmode, operands[2], const1_rtx);
7388      cond[1] = operands[4];
7389
7390      if (which_alternative == 0)
7391        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
7392      else if (which_alternative == 1)
7393        {
7394          /* We must provide an alternative for a hi reg because reload 
7395             cannot handle output reloads on a jump instruction, but we
7396             can't subtract into that.  Fortunately a mov from lo to hi
7397             does not clobber the condition codes.  */
7398          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7399          output_asm_insn (\"mov\\t%0, %1\", operands);
7400        }
7401      else
7402        {
7403          /* Similarly, but the target is memory.  */
7404          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7405          output_asm_insn (\"str\\t%1, %0\", operands);
7406        }
7407
7408      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7409        {
7410          case 4:
7411            output_asm_insn (\"b%d0\\t%l1\", cond);
7412            return \"\";
7413          case 6:
7414            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
7415            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
7416          default:
7417            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
7418            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7419        }
7420    }
7421   "
7422   [(set (attr "far_jump")
7423         (if_then_else
7424             (ior (and (eq (symbol_ref ("which_alternative"))
7425                           (const_int 0))
7426                       (eq_attr "length" "8"))
7427                  (eq_attr "length" "10"))
7428             (const_string "yes")
7429             (const_string "no")))
7430    (set_attr_alternative "length"
7431       [
7432        ;; Alternative 0
7433        (if_then_else
7434          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7435               (le (minus (match_dup 4) (pc)) (const_int 256)))
7436          (const_int 4)
7437          (if_then_else
7438            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7439                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7440            (const_int 6)
7441            (const_int 8)))
7442        ;; Alternative 1
7443        (if_then_else
7444          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7445               (le (minus (match_dup 4) (pc)) (const_int 256)))
7446          (const_int 6)
7447          (if_then_else
7448            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7449                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7450            (const_int 8)
7451            (const_int 10)))
7452        ;; Alternative 2
7453        (if_then_else
7454          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7455               (le (minus (match_dup 4) (pc)) (const_int 256)))
7456          (const_int 6)
7457          (if_then_else
7458            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7459                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7460            (const_int 8)
7461            (const_int 10)))
7462        ;; Alternative 3
7463        (if_then_else
7464          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7465               (le (minus (match_dup 4) (pc)) (const_int 256)))
7466          (const_int 6)
7467          (if_then_else
7468            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7469                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7470            (const_int 8)
7471            (const_int 10)))])]
7472 )
7473
7474 (define_insn "*addsi3_cbranch"
7475   [(set (pc)
7476         (if_then_else
7477          (match_operator 4 "arm_comparison_operator"
7478           [(plus:SI
7479             (match_operand:SI 2 "s_register_operand" "%0,l,*l,1,1,1")
7480             (match_operand:SI 3 "reg_or_int_operand" "IJ,lL,*l,lIJ,lIJ,lIJ"))
7481            (const_int 0)])
7482          (label_ref (match_operand 5 "" ""))
7483          (pc)))
7484    (set
7485     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
7486     (plus:SI (match_dup 2) (match_dup 3)))
7487    (clobber (match_scratch:SI 1 "=X,X,l,l,&l,&l"))]
7488   "TARGET_THUMB1
7489    && (GET_CODE (operands[4]) == EQ
7490        || GET_CODE (operands[4]) == NE
7491        || GET_CODE (operands[4]) == GE
7492        || GET_CODE (operands[4]) == LT)"
7493   "*
7494    {
7495      rtx cond[3];
7496
7497      cond[0] = (which_alternative < 2) ? operands[0] : operands[1];
7498      cond[1] = operands[2];
7499      cond[2] = operands[3];
7500
7501      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
7502        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
7503      else
7504        output_asm_insn (\"add\\t%0, %1, %2\", cond);
7505
7506      if (which_alternative >= 2
7507          && which_alternative < 4)
7508        output_asm_insn (\"mov\\t%0, %1\", operands);
7509      else if (which_alternative >= 4)
7510        output_asm_insn (\"str\\t%1, %0\", operands);
7511
7512      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
7513        {
7514          case 4:
7515            return \"b%d4\\t%l5\";
7516          case 6:
7517            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7518          default:
7519            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7520        }
7521    }
7522   "
7523   [(set (attr "far_jump")
7524         (if_then_else
7525             (ior (and (lt (symbol_ref ("which_alternative"))
7526                           (const_int 3))
7527                       (eq_attr "length" "8"))
7528                  (eq_attr "length" "10"))
7529             (const_string "yes")
7530             (const_string "no")))
7531    (set (attr "length")
7532      (if_then_else
7533        (lt (symbol_ref ("which_alternative"))
7534                        (const_int 3))
7535        (if_then_else
7536          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7537               (le (minus (match_dup 5) (pc)) (const_int 256)))
7538          (const_int 4)
7539          (if_then_else
7540            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7541                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7542            (const_int 6)
7543            (const_int 8)))
7544        (if_then_else
7545          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7546               (le (minus (match_dup 5) (pc)) (const_int 256)))
7547          (const_int 6)
7548          (if_then_else
7549            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7550                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7551            (const_int 8)
7552            (const_int 10)))))]
7553 )
7554
7555 (define_insn "*addsi3_cbranch_scratch"
7556   [(set (pc)
7557         (if_then_else
7558          (match_operator 3 "arm_comparison_operator"
7559           [(plus:SI
7560             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
7561             (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
7562            (const_int 0)])
7563          (label_ref (match_operand 4 "" ""))
7564          (pc)))
7565    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
7566   "TARGET_THUMB1
7567    && (GET_CODE (operands[3]) == EQ
7568        || GET_CODE (operands[3]) == NE
7569        || GET_CODE (operands[3]) == GE
7570        || GET_CODE (operands[3]) == LT)"
7571   "*
7572    {
7573      switch (which_alternative)
7574        {
7575        case 0:
7576          output_asm_insn (\"cmp\t%1, #%n2\", operands);
7577          break;
7578        case 1:
7579          output_asm_insn (\"cmn\t%1, %2\", operands);
7580          break;
7581        case 2:
7582          if (INTVAL (operands[2]) < 0)
7583            output_asm_insn (\"sub\t%0, %1, %2\", operands);
7584          else
7585            output_asm_insn (\"add\t%0, %1, %2\", operands);
7586          break;
7587        case 3:
7588          if (INTVAL (operands[2]) < 0)
7589            output_asm_insn (\"sub\t%0, %0, %2\", operands);
7590          else
7591            output_asm_insn (\"add\t%0, %0, %2\", operands);
7592          break;
7593        }
7594
7595      switch (get_attr_length (insn))
7596        {
7597          case 4:
7598            return \"b%d3\\t%l4\";
7599          case 6:
7600            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7601          default:
7602            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7603        }
7604    }
7605   "
7606   [(set (attr "far_jump")
7607         (if_then_else
7608             (eq_attr "length" "8")
7609             (const_string "yes")
7610             (const_string "no")))
7611    (set (attr "length")
7612        (if_then_else
7613          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7614               (le (minus (match_dup 4) (pc)) (const_int 256)))
7615          (const_int 4)
7616          (if_then_else
7617            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7618                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7619            (const_int 6)
7620            (const_int 8))))]
7621 )
7622
7623 (define_insn "*subsi3_cbranch"
7624   [(set (pc)
7625         (if_then_else
7626          (match_operator 4 "arm_comparison_operator"
7627           [(minus:SI
7628             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
7629             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7630            (const_int 0)])
7631          (label_ref (match_operand 5 "" ""))
7632          (pc)))
7633    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
7634         (minus:SI (match_dup 2) (match_dup 3)))
7635    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
7636   "TARGET_THUMB1
7637    && (GET_CODE (operands[4]) == EQ
7638        || GET_CODE (operands[4]) == NE
7639        || GET_CODE (operands[4]) == GE
7640        || GET_CODE (operands[4]) == LT)"
7641   "*
7642    {
7643      if (which_alternative == 0)
7644        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
7645      else if (which_alternative == 1)
7646        {
7647          /* We must provide an alternative for a hi reg because reload 
7648             cannot handle output reloads on a jump instruction, but we
7649             can't subtract into that.  Fortunately a mov from lo to hi
7650             does not clobber the condition codes.  */
7651          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
7652          output_asm_insn (\"mov\\t%0, %1\", operands);
7653        }
7654      else
7655        {
7656          /* Similarly, but the target is memory.  */
7657          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
7658          output_asm_insn (\"str\\t%1, %0\", operands);
7659        }
7660
7661      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
7662        {
7663          case 4:
7664            return \"b%d4\\t%l5\";
7665          case 6:
7666            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7667          default:
7668            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7669        }
7670    }
7671   "
7672   [(set (attr "far_jump")
7673         (if_then_else
7674             (ior (and (eq (symbol_ref ("which_alternative"))
7675                           (const_int 0))
7676                       (eq_attr "length" "8"))
7677                  (eq_attr "length" "10"))
7678             (const_string "yes")
7679             (const_string "no")))
7680    (set (attr "length")
7681      (if_then_else
7682        (eq (symbol_ref ("which_alternative"))
7683                        (const_int 0))
7684        (if_then_else
7685          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7686               (le (minus (match_dup 5) (pc)) (const_int 256)))
7687          (const_int 4)
7688          (if_then_else
7689            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7690                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7691            (const_int 6)
7692            (const_int 8)))
7693        (if_then_else
7694          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7695               (le (minus (match_dup 5) (pc)) (const_int 256)))
7696          (const_int 6)
7697          (if_then_else
7698            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7699                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7700            (const_int 8)
7701            (const_int 10)))))]
7702 )
7703
7704 (define_insn "*subsi3_cbranch_scratch"
7705   [(set (pc)
7706         (if_then_else
7707          (match_operator 0 "arm_comparison_operator"
7708           [(minus:SI (match_operand:SI 1 "register_operand" "l")
7709                      (match_operand:SI 2 "nonmemory_operand" "l"))
7710            (const_int 0)])
7711          (label_ref (match_operand 3 "" ""))
7712          (pc)))]
7713   "TARGET_THUMB1
7714    && (GET_CODE (operands[0]) == EQ
7715        || GET_CODE (operands[0]) == NE
7716        || GET_CODE (operands[0]) == GE
7717        || GET_CODE (operands[0]) == LT)"
7718   "*
7719   output_asm_insn (\"cmp\\t%1, %2\", operands);
7720   switch (get_attr_length (insn))
7721     {
7722     case 4:  return \"b%d0\\t%l3\";
7723     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7724     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7725     }
7726   "
7727   [(set (attr "far_jump")
7728         (if_then_else
7729             (eq_attr "length" "8")
7730             (const_string "yes")
7731             (const_string "no")))
7732    (set (attr "length") 
7733         (if_then_else
7734             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7735                  (le (minus (match_dup 3) (pc)) (const_int 256)))
7736             (const_int 4)
7737             (if_then_else
7738                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7739                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
7740                 (const_int 6)
7741                 (const_int 8))))]
7742 )
7743
7744 ;; Comparison and test insns
7745
7746 (define_insn "*arm_cmpsi_insn"
7747   [(set (reg:CC CC_REGNUM)
7748         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
7749                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
7750   "TARGET_32BIT"
7751   "@
7752    cmp%?\\t%0, %1
7753    cmn%?\\t%0, #%n1"
7754   [(set_attr "conds" "set")]
7755 )
7756
7757 (define_insn "*arm_cmpsi_shiftsi"
7758   [(set (reg:CC CC_REGNUM)
7759         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
7760                     (match_operator:SI  3 "shift_operator"
7761                      [(match_operand:SI 1 "s_register_operand" "r")
7762                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
7763   "TARGET_ARM"
7764   "cmp%?\\t%0, %1%S3"
7765   [(set_attr "conds" "set")
7766    (set_attr "shift" "1")
7767    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
7768                       (const_string "alu_shift")
7769                       (const_string "alu_shift_reg")))]
7770 )
7771
7772 (define_insn "*arm_cmpsi_shiftsi_swp"
7773   [(set (reg:CC_SWP CC_REGNUM)
7774         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
7775                          [(match_operand:SI 1 "s_register_operand" "r")
7776                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
7777                         (match_operand:SI 0 "s_register_operand" "r")))]
7778   "TARGET_ARM"
7779   "cmp%?\\t%0, %1%S3"
7780   [(set_attr "conds" "set")
7781    (set_attr "shift" "1")
7782    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
7783                       (const_string "alu_shift")
7784                       (const_string "alu_shift_reg")))]
7785 )
7786
7787 (define_insn "*arm_cmpsi_negshiftsi_si"
7788   [(set (reg:CC_Z CC_REGNUM)
7789         (compare:CC_Z
7790          (neg:SI (match_operator:SI 1 "shift_operator"
7791                     [(match_operand:SI 2 "s_register_operand" "r")
7792                      (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7793          (match_operand:SI 0 "s_register_operand" "r")))]
7794   "TARGET_ARM"
7795   "cmn%?\\t%0, %2%S1"
7796   [(set_attr "conds" "set")
7797    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7798                                     (const_string "alu_shift")
7799                                     (const_string "alu_shift_reg")))]
7800 )
7801
7802 ;; DImode comparisons.  The generic code generates branches that
7803 ;; if-conversion can not reduce to a conditional compare, so we do
7804 ;; that directly.
7805
7806 (define_insn "*arm_cmpdi_insn"
7807   [(set (reg:CC_NCV CC_REGNUM)
7808         (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
7809                         (match_operand:DI 1 "arm_di_operand"       "rDi")))
7810    (clobber (match_scratch:SI 2 "=r"))]
7811   "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
7812   "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
7813   [(set_attr "conds" "set")
7814    (set_attr "length" "8")]
7815 )
7816
7817 (define_insn "*arm_cmpdi_unsigned"
7818   [(set (reg:CC_CZ CC_REGNUM)
7819         (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "r")
7820                        (match_operand:DI 1 "arm_di_operand"     "rDi")))]
7821   "TARGET_ARM"
7822   "cmp%?\\t%R0, %R1\;cmpeq\\t%Q0, %Q1"
7823   [(set_attr "conds" "set")
7824    (set_attr "length" "8")]
7825 )
7826
7827 (define_insn "*arm_cmpdi_zero"
7828   [(set (reg:CC_Z CC_REGNUM)
7829         (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
7830                       (const_int 0)))
7831    (clobber (match_scratch:SI 1 "=r"))]
7832   "TARGET_32BIT"
7833   "orr%.\\t%1, %Q0, %R0"
7834   [(set_attr "conds" "set")]
7835 )
7836
7837 (define_insn "*thumb_cmpdi_zero"
7838   [(set (reg:CC_Z CC_REGNUM)
7839         (compare:CC_Z (match_operand:DI 0 "s_register_operand" "l")
7840                       (const_int 0)))
7841    (clobber (match_scratch:SI 1 "=l"))]
7842   "TARGET_THUMB1"
7843   "orr\\t%1, %Q0, %R0"
7844   [(set_attr "conds" "set")
7845    (set_attr "length" "2")]
7846 )
7847
7848 ;; Cirrus SF compare instruction
7849 (define_insn "*cirrus_cmpsf"
7850   [(set (reg:CCFP CC_REGNUM)
7851         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
7852                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
7853   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7854   "cfcmps%?\\tr15, %V0, %V1"
7855   [(set_attr "type"   "mav_farith")
7856    (set_attr "cirrus" "compare")]
7857 )
7858
7859 ;; Cirrus DF compare instruction
7860 (define_insn "*cirrus_cmpdf"
7861   [(set (reg:CCFP CC_REGNUM)
7862         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
7863                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
7864   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7865   "cfcmpd%?\\tr15, %V0, %V1"
7866   [(set_attr "type"   "mav_farith")
7867    (set_attr "cirrus" "compare")]
7868 )
7869
7870 (define_insn "*cirrus_cmpdi"
7871   [(set (reg:CC CC_REGNUM)
7872         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
7873                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
7874   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7875   "cfcmp64%?\\tr15, %V0, %V1"
7876   [(set_attr "type"   "mav_farith")
7877    (set_attr "cirrus" "compare")]
7878 )
7879
7880 ; This insn allows redundant compares to be removed by cse, nothing should
7881 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7882 ; is deleted later on. The match_dup will match the mode here, so that
7883 ; mode changes of the condition codes aren't lost by this even though we don't
7884 ; specify what they are.
7885
7886 (define_insn "*deleted_compare"
7887   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
7888   "TARGET_32BIT"
7889   "\\t%@ deleted compare"
7890   [(set_attr "conds" "set")
7891    (set_attr "length" "0")]
7892 )
7893
7894 \f
7895 ;; Conditional branch insns
7896
7897 (define_expand "cbranch_cc"
7898   [(set (pc)
7899         (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7900                                             (match_operand 2 "" "")])
7901                       (label_ref (match_operand 3 "" ""))
7902                       (pc)))]
7903   "TARGET_32BIT"
7904   "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
7905                                       operands[1], operands[2]);
7906    operands[2] = const0_rtx;"
7907 )
7908
7909 ;;
7910 ;; Patterns to match conditional branch insns.
7911 ;;
7912
7913 (define_insn "*arm_cond_branch"
7914   [(set (pc)
7915         (if_then_else (match_operator 1 "arm_comparison_operator"
7916                        [(match_operand 2 "cc_register" "") (const_int 0)])
7917                       (label_ref (match_operand 0 "" ""))
7918                       (pc)))]
7919   "TARGET_32BIT"
7920   "*
7921   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7922     {
7923       arm_ccfsm_state += 2;
7924       return \"\";
7925     }
7926   return \"b%d1\\t%l0\";
7927   "
7928   [(set_attr "conds" "use")
7929    (set_attr "type" "branch")]
7930 )
7931
7932 (define_insn "*arm_cond_branch_reversed"
7933   [(set (pc)
7934         (if_then_else (match_operator 1 "arm_comparison_operator"
7935                        [(match_operand 2 "cc_register" "") (const_int 0)])
7936                       (pc)
7937                       (label_ref (match_operand 0 "" ""))))]
7938   "TARGET_32BIT"
7939   "*
7940   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7941     {
7942       arm_ccfsm_state += 2;
7943       return \"\";
7944     }
7945   return \"b%D1\\t%l0\";
7946   "
7947   [(set_attr "conds" "use")
7948    (set_attr "type" "branch")]
7949 )
7950
7951 \f
7952
7953 ; scc insns
7954
7955 (define_expand "cstore_cc"
7956   [(set (match_operand:SI 0 "s_register_operand" "")
7957         (match_operator:SI 1 "" [(match_operand 2 "" "")
7958                                  (match_operand 3 "" "")]))]
7959   "TARGET_32BIT"
7960   "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
7961                                       operands[2], operands[3]);
7962    operands[3] = const0_rtx;"
7963 )
7964
7965 (define_insn "*mov_scc"
7966   [(set (match_operand:SI 0 "s_register_operand" "=r")
7967         (match_operator:SI 1 "arm_comparison_operator"
7968          [(match_operand 2 "cc_register" "") (const_int 0)]))]
7969   "TARGET_ARM"
7970   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7971   [(set_attr "conds" "use")
7972    (set_attr "length" "8")]
7973 )
7974
7975 (define_insn "*mov_negscc"
7976   [(set (match_operand:SI 0 "s_register_operand" "=r")
7977         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7978                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7979   "TARGET_ARM"
7980   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7981   [(set_attr "conds" "use")
7982    (set_attr "length" "8")]
7983 )
7984
7985 (define_insn "*mov_notscc"
7986   [(set (match_operand:SI 0 "s_register_operand" "=r")
7987         (not:SI (match_operator:SI 1 "arm_comparison_operator"
7988                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7989   "TARGET_ARM"
7990   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7991   [(set_attr "conds" "use")
7992    (set_attr "length" "8")]
7993 )
7994
7995 (define_expand "cstoresi4"
7996   [(set (match_operand:SI 0 "s_register_operand" "")
7997         (match_operator:SI 1 "arm_comparison_operator"
7998          [(match_operand:SI 2 "s_register_operand" "")
7999           (match_operand:SI 3 "reg_or_int_operand" "")]))]
8000   "TARGET_32BIT || TARGET_THUMB1"
8001   "{
8002   rtx op3, scratch, scratch2;
8003
8004   if (!TARGET_THUMB1)
8005     {
8006       if (!arm_add_operand (operands[3], SImode))
8007         operands[3] = force_reg (SImode, operands[3]);
8008       emit_insn (gen_cstore_cc (operands[0], operands[1],
8009                                 operands[2], operands[3]));
8010       DONE;
8011     }
8012
8013   if (operands[3] == const0_rtx)
8014     {
8015       switch (GET_CODE (operands[1]))
8016         {
8017         case EQ:
8018           emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
8019           break;
8020
8021         case NE:
8022           emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
8023           break;
8024
8025         case LE:
8026           scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
8027                                   NULL_RTX, 0, OPTAB_WIDEN);
8028           scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
8029                                   NULL_RTX, 0, OPTAB_WIDEN);
8030           expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
8031                         operands[0], 1, OPTAB_WIDEN);
8032           break;
8033
8034         case GE:
8035           scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
8036                                  NULL_RTX, 1);
8037           expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
8038                         NULL_RTX, 1, OPTAB_WIDEN);
8039           break;
8040
8041         case GT:
8042           scratch = expand_binop (SImode, ashr_optab, operands[2],
8043                                   GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
8044           scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
8045                                   NULL_RTX, 0, OPTAB_WIDEN);
8046           expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
8047                         0, OPTAB_WIDEN);
8048           break;
8049
8050         /* LT is handled by generic code.  No need for unsigned with 0.  */
8051         default:
8052           FAIL;
8053         }
8054       DONE;
8055     }
8056
8057   switch (GET_CODE (operands[1]))
8058     {
8059     case EQ:
8060       scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
8061                               NULL_RTX, 0, OPTAB_WIDEN);
8062       emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
8063       break;
8064
8065     case NE:
8066       scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
8067                               NULL_RTX, 0, OPTAB_WIDEN);
8068       emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
8069       break;
8070
8071     case LE:
8072       op3 = force_reg (SImode, operands[3]);
8073
8074       scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
8075                               NULL_RTX, 1, OPTAB_WIDEN);
8076       scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
8077                               NULL_RTX, 0, OPTAB_WIDEN);
8078       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
8079                                           op3, operands[2]));
8080       break;
8081
8082     case GE:
8083       op3 = operands[3];
8084       if (!thumb1_cmp_operand (op3, SImode))
8085         op3 = force_reg (SImode, op3);
8086       scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
8087                               NULL_RTX, 0, OPTAB_WIDEN);
8088       scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
8089                                NULL_RTX, 1, OPTAB_WIDEN);
8090       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
8091                                           operands[2], op3));
8092       break;
8093
8094     case LEU:
8095       op3 = force_reg (SImode, operands[3]);
8096       scratch = force_reg (SImode, const0_rtx);
8097       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
8098                                           op3, operands[2]));
8099       break;
8100
8101     case GEU:
8102       op3 = operands[3];
8103       if (!thumb1_cmp_operand (op3, SImode))
8104         op3 = force_reg (SImode, op3);
8105       scratch = force_reg (SImode, const0_rtx);
8106       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
8107                                           operands[2], op3));
8108       break;
8109
8110     case LTU:
8111       op3 = operands[3];
8112       if (!thumb1_cmp_operand (op3, SImode))
8113         op3 = force_reg (SImode, op3);
8114       scratch = gen_reg_rtx (SImode);
8115       emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
8116       break;
8117
8118     case GTU:
8119       op3 = force_reg (SImode, operands[3]);
8120       scratch = gen_reg_rtx (SImode);
8121       emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
8122       break;
8123
8124     /* No good sequences for GT, LT.  */
8125     default:
8126       FAIL;
8127     }
8128   DONE;
8129 }")
8130
8131 (define_expand "cstoresf4"
8132   [(set (match_operand:SI 0 "s_register_operand" "")
8133         (match_operator:SI 1 "arm_comparison_operator"
8134          [(match_operand:SF 2 "s_register_operand" "")
8135           (match_operand:SF 3 "arm_float_compare_operand" "")]))]
8136   "TARGET_32BIT && TARGET_HARD_FLOAT"
8137   "emit_insn (gen_cstore_cc (operands[0], operands[1],
8138                              operands[2], operands[3])); DONE;"
8139 )
8140
8141 (define_expand "cstoredf4"
8142   [(set (match_operand:SI 0 "s_register_operand" "")
8143         (match_operator:SI 1 "arm_comparison_operator"
8144          [(match_operand:DF 2 "s_register_operand" "")
8145           (match_operand:DF 3 "arm_float_compare_operand" "")]))]
8146   "TARGET_32BIT && TARGET_HARD_FLOAT"
8147   "emit_insn (gen_cstore_cc (operands[0], operands[1],
8148                              operands[2], operands[3])); DONE;"
8149 )
8150
8151 (define_expand "cstoredi4"
8152   [(set (match_operand:SI 0 "s_register_operand" "")
8153         (match_operator:SI 1 "arm_comparison_operator"
8154          [(match_operand:DI 2 "cmpdi_operand" "")
8155           (match_operand:DI 3 "cmpdi_operand" "")]))]
8156   "TARGET_32BIT"
8157   "{
8158      rtx swap = NULL_RTX;
8159      enum rtx_code code = GET_CODE (operands[1]);
8160
8161      /* We should not have two constants.  */
8162      gcc_assert (GET_MODE (operands[2]) == DImode
8163                  || GET_MODE (operands[3]) == DImode);
8164
8165     /* Flip unimplemented DImode comparisons to a form that
8166        arm_gen_compare_reg can handle.  */
8167      switch (code)
8168      {
8169      case GT:
8170        swap = gen_rtx_LT (VOIDmode, operands[3], operands[2]); break;
8171      case LE:
8172        swap = gen_rtx_GE (VOIDmode, operands[3], operands[2]); break;
8173      case GTU:
8174        swap = gen_rtx_LTU (VOIDmode, operands[3], operands[2]); break;
8175      case LEU:
8176        swap = gen_rtx_GEU (VOIDmode, operands[3], operands[2]); break;
8177      default:
8178        break;
8179      }
8180      if (swap)
8181        emit_insn (gen_cstore_cc (operands[0], swap, operands[3],
8182                                  operands[2]));
8183      else
8184        emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
8185                                  operands[3]));
8186      DONE;
8187    }"
8188 )
8189
8190 (define_expand "cstoresi_eq0_thumb1"
8191   [(parallel
8192     [(set (match_operand:SI 0 "s_register_operand" "")
8193           (eq:SI (match_operand:SI 1 "s_register_operand" "")
8194                  (const_int 0)))
8195      (clobber (match_dup:SI 2))])]
8196   "TARGET_THUMB1"
8197   "operands[2] = gen_reg_rtx (SImode);"
8198 )
8199
8200 (define_expand "cstoresi_ne0_thumb1"
8201   [(parallel
8202     [(set (match_operand:SI 0 "s_register_operand" "")
8203           (ne:SI (match_operand:SI 1 "s_register_operand" "")
8204                  (const_int 0)))
8205      (clobber (match_dup:SI 2))])]
8206   "TARGET_THUMB1"
8207   "operands[2] = gen_reg_rtx (SImode);"
8208 )
8209
8210 (define_insn "*cstoresi_eq0_thumb1_insn"
8211   [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
8212         (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
8213                (const_int 0)))
8214    (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
8215   "TARGET_THUMB1"
8216   "@
8217    neg\\t%0, %1\;adc\\t%0, %0, %1
8218    neg\\t%2, %1\;adc\\t%0, %1, %2"
8219   [(set_attr "length" "4")]
8220 )
8221
8222 (define_insn "*cstoresi_ne0_thumb1_insn"
8223   [(set (match_operand:SI 0 "s_register_operand" "=l")
8224         (ne:SI (match_operand:SI 1 "s_register_operand" "0")
8225                (const_int 0)))
8226    (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
8227   "TARGET_THUMB1"
8228   "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
8229   [(set_attr "length" "4")]
8230 )
8231
8232 ;; Used as part of the expansion of thumb ltu and gtu sequences
8233 (define_insn "cstoresi_nltu_thumb1"
8234   [(set (match_operand:SI 0 "s_register_operand" "=l,l")
8235         (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
8236                         (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
8237   "TARGET_THUMB1"
8238   "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
8239   [(set_attr "length" "4")]
8240 )
8241
8242 (define_insn_and_split "cstoresi_ltu_thumb1"
8243   [(set (match_operand:SI 0 "s_register_operand" "=l,l")
8244         (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
8245                 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")))]
8246   "TARGET_THUMB1"
8247   "#"
8248   "TARGET_THUMB1"
8249   [(set (match_dup 3)
8250         (neg:SI (ltu:SI (match_dup 1) (match_dup 2))))
8251    (set (match_dup 0) (neg:SI (match_dup 3)))]
8252   "operands[3] = gen_reg_rtx (SImode);"
8253   [(set_attr "length" "4")]
8254 )
8255
8256 ;; Used as part of the expansion of thumb les sequence.
8257 (define_insn "thumb1_addsi3_addgeu"
8258   [(set (match_operand:SI 0 "s_register_operand" "=l")
8259         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8260                           (match_operand:SI 2 "s_register_operand" "l"))
8261                  (geu:SI (match_operand:SI 3 "s_register_operand" "l")
8262                          (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
8263   "TARGET_THUMB1"
8264   "cmp\\t%3, %4\;adc\\t%0, %1, %2"
8265   [(set_attr "length" "4")]
8266 )
8267
8268 \f
8269 ;; Conditional move insns
8270
8271 (define_expand "movsicc"
8272   [(set (match_operand:SI 0 "s_register_operand" "")
8273         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
8274                          (match_operand:SI 2 "arm_not_operand" "")
8275                          (match_operand:SI 3 "arm_not_operand" "")))]
8276   "TARGET_32BIT"
8277   "
8278   {
8279     enum rtx_code code = GET_CODE (operands[1]);
8280     rtx ccreg;
8281
8282     if (code == UNEQ || code == LTGT)
8283       FAIL;
8284
8285     ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8286                                  XEXP (operands[1], 1));
8287     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
8288   }"
8289 )
8290
8291 (define_expand "movsfcc"
8292   [(set (match_operand:SF 0 "s_register_operand" "")
8293         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
8294                          (match_operand:SF 2 "s_register_operand" "")
8295                          (match_operand:SF 3 "nonmemory_operand" "")))]
8296   "TARGET_32BIT && TARGET_HARD_FLOAT"
8297   "
8298   {
8299     enum rtx_code code = GET_CODE (operands[1]);
8300     rtx ccreg;
8301
8302     if (code == UNEQ || code == LTGT)
8303       FAIL;
8304
8305     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
8306        Otherwise, ensure it is a valid FP add operand */
8307     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
8308         || (!arm_float_add_operand (operands[3], SFmode)))
8309       operands[3] = force_reg (SFmode, operands[3]);
8310
8311     ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8312                                  XEXP (operands[1], 1));
8313     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
8314   }"
8315 )
8316
8317 (define_expand "movdfcc"
8318   [(set (match_operand:DF 0 "s_register_operand" "")
8319         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
8320                          (match_operand:DF 2 "s_register_operand" "")
8321                          (match_operand:DF 3 "arm_float_add_operand" "")))]
8322   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
8323   "
8324   {
8325     enum rtx_code code = GET_CODE (operands[1]);
8326     rtx ccreg;
8327
8328     if (code == UNEQ || code == LTGT)
8329       FAIL;
8330
8331     ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8332                                  XEXP (operands[1], 1));
8333     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
8334   }"
8335 )
8336
8337 (define_insn "*movsicc_insn"
8338   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8339         (if_then_else:SI
8340          (match_operator 3 "arm_comparison_operator"
8341           [(match_operand 4 "cc_register" "") (const_int 0)])
8342          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
8343          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
8344   "TARGET_ARM"
8345   "@
8346    mov%D3\\t%0, %2
8347    mvn%D3\\t%0, #%B2
8348    mov%d3\\t%0, %1
8349    mvn%d3\\t%0, #%B1
8350    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
8351    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
8352    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
8353    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
8354   [(set_attr "length" "4,4,4,4,8,8,8,8")
8355    (set_attr "conds" "use")]
8356 )
8357
8358 (define_insn "*movsfcc_soft_insn"
8359   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8360         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8361                           [(match_operand 4 "cc_register" "") (const_int 0)])
8362                          (match_operand:SF 1 "s_register_operand" "0,r")
8363                          (match_operand:SF 2 "s_register_operand" "r,0")))]
8364   "TARGET_ARM && TARGET_SOFT_FLOAT"
8365   "@
8366    mov%D3\\t%0, %2
8367    mov%d3\\t%0, %1"
8368   [(set_attr "conds" "use")]
8369 )
8370
8371 \f
8372 ;; Jump and linkage insns
8373
8374 (define_expand "jump"
8375   [(set (pc)
8376         (label_ref (match_operand 0 "" "")))]
8377   "TARGET_EITHER"
8378   ""
8379 )
8380
8381 (define_insn "*arm_jump"
8382   [(set (pc)
8383         (label_ref (match_operand 0 "" "")))]
8384   "TARGET_32BIT"
8385   "*
8386   {
8387     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
8388       {
8389         arm_ccfsm_state += 2;
8390         return \"\";
8391       }
8392     return \"b%?\\t%l0\";
8393   }
8394   "
8395   [(set_attr "predicable" "yes")]
8396 )
8397
8398 (define_insn "*thumb_jump"
8399   [(set (pc)
8400         (label_ref (match_operand 0 "" "")))]
8401   "TARGET_THUMB1"
8402   "*
8403   if (get_attr_length (insn) == 2)
8404     return \"b\\t%l0\";
8405   return \"bl\\t%l0\\t%@ far jump\";
8406   "
8407   [(set (attr "far_jump")
8408         (if_then_else
8409             (eq_attr "length" "4")
8410             (const_string "yes")
8411             (const_string "no")))
8412    (set (attr "length") 
8413         (if_then_else
8414             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8415                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
8416             (const_int 2)
8417             (const_int 4)))]
8418 )
8419
8420 (define_expand "call"
8421   [(parallel [(call (match_operand 0 "memory_operand" "")
8422                     (match_operand 1 "general_operand" ""))
8423               (use (match_operand 2 "" ""))
8424               (clobber (reg:SI LR_REGNUM))])]
8425   "TARGET_EITHER"
8426   "
8427   {
8428     rtx callee, pat;
8429     
8430     /* In an untyped call, we can get NULL for operand 2.  */
8431     if (operands[2] == NULL_RTX)
8432       operands[2] = const0_rtx;
8433       
8434     /* Decide if we should generate indirect calls by loading the
8435        32-bit address of the callee into a register before performing the
8436        branch and link.  */
8437     callee = XEXP (operands[0], 0);
8438     if (GET_CODE (callee) == SYMBOL_REF
8439         ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8440         : !REG_P (callee))
8441       XEXP (operands[0], 0) = force_reg (Pmode, callee);
8442
8443     pat = gen_call_internal (operands[0], operands[1], operands[2]);
8444     arm_emit_call_insn (pat, XEXP (operands[0], 0));
8445     DONE;
8446   }"
8447 )
8448
8449 (define_expand "call_internal"
8450   [(parallel [(call (match_operand 0 "memory_operand" "")
8451                     (match_operand 1 "general_operand" ""))
8452               (use (match_operand 2 "" ""))
8453               (clobber (reg:SI LR_REGNUM))])])
8454
8455 (define_insn "*call_reg_armv5"
8456   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8457          (match_operand 1 "" ""))
8458    (use (match_operand 2 "" ""))
8459    (clobber (reg:SI LR_REGNUM))]
8460   "TARGET_ARM && arm_arch5"
8461   "blx%?\\t%0"
8462   [(set_attr "type" "call")]
8463 )
8464
8465 (define_insn "*call_reg_arm"
8466   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8467          (match_operand 1 "" ""))
8468    (use (match_operand 2 "" ""))
8469    (clobber (reg:SI LR_REGNUM))]
8470   "TARGET_ARM && !arm_arch5"
8471   "*
8472   return output_call (operands);
8473   "
8474   ;; length is worst case, normally it is only two
8475   [(set_attr "length" "12")
8476    (set_attr "type" "call")]
8477 )
8478
8479
8480 ;; Note: not used for armv5+ because the sequence used (ldr pc, ...) is not
8481 ;; considered a function call by the branch predictor of some cores (PR40887).
8482 ;; Falls back to blx rN (*call_reg_armv5).
8483
8484 (define_insn "*call_mem"
8485   [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
8486          (match_operand 1 "" ""))
8487    (use (match_operand 2 "" ""))
8488    (clobber (reg:SI LR_REGNUM))]
8489   "TARGET_ARM && !arm_arch5"
8490   "*
8491   return output_call_mem (operands);
8492   "
8493   [(set_attr "length" "12")
8494    (set_attr "type" "call")]
8495 )
8496
8497 (define_insn "*call_reg_thumb1_v5"
8498   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8499          (match_operand 1 "" ""))
8500    (use (match_operand 2 "" ""))
8501    (clobber (reg:SI LR_REGNUM))]
8502   "TARGET_THUMB1 && arm_arch5"
8503   "blx\\t%0"
8504   [(set_attr "length" "2")
8505    (set_attr "type" "call")]
8506 )
8507
8508 (define_insn "*call_reg_thumb1"
8509   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8510          (match_operand 1 "" ""))
8511    (use (match_operand 2 "" ""))
8512    (clobber (reg:SI LR_REGNUM))]
8513   "TARGET_THUMB1 && !arm_arch5"
8514   "*
8515   {
8516     if (!TARGET_CALLER_INTERWORKING)
8517       return thumb_call_via_reg (operands[0]);
8518     else if (operands[1] == const0_rtx)
8519       return \"bl\\t%__interwork_call_via_%0\";
8520     else if (frame_pointer_needed)
8521       return \"bl\\t%__interwork_r7_call_via_%0\";
8522     else
8523       return \"bl\\t%__interwork_r11_call_via_%0\";
8524   }"
8525   [(set_attr "type" "call")]
8526 )
8527
8528 (define_expand "call_value"
8529   [(parallel [(set (match_operand       0 "" "")
8530                    (call (match_operand 1 "memory_operand" "")
8531                          (match_operand 2 "general_operand" "")))
8532               (use (match_operand 3 "" ""))
8533               (clobber (reg:SI LR_REGNUM))])]
8534   "TARGET_EITHER"
8535   "
8536   {
8537     rtx pat, callee;
8538     
8539     /* In an untyped call, we can get NULL for operand 2.  */
8540     if (operands[3] == 0)
8541       operands[3] = const0_rtx;
8542       
8543     /* Decide if we should generate indirect calls by loading the
8544        32-bit address of the callee into a register before performing the
8545        branch and link.  */
8546     callee = XEXP (operands[1], 0);
8547     if (GET_CODE (callee) == SYMBOL_REF
8548         ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8549         : !REG_P (callee))
8550       XEXP (operands[1], 0) = force_reg (Pmode, callee);
8551
8552     pat = gen_call_value_internal (operands[0], operands[1],
8553                                    operands[2], operands[3]);
8554     arm_emit_call_insn (pat, XEXP (operands[1], 0));
8555     DONE;
8556   }"
8557 )
8558
8559 (define_expand "call_value_internal"
8560   [(parallel [(set (match_operand       0 "" "")
8561                    (call (match_operand 1 "memory_operand" "")
8562                          (match_operand 2 "general_operand" "")))
8563               (use (match_operand 3 "" ""))
8564               (clobber (reg:SI LR_REGNUM))])])
8565
8566 (define_insn "*call_value_reg_armv5"
8567   [(set (match_operand 0 "" "")
8568         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8569               (match_operand 2 "" "")))
8570    (use (match_operand 3 "" ""))
8571    (clobber (reg:SI LR_REGNUM))]
8572   "TARGET_ARM && arm_arch5"
8573   "blx%?\\t%1"
8574   [(set_attr "type" "call")]
8575 )
8576
8577 (define_insn "*call_value_reg_arm"
8578   [(set (match_operand 0 "" "")
8579         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8580               (match_operand 2 "" "")))
8581    (use (match_operand 3 "" ""))
8582    (clobber (reg:SI LR_REGNUM))]
8583   "TARGET_ARM && !arm_arch5"
8584   "*
8585   return output_call (&operands[1]);
8586   "
8587   [(set_attr "length" "12")
8588    (set_attr "type" "call")]
8589 )
8590
8591 ;; Note: see *call_mem
8592
8593 (define_insn "*call_value_mem"
8594   [(set (match_operand 0 "" "")
8595         (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
8596               (match_operand 2 "" "")))
8597    (use (match_operand 3 "" ""))
8598    (clobber (reg:SI LR_REGNUM))]
8599   "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
8600   "*
8601   return output_call_mem (&operands[1]);
8602   "
8603   [(set_attr "length" "12")
8604    (set_attr "type" "call")]
8605 )
8606
8607 (define_insn "*call_value_reg_thumb1_v5"
8608   [(set (match_operand 0 "" "")
8609         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8610               (match_operand 2 "" "")))
8611    (use (match_operand 3 "" ""))
8612    (clobber (reg:SI LR_REGNUM))]
8613   "TARGET_THUMB1 && arm_arch5"
8614   "blx\\t%1"
8615   [(set_attr "length" "2")
8616    (set_attr "type" "call")]
8617 )
8618
8619 (define_insn "*call_value_reg_thumb1"
8620   [(set (match_operand 0 "" "")
8621         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8622               (match_operand 2 "" "")))
8623    (use (match_operand 3 "" ""))
8624    (clobber (reg:SI LR_REGNUM))]
8625   "TARGET_THUMB1 && !arm_arch5"
8626   "*
8627   {
8628     if (!TARGET_CALLER_INTERWORKING)
8629       return thumb_call_via_reg (operands[1]);
8630     else if (operands[2] == const0_rtx)
8631       return \"bl\\t%__interwork_call_via_%1\";
8632     else if (frame_pointer_needed)
8633       return \"bl\\t%__interwork_r7_call_via_%1\";
8634     else
8635       return \"bl\\t%__interwork_r11_call_via_%1\";
8636   }"
8637   [(set_attr "type" "call")]
8638 )
8639
8640 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8641 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8642
8643 (define_insn "*call_symbol"
8644   [(call (mem:SI (match_operand:SI 0 "" ""))
8645          (match_operand 1 "" ""))
8646    (use (match_operand 2 "" ""))
8647    (clobber (reg:SI LR_REGNUM))]
8648   "TARGET_32BIT
8649    && (GET_CODE (operands[0]) == SYMBOL_REF)
8650    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
8651   "*
8652   {
8653     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
8654   }"
8655   [(set_attr "type" "call")]
8656 )
8657
8658 (define_insn "*call_value_symbol"
8659   [(set (match_operand 0 "" "")
8660         (call (mem:SI (match_operand:SI 1 "" ""))
8661         (match_operand:SI 2 "" "")))
8662    (use (match_operand 3 "" ""))
8663    (clobber (reg:SI LR_REGNUM))]
8664   "TARGET_32BIT
8665    && (GET_CODE (operands[1]) == SYMBOL_REF)
8666    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
8667   "*
8668   {
8669     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
8670   }"
8671   [(set_attr "type" "call")]
8672 )
8673
8674 (define_insn "*call_insn"
8675   [(call (mem:SI (match_operand:SI 0 "" ""))
8676          (match_operand:SI 1 "" ""))
8677    (use (match_operand 2 "" ""))
8678    (clobber (reg:SI LR_REGNUM))]
8679   "TARGET_THUMB1
8680    && GET_CODE (operands[0]) == SYMBOL_REF
8681    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
8682   "bl\\t%a0"
8683   [(set_attr "length" "4")
8684    (set_attr "type" "call")]
8685 )
8686
8687 (define_insn "*call_value_insn"
8688   [(set (match_operand 0 "" "")
8689         (call (mem:SI (match_operand 1 "" ""))
8690               (match_operand 2 "" "")))
8691    (use (match_operand 3 "" ""))
8692    (clobber (reg:SI LR_REGNUM))]
8693   "TARGET_THUMB1
8694    && GET_CODE (operands[1]) == SYMBOL_REF
8695    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
8696   "bl\\t%a1"
8697   [(set_attr "length" "4")
8698    (set_attr "type" "call")]
8699 )
8700
8701 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
8702 (define_expand "sibcall"
8703   [(parallel [(call (match_operand 0 "memory_operand" "")
8704                     (match_operand 1 "general_operand" ""))
8705               (return)
8706               (use (match_operand 2 "" ""))])]
8707   "TARGET_32BIT"
8708   "
8709   {
8710     if (operands[2] == NULL_RTX)
8711       operands[2] = const0_rtx;
8712   }"
8713 )
8714
8715 (define_expand "sibcall_value"
8716   [(parallel [(set (match_operand 0 "" "")
8717                    (call (match_operand 1 "memory_operand" "")
8718                          (match_operand 2 "general_operand" "")))
8719               (return)
8720               (use (match_operand 3 "" ""))])]
8721   "TARGET_32BIT"
8722   "
8723   {
8724     if (operands[3] == NULL_RTX)
8725       operands[3] = const0_rtx;
8726   }"
8727 )
8728
8729 (define_insn "*sibcall_insn"
8730  [(call (mem:SI (match_operand:SI 0 "" "X"))
8731         (match_operand 1 "" ""))
8732   (return)
8733   (use (match_operand 2 "" ""))]
8734   "TARGET_32BIT && GET_CODE (operands[0]) == SYMBOL_REF"
8735   "*
8736   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8737   "
8738   [(set_attr "type" "call")]
8739 )
8740
8741 (define_insn "*sibcall_value_insn"
8742  [(set (match_operand 0 "" "")
8743        (call (mem:SI (match_operand:SI 1 "" "X"))
8744              (match_operand 2 "" "")))
8745   (return)
8746   (use (match_operand 3 "" ""))]
8747   "TARGET_32BIT && GET_CODE (operands[1]) == SYMBOL_REF"
8748   "*
8749   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8750   "
8751   [(set_attr "type" "call")]
8752 )
8753
8754 (define_expand "return"
8755   [(return)]
8756   "TARGET_32BIT && USE_RETURN_INSN (FALSE)"
8757   "")
8758
8759 ;; Often the return insn will be the same as loading from memory, so set attr
8760 (define_insn "*arm_return"
8761   [(return)]
8762   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
8763   "*
8764   {
8765     if (arm_ccfsm_state == 2)
8766       {
8767         arm_ccfsm_state += 2;
8768         return \"\";
8769       }
8770     return output_return_instruction (const_true_rtx, TRUE, FALSE);
8771   }"
8772   [(set_attr "type" "load1")
8773    (set_attr "length" "12")
8774    (set_attr "predicable" "yes")]
8775 )
8776
8777 (define_insn "*cond_return"
8778   [(set (pc)
8779         (if_then_else (match_operator 0 "arm_comparison_operator"
8780                        [(match_operand 1 "cc_register" "") (const_int 0)])
8781                       (return)
8782                       (pc)))]
8783   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
8784   "*
8785   {
8786     if (arm_ccfsm_state == 2)
8787       {
8788         arm_ccfsm_state += 2;
8789         return \"\";
8790       }
8791     return output_return_instruction (operands[0], TRUE, FALSE);
8792   }"
8793   [(set_attr "conds" "use")
8794    (set_attr "length" "12")
8795    (set_attr "type" "load1")]
8796 )
8797
8798 (define_insn "*cond_return_inverted"
8799   [(set (pc)
8800         (if_then_else (match_operator 0 "arm_comparison_operator"
8801                        [(match_operand 1 "cc_register" "") (const_int 0)])
8802                       (pc)
8803                       (return)))]
8804   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
8805   "*
8806   {
8807     if (arm_ccfsm_state == 2)
8808       {
8809         arm_ccfsm_state += 2;
8810         return \"\";
8811       }
8812     return output_return_instruction (operands[0], TRUE, TRUE);
8813   }"
8814   [(set_attr "conds" "use")
8815    (set_attr "length" "12")
8816    (set_attr "type" "load1")]
8817 )
8818
8819 ;; Generate a sequence of instructions to determine if the processor is
8820 ;; in 26-bit or 32-bit mode, and return the appropriate return address
8821 ;; mask.
8822
8823 (define_expand "return_addr_mask"
8824   [(set (match_dup 1)
8825       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8826                        (const_int 0)))
8827    (set (match_operand:SI 0 "s_register_operand" "")
8828       (if_then_else:SI (eq (match_dup 1) (const_int 0))
8829                        (const_int -1)
8830                        (const_int 67108860)))] ; 0x03fffffc
8831   "TARGET_ARM"
8832   "
8833   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
8834   ")
8835
8836 (define_insn "*check_arch2"
8837   [(set (match_operand:CC_NOOV 0 "cc_register" "")
8838       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8839                        (const_int 0)))]
8840   "TARGET_ARM"
8841   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8842   [(set_attr "length" "8")
8843    (set_attr "conds" "set")]
8844 )
8845
8846 ;; Call subroutine returning any type.
8847
8848 (define_expand "untyped_call"
8849   [(parallel [(call (match_operand 0 "" "")
8850                     (const_int 0))
8851               (match_operand 1 "" "")
8852               (match_operand 2 "" "")])]
8853   "TARGET_EITHER"
8854   "
8855   {
8856     int i;
8857     rtx par = gen_rtx_PARALLEL (VOIDmode,
8858                                 rtvec_alloc (XVECLEN (operands[2], 0)));
8859     rtx addr = gen_reg_rtx (Pmode);
8860     rtx mem;
8861     int size = 0;
8862
8863     emit_move_insn (addr, XEXP (operands[1], 0));
8864     mem = change_address (operands[1], BLKmode, addr);
8865
8866     for (i = 0; i < XVECLEN (operands[2], 0); i++)
8867       {
8868         rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
8869
8870         /* Default code only uses r0 as a return value, but we could
8871            be using anything up to 4 registers.  */
8872         if (REGNO (src) == R0_REGNUM)
8873           src = gen_rtx_REG (TImode, R0_REGNUM);
8874
8875         XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8876                                                  GEN_INT (size));
8877         size += GET_MODE_SIZE (GET_MODE (src));
8878       }
8879
8880     emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8881                                     const0_rtx));
8882
8883     size = 0;
8884
8885     for (i = 0; i < XVECLEN (par, 0); i++)
8886       {
8887         HOST_WIDE_INT offset = 0;
8888         rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8889
8890         if (size != 0)
8891           emit_move_insn (addr, plus_constant (addr, size));
8892
8893         mem = change_address (mem, GET_MODE (reg), NULL);
8894         if (REGNO (reg) == R0_REGNUM)
8895           {
8896             /* On thumb we have to use a write-back instruction.  */
8897             emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
8898                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8899             size = TARGET_ARM ? 16 : 0;
8900           }
8901         else
8902           {
8903             emit_move_insn (mem, reg);
8904             size = GET_MODE_SIZE (GET_MODE (reg));
8905           }
8906       }
8907
8908     /* The optimizer does not know that the call sets the function value
8909        registers we stored in the result block.  We avoid problems by
8910        claiming that all hard registers are used and clobbered at this
8911        point.  */
8912     emit_insn (gen_blockage ());
8913
8914     DONE;
8915   }"
8916 )
8917
8918 (define_expand "untyped_return"
8919   [(match_operand:BLK 0 "memory_operand" "")
8920    (match_operand 1 "" "")]
8921   "TARGET_EITHER"
8922   "
8923   {
8924     int i;
8925     rtx addr = gen_reg_rtx (Pmode);
8926     rtx mem;
8927     int size = 0;
8928
8929     emit_move_insn (addr, XEXP (operands[0], 0));
8930     mem = change_address (operands[0], BLKmode, addr);
8931
8932     for (i = 0; i < XVECLEN (operands[1], 0); i++)
8933       {
8934         HOST_WIDE_INT offset = 0;
8935         rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8936
8937         if (size != 0)
8938           emit_move_insn (addr, plus_constant (addr, size));
8939
8940         mem = change_address (mem, GET_MODE (reg), NULL);
8941         if (REGNO (reg) == R0_REGNUM)
8942           {
8943             /* On thumb we have to use a write-back instruction.  */
8944             emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
8945                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8946             size = TARGET_ARM ? 16 : 0;
8947           }
8948         else
8949           {
8950             emit_move_insn (reg, mem);
8951             size = GET_MODE_SIZE (GET_MODE (reg));
8952           }
8953       }
8954
8955     /* Emit USE insns before the return.  */
8956     for (i = 0; i < XVECLEN (operands[1], 0); i++)
8957       emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
8958
8959     /* Construct the return.  */
8960     expand_naked_return ();
8961
8962     DONE;
8963   }"
8964 )
8965
8966 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8967 ;; all of memory.  This blocks insns from being moved across this point.
8968
8969 (define_insn "blockage"
8970   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
8971   "TARGET_EITHER"
8972   ""
8973   [(set_attr "length" "0")
8974    (set_attr "type" "block")]
8975 )
8976
8977 (define_expand "casesi"
8978   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
8979    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
8980    (match_operand:SI 2 "const_int_operand" "")  ; total range
8981    (match_operand:SI 3 "" "")                   ; table label
8982    (match_operand:SI 4 "" "")]                  ; Out of range label
8983   "TARGET_32BIT || optimize_size || flag_pic"
8984   "
8985   {
8986     enum insn_code code;
8987     if (operands[1] != const0_rtx)
8988       {
8989         rtx reg = gen_reg_rtx (SImode);
8990
8991         emit_insn (gen_addsi3 (reg, operands[0],
8992                                GEN_INT (-INTVAL (operands[1]))));
8993         operands[0] = reg;
8994       }
8995
8996     if (TARGET_ARM)
8997       code = CODE_FOR_arm_casesi_internal;
8998     else if (TARGET_THUMB1)
8999       code = CODE_FOR_thumb1_casesi_internal_pic;
9000     else if (flag_pic)
9001       code = CODE_FOR_thumb2_casesi_internal_pic;
9002     else
9003       code = CODE_FOR_thumb2_casesi_internal;
9004
9005     if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
9006       operands[2] = force_reg (SImode, operands[2]);
9007
9008     emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
9009                                           operands[3], operands[4]));
9010     DONE;
9011   }"
9012 )
9013
9014 ;; The USE in this pattern is needed to tell flow analysis that this is
9015 ;; a CASESI insn.  It has no other purpose.
9016 (define_insn "arm_casesi_internal"
9017   [(parallel [(set (pc)
9018                (if_then_else
9019                 (leu (match_operand:SI 0 "s_register_operand" "r")
9020                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
9021                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
9022                                  (label_ref (match_operand 2 "" ""))))
9023                 (label_ref (match_operand 3 "" ""))))
9024               (clobber (reg:CC CC_REGNUM))
9025               (use (label_ref (match_dup 2)))])]
9026   "TARGET_ARM"
9027   "*
9028     if (flag_pic)
9029       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
9030     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
9031   "
9032   [(set_attr "conds" "clob")
9033    (set_attr "length" "12")]
9034 )
9035
9036 (define_expand "thumb1_casesi_internal_pic"
9037   [(match_operand:SI 0 "s_register_operand" "")
9038    (match_operand:SI 1 "thumb1_cmp_operand" "")
9039    (match_operand 2 "" "")
9040    (match_operand 3 "" "")]
9041   "TARGET_THUMB1"
9042   {
9043     rtx reg0;
9044     rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[1]);
9045     emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[1],
9046                                     operands[3]));
9047     reg0 = gen_rtx_REG (SImode, 0);
9048     emit_move_insn (reg0, operands[0]);
9049     emit_jump_insn (gen_thumb1_casesi_dispatch (operands[2]/*, operands[3]*/));
9050     DONE;
9051   }
9052 )
9053
9054 (define_insn "thumb1_casesi_dispatch"
9055   [(parallel [(set (pc) (unspec [(reg:SI 0)
9056                                  (label_ref (match_operand 0 "" ""))
9057 ;;                               (label_ref (match_operand 1 "" ""))
9058 ]
9059                          UNSPEC_THUMB1_CASESI))
9060               (clobber (reg:SI IP_REGNUM))
9061               (clobber (reg:SI LR_REGNUM))])]
9062   "TARGET_THUMB1"
9063   "* return thumb1_output_casesi(operands);"
9064   [(set_attr "length" "4")]
9065 )
9066
9067 (define_expand "indirect_jump"
9068   [(set (pc)
9069         (match_operand:SI 0 "s_register_operand" ""))]
9070   "TARGET_EITHER"
9071   "
9072   /* Thumb-2 doesn't have mov pc, reg.  Explicitly set the low bit of the
9073      address and use bx.  */
9074   if (TARGET_THUMB2)
9075     {
9076       rtx tmp;
9077       tmp = gen_reg_rtx (SImode);
9078       emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
9079       operands[0] = tmp;
9080     }
9081   "
9082 )
9083
9084 ;; NB Never uses BX.
9085 (define_insn "*arm_indirect_jump"
9086   [(set (pc)
9087         (match_operand:SI 0 "s_register_operand" "r"))]
9088   "TARGET_ARM"
9089   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
9090   [(set_attr "predicable" "yes")]
9091 )
9092
9093 (define_insn "*load_indirect_jump"
9094   [(set (pc)
9095         (match_operand:SI 0 "memory_operand" "m"))]
9096   "TARGET_ARM"
9097   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
9098   [(set_attr "type" "load1")
9099    (set_attr "pool_range" "4096")
9100    (set_attr "neg_pool_range" "4084")
9101    (set_attr "predicable" "yes")]
9102 )
9103
9104 ;; NB Never uses BX.
9105 (define_insn "*thumb1_indirect_jump"
9106   [(set (pc)
9107         (match_operand:SI 0 "register_operand" "l*r"))]
9108   "TARGET_THUMB1"
9109   "mov\\tpc, %0"
9110   [(set_attr "conds" "clob")
9111    (set_attr "length" "2")]
9112 )
9113
9114 \f
9115 ;; Misc insns
9116
9117 (define_insn "nop"
9118   [(const_int 0)]
9119   "TARGET_EITHER"
9120   "*
9121   if (TARGET_UNIFIED_ASM)
9122     return \"nop\";
9123   if (TARGET_ARM)
9124     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
9125   return  \"mov\\tr8, r8\";
9126   "
9127   [(set (attr "length")
9128         (if_then_else (eq_attr "is_thumb" "yes")
9129                       (const_int 2)
9130                       (const_int 4)))]
9131 )
9132
9133 \f
9134 ;; Patterns to allow combination of arithmetic, cond code and shifts
9135
9136 (define_insn "*arith_shiftsi"
9137   [(set (match_operand:SI 0 "s_register_operand" "=r")
9138         (match_operator:SI 1 "shiftable_operator"
9139           [(match_operator:SI 3 "shift_operator"
9140              [(match_operand:SI 4 "s_register_operand" "r")
9141               (match_operand:SI 5 "reg_or_int_operand" "rI")])
9142            (match_operand:SI 2 "s_register_operand" "rk")]))]
9143   "TARGET_ARM"
9144   "%i1%?\\t%0, %2, %4%S3"
9145   [(set_attr "predicable" "yes")
9146    (set_attr "shift" "4")
9147    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
9148                       (const_string "alu_shift")
9149                       (const_string "alu_shift_reg")))]
9150 )
9151
9152 (define_split
9153   [(set (match_operand:SI 0 "s_register_operand" "")
9154         (match_operator:SI 1 "shiftable_operator"
9155          [(match_operator:SI 2 "shiftable_operator"
9156            [(match_operator:SI 3 "shift_operator"
9157              [(match_operand:SI 4 "s_register_operand" "")
9158               (match_operand:SI 5 "reg_or_int_operand" "")])
9159             (match_operand:SI 6 "s_register_operand" "")])
9160           (match_operand:SI 7 "arm_rhs_operand" "")]))
9161    (clobber (match_operand:SI 8 "s_register_operand" ""))]
9162   "TARGET_ARM"
9163   [(set (match_dup 8)
9164         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9165                          (match_dup 6)]))
9166    (set (match_dup 0)
9167         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
9168   "")
9169
9170 (define_insn "*arith_shiftsi_compare0"
9171   [(set (reg:CC_NOOV CC_REGNUM)
9172         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
9173                           [(match_operator:SI 3 "shift_operator"
9174                             [(match_operand:SI 4 "s_register_operand" "r")
9175                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
9176                            (match_operand:SI 2 "s_register_operand" "r")])
9177                          (const_int 0)))
9178    (set (match_operand:SI 0 "s_register_operand" "=r")
9179         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9180                          (match_dup 2)]))]
9181   "TARGET_ARM"
9182   "%i1%.\\t%0, %2, %4%S3"
9183   [(set_attr "conds" "set")
9184    (set_attr "shift" "4")
9185    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
9186                       (const_string "alu_shift")
9187                       (const_string "alu_shift_reg")))]
9188 )
9189
9190 (define_insn "*arith_shiftsi_compare0_scratch"
9191   [(set (reg:CC_NOOV CC_REGNUM)
9192         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
9193                           [(match_operator:SI 3 "shift_operator"
9194                             [(match_operand:SI 4 "s_register_operand" "r")
9195                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
9196                            (match_operand:SI 2 "s_register_operand" "r")])
9197                          (const_int 0)))
9198    (clobber (match_scratch:SI 0 "=r"))]
9199   "TARGET_ARM"
9200   "%i1%.\\t%0, %2, %4%S3"
9201   [(set_attr "conds" "set")
9202    (set_attr "shift" "4")
9203    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
9204                       (const_string "alu_shift")
9205                       (const_string "alu_shift_reg")))]
9206 )
9207
9208 (define_insn "*sub_shiftsi"
9209   [(set (match_operand:SI 0 "s_register_operand" "=r")
9210         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
9211                   (match_operator:SI 2 "shift_operator"
9212                    [(match_operand:SI 3 "s_register_operand" "r")
9213                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
9214   "TARGET_ARM"
9215   "sub%?\\t%0, %1, %3%S2"
9216   [(set_attr "predicable" "yes")
9217    (set_attr "shift" "3")
9218    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
9219                       (const_string "alu_shift")
9220                       (const_string "alu_shift_reg")))]
9221 )
9222
9223 (define_insn "*sub_shiftsi_compare0"
9224   [(set (reg:CC_NOOV CC_REGNUM)
9225         (compare:CC_NOOV
9226          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
9227                    (match_operator:SI 2 "shift_operator"
9228                     [(match_operand:SI 3 "s_register_operand" "r")
9229                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
9230          (const_int 0)))
9231    (set (match_operand:SI 0 "s_register_operand" "=r")
9232         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9233                                                  (match_dup 4)])))]
9234   "TARGET_ARM"
9235   "sub%.\\t%0, %1, %3%S2"
9236   [(set_attr "conds" "set")
9237    (set_attr "shift" "3")
9238    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
9239                       (const_string "alu_shift")
9240                       (const_string "alu_shift_reg")))]
9241 )
9242
9243 (define_insn "*sub_shiftsi_compare0_scratch"
9244   [(set (reg:CC_NOOV CC_REGNUM)
9245         (compare:CC_NOOV
9246          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
9247                    (match_operator:SI 2 "shift_operator"
9248                     [(match_operand:SI 3 "s_register_operand" "r")
9249                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
9250          (const_int 0)))
9251    (clobber (match_scratch:SI 0 "=r"))]
9252   "TARGET_ARM"
9253   "sub%.\\t%0, %1, %3%S2"
9254   [(set_attr "conds" "set")
9255    (set_attr "shift" "3")
9256    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
9257                       (const_string "alu_shift")
9258                       (const_string "alu_shift_reg")))]
9259 )
9260
9261 \f
9262
9263 (define_insn "*and_scc"
9264   [(set (match_operand:SI 0 "s_register_operand" "=r")
9265         (and:SI (match_operator:SI 1 "arm_comparison_operator"
9266                  [(match_operand 3 "cc_register" "") (const_int 0)])
9267                 (match_operand:SI 2 "s_register_operand" "r")))]
9268   "TARGET_ARM"
9269   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
9270   [(set_attr "conds" "use")
9271    (set_attr "length" "8")]
9272 )
9273
9274 (define_insn "*ior_scc"
9275   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9276         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
9277                  [(match_operand 3 "cc_register" "") (const_int 0)])
9278                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
9279   "TARGET_ARM"
9280   "@
9281    orr%d2\\t%0, %1, #1
9282    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
9283   [(set_attr "conds" "use")
9284    (set_attr "length" "4,8")]
9285 )
9286
9287 ; A series of splitters for the compare_scc pattern below.  Note that
9288 ; order is important.
9289 (define_split
9290   [(set (match_operand:SI 0 "s_register_operand" "")
9291         (lt:SI (match_operand:SI 1 "s_register_operand" "")
9292                (const_int 0)))
9293    (clobber (reg:CC CC_REGNUM))]
9294   "TARGET_32BIT && reload_completed"
9295   [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
9296
9297 (define_split
9298   [(set (match_operand:SI 0 "s_register_operand" "")
9299         (ge:SI (match_operand:SI 1 "s_register_operand" "")
9300                (const_int 0)))
9301    (clobber (reg:CC CC_REGNUM))]
9302   "TARGET_32BIT && reload_completed"
9303   [(set (match_dup 0) (not:SI (match_dup 1)))
9304    (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
9305
9306 (define_split
9307   [(set (match_operand:SI 0 "s_register_operand" "")
9308         (eq:SI (match_operand:SI 1 "s_register_operand" "")
9309                (const_int 0)))
9310    (clobber (reg:CC CC_REGNUM))]
9311   "TARGET_32BIT && reload_completed"
9312   [(parallel
9313     [(set (reg:CC CC_REGNUM)
9314           (compare:CC (const_int 1) (match_dup 1)))
9315      (set (match_dup 0)
9316           (minus:SI (const_int 1) (match_dup 1)))])
9317    (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
9318               (set (match_dup 0) (const_int 0)))])
9319
9320 (define_split
9321   [(set (match_operand:SI 0 "s_register_operand" "")
9322         (ne:SI (match_operand:SI 1 "s_register_operand" "")
9323                (match_operand:SI 2 "const_int_operand" "")))
9324    (clobber (reg:CC CC_REGNUM))]
9325   "TARGET_32BIT && reload_completed"
9326   [(parallel
9327     [(set (reg:CC CC_REGNUM)
9328           (compare:CC (match_dup 1) (match_dup 2)))
9329      (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
9330    (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
9331               (set (match_dup 0) (const_int 1)))]
9332 {
9333   operands[3] = GEN_INT (-INTVAL (operands[2]));
9334 })
9335
9336 (define_split
9337   [(set (match_operand:SI 0 "s_register_operand" "")
9338         (ne:SI (match_operand:SI 1 "s_register_operand" "")
9339                (match_operand:SI 2 "arm_add_operand" "")))
9340    (clobber (reg:CC CC_REGNUM))]
9341   "TARGET_32BIT && reload_completed"
9342   [(parallel
9343     [(set (reg:CC_NOOV CC_REGNUM)
9344           (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
9345                            (const_int 0)))
9346      (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
9347    (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
9348               (set (match_dup 0) (const_int 1)))])
9349
9350 (define_insn_and_split "*compare_scc"
9351   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9352         (match_operator:SI 1 "arm_comparison_operator"
9353          [(match_operand:SI 2 "s_register_operand" "r,r")
9354           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
9355    (clobber (reg:CC CC_REGNUM))]
9356   "TARGET_32BIT"
9357   "#"
9358   "&& reload_completed"
9359   [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
9360    (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
9361    (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
9362 {
9363   rtx tmp1;
9364   enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9365                                            operands[2], operands[3]);
9366   enum rtx_code rc = GET_CODE (operands[1]);
9367
9368   tmp1 = gen_rtx_REG (mode, CC_REGNUM);
9369
9370   operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
9371   if (mode == CCFPmode || mode == CCFPEmode)
9372     rc = reverse_condition_maybe_unordered (rc);
9373   else
9374     rc = reverse_condition (rc);
9375   operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
9376 })
9377
9378 ;; Attempt to improve the sequence generated by the compare_scc splitters
9379 ;; not to use conditional execution.
9380 (define_peephole2
9381   [(set (reg:CC CC_REGNUM)
9382         (compare:CC (match_operand:SI 1 "register_operand" "")
9383                     (match_operand:SI 2 "arm_rhs_operand" "")))
9384    (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9385               (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9386    (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9387               (set (match_dup 0) (const_int 1)))
9388    (match_scratch:SI 3 "r")]
9389   "TARGET_32BIT"
9390   [(set (match_dup 3) (minus:SI (match_dup 1) (match_dup 2)))
9391    (parallel
9392     [(set (reg:CC CC_REGNUM)
9393           (compare:CC (const_int 0) (match_dup 3)))
9394      (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
9395    (set (match_dup 0)
9396         (plus:SI (plus:SI (match_dup 0) (match_dup 3))
9397                  (geu:SI (reg:CC CC_REGNUM) (const_int 0))))])
9398
9399 (define_insn "*cond_move"
9400   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9401         (if_then_else:SI (match_operator 3 "equality_operator"
9402                           [(match_operator 4 "arm_comparison_operator"
9403                             [(match_operand 5 "cc_register" "") (const_int 0)])
9404                            (const_int 0)])
9405                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9406                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
9407   "TARGET_ARM"
9408   "*
9409     if (GET_CODE (operands[3]) == NE)
9410       {
9411         if (which_alternative != 1)
9412           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
9413         if (which_alternative != 0)
9414           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
9415         return \"\";
9416       }
9417     if (which_alternative != 0)
9418       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9419     if (which_alternative != 1)
9420       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
9421     return \"\";
9422   "
9423   [(set_attr "conds" "use")
9424    (set_attr "length" "4,4,8")]
9425 )
9426
9427 (define_insn "*cond_arith"
9428   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9429         (match_operator:SI 5 "shiftable_operator" 
9430          [(match_operator:SI 4 "arm_comparison_operator"
9431            [(match_operand:SI 2 "s_register_operand" "r,r")
9432             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9433           (match_operand:SI 1 "s_register_operand" "0,?r")]))
9434    (clobber (reg:CC CC_REGNUM))]
9435   "TARGET_ARM"
9436   "*
9437     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
9438       return \"%i5\\t%0, %1, %2, lsr #31\";
9439
9440     output_asm_insn (\"cmp\\t%2, %3\", operands);
9441     if (GET_CODE (operands[5]) == AND)
9442       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
9443     else if (GET_CODE (operands[5]) == MINUS)
9444       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
9445     else if (which_alternative != 0)
9446       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9447     return \"%i5%d4\\t%0, %1, #1\";
9448   "
9449   [(set_attr "conds" "clob")
9450    (set_attr "length" "12")]
9451 )
9452
9453 (define_insn "*cond_sub"
9454   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9455         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
9456                   (match_operator:SI 4 "arm_comparison_operator"
9457                    [(match_operand:SI 2 "s_register_operand" "r,r")
9458                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
9459    (clobber (reg:CC CC_REGNUM))]
9460   "TARGET_ARM"
9461   "*
9462     output_asm_insn (\"cmp\\t%2, %3\", operands);
9463     if (which_alternative != 0)
9464       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9465     return \"sub%d4\\t%0, %1, #1\";
9466   "
9467   [(set_attr "conds" "clob")
9468    (set_attr "length" "8,12")]
9469 )
9470
9471 ;; ??? Is it worth using these conditional patterns in Thumb-2 mode?
9472 (define_insn "*cmp_ite0"
9473   [(set (match_operand 6 "dominant_cc_register" "")
9474         (compare
9475          (if_then_else:SI
9476           (match_operator 4 "arm_comparison_operator"
9477            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9478             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9479           (match_operator:SI 5 "arm_comparison_operator"
9480            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9481             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
9482           (const_int 0))
9483          (const_int 0)))]
9484   "TARGET_ARM"
9485   "*
9486   {
9487     static const char * const opcodes[4][2] =
9488     {
9489       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9490        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9491       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9492        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9493       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9494        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9495       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9496        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9497     };
9498     int swap =
9499       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9500
9501     return opcodes[which_alternative][swap];
9502   }"
9503   [(set_attr "conds" "set")
9504    (set_attr "length" "8")]
9505 )
9506
9507 (define_insn "*cmp_ite1"
9508   [(set (match_operand 6 "dominant_cc_register" "")
9509         (compare
9510          (if_then_else:SI
9511           (match_operator 4 "arm_comparison_operator"
9512            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9513             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9514           (match_operator:SI 5 "arm_comparison_operator"
9515            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9516             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
9517           (const_int 1))
9518          (const_int 0)))]
9519   "TARGET_ARM"
9520   "*
9521   {
9522     static const char * const opcodes[4][2] =
9523     {
9524       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
9525        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9526       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
9527        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9528       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
9529        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9530       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
9531        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9532     };
9533     int swap =
9534       comparison_dominates_p (GET_CODE (operands[5]),
9535                               reverse_condition (GET_CODE (operands[4])));
9536
9537     return opcodes[which_alternative][swap];
9538   }"
9539   [(set_attr "conds" "set")
9540    (set_attr "length" "8")]
9541 )
9542
9543 (define_insn "*cmp_and"
9544   [(set (match_operand 6 "dominant_cc_register" "")
9545         (compare
9546          (and:SI
9547           (match_operator 4 "arm_comparison_operator"
9548            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9549             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9550           (match_operator:SI 5 "arm_comparison_operator"
9551            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9552             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9553          (const_int 0)))]
9554   "TARGET_ARM"
9555   "*
9556   {
9557     static const char *const opcodes[4][2] =
9558     {
9559       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9560        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9561       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9562        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9563       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9564        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9565       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9566        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9567     };
9568     int swap =
9569       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9570
9571     return opcodes[which_alternative][swap];
9572   }"
9573   [(set_attr "conds" "set")
9574    (set_attr "predicable" "no")
9575    (set_attr "length" "8")]
9576 )
9577
9578 (define_insn "*cmp_ior"
9579   [(set (match_operand 6 "dominant_cc_register" "")
9580         (compare
9581          (ior:SI
9582           (match_operator 4 "arm_comparison_operator"
9583            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9584             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9585           (match_operator:SI 5 "arm_comparison_operator"
9586            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9587             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9588          (const_int 0)))]
9589   "TARGET_ARM"
9590   "*
9591 {
9592   static const char *const opcodes[4][2] =
9593   {
9594     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
9595      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9596     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
9597      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9598     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
9599      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9600     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
9601      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9602   };
9603   int swap =
9604     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9605
9606   return opcodes[which_alternative][swap];
9607 }
9608 "
9609   [(set_attr "conds" "set")
9610    (set_attr "length" "8")]
9611 )
9612
9613 (define_insn_and_split "*ior_scc_scc"
9614   [(set (match_operand:SI 0 "s_register_operand" "=r")
9615         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9616                  [(match_operand:SI 1 "s_register_operand" "r")
9617                   (match_operand:SI 2 "arm_add_operand" "rIL")])
9618                 (match_operator:SI 6 "arm_comparison_operator"
9619                  [(match_operand:SI 4 "s_register_operand" "r")
9620                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
9621    (clobber (reg:CC CC_REGNUM))]
9622   "TARGET_ARM
9623    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9624        != CCmode)"
9625   "#"
9626   "TARGET_ARM && reload_completed"
9627   [(set (match_dup 7)
9628         (compare
9629          (ior:SI
9630           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9631           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9632          (const_int 0)))
9633    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9634   "operands[7]
9635      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9636                                                   DOM_CC_X_OR_Y),
9637                     CC_REGNUM);"
9638   [(set_attr "conds" "clob")
9639    (set_attr "length" "16")])
9640
9641 ; If the above pattern is followed by a CMP insn, then the compare is 
9642 ; redundant, since we can rework the conditional instruction that follows.
9643 (define_insn_and_split "*ior_scc_scc_cmp"
9644   [(set (match_operand 0 "dominant_cc_register" "")
9645         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9646                           [(match_operand:SI 1 "s_register_operand" "r")
9647                            (match_operand:SI 2 "arm_add_operand" "rIL")])
9648                          (match_operator:SI 6 "arm_comparison_operator"
9649                           [(match_operand:SI 4 "s_register_operand" "r")
9650                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
9651                  (const_int 0)))
9652    (set (match_operand:SI 7 "s_register_operand" "=r")
9653         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9654                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9655   "TARGET_ARM"
9656   "#"
9657   "TARGET_ARM && reload_completed"
9658   [(set (match_dup 0)
9659         (compare
9660          (ior:SI
9661           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9662           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9663          (const_int 0)))
9664    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9665   ""
9666   [(set_attr "conds" "set")
9667    (set_attr "length" "16")])
9668
9669 (define_insn_and_split "*and_scc_scc"
9670   [(set (match_operand:SI 0 "s_register_operand" "=r")
9671         (and:SI (match_operator:SI 3 "arm_comparison_operator"
9672                  [(match_operand:SI 1 "s_register_operand" "r")
9673                   (match_operand:SI 2 "arm_add_operand" "rIL")])
9674                 (match_operator:SI 6 "arm_comparison_operator"
9675                  [(match_operand:SI 4 "s_register_operand" "r")
9676                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
9677    (clobber (reg:CC CC_REGNUM))]
9678   "TARGET_ARM
9679    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9680        != CCmode)"
9681   "#"
9682   "TARGET_ARM && reload_completed
9683    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9684        != CCmode)"
9685   [(set (match_dup 7)
9686         (compare
9687          (and:SI
9688           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9689           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9690          (const_int 0)))
9691    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9692   "operands[7]
9693      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9694                                                   DOM_CC_X_AND_Y),
9695                     CC_REGNUM);"
9696   [(set_attr "conds" "clob")
9697    (set_attr "length" "16")])
9698
9699 ; If the above pattern is followed by a CMP insn, then the compare is 
9700 ; redundant, since we can rework the conditional instruction that follows.
9701 (define_insn_and_split "*and_scc_scc_cmp"
9702   [(set (match_operand 0 "dominant_cc_register" "")
9703         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9704                           [(match_operand:SI 1 "s_register_operand" "r")
9705                            (match_operand:SI 2 "arm_add_operand" "rIL")])
9706                          (match_operator:SI 6 "arm_comparison_operator"
9707                           [(match_operand:SI 4 "s_register_operand" "r")
9708                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
9709                  (const_int 0)))
9710    (set (match_operand:SI 7 "s_register_operand" "=r")
9711         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9712                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9713   "TARGET_ARM"
9714   "#"
9715   "TARGET_ARM && reload_completed"
9716   [(set (match_dup 0)
9717         (compare
9718          (and:SI
9719           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9720           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9721          (const_int 0)))
9722    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9723   ""
9724   [(set_attr "conds" "set")
9725    (set_attr "length" "16")])
9726
9727 ;; If there is no dominance in the comparison, then we can still save an
9728 ;; instruction in the AND case, since we can know that the second compare
9729 ;; need only zero the value if false (if true, then the value is already
9730 ;; correct).
9731 (define_insn_and_split "*and_scc_scc_nodom"
9732   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
9733         (and:SI (match_operator:SI 3 "arm_comparison_operator"
9734                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
9735                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9736                 (match_operator:SI 6 "arm_comparison_operator"
9737                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
9738                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9739    (clobber (reg:CC CC_REGNUM))]
9740   "TARGET_ARM
9741    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9742        == CCmode)"
9743   "#"
9744   "TARGET_ARM && reload_completed"
9745   [(parallel [(set (match_dup 0)
9746                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9747               (clobber (reg:CC CC_REGNUM))])
9748    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9749    (set (match_dup 0)
9750         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9751                          (match_dup 0)
9752                          (const_int 0)))]
9753   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9754                                               operands[4], operands[5]),
9755                               CC_REGNUM);
9756    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9757                                   operands[5]);"
9758   [(set_attr "conds" "clob")
9759    (set_attr "length" "20")])
9760
9761 (define_split
9762   [(set (reg:CC_NOOV CC_REGNUM)
9763         (compare:CC_NOOV (ior:SI
9764                           (and:SI (match_operand:SI 0 "s_register_operand" "")
9765                                   (const_int 1))
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                          (const_int 0)))
9770    (clobber (match_operand:SI 4 "s_register_operand" ""))]
9771   "TARGET_ARM"
9772   [(set (match_dup 4)
9773         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9774                 (match_dup 0)))
9775    (set (reg:CC_NOOV CC_REGNUM)
9776         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9777                          (const_int 0)))]
9778   "")
9779
9780 (define_split
9781   [(set (reg:CC_NOOV CC_REGNUM)
9782         (compare:CC_NOOV (ior:SI
9783                           (match_operator:SI 1 "arm_comparison_operator"
9784                            [(match_operand:SI 2 "s_register_operand" "")
9785                             (match_operand:SI 3 "arm_add_operand" "")])
9786                           (and:SI (match_operand:SI 0 "s_register_operand" "")
9787                                   (const_int 1)))
9788                          (const_int 0)))
9789    (clobber (match_operand:SI 4 "s_register_operand" ""))]
9790   "TARGET_ARM"
9791   [(set (match_dup 4)
9792         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9793                 (match_dup 0)))
9794    (set (reg:CC_NOOV CC_REGNUM)
9795         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9796                          (const_int 0)))]
9797   "")
9798 ;; ??? The conditional patterns above need checking for Thumb-2 usefulness
9799
9800 (define_insn "*negscc"
9801   [(set (match_operand:SI 0 "s_register_operand" "=r")
9802         (neg:SI (match_operator 3 "arm_comparison_operator"
9803                  [(match_operand:SI 1 "s_register_operand" "r")
9804                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
9805    (clobber (reg:CC CC_REGNUM))]
9806   "TARGET_ARM"
9807   "*
9808   if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
9809     return \"mov\\t%0, %1, asr #31\";
9810
9811   if (GET_CODE (operands[3]) == NE)
9812     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9813
9814   output_asm_insn (\"cmp\\t%1, %2\", operands);
9815   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9816   return \"mvn%d3\\t%0, #0\";
9817   "
9818   [(set_attr "conds" "clob")
9819    (set_attr "length" "12")]
9820 )
9821
9822 (define_insn "movcond"
9823   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9824         (if_then_else:SI
9825          (match_operator 5 "arm_comparison_operator"
9826           [(match_operand:SI 3 "s_register_operand" "r,r,r")
9827            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9828          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9829          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
9830    (clobber (reg:CC CC_REGNUM))]
9831   "TARGET_ARM"
9832   "*
9833   if (GET_CODE (operands[5]) == LT
9834       && (operands[4] == const0_rtx))
9835     {
9836       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9837         {
9838           if (operands[2] == const0_rtx)
9839             return \"and\\t%0, %1, %3, asr #31\";
9840           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9841         }
9842       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9843         {
9844           if (operands[1] == const0_rtx)
9845             return \"bic\\t%0, %2, %3, asr #31\";
9846           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9847         }
9848       /* The only case that falls through to here is when both ops 1 & 2
9849          are constants.  */
9850     }
9851
9852   if (GET_CODE (operands[5]) == GE
9853       && (operands[4] == const0_rtx))
9854     {
9855       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9856         {
9857           if (operands[2] == const0_rtx)
9858             return \"bic\\t%0, %1, %3, asr #31\";
9859           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9860         }
9861       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9862         {
9863           if (operands[1] == const0_rtx)
9864             return \"and\\t%0, %2, %3, asr #31\";
9865           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9866         }
9867       /* The only case that falls through to here is when both ops 1 & 2
9868          are constants.  */
9869     }
9870   if (GET_CODE (operands[4]) == CONST_INT
9871       && !const_ok_for_arm (INTVAL (operands[4])))
9872     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9873   else
9874     output_asm_insn (\"cmp\\t%3, %4\", operands);
9875   if (which_alternative != 0)
9876     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9877   if (which_alternative != 1)
9878     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9879   return \"\";
9880   "
9881   [(set_attr "conds" "clob")
9882    (set_attr "length" "8,8,12")]
9883 )
9884
9885 ;; ??? The patterns below need checking for Thumb-2 usefulness.
9886
9887 (define_insn "*ifcompare_plus_move"
9888   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9889         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9890                           [(match_operand:SI 4 "s_register_operand" "r,r")
9891                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9892                          (plus:SI
9893                           (match_operand:SI 2 "s_register_operand" "r,r")
9894                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
9895                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9896    (clobber (reg:CC CC_REGNUM))]
9897   "TARGET_ARM"
9898   "#"
9899   [(set_attr "conds" "clob")
9900    (set_attr "length" "8,12")]
9901 )
9902
9903 (define_insn "*if_plus_move"
9904   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9905         (if_then_else:SI
9906          (match_operator 4 "arm_comparison_operator"
9907           [(match_operand 5 "cc_register" "") (const_int 0)])
9908          (plus:SI
9909           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9910           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9911          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
9912   "TARGET_ARM"
9913   "@
9914    add%d4\\t%0, %2, %3
9915    sub%d4\\t%0, %2, #%n3
9916    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
9917    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
9918   [(set_attr "conds" "use")
9919    (set_attr "length" "4,4,8,8")
9920    (set_attr "type" "*,*,*,*")]
9921 )
9922
9923 (define_insn "*ifcompare_move_plus"
9924   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9925         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9926                           [(match_operand:SI 4 "s_register_operand" "r,r")
9927                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9928                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9929                          (plus:SI
9930                           (match_operand:SI 2 "s_register_operand" "r,r")
9931                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
9932    (clobber (reg:CC CC_REGNUM))]
9933   "TARGET_ARM"
9934   "#"
9935   [(set_attr "conds" "clob")
9936    (set_attr "length" "8,12")]
9937 )
9938
9939 (define_insn "*if_move_plus"
9940   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9941         (if_then_else:SI
9942          (match_operator 4 "arm_comparison_operator"
9943           [(match_operand 5 "cc_register" "") (const_int 0)])
9944          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
9945          (plus:SI
9946           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9947           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
9948   "TARGET_ARM"
9949   "@
9950    add%D4\\t%0, %2, %3
9951    sub%D4\\t%0, %2, #%n3
9952    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
9953    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
9954   [(set_attr "conds" "use")
9955    (set_attr "length" "4,4,8,8")
9956    (set_attr "type" "*,*,*,*")]
9957 )
9958
9959 (define_insn "*ifcompare_arith_arith"
9960   [(set (match_operand:SI 0 "s_register_operand" "=r")
9961         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
9962                           [(match_operand:SI 5 "s_register_operand" "r")
9963                            (match_operand:SI 6 "arm_add_operand" "rIL")])
9964                          (match_operator:SI 8 "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    (clobber (reg:CC CC_REGNUM))]
9971   "TARGET_ARM"
9972   "#"
9973   [(set_attr "conds" "clob")
9974    (set_attr "length" "12")]
9975 )
9976
9977 (define_insn "*if_arith_arith"
9978   [(set (match_operand:SI 0 "s_register_operand" "=r")
9979         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
9980                           [(match_operand 8 "cc_register" "") (const_int 0)])
9981                          (match_operator:SI 6 "shiftable_operator"
9982                           [(match_operand:SI 1 "s_register_operand" "r")
9983                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
9984                          (match_operator:SI 7 "shiftable_operator"
9985                           [(match_operand:SI 3 "s_register_operand" "r")
9986                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
9987   "TARGET_ARM"
9988   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
9989   [(set_attr "conds" "use")
9990    (set_attr "length" "8")]
9991 )
9992
9993 (define_insn "*ifcompare_arith_move"
9994   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9995         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9996                           [(match_operand:SI 2 "s_register_operand" "r,r")
9997                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9998                          (match_operator:SI 7 "shiftable_operator"
9999                           [(match_operand:SI 4 "s_register_operand" "r,r")
10000                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
10001                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
10002    (clobber (reg:CC CC_REGNUM))]
10003   "TARGET_ARM"
10004   "*
10005   /* If we have an operation where (op x 0) is the identity operation and
10006      the conditional operator is LT or GE and we are comparing against zero and
10007      everything is in registers then we can do this in two instructions.  */
10008   if (operands[3] == const0_rtx
10009       && GET_CODE (operands[7]) != AND
10010       && GET_CODE (operands[5]) == REG
10011       && GET_CODE (operands[1]) == REG 
10012       && REGNO (operands[1]) == REGNO (operands[4])
10013       && REGNO (operands[4]) != REGNO (operands[0]))
10014     {
10015       if (GET_CODE (operands[6]) == LT)
10016         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
10017       else if (GET_CODE (operands[6]) == GE)
10018         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
10019     }
10020   if (GET_CODE (operands[3]) == CONST_INT
10021       && !const_ok_for_arm (INTVAL (operands[3])))
10022     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
10023   else
10024     output_asm_insn (\"cmp\\t%2, %3\", operands);
10025   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
10026   if (which_alternative != 0)
10027     return \"mov%D6\\t%0, %1\";
10028   return \"\";
10029   "
10030   [(set_attr "conds" "clob")
10031    (set_attr "length" "8,12")]
10032 )
10033
10034 (define_insn "*if_arith_move"
10035   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10036         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10037                           [(match_operand 6 "cc_register" "") (const_int 0)])
10038                          (match_operator:SI 5 "shiftable_operator"
10039                           [(match_operand:SI 2 "s_register_operand" "r,r")
10040                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
10041                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
10042   "TARGET_ARM"
10043   "@
10044    %I5%d4\\t%0, %2, %3
10045    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
10046   [(set_attr "conds" "use")
10047    (set_attr "length" "4,8")
10048    (set_attr "type" "*,*")]
10049 )
10050
10051 (define_insn "*ifcompare_move_arith"
10052   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10053         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
10054                           [(match_operand:SI 4 "s_register_operand" "r,r")
10055                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10056                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10057                          (match_operator:SI 7 "shiftable_operator"
10058                           [(match_operand:SI 2 "s_register_operand" "r,r")
10059                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
10060    (clobber (reg:CC CC_REGNUM))]
10061   "TARGET_ARM"
10062   "*
10063   /* If we have an operation where (op x 0) is the identity operation and
10064      the conditional operator is LT or GE and we are comparing against zero and
10065      everything is in registers then we can do this in two instructions */
10066   if (operands[5] == const0_rtx
10067       && GET_CODE (operands[7]) != AND
10068       && GET_CODE (operands[3]) == REG
10069       && GET_CODE (operands[1]) == REG 
10070       && REGNO (operands[1]) == REGNO (operands[2])
10071       && REGNO (operands[2]) != REGNO (operands[0]))
10072     {
10073       if (GET_CODE (operands[6]) == GE)
10074         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
10075       else if (GET_CODE (operands[6]) == LT)
10076         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
10077     }
10078
10079   if (GET_CODE (operands[5]) == CONST_INT
10080       && !const_ok_for_arm (INTVAL (operands[5])))
10081     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
10082   else
10083     output_asm_insn (\"cmp\\t%4, %5\", operands);
10084
10085   if (which_alternative != 0)
10086     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
10087   return \"%I7%D6\\t%0, %2, %3\";
10088   "
10089   [(set_attr "conds" "clob")
10090    (set_attr "length" "8,12")]
10091 )
10092
10093 (define_insn "*if_move_arith"
10094   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10095         (if_then_else:SI
10096          (match_operator 4 "arm_comparison_operator"
10097           [(match_operand 6 "cc_register" "") (const_int 0)])
10098          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10099          (match_operator:SI 5 "shiftable_operator"
10100           [(match_operand:SI 2 "s_register_operand" "r,r")
10101            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
10102   "TARGET_ARM"
10103   "@
10104    %I5%D4\\t%0, %2, %3
10105    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
10106   [(set_attr "conds" "use")
10107    (set_attr "length" "4,8")
10108    (set_attr "type" "*,*")]
10109 )
10110
10111 (define_insn "*ifcompare_move_not"
10112   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10113         (if_then_else:SI
10114          (match_operator 5 "arm_comparison_operator"
10115           [(match_operand:SI 3 "s_register_operand" "r,r")
10116            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10117          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10118          (not:SI
10119           (match_operand:SI 2 "s_register_operand" "r,r"))))
10120    (clobber (reg:CC CC_REGNUM))]
10121   "TARGET_ARM"
10122   "#"
10123   [(set_attr "conds" "clob")
10124    (set_attr "length" "8,12")]
10125 )
10126
10127 (define_insn "*if_move_not"
10128   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10129         (if_then_else:SI
10130          (match_operator 4 "arm_comparison_operator"
10131           [(match_operand 3 "cc_register" "") (const_int 0)])
10132          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10133          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
10134   "TARGET_ARM"
10135   "@
10136    mvn%D4\\t%0, %2
10137    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
10138    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
10139   [(set_attr "conds" "use")
10140    (set_attr "length" "4,8,8")]
10141 )
10142
10143 (define_insn "*ifcompare_not_move"
10144   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10145         (if_then_else:SI 
10146          (match_operator 5 "arm_comparison_operator"
10147           [(match_operand:SI 3 "s_register_operand" "r,r")
10148            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10149          (not:SI
10150           (match_operand:SI 2 "s_register_operand" "r,r"))
10151          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
10152    (clobber (reg:CC CC_REGNUM))]
10153   "TARGET_ARM"
10154   "#"
10155   [(set_attr "conds" "clob")
10156    (set_attr "length" "8,12")]
10157 )
10158
10159 (define_insn "*if_not_move"
10160   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10161         (if_then_else:SI
10162          (match_operator 4 "arm_comparison_operator"
10163           [(match_operand 3 "cc_register" "") (const_int 0)])
10164          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10165          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
10166   "TARGET_ARM"
10167   "@
10168    mvn%d4\\t%0, %2
10169    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
10170    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
10171   [(set_attr "conds" "use")
10172    (set_attr "length" "4,8,8")]
10173 )
10174
10175 (define_insn "*ifcompare_shift_move"
10176   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10177         (if_then_else:SI
10178          (match_operator 6 "arm_comparison_operator"
10179           [(match_operand:SI 4 "s_register_operand" "r,r")
10180            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10181          (match_operator:SI 7 "shift_operator"
10182           [(match_operand:SI 2 "s_register_operand" "r,r")
10183            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
10184          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
10185    (clobber (reg:CC CC_REGNUM))]
10186   "TARGET_ARM"
10187   "#"
10188   [(set_attr "conds" "clob")
10189    (set_attr "length" "8,12")]
10190 )
10191
10192 (define_insn "*if_shift_move"
10193   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10194         (if_then_else:SI
10195          (match_operator 5 "arm_comparison_operator"
10196           [(match_operand 6 "cc_register" "") (const_int 0)])
10197          (match_operator:SI 4 "shift_operator"
10198           [(match_operand:SI 2 "s_register_operand" "r,r,r")
10199            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
10200          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
10201   "TARGET_ARM"
10202   "@
10203    mov%d5\\t%0, %2%S4
10204    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
10205    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
10206   [(set_attr "conds" "use")
10207    (set_attr "shift" "2")
10208    (set_attr "length" "4,8,8")
10209    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
10210                       (const_string "alu_shift")
10211                       (const_string "alu_shift_reg")))]
10212 )
10213
10214 (define_insn "*ifcompare_move_shift"
10215   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10216         (if_then_else:SI
10217          (match_operator 6 "arm_comparison_operator"
10218           [(match_operand:SI 4 "s_register_operand" "r,r")
10219            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10220          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10221          (match_operator:SI 7 "shift_operator"
10222           [(match_operand:SI 2 "s_register_operand" "r,r")
10223            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
10224    (clobber (reg:CC CC_REGNUM))]
10225   "TARGET_ARM"
10226   "#"
10227   [(set_attr "conds" "clob")
10228    (set_attr "length" "8,12")]
10229 )
10230
10231 (define_insn "*if_move_shift"
10232   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10233         (if_then_else:SI
10234          (match_operator 5 "arm_comparison_operator"
10235           [(match_operand 6 "cc_register" "") (const_int 0)])
10236          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10237          (match_operator:SI 4 "shift_operator"
10238           [(match_operand:SI 2 "s_register_operand" "r,r,r")
10239            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
10240   "TARGET_ARM"
10241   "@
10242    mov%D5\\t%0, %2%S4
10243    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
10244    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
10245   [(set_attr "conds" "use")
10246    (set_attr "shift" "2")
10247    (set_attr "length" "4,8,8")
10248    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
10249                       (const_string "alu_shift")
10250                       (const_string "alu_shift_reg")))]
10251 )
10252
10253 (define_insn "*ifcompare_shift_shift"
10254   [(set (match_operand:SI 0 "s_register_operand" "=r")
10255         (if_then_else:SI
10256          (match_operator 7 "arm_comparison_operator"
10257           [(match_operand:SI 5 "s_register_operand" "r")
10258            (match_operand:SI 6 "arm_add_operand" "rIL")])
10259          (match_operator:SI 8 "shift_operator"
10260           [(match_operand:SI 1 "s_register_operand" "r")
10261            (match_operand:SI 2 "arm_rhs_operand" "rM")])
10262          (match_operator:SI 9 "shift_operator"
10263           [(match_operand:SI 3 "s_register_operand" "r")
10264            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
10265    (clobber (reg:CC CC_REGNUM))]
10266   "TARGET_ARM"
10267   "#"
10268   [(set_attr "conds" "clob")
10269    (set_attr "length" "12")]
10270 )
10271
10272 (define_insn "*if_shift_shift"
10273   [(set (match_operand:SI 0 "s_register_operand" "=r")
10274         (if_then_else:SI
10275          (match_operator 5 "arm_comparison_operator"
10276           [(match_operand 8 "cc_register" "") (const_int 0)])
10277          (match_operator:SI 6 "shift_operator"
10278           [(match_operand:SI 1 "s_register_operand" "r")
10279            (match_operand:SI 2 "arm_rhs_operand" "rM")])
10280          (match_operator:SI 7 "shift_operator"
10281           [(match_operand:SI 3 "s_register_operand" "r")
10282            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
10283   "TARGET_ARM"
10284   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
10285   [(set_attr "conds" "use")
10286    (set_attr "shift" "1")
10287    (set_attr "length" "8")
10288    (set (attr "type") (if_then_else
10289                         (and (match_operand 2 "const_int_operand" "")
10290                              (match_operand 4 "const_int_operand" ""))
10291                       (const_string "alu_shift")
10292                       (const_string "alu_shift_reg")))]
10293 )
10294
10295 (define_insn "*ifcompare_not_arith"
10296   [(set (match_operand:SI 0 "s_register_operand" "=r")
10297         (if_then_else:SI
10298          (match_operator 6 "arm_comparison_operator"
10299           [(match_operand:SI 4 "s_register_operand" "r")
10300            (match_operand:SI 5 "arm_add_operand" "rIL")])
10301          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10302          (match_operator:SI 7 "shiftable_operator"
10303           [(match_operand:SI 2 "s_register_operand" "r")
10304            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
10305    (clobber (reg:CC CC_REGNUM))]
10306   "TARGET_ARM"
10307   "#"
10308   [(set_attr "conds" "clob")
10309    (set_attr "length" "12")]
10310 )
10311
10312 (define_insn "*if_not_arith"
10313   [(set (match_operand:SI 0 "s_register_operand" "=r")
10314         (if_then_else:SI
10315          (match_operator 5 "arm_comparison_operator"
10316           [(match_operand 4 "cc_register" "") (const_int 0)])
10317          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10318          (match_operator:SI 6 "shiftable_operator"
10319           [(match_operand:SI 2 "s_register_operand" "r")
10320            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
10321   "TARGET_ARM"
10322   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
10323   [(set_attr "conds" "use")
10324    (set_attr "length" "8")]
10325 )
10326
10327 (define_insn "*ifcompare_arith_not"
10328   [(set (match_operand:SI 0 "s_register_operand" "=r")
10329         (if_then_else:SI
10330          (match_operator 6 "arm_comparison_operator"
10331           [(match_operand:SI 4 "s_register_operand" "r")
10332            (match_operand:SI 5 "arm_add_operand" "rIL")])
10333          (match_operator:SI 7 "shiftable_operator"
10334           [(match_operand:SI 2 "s_register_operand" "r")
10335            (match_operand:SI 3 "arm_rhs_operand" "rI")])
10336          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
10337    (clobber (reg:CC CC_REGNUM))]
10338   "TARGET_ARM"
10339   "#"
10340   [(set_attr "conds" "clob")
10341    (set_attr "length" "12")]
10342 )
10343
10344 (define_insn "*if_arith_not"
10345   [(set (match_operand:SI 0 "s_register_operand" "=r")
10346         (if_then_else:SI
10347          (match_operator 5 "arm_comparison_operator"
10348           [(match_operand 4 "cc_register" "") (const_int 0)])
10349          (match_operator:SI 6 "shiftable_operator"
10350           [(match_operand:SI 2 "s_register_operand" "r")
10351            (match_operand:SI 3 "arm_rhs_operand" "rI")])
10352          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
10353   "TARGET_ARM"
10354   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
10355   [(set_attr "conds" "use")
10356    (set_attr "length" "8")]
10357 )
10358
10359 (define_insn "*ifcompare_neg_move"
10360   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10361         (if_then_else:SI
10362          (match_operator 5 "arm_comparison_operator"
10363           [(match_operand:SI 3 "s_register_operand" "r,r")
10364            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10365          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10366          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
10367    (clobber (reg:CC CC_REGNUM))]
10368   "TARGET_ARM"
10369   "#"
10370   [(set_attr "conds" "clob")
10371    (set_attr "length" "8,12")]
10372 )
10373
10374 (define_insn "*if_neg_move"
10375   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10376         (if_then_else:SI
10377          (match_operator 4 "arm_comparison_operator"
10378           [(match_operand 3 "cc_register" "") (const_int 0)])
10379          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10380          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
10381   "TARGET_ARM"
10382   "@
10383    rsb%d4\\t%0, %2, #0
10384    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
10385    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
10386   [(set_attr "conds" "use")
10387    (set_attr "length" "4,8,8")]
10388 )
10389
10390 (define_insn "*ifcompare_move_neg"
10391   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10392         (if_then_else:SI
10393          (match_operator 5 "arm_comparison_operator"
10394           [(match_operand:SI 3 "s_register_operand" "r,r")
10395            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10396          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10397          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
10398    (clobber (reg:CC CC_REGNUM))]
10399   "TARGET_ARM"
10400   "#"
10401   [(set_attr "conds" "clob")
10402    (set_attr "length" "8,12")]
10403 )
10404
10405 (define_insn "*if_move_neg"
10406   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10407         (if_then_else:SI
10408          (match_operator 4 "arm_comparison_operator"
10409           [(match_operand 3 "cc_register" "") (const_int 0)])
10410          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10411          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
10412   "TARGET_ARM"
10413   "@
10414    rsb%D4\\t%0, %2, #0
10415    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
10416    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
10417   [(set_attr "conds" "use")
10418    (set_attr "length" "4,8,8")]
10419 )
10420
10421 (define_insn "*arith_adjacentmem"
10422   [(set (match_operand:SI 0 "s_register_operand" "=r")
10423         (match_operator:SI 1 "shiftable_operator"
10424          [(match_operand:SI 2 "memory_operand" "m")
10425           (match_operand:SI 3 "memory_operand" "m")]))
10426    (clobber (match_scratch:SI 4 "=r"))]
10427   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
10428   "*
10429   {
10430     rtx ldm[3];
10431     rtx arith[4];
10432     rtx base_reg;
10433     HOST_WIDE_INT val1 = 0, val2 = 0;
10434
10435     if (REGNO (operands[0]) > REGNO (operands[4]))
10436       {
10437         ldm[1] = operands[4];
10438         ldm[2] = operands[0];
10439       }
10440     else
10441       {
10442         ldm[1] = operands[0];
10443         ldm[2] = operands[4];
10444       }
10445
10446     base_reg = XEXP (operands[2], 0);
10447
10448     if (!REG_P (base_reg))
10449       {
10450         val1 = INTVAL (XEXP (base_reg, 1));
10451         base_reg = XEXP (base_reg, 0);
10452       }
10453
10454     if (!REG_P (XEXP (operands[3], 0)))
10455       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
10456
10457     arith[0] = operands[0];
10458     arith[3] = operands[1];
10459
10460     if (val1 < val2)
10461       {
10462         arith[1] = ldm[1];
10463         arith[2] = ldm[2];
10464       }
10465     else
10466       {
10467         arith[1] = ldm[2];
10468         arith[2] = ldm[1];
10469       }
10470
10471     ldm[0] = base_reg;
10472     if (val1 !=0 && val2 != 0)
10473       {
10474         rtx ops[3];
10475
10476         if (val1 == 4 || val2 == 4)
10477           /* Other val must be 8, since we know they are adjacent and neither
10478              is zero.  */
10479           output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
10480         else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
10481           {
10482             ldm[0] = ops[0] = operands[4];
10483             ops[1] = base_reg;
10484             ops[2] = GEN_INT (val1);
10485             output_add_immediate (ops);
10486             if (val1 < val2)
10487               output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
10488             else
10489               output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
10490           }
10491         else
10492           {
10493             /* Offset is out of range for a single add, so use two ldr.  */
10494             ops[0] = ldm[1];
10495             ops[1] = base_reg;
10496             ops[2] = GEN_INT (val1);
10497             output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10498             ops[0] = ldm[2];
10499             ops[2] = GEN_INT (val2);
10500             output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10501           }
10502       }
10503     else if (val1 != 0)
10504       {
10505         if (val1 < val2)
10506           output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
10507         else
10508           output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
10509       }
10510     else
10511       {
10512         if (val1 < val2)
10513           output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
10514         else
10515           output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
10516       }
10517     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10518     return \"\";
10519   }"
10520   [(set_attr "length" "12")
10521    (set_attr "predicable" "yes")
10522    (set_attr "type" "load1")]
10523 )
10524
10525 ; This pattern is never tried by combine, so do it as a peephole
10526
10527 (define_peephole2
10528   [(set (match_operand:SI 0 "arm_general_register_operand" "")
10529         (match_operand:SI 1 "arm_general_register_operand" ""))
10530    (set (reg:CC CC_REGNUM)
10531         (compare:CC (match_dup 1) (const_int 0)))]
10532   "TARGET_ARM"
10533   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10534               (set (match_dup 0) (match_dup 1))])]
10535   ""
10536 )
10537
10538 ; Peepholes to spot possible load- and store-multiples, if the ordering is
10539 ; reversed, check that the memory references aren't volatile.
10540
10541 (define_peephole
10542   [(set (match_operand:SI 0 "s_register_operand" "=rk")
10543         (match_operand:SI 4 "memory_operand" "m"))
10544    (set (match_operand:SI 1 "s_register_operand" "=rk")
10545         (match_operand:SI 5 "memory_operand" "m"))
10546    (set (match_operand:SI 2 "s_register_operand" "=rk")
10547         (match_operand:SI 6 "memory_operand" "m"))
10548    (set (match_operand:SI 3 "s_register_operand" "=rk")
10549         (match_operand:SI 7 "memory_operand" "m"))]
10550   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
10551   "*
10552   return emit_ldm_seq (operands, 4);
10553   "
10554 )
10555
10556 (define_peephole
10557   [(set (match_operand:SI 0 "s_register_operand" "=rk")
10558         (match_operand:SI 3 "memory_operand" "m"))
10559    (set (match_operand:SI 1 "s_register_operand" "=rk")
10560         (match_operand:SI 4 "memory_operand" "m"))
10561    (set (match_operand:SI 2 "s_register_operand" "=rk")
10562         (match_operand:SI 5 "memory_operand" "m"))]
10563   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
10564   "*
10565   return emit_ldm_seq (operands, 3);
10566   "
10567 )
10568
10569 (define_peephole
10570   [(set (match_operand:SI 0 "s_register_operand" "=rk")
10571         (match_operand:SI 2 "memory_operand" "m"))
10572    (set (match_operand:SI 1 "s_register_operand" "=rk")
10573         (match_operand:SI 3 "memory_operand" "m"))]
10574   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
10575   "*
10576   return emit_ldm_seq (operands, 2);
10577   "
10578 )
10579
10580 (define_peephole
10581   [(set (match_operand:SI 4 "memory_operand" "=m")
10582         (match_operand:SI 0 "s_register_operand" "rk"))
10583    (set (match_operand:SI 5 "memory_operand" "=m")
10584         (match_operand:SI 1 "s_register_operand" "rk"))
10585    (set (match_operand:SI 6 "memory_operand" "=m")
10586         (match_operand:SI 2 "s_register_operand" "rk"))
10587    (set (match_operand:SI 7 "memory_operand" "=m")
10588         (match_operand:SI 3 "s_register_operand" "rk"))]
10589   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
10590   "*
10591   return emit_stm_seq (operands, 4);
10592   "
10593 )
10594
10595 (define_peephole
10596   [(set (match_operand:SI 3 "memory_operand" "=m")
10597         (match_operand:SI 0 "s_register_operand" "rk"))
10598    (set (match_operand:SI 4 "memory_operand" "=m")
10599         (match_operand:SI 1 "s_register_operand" "rk"))
10600    (set (match_operand:SI 5 "memory_operand" "=m")
10601         (match_operand:SI 2 "s_register_operand" "rk"))]
10602   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
10603   "*
10604   return emit_stm_seq (operands, 3);
10605   "
10606 )
10607
10608 (define_peephole
10609   [(set (match_operand:SI 2 "memory_operand" "=m")
10610         (match_operand:SI 0 "s_register_operand" "rk"))
10611    (set (match_operand:SI 3 "memory_operand" "=m")
10612         (match_operand:SI 1 "s_register_operand" "rk"))]
10613   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
10614   "*
10615   return emit_stm_seq (operands, 2);
10616   "
10617 )
10618
10619 (define_split
10620   [(set (match_operand:SI 0 "s_register_operand" "")
10621         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10622                        (const_int 0))
10623                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
10624                          [(match_operand:SI 3 "s_register_operand" "")
10625                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
10626    (clobber (match_operand:SI 5 "s_register_operand" ""))]
10627   "TARGET_ARM"
10628   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10629    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10630                               (match_dup 5)))]
10631   ""
10632 )
10633
10634 ;; This split can be used because CC_Z mode implies that the following
10635 ;; branch will be an equality, or an unsigned inequality, so the sign
10636 ;; extension is not needed.
10637
10638 (define_split
10639   [(set (reg:CC_Z CC_REGNUM)
10640         (compare:CC_Z
10641          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
10642                     (const_int 24))
10643          (match_operand 1 "const_int_operand" "")))
10644    (clobber (match_scratch:SI 2 ""))]
10645   "TARGET_ARM
10646    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10647        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
10648   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
10649    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
10650   "
10651   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
10652   "
10653 )
10654 ;; ??? Check the patterns above for Thumb-2 usefulness
10655
10656 (define_expand "prologue"
10657   [(clobber (const_int 0))]
10658   "TARGET_EITHER"
10659   "if (TARGET_32BIT)
10660      arm_expand_prologue ();
10661    else
10662      thumb1_expand_prologue ();
10663   DONE;
10664   "
10665 )
10666
10667 (define_expand "epilogue"
10668   [(clobber (const_int 0))]
10669   "TARGET_EITHER"
10670   "
10671   if (crtl->calls_eh_return)
10672     emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
10673   if (TARGET_THUMB1)
10674     thumb1_expand_epilogue ();
10675   else if (USE_RETURN_INSN (FALSE))
10676     {
10677       emit_jump_insn (gen_return ());
10678       DONE;
10679     }
10680   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10681         gen_rtvec (1,
10682                 gen_rtx_RETURN (VOIDmode)),
10683         VUNSPEC_EPILOGUE));
10684   DONE;
10685   "
10686 )
10687
10688 ;; Note - although unspec_volatile's USE all hard registers,
10689 ;; USEs are ignored after relaod has completed.  Thus we need
10690 ;; to add an unspec of the link register to ensure that flow
10691 ;; does not think that it is unused by the sibcall branch that
10692 ;; will replace the standard function epilogue.
10693 (define_insn "sibcall_epilogue"
10694   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
10695               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10696   "TARGET_32BIT"
10697   "*
10698   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
10699     return output_return_instruction (const_true_rtx, FALSE, FALSE);
10700   return arm_output_epilogue (next_nonnote_insn (insn));
10701   "
10702 ;; Length is absolute worst case
10703   [(set_attr "length" "44")
10704    (set_attr "type" "block")
10705    ;; We don't clobber the conditions, but the potential length of this
10706    ;; operation is sufficient to make conditionalizing the sequence 
10707    ;; unlikely to be profitable.
10708    (set_attr "conds" "clob")]
10709 )
10710
10711 (define_insn "*epilogue_insns"
10712   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
10713   "TARGET_EITHER"
10714   "*
10715   if (TARGET_32BIT)
10716     return arm_output_epilogue (NULL);
10717   else /* TARGET_THUMB1 */
10718     return thumb_unexpanded_epilogue ();
10719   "
10720   ; Length is absolute worst case
10721   [(set_attr "length" "44")
10722    (set_attr "type" "block")
10723    ;; We don't clobber the conditions, but the potential length of this
10724    ;; operation is sufficient to make conditionalizing the sequence 
10725    ;; unlikely to be profitable.
10726    (set_attr "conds" "clob")]
10727 )
10728
10729 (define_expand "eh_epilogue"
10730   [(use (match_operand:SI 0 "register_operand" ""))
10731    (use (match_operand:SI 1 "register_operand" ""))
10732    (use (match_operand:SI 2 "register_operand" ""))]
10733   "TARGET_EITHER"
10734   "
10735   {
10736     cfun->machine->eh_epilogue_sp_ofs = operands[1];
10737     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10738       {
10739         rtx ra = gen_rtx_REG (Pmode, 2);
10740
10741         emit_move_insn (ra, operands[2]);
10742         operands[2] = ra;
10743       }
10744     /* This is a hack -- we may have crystalized the function type too
10745        early.  */
10746     cfun->machine->func_type = 0;
10747   }"
10748 )
10749
10750 ;; This split is only used during output to reduce the number of patterns
10751 ;; that need assembler instructions adding to them.  We allowed the setting
10752 ;; of the conditions to be implicit during rtl generation so that
10753 ;; the conditional compare patterns would work.  However this conflicts to
10754 ;; some extent with the conditional data operations, so we have to split them
10755 ;; up again here.
10756
10757 ;; ??? Need to audit these splitters for Thumb-2.  Why isn't normal
10758 ;; conditional execution sufficient?
10759
10760 (define_split
10761   [(set (match_operand:SI 0 "s_register_operand" "")
10762         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10763                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10764                          (match_dup 0)
10765                          (match_operand 4 "" "")))
10766    (clobber (reg:CC CC_REGNUM))]
10767   "TARGET_ARM && reload_completed"
10768   [(set (match_dup 5) (match_dup 6))
10769    (cond_exec (match_dup 7)
10770               (set (match_dup 0) (match_dup 4)))]
10771   "
10772   {
10773     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10774                                              operands[2], operands[3]);
10775     enum rtx_code rc = GET_CODE (operands[1]);
10776
10777     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10778     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10779     if (mode == CCFPmode || mode == CCFPEmode)
10780       rc = reverse_condition_maybe_unordered (rc);
10781     else
10782       rc = reverse_condition (rc);
10783
10784     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10785   }"
10786 )
10787
10788 (define_split
10789   [(set (match_operand:SI 0 "s_register_operand" "")
10790         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10791                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10792                          (match_operand 4 "" "")
10793                          (match_dup 0)))
10794    (clobber (reg:CC CC_REGNUM))]
10795   "TARGET_ARM && reload_completed"
10796   [(set (match_dup 5) (match_dup 6))
10797    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10798               (set (match_dup 0) (match_dup 4)))]
10799   "
10800   {
10801     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10802                                              operands[2], operands[3]);
10803
10804     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10805     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10806   }"
10807 )
10808
10809 (define_split
10810   [(set (match_operand:SI 0 "s_register_operand" "")
10811         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10812                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10813                          (match_operand 4 "" "")
10814                          (match_operand 5 "" "")))
10815    (clobber (reg:CC CC_REGNUM))]
10816   "TARGET_ARM && reload_completed"
10817   [(set (match_dup 6) (match_dup 7))
10818    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10819               (set (match_dup 0) (match_dup 4)))
10820    (cond_exec (match_dup 8)
10821               (set (match_dup 0) (match_dup 5)))]
10822   "
10823   {
10824     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10825                                              operands[2], operands[3]);
10826     enum rtx_code rc = GET_CODE (operands[1]);
10827
10828     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10829     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10830     if (mode == CCFPmode || mode == CCFPEmode)
10831       rc = reverse_condition_maybe_unordered (rc);
10832     else
10833       rc = reverse_condition (rc);
10834
10835     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10836   }"
10837 )
10838
10839 (define_split
10840   [(set (match_operand:SI 0 "s_register_operand" "")
10841         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10842                           [(match_operand:SI 2 "s_register_operand" "")
10843                            (match_operand:SI 3 "arm_add_operand" "")])
10844                          (match_operand:SI 4 "arm_rhs_operand" "")
10845                          (not:SI
10846                           (match_operand:SI 5 "s_register_operand" ""))))
10847    (clobber (reg:CC CC_REGNUM))]
10848   "TARGET_ARM && reload_completed"
10849   [(set (match_dup 6) (match_dup 7))
10850    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10851               (set (match_dup 0) (match_dup 4)))
10852    (cond_exec (match_dup 8)
10853               (set (match_dup 0) (not:SI (match_dup 5))))]
10854   "
10855   {
10856     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10857                                              operands[2], operands[3]);
10858     enum rtx_code rc = GET_CODE (operands[1]);
10859
10860     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10861     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10862     if (mode == CCFPmode || mode == CCFPEmode)
10863       rc = reverse_condition_maybe_unordered (rc);
10864     else
10865       rc = reverse_condition (rc);
10866
10867     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10868   }"
10869 )
10870
10871 (define_insn "*cond_move_not"
10872   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10873         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10874                           [(match_operand 3 "cc_register" "") (const_int 0)])
10875                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10876                          (not:SI
10877                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
10878   "TARGET_ARM"
10879   "@
10880    mvn%D4\\t%0, %2
10881    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
10882   [(set_attr "conds" "use")
10883    (set_attr "length" "4,8")]
10884 )
10885
10886 ;; The next two patterns occur when an AND operation is followed by a
10887 ;; scc insn sequence 
10888
10889 (define_insn "*sign_extract_onebit"
10890   [(set (match_operand:SI 0 "s_register_operand" "=r")
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 (\"ands\\t%0, %1, %2\", operands);
10899     return \"mvnne\\t%0, #0\";
10900   "
10901   [(set_attr "conds" "clob")
10902    (set_attr "length" "8")]
10903 )
10904
10905 (define_insn "*not_signextract_onebit"
10906   [(set (match_operand:SI 0 "s_register_operand" "=r")
10907         (not:SI
10908          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10909                           (const_int 1)
10910                           (match_operand:SI 2 "const_int_operand" "n"))))
10911    (clobber (reg:CC CC_REGNUM))]
10912   "TARGET_ARM"
10913   "*
10914     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10915     output_asm_insn (\"tst\\t%1, %2\", operands);
10916     output_asm_insn (\"mvneq\\t%0, #0\", operands);
10917     return \"movne\\t%0, #0\";
10918   "
10919   [(set_attr "conds" "clob")
10920    (set_attr "length" "12")]
10921 )
10922 ;; ??? The above patterns need auditing for Thumb-2
10923
10924 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
10925 ;; expressions.  For simplicity, the first register is also in the unspec
10926 ;; part.
10927 (define_insn "*push_multi"
10928   [(match_parallel 2 "multi_register_push"
10929     [(set (match_operand:BLK 0 "memory_operand" "=m")
10930           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
10931                       UNSPEC_PUSH_MULT))])]
10932   "TARGET_32BIT"
10933   "*
10934   {
10935     int num_saves = XVECLEN (operands[2], 0);
10936      
10937     /* For the StrongARM at least it is faster to
10938        use STR to store only a single register.
10939        In Thumb mode always use push, and the assembler will pick
10940        something appropriate.  */
10941     if (num_saves == 1 && TARGET_ARM)
10942       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10943     else
10944       {
10945         int i;
10946         char pattern[100];
10947
10948         if (TARGET_ARM)
10949             strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10950         else
10951             strcpy (pattern, \"push\\t{%1\");
10952
10953         for (i = 1; i < num_saves; i++)
10954           {
10955             strcat (pattern, \", %|\");
10956             strcat (pattern,
10957                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10958           }
10959
10960         strcat (pattern, \"}\");
10961         output_asm_insn (pattern, operands);
10962       }
10963
10964     return \"\";
10965   }"
10966   [(set_attr "type" "store4")]
10967 )
10968
10969 (define_insn "stack_tie"
10970   [(set (mem:BLK (scratch))
10971         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10972                      (match_operand:SI 1 "s_register_operand" "rk")]
10973                     UNSPEC_PRLG_STK))]
10974   ""
10975   ""
10976   [(set_attr "length" "0")]
10977 )
10978
10979 ;; Similarly for the floating point registers
10980 (define_insn "*push_fp_multi"
10981   [(match_parallel 2 "multi_register_push"
10982     [(set (match_operand:BLK 0 "memory_operand" "=m")
10983           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "")]
10984                       UNSPEC_PUSH_MULT))])]
10985   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
10986   "*
10987   {
10988     char pattern[100];
10989
10990     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10991     output_asm_insn (pattern, operands);
10992     return \"\";
10993   }"
10994   [(set_attr "type" "f_store")]
10995 )
10996
10997 ;; Special patterns for dealing with the constant pool
10998
10999 (define_insn "align_4"
11000   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
11001   "TARGET_EITHER"
11002   "*
11003   assemble_align (32);
11004   return \"\";
11005   "
11006 )
11007
11008 (define_insn "align_8"
11009   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
11010   "TARGET_EITHER"
11011   "*
11012   assemble_align (64);
11013   return \"\";
11014   "
11015 )
11016
11017 (define_insn "consttable_end"
11018   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
11019   "TARGET_EITHER"
11020   "*
11021   making_const_table = FALSE;
11022   return \"\";
11023   "
11024 )
11025
11026 (define_insn "consttable_1"
11027   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
11028   "TARGET_THUMB1"
11029   "*
11030   making_const_table = TRUE;
11031   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
11032   assemble_zeros (3);
11033   return \"\";
11034   "
11035   [(set_attr "length" "4")]
11036 )
11037
11038 (define_insn "consttable_2"
11039   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
11040   "TARGET_THUMB1"
11041   "*
11042   making_const_table = TRUE;
11043   gcc_assert (GET_MODE_CLASS (GET_MODE (operands[0])) != MODE_FLOAT);
11044   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
11045   assemble_zeros (2);
11046   return \"\";
11047   "
11048   [(set_attr "length" "4")]
11049 )
11050
11051 (define_insn "consttable_4"
11052   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
11053   "TARGET_EITHER"
11054   "*
11055   {
11056     rtx x = operands[0];
11057     making_const_table = TRUE;
11058     switch (GET_MODE_CLASS (GET_MODE (x)))
11059       {
11060       case MODE_FLOAT:
11061         if (GET_MODE (x) == HFmode)
11062           arm_emit_fp16_const (x);
11063         else
11064           {
11065             REAL_VALUE_TYPE r;
11066             REAL_VALUE_FROM_CONST_DOUBLE (r, x);
11067             assemble_real (r, GET_MODE (x), BITS_PER_WORD);
11068           }
11069         break;
11070       default:
11071         /* XXX: Sometimes gcc does something really dumb and ends up with
11072            a HIGH in a constant pool entry, usually because it's trying to
11073            load into a VFP register.  We know this will always be used in
11074            combination with a LO_SUM which ignores the high bits, so just
11075            strip off the HIGH.  */
11076         if (GET_CODE (x) == HIGH)
11077           x = XEXP (x, 0);
11078         assemble_integer (x, 4, BITS_PER_WORD, 1);
11079         mark_symbol_refs_as_used (x);
11080         break;
11081       }
11082     return \"\";
11083   }"
11084   [(set_attr "length" "4")]
11085 )
11086
11087 (define_insn "consttable_8"
11088   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
11089   "TARGET_EITHER"
11090   "*
11091   {
11092     making_const_table = TRUE;
11093     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
11094       {
11095        case MODE_FLOAT:
11096         {
11097           REAL_VALUE_TYPE r;
11098           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
11099           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
11100           break;
11101         }
11102       default:
11103         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
11104         break;
11105       }
11106     return \"\";
11107   }"
11108   [(set_attr "length" "8")]
11109 )
11110
11111 (define_insn "consttable_16"
11112   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
11113   "TARGET_EITHER"
11114   "*
11115   {
11116     making_const_table = TRUE;
11117     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
11118       {
11119        case MODE_FLOAT:
11120         {
11121           REAL_VALUE_TYPE r;
11122           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
11123           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
11124           break;
11125         }
11126       default:
11127         assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
11128         break;
11129       }
11130     return \"\";
11131   }"
11132   [(set_attr "length" "16")]
11133 )
11134
11135 ;; Miscellaneous Thumb patterns
11136
11137 (define_expand "tablejump"
11138   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
11139               (use (label_ref (match_operand 1 "" "")))])]
11140   "TARGET_THUMB1"
11141   "
11142   if (flag_pic)
11143     {
11144       /* Hopefully, CSE will eliminate this copy.  */
11145       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
11146       rtx reg2 = gen_reg_rtx (SImode);
11147
11148       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
11149       operands[0] = reg2;
11150     }
11151   "
11152 )
11153
11154 ;; NB never uses BX.
11155 (define_insn "*thumb1_tablejump"
11156   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
11157    (use (label_ref (match_operand 1 "" "")))]
11158   "TARGET_THUMB1"
11159   "mov\\t%|pc, %0"
11160   [(set_attr "length" "2")]
11161 )
11162
11163 ;; V5 Instructions,
11164
11165 (define_insn "clzsi2"
11166   [(set (match_operand:SI 0 "s_register_operand" "=r")
11167         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
11168   "TARGET_32BIT && arm_arch5"
11169   "clz%?\\t%0, %1"
11170   [(set_attr "predicable" "yes")
11171    (set_attr "insn" "clz")])
11172
11173 (define_insn "rbitsi2"
11174   [(set (match_operand:SI 0 "s_register_operand" "=r")
11175         (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
11176   "TARGET_32BIT && arm_arch_thumb2"
11177   "rbit%?\\t%0, %1"
11178   [(set_attr "predicable" "yes")
11179    (set_attr "insn" "clz")])
11180
11181 (define_expand "ctzsi2"
11182  [(set (match_operand:SI           0 "s_register_operand" "")
11183        (ctz:SI (match_operand:SI  1 "s_register_operand" "")))]
11184   "TARGET_32BIT && arm_arch_thumb2"
11185   "
11186    {
11187      rtx tmp = gen_reg_rtx (SImode); 
11188      emit_insn (gen_rbitsi2 (tmp, operands[1]));
11189      emit_insn (gen_clzsi2 (operands[0], tmp));
11190    }
11191    DONE;
11192   "
11193 )
11194
11195 ;; V5E instructions.
11196
11197 (define_insn "prefetch"
11198   [(prefetch (match_operand:SI 0 "address_operand" "p")
11199              (match_operand:SI 1 "" "")
11200              (match_operand:SI 2 "" ""))]
11201   "TARGET_32BIT && arm_arch5e"
11202   "pld\\t%a0")
11203
11204 ;; General predication pattern
11205
11206 (define_cond_exec
11207   [(match_operator 0 "arm_comparison_operator"
11208     [(match_operand 1 "cc_register" "")
11209      (const_int 0)])]
11210   "TARGET_32BIT"
11211   ""
11212 )
11213
11214 (define_insn "prologue_use"
11215   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
11216   ""
11217   "%@ %0 needed for prologue"
11218   [(set_attr "length" "0")]
11219 )
11220
11221
11222 ;; Patterns for exception handling
11223
11224 (define_expand "eh_return"
11225   [(use (match_operand 0 "general_operand" ""))]
11226   "TARGET_EITHER"
11227   "
11228   {
11229     if (TARGET_32BIT)
11230       emit_insn (gen_arm_eh_return (operands[0]));
11231     else
11232       emit_insn (gen_thumb_eh_return (operands[0]));
11233     DONE;
11234   }"
11235 )
11236                                    
11237 ;; We can't expand this before we know where the link register is stored.
11238 (define_insn_and_split "arm_eh_return"
11239   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
11240                     VUNSPEC_EH_RETURN)
11241    (clobber (match_scratch:SI 1 "=&r"))]
11242   "TARGET_ARM"
11243   "#"
11244   "&& reload_completed"
11245   [(const_int 0)]
11246   "
11247   {
11248     arm_set_return_address (operands[0], operands[1]);
11249     DONE;
11250   }"
11251 )
11252
11253 (define_insn_and_split "thumb_eh_return"
11254   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
11255                     VUNSPEC_EH_RETURN)
11256    (clobber (match_scratch:SI 1 "=&l"))]
11257   "TARGET_THUMB1"
11258   "#"
11259   "&& reload_completed"
11260   [(const_int 0)]
11261   "
11262   {
11263     thumb_set_return_address (operands[0], operands[1]);
11264     DONE;
11265   }"
11266 )
11267
11268 \f
11269 ;; TLS support
11270
11271 (define_insn "load_tp_hard"
11272   [(set (match_operand:SI 0 "register_operand" "=r")
11273         (unspec:SI [(const_int 0)] UNSPEC_TLS))]
11274   "TARGET_HARD_TP"
11275   "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
11276   [(set_attr "predicable" "yes")]
11277 )
11278
11279 ;; Doesn't clobber R1-R3.  Must use r0 for the first operand.
11280 (define_insn "load_tp_soft"
11281   [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
11282    (clobber (reg:SI LR_REGNUM))
11283    (clobber (reg:SI IP_REGNUM))
11284    (clobber (reg:CC CC_REGNUM))]
11285   "TARGET_SOFT_TP"
11286   "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
11287   [(set_attr "conds" "clob")]
11288 )
11289
11290 (define_insn "*arm_movtas_ze" 
11291   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
11292                    (const_int 16)
11293                    (const_int 16))
11294         (match_operand:SI 1 "const_int_operand" ""))]
11295   "TARGET_32BIT"
11296   "movt%?\t%0, %c1"
11297  [(set_attr "predicable" "yes")
11298    (set_attr "length" "4")]
11299 )
11300
11301 (define_insn "arm_rev"
11302   [(set (match_operand:SI 0 "s_register_operand" "=r")
11303         (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
11304   "TARGET_EITHER && arm_arch6"
11305   "rev\t%0, %1"
11306   [(set (attr "length")
11307         (if_then_else (eq_attr "is_thumb" "yes")
11308                       (const_int 2)
11309                       (const_int 4)))]
11310 )
11311
11312 (define_expand "arm_legacy_rev"
11313   [(set (match_operand:SI 2 "s_register_operand" "")
11314         (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
11315                              (const_int 16))
11316                 (match_dup 1)))
11317    (set (match_dup 2)
11318         (lshiftrt:SI (match_dup 2)
11319                      (const_int 8)))
11320    (set (match_operand:SI 3 "s_register_operand" "")
11321         (rotatert:SI (match_dup 1)
11322                      (const_int 8)))
11323    (set (match_dup 2)
11324         (and:SI (match_dup 2)
11325                 (const_int -65281)))
11326    (set (match_operand:SI 0 "s_register_operand" "")
11327         (xor:SI (match_dup 3)
11328                 (match_dup 2)))]
11329   "TARGET_32BIT"
11330   ""
11331 )
11332
11333 ;; Reuse temporaries to keep register pressure down.
11334 (define_expand "thumb_legacy_rev"
11335   [(set (match_operand:SI 2 "s_register_operand" "")
11336      (ashift:SI (match_operand:SI 1 "s_register_operand" "")
11337                 (const_int 24)))
11338    (set (match_operand:SI 3 "s_register_operand" "")
11339      (lshiftrt:SI (match_dup 1)
11340                   (const_int 24)))
11341    (set (match_dup 3)
11342      (ior:SI (match_dup 3)
11343              (match_dup 2)))
11344    (set (match_operand:SI 4 "s_register_operand" "")
11345      (const_int 16))
11346    (set (match_operand:SI 5 "s_register_operand" "")
11347      (rotatert:SI (match_dup 1)
11348                   (match_dup 4)))
11349    (set (match_dup 2)
11350      (ashift:SI (match_dup 5)
11351                 (const_int 24)))
11352    (set (match_dup 5)
11353      (lshiftrt:SI (match_dup 5)
11354                   (const_int 24)))
11355    (set (match_dup 5)
11356      (ior:SI (match_dup 5)
11357              (match_dup 2)))
11358    (set (match_dup 5)
11359      (rotatert:SI (match_dup 5)
11360                   (match_dup 4)))
11361    (set (match_operand:SI 0 "s_register_operand" "")
11362      (ior:SI (match_dup 5)
11363              (match_dup 3)))]
11364   "TARGET_THUMB"
11365   ""
11366 )
11367
11368 (define_expand "bswapsi2"
11369   [(set (match_operand:SI 0 "s_register_operand" "=r")
11370         (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
11371 "TARGET_EITHER"
11372 "
11373   if (!arm_arch6)
11374     {
11375       if (!optimize_size)
11376         {
11377           rtx op2 = gen_reg_rtx (SImode);
11378           rtx op3 = gen_reg_rtx (SImode);
11379
11380           if (TARGET_THUMB)
11381             {
11382               rtx op4 = gen_reg_rtx (SImode);
11383               rtx op5 = gen_reg_rtx (SImode);
11384
11385               emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
11386                                                op2, op3, op4, op5));
11387             }
11388           else
11389             {
11390               emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
11391                                              op2, op3));
11392             }
11393
11394           DONE;
11395         }
11396       else
11397         FAIL;
11398     }
11399   "
11400 )
11401
11402 ;; Load the FPA co-processor patterns
11403 (include "fpa.md")
11404 ;; Load the Maverick co-processor patterns
11405 (include "cirrus.md")
11406 ;; Vector bits common to IWMMXT and Neon
11407 (include "vec-common.md")
11408 ;; Load the Intel Wireless Multimedia Extension patterns
11409 (include "iwmmxt.md")
11410 ;; Load the VFP co-processor patterns
11411 (include "vfp.md")
11412 ;; Thumb-2 patterns
11413 (include "thumb2.md")
11414 ;; Neon patterns
11415 (include "neon.md")
11416