OSDN Git Service

2009-07-26 Mikael Pettersson <mikpe@it.uu.se>
[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
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   ]
104 )
105
106 ;; UNSPEC_VOLATILE Usage:
107
108 (define_constants
109   [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
110                         ;   insn in the code.
111    (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
112                         ;   instruction epilogue sequence that isn't expanded
113                         ;   into normal RTL.  Used for both normal and sibcall
114                         ;   epilogues.
115    (VUNSPEC_ALIGN    2) ; `align' insn.  Used at the head of a minipool table 
116                         ;   for inlined constants.
117    (VUNSPEC_POOL_END 3) ; `end-of-table'.  Used to mark the end of a minipool
118                         ;   table.
119    (VUNSPEC_POOL_1   4) ; `pool-entry(1)'.  An entry in the constant pool for
120                         ;   an 8-bit object.
121    (VUNSPEC_POOL_2   5) ; `pool-entry(2)'.  An entry in the constant pool for
122                         ;   a 16-bit object.
123    (VUNSPEC_POOL_4   6) ; `pool-entry(4)'.  An entry in the constant pool for
124                         ;   a 32-bit object.
125    (VUNSPEC_POOL_8   7) ; `pool-entry(8)'.  An entry in the constant pool for
126                         ;   a 64-bit object.
127    (VUNSPEC_POOL_16  8) ; `pool-entry(16)'.  An entry in the constant pool for
128                         ;   a 128-bit object.
129    (VUNSPEC_TMRC     9) ; Used by the iWMMXt TMRC instruction.
130    (VUNSPEC_TMCR     10) ; Used by the iWMMXt TMCR instruction.
131    (VUNSPEC_ALIGN8   11) ; 8-byte alignment version of VUNSPEC_ALIGN
132    (VUNSPEC_WCMP_EQ  12) ; Used by the iWMMXt WCMPEQ instructions
133    (VUNSPEC_WCMP_GTU 13) ; Used by the iWMMXt WCMPGTU instructions
134    (VUNSPEC_WCMP_GT  14) ; Used by the iwMMXT WCMPGT instructions
135    (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
136                          ; handling.
137   ]
138 )
139 \f
140 ;;---------------------------------------------------------------------------
141 ;; Attributes
142
143 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
144 ; generating ARM code.  This is used to control the length of some insn
145 ; patterns that share the same RTL in both ARM and Thumb code.
146 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
147
148 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
149 ; scheduling decisions for the load unit and the multiplier.
150 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_tune_strongarm")))
151
152 ; IS_XSCALE is set to 'yes' when compiling for XScale.
153 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
154
155 ;; Operand number of an input operand that is shifted.  Zero if the
156 ;; given instruction does not shift one of its input operands.
157 (define_attr "shift" "" (const_int 0))
158
159 ; Floating Point Unit.  If we only have floating point emulation, then there
160 ; is no point in scheduling the floating point insns.  (Well, for best
161 ; performance we should try and group them together).
162 (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp,vfpv3d16,vfpv3,neon,neon_fp16"
163   (const (symbol_ref "arm_fpu_attr")))
164
165 ; LENGTH of an instruction (in bytes)
166 (define_attr "length" "" (const_int 4))
167
168 ; POOL_RANGE is how far away from a constant pool entry that this insn
169 ; can be placed.  If the distance is zero, then this insn will never
170 ; reference the pool.
171 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
172 ; before its address.
173 (define_attr "pool_range" "" (const_int 0))
174 (define_attr "neg_pool_range" "" (const_int 0))
175
176 ; An assembler sequence may clobber the condition codes without us knowing.
177 ; If such an insn references the pool, then we have no way of knowing how,
178 ; so use the most conservative value for pool_range.
179 (define_asm_attributes
180  [(set_attr "conds" "clob")
181   (set_attr "length" "4")
182   (set_attr "pool_range" "250")])
183
184 ;; The instruction used to implement a particular pattern.  This
185 ;; information is used by pipeline descriptions to provide accurate
186 ;; scheduling information.
187
188 (define_attr "insn"
189         "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"
190         (const_string "other"))
191
192 ; TYPE attribute is used to detect floating point instructions which, if
193 ; running on a co-processor can run in parallel with other, basic instructions
194 ; If write-buffer scheduling is enabled then it can also be used in the
195 ; scheduling of writes.
196
197 ; Classification of each insn
198 ; Note: vfp.md has different meanings for some of these, and some further
199 ; types as well.  See that file for details.
200 ; alu           any alu  instruction that doesn't hit memory or fp
201 ;               regs or have a shifted source operand
202 ; alu_shift     any data instruction that doesn't hit memory or fp
203 ;               regs, but has a source operand shifted by a constant
204 ; alu_shift_reg any data instruction that doesn't hit memory or fp
205 ;               regs, but has a source operand shifted by a register value
206 ; mult          a multiply instruction
207 ; block         blockage insn, this blocks all functional units
208 ; float         a floating point arithmetic operation (subject to expansion)
209 ; fdivd         DFmode floating point division
210 ; fdivs         SFmode floating point division
211 ; fmul          Floating point multiply
212 ; ffmul         Fast floating point multiply
213 ; farith        Floating point arithmetic (4 cycle)
214 ; ffarith       Fast floating point arithmetic (2 cycle)
215 ; float_em      a floating point arithmetic operation that is normally emulated
216 ;               even on a machine with an fpa.
217 ; f_load        a floating point load from memory
218 ; f_store       a floating point store to memory
219 ; f_load[sd]    single/double load from memory
220 ; f_store[sd]   single/double store to memory
221 ; f_flag        a transfer of co-processor flags to the CPSR
222 ; f_mem_r       a transfer of a floating point register to a real reg via mem
223 ; r_mem_f       the reverse of f_mem_r
224 ; f_2_r         fast transfer float to arm (no memory needed)
225 ; r_2_f         fast transfer arm to float
226 ; f_cvt         convert floating<->integral
227 ; branch        a branch
228 ; call          a subroutine call
229 ; load_byte     load byte(s) from memory to arm registers
230 ; load1         load 1 word from memory to arm registers
231 ; load2         load 2 words from memory to arm registers
232 ; load3         load 3 words from memory to arm registers
233 ; load4         load 4 words from memory to arm registers
234 ; store         store 1 word to memory from arm registers
235 ; store2        store 2 words
236 ; store3        store 3 words
237 ; store4        store 4 (or more) words
238 ;  Additions for Cirrus Maverick co-processor:
239 ; mav_farith    Floating point arithmetic (4 cycle)
240 ; mav_dmult     Double multiplies (7 cycle)
241 ;
242
243 (define_attr "type"
244         "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"
245         (if_then_else 
246          (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
247          (const_string "mult")
248          (const_string "alu")))
249
250 ; Load scheduling, set from the arm_ld_sched variable
251 ; initialized by arm_override_options() 
252 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
253
254 ;; Classification of NEON instructions for scheduling purposes.
255 ;; Do not set this attribute and the "type" attribute together in
256 ;; any one instruction pattern.
257 (define_attr "neon_type"
258    "neon_int_1,\
259    neon_int_2,\
260    neon_int_3,\
261    neon_int_4,\
262    neon_int_5,\
263    neon_vqneg_vqabs,\
264    neon_vmov,\
265    neon_vaba,\
266    neon_vsma,\
267    neon_vaba_qqq,\
268    neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
269    neon_mul_qqq_8_16_32_ddd_32,\
270    neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,\
271    neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
272    neon_mla_qqq_8_16,\
273    neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,\
274    neon_mla_qqq_32_qqd_32_scalar,\
275    neon_mul_ddd_16_scalar_32_16_long_scalar,\
276    neon_mul_qqd_32_scalar,\
277    neon_mla_ddd_16_scalar_qdd_32_16_long_scalar,\
278    neon_shift_1,\
279    neon_shift_2,\
280    neon_shift_3,\
281    neon_vshl_ddd,\
282    neon_vqshl_vrshl_vqrshl_qqq,\
283    neon_vsra_vrsra,\
284    neon_fp_vadd_ddd_vabs_dd,\
285    neon_fp_vadd_qqq_vabs_qq,\
286    neon_fp_vsum,\
287    neon_fp_vmul_ddd,\
288    neon_fp_vmul_qqd,\
289    neon_fp_vmla_ddd,\
290    neon_fp_vmla_qqq,\
291    neon_fp_vmla_ddd_scalar,\
292    neon_fp_vmla_qqq_scalar,\
293    neon_fp_vrecps_vrsqrts_ddd,\
294    neon_fp_vrecps_vrsqrts_qqq,\
295    neon_bp_simple,\
296    neon_bp_2cycle,\
297    neon_bp_3cycle,\
298    neon_ldr,\
299    neon_str,\
300    neon_vld1_1_2_regs,\
301    neon_vld1_3_4_regs,\
302    neon_vld2_2_regs_vld1_vld2_all_lanes,\
303    neon_vld2_4_regs,\
304    neon_vld3_vld4,\
305    neon_vst1_1_2_regs_vst2_2_regs,\
306    neon_vst1_3_4_regs,\
307    neon_vst2_4_regs_vst3_vst4,\
308    neon_vst3_vst4,\
309    neon_vld1_vld2_lane,\
310    neon_vld3_vld4_lane,\
311    neon_vst1_vst2_lane,\
312    neon_vst3_vst4_lane,\
313    neon_vld3_vld4_all_lanes,\
314    neon_mcr,\
315    neon_mcr_2_mcrr,\
316    neon_mrc,\
317    neon_mrrc,\
318    neon_ldm_2,\
319    neon_stm_2,\
320    none"
321  (const_string "none"))
322
323 ; condition codes: this one is used by final_prescan_insn to speed up
324 ; conditionalizing instructions.  It saves having to scan the rtl to see if
325 ; it uses or alters the condition codes.
326
327 ; USE means that the condition codes are used by the insn in the process of
328 ;   outputting code, this means (at present) that we can't use the insn in
329 ;   inlined branches
330 ;
331 ; SET means that the purpose of the insn is to set the condition codes in a
332 ;   well defined manner.
333 ;
334 ; CLOB means that the condition codes are altered in an undefined manner, if
335 ;   they are altered at all
336 ;
337 ; UNCONDITIONAL means the instions can not be conditionally executed.
338 ;
339 ; NOCOND means that the condition codes are neither altered nor affect the
340 ;   output of this insn
341
342 (define_attr "conds" "use,set,clob,unconditional,nocond"
343         (if_then_else (eq_attr "type" "call")
344          (const_string "clob")
345          (if_then_else (eq_attr "neon_type" "none")
346           (const_string "nocond")
347           (const_string "unconditional"))))
348
349 ; Predicable means that the insn can be conditionally executed based on
350 ; an automatically added predicate (additional patterns are generated by 
351 ; gen...).  We default to 'no' because no Thumb patterns match this rule
352 ; and not all ARM patterns do.
353 (define_attr "predicable" "no,yes" (const_string "no"))
354
355 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
356 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
357 ; suffer blockages enough to warrant modelling this (and it can adversely
358 ; affect the schedule).
359 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
360
361 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
362 ; to stall the processor.  Used with model_wbuf above.
363 (define_attr "write_conflict" "no,yes"
364   (if_then_else (eq_attr "type"
365                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
366                 (const_string "yes")
367                 (const_string "no")))
368
369 ; Classify the insns into those that take one cycle and those that take more
370 ; than one on the main cpu execution unit.
371 (define_attr "core_cycles" "single,multi"
372   (if_then_else (eq_attr "type"
373                  "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
374                 (const_string "single")
375                 (const_string "multi")))
376
377 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
378 ;; distant label.  Only applicable to Thumb code.
379 (define_attr "far_jump" "yes,no" (const_string "no"))
380
381
382 ;; The number of machine instructions this pattern expands to.
383 ;; Used for Thumb-2 conditional execution.
384 (define_attr "ce_count" "" (const_int 1))
385
386 ;;---------------------------------------------------------------------------
387 ;; Mode iterators
388
389 ; A list of modes that are exactly 64 bits in size.  We use this to expand
390 ; some splits that are the same for all modes when operating on ARM 
391 ; registers.
392 (define_mode_iterator ANY64 [DI DF V8QI V4HI V2SI V2SF])
393
394 ;;---------------------------------------------------------------------------
395 ;; Predicates
396
397 (include "predicates.md")
398 (include "constraints.md")
399
400 ;;---------------------------------------------------------------------------
401 ;; Pipeline descriptions
402
403 ;; Processor type.  This is created automatically from arm-cores.def.
404 (include "arm-tune.md")
405
406 (define_attr "tune_cortexr4" "yes,no"
407   (const (if_then_else
408           (eq_attr "tune" "cortexr4,cortexr4f")
409           (const_string "yes")
410           (const_string "no"))))
411
412 ;; True if the generic scheduling description should be used.
413
414 (define_attr "generic_sched" "yes,no"
415   (const (if_then_else 
416           (ior (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa8,cortexa9")
417               (eq_attr "tune_cortexr4" "yes"))
418           (const_string "no")
419           (const_string "yes"))))
420
421 (define_attr "generic_vfp" "yes,no"
422   (const (if_then_else
423           (and (eq_attr "fpu" "vfp")
424                (eq_attr "tune" "!arm1020e,arm1022e,cortexa8,cortexa9")
425                (eq_attr "tune_cortexr4" "no"))
426           (const_string "yes")
427           (const_string "no"))))
428
429 (include "arm-generic.md")
430 (include "arm926ejs.md")
431 (include "arm1020e.md")
432 (include "arm1026ejs.md")
433 (include "arm1136jfs.md")
434 (include "cortex-a8.md")
435 (include "cortex-a9.md")
436 (include "cortex-r4.md")
437 (include "cortex-r4f.md")
438 (include "vfp11.md")
439
440 \f
441 ;;---------------------------------------------------------------------------
442 ;; Insn patterns
443 ;;
444 ;; Addition insns.
445
446 ;; Note: For DImode insns, there is normally no reason why operands should
447 ;; not be in the same register, what we don't want is for something being
448 ;; written to partially overlap something that is an input.
449 ;; Cirrus 64bit additions should not be split because we have a native
450 ;; 64bit addition instructions.
451
452 (define_expand "adddi3"
453  [(parallel
454    [(set (match_operand:DI           0 "s_register_operand" "")
455           (plus:DI (match_operand:DI 1 "s_register_operand" "")
456                    (match_operand:DI 2 "s_register_operand" "")))
457     (clobber (reg:CC CC_REGNUM))])]
458   "TARGET_EITHER"
459   "
460   if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
461     {
462       if (!cirrus_fp_register (operands[0], DImode))
463         operands[0] = force_reg (DImode, operands[0]);
464       if (!cirrus_fp_register (operands[1], DImode))
465         operands[1] = force_reg (DImode, operands[1]);
466       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
467       DONE;
468     }
469
470   if (TARGET_THUMB1)
471     {
472       if (GET_CODE (operands[1]) != REG)
473         operands[1] = force_reg (DImode, operands[1]);
474       if (GET_CODE (operands[2]) != REG)
475         operands[2] = force_reg (DImode, operands[2]);
476      }
477   "
478 )
479
480 (define_insn "*thumb1_adddi3"
481   [(set (match_operand:DI          0 "register_operand" "=l")
482         (plus:DI (match_operand:DI 1 "register_operand" "%0")
483                  (match_operand:DI 2 "register_operand" "l")))
484    (clobber (reg:CC CC_REGNUM))
485   ]
486   "TARGET_THUMB1"
487   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
488   [(set_attr "length" "4")]
489 )
490
491 (define_insn_and_split "*arm_adddi3"
492   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
493         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
494                  (match_operand:DI 2 "s_register_operand" "r,  0")))
495    (clobber (reg:CC CC_REGNUM))]
496   "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
497   "#"
498   "TARGET_32BIT && reload_completed"
499   [(parallel [(set (reg:CC_C CC_REGNUM)
500                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
501                                  (match_dup 1)))
502               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
503    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
504                                (plus:SI (match_dup 4) (match_dup 5))))]
505   "
506   {
507     operands[3] = gen_highpart (SImode, operands[0]);
508     operands[0] = gen_lowpart (SImode, operands[0]);
509     operands[4] = gen_highpart (SImode, operands[1]);
510     operands[1] = gen_lowpart (SImode, operands[1]);
511     operands[5] = gen_highpart (SImode, operands[2]);
512     operands[2] = gen_lowpart (SImode, operands[2]);
513   }"
514   [(set_attr "conds" "clob")
515    (set_attr "length" "8")]
516 )
517
518 (define_insn_and_split "*adddi_sesidi_di"
519   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
520         (plus:DI (sign_extend:DI
521                   (match_operand:SI 2 "s_register_operand" "r,r"))
522                  (match_operand:DI 1 "s_register_operand" "r,0")))
523    (clobber (reg:CC CC_REGNUM))]
524   "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
525   "#"
526   "TARGET_32BIT && reload_completed"
527   [(parallel [(set (reg:CC_C CC_REGNUM)
528                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
529                                  (match_dup 1)))
530               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
531    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
532                                (plus:SI (ashiftrt:SI (match_dup 2)
533                                                      (const_int 31))
534                                         (match_dup 4))))]
535   "
536   {
537     operands[3] = gen_highpart (SImode, operands[0]);
538     operands[0] = gen_lowpart (SImode, operands[0]);
539     operands[4] = gen_highpart (SImode, operands[1]);
540     operands[1] = gen_lowpart (SImode, operands[1]);
541     operands[2] = gen_lowpart (SImode, operands[2]);
542   }"
543   [(set_attr "conds" "clob")
544    (set_attr "length" "8")]
545 )
546
547 (define_insn_and_split "*adddi_zesidi_di"
548   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
549         (plus:DI (zero_extend:DI
550                   (match_operand:SI 2 "s_register_operand" "r,r"))
551                  (match_operand:DI 1 "s_register_operand" "r,0")))
552    (clobber (reg:CC CC_REGNUM))]
553   "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
554   "#"
555   "TARGET_32BIT && reload_completed"
556   [(parallel [(set (reg:CC_C CC_REGNUM)
557                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
558                                  (match_dup 1)))
559               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
560    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
561                                (plus:SI (match_dup 4) (const_int 0))))]
562   "
563   {
564     operands[3] = gen_highpart (SImode, operands[0]);
565     operands[0] = gen_lowpart (SImode, operands[0]);
566     operands[4] = gen_highpart (SImode, operands[1]);
567     operands[1] = gen_lowpart (SImode, operands[1]);
568     operands[2] = gen_lowpart (SImode, operands[2]);
569   }"
570   [(set_attr "conds" "clob")
571    (set_attr "length" "8")]
572 )
573
574 (define_expand "addsi3"
575   [(set (match_operand:SI          0 "s_register_operand" "")
576         (plus:SI (match_operand:SI 1 "s_register_operand" "")
577                  (match_operand:SI 2 "reg_or_int_operand" "")))]
578   "TARGET_EITHER"
579   "
580   if (TARGET_32BIT && GET_CODE (operands[2]) == CONST_INT)
581     {
582       arm_split_constant (PLUS, SImode, NULL_RTX,
583                           INTVAL (operands[2]), operands[0], operands[1],
584                           optimize && can_create_pseudo_p ());
585       DONE;
586     }
587   "
588 )
589
590 ; If there is a scratch available, this will be faster than synthesizing the
591 ; addition.
592 (define_peephole2
593   [(match_scratch:SI 3 "r")
594    (set (match_operand:SI          0 "arm_general_register_operand" "")
595         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
596                  (match_operand:SI 2 "const_int_operand"  "")))]
597   "TARGET_32BIT &&
598    !(const_ok_for_arm (INTVAL (operands[2]))
599      || const_ok_for_arm (-INTVAL (operands[2])))
600     && const_ok_for_arm (~INTVAL (operands[2]))"
601   [(set (match_dup 3) (match_dup 2))
602    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
603   ""
604 )
605
606 ;; The r/r/k alternative is required when reloading the address
607 ;;  (plus (reg rN) (reg sp)) into (reg rN).  In this case reload will
608 ;; put the duplicated register first, and not try the commutative version.
609 (define_insn_and_split "*arm_addsi3"
610   [(set (match_operand:SI          0 "s_register_operand" "=r, !k, r,r, !k,r")
611         (plus:SI (match_operand:SI 1 "s_register_operand" "%rk,!k, r,rk,!k,rk")
612                  (match_operand:SI 2 "reg_or_int_operand" "rI, rI,!k,L, L,?n")))]
613   "TARGET_32BIT"
614   "@
615    add%?\\t%0, %1, %2
616    add%?\\t%0, %1, %2
617    add%?\\t%0, %2, %1
618    sub%?\\t%0, %1, #%n2
619    sub%?\\t%0, %1, #%n2
620    #"
621   "TARGET_32BIT
622    && GET_CODE (operands[2]) == CONST_INT
623    && !(const_ok_for_arm (INTVAL (operands[2]))
624         || const_ok_for_arm (-INTVAL (operands[2])))
625    && (reload_completed || !arm_eliminable_register (operands[1]))"
626   [(clobber (const_int 0))]
627   "
628   arm_split_constant (PLUS, SImode, curr_insn,
629                       INTVAL (operands[2]), operands[0],
630                       operands[1], 0);
631   DONE;
632   "
633   [(set_attr "length" "4,4,4,4,4,16")
634    (set_attr "predicable" "yes")]
635 )
636
637 ;; Register group 'k' is a single register group containing only the stack
638 ;; register.  Trying to reload it will always fail catastrophically,
639 ;; so never allow those alternatives to match if reloading is needed.
640
641 (define_insn_and_split "*thumb1_addsi3"
642   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*rk,*hk,l,!k,l,l")
643         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k,0,l")
644                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,!M,!O,Pa,Pb")))]
645   "TARGET_THUMB1"
646   "*
647    static const char * const asms[] = 
648    {
649      \"add\\t%0, %0, %2\",
650      \"sub\\t%0, %0, #%n2\",
651      \"add\\t%0, %1, %2\",
652      \"add\\t%0, %0, %2\",
653      \"add\\t%0, %0, %2\",
654      \"add\\t%0, %1, %2\",
655      \"add\\t%0, %1, %2\",
656      \"#\",
657      \"#\"
658    };
659    if ((which_alternative == 2 || which_alternative == 6)
660        && GET_CODE (operands[2]) == CONST_INT
661        && INTVAL (operands[2]) < 0)
662      return \"sub\\t%0, %1, #%n2\";
663    return asms[which_alternative];
664   "
665   "&& reload_completed && CONST_INT_P (operands[2])
666    && operands[1] != stack_pointer_rtx
667    && (INTVAL (operands[2]) > 255 || INTVAL (operands[2]) < -255)"
668   [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
669    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
670   {
671     HOST_WIDE_INT offset = INTVAL (operands[2]);
672     if (offset > 255)
673       offset = 255;
674     else if (offset < -255)
675       offset = -255;
676     
677     operands[3] = GEN_INT (offset);
678     operands[2] = GEN_INT (INTVAL (operands[2]) - offset);
679   }
680   [(set_attr "length" "2,2,2,2,2,2,2,4,4")]
681 )
682
683 ;; Reloading and elimination of the frame pointer can
684 ;; sometimes cause this optimization to be missed.
685 (define_peephole2
686   [(set (match_operand:SI 0 "arm_general_register_operand" "")
687         (match_operand:SI 1 "const_int_operand" ""))
688    (set (match_dup 0)
689         (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
690   "TARGET_THUMB1
691    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
692    && (INTVAL (operands[1]) & 3) == 0"
693   [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
694   ""
695 )
696
697 ;; ??? Make Thumb-2 variants which prefer low regs
698 (define_insn "*addsi3_compare0"
699   [(set (reg:CC_NOOV CC_REGNUM)
700         (compare:CC_NOOV
701          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
702                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
703          (const_int 0)))
704    (set (match_operand:SI 0 "s_register_operand" "=r,r")
705         (plus:SI (match_dup 1) (match_dup 2)))]
706   "TARGET_32BIT"
707   "@
708    add%.\\t%0, %1, %2
709    sub%.\\t%0, %1, #%n2"
710   [(set_attr "conds" "set")]
711 )
712
713 (define_insn "*addsi3_compare0_scratch"
714   [(set (reg:CC_NOOV CC_REGNUM)
715         (compare:CC_NOOV
716          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
717                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
718          (const_int 0)))]
719   "TARGET_32BIT"
720   "@
721    cmn%?\\t%0, %1
722    cmp%?\\t%0, #%n1"
723   [(set_attr "conds" "set")]
724 )
725
726 (define_insn "*compare_negsi_si"
727   [(set (reg:CC_Z CC_REGNUM)
728         (compare:CC_Z
729          (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
730          (match_operand:SI 1 "s_register_operand" "r")))]
731   "TARGET_32BIT"
732   "cmn%?\\t%1, %0"
733   [(set_attr "conds" "set")]
734 )
735
736 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
737 ;; addend is a constant.
738 (define_insn "*cmpsi2_addneg"
739   [(set (reg:CC CC_REGNUM)
740         (compare:CC
741          (match_operand:SI 1 "s_register_operand" "r,r")
742          (match_operand:SI 2 "arm_addimm_operand" "I,L")))
743    (set (match_operand:SI 0 "s_register_operand" "=r,r")
744         (plus:SI (match_dup 1)
745                  (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
746   "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
747   "@
748    sub%.\\t%0, %1, %2
749    add%.\\t%0, %1, #%n2"
750   [(set_attr "conds" "set")]
751 )
752
753 ;; Convert the sequence
754 ;;  sub  rd, rn, #1
755 ;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
756 ;;  bne  dest
757 ;; into
758 ;;  subs rd, rn, #1
759 ;;  bcs  dest   ((unsigned)rn >= 1)
760 ;; similarly for the beq variant using bcc.
761 ;; This is a common looping idiom (while (n--))
762 (define_peephole2
763   [(set (match_operand:SI 0 "arm_general_register_operand" "")
764         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
765                  (const_int -1)))
766    (set (match_operand 2 "cc_register" "")
767         (compare (match_dup 0) (const_int -1)))
768    (set (pc)
769         (if_then_else (match_operator 3 "equality_operator"
770                        [(match_dup 2) (const_int 0)])
771                       (match_operand 4 "" "")
772                       (match_operand 5 "" "")))]
773   "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
774   [(parallel[
775     (set (match_dup 2)
776          (compare:CC
777           (match_dup 1) (const_int 1)))
778     (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
779    (set (pc)
780         (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
781                       (match_dup 4)
782                       (match_dup 5)))]
783   "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
784    operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
785                                   ? GEU : LTU),
786                                  VOIDmode, 
787                                  operands[2], const0_rtx);"
788 )
789
790 ;; The next four insns work because they compare the result with one of
791 ;; the operands, and we know that the use of the condition code is
792 ;; either GEU or LTU, so we can use the carry flag from the addition
793 ;; instead of doing the compare a second time.
794 (define_insn "*addsi3_compare_op1"
795   [(set (reg:CC_C CC_REGNUM)
796         (compare:CC_C
797          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
798                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
799          (match_dup 1)))
800    (set (match_operand:SI 0 "s_register_operand" "=r,r")
801         (plus:SI (match_dup 1) (match_dup 2)))]
802   "TARGET_32BIT"
803   "@
804    add%.\\t%0, %1, %2
805    sub%.\\t%0, %1, #%n2"
806   [(set_attr "conds" "set")]
807 )
808
809 (define_insn "*addsi3_compare_op2"
810   [(set (reg:CC_C CC_REGNUM)
811         (compare:CC_C
812          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
813                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
814          (match_dup 2)))
815    (set (match_operand:SI 0 "s_register_operand" "=r,r")
816         (plus:SI (match_dup 1) (match_dup 2)))]
817   "TARGET_32BIT"
818   "@
819    add%.\\t%0, %1, %2
820    sub%.\\t%0, %1, #%n2"
821   [(set_attr "conds" "set")]
822 )
823
824 (define_insn "*compare_addsi2_op0"
825   [(set (reg:CC_C CC_REGNUM)
826         (compare:CC_C
827          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
828                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
829          (match_dup 0)))]
830   "TARGET_32BIT"
831   "@
832    cmn%?\\t%0, %1
833    cmp%?\\t%0, #%n1"
834   [(set_attr "conds" "set")]
835 )
836
837 (define_insn "*compare_addsi2_op1"
838   [(set (reg:CC_C CC_REGNUM)
839         (compare:CC_C
840          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
841                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
842          (match_dup 1)))]
843   "TARGET_32BIT"
844   "@
845    cmn%?\\t%0, %1
846    cmp%?\\t%0, #%n1"
847   [(set_attr "conds" "set")]
848 )
849
850 (define_insn "*addsi3_carryin"
851   [(set (match_operand:SI 0 "s_register_operand" "=r")
852         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
853                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
854                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
855   "TARGET_32BIT"
856   "adc%?\\t%0, %1, %2"
857   [(set_attr "conds" "use")]
858 )
859
860 (define_insn "*addsi3_carryin_shift"
861   [(set (match_operand:SI 0 "s_register_operand" "=r")
862         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
863                  (plus:SI
864                    (match_operator:SI 2 "shift_operator"
865                       [(match_operand:SI 3 "s_register_operand" "r")
866                        (match_operand:SI 4 "reg_or_int_operand" "rM")])
867                     (match_operand:SI 1 "s_register_operand" "r"))))]
868   "TARGET_32BIT"
869   "adc%?\\t%0, %1, %3%S2"
870   [(set_attr "conds" "use")
871    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
872                       (const_string "alu_shift")
873                       (const_string "alu_shift_reg")))]
874 )
875
876 (define_insn "*addsi3_carryin_alt1"
877   [(set (match_operand:SI 0 "s_register_operand" "=r")
878         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
879                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
880                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
881   "TARGET_32BIT"
882   "adc%?\\t%0, %1, %2"
883   [(set_attr "conds" "use")]
884 )
885
886 (define_insn "*addsi3_carryin_alt2"
887   [(set (match_operand:SI 0 "s_register_operand" "=r")
888         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
889                           (match_operand:SI 1 "s_register_operand" "r"))
890                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
891   "TARGET_32BIT"
892   "adc%?\\t%0, %1, %2"
893   [(set_attr "conds" "use")]
894 )
895
896 (define_insn "*addsi3_carryin_alt3"
897   [(set (match_operand:SI 0 "s_register_operand" "=r")
898         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
899                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
900                  (match_operand:SI 1 "s_register_operand" "r")))]
901   "TARGET_32BIT"
902   "adc%?\\t%0, %1, %2"
903   [(set_attr "conds" "use")]
904 )
905
906 (define_expand "incscc"
907   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
908         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
909                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
910                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
911   "TARGET_32BIT"
912   ""
913 )
914
915 (define_insn "*arm_incscc"
916   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
917         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
918                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
919                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
920   "TARGET_ARM"
921   "@
922   add%d2\\t%0, %1, #1
923   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
924   [(set_attr "conds" "use")
925    (set_attr "length" "4,8")]
926 )
927
928 ; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
929 (define_split
930   [(set (match_operand:SI 0 "s_register_operand" "")
931         (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
932                             (match_operand:SI 2 "s_register_operand" ""))
933                  (const_int -1)))
934    (clobber (match_operand:SI 3 "s_register_operand" ""))]
935   "TARGET_32BIT"
936   [(set (match_dup 3) (match_dup 1))
937    (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
938   "
939   operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
940 ")
941
942 (define_expand "addsf3"
943   [(set (match_operand:SF          0 "s_register_operand" "")
944         (plus:SF (match_operand:SF 1 "s_register_operand" "")
945                  (match_operand:SF 2 "arm_float_add_operand" "")))]
946   "TARGET_32BIT && TARGET_HARD_FLOAT"
947   "
948   if (TARGET_MAVERICK
949       && !cirrus_fp_register (operands[2], SFmode))
950     operands[2] = force_reg (SFmode, operands[2]);
951 ")
952
953 (define_expand "adddf3"
954   [(set (match_operand:DF          0 "s_register_operand" "")
955         (plus:DF (match_operand:DF 1 "s_register_operand" "")
956                  (match_operand:DF 2 "arm_float_add_operand" "")))]
957   "TARGET_32BIT && TARGET_HARD_FLOAT"
958   "
959   if (TARGET_MAVERICK
960       && !cirrus_fp_register (operands[2], DFmode))
961     operands[2] = force_reg (DFmode, operands[2]);
962 ")
963
964 (define_expand "subdi3"
965  [(parallel
966    [(set (match_operand:DI            0 "s_register_operand" "")
967           (minus:DI (match_operand:DI 1 "s_register_operand" "")
968                     (match_operand:DI 2 "s_register_operand" "")))
969     (clobber (reg:CC CC_REGNUM))])]
970   "TARGET_EITHER"
971   "
972   if (TARGET_HARD_FLOAT && TARGET_MAVERICK
973       && TARGET_32BIT
974       && cirrus_fp_register (operands[0], DImode)
975       && cirrus_fp_register (operands[1], DImode))
976     {
977       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
978       DONE;
979     }
980
981   if (TARGET_THUMB1)
982     {
983       if (GET_CODE (operands[1]) != REG)
984         operands[1] = force_reg (DImode, operands[1]);
985       if (GET_CODE (operands[2]) != REG)
986         operands[2] = force_reg (DImode, operands[2]);
987      }  
988   "
989 )
990
991 (define_insn "*arm_subdi3"
992   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
993         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
994                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
995    (clobber (reg:CC CC_REGNUM))]
996   "TARGET_32BIT"
997   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
998   [(set_attr "conds" "clob")
999    (set_attr "length" "8")]
1000 )
1001
1002 (define_insn "*thumb_subdi3"
1003   [(set (match_operand:DI           0 "register_operand" "=l")
1004         (minus:DI (match_operand:DI 1 "register_operand"  "0")
1005                   (match_operand:DI 2 "register_operand"  "l")))
1006    (clobber (reg:CC CC_REGNUM))]
1007   "TARGET_THUMB1"
1008   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
1009   [(set_attr "length" "4")]
1010 )
1011
1012 (define_insn "*subdi_di_zesidi"
1013   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
1014         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
1015                   (zero_extend:DI
1016                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
1017    (clobber (reg:CC CC_REGNUM))]
1018   "TARGET_32BIT"
1019   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
1020   [(set_attr "conds" "clob")
1021    (set_attr "length" "8")]
1022 )
1023
1024 (define_insn "*subdi_di_sesidi"
1025   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
1026         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
1027                   (sign_extend:DI
1028                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
1029    (clobber (reg:CC CC_REGNUM))]
1030   "TARGET_32BIT"
1031   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
1032   [(set_attr "conds" "clob")
1033    (set_attr "length" "8")]
1034 )
1035
1036 (define_insn "*subdi_zesidi_di"
1037   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
1038         (minus:DI (zero_extend:DI
1039                    (match_operand:SI 2 "s_register_operand"  "r,r"))
1040                   (match_operand:DI  1 "s_register_operand" "?r,0")))
1041    (clobber (reg:CC CC_REGNUM))]
1042   "TARGET_ARM"
1043   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
1044   [(set_attr "conds" "clob")
1045    (set_attr "length" "8")]
1046 )
1047
1048 (define_insn "*subdi_sesidi_di"
1049   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
1050         (minus:DI (sign_extend:DI
1051                    (match_operand:SI 2 "s_register_operand"   "r,r"))
1052                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
1053    (clobber (reg:CC CC_REGNUM))]
1054   "TARGET_ARM"
1055   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
1056   [(set_attr "conds" "clob")
1057    (set_attr "length" "8")]
1058 )
1059
1060 (define_insn "*subdi_zesidi_zesidi"
1061   [(set (match_operand:DI            0 "s_register_operand" "=r")
1062         (minus:DI (zero_extend:DI
1063                    (match_operand:SI 1 "s_register_operand"  "r"))
1064                   (zero_extend:DI
1065                    (match_operand:SI 2 "s_register_operand"  "r"))))
1066    (clobber (reg:CC CC_REGNUM))]
1067   "TARGET_32BIT"
1068   "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
1069   [(set_attr "conds" "clob")
1070    (set_attr "length" "8")]
1071 )
1072
1073 (define_expand "subsi3"
1074   [(set (match_operand:SI           0 "s_register_operand" "")
1075         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1076                   (match_operand:SI 2 "s_register_operand" "")))]
1077   "TARGET_EITHER"
1078   "
1079   if (GET_CODE (operands[1]) == CONST_INT)
1080     {
1081       if (TARGET_32BIT)
1082         {
1083           arm_split_constant (MINUS, SImode, NULL_RTX,
1084                               INTVAL (operands[1]), operands[0],
1085                               operands[2], optimize && can_create_pseudo_p ());
1086           DONE;
1087         }
1088       else /* TARGET_THUMB1 */
1089         operands[1] = force_reg (SImode, operands[1]);
1090     }
1091   "
1092 )
1093
1094 (define_insn "*thumb1_subsi3_insn"
1095   [(set (match_operand:SI           0 "register_operand" "=l")
1096         (minus:SI (match_operand:SI 1 "register_operand" "l")
1097                   (match_operand:SI 2 "register_operand" "l")))]
1098   "TARGET_THUMB1"
1099   "sub\\t%0, %1, %2"
1100   [(set_attr "length" "2")]
1101 )
1102
1103 ; ??? Check Thumb-2 split length
1104 (define_insn_and_split "*arm_subsi3_insn"
1105   [(set (match_operand:SI           0 "s_register_operand" "=r,rk,r")
1106         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,!k,?n")
1107                   (match_operand:SI 2 "s_register_operand" "r, r, r")))]
1108   "TARGET_32BIT"
1109   "@
1110    rsb%?\\t%0, %2, %1
1111    sub%?\\t%0, %1, %2
1112    #"
1113   "TARGET_32BIT
1114    && GET_CODE (operands[1]) == CONST_INT
1115    && !const_ok_for_arm (INTVAL (operands[1]))"
1116   [(clobber (const_int 0))]
1117   "
1118   arm_split_constant (MINUS, SImode, curr_insn,
1119                       INTVAL (operands[1]), operands[0], operands[2], 0);
1120   DONE;
1121   "
1122   [(set_attr "length" "4,4,16")
1123    (set_attr "predicable" "yes")]
1124 )
1125
1126 (define_peephole2
1127   [(match_scratch:SI 3 "r")
1128    (set (match_operand:SI 0 "arm_general_register_operand" "")
1129         (minus:SI (match_operand:SI 1 "const_int_operand" "")
1130                   (match_operand:SI 2 "arm_general_register_operand" "")))]
1131   "TARGET_32BIT
1132    && !const_ok_for_arm (INTVAL (operands[1]))
1133    && const_ok_for_arm (~INTVAL (operands[1]))"
1134   [(set (match_dup 3) (match_dup 1))
1135    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1136   ""
1137 )
1138
1139 (define_insn "*subsi3_compare0"
1140   [(set (reg:CC_NOOV CC_REGNUM)
1141         (compare:CC_NOOV
1142          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1143                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1144          (const_int 0)))
1145    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1146         (minus:SI (match_dup 1) (match_dup 2)))]
1147   "TARGET_32BIT"
1148   "@
1149    sub%.\\t%0, %1, %2
1150    rsb%.\\t%0, %2, %1"
1151   [(set_attr "conds" "set")]
1152 )
1153
1154 (define_expand "decscc"
1155   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1156         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1157                   (match_operator:SI 2 "arm_comparison_operator"
1158                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1159   "TARGET_32BIT"
1160   ""
1161 )
1162
1163 (define_insn "*arm_decscc"
1164   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1165         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1166                   (match_operator:SI 2 "arm_comparison_operator"
1167                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1168   "TARGET_ARM"
1169   "@
1170    sub%d2\\t%0, %1, #1
1171    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1172   [(set_attr "conds" "use")
1173    (set_attr "length" "*,8")]
1174 )
1175
1176 (define_expand "subsf3"
1177   [(set (match_operand:SF           0 "s_register_operand" "")
1178         (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1179                   (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1180   "TARGET_32BIT && TARGET_HARD_FLOAT"
1181   "
1182   if (TARGET_MAVERICK)
1183     {
1184       if (!cirrus_fp_register (operands[1], SFmode))
1185         operands[1] = force_reg (SFmode, operands[1]);
1186       if (!cirrus_fp_register (operands[2], SFmode))
1187         operands[2] = force_reg (SFmode, operands[2]);
1188     }
1189 ")
1190
1191 (define_expand "subdf3"
1192   [(set (match_operand:DF           0 "s_register_operand" "")
1193         (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1194                   (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1195   "TARGET_32BIT && TARGET_HARD_FLOAT"
1196   "
1197   if (TARGET_MAVERICK)
1198     {
1199        if (!cirrus_fp_register (operands[1], DFmode))
1200          operands[1] = force_reg (DFmode, operands[1]);
1201        if (!cirrus_fp_register (operands[2], DFmode))
1202          operands[2] = force_reg (DFmode, operands[2]);
1203     }
1204 ")
1205
1206 \f
1207 ;; Multiplication insns
1208
1209 (define_expand "mulsi3"
1210   [(set (match_operand:SI          0 "s_register_operand" "")
1211         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1212                  (match_operand:SI 1 "s_register_operand" "")))]
1213   "TARGET_EITHER"
1214   ""
1215 )
1216
1217 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1218 (define_insn "*arm_mulsi3"
1219   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1220         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1221                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1222   "TARGET_32BIT && !arm_arch6"
1223   "mul%?\\t%0, %2, %1"
1224   [(set_attr "insn" "mul")
1225    (set_attr "predicable" "yes")]
1226 )
1227
1228 (define_insn "*arm_mulsi3_v6"
1229   [(set (match_operand:SI          0 "s_register_operand" "=r")
1230         (mult:SI (match_operand:SI 1 "s_register_operand" "r")
1231                  (match_operand:SI 2 "s_register_operand" "r")))]
1232   "TARGET_32BIT && arm_arch6"
1233   "mul%?\\t%0, %1, %2"
1234   [(set_attr "insn" "mul")
1235    (set_attr "predicable" "yes")]
1236 )
1237
1238 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1239 ; 1 and 2; are the same, because reload will make operand 0 match 
1240 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1241 ; this by adding another alternative to match this case, and then `reload' 
1242 ; it ourselves.  This alternative must come first.
1243 (define_insn "*thumb_mulsi3"
1244   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1245         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1246                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1247   "TARGET_THUMB1 && !arm_arch6"
1248   "*
1249   if (which_alternative < 2)
1250     return \"mov\\t%0, %1\;mul\\t%0, %2\";
1251   else
1252     return \"mul\\t%0, %2\";
1253   "
1254   [(set_attr "length" "4,4,2")
1255    (set_attr "insn" "mul")]
1256 )
1257
1258 (define_insn "*thumb_mulsi3_v6"
1259   [(set (match_operand:SI          0 "register_operand" "=l,l,l")
1260         (mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
1261                  (match_operand:SI 2 "register_operand" "l,0,0")))]
1262   "TARGET_THUMB1 && arm_arch6"
1263   "@
1264    mul\\t%0, %2 
1265    mul\\t%0, %1 
1266    mul\\t%0, %1"
1267   [(set_attr "length" "2")
1268    (set_attr "insn" "mul")]
1269 )
1270
1271 (define_insn "*mulsi3_compare0"
1272   [(set (reg:CC_NOOV CC_REGNUM)
1273         (compare:CC_NOOV (mult:SI
1274                           (match_operand:SI 2 "s_register_operand" "r,r")
1275                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1276                          (const_int 0)))
1277    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1278         (mult:SI (match_dup 2) (match_dup 1)))]
1279   "TARGET_ARM && !arm_arch6"
1280   "mul%.\\t%0, %2, %1"
1281   [(set_attr "conds" "set")
1282    (set_attr "insn" "muls")]
1283 )
1284
1285 (define_insn "*mulsi3_compare0_v6"
1286   [(set (reg:CC_NOOV CC_REGNUM)
1287         (compare:CC_NOOV (mult:SI
1288                           (match_operand:SI 2 "s_register_operand" "r")
1289                           (match_operand:SI 1 "s_register_operand" "r"))
1290                          (const_int 0)))
1291    (set (match_operand:SI 0 "s_register_operand" "=r")
1292         (mult:SI (match_dup 2) (match_dup 1)))]
1293   "TARGET_ARM && arm_arch6 && optimize_size"
1294   "mul%.\\t%0, %2, %1"
1295   [(set_attr "conds" "set")
1296    (set_attr "insn" "muls")]
1297 )
1298
1299 (define_insn "*mulsi_compare0_scratch"
1300   [(set (reg:CC_NOOV CC_REGNUM)
1301         (compare:CC_NOOV (mult:SI
1302                           (match_operand:SI 2 "s_register_operand" "r,r")
1303                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1304                          (const_int 0)))
1305    (clobber (match_scratch:SI 0 "=&r,&r"))]
1306   "TARGET_ARM && !arm_arch6"
1307   "mul%.\\t%0, %2, %1"
1308   [(set_attr "conds" "set")
1309    (set_attr "insn" "muls")]
1310 )
1311
1312 (define_insn "*mulsi_compare0_scratch_v6"
1313   [(set (reg:CC_NOOV CC_REGNUM)
1314         (compare:CC_NOOV (mult:SI
1315                           (match_operand:SI 2 "s_register_operand" "r")
1316                           (match_operand:SI 1 "s_register_operand" "r"))
1317                          (const_int 0)))
1318    (clobber (match_scratch:SI 0 "=r"))]
1319   "TARGET_ARM && arm_arch6 && optimize_size"
1320   "mul%.\\t%0, %2, %1"
1321   [(set_attr "conds" "set")
1322    (set_attr "insn" "muls")]
1323 )
1324
1325 ;; Unnamed templates to match MLA instruction.
1326
1327 (define_insn "*mulsi3addsi"
1328   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1329         (plus:SI
1330           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1331                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1332           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1333   "TARGET_32BIT && !arm_arch6"
1334   "mla%?\\t%0, %2, %1, %3"
1335   [(set_attr "insn" "mla")
1336    (set_attr "predicable" "yes")]
1337 )
1338
1339 (define_insn "*mulsi3addsi_v6"
1340   [(set (match_operand:SI 0 "s_register_operand" "=r")
1341         (plus:SI
1342           (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1343                    (match_operand:SI 1 "s_register_operand" "r"))
1344           (match_operand:SI 3 "s_register_operand" "r")))]
1345   "TARGET_32BIT && arm_arch6"
1346   "mla%?\\t%0, %2, %1, %3"
1347   [(set_attr "insn" "mla")
1348    (set_attr "predicable" "yes")]
1349 )
1350
1351 (define_insn "*mulsi3addsi_compare0"
1352   [(set (reg:CC_NOOV CC_REGNUM)
1353         (compare:CC_NOOV
1354          (plus:SI (mult:SI
1355                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1356                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1357                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1358          (const_int 0)))
1359    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1360         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1361                  (match_dup 3)))]
1362   "TARGET_ARM && arm_arch6"
1363   "mla%.\\t%0, %2, %1, %3"
1364   [(set_attr "conds" "set")
1365    (set_attr "insn" "mlas")]
1366 )
1367
1368 (define_insn "*mulsi3addsi_compare0_v6"
1369   [(set (reg:CC_NOOV CC_REGNUM)
1370         (compare:CC_NOOV
1371          (plus:SI (mult:SI
1372                    (match_operand:SI 2 "s_register_operand" "r")
1373                    (match_operand:SI 1 "s_register_operand" "r"))
1374                   (match_operand:SI 3 "s_register_operand" "r"))
1375          (const_int 0)))
1376    (set (match_operand:SI 0 "s_register_operand" "=r")
1377         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1378                  (match_dup 3)))]
1379   "TARGET_ARM && arm_arch6 && optimize_size"
1380   "mla%.\\t%0, %2, %1, %3"
1381   [(set_attr "conds" "set")
1382    (set_attr "insn" "mlas")]
1383 )
1384
1385 (define_insn "*mulsi3addsi_compare0_scratch"
1386   [(set (reg:CC_NOOV CC_REGNUM)
1387         (compare:CC_NOOV
1388          (plus:SI (mult:SI
1389                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1390                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1391                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1392          (const_int 0)))
1393    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1394   "TARGET_ARM && !arm_arch6"
1395   "mla%.\\t%0, %2, %1, %3"
1396   [(set_attr "conds" "set")
1397    (set_attr "insn" "mlas")]
1398 )
1399
1400 (define_insn "*mulsi3addsi_compare0_scratch_v6"
1401   [(set (reg:CC_NOOV CC_REGNUM)
1402         (compare:CC_NOOV
1403          (plus:SI (mult:SI
1404                    (match_operand:SI 2 "s_register_operand" "r")
1405                    (match_operand:SI 1 "s_register_operand" "r"))
1406                   (match_operand:SI 3 "s_register_operand" "r"))
1407          (const_int 0)))
1408    (clobber (match_scratch:SI 0 "=r"))]
1409   "TARGET_ARM && arm_arch6 && optimize_size"
1410   "mla%.\\t%0, %2, %1, %3"
1411   [(set_attr "conds" "set")
1412    (set_attr "insn" "mlas")]
1413 )
1414
1415 (define_insn "*mulsi3subsi"
1416   [(set (match_operand:SI 0 "s_register_operand" "=r")
1417         (minus:SI
1418           (match_operand:SI 3 "s_register_operand" "r")
1419           (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1420                    (match_operand:SI 1 "s_register_operand" "r"))))]
1421   "TARGET_32BIT && arm_arch_thumb2"
1422   "mls%?\\t%0, %2, %1, %3"
1423   [(set_attr "insn" "mla")
1424    (set_attr "predicable" "yes")]
1425 )
1426
1427 ;; Unnamed template to match long long multiply-accumulate (smlal)
1428
1429 (define_insn "*mulsidi3adddi"
1430   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1431         (plus:DI
1432          (mult:DI
1433           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1434           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1435          (match_operand:DI 1 "s_register_operand" "0")))]
1436   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1437   "smlal%?\\t%Q0, %R0, %3, %2"
1438   [(set_attr "insn" "smlal")
1439    (set_attr "predicable" "yes")]
1440 )
1441
1442 (define_insn "*mulsidi3adddi_v6"
1443   [(set (match_operand:DI 0 "s_register_operand" "=r")
1444         (plus:DI
1445          (mult:DI
1446           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1447           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1448          (match_operand:DI 1 "s_register_operand" "0")))]
1449   "TARGET_32BIT && arm_arch6"
1450   "smlal%?\\t%Q0, %R0, %3, %2"
1451   [(set_attr "insn" "smlal")
1452    (set_attr "predicable" "yes")]
1453 )
1454
1455 ;; 32x32->64 widening multiply.
1456 ;; As with mulsi3, the only difference between the v3-5 and v6+
1457 ;; versions of these patterns is the requirement that the output not
1458 ;; overlap the inputs, but that still means we have to have a named
1459 ;; expander and two different starred insns.
1460
1461 (define_expand "mulsidi3"
1462   [(set (match_operand:DI 0 "s_register_operand" "")
1463         (mult:DI
1464          (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1465          (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1466   "TARGET_32BIT && arm_arch3m"
1467   ""
1468 )
1469
1470 (define_insn "*mulsidi3_nov6"
1471   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1472         (mult:DI
1473          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1474          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1475   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1476   "smull%?\\t%Q0, %R0, %1, %2"
1477   [(set_attr "insn" "smull")
1478    (set_attr "predicable" "yes")]
1479 )
1480
1481 (define_insn "*mulsidi3_v6"
1482   [(set (match_operand:DI 0 "s_register_operand" "=r")
1483         (mult:DI
1484          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1485          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1486   "TARGET_32BIT && arm_arch6"
1487   "smull%?\\t%Q0, %R0, %1, %2"
1488   [(set_attr "insn" "smull")
1489    (set_attr "predicable" "yes")]
1490 )
1491
1492 (define_expand "umulsidi3"
1493   [(set (match_operand:DI 0 "s_register_operand" "")
1494         (mult:DI
1495          (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1496          (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1497   "TARGET_32BIT && arm_arch3m"
1498   ""
1499 )
1500
1501 (define_insn "*umulsidi3_nov6"
1502   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1503         (mult:DI
1504          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1505          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1506   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1507   "umull%?\\t%Q0, %R0, %1, %2"
1508   [(set_attr "insn" "umull")
1509    (set_attr "predicable" "yes")]
1510 )
1511
1512 (define_insn "*umulsidi3_v6"
1513   [(set (match_operand:DI 0 "s_register_operand" "=r")
1514         (mult:DI
1515          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1516          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1517   "TARGET_32BIT && arm_arch6"
1518   "umull%?\\t%Q0, %R0, %1, %2"
1519   [(set_attr "insn" "umull")
1520    (set_attr "predicable" "yes")]
1521 )
1522
1523 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1524
1525 (define_insn "*umulsidi3adddi"
1526   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1527         (plus:DI
1528          (mult:DI
1529           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1530           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1531          (match_operand:DI 1 "s_register_operand" "0")))]
1532   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1533   "umlal%?\\t%Q0, %R0, %3, %2"
1534   [(set_attr "insn" "umlal")
1535    (set_attr "predicable" "yes")]
1536 )
1537
1538 (define_insn "*umulsidi3adddi_v6"
1539   [(set (match_operand:DI 0 "s_register_operand" "=r")
1540         (plus:DI
1541          (mult:DI
1542           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1543           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1544          (match_operand:DI 1 "s_register_operand" "0")))]
1545   "TARGET_32BIT && arm_arch6"
1546   "umlal%?\\t%Q0, %R0, %3, %2"
1547   [(set_attr "insn" "umlal")
1548    (set_attr "predicable" "yes")]
1549 )
1550
1551 (define_expand "smulsi3_highpart"
1552   [(parallel
1553     [(set (match_operand:SI 0 "s_register_operand" "")
1554           (truncate:SI
1555            (lshiftrt:DI
1556             (mult:DI
1557              (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1558              (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1559             (const_int 32))))
1560      (clobber (match_scratch:SI 3 ""))])]
1561   "TARGET_32BIT && arm_arch3m"
1562   ""
1563 )
1564
1565 (define_insn "*smulsi3_highpart_nov6"
1566   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1567         (truncate:SI
1568          (lshiftrt:DI
1569           (mult:DI
1570            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1571            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1572           (const_int 32))))
1573    (clobber (match_scratch:SI 3 "=&r,&r"))]
1574   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1575   "smull%?\\t%3, %0, %2, %1"
1576   [(set_attr "insn" "smull")
1577    (set_attr "predicable" "yes")]
1578 )
1579
1580 (define_insn "*smulsi3_highpart_v6"
1581   [(set (match_operand:SI 0 "s_register_operand" "=r")
1582         (truncate:SI
1583          (lshiftrt:DI
1584           (mult:DI
1585            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1586            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1587           (const_int 32))))
1588    (clobber (match_scratch:SI 3 "=r"))]
1589   "TARGET_32BIT && arm_arch6"
1590   "smull%?\\t%3, %0, %2, %1"
1591   [(set_attr "insn" "smull")
1592    (set_attr "predicable" "yes")]
1593 )
1594
1595 (define_expand "umulsi3_highpart"
1596   [(parallel
1597     [(set (match_operand:SI 0 "s_register_operand" "")
1598           (truncate:SI
1599            (lshiftrt:DI
1600             (mult:DI
1601              (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1602               (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1603             (const_int 32))))
1604      (clobber (match_scratch:SI 3 ""))])]
1605   "TARGET_32BIT && arm_arch3m"
1606   ""
1607 )
1608
1609 (define_insn "*umulsi3_highpart_nov6"
1610   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1611         (truncate:SI
1612          (lshiftrt:DI
1613           (mult:DI
1614            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1615            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1616           (const_int 32))))
1617    (clobber (match_scratch:SI 3 "=&r,&r"))]
1618   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1619   "umull%?\\t%3, %0, %2, %1"
1620   [(set_attr "insn" "umull")
1621    (set_attr "predicable" "yes")]
1622 )
1623
1624 (define_insn "*umulsi3_highpart_v6"
1625   [(set (match_operand:SI 0 "s_register_operand" "=r")
1626         (truncate:SI
1627          (lshiftrt:DI
1628           (mult:DI
1629            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1630            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1631           (const_int 32))))
1632    (clobber (match_scratch:SI 3 "=r"))]
1633   "TARGET_32BIT && arm_arch6"
1634   "umull%?\\t%3, %0, %2, %1"
1635   [(set_attr "insn" "umull")
1636    (set_attr "predicable" "yes")]
1637 )
1638
1639 (define_insn "mulhisi3"
1640   [(set (match_operand:SI 0 "s_register_operand" "=r")
1641         (mult:SI (sign_extend:SI
1642                   (match_operand:HI 1 "s_register_operand" "%r"))
1643                  (sign_extend:SI
1644                   (match_operand:HI 2 "s_register_operand" "r"))))]
1645   "TARGET_DSP_MULTIPLY"
1646   "smulbb%?\\t%0, %1, %2"
1647   [(set_attr "insn" "smulxy")
1648    (set_attr "predicable" "yes")]
1649 )
1650
1651 (define_insn "*mulhisi3tb"
1652   [(set (match_operand:SI 0 "s_register_operand" "=r")
1653         (mult:SI (ashiftrt:SI
1654                   (match_operand:SI 1 "s_register_operand" "r")
1655                   (const_int 16))
1656                  (sign_extend:SI
1657                   (match_operand:HI 2 "s_register_operand" "r"))))]
1658   "TARGET_DSP_MULTIPLY"
1659   "smultb%?\\t%0, %1, %2"
1660   [(set_attr "insn" "smulxy")
1661    (set_attr "predicable" "yes")]
1662 )
1663
1664 (define_insn "*mulhisi3bt"
1665   [(set (match_operand:SI 0 "s_register_operand" "=r")
1666         (mult:SI (sign_extend:SI
1667                   (match_operand:HI 1 "s_register_operand" "r"))
1668                  (ashiftrt:SI
1669                   (match_operand:SI 2 "s_register_operand" "r")
1670                   (const_int 16))))]
1671   "TARGET_DSP_MULTIPLY"
1672   "smulbt%?\\t%0, %1, %2"
1673   [(set_attr "insn" "smulxy")
1674    (set_attr "predicable" "yes")]
1675 )
1676
1677 (define_insn "*mulhisi3tt"
1678   [(set (match_operand:SI 0 "s_register_operand" "=r")
1679         (mult:SI (ashiftrt:SI
1680                   (match_operand:SI 1 "s_register_operand" "r")
1681                   (const_int 16))
1682                  (ashiftrt:SI
1683                   (match_operand:SI 2 "s_register_operand" "r")
1684                   (const_int 16))))]
1685   "TARGET_DSP_MULTIPLY"
1686   "smultt%?\\t%0, %1, %2"
1687   [(set_attr "insn" "smulxy")
1688    (set_attr "predicable" "yes")]
1689 )
1690
1691 (define_insn "*mulhisi3addsi"
1692   [(set (match_operand:SI 0 "s_register_operand" "=r")
1693         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1694                  (mult:SI (sign_extend:SI
1695                            (match_operand:HI 2 "s_register_operand" "%r"))
1696                           (sign_extend:SI
1697                            (match_operand:HI 3 "s_register_operand" "r")))))]
1698   "TARGET_DSP_MULTIPLY"
1699   "smlabb%?\\t%0, %2, %3, %1"
1700   [(set_attr "insn" "smlaxy")
1701    (set_attr "predicable" "yes")]
1702 )
1703
1704 (define_insn "*mulhidi3adddi"
1705   [(set (match_operand:DI 0 "s_register_operand" "=r")
1706         (plus:DI
1707           (match_operand:DI 1 "s_register_operand" "0")
1708           (mult:DI (sign_extend:DI
1709                     (match_operand:HI 2 "s_register_operand" "%r"))
1710                    (sign_extend:DI
1711                     (match_operand:HI 3 "s_register_operand" "r")))))]
1712   "TARGET_DSP_MULTIPLY"
1713   "smlalbb%?\\t%Q0, %R0, %2, %3"
1714   [(set_attr "insn" "smlalxy")
1715    (set_attr "predicable" "yes")])
1716
1717 (define_expand "mulsf3"
1718   [(set (match_operand:SF          0 "s_register_operand" "")
1719         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1720                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1721   "TARGET_32BIT && TARGET_HARD_FLOAT"
1722   "
1723   if (TARGET_MAVERICK
1724       && !cirrus_fp_register (operands[2], SFmode))
1725     operands[2] = force_reg (SFmode, operands[2]);
1726 ")
1727
1728 (define_expand "muldf3"
1729   [(set (match_operand:DF          0 "s_register_operand" "")
1730         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1731                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1732   "TARGET_32BIT && TARGET_HARD_FLOAT"
1733   "
1734   if (TARGET_MAVERICK
1735       && !cirrus_fp_register (operands[2], DFmode))
1736     operands[2] = force_reg (DFmode, operands[2]);
1737 ")
1738 \f
1739 ;; Division insns
1740
1741 (define_expand "divsf3"
1742   [(set (match_operand:SF 0 "s_register_operand" "")
1743         (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1744                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1745   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1746   "")
1747
1748 (define_expand "divdf3"
1749   [(set (match_operand:DF 0 "s_register_operand" "")
1750         (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1751                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1752   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1753   "")
1754 \f
1755 ;; Modulo insns
1756
1757 (define_expand "modsf3"
1758   [(set (match_operand:SF 0 "s_register_operand" "")
1759         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1760                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1761   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
1762   "")
1763
1764 (define_expand "moddf3"
1765   [(set (match_operand:DF 0 "s_register_operand" "")
1766         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1767                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1768   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
1769   "")
1770 \f
1771 ;; Boolean and,ior,xor insns
1772
1773 ;; Split up double word logical operations
1774
1775 ;; Split up simple DImode logical operations.  Simply perform the logical
1776 ;; operation on the upper and lower halves of the registers.
1777 (define_split
1778   [(set (match_operand:DI 0 "s_register_operand" "")
1779         (match_operator:DI 6 "logical_binary_operator"
1780           [(match_operand:DI 1 "s_register_operand" "")
1781            (match_operand:DI 2 "s_register_operand" "")]))]
1782   "TARGET_32BIT && reload_completed
1783    && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1784   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1785    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1786   "
1787   {
1788     operands[3] = gen_highpart (SImode, operands[0]);
1789     operands[0] = gen_lowpart (SImode, operands[0]);
1790     operands[4] = gen_highpart (SImode, operands[1]);
1791     operands[1] = gen_lowpart (SImode, operands[1]);
1792     operands[5] = gen_highpart (SImode, operands[2]);
1793     operands[2] = gen_lowpart (SImode, operands[2]);
1794   }"
1795 )
1796
1797 (define_split
1798   [(set (match_operand:DI 0 "s_register_operand" "")
1799         (match_operator:DI 6 "logical_binary_operator"
1800           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1801            (match_operand:DI 1 "s_register_operand" "")]))]
1802   "TARGET_32BIT && reload_completed"
1803   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1804    (set (match_dup 3) (match_op_dup:SI 6
1805                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1806                          (match_dup 4)]))]
1807   "
1808   {
1809     operands[3] = gen_highpart (SImode, operands[0]);
1810     operands[0] = gen_lowpart (SImode, operands[0]);
1811     operands[4] = gen_highpart (SImode, operands[1]);
1812     operands[1] = gen_lowpart (SImode, operands[1]);
1813     operands[5] = gen_highpart (SImode, operands[2]);
1814     operands[2] = gen_lowpart (SImode, operands[2]);
1815   }"
1816 )
1817
1818 ;; The zero extend of operand 2 means we can just copy the high part of
1819 ;; operand1 into operand0.
1820 (define_split
1821   [(set (match_operand:DI 0 "s_register_operand" "")
1822         (ior:DI
1823           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1824           (match_operand:DI 1 "s_register_operand" "")))]
1825   "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
1826   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1827    (set (match_dup 3) (match_dup 4))]
1828   "
1829   {
1830     operands[4] = gen_highpart (SImode, operands[1]);
1831     operands[3] = gen_highpart (SImode, operands[0]);
1832     operands[0] = gen_lowpart (SImode, operands[0]);
1833     operands[1] = gen_lowpart (SImode, operands[1]);
1834   }"
1835 )
1836
1837 ;; The zero extend of operand 2 means we can just copy the high part of
1838 ;; operand1 into operand0.
1839 (define_split
1840   [(set (match_operand:DI 0 "s_register_operand" "")
1841         (xor:DI
1842           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1843           (match_operand:DI 1 "s_register_operand" "")))]
1844   "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
1845   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1846    (set (match_dup 3) (match_dup 4))]
1847   "
1848   {
1849     operands[4] = gen_highpart (SImode, operands[1]);
1850     operands[3] = gen_highpart (SImode, operands[0]);
1851     operands[0] = gen_lowpart (SImode, operands[0]);
1852     operands[1] = gen_lowpart (SImode, operands[1]);
1853   }"
1854 )
1855
1856 (define_insn "anddi3"
1857   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1858         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1859                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1860   "TARGET_32BIT && ! TARGET_IWMMXT"
1861   "#"
1862   [(set_attr "length" "8")]
1863 )
1864
1865 (define_insn_and_split "*anddi_zesidi_di"
1866   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1867         (and:DI (zero_extend:DI
1868                  (match_operand:SI 2 "s_register_operand" "r,r"))
1869                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1870   "TARGET_32BIT"
1871   "#"
1872   "TARGET_32BIT && reload_completed"
1873   ; The zero extend of operand 2 clears the high word of the output
1874   ; operand.
1875   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1876    (set (match_dup 3) (const_int 0))]
1877   "
1878   {
1879     operands[3] = gen_highpart (SImode, operands[0]);
1880     operands[0] = gen_lowpart (SImode, operands[0]);
1881     operands[1] = gen_lowpart (SImode, operands[1]);
1882   }"
1883   [(set_attr "length" "8")]
1884 )
1885
1886 (define_insn "*anddi_sesdi_di"
1887   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1888         (and:DI (sign_extend:DI
1889                  (match_operand:SI 2 "s_register_operand" "r,r"))
1890                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1891   "TARGET_32BIT"
1892   "#"
1893   [(set_attr "length" "8")]
1894 )
1895
1896 (define_expand "andsi3"
1897   [(set (match_operand:SI         0 "s_register_operand" "")
1898         (and:SI (match_operand:SI 1 "s_register_operand" "")
1899                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1900   "TARGET_EITHER"
1901   "
1902   if (TARGET_32BIT)
1903     {
1904       if (GET_CODE (operands[2]) == CONST_INT)
1905         {
1906           arm_split_constant (AND, SImode, NULL_RTX,
1907                               INTVAL (operands[2]), operands[0],
1908                               operands[1], optimize && can_create_pseudo_p ());
1909
1910           DONE;
1911         }
1912     }
1913   else /* TARGET_THUMB1 */
1914     {
1915       if (GET_CODE (operands[2]) != CONST_INT)
1916         operands[2] = force_reg (SImode, operands[2]);
1917       else
1918         {
1919           int i;
1920           
1921           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1922             {
1923               operands[2] = force_reg (SImode,
1924                                        GEN_INT (~INTVAL (operands[2])));
1925               
1926               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1927               
1928               DONE;
1929             }
1930
1931           for (i = 9; i <= 31; i++)
1932             {
1933               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1934                 {
1935                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1936                                         const0_rtx));
1937                   DONE;
1938                 }
1939               else if ((((HOST_WIDE_INT) 1) << i) - 1
1940                        == ~INTVAL (operands[2]))
1941                 {
1942                   rtx shift = GEN_INT (i);
1943                   rtx reg = gen_reg_rtx (SImode);
1944                 
1945                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1946                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1947                   
1948                   DONE;
1949                 }
1950             }
1951
1952           operands[2] = force_reg (SImode, operands[2]);
1953         }
1954     }
1955   "
1956 )
1957
1958 ; ??? Check split length for Thumb-2
1959 (define_insn_and_split "*arm_andsi3_insn"
1960   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1961         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1962                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1963   "TARGET_32BIT"
1964   "@
1965    and%?\\t%0, %1, %2
1966    bic%?\\t%0, %1, #%B2
1967    #"
1968   "TARGET_32BIT
1969    && GET_CODE (operands[2]) == CONST_INT
1970    && !(const_ok_for_arm (INTVAL (operands[2]))
1971         || const_ok_for_arm (~INTVAL (operands[2])))"
1972   [(clobber (const_int 0))]
1973   "
1974   arm_split_constant  (AND, SImode, curr_insn, 
1975                        INTVAL (operands[2]), operands[0], operands[1], 0);
1976   DONE;
1977   "
1978   [(set_attr "length" "4,4,16")
1979    (set_attr "predicable" "yes")]
1980 )
1981
1982 (define_insn "*thumb1_andsi3_insn"
1983   [(set (match_operand:SI         0 "register_operand" "=l")
1984         (and:SI (match_operand:SI 1 "register_operand" "%0")
1985                 (match_operand:SI 2 "register_operand" "l")))]
1986   "TARGET_THUMB1"
1987   "and\\t%0, %0, %2"
1988   [(set_attr "length" "2")]
1989 )
1990
1991 (define_insn "*andsi3_compare0"
1992   [(set (reg:CC_NOOV CC_REGNUM)
1993         (compare:CC_NOOV
1994          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1995                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1996          (const_int 0)))
1997    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1998         (and:SI (match_dup 1) (match_dup 2)))]
1999   "TARGET_32BIT"
2000   "@
2001    and%.\\t%0, %1, %2
2002    bic%.\\t%0, %1, #%B2"
2003   [(set_attr "conds" "set")]
2004 )
2005
2006 (define_insn "*andsi3_compare0_scratch"
2007   [(set (reg:CC_NOOV CC_REGNUM)
2008         (compare:CC_NOOV
2009          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
2010                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
2011          (const_int 0)))
2012    (clobber (match_scratch:SI 2 "=X,r"))]
2013   "TARGET_32BIT"
2014   "@
2015    tst%?\\t%0, %1
2016    bic%.\\t%2, %0, #%B1"
2017   [(set_attr "conds" "set")]
2018 )
2019
2020 (define_insn "*zeroextractsi_compare0_scratch"
2021   [(set (reg:CC_NOOV CC_REGNUM)
2022         (compare:CC_NOOV (zero_extract:SI
2023                           (match_operand:SI 0 "s_register_operand" "r")
2024                           (match_operand 1 "const_int_operand" "n")
2025                           (match_operand 2 "const_int_operand" "n"))
2026                          (const_int 0)))]
2027   "TARGET_32BIT
2028   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2029       && INTVAL (operands[1]) > 0 
2030       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2031       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
2032   "*
2033   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2034                          << INTVAL (operands[2]));
2035   output_asm_insn (\"tst%?\\t%0, %1\", operands);
2036   return \"\";
2037   "
2038   [(set_attr "conds" "set")]
2039 )
2040
2041 (define_insn_and_split "*ne_zeroextractsi"
2042   [(set (match_operand:SI 0 "s_register_operand" "=r")
2043         (ne:SI (zero_extract:SI
2044                 (match_operand:SI 1 "s_register_operand" "r")
2045                 (match_operand:SI 2 "const_int_operand" "n")
2046                 (match_operand:SI 3 "const_int_operand" "n"))
2047                (const_int 0)))
2048    (clobber (reg:CC CC_REGNUM))]
2049   "TARGET_32BIT
2050    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2051        && INTVAL (operands[2]) > 0 
2052        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2053        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2054   "#"
2055   "TARGET_32BIT
2056    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2057        && INTVAL (operands[2]) > 0 
2058        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2059        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2060   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2061                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2062                                     (const_int 0)))
2063               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2064    (set (match_dup 0)
2065         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2066                          (match_dup 0) (const_int 1)))]
2067   "
2068   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2069                          << INTVAL (operands[3])); 
2070   "
2071   [(set_attr "conds" "clob")
2072    (set (attr "length")
2073         (if_then_else (eq_attr "is_thumb" "yes")
2074                       (const_int 12)
2075                       (const_int 8)))]
2076 )
2077
2078 (define_insn_and_split "*ne_zeroextractsi_shifted"
2079   [(set (match_operand:SI 0 "s_register_operand" "=r")
2080         (ne:SI (zero_extract:SI
2081                 (match_operand:SI 1 "s_register_operand" "r")
2082                 (match_operand:SI 2 "const_int_operand" "n")
2083                 (const_int 0))
2084                (const_int 0)))
2085    (clobber (reg:CC CC_REGNUM))]
2086   "TARGET_ARM"
2087   "#"
2088   "TARGET_ARM"
2089   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2090                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2091                                     (const_int 0)))
2092               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2093    (set (match_dup 0)
2094         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2095                          (match_dup 0) (const_int 1)))]
2096   "
2097   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2098   "
2099   [(set_attr "conds" "clob")
2100    (set_attr "length" "8")]
2101 )
2102
2103 (define_insn_and_split "*ite_ne_zeroextractsi"
2104   [(set (match_operand:SI 0 "s_register_operand" "=r")
2105         (if_then_else:SI (ne (zero_extract:SI
2106                               (match_operand:SI 1 "s_register_operand" "r")
2107                               (match_operand:SI 2 "const_int_operand" "n")
2108                               (match_operand:SI 3 "const_int_operand" "n"))
2109                              (const_int 0))
2110                          (match_operand:SI 4 "arm_not_operand" "rIK")
2111                          (const_int 0)))
2112    (clobber (reg:CC CC_REGNUM))]
2113   "TARGET_ARM
2114    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2115        && INTVAL (operands[2]) > 0 
2116        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2117        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2118    && !reg_overlap_mentioned_p (operands[0], operands[4])"
2119   "#"
2120   "TARGET_ARM
2121    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2122        && INTVAL (operands[2]) > 0 
2123        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2124        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2125    && !reg_overlap_mentioned_p (operands[0], operands[4])"
2126   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2127                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2128                                     (const_int 0)))
2129               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2130    (set (match_dup 0)
2131         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2132                          (match_dup 0) (match_dup 4)))]
2133   "
2134   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2135                          << INTVAL (operands[3])); 
2136   "
2137   [(set_attr "conds" "clob")
2138    (set_attr "length" "8")]
2139 )
2140
2141 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2142   [(set (match_operand:SI 0 "s_register_operand" "=r")
2143         (if_then_else:SI (ne (zero_extract:SI
2144                               (match_operand:SI 1 "s_register_operand" "r")
2145                               (match_operand:SI 2 "const_int_operand" "n")
2146                               (const_int 0))
2147                              (const_int 0))
2148                          (match_operand:SI 3 "arm_not_operand" "rIK")
2149                          (const_int 0)))
2150    (clobber (reg:CC CC_REGNUM))]
2151   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2152   "#"
2153   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2154   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2155                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2156                                     (const_int 0)))
2157               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2158    (set (match_dup 0)
2159         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2160                          (match_dup 0) (match_dup 3)))]
2161   "
2162   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2163   "
2164   [(set_attr "conds" "clob")
2165    (set_attr "length" "8")]
2166 )
2167
2168 (define_split
2169   [(set (match_operand:SI 0 "s_register_operand" "")
2170         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
2171                          (match_operand:SI 2 "const_int_operand" "")
2172                          (match_operand:SI 3 "const_int_operand" "")))
2173    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2174   "TARGET_THUMB1"
2175   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
2176    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
2177   "{
2178      HOST_WIDE_INT temp = INTVAL (operands[2]);
2179
2180      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2181      operands[3] = GEN_INT (32 - temp);
2182    }"
2183 )
2184
2185 ;; ??? Use Thumb-2 has bitfield insert/extract instructions.
2186 (define_split
2187   [(set (match_operand:SI 0 "s_register_operand" "")
2188         (match_operator:SI 1 "shiftable_operator"
2189          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2190                            (match_operand:SI 3 "const_int_operand" "")
2191                            (match_operand:SI 4 "const_int_operand" ""))
2192           (match_operand:SI 5 "s_register_operand" "")]))
2193    (clobber (match_operand:SI 6 "s_register_operand" ""))]
2194   "TARGET_ARM"
2195   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2196    (set (match_dup 0)
2197         (match_op_dup 1
2198          [(lshiftrt:SI (match_dup 6) (match_dup 4))
2199           (match_dup 5)]))]
2200   "{
2201      HOST_WIDE_INT temp = INTVAL (operands[3]);
2202
2203      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2204      operands[4] = GEN_INT (32 - temp);
2205    }"
2206 )
2207   
2208 (define_split
2209   [(set (match_operand:SI 0 "s_register_operand" "")
2210         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2211                          (match_operand:SI 2 "const_int_operand" "")
2212                          (match_operand:SI 3 "const_int_operand" "")))]
2213   "TARGET_THUMB1"
2214   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2215    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2216   "{
2217      HOST_WIDE_INT temp = INTVAL (operands[2]);
2218
2219      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2220      operands[3] = GEN_INT (32 - temp);
2221    }"
2222 )
2223
2224 (define_split
2225   [(set (match_operand:SI 0 "s_register_operand" "")
2226         (match_operator:SI 1 "shiftable_operator"
2227          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2228                            (match_operand:SI 3 "const_int_operand" "")
2229                            (match_operand:SI 4 "const_int_operand" ""))
2230           (match_operand:SI 5 "s_register_operand" "")]))
2231    (clobber (match_operand:SI 6 "s_register_operand" ""))]
2232   "TARGET_ARM"
2233   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2234    (set (match_dup 0)
2235         (match_op_dup 1
2236          [(ashiftrt:SI (match_dup 6) (match_dup 4))
2237           (match_dup 5)]))]
2238   "{
2239      HOST_WIDE_INT temp = INTVAL (operands[3]);
2240
2241      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2242      operands[4] = GEN_INT (32 - temp);
2243    }"
2244 )
2245   
2246 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
2247 ;;; represented by the bitfield, then this will produce incorrect results.
2248 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
2249 ;;; which have a real bit-field insert instruction, the truncation happens
2250 ;;; in the bit-field insert instruction itself.  Since arm does not have a
2251 ;;; bit-field insert instruction, we would have to emit code here to truncate
2252 ;;; the value before we insert.  This loses some of the advantage of having
2253 ;;; this insv pattern, so this pattern needs to be reevalutated.
2254
2255 (define_expand "insv"
2256   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
2257                          (match_operand:SI 1 "general_operand" "")
2258                          (match_operand:SI 2 "general_operand" ""))
2259         (match_operand:SI 3 "reg_or_int_operand" ""))]
2260   "TARGET_ARM || arm_arch_thumb2"
2261   "
2262   {
2263     int start_bit = INTVAL (operands[2]);
2264     int width = INTVAL (operands[1]);
2265     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2266     rtx target, subtarget;
2267
2268     if (arm_arch_thumb2)
2269       {
2270         bool use_bfi = TRUE;
2271
2272         if (GET_CODE (operands[3]) == CONST_INT)
2273           {
2274             HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2275
2276             if (val == 0)
2277               {
2278                 emit_insn (gen_insv_zero (operands[0], operands[1],
2279                                           operands[2]));
2280                 DONE;
2281               }
2282
2283             /* See if the set can be done with a single orr instruction.  */
2284             if (val == mask && const_ok_for_arm (val << start_bit))
2285               use_bfi = FALSE;
2286           }
2287           
2288         if (use_bfi)
2289           {
2290             if (GET_CODE (operands[3]) != REG)
2291               operands[3] = force_reg (SImode, operands[3]);
2292
2293             emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2294                                     operands[3]));
2295             DONE;
2296           }
2297       }
2298
2299     target = copy_rtx (operands[0]);
2300     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
2301        subreg as the final target.  */
2302     if (GET_CODE (target) == SUBREG)
2303       {
2304         subtarget = gen_reg_rtx (SImode);
2305         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2306             < GET_MODE_SIZE (SImode))
2307           target = SUBREG_REG (target);
2308       }
2309     else
2310       subtarget = target;    
2311
2312     if (GET_CODE (operands[3]) == CONST_INT)
2313       {
2314         /* Since we are inserting a known constant, we may be able to
2315            reduce the number of bits that we have to clear so that
2316            the mask becomes simple.  */
2317         /* ??? This code does not check to see if the new mask is actually
2318            simpler.  It may not be.  */
2319         rtx op1 = gen_reg_rtx (SImode);
2320         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
2321            start of this pattern.  */
2322         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2323         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2324
2325         emit_insn (gen_andsi3 (op1, operands[0],
2326                                gen_int_mode (~mask2, SImode)));
2327         emit_insn (gen_iorsi3 (subtarget, op1,
2328                                gen_int_mode (op3_value << start_bit, SImode)));
2329       }
2330     else if (start_bit == 0
2331              && !(const_ok_for_arm (mask)
2332                   || const_ok_for_arm (~mask)))
2333       {
2334         /* A Trick, since we are setting the bottom bits in the word,
2335            we can shift operand[3] up, operand[0] down, OR them together
2336            and rotate the result back again.  This takes 3 insns, and
2337            the third might be mergeable into another op.  */
2338         /* The shift up copes with the possibility that operand[3] is
2339            wider than the bitfield.  */
2340         rtx op0 = gen_reg_rtx (SImode);
2341         rtx op1 = gen_reg_rtx (SImode);
2342
2343         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2344         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2345         emit_insn (gen_iorsi3  (op1, op1, op0));
2346         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2347       }
2348     else if ((width + start_bit == 32)
2349              && !(const_ok_for_arm (mask)
2350                   || const_ok_for_arm (~mask)))
2351       {
2352         /* Similar trick, but slightly less efficient.  */
2353
2354         rtx op0 = gen_reg_rtx (SImode);
2355         rtx op1 = gen_reg_rtx (SImode);
2356
2357         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2358         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2359         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2360         emit_insn (gen_iorsi3 (subtarget, op1, op0));
2361       }
2362     else
2363       {
2364         rtx op0 = gen_int_mode (mask, SImode);
2365         rtx op1 = gen_reg_rtx (SImode);
2366         rtx op2 = gen_reg_rtx (SImode);
2367
2368         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2369           {
2370             rtx tmp = gen_reg_rtx (SImode);
2371
2372             emit_insn (gen_movsi (tmp, op0));
2373             op0 = tmp;
2374           }
2375
2376         /* Mask out any bits in operand[3] that are not needed.  */
2377            emit_insn (gen_andsi3 (op1, operands[3], op0));
2378
2379         if (GET_CODE (op0) == CONST_INT
2380             && (const_ok_for_arm (mask << start_bit)
2381                 || const_ok_for_arm (~(mask << start_bit))))
2382           {
2383             op0 = gen_int_mode (~(mask << start_bit), SImode);
2384             emit_insn (gen_andsi3 (op2, operands[0], op0));
2385           }
2386         else
2387           {
2388             if (GET_CODE (op0) == CONST_INT)
2389               {
2390                 rtx tmp = gen_reg_rtx (SImode);
2391
2392                 emit_insn (gen_movsi (tmp, op0));
2393                 op0 = tmp;
2394               }
2395
2396             if (start_bit != 0)
2397               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
2398             
2399             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2400           }
2401
2402         if (start_bit != 0)
2403           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
2404
2405         emit_insn (gen_iorsi3 (subtarget, op1, op2));
2406       }
2407
2408     if (subtarget != target)
2409       {
2410         /* If TARGET is still a SUBREG, then it must be wider than a word,
2411            so we must be careful only to set the subword we were asked to.  */
2412         if (GET_CODE (target) == SUBREG)
2413           emit_move_insn (target, subtarget);
2414         else
2415           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2416       }
2417
2418     DONE;
2419   }"
2420 )
2421
2422 (define_insn "insv_zero"
2423   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2424                          (match_operand:SI 1 "const_int_operand" "M")
2425                          (match_operand:SI 2 "const_int_operand" "M"))
2426         (const_int 0))]
2427   "arm_arch_thumb2"
2428   "bfc%?\t%0, %2, %1"
2429   [(set_attr "length" "4")
2430    (set_attr "predicable" "yes")]
2431 )
2432
2433 (define_insn "insv_t2"
2434   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2435                          (match_operand:SI 1 "const_int_operand" "M")
2436                          (match_operand:SI 2 "const_int_operand" "M"))
2437         (match_operand:SI 3 "s_register_operand" "r"))]
2438   "arm_arch_thumb2"
2439   "bfi%?\t%0, %3, %2, %1"
2440   [(set_attr "length" "4")
2441    (set_attr "predicable" "yes")]
2442 )
2443
2444 ; constants for op 2 will never be given to these patterns.
2445 (define_insn_and_split "*anddi_notdi_di"
2446   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2447         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2448                 (match_operand:DI 2 "s_register_operand" "0,r")))]
2449   "TARGET_32BIT"
2450   "#"
2451   "TARGET_32BIT && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2452   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2453    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2454   "
2455   {
2456     operands[3] = gen_highpart (SImode, operands[0]);
2457     operands[0] = gen_lowpart (SImode, operands[0]);
2458     operands[4] = gen_highpart (SImode, operands[1]);
2459     operands[1] = gen_lowpart (SImode, operands[1]);
2460     operands[5] = gen_highpart (SImode, operands[2]);
2461     operands[2] = gen_lowpart (SImode, operands[2]);
2462   }"
2463   [(set_attr "length" "8")
2464    (set_attr "predicable" "yes")]
2465 )
2466   
2467 (define_insn_and_split "*anddi_notzesidi_di"
2468   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2469         (and:DI (not:DI (zero_extend:DI
2470                          (match_operand:SI 2 "s_register_operand" "r,r")))
2471                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2472   "TARGET_32BIT"
2473   "@
2474    bic%?\\t%Q0, %Q1, %2
2475    #"
2476   ; (not (zero_extend ...)) allows us to just copy the high word from
2477   ; operand1 to operand0.
2478   "TARGET_32BIT
2479    && reload_completed
2480    && operands[0] != operands[1]"
2481   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2482    (set (match_dup 3) (match_dup 4))]
2483   "
2484   {
2485     operands[3] = gen_highpart (SImode, operands[0]);
2486     operands[0] = gen_lowpart (SImode, operands[0]);
2487     operands[4] = gen_highpart (SImode, operands[1]);
2488     operands[1] = gen_lowpart (SImode, operands[1]);
2489   }"
2490   [(set_attr "length" "4,8")
2491    (set_attr "predicable" "yes")]
2492 )
2493   
2494 (define_insn_and_split "*anddi_notsesidi_di"
2495   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2496         (and:DI (not:DI (sign_extend:DI
2497                          (match_operand:SI 2 "s_register_operand" "r,r")))
2498                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2499   "TARGET_32BIT"
2500   "#"
2501   "TARGET_32BIT && reload_completed"
2502   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2503    (set (match_dup 3) (and:SI (not:SI
2504                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2505                                (match_dup 4)))]
2506   "
2507   {
2508     operands[3] = gen_highpart (SImode, operands[0]);
2509     operands[0] = gen_lowpart (SImode, operands[0]);
2510     operands[4] = gen_highpart (SImode, operands[1]);
2511     operands[1] = gen_lowpart (SImode, operands[1]);
2512   }"
2513   [(set_attr "length" "8")
2514    (set_attr "predicable" "yes")]
2515 )
2516   
2517 (define_insn "andsi_notsi_si"
2518   [(set (match_operand:SI 0 "s_register_operand" "=r")
2519         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2520                 (match_operand:SI 1 "s_register_operand" "r")))]
2521   "TARGET_32BIT"
2522   "bic%?\\t%0, %1, %2"
2523   [(set_attr "predicable" "yes")]
2524 )
2525
2526 (define_insn "bicsi3"
2527   [(set (match_operand:SI                 0 "register_operand" "=l")
2528         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2529                 (match_operand:SI         2 "register_operand" "0")))]
2530   "TARGET_THUMB1"
2531   "bic\\t%0, %0, %1"
2532   [(set_attr "length" "2")]
2533 )
2534
2535 (define_insn "andsi_not_shiftsi_si"
2536   [(set (match_operand:SI 0 "s_register_operand" "=r")
2537         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2538                          [(match_operand:SI 2 "s_register_operand" "r")
2539                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2540                 (match_operand:SI 1 "s_register_operand" "r")))]
2541   "TARGET_ARM"
2542   "bic%?\\t%0, %1, %2%S4"
2543   [(set_attr "predicable" "yes")
2544    (set_attr "shift" "2")
2545    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2546                       (const_string "alu_shift")
2547                       (const_string "alu_shift_reg")))]
2548 )
2549
2550 (define_insn "*andsi_notsi_si_compare0"
2551   [(set (reg:CC_NOOV CC_REGNUM)
2552         (compare:CC_NOOV
2553          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2554                  (match_operand:SI 1 "s_register_operand" "r"))
2555          (const_int 0)))
2556    (set (match_operand:SI 0 "s_register_operand" "=r")
2557         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2558   "TARGET_32BIT"
2559   "bic%.\\t%0, %1, %2"
2560   [(set_attr "conds" "set")]
2561 )
2562
2563 (define_insn "*andsi_notsi_si_compare0_scratch"
2564   [(set (reg:CC_NOOV CC_REGNUM)
2565         (compare:CC_NOOV
2566          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2567                  (match_operand:SI 1 "s_register_operand" "r"))
2568          (const_int 0)))
2569    (clobber (match_scratch:SI 0 "=r"))]
2570   "TARGET_32BIT"
2571   "bic%.\\t%0, %1, %2"
2572   [(set_attr "conds" "set")]
2573 )
2574
2575 (define_insn "iordi3"
2576   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2577         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2578                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2579   "TARGET_32BIT && ! TARGET_IWMMXT"
2580   "#"
2581   [(set_attr "length" "8")
2582    (set_attr "predicable" "yes")]
2583 )
2584
2585 (define_insn "*iordi_zesidi_di"
2586   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2587         (ior:DI (zero_extend:DI
2588                  (match_operand:SI 2 "s_register_operand" "r,r"))
2589                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2590   "TARGET_32BIT"
2591   "@
2592    orr%?\\t%Q0, %Q1, %2
2593    #"
2594   [(set_attr "length" "4,8")
2595    (set_attr "predicable" "yes")]
2596 )
2597
2598 (define_insn "*iordi_sesidi_di"
2599   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2600         (ior:DI (sign_extend:DI
2601                  (match_operand:SI 2 "s_register_operand" "r,r"))
2602                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2603   "TARGET_32BIT"
2604   "#"
2605   [(set_attr "length" "8")
2606    (set_attr "predicable" "yes")]
2607 )
2608
2609 (define_expand "iorsi3"
2610   [(set (match_operand:SI         0 "s_register_operand" "")
2611         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2612                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2613   "TARGET_EITHER"
2614   "
2615   if (GET_CODE (operands[2]) == CONST_INT)
2616     {
2617       if (TARGET_32BIT)
2618         {
2619           arm_split_constant (IOR, SImode, NULL_RTX,
2620                               INTVAL (operands[2]), operands[0], operands[1],
2621                               optimize && can_create_pseudo_p ());
2622           DONE;
2623         }
2624       else /* TARGET_THUMB1 */
2625         operands [2] = force_reg (SImode, operands [2]);
2626     }
2627   "
2628 )
2629
2630 (define_insn_and_split "*arm_iorsi3"
2631   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2632         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2633                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2634   "TARGET_ARM"
2635   "@
2636    orr%?\\t%0, %1, %2
2637    #"
2638   "TARGET_ARM
2639    && GET_CODE (operands[2]) == CONST_INT
2640    && !const_ok_for_arm (INTVAL (operands[2]))"
2641   [(clobber (const_int 0))]
2642   "
2643   arm_split_constant (IOR, SImode, curr_insn, 
2644                       INTVAL (operands[2]), operands[0], operands[1], 0);
2645   DONE;
2646   "
2647   [(set_attr "length" "4,16")
2648    (set_attr "predicable" "yes")]
2649 )
2650
2651 (define_insn "*thumb1_iorsi3"
2652   [(set (match_operand:SI         0 "register_operand" "=l")
2653         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2654                 (match_operand:SI 2 "register_operand" "l")))]
2655   "TARGET_THUMB1"
2656   "orr\\t%0, %0, %2"
2657   [(set_attr "length" "2")]
2658 )
2659
2660 (define_peephole2
2661   [(match_scratch:SI 3 "r")
2662    (set (match_operand:SI 0 "arm_general_register_operand" "")
2663         (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2664                 (match_operand:SI 2 "const_int_operand" "")))]
2665   "TARGET_ARM
2666    && !const_ok_for_arm (INTVAL (operands[2]))
2667    && const_ok_for_arm (~INTVAL (operands[2]))"
2668   [(set (match_dup 3) (match_dup 2))
2669    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2670   ""
2671 )
2672
2673 (define_insn "*iorsi3_compare0"
2674   [(set (reg:CC_NOOV CC_REGNUM)
2675         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2676                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2677                          (const_int 0)))
2678    (set (match_operand:SI 0 "s_register_operand" "=r")
2679         (ior:SI (match_dup 1) (match_dup 2)))]
2680   "TARGET_32BIT"
2681   "orr%.\\t%0, %1, %2"
2682   [(set_attr "conds" "set")]
2683 )
2684
2685 (define_insn "*iorsi3_compare0_scratch"
2686   [(set (reg:CC_NOOV CC_REGNUM)
2687         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2688                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2689                          (const_int 0)))
2690    (clobber (match_scratch:SI 0 "=r"))]
2691   "TARGET_32BIT"
2692   "orr%.\\t%0, %1, %2"
2693   [(set_attr "conds" "set")]
2694 )
2695
2696 (define_insn "xordi3"
2697   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2698         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2699                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2700   "TARGET_32BIT && !TARGET_IWMMXT"
2701   "#"
2702   [(set_attr "length" "8")
2703    (set_attr "predicable" "yes")]
2704 )
2705
2706 (define_insn "*xordi_zesidi_di"
2707   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2708         (xor:DI (zero_extend:DI
2709                  (match_operand:SI 2 "s_register_operand" "r,r"))
2710                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2711   "TARGET_32BIT"
2712   "@
2713    eor%?\\t%Q0, %Q1, %2
2714    #"
2715   [(set_attr "length" "4,8")
2716    (set_attr "predicable" "yes")]
2717 )
2718
2719 (define_insn "*xordi_sesidi_di"
2720   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2721         (xor:DI (sign_extend:DI
2722                  (match_operand:SI 2 "s_register_operand" "r,r"))
2723                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2724   "TARGET_32BIT"
2725   "#"
2726   [(set_attr "length" "8")
2727    (set_attr "predicable" "yes")]
2728 )
2729
2730 (define_expand "xorsi3"
2731   [(set (match_operand:SI         0 "s_register_operand" "")
2732         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2733                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2734   "TARGET_EITHER"
2735   "if (TARGET_THUMB1)
2736      if (GET_CODE (operands[2]) == CONST_INT)
2737        operands[2] = force_reg (SImode, operands[2]);
2738   "
2739 )
2740
2741 (define_insn "*arm_xorsi3"
2742   [(set (match_operand:SI         0 "s_register_operand" "=r")
2743         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2744                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2745   "TARGET_32BIT"
2746   "eor%?\\t%0, %1, %2"
2747   [(set_attr "predicable" "yes")]
2748 )
2749
2750 (define_insn "*thumb1_xorsi3"
2751   [(set (match_operand:SI         0 "register_operand" "=l")
2752         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2753                 (match_operand:SI 2 "register_operand" "l")))]
2754   "TARGET_THUMB1"
2755   "eor\\t%0, %0, %2"
2756   [(set_attr "length" "2")]
2757 )
2758
2759 (define_insn "*xorsi3_compare0"
2760   [(set (reg:CC_NOOV CC_REGNUM)
2761         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2762                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2763                          (const_int 0)))
2764    (set (match_operand:SI 0 "s_register_operand" "=r")
2765         (xor:SI (match_dup 1) (match_dup 2)))]
2766   "TARGET_32BIT"
2767   "eor%.\\t%0, %1, %2"
2768   [(set_attr "conds" "set")]
2769 )
2770
2771 (define_insn "*xorsi3_compare0_scratch"
2772   [(set (reg:CC_NOOV CC_REGNUM)
2773         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2774                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2775                          (const_int 0)))]
2776   "TARGET_32BIT"
2777   "teq%?\\t%0, %1"
2778   [(set_attr "conds" "set")]
2779 )
2780
2781 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2782 ; (NOT D) we can sometimes merge the final NOT into one of the following
2783 ; insns.
2784
2785 (define_split
2786   [(set (match_operand:SI 0 "s_register_operand" "")
2787         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2788                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2789                 (match_operand:SI 3 "arm_rhs_operand" "")))
2790    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2791   "TARGET_32BIT"
2792   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2793                               (not:SI (match_dup 3))))
2794    (set (match_dup 0) (not:SI (match_dup 4)))]
2795   ""
2796 )
2797
2798 (define_insn "*andsi_iorsi3_notsi"
2799   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2800         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2801                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2802                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2803   "TARGET_32BIT"
2804   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2805   [(set_attr "length" "8")
2806    (set_attr "ce_count" "2")
2807    (set_attr "predicable" "yes")]
2808 )
2809
2810 ; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
2811 ; insns are available?
2812 (define_split
2813   [(set (match_operand:SI 0 "s_register_operand" "")
2814         (match_operator:SI 1 "logical_binary_operator"
2815          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2816                            (match_operand:SI 3 "const_int_operand" "")
2817                            (match_operand:SI 4 "const_int_operand" ""))
2818           (match_operator:SI 9 "logical_binary_operator"
2819            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2820                          (match_operand:SI 6 "const_int_operand" ""))
2821             (match_operand:SI 7 "s_register_operand" "")])]))
2822    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2823   "TARGET_32BIT
2824    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2825    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2826   [(set (match_dup 8)
2827         (match_op_dup 1
2828          [(ashift:SI (match_dup 2) (match_dup 4))
2829           (match_dup 5)]))
2830    (set (match_dup 0)
2831         (match_op_dup 1
2832          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2833           (match_dup 7)]))]
2834   "
2835   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2836 ")
2837
2838 (define_split
2839   [(set (match_operand:SI 0 "s_register_operand" "")
2840         (match_operator:SI 1 "logical_binary_operator"
2841          [(match_operator:SI 9 "logical_binary_operator"
2842            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2843                          (match_operand:SI 6 "const_int_operand" ""))
2844             (match_operand:SI 7 "s_register_operand" "")])
2845           (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2846                            (match_operand:SI 3 "const_int_operand" "")
2847                            (match_operand:SI 4 "const_int_operand" ""))]))
2848    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2849   "TARGET_32BIT
2850    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2851    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2852   [(set (match_dup 8)
2853         (match_op_dup 1
2854          [(ashift:SI (match_dup 2) (match_dup 4))
2855           (match_dup 5)]))
2856    (set (match_dup 0)
2857         (match_op_dup 1
2858          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2859           (match_dup 7)]))]
2860   "
2861   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2862 ")
2863
2864 (define_split
2865   [(set (match_operand:SI 0 "s_register_operand" "")
2866         (match_operator:SI 1 "logical_binary_operator"
2867          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2868                            (match_operand:SI 3 "const_int_operand" "")
2869                            (match_operand:SI 4 "const_int_operand" ""))
2870           (match_operator:SI 9 "logical_binary_operator"
2871            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2872                          (match_operand:SI 6 "const_int_operand" ""))
2873             (match_operand:SI 7 "s_register_operand" "")])]))
2874    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2875   "TARGET_32BIT
2876    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2877    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2878   [(set (match_dup 8)
2879         (match_op_dup 1
2880          [(ashift:SI (match_dup 2) (match_dup 4))
2881           (match_dup 5)]))
2882    (set (match_dup 0)
2883         (match_op_dup 1
2884          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2885           (match_dup 7)]))]
2886   "
2887   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2888 ")
2889
2890 (define_split
2891   [(set (match_operand:SI 0 "s_register_operand" "")
2892         (match_operator:SI 1 "logical_binary_operator"
2893          [(match_operator:SI 9 "logical_binary_operator"
2894            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2895                          (match_operand:SI 6 "const_int_operand" ""))
2896             (match_operand:SI 7 "s_register_operand" "")])
2897           (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2898                            (match_operand:SI 3 "const_int_operand" "")
2899                            (match_operand:SI 4 "const_int_operand" ""))]))
2900    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2901   "TARGET_32BIT
2902    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2903    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2904   [(set (match_dup 8)
2905         (match_op_dup 1
2906          [(ashift:SI (match_dup 2) (match_dup 4))
2907           (match_dup 5)]))
2908    (set (match_dup 0)
2909         (match_op_dup 1
2910          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2911           (match_dup 7)]))]
2912   "
2913   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2914 ")
2915 \f
2916
2917 ;; Minimum and maximum insns
2918
2919 (define_expand "smaxsi3"
2920   [(parallel [
2921     (set (match_operand:SI 0 "s_register_operand" "")
2922          (smax:SI (match_operand:SI 1 "s_register_operand" "")
2923                   (match_operand:SI 2 "arm_rhs_operand" "")))
2924     (clobber (reg:CC CC_REGNUM))])]
2925   "TARGET_32BIT"
2926   "
2927   if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
2928     {
2929       /* No need for a clobber of the condition code register here.  */
2930       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2931                               gen_rtx_SMAX (SImode, operands[1],
2932                                             operands[2])));
2933       DONE;
2934     }
2935 ")
2936
2937 (define_insn "*smax_0"
2938   [(set (match_operand:SI 0 "s_register_operand" "=r")
2939         (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2940                  (const_int 0)))]
2941   "TARGET_32BIT"
2942   "bic%?\\t%0, %1, %1, asr #31"
2943   [(set_attr "predicable" "yes")]
2944 )
2945
2946 (define_insn "*smax_m1"
2947   [(set (match_operand:SI 0 "s_register_operand" "=r")
2948         (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2949                  (const_int -1)))]
2950   "TARGET_32BIT"
2951   "orr%?\\t%0, %1, %1, asr #31"
2952   [(set_attr "predicable" "yes")]
2953 )
2954
2955 (define_insn "*arm_smax_insn"
2956   [(set (match_operand:SI          0 "s_register_operand" "=r,r")
2957         (smax:SI (match_operand:SI 1 "s_register_operand"  "%0,?r")
2958                  (match_operand:SI 2 "arm_rhs_operand"    "rI,rI")))
2959    (clobber (reg:CC CC_REGNUM))]
2960   "TARGET_ARM"
2961   "@
2962    cmp\\t%1, %2\;movlt\\t%0, %2
2963    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2964   [(set_attr "conds" "clob")
2965    (set_attr "length" "8,12")]
2966 )
2967
2968 (define_expand "sminsi3"
2969   [(parallel [
2970     (set (match_operand:SI 0 "s_register_operand" "")
2971          (smin:SI (match_operand:SI 1 "s_register_operand" "")
2972                   (match_operand:SI 2 "arm_rhs_operand" "")))
2973     (clobber (reg:CC CC_REGNUM))])]
2974   "TARGET_32BIT"
2975   "
2976   if (operands[2] == const0_rtx)
2977     {
2978       /* No need for a clobber of the condition code register here.  */
2979       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2980                               gen_rtx_SMIN (SImode, operands[1],
2981                                             operands[2])));
2982       DONE;
2983     }
2984 ")
2985
2986 (define_insn "*smin_0"
2987   [(set (match_operand:SI 0 "s_register_operand" "=r")
2988         (smin:SI (match_operand:SI 1 "s_register_operand" "r")
2989                  (const_int 0)))]
2990   "TARGET_32BIT"
2991   "and%?\\t%0, %1, %1, asr #31"
2992   [(set_attr "predicable" "yes")]
2993 )
2994
2995 (define_insn "*arm_smin_insn"
2996   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2997         (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
2998                  (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
2999    (clobber (reg:CC CC_REGNUM))]
3000   "TARGET_ARM"
3001   "@
3002    cmp\\t%1, %2\;movge\\t%0, %2
3003    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
3004   [(set_attr "conds" "clob")
3005    (set_attr "length" "8,12")]
3006 )
3007
3008 (define_expand "umaxsi3"
3009   [(parallel [
3010     (set (match_operand:SI 0 "s_register_operand" "")
3011          (umax:SI (match_operand:SI 1 "s_register_operand" "")
3012                   (match_operand:SI 2 "arm_rhs_operand" "")))
3013     (clobber (reg:CC CC_REGNUM))])]
3014   "TARGET_32BIT"
3015   ""
3016 )
3017
3018 (define_insn "*arm_umaxsi3"
3019   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3020         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3021                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
3022    (clobber (reg:CC CC_REGNUM))]
3023   "TARGET_ARM"
3024   "@
3025    cmp\\t%1, %2\;movcc\\t%0, %2
3026    cmp\\t%1, %2\;movcs\\t%0, %1
3027    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
3028   [(set_attr "conds" "clob")
3029    (set_attr "length" "8,8,12")]
3030 )
3031
3032 (define_expand "uminsi3"
3033   [(parallel [
3034     (set (match_operand:SI 0 "s_register_operand" "")
3035          (umin:SI (match_operand:SI 1 "s_register_operand" "")
3036                   (match_operand:SI 2 "arm_rhs_operand" "")))
3037     (clobber (reg:CC CC_REGNUM))])]
3038   "TARGET_32BIT"
3039   ""
3040 )
3041
3042 (define_insn "*arm_uminsi3"
3043   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3044         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3045                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
3046    (clobber (reg:CC CC_REGNUM))]
3047   "TARGET_ARM"
3048   "@
3049    cmp\\t%1, %2\;movcs\\t%0, %2
3050    cmp\\t%1, %2\;movcc\\t%0, %1
3051    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
3052   [(set_attr "conds" "clob")
3053    (set_attr "length" "8,8,12")]
3054 )
3055
3056 (define_insn "*store_minmaxsi"
3057   [(set (match_operand:SI 0 "memory_operand" "=m")
3058         (match_operator:SI 3 "minmax_operator"
3059          [(match_operand:SI 1 "s_register_operand" "r")
3060           (match_operand:SI 2 "s_register_operand" "r")]))
3061    (clobber (reg:CC CC_REGNUM))]
3062   "TARGET_32BIT"
3063   "*
3064   operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3065                                 operands[1], operands[2]);
3066   output_asm_insn (\"cmp\\t%1, %2\", operands);
3067   if (TARGET_THUMB2)
3068     output_asm_insn (\"ite\t%d3\", operands);
3069   output_asm_insn (\"str%d3\\t%1, %0\", operands);
3070   output_asm_insn (\"str%D3\\t%2, %0\", operands);
3071   return \"\";
3072   "
3073   [(set_attr "conds" "clob")
3074    (set (attr "length")
3075         (if_then_else (eq_attr "is_thumb" "yes")
3076                       (const_int 14)
3077                       (const_int 12)))
3078    (set_attr "type" "store1")]
3079 )
3080
3081 ; Reject the frame pointer in operand[1], since reloading this after
3082 ; it has been eliminated can cause carnage.
3083 (define_insn "*minmax_arithsi"
3084   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3085         (match_operator:SI 4 "shiftable_operator"
3086          [(match_operator:SI 5 "minmax_operator"
3087            [(match_operand:SI 2 "s_register_operand" "r,r")
3088             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3089           (match_operand:SI 1 "s_register_operand" "0,?r")]))
3090    (clobber (reg:CC CC_REGNUM))]
3091   "TARGET_32BIT && !arm_eliminable_register (operands[1])"
3092   "*
3093   {
3094     enum rtx_code code = GET_CODE (operands[4]);
3095     bool need_else;
3096
3097     if (which_alternative != 0 || operands[3] != const0_rtx
3098         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
3099       need_else = true;
3100     else
3101       need_else = false;
3102
3103     operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3104                                   operands[2], operands[3]);
3105     output_asm_insn (\"cmp\\t%2, %3\", operands);
3106     if (TARGET_THUMB2)
3107       {
3108         if (need_else)
3109           output_asm_insn (\"ite\\t%d5\", operands);
3110         else
3111           output_asm_insn (\"it\\t%d5\", operands);
3112       }
3113     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
3114     if (need_else)
3115       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3116     return \"\";
3117   }"
3118   [(set_attr "conds" "clob")
3119    (set (attr "length")
3120         (if_then_else (eq_attr "is_thumb" "yes")
3121                       (const_int 14)
3122                       (const_int 12)))]
3123 )
3124
3125 \f
3126 ;; Shift and rotation insns
3127
3128 (define_expand "ashldi3"
3129   [(set (match_operand:DI            0 "s_register_operand" "")
3130         (ashift:DI (match_operand:DI 1 "s_register_operand" "")
3131                    (match_operand:SI 2 "reg_or_int_operand" "")))]
3132   "TARGET_32BIT"
3133   "
3134   if (GET_CODE (operands[2]) == CONST_INT)
3135     {
3136       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3137         {
3138           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3139           DONE;
3140         }
3141         /* Ideally we shouldn't fail here if we could know that operands[1] 
3142            ends up already living in an iwmmxt register. Otherwise it's
3143            cheaper to have the alternate code being generated than moving
3144            values to iwmmxt regs and back.  */
3145         FAIL;
3146     }
3147   else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
3148     FAIL;
3149   "
3150 )
3151
3152 (define_insn "arm_ashldi3_1bit"
3153   [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
3154         (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
3155                    (const_int 1)))
3156    (clobber (reg:CC CC_REGNUM))]
3157   "TARGET_32BIT"
3158   "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
3159   [(set_attr "conds" "clob")
3160    (set_attr "length" "8")]
3161 )
3162
3163 (define_expand "ashlsi3"
3164   [(set (match_operand:SI            0 "s_register_operand" "")
3165         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3166                    (match_operand:SI 2 "arm_rhs_operand" "")))]
3167   "TARGET_EITHER"
3168   "
3169   if (GET_CODE (operands[2]) == CONST_INT
3170       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3171     {
3172       emit_insn (gen_movsi (operands[0], const0_rtx));
3173       DONE;
3174     }
3175   "
3176 )
3177
3178 (define_insn "*thumb1_ashlsi3"
3179   [(set (match_operand:SI            0 "register_operand" "=l,l")
3180         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
3181                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
3182   "TARGET_THUMB1"
3183   "lsl\\t%0, %1, %2"
3184   [(set_attr "length" "2")]
3185 )
3186
3187 (define_expand "ashrdi3"
3188   [(set (match_operand:DI              0 "s_register_operand" "")
3189         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3190                      (match_operand:SI 2 "reg_or_int_operand" "")))]
3191   "TARGET_32BIT"
3192   "
3193   if (GET_CODE (operands[2]) == CONST_INT)
3194     {
3195       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3196         {
3197           emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3198           DONE;
3199         }
3200         /* Ideally we shouldn't fail here if we could know that operands[1] 
3201            ends up already living in an iwmmxt register. Otherwise it's
3202            cheaper to have the alternate code being generated than moving
3203            values to iwmmxt regs and back.  */
3204         FAIL;
3205     }
3206   else if (!TARGET_REALLY_IWMMXT)
3207     FAIL;
3208   "
3209 )
3210
3211 (define_insn "arm_ashrdi3_1bit"
3212   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
3213         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
3214                      (const_int 1)))
3215    (clobber (reg:CC CC_REGNUM))]
3216   "TARGET_32BIT"
3217   "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
3218   [(set_attr "conds" "clob")
3219    (set_attr "length" "8")]
3220 )
3221
3222 (define_expand "ashrsi3"
3223   [(set (match_operand:SI              0 "s_register_operand" "")
3224         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3225                      (match_operand:SI 2 "arm_rhs_operand" "")))]
3226   "TARGET_EITHER"
3227   "
3228   if (GET_CODE (operands[2]) == CONST_INT
3229       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3230     operands[2] = GEN_INT (31);
3231   "
3232 )
3233
3234 (define_insn "*thumb1_ashrsi3"
3235   [(set (match_operand:SI              0 "register_operand" "=l,l")
3236         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3237                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
3238   "TARGET_THUMB1"
3239   "asr\\t%0, %1, %2"
3240   [(set_attr "length" "2")]
3241 )
3242
3243 (define_expand "lshrdi3"
3244   [(set (match_operand:DI              0 "s_register_operand" "")
3245         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3246                      (match_operand:SI 2 "reg_or_int_operand" "")))]
3247   "TARGET_32BIT"
3248   "
3249   if (GET_CODE (operands[2]) == CONST_INT)
3250     {
3251       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3252         {
3253           emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3254           DONE;
3255         }
3256         /* Ideally we shouldn't fail here if we could know that operands[1] 
3257            ends up already living in an iwmmxt register. Otherwise it's
3258            cheaper to have the alternate code being generated than moving
3259            values to iwmmxt regs and back.  */
3260         FAIL;
3261     }
3262   else if (!TARGET_REALLY_IWMMXT)
3263     FAIL;
3264   "
3265 )
3266
3267 (define_insn "arm_lshrdi3_1bit"
3268   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
3269         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
3270                      (const_int 1)))
3271    (clobber (reg:CC CC_REGNUM))]
3272   "TARGET_32BIT"
3273   "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
3274   [(set_attr "conds" "clob")
3275    (set_attr "length" "8")]
3276 )
3277
3278 (define_expand "lshrsi3"
3279   [(set (match_operand:SI              0 "s_register_operand" "")
3280         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3281                      (match_operand:SI 2 "arm_rhs_operand" "")))]
3282   "TARGET_EITHER"
3283   "
3284   if (GET_CODE (operands[2]) == CONST_INT
3285       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3286     {
3287       emit_insn (gen_movsi (operands[0], const0_rtx));
3288       DONE;
3289     }
3290   "
3291 )
3292
3293 (define_insn "*thumb1_lshrsi3"
3294   [(set (match_operand:SI              0 "register_operand" "=l,l")
3295         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3296                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
3297   "TARGET_THUMB1"
3298   "lsr\\t%0, %1, %2"
3299   [(set_attr "length" "2")]
3300 )
3301
3302 (define_expand "rotlsi3"
3303   [(set (match_operand:SI              0 "s_register_operand" "")
3304         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3305                      (match_operand:SI 2 "reg_or_int_operand" "")))]
3306   "TARGET_32BIT"
3307   "
3308   if (GET_CODE (operands[2]) == CONST_INT)
3309     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3310   else
3311     {
3312       rtx reg = gen_reg_rtx (SImode);
3313       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3314       operands[2] = reg;
3315     }
3316   "
3317 )
3318
3319 (define_expand "rotrsi3"
3320   [(set (match_operand:SI              0 "s_register_operand" "")
3321         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3322                      (match_operand:SI 2 "arm_rhs_operand" "")))]
3323   "TARGET_EITHER"
3324   "
3325   if (TARGET_32BIT)
3326     {
3327       if (GET_CODE (operands[2]) == CONST_INT
3328           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3329         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3330     }
3331   else /* TARGET_THUMB1 */
3332     {
3333       if (GET_CODE (operands [2]) == CONST_INT)
3334         operands [2] = force_reg (SImode, operands[2]);
3335     }
3336   "
3337 )
3338
3339 (define_insn "*thumb1_rotrsi3"
3340   [(set (match_operand:SI              0 "register_operand" "=l")
3341         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
3342                      (match_operand:SI 2 "register_operand" "l")))]
3343   "TARGET_THUMB1"
3344   "ror\\t%0, %0, %2"
3345   [(set_attr "length" "2")]
3346 )
3347
3348 (define_insn "*arm_shiftsi3"
3349   [(set (match_operand:SI   0 "s_register_operand" "=r")
3350         (match_operator:SI  3 "shift_operator"
3351          [(match_operand:SI 1 "s_register_operand"  "r")
3352           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
3353   "TARGET_32BIT"
3354   "* return arm_output_shift(operands, 0);"
3355   [(set_attr "predicable" "yes")
3356    (set_attr "shift" "1")
3357    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3358                       (const_string "alu_shift")
3359                       (const_string "alu_shift_reg")))]
3360 )
3361
3362 (define_insn "*shiftsi3_compare0"
3363   [(set (reg:CC_NOOV CC_REGNUM)
3364         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3365                           [(match_operand:SI 1 "s_register_operand" "r")
3366                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
3367                          (const_int 0)))
3368    (set (match_operand:SI 0 "s_register_operand" "=r")
3369         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
3370   "TARGET_32BIT"
3371   "* return arm_output_shift(operands, 1);"
3372   [(set_attr "conds" "set")
3373    (set_attr "shift" "1")
3374    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3375                       (const_string "alu_shift")
3376                       (const_string "alu_shift_reg")))]
3377 )
3378
3379 (define_insn "*shiftsi3_compare0_scratch"
3380   [(set (reg:CC_NOOV CC_REGNUM)
3381         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3382                           [(match_operand:SI 1 "s_register_operand" "r")
3383                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
3384                          (const_int 0)))
3385    (clobber (match_scratch:SI 0 "=r"))]
3386   "TARGET_32BIT"
3387   "* return arm_output_shift(operands, 1);"
3388   [(set_attr "conds" "set")
3389    (set_attr "shift" "1")]
3390 )
3391
3392 (define_insn "*arm_notsi_shiftsi"
3393   [(set (match_operand:SI 0 "s_register_operand" "=r")
3394         (not:SI (match_operator:SI 3 "shift_operator"
3395                  [(match_operand:SI 1 "s_register_operand" "r")
3396                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
3397   "TARGET_ARM"
3398   "mvn%?\\t%0, %1%S3"
3399   [(set_attr "predicable" "yes")
3400    (set_attr "shift" "1")
3401    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3402                       (const_string "alu_shift")
3403                       (const_string "alu_shift_reg")))]
3404 )
3405
3406 (define_insn "*arm_notsi_shiftsi_compare0"
3407   [(set (reg:CC_NOOV CC_REGNUM)
3408         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
3409                           [(match_operand:SI 1 "s_register_operand" "r")
3410                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
3411                          (const_int 0)))
3412    (set (match_operand:SI 0 "s_register_operand" "=r")
3413         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
3414   "TARGET_ARM"
3415   "mvn%.\\t%0, %1%S3"
3416   [(set_attr "conds" "set")
3417    (set_attr "shift" "1")
3418    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3419                       (const_string "alu_shift")
3420                       (const_string "alu_shift_reg")))]
3421 )
3422
3423 (define_insn "*arm_not_shiftsi_compare0_scratch"
3424   [(set (reg:CC_NOOV CC_REGNUM)
3425         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
3426                           [(match_operand:SI 1 "s_register_operand" "r")
3427                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
3428                          (const_int 0)))
3429    (clobber (match_scratch:SI 0 "=r"))]
3430   "TARGET_ARM"
3431   "mvn%.\\t%0, %1%S3"
3432   [(set_attr "conds" "set")
3433    (set_attr "shift" "1")
3434    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3435                       (const_string "alu_shift")
3436                       (const_string "alu_shift_reg")))]
3437 )
3438
3439 ;; We don't really have extzv, but defining this using shifts helps
3440 ;; to reduce register pressure later on.
3441
3442 (define_expand "extzv"
3443   [(set (match_dup 4)
3444         (ashift:SI (match_operand:SI   1 "register_operand" "")
3445                    (match_operand:SI   2 "const_int_operand" "")))
3446    (set (match_operand:SI              0 "register_operand" "")
3447         (lshiftrt:SI (match_dup 4)
3448                      (match_operand:SI 3 "const_int_operand" "")))]
3449   "TARGET_THUMB1 || arm_arch_thumb2"
3450   "
3451   {
3452     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3453     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3454     
3455     if (arm_arch_thumb2)
3456       {
3457         emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
3458                                  operands[3]));
3459         DONE;
3460       }
3461
3462     operands[3] = GEN_INT (rshift);
3463     
3464     if (lshift == 0)
3465       {
3466         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3467         DONE;
3468       }
3469       
3470     operands[2] = GEN_INT (lshift);
3471     operands[4] = gen_reg_rtx (SImode);
3472   }"
3473 )
3474
3475 (define_insn "extv"
3476   [(set (match_operand:SI 0 "s_register_operand" "=r")
3477         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3478                          (match_operand:SI 2 "const_int_operand" "M")
3479                          (match_operand:SI 3 "const_int_operand" "M")))]
3480   "arm_arch_thumb2"
3481   "sbfx%?\t%0, %1, %3, %2"
3482   [(set_attr "length" "4")
3483    (set_attr "predicable" "yes")]
3484 )
3485
3486 (define_insn "extzv_t2"
3487   [(set (match_operand:SI 0 "s_register_operand" "=r")
3488         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3489                          (match_operand:SI 2 "const_int_operand" "M")
3490                          (match_operand:SI 3 "const_int_operand" "M")))]
3491   "arm_arch_thumb2"
3492   "ubfx%?\t%0, %1, %3, %2"
3493   [(set_attr "length" "4")
3494    (set_attr "predicable" "yes")]
3495 )
3496
3497 \f
3498 ;; Unary arithmetic insns
3499
3500 (define_expand "negdi2"
3501  [(parallel
3502    [(set (match_operand:DI          0 "s_register_operand" "")
3503           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
3504     (clobber (reg:CC CC_REGNUM))])]
3505   "TARGET_EITHER"
3506   "
3507   if (TARGET_THUMB1)
3508     {
3509       if (GET_CODE (operands[1]) != REG)
3510         operands[1] = force_reg (DImode, operands[1]);
3511      }
3512   "
3513 )
3514
3515 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
3516 ;; The second alternative is to allow the common case of a *full* overlap.
3517 (define_insn "*arm_negdi2"
3518   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
3519         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
3520    (clobber (reg:CC CC_REGNUM))]
3521   "TARGET_ARM"
3522   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
3523   [(set_attr "conds" "clob")
3524    (set_attr "length" "8")]
3525 )
3526
3527 (define_insn "*thumb1_negdi2"
3528   [(set (match_operand:DI         0 "register_operand" "=&l")
3529         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
3530    (clobber (reg:CC CC_REGNUM))]
3531   "TARGET_THUMB1"
3532   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
3533   [(set_attr "length" "6")]
3534 )
3535
3536 (define_expand "negsi2"
3537   [(set (match_operand:SI         0 "s_register_operand" "")
3538         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
3539   "TARGET_EITHER"
3540   ""
3541 )
3542
3543 (define_insn "*arm_negsi2"
3544   [(set (match_operand:SI         0 "s_register_operand" "=r")
3545         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
3546   "TARGET_32BIT"
3547   "rsb%?\\t%0, %1, #0"
3548   [(set_attr "predicable" "yes")]
3549 )
3550
3551 (define_insn "*thumb1_negsi2"
3552   [(set (match_operand:SI         0 "register_operand" "=l")
3553         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
3554   "TARGET_THUMB1"
3555   "neg\\t%0, %1"
3556   [(set_attr "length" "2")]
3557 )
3558
3559 (define_expand "negsf2"
3560   [(set (match_operand:SF         0 "s_register_operand" "")
3561         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
3562   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3563   ""
3564 )
3565
3566 (define_expand "negdf2"
3567   [(set (match_operand:DF         0 "s_register_operand" "")
3568         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
3569   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3570   "")
3571
3572 ;; abssi2 doesn't really clobber the condition codes if a different register
3573 ;; is being set.  To keep things simple, assume during rtl manipulations that
3574 ;; it does, but tell the final scan operator the truth.  Similarly for
3575 ;; (neg (abs...))
3576
3577 (define_expand "abssi2"
3578   [(parallel
3579     [(set (match_operand:SI         0 "s_register_operand" "")
3580           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3581      (clobber (match_dup 2))])]
3582   "TARGET_EITHER"
3583   "
3584   if (TARGET_THUMB1)
3585     operands[2] = gen_rtx_SCRATCH (SImode);
3586   else
3587     operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
3588 ")
3589
3590 (define_insn "*arm_abssi2"
3591   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3592         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3593    (clobber (reg:CC CC_REGNUM))]
3594   "TARGET_ARM"
3595   "@
3596    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3597    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3598   [(set_attr "conds" "clob,*")
3599    (set_attr "shift" "1")
3600    ;; predicable can't be set based on the variant, so left as no
3601    (set_attr "length" "8")]
3602 )
3603
3604 (define_insn_and_split "*thumb1_abssi2"
3605   [(set (match_operand:SI 0 "s_register_operand" "=l")
3606         (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
3607    (clobber (match_scratch:SI 2 "=&l"))]
3608   "TARGET_THUMB1"
3609   "#"
3610   "TARGET_THUMB1 && reload_completed"
3611   [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3612    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
3613    (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3614   ""
3615   [(set_attr "length" "6")]
3616 )
3617
3618 (define_insn "*arm_neg_abssi2"
3619   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3620         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3621    (clobber (reg:CC CC_REGNUM))]
3622   "TARGET_ARM"
3623   "@
3624    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3625    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3626   [(set_attr "conds" "clob,*")
3627    (set_attr "shift" "1")
3628    ;; predicable can't be set based on the variant, so left as no
3629    (set_attr "length" "8")]
3630 )
3631
3632 (define_insn_and_split "*thumb1_neg_abssi2"
3633   [(set (match_operand:SI 0 "s_register_operand" "=l")
3634         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
3635    (clobber (match_scratch:SI 2 "=&l"))]
3636   "TARGET_THUMB1"
3637   "#"
3638   "TARGET_THUMB1 && reload_completed"
3639   [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3640    (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
3641    (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3642   ""
3643   [(set_attr "length" "6")]
3644 )
3645
3646 (define_expand "abssf2"
3647   [(set (match_operand:SF         0 "s_register_operand" "")
3648         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3649   "TARGET_32BIT && TARGET_HARD_FLOAT"
3650   "")
3651
3652 (define_expand "absdf2"
3653   [(set (match_operand:DF         0 "s_register_operand" "")
3654         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3655   "TARGET_32BIT && TARGET_HARD_FLOAT"
3656   "")
3657
3658 (define_expand "sqrtsf2"
3659   [(set (match_operand:SF 0 "s_register_operand" "")
3660         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3661   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3662   "")
3663
3664 (define_expand "sqrtdf2"
3665   [(set (match_operand:DF 0 "s_register_operand" "")
3666         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3667   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3668   "")
3669
3670 (define_insn_and_split "one_cmpldi2"
3671   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3672         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3673   "TARGET_32BIT"
3674   "#"
3675   "TARGET_32BIT && reload_completed"
3676   [(set (match_dup 0) (not:SI (match_dup 1)))
3677    (set (match_dup 2) (not:SI (match_dup 3)))]
3678   "
3679   {
3680     operands[2] = gen_highpart (SImode, operands[0]);
3681     operands[0] = gen_lowpart (SImode, operands[0]);
3682     operands[3] = gen_highpart (SImode, operands[1]);
3683     operands[1] = gen_lowpart (SImode, operands[1]);
3684   }"
3685   [(set_attr "length" "8")
3686    (set_attr "predicable" "yes")]
3687 )
3688
3689 (define_expand "one_cmplsi2"
3690   [(set (match_operand:SI         0 "s_register_operand" "")
3691         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3692   "TARGET_EITHER"
3693   ""
3694 )
3695
3696 (define_insn "*arm_one_cmplsi2"
3697   [(set (match_operand:SI         0 "s_register_operand" "=r")
3698         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3699   "TARGET_32BIT"
3700   "mvn%?\\t%0, %1"
3701   [(set_attr "predicable" "yes")]
3702 )
3703
3704 (define_insn "*thumb1_one_cmplsi2"
3705   [(set (match_operand:SI         0 "register_operand" "=l")
3706         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3707   "TARGET_THUMB1"
3708   "mvn\\t%0, %1"
3709   [(set_attr "length" "2")]
3710 )
3711
3712 (define_insn "*notsi_compare0"
3713   [(set (reg:CC_NOOV CC_REGNUM)
3714         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3715                          (const_int 0)))
3716    (set (match_operand:SI 0 "s_register_operand" "=r")
3717         (not:SI (match_dup 1)))]
3718   "TARGET_32BIT"
3719   "mvn%.\\t%0, %1"
3720   [(set_attr "conds" "set")]
3721 )
3722
3723 (define_insn "*notsi_compare0_scratch"
3724   [(set (reg:CC_NOOV CC_REGNUM)
3725         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3726                          (const_int 0)))
3727    (clobber (match_scratch:SI 0 "=r"))]
3728   "TARGET_32BIT"
3729   "mvn%.\\t%0, %1"
3730   [(set_attr "conds" "set")]
3731 )
3732 \f
3733 ;; Fixed <--> Floating conversion insns
3734
3735 (define_expand "floatsihf2"
3736   [(set (match_operand:HF           0 "general_operand" "")
3737         (float:HF (match_operand:SI 1 "general_operand" "")))]
3738   "TARGET_EITHER"
3739   "
3740   {
3741     rtx op1 = gen_reg_rtx (SFmode);
3742     expand_float (op1, operands[1], 0);
3743     op1 = convert_to_mode (HFmode, op1, 0);
3744     emit_move_insn (operands[0], op1);
3745     DONE;
3746   }"
3747 )
3748
3749 (define_expand "floatdihf2"
3750   [(set (match_operand:HF           0 "general_operand" "")
3751         (float:HF (match_operand:DI 1 "general_operand" "")))]
3752   "TARGET_EITHER"
3753   "
3754   {
3755     rtx op1 = gen_reg_rtx (SFmode);
3756     expand_float (op1, operands[1], 0);
3757     op1 = convert_to_mode (HFmode, op1, 0);
3758     emit_move_insn (operands[0], op1);
3759     DONE;
3760   }"
3761 )
3762
3763 (define_expand "floatsisf2"
3764   [(set (match_operand:SF           0 "s_register_operand" "")
3765         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3766   "TARGET_32BIT && TARGET_HARD_FLOAT"
3767   "
3768   if (TARGET_MAVERICK)
3769     {
3770       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3771       DONE;
3772     }
3773 ")
3774
3775 (define_expand "floatsidf2"
3776   [(set (match_operand:DF           0 "s_register_operand" "")
3777         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3778   "TARGET_32BIT && TARGET_HARD_FLOAT"
3779   "
3780   if (TARGET_MAVERICK)
3781     {
3782       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3783       DONE;
3784     }
3785 ")
3786
3787 (define_expand "fix_trunchfsi2"
3788   [(set (match_operand:SI         0 "general_operand" "")
3789         (fix:SI (fix:HF (match_operand:HF 1 "general_operand"  ""))))]
3790   "TARGET_EITHER"
3791   "
3792   {
3793     rtx op1 = convert_to_mode (SFmode, operands[1], 0);
3794     expand_fix (operands[0], op1, 0);
3795     DONE;
3796   }"
3797 )
3798
3799 (define_expand "fix_trunchfdi2"
3800   [(set (match_operand:DI         0 "general_operand" "")
3801         (fix:DI (fix:HF (match_operand:HF 1 "general_operand"  ""))))]
3802   "TARGET_EITHER"
3803   "
3804   {
3805     rtx op1 = convert_to_mode (SFmode, operands[1], 0);
3806     expand_fix (operands[0], op1, 0);
3807     DONE;
3808   }"
3809 )
3810
3811 (define_expand "fix_truncsfsi2"
3812   [(set (match_operand:SI         0 "s_register_operand" "")
3813         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3814   "TARGET_32BIT && TARGET_HARD_FLOAT"
3815   "
3816   if (TARGET_MAVERICK)
3817     {
3818       if (!cirrus_fp_register (operands[0], SImode))
3819         operands[0] = force_reg (SImode, operands[0]);
3820       if (!cirrus_fp_register (operands[1], SFmode))
3821         operands[1] = force_reg (SFmode, operands[0]);
3822       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3823       DONE;
3824     }
3825 ")
3826
3827 (define_expand "fix_truncdfsi2"
3828   [(set (match_operand:SI         0 "s_register_operand" "")
3829         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3830   "TARGET_32BIT && TARGET_HARD_FLOAT"
3831   "
3832   if (TARGET_MAVERICK)
3833     {
3834       if (!cirrus_fp_register (operands[1], DFmode))
3835         operands[1] = force_reg (DFmode, operands[0]);
3836       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3837       DONE;
3838     }
3839 ")
3840
3841 ;; Truncation insns
3842
3843 (define_expand "truncdfsf2"
3844   [(set (match_operand:SF  0 "s_register_operand" "")
3845         (float_truncate:SF
3846          (match_operand:DF 1 "s_register_operand" "")))]
3847   "TARGET_32BIT && TARGET_HARD_FLOAT"
3848   ""
3849 )
3850
3851 /* DFmode -> HFmode conversions have to go through SFmode.  */
3852 (define_expand "truncdfhf2"
3853   [(set (match_operand:HF  0 "general_operand" "")
3854         (float_truncate:HF
3855          (match_operand:DF 1 "general_operand" "")))]
3856   "TARGET_EITHER"
3857   "
3858   {
3859     rtx op1;
3860     op1 = convert_to_mode (SFmode, operands[1], 0);
3861     op1 = convert_to_mode (HFmode, op1, 0);
3862     emit_move_insn (operands[0], op1);
3863     DONE;
3864   }"
3865 )
3866 \f
3867 ;; Zero and sign extension instructions.
3868
3869 (define_expand "zero_extendsidi2"
3870   [(set (match_operand:DI 0 "s_register_operand" "")
3871         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
3872   "TARGET_32BIT"
3873   ""
3874 )
3875
3876 (define_insn "*arm_zero_extendsidi2"
3877   [(set (match_operand:DI 0 "s_register_operand" "=r")
3878         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3879   "TARGET_ARM"
3880   "*
3881     if (REGNO (operands[1])
3882         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3883       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3884     return \"mov%?\\t%R0, #0\";
3885   "
3886   [(set_attr "length" "8")
3887    (set_attr "predicable" "yes")]
3888 )
3889
3890 (define_expand "zero_extendqidi2"
3891   [(set (match_operand:DI                 0 "s_register_operand"  "")
3892         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))]
3893   "TARGET_32BIT"
3894   ""
3895 )
3896
3897 (define_insn "*arm_zero_extendqidi2"
3898   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3899         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3900   "TARGET_ARM"
3901   "@
3902    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3903    ldr%(b%)\\t%Q0, %1\;mov%?\\t%R0, #0"
3904   [(set_attr "length" "8")
3905    (set_attr "predicable" "yes")
3906    (set_attr "type" "*,load_byte")
3907    (set_attr "pool_range" "*,4092")
3908    (set_attr "neg_pool_range" "*,4084")]
3909 )
3910
3911 (define_expand "extendsidi2"
3912   [(set (match_operand:DI 0 "s_register_operand" "")
3913         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
3914   "TARGET_32BIT"
3915   ""
3916 )
3917
3918 (define_insn "*arm_extendsidi2"
3919   [(set (match_operand:DI 0 "s_register_operand" "=r")
3920         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3921   "TARGET_ARM"
3922   "*
3923     if (REGNO (operands[1])
3924         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3925       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3926     return \"mov%?\\t%R0, %Q0, asr #31\";
3927   "
3928   [(set_attr "length" "8")
3929    (set_attr "shift" "1")
3930    (set_attr "predicable" "yes")]
3931 )
3932
3933 (define_expand "zero_extendhisi2"
3934   [(set (match_dup 2)
3935         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3936                    (const_int 16)))
3937    (set (match_operand:SI 0 "s_register_operand" "")
3938         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3939   "TARGET_EITHER"
3940   "
3941   {
3942     if ((TARGET_THUMB1 || arm_arch4) && GET_CODE (operands[1]) == MEM)
3943       {
3944         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3945                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3946         DONE;
3947       }
3948
3949     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3950       {
3951         emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3952         DONE;
3953       }
3954
3955     if (!s_register_operand (operands[1], HImode))
3956       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3957
3958     if (arm_arch6)
3959       {
3960         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3961                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3962         DONE;
3963       }
3964
3965     operands[1] = gen_lowpart (SImode, operands[1]);
3966     operands[2] = gen_reg_rtx (SImode);
3967   }"
3968 )
3969
3970 (define_insn "*thumb1_zero_extendhisi2"
3971   [(set (match_operand:SI 0 "register_operand" "=l")
3972         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3973   "TARGET_THUMB1 && !arm_arch6"
3974   "*
3975   rtx mem = XEXP (operands[1], 0);
3976
3977   if (GET_CODE (mem) == CONST)
3978     mem = XEXP (mem, 0);
3979     
3980   if (GET_CODE (mem) == LABEL_REF)
3981     return \"ldr\\t%0, %1\";
3982     
3983   if (GET_CODE (mem) == PLUS)
3984     {
3985       rtx a = XEXP (mem, 0);
3986       rtx b = XEXP (mem, 1);
3987
3988       /* This can happen due to bugs in reload.  */
3989       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3990         {
3991           rtx ops[2];
3992           ops[0] = operands[0];
3993           ops[1] = a;
3994       
3995           output_asm_insn (\"mov        %0, %1\", ops);
3996
3997           XEXP (mem, 0) = operands[0];
3998        }
3999
4000       else if (   GET_CODE (a) == LABEL_REF
4001                && GET_CODE (b) == CONST_INT)
4002         return \"ldr\\t%0, %1\";
4003     }
4004     
4005   return \"ldrh\\t%0, %1\";
4006   "
4007   [(set_attr "length" "4")
4008    (set_attr "type" "load_byte")
4009    (set_attr "pool_range" "60")]
4010 )
4011
4012 (define_insn "*thumb1_zero_extendhisi2_v6"
4013   [(set (match_operand:SI 0 "register_operand" "=l,l")
4014         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
4015   "TARGET_THUMB1 && arm_arch6"
4016   "*
4017   rtx mem;
4018
4019   if (which_alternative == 0)
4020     return \"uxth\\t%0, %1\";
4021
4022   mem = XEXP (operands[1], 0);
4023
4024   if (GET_CODE (mem) == CONST)
4025     mem = XEXP (mem, 0);
4026     
4027   if (GET_CODE (mem) == LABEL_REF)
4028     return \"ldr\\t%0, %1\";
4029     
4030   if (GET_CODE (mem) == PLUS)
4031     {
4032       rtx a = XEXP (mem, 0);
4033       rtx b = XEXP (mem, 1);
4034
4035       /* This can happen due to bugs in reload.  */
4036       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
4037         {
4038           rtx ops[2];
4039           ops[0] = operands[0];
4040           ops[1] = a;
4041       
4042           output_asm_insn (\"mov        %0, %1\", ops);
4043
4044           XEXP (mem, 0) = operands[0];
4045        }
4046
4047       else if (   GET_CODE (a) == LABEL_REF
4048                && GET_CODE (b) == CONST_INT)
4049         return \"ldr\\t%0, %1\";
4050     }
4051     
4052   return \"ldrh\\t%0, %1\";
4053   "
4054   [(set_attr "length" "2,4")
4055    (set_attr "type" "alu_shift,load_byte")
4056    (set_attr "pool_range" "*,60")]
4057 )
4058
4059 (define_insn "*arm_zero_extendhisi2"
4060   [(set (match_operand:SI 0 "s_register_operand" "=r")
4061         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
4062   "TARGET_ARM && arm_arch4 && !arm_arch6"
4063   "ldr%(h%)\\t%0, %1"
4064   [(set_attr "type" "load_byte")
4065    (set_attr "predicable" "yes")
4066    (set_attr "pool_range" "256")
4067    (set_attr "neg_pool_range" "244")]
4068 )
4069
4070 (define_insn "*arm_zero_extendhisi2_v6"
4071   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4072         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4073   "TARGET_ARM && arm_arch6"
4074   "@
4075    uxth%?\\t%0, %1
4076    ldr%(h%)\\t%0, %1"
4077   [(set_attr "type" "alu_shift,load_byte")
4078    (set_attr "predicable" "yes")
4079    (set_attr "pool_range" "*,256")
4080    (set_attr "neg_pool_range" "*,244")]
4081 )
4082
4083 (define_insn "*arm_zero_extendhisi2addsi"
4084   [(set (match_operand:SI 0 "s_register_operand" "=r")
4085         (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4086                  (match_operand:SI 2 "s_register_operand" "r")))]
4087   "TARGET_INT_SIMD"
4088   "uxtah%?\\t%0, %2, %1"
4089   [(set_attr "type" "alu_shift")
4090    (set_attr "predicable" "yes")]
4091 )
4092
4093 (define_expand "zero_extendqisi2"
4094   [(set (match_operand:SI 0 "s_register_operand" "")
4095         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
4096   "TARGET_EITHER"
4097   "
4098   if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
4099     {
4100       if (TARGET_ARM)
4101         {
4102           emit_insn (gen_andsi3 (operands[0],
4103                                  gen_lowpart (SImode, operands[1]),
4104                                  GEN_INT (255)));
4105         }
4106       else /* TARGET_THUMB */
4107         {
4108           rtx temp = gen_reg_rtx (SImode);
4109           rtx ops[3];
4110           
4111           operands[1] = copy_to_mode_reg (QImode, operands[1]);
4112           operands[1] = gen_lowpart (SImode, operands[1]);
4113
4114           ops[0] = temp;
4115           ops[1] = operands[1];
4116           ops[2] = GEN_INT (24);
4117
4118           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
4119                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
4120           
4121           ops[0] = operands[0];
4122           ops[1] = temp;
4123           ops[2] = GEN_INT (24);
4124
4125           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
4126                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
4127         }
4128       DONE;
4129     }
4130   "
4131 )
4132
4133 (define_insn "*thumb1_zero_extendqisi2"
4134   [(set (match_operand:SI 0 "register_operand" "=l")
4135         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
4136   "TARGET_THUMB1 && !arm_arch6"
4137   "ldrb\\t%0, %1"
4138   [(set_attr "length" "2")
4139    (set_attr "type" "load_byte")
4140    (set_attr "pool_range" "32")]
4141 )
4142
4143 (define_insn "*thumb1_zero_extendqisi2_v6"
4144   [(set (match_operand:SI 0 "register_operand" "=l,l")
4145         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
4146   "TARGET_THUMB1 && arm_arch6"
4147   "@
4148    uxtb\\t%0, %1
4149    ldrb\\t%0, %1"
4150   [(set_attr "length" "2,2")
4151    (set_attr "type" "alu_shift,load_byte")
4152    (set_attr "pool_range" "*,32")]
4153 )
4154
4155 (define_insn "*arm_zero_extendqisi2"
4156   [(set (match_operand:SI 0 "s_register_operand" "=r")
4157         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
4158   "TARGET_ARM && !arm_arch6"
4159   "ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
4160   [(set_attr "type" "load_byte")
4161    (set_attr "predicable" "yes")
4162    (set_attr "pool_range" "4096")
4163    (set_attr "neg_pool_range" "4084")]
4164 )
4165
4166 (define_insn "*arm_zero_extendqisi2_v6"
4167   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4168         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4169   "TARGET_ARM && arm_arch6"
4170   "@
4171    uxtb%(%)\\t%0, %1
4172    ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
4173   [(set_attr "type" "alu_shift,load_byte")
4174    (set_attr "predicable" "yes")
4175    (set_attr "pool_range" "*,4096")
4176    (set_attr "neg_pool_range" "*,4084")]
4177 )
4178
4179 (define_insn "*arm_zero_extendqisi2addsi"
4180   [(set (match_operand:SI 0 "s_register_operand" "=r")
4181         (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4182                  (match_operand:SI 2 "s_register_operand" "r")))]
4183   "TARGET_INT_SIMD"
4184   "uxtab%?\\t%0, %2, %1"
4185   [(set_attr "predicable" "yes")
4186    (set_attr "insn" "xtab")
4187    (set_attr "type" "alu_shift")]
4188 )
4189
4190 (define_split
4191   [(set (match_operand:SI 0 "s_register_operand" "")
4192         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
4193    (clobber (match_operand:SI 2 "s_register_operand" ""))]
4194   "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
4195   [(set (match_dup 2) (match_dup 1))
4196    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4197   ""
4198 )
4199
4200 (define_split
4201   [(set (match_operand:SI 0 "s_register_operand" "")
4202         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
4203    (clobber (match_operand:SI 2 "s_register_operand" ""))]
4204   "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
4205   [(set (match_dup 2) (match_dup 1))
4206    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4207   ""
4208 )
4209
4210 (define_code_iterator ior_xor [ior xor])
4211
4212 (define_split
4213   [(set (match_operand:SI 0 "s_register_operand" "")
4214         (ior_xor:SI (and:SI (ashift:SI
4215                              (match_operand:SI 1 "s_register_operand" "")
4216                              (match_operand:SI 2 "const_int_operand" ""))
4217                             (match_operand:SI 3 "const_int_operand" ""))
4218                     (zero_extend:SI
4219                      (match_operator 5 "subreg_lowpart_operator"
4220                       [(match_operand:SI 4 "s_register_operand" "")]))))]
4221   "TARGET_32BIT
4222    && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
4223        == (GET_MODE_MASK (GET_MODE (operands[5]))
4224            & (GET_MODE_MASK (GET_MODE (operands[5]))
4225               << (INTVAL (operands[2])))))"
4226   [(set (match_dup 0) (ior_xor:SI (ashift:SI (match_dup 1) (match_dup 2))
4227                                   (match_dup 4)))
4228    (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
4229   "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
4230 )
4231
4232 (define_insn "*compareqi_eq0"
4233   [(set (reg:CC_Z CC_REGNUM)
4234         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
4235                          (const_int 0)))]
4236   "TARGET_32BIT"
4237   "tst\\t%0, #255"
4238   [(set_attr "conds" "set")]
4239 )
4240
4241 (define_expand "extendhisi2"
4242   [(set (match_dup 2)
4243         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
4244                    (const_int 16)))
4245    (set (match_operand:SI 0 "s_register_operand" "")
4246         (ashiftrt:SI (match_dup 2)
4247                      (const_int 16)))]
4248   "TARGET_EITHER"
4249   "
4250   {
4251     if (GET_CODE (operands[1]) == MEM)
4252       {
4253         if (TARGET_THUMB1)
4254           {
4255             emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
4256             DONE;
4257           }
4258         else if (arm_arch4)
4259           {
4260             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4261                        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4262             DONE;
4263           }
4264       }
4265
4266     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
4267       {
4268         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
4269         DONE;
4270       }
4271
4272     if (!s_register_operand (operands[1], HImode))
4273       operands[1] = copy_to_mode_reg (HImode, operands[1]);
4274
4275     if (arm_arch6)
4276       {
4277         if (TARGET_THUMB1)
4278           emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
4279         else
4280           emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4281                      gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4282
4283         DONE;
4284       }
4285
4286     operands[1] = gen_lowpart (SImode, operands[1]);
4287     operands[2] = gen_reg_rtx (SImode);
4288   }"
4289 )
4290
4291 (define_insn "thumb1_extendhisi2"
4292   [(set (match_operand:SI 0 "register_operand" "=l")
4293         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
4294    (clobber (match_scratch:SI 2 "=&l"))]
4295   "TARGET_THUMB1 && !arm_arch6"
4296   "*
4297   {
4298     rtx ops[4];
4299     rtx mem = XEXP (operands[1], 0);
4300
4301     /* This code used to try to use 'V', and fix the address only if it was
4302        offsettable, but this fails for e.g. REG+48 because 48 is outside the
4303        range of QImode offsets, and offsettable_address_p does a QImode
4304        address check.  */
4305        
4306     if (GET_CODE (mem) == CONST)
4307       mem = XEXP (mem, 0);
4308     
4309     if (GET_CODE (mem) == LABEL_REF)
4310       return \"ldr\\t%0, %1\";
4311     
4312     if (GET_CODE (mem) == PLUS)
4313       {
4314         rtx a = XEXP (mem, 0);
4315         rtx b = XEXP (mem, 1);
4316
4317         if (GET_CODE (a) == LABEL_REF
4318             && GET_CODE (b) == CONST_INT)
4319           return \"ldr\\t%0, %1\";
4320
4321         if (GET_CODE (b) == REG)
4322           return \"ldrsh\\t%0, %1\";
4323           
4324         ops[1] = a;
4325         ops[2] = b;
4326       }
4327     else
4328       {
4329         ops[1] = mem;
4330         ops[2] = const0_rtx;
4331       }
4332
4333     gcc_assert (GET_CODE (ops[1]) == REG);
4334
4335     ops[0] = operands[0];
4336     ops[3] = operands[2];
4337     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4338     return \"\";
4339   }"
4340   [(set_attr "length" "4")
4341    (set_attr "type" "load_byte")
4342    (set_attr "pool_range" "1020")]
4343 )
4344
4345 ;; We used to have an early-clobber on the scratch register here.
4346 ;; However, there's a bug somewhere in reload which means that this
4347 ;; can be partially ignored during spill allocation if the memory
4348 ;; address also needs reloading; this causes us to die later on when
4349 ;; we try to verify the operands.  Fortunately, we don't really need
4350 ;; the early-clobber: we can always use operand 0 if operand 2
4351 ;; overlaps the address.
4352 (define_insn "*thumb1_extendhisi2_insn_v6"
4353   [(set (match_operand:SI 0 "register_operand" "=l,l")
4354         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
4355    (clobber (match_scratch:SI 2 "=X,l"))]
4356   "TARGET_THUMB1 && arm_arch6"
4357   "*
4358   {
4359     rtx ops[4];
4360     rtx mem;
4361
4362     if (which_alternative == 0)
4363       return \"sxth\\t%0, %1\";
4364
4365     mem = XEXP (operands[1], 0);
4366
4367     /* This code used to try to use 'V', and fix the address only if it was
4368        offsettable, but this fails for e.g. REG+48 because 48 is outside the
4369        range of QImode offsets, and offsettable_address_p does a QImode
4370        address check.  */
4371        
4372     if (GET_CODE (mem) == CONST)
4373       mem = XEXP (mem, 0);
4374     
4375     if (GET_CODE (mem) == LABEL_REF)
4376       return \"ldr\\t%0, %1\";
4377     
4378     if (GET_CODE (mem) == PLUS)
4379       {
4380         rtx a = XEXP (mem, 0);
4381         rtx b = XEXP (mem, 1);
4382
4383         if (GET_CODE (a) == LABEL_REF
4384             && GET_CODE (b) == CONST_INT)
4385           return \"ldr\\t%0, %1\";
4386
4387         if (GET_CODE (b) == REG)
4388           return \"ldrsh\\t%0, %1\";
4389           
4390         ops[1] = a;
4391         ops[2] = b;
4392       }
4393     else
4394       {
4395         ops[1] = mem;
4396         ops[2] = const0_rtx;
4397       }
4398       
4399     gcc_assert (GET_CODE (ops[1]) == REG);
4400
4401     ops[0] = operands[0];
4402     if (reg_mentioned_p (operands[2], ops[1]))
4403       ops[3] = ops[0];
4404     else
4405       ops[3] = operands[2];
4406     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4407     return \"\";
4408   }"
4409   [(set_attr "length" "2,4")
4410    (set_attr "type" "alu_shift,load_byte")
4411    (set_attr "pool_range" "*,1020")]
4412 )
4413
4414 ;; This pattern will only be used when ldsh is not available
4415 (define_expand "extendhisi2_mem"
4416   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4417    (set (match_dup 3)
4418         (zero_extend:SI (match_dup 7)))
4419    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4420    (set (match_operand:SI 0 "" "")
4421         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
4422   "TARGET_ARM"
4423   "
4424   {
4425     rtx mem1, mem2;
4426     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4427
4428     mem1 = change_address (operands[1], QImode, addr);
4429     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
4430     operands[0] = gen_lowpart (SImode, operands[0]);
4431     operands[1] = mem1;
4432     operands[2] = gen_reg_rtx (SImode);
4433     operands[3] = gen_reg_rtx (SImode);
4434     operands[6] = gen_reg_rtx (SImode);
4435     operands[7] = mem2;
4436
4437     if (BYTES_BIG_ENDIAN)
4438       {
4439         operands[4] = operands[2];
4440         operands[5] = operands[3];
4441       }
4442     else
4443       {
4444         operands[4] = operands[3];
4445         operands[5] = operands[2];
4446       }
4447   }"
4448 )
4449
4450 (define_insn "*arm_extendhisi2"
4451   [(set (match_operand:SI 0 "s_register_operand" "=r")
4452         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
4453   "TARGET_ARM && arm_arch4 && !arm_arch6"
4454   "ldr%(sh%)\\t%0, %1"
4455   [(set_attr "type" "load_byte")
4456    (set_attr "predicable" "yes")
4457    (set_attr "pool_range" "256")
4458    (set_attr "neg_pool_range" "244")]
4459 )
4460
4461 ;; ??? Check Thumb-2 pool range
4462 (define_insn "*arm_extendhisi2_v6"
4463   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4464         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4465   "TARGET_32BIT && arm_arch6"
4466   "@
4467    sxth%?\\t%0, %1
4468    ldr%(sh%)\\t%0, %1"
4469   [(set_attr "type" "alu_shift,load_byte")
4470    (set_attr "predicable" "yes")
4471    (set_attr "pool_range" "*,256")
4472    (set_attr "neg_pool_range" "*,244")]
4473 )
4474
4475 (define_insn "*arm_extendhisi2addsi"
4476   [(set (match_operand:SI 0 "s_register_operand" "=r")
4477         (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4478                  (match_operand:SI 2 "s_register_operand" "r")))]
4479   "TARGET_INT_SIMD"
4480   "sxtah%?\\t%0, %2, %1"
4481 )
4482
4483 (define_expand "extendqihi2"
4484   [(set (match_dup 2)
4485         (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
4486                    (const_int 24)))
4487    (set (match_operand:HI 0 "s_register_operand" "")
4488         (ashiftrt:SI (match_dup 2)
4489                      (const_int 24)))]
4490   "TARGET_ARM"
4491   "
4492   {
4493     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
4494       {
4495         emit_insn (gen_rtx_SET (VOIDmode,
4496                                 operands[0],
4497                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
4498         DONE;
4499       }
4500     if (!s_register_operand (operands[1], QImode))
4501       operands[1] = copy_to_mode_reg (QImode, operands[1]);
4502     operands[0] = gen_lowpart (SImode, operands[0]);
4503     operands[1] = gen_lowpart (SImode, operands[1]);
4504     operands[2] = gen_reg_rtx (SImode);
4505   }"
4506 )
4507
4508 (define_insn "*arm_extendqihi_insn"
4509   [(set (match_operand:HI 0 "s_register_operand" "=r")
4510         (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
4511   "TARGET_ARM && arm_arch4"
4512   "ldr%(sb%)\\t%0, %1"
4513   [(set_attr "type" "load_byte")
4514    (set_attr "predicable" "yes")
4515    (set_attr "pool_range" "256")
4516    (set_attr "neg_pool_range" "244")]
4517 )
4518
4519 (define_expand "extendqisi2"
4520   [(set (match_dup 2)
4521         (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
4522                    (const_int 24)))
4523    (set (match_operand:SI 0 "s_register_operand" "")
4524         (ashiftrt:SI (match_dup 2)
4525                      (const_int 24)))]
4526   "TARGET_EITHER"
4527   "
4528   {
4529     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
4530       {
4531         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4532                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4533         DONE;
4534       }
4535
4536     if (!s_register_operand (operands[1], QImode))
4537       operands[1] = copy_to_mode_reg (QImode, operands[1]);
4538
4539     if (arm_arch6)
4540       {
4541         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
4542                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4543         DONE;
4544       }
4545
4546     operands[1] = gen_lowpart (SImode, operands[1]);
4547     operands[2] = gen_reg_rtx (SImode);
4548   }"
4549 )
4550
4551 (define_insn "*arm_extendqisi"
4552   [(set (match_operand:SI 0 "s_register_operand" "=r")
4553         (sign_extend:SI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
4554   "TARGET_ARM && arm_arch4 && !arm_arch6"
4555   "ldr%(sb%)\\t%0, %1"
4556   [(set_attr "type" "load_byte")
4557    (set_attr "predicable" "yes")
4558    (set_attr "pool_range" "256")
4559    (set_attr "neg_pool_range" "244")]
4560 )
4561
4562 (define_insn "*arm_extendqisi_v6"
4563   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4564         (sign_extend:SI
4565          (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
4566   "TARGET_ARM && arm_arch6"
4567   "@
4568    sxtb%?\\t%0, %1
4569    ldr%(sb%)\\t%0, %1"
4570   [(set_attr "type" "alu_shift,load_byte")
4571    (set_attr "predicable" "yes")
4572    (set_attr "pool_range" "*,256")
4573    (set_attr "neg_pool_range" "*,244")]
4574 )
4575
4576 (define_insn "*arm_extendqisi2addsi"
4577   [(set (match_operand:SI 0 "s_register_operand" "=r")
4578         (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4579                  (match_operand:SI 2 "s_register_operand" "r")))]
4580   "TARGET_INT_SIMD"
4581   "sxtab%?\\t%0, %2, %1"
4582   [(set_attr "type" "alu_shift")
4583    (set_attr "insn" "xtab")
4584    (set_attr "predicable" "yes")]
4585 )
4586
4587 (define_insn "*thumb1_extendqisi2"
4588   [(set (match_operand:SI 0 "register_operand" "=l,l")
4589         (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
4590   "TARGET_THUMB1 && !arm_arch6"
4591   "*
4592   {
4593     rtx ops[3];
4594     rtx mem = XEXP (operands[1], 0);
4595     
4596     if (GET_CODE (mem) == CONST)
4597       mem = XEXP (mem, 0);
4598     
4599     if (GET_CODE (mem) == LABEL_REF)
4600       return \"ldr\\t%0, %1\";
4601
4602     if (GET_CODE (mem) == PLUS
4603         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4604       return \"ldr\\t%0, %1\";
4605       
4606     if (which_alternative == 0)
4607       return \"ldrsb\\t%0, %1\";
4608       
4609     ops[0] = operands[0];
4610     
4611     if (GET_CODE (mem) == PLUS)
4612       {
4613         rtx a = XEXP (mem, 0);
4614         rtx b = XEXP (mem, 1);
4615         
4616         ops[1] = a;
4617         ops[2] = b;
4618
4619         if (GET_CODE (a) == REG)
4620           {
4621             if (GET_CODE (b) == REG)
4622               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4623             else if (REGNO (a) == REGNO (ops[0]))
4624               {
4625                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4626                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4627                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4628               }
4629             else
4630               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4631           }
4632         else
4633           {
4634             gcc_assert (GET_CODE (b) == REG);
4635             if (REGNO (b) == REGNO (ops[0]))
4636               {
4637                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4638                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4639                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4640               }
4641             else
4642               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4643           }
4644       }
4645     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4646       {
4647         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4648         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4649         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4650       }
4651     else
4652       {
4653         ops[1] = mem;
4654         ops[2] = const0_rtx;
4655         
4656         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4657       }
4658     return \"\";
4659   }"
4660   [(set_attr "length" "2,6")
4661    (set_attr "type" "load_byte,load_byte")
4662    (set_attr "pool_range" "32,32")]
4663 )
4664
4665 (define_insn "*thumb1_extendqisi2_v6"
4666   [(set (match_operand:SI 0 "register_operand" "=l,l,l")
4667         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
4668   "TARGET_THUMB1 && arm_arch6"
4669   "*
4670   {
4671     rtx ops[3];
4672     rtx mem;
4673
4674     if (which_alternative == 0)
4675       return \"sxtb\\t%0, %1\";
4676
4677     mem = XEXP (operands[1], 0);
4678     
4679     if (GET_CODE (mem) == CONST)
4680       mem = XEXP (mem, 0);
4681     
4682     if (GET_CODE (mem) == LABEL_REF)
4683       return \"ldr\\t%0, %1\";
4684
4685     if (GET_CODE (mem) == PLUS
4686         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4687       return \"ldr\\t%0, %1\";
4688       
4689     if (which_alternative == 0)
4690       return \"ldrsb\\t%0, %1\";
4691       
4692     ops[0] = operands[0];
4693     
4694     if (GET_CODE (mem) == PLUS)
4695       {
4696         rtx a = XEXP (mem, 0);
4697         rtx b = XEXP (mem, 1);
4698         
4699         ops[1] = a;
4700         ops[2] = b;
4701
4702         if (GET_CODE (a) == REG)
4703           {
4704             if (GET_CODE (b) == REG)
4705               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4706             else if (REGNO (a) == REGNO (ops[0]))
4707               {
4708                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4709                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4710               }
4711             else
4712               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4713           }
4714         else
4715           {
4716             gcc_assert (GET_CODE (b) == REG);
4717             if (REGNO (b) == REGNO (ops[0]))
4718               {
4719                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4720                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4721               }
4722             else
4723               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4724           }
4725       }
4726     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4727       {
4728         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4729         output_asm_insn (\"sxtb\\t%0, %0\", ops);
4730       }
4731     else
4732       {
4733         ops[1] = mem;
4734         ops[2] = const0_rtx;
4735         
4736         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4737       }
4738     return \"\";
4739   }"
4740   [(set_attr "length" "2,2,4")
4741    (set_attr "type" "alu_shift,load_byte,load_byte")
4742    (set_attr "pool_range" "*,32,32")]
4743 )
4744
4745 (define_expand "extendsfdf2"
4746   [(set (match_operand:DF                  0 "s_register_operand" "")
4747         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
4748   "TARGET_32BIT && TARGET_HARD_FLOAT"
4749   ""
4750 )
4751
4752 /* HFmode -> DFmode conversions have to go through SFmode.  */
4753 (define_expand "extendhfdf2"
4754   [(set (match_operand:DF                  0 "general_operand" "")
4755         (float_extend:DF (match_operand:HF 1 "general_operand"  "")))]
4756   "TARGET_EITHER"
4757   "
4758   {
4759     rtx op1;
4760     op1 = convert_to_mode (SFmode, operands[1], 0);
4761     op1 = convert_to_mode (DFmode, op1, 0);
4762     emit_insn (gen_movdf (operands[0], op1));
4763     DONE;
4764   }"
4765 )
4766 \f
4767 ;; Move insns (including loads and stores)
4768
4769 ;; XXX Just some ideas about movti.
4770 ;; I don't think these are a good idea on the arm, there just aren't enough
4771 ;; registers
4772 ;;(define_expand "loadti"
4773 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
4774 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
4775 ;;  "" "")
4776
4777 ;;(define_expand "storeti"
4778 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4779 ;;      (match_operand:TI 1 "s_register_operand" ""))]
4780 ;;  "" "")
4781
4782 ;;(define_expand "movti"
4783 ;;  [(set (match_operand:TI 0 "general_operand" "")
4784 ;;      (match_operand:TI 1 "general_operand" ""))]
4785 ;;  ""
4786 ;;  "
4787 ;;{
4788 ;;  rtx insn;
4789 ;;
4790 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4791 ;;    operands[1] = copy_to_reg (operands[1]);
4792 ;;  if (GET_CODE (operands[0]) == MEM)
4793 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4794 ;;  else if (GET_CODE (operands[1]) == MEM)
4795 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4796 ;;  else
4797 ;;    FAIL;
4798 ;;
4799 ;;  emit_insn (insn);
4800 ;;  DONE;
4801 ;;}")
4802
4803 ;; Recognize garbage generated above.
4804
4805 ;;(define_insn ""
4806 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4807 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4808 ;;  ""
4809 ;;  "*
4810 ;;  {
4811 ;;    register mem = (which_alternative < 3);
4812 ;;    register const char *template;
4813 ;;
4814 ;;    operands[mem] = XEXP (operands[mem], 0);
4815 ;;    switch (which_alternative)
4816 ;;      {
4817 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4818 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
4819 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
4820 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
4821 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
4822 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
4823 ;;      }
4824 ;;    output_asm_insn (template, operands);
4825 ;;    return \"\";
4826 ;;  }")
4827
4828 (define_expand "movdi"
4829   [(set (match_operand:DI 0 "general_operand" "")
4830         (match_operand:DI 1 "general_operand" ""))]
4831   "TARGET_EITHER"
4832   "
4833   if (can_create_pseudo_p ())
4834     {
4835       if (GET_CODE (operands[0]) != REG)
4836         operands[1] = force_reg (DImode, operands[1]);
4837     }
4838   "
4839 )
4840
4841 (define_insn "*arm_movdi"
4842   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4843         (match_operand:DI 1 "di_operand"              "rDa,Db,Dc,mi,r"))]
4844   "TARGET_ARM
4845    && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4846    && !TARGET_IWMMXT
4847    && (   register_operand (operands[0], DImode)
4848        || register_operand (operands[1], DImode))"
4849   "*
4850   switch (which_alternative)
4851     {
4852     case 0:
4853     case 1:
4854     case 2:
4855       return \"#\";
4856     default:
4857       return output_move_double (operands);
4858     }
4859   "
4860   [(set_attr "length" "8,12,16,8,8")
4861    (set_attr "type" "*,*,*,load2,store2")
4862    (set_attr "pool_range" "*,*,*,1020,*")
4863    (set_attr "neg_pool_range" "*,*,*,1008,*")]
4864 )
4865
4866 (define_split
4867   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4868         (match_operand:ANY64 1 "const_double_operand" ""))]
4869   "TARGET_32BIT
4870    && reload_completed
4871    && (arm_const_double_inline_cost (operands[1])
4872        <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4873   [(const_int 0)]
4874   "
4875   arm_split_constant (SET, SImode, curr_insn,
4876                       INTVAL (gen_lowpart (SImode, operands[1])),
4877                       gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4878   arm_split_constant (SET, SImode, curr_insn,
4879                       INTVAL (gen_highpart_mode (SImode,
4880                                                  GET_MODE (operands[0]),
4881                                                  operands[1])),
4882                       gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4883   DONE;
4884   "
4885 )
4886
4887 ; If optimizing for size, or if we have load delay slots, then 
4888 ; we want to split the constant into two separate operations. 
4889 ; In both cases this may split a trivial part into a single data op
4890 ; leaving a single complex constant to load.  We can also get longer
4891 ; offsets in a LDR which means we get better chances of sharing the pool
4892 ; entries.  Finally, we can normally do a better job of scheduling
4893 ; LDR instructions than we can with LDM.
4894 ; This pattern will only match if the one above did not.
4895 (define_split
4896   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4897         (match_operand:ANY64 1 "const_double_operand" ""))]
4898   "TARGET_ARM && reload_completed
4899    && arm_const_double_by_parts (operands[1])"
4900   [(set (match_dup 0) (match_dup 1))
4901    (set (match_dup 2) (match_dup 3))]
4902   "
4903   operands[2] = gen_highpart (SImode, operands[0]);
4904   operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4905                                    operands[1]);
4906   operands[0] = gen_lowpart (SImode, operands[0]);
4907   operands[1] = gen_lowpart (SImode, operands[1]);
4908   "
4909 )
4910
4911 (define_split
4912   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4913         (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4914   "TARGET_EITHER && reload_completed"
4915   [(set (match_dup 0) (match_dup 1))
4916    (set (match_dup 2) (match_dup 3))]
4917   "
4918   operands[2] = gen_highpart (SImode, operands[0]);
4919   operands[3] = gen_highpart (SImode, operands[1]);
4920   operands[0] = gen_lowpart (SImode, operands[0]);
4921   operands[1] = gen_lowpart (SImode, operands[1]);
4922
4923   /* Handle a partial overlap.  */
4924   if (rtx_equal_p (operands[0], operands[3]))
4925     {
4926       rtx tmp0 = operands[0];
4927       rtx tmp1 = operands[1];
4928
4929       operands[0] = operands[2];
4930       operands[1] = operands[3];
4931       operands[2] = tmp0;
4932       operands[3] = tmp1;
4933     }
4934   "
4935 )
4936
4937 ;; We can't actually do base+index doubleword loads if the index and
4938 ;; destination overlap.  Split here so that we at least have chance to
4939 ;; schedule.
4940 (define_split
4941   [(set (match_operand:DI 0 "s_register_operand" "")
4942         (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4943                          (match_operand:SI 2 "s_register_operand" ""))))]
4944   "TARGET_LDRD
4945   && reg_overlap_mentioned_p (operands[0], operands[1])
4946   && reg_overlap_mentioned_p (operands[0], operands[2])"
4947   [(set (match_dup 4)
4948         (plus:SI (match_dup 1)
4949                  (match_dup 2)))
4950    (set (match_dup 0)
4951         (mem:DI (match_dup 4)))]
4952   "
4953   operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4954   "
4955 )
4956
4957 ;;; ??? This should have alternatives for constants.
4958 ;;; ??? This was originally identical to the movdf_insn pattern.
4959 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4960 ;;; thumb_reorg with a memory reference.
4961 (define_insn "*thumb1_movdi_insn"
4962   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4963         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
4964   "TARGET_THUMB1
4965    && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4966    && (   register_operand (operands[0], DImode)
4967        || register_operand (operands[1], DImode))"
4968   "*
4969   {
4970   switch (which_alternative)
4971     {
4972     default:
4973     case 0:
4974       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4975         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
4976       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
4977     case 1:
4978       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4979     case 2:
4980       operands[1] = GEN_INT (- INTVAL (operands[1]));
4981       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4982     case 3:
4983       return \"ldmia\\t%1, {%0, %H0}\";
4984     case 4:
4985       return \"stmia\\t%0, {%1, %H1}\";
4986     case 5:
4987       return thumb_load_double_from_address (operands);
4988     case 6:
4989       operands[2] = gen_rtx_MEM (SImode,
4990                              plus_constant (XEXP (operands[0], 0), 4));
4991       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4992       return \"\";
4993     case 7:
4994       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4995         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4996       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4997     }
4998   }"
4999   [(set_attr "length" "4,4,6,2,2,6,4,4")
5000    (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
5001    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
5002 )
5003
5004 (define_expand "movsi"
5005   [(set (match_operand:SI 0 "general_operand" "")
5006         (match_operand:SI 1 "general_operand" ""))]
5007   "TARGET_EITHER"
5008   "
5009   {
5010   rtx base, offset, tmp;
5011
5012   if (TARGET_32BIT)
5013     {
5014       /* Everything except mem = const or mem = mem can be done easily.  */
5015       if (GET_CODE (operands[0]) == MEM)
5016         operands[1] = force_reg (SImode, operands[1]);
5017       if (arm_general_register_operand (operands[0], SImode)
5018           && GET_CODE (operands[1]) == CONST_INT
5019           && !(const_ok_for_arm (INTVAL (operands[1]))
5020                || const_ok_for_arm (~INTVAL (operands[1]))))
5021         {
5022            arm_split_constant (SET, SImode, NULL_RTX,
5023                                INTVAL (operands[1]), operands[0], NULL_RTX,
5024                                optimize && can_create_pseudo_p ());
5025           DONE;
5026         }
5027
5028       if (TARGET_USE_MOVT && !target_word_relocations
5029           && GET_CODE (operands[1]) == SYMBOL_REF
5030           && !flag_pic && !arm_tls_referenced_p (operands[1]))
5031         {
5032           arm_emit_movpair (operands[0], operands[1]);
5033           DONE;
5034         }
5035     }
5036   else /* TARGET_THUMB1...  */
5037     {
5038       if (can_create_pseudo_p ())
5039         {
5040           if (GET_CODE (operands[0]) != REG)
5041             operands[1] = force_reg (SImode, operands[1]);
5042         }
5043     }
5044
5045   if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
5046     {
5047       split_const (operands[1], &base, &offset);
5048       if (GET_CODE (base) == SYMBOL_REF
5049           && !offset_within_block_p (base, INTVAL (offset)))
5050         {
5051           tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5052           emit_move_insn (tmp, base);
5053           emit_insn (gen_addsi3 (operands[0], tmp, offset));
5054           DONE;
5055         }
5056     }
5057
5058   /* Recognize the case where operand[1] is a reference to thread-local
5059      data and load its address to a register.  */
5060   if (arm_tls_referenced_p (operands[1]))
5061     {
5062       rtx tmp = operands[1];
5063       rtx addend = NULL;
5064
5065       if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
5066         {
5067           addend = XEXP (XEXP (tmp, 0), 1);
5068           tmp = XEXP (XEXP (tmp, 0), 0);
5069         }
5070
5071       gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
5072       gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
5073
5074       tmp = legitimize_tls_address (tmp,
5075                                     !can_create_pseudo_p () ? operands[0] : 0);
5076       if (addend)
5077         {
5078           tmp = gen_rtx_PLUS (SImode, tmp, addend);
5079           tmp = force_operand (tmp, operands[0]);
5080         }
5081       operands[1] = tmp;
5082     }
5083   else if (flag_pic
5084            && (CONSTANT_P (operands[1])
5085                || symbol_mentioned_p (operands[1])
5086                || label_mentioned_p (operands[1])))
5087       operands[1] = legitimize_pic_address (operands[1], SImode,
5088                                             (!can_create_pseudo_p ()
5089                                              ? operands[0]
5090                                              : 0));
5091   }
5092   "
5093 )
5094
5095 ;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5096 ;; LO_SUM adds in the high bits.  Fortunately these are opaque operations
5097 ;; so this does not matter.
5098 (define_insn "*arm_movt"
5099   [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5100         (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5101                    (match_operand:SI 2 "general_operand"      "i")))]
5102   "TARGET_32BIT"
5103   "movt%?\t%0, #:upper16:%c2"
5104   [(set_attr "predicable" "yes")
5105    (set_attr "length" "4")]
5106 )
5107
5108 (define_insn "*arm_movsi_insn"
5109   [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
5110         (match_operand:SI 1 "general_operand"      "rk, I,K,j,mi,rk"))]
5111   "TARGET_ARM && ! TARGET_IWMMXT
5112    && !(TARGET_HARD_FLOAT && TARGET_VFP)
5113    && (   register_operand (operands[0], SImode)
5114        || register_operand (operands[1], SImode))"
5115   "@
5116    mov%?\\t%0, %1
5117    mov%?\\t%0, %1
5118    mvn%?\\t%0, #%B1
5119    movw%?\\t%0, %1
5120    ldr%?\\t%0, %1
5121    str%?\\t%1, %0"
5122   [(set_attr "type" "*,*,*,*,load1,store1")
5123    (set_attr "predicable" "yes")
5124    (set_attr "pool_range" "*,*,*,*,4096,*")
5125    (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
5126 )
5127
5128 (define_split
5129   [(set (match_operand:SI 0 "arm_general_register_operand" "")
5130         (match_operand:SI 1 "const_int_operand" ""))]
5131   "TARGET_32BIT
5132   && (!(const_ok_for_arm (INTVAL (operands[1]))
5133         || const_ok_for_arm (~INTVAL (operands[1]))))"
5134   [(clobber (const_int 0))]
5135   "
5136   arm_split_constant (SET, SImode, NULL_RTX, 
5137                       INTVAL (operands[1]), operands[0], NULL_RTX, 0);
5138   DONE;
5139   "
5140 )
5141
5142 (define_insn "*thumb1_movsi_insn"
5143   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lhk")
5144         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lhk"))]
5145   "TARGET_THUMB1
5146    && (   register_operand (operands[0], SImode) 
5147        || register_operand (operands[1], SImode))"
5148   "@
5149    mov  %0, %1
5150    mov  %0, %1
5151    #
5152    #
5153    ldmia\\t%1, {%0}
5154    stmia\\t%0, {%1}
5155    ldr\\t%0, %1
5156    str\\t%1, %0
5157    mov\\t%0, %1"
5158   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
5159    (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
5160    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
5161 )
5162
5163 (define_split 
5164   [(set (match_operand:SI 0 "register_operand" "")
5165         (match_operand:SI 1 "const_int_operand" ""))]
5166   "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
5167   [(set (match_dup 0) (match_dup 1))
5168    (set (match_dup 0) (neg:SI (match_dup 0)))]
5169   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
5170 )
5171
5172 (define_split 
5173   [(set (match_operand:SI 0 "register_operand" "")
5174         (match_operand:SI 1 "const_int_operand" ""))]
5175   "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
5176   [(set (match_dup 0) (match_dup 1))
5177    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
5178   "
5179   {
5180     unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu;
5181     unsigned HOST_WIDE_INT mask = 0xff;
5182     int i;
5183     
5184     for (i = 0; i < 25; i++)
5185       if ((val & (mask << i)) == val)
5186         break;
5187
5188     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
5189     if (i == 0)
5190       FAIL;
5191
5192     operands[1] = GEN_INT (val >> i);
5193     operands[2] = GEN_INT (i);
5194   }"
5195 )
5196
5197 ;; When generating pic, we need to load the symbol offset into a register.
5198 ;; So that the optimizer does not confuse this with a normal symbol load
5199 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
5200 ;; since that is the only type of relocation we can use.
5201
5202 ;; The rather odd constraints on the following are to force reload to leave
5203 ;; the insn alone, and to force the minipool generation pass to then move
5204 ;; the GOT symbol to memory.
5205
5206 (define_insn "pic_load_addr_arm"
5207   [(set (match_operand:SI 0 "s_register_operand" "=r")
5208         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
5209   "TARGET_ARM && flag_pic"
5210   "ldr%?\\t%0, %1"
5211   [(set_attr "type" "load1")
5212    (set (attr "pool_range")     (const_int 4096))
5213    (set (attr "neg_pool_range") (const_int 4084))]
5214 )
5215
5216 (define_insn "pic_load_addr_thumb1"
5217   [(set (match_operand:SI 0 "s_register_operand" "=l")
5218         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
5219   "TARGET_THUMB1 && flag_pic"
5220   "ldr\\t%0, %1"
5221   [(set_attr "type" "load1")
5222    (set (attr "pool_range") (const_int 1024))]
5223 )
5224
5225 (define_insn "pic_add_dot_plus_four"
5226   [(set (match_operand:SI 0 "register_operand" "=r")
5227         (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5228                     (const_int 4)
5229                     (match_operand 2 "" "")]
5230                    UNSPEC_PIC_BASE))]
5231   "TARGET_THUMB1"
5232   "*
5233   (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5234                                      INTVAL (operands[2]));
5235   return \"add\\t%0, %|pc\";
5236   "
5237   [(set_attr "length" "2")]
5238 )
5239
5240 (define_insn "pic_add_dot_plus_eight"
5241   [(set (match_operand:SI 0 "register_operand" "=r")
5242         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5243                     (const_int 8)
5244                     (match_operand 2 "" "")]
5245                    UNSPEC_PIC_BASE))]
5246   "TARGET_ARM"
5247   "*
5248     (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5249                                        INTVAL (operands[2]));
5250     return \"add%?\\t%0, %|pc, %1\";
5251   "
5252   [(set_attr "predicable" "yes")]
5253 )
5254
5255 (define_insn "tls_load_dot_plus_eight"
5256   [(set (match_operand:SI 0 "register_operand" "+r")
5257         (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5258                             (const_int 8)
5259                             (match_operand 2 "" "")]
5260                            UNSPEC_PIC_BASE)))]
5261   "TARGET_ARM"
5262   "*
5263     (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5264                                        INTVAL (operands[2]));
5265     return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5266   "
5267   [(set_attr "predicable" "yes")]
5268 )
5269
5270 ;; PIC references to local variables can generate pic_add_dot_plus_eight
5271 ;; followed by a load.  These sequences can be crunched down to
5272 ;; tls_load_dot_plus_eight by a peephole.
5273
5274 (define_peephole2
5275   [(set (match_operand:SI 0 "register_operand" "")
5276         (unspec:SI [(match_operand:SI 3 "register_operand" "")
5277                     (const_int 8)
5278                     (match_operand 1 "" "")]
5279                    UNSPEC_PIC_BASE))
5280    (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
5281   "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
5282   [(set (match_dup 2)
5283         (mem:SI (unspec:SI [(match_dup 3)
5284                             (const_int 8)
5285                             (match_dup 1)]
5286                            UNSPEC_PIC_BASE)))]
5287   ""
5288 )
5289
5290 (define_insn "pic_offset_arm"
5291   [(set (match_operand:SI 0 "register_operand" "=r")
5292         (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5293                          (unspec:SI [(match_operand:SI 2 "" "X")]
5294                                     UNSPEC_PIC_OFFSET))))]
5295   "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5296   "ldr%?\\t%0, [%1,%2]"
5297   [(set_attr "type" "load1")]
5298 )
5299
5300 (define_expand "builtin_setjmp_receiver"
5301   [(label_ref (match_operand 0 "" ""))]
5302   "flag_pic"
5303   "
5304 {
5305   /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5306      register.  */
5307   if (arm_pic_register != INVALID_REGNUM)
5308     arm_load_pic_register (1UL << 3);
5309   DONE;
5310 }")
5311
5312 ;; If copying one reg to another we can set the condition codes according to
5313 ;; its value.  Such a move is common after a return from subroutine and the
5314 ;; result is being tested against zero.
5315
5316 (define_insn "*movsi_compare0"
5317   [(set (reg:CC CC_REGNUM)
5318         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5319                     (const_int 0)))
5320    (set (match_operand:SI 0 "s_register_operand" "=r,r")
5321         (match_dup 1))]
5322   "TARGET_32BIT"
5323   "@
5324    cmp%?\\t%0, #0
5325    sub%.\\t%0, %1, #0"
5326   [(set_attr "conds" "set")]
5327 )
5328
5329 ;; Subroutine to store a half word from a register into memory.
5330 ;; Operand 0 is the source register (HImode)
5331 ;; Operand 1 is the destination address in a register (SImode)
5332
5333 ;; In both this routine and the next, we must be careful not to spill
5334 ;; a memory address of reg+large_const into a separate PLUS insn, since this
5335 ;; can generate unrecognizable rtl.
5336
5337 (define_expand "storehi"
5338   [;; store the low byte
5339    (set (match_operand 1 "" "") (match_dup 3))
5340    ;; extract the high byte
5341    (set (match_dup 2)
5342         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
5343    ;; store the high byte
5344    (set (match_dup 4) (match_dup 5))]
5345   "TARGET_ARM"
5346   "
5347   {
5348     rtx op1 = operands[1];
5349     rtx addr = XEXP (op1, 0);
5350     enum rtx_code code = GET_CODE (addr);
5351
5352     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5353         || code == MINUS)
5354       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
5355
5356     operands[4] = adjust_address (op1, QImode, 1);
5357     operands[1] = adjust_address (operands[1], QImode, 0);
5358     operands[3] = gen_lowpart (QImode, operands[0]);
5359     operands[0] = gen_lowpart (SImode, operands[0]);
5360     operands[2] = gen_reg_rtx (SImode);
5361     operands[5] = gen_lowpart (QImode, operands[2]);
5362   }"
5363 )
5364
5365 (define_expand "storehi_bigend"
5366   [(set (match_dup 4) (match_dup 3))
5367    (set (match_dup 2)
5368         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
5369    (set (match_operand 1 "" "") (match_dup 5))]
5370   "TARGET_ARM"
5371   "
5372   {
5373     rtx op1 = operands[1];
5374     rtx addr = XEXP (op1, 0);
5375     enum rtx_code code = GET_CODE (addr);
5376
5377     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5378         || code == MINUS)
5379       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
5380
5381     operands[4] = adjust_address (op1, QImode, 1);
5382     operands[1] = adjust_address (operands[1], QImode, 0);
5383     operands[3] = gen_lowpart (QImode, operands[0]);
5384     operands[0] = gen_lowpart (SImode, operands[0]);
5385     operands[2] = gen_reg_rtx (SImode);
5386     operands[5] = gen_lowpart (QImode, operands[2]);
5387   }"
5388 )
5389
5390 ;; Subroutine to store a half word integer constant into memory.
5391 (define_expand "storeinthi"
5392   [(set (match_operand 0 "" "")
5393         (match_operand 1 "" ""))
5394    (set (match_dup 3) (match_dup 2))]
5395   "TARGET_ARM"
5396   "
5397   {
5398     HOST_WIDE_INT value = INTVAL (operands[1]);
5399     rtx addr = XEXP (operands[0], 0);
5400     rtx op0 = operands[0];
5401     enum rtx_code code = GET_CODE (addr);
5402
5403     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5404         || code == MINUS)
5405       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
5406
5407     operands[1] = gen_reg_rtx (SImode);
5408     if (BYTES_BIG_ENDIAN)
5409       {
5410         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5411         if ((value & 255) == ((value >> 8) & 255))
5412           operands[2] = operands[1];
5413         else
5414           {
5415             operands[2] = gen_reg_rtx (SImode);
5416             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5417           }
5418       }
5419     else
5420       {
5421         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5422         if ((value & 255) == ((value >> 8) & 255))
5423           operands[2] = operands[1];
5424         else
5425           {
5426             operands[2] = gen_reg_rtx (SImode);
5427             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5428           }
5429       }
5430
5431     operands[3] = adjust_address (op0, QImode, 1);
5432     operands[0] = adjust_address (operands[0], QImode, 0);
5433     operands[2] = gen_lowpart (QImode, operands[2]);
5434     operands[1] = gen_lowpart (QImode, operands[1]);
5435   }"
5436 )
5437
5438 (define_expand "storehi_single_op"
5439   [(set (match_operand:HI 0 "memory_operand" "")
5440         (match_operand:HI 1 "general_operand" ""))]
5441   "TARGET_32BIT && arm_arch4"
5442   "
5443   if (!s_register_operand (operands[1], HImode))
5444     operands[1] = copy_to_mode_reg (HImode, operands[1]);
5445   "
5446 )
5447
5448 (define_expand "movhi"
5449   [(set (match_operand:HI 0 "general_operand" "")
5450         (match_operand:HI 1 "general_operand" ""))]
5451   "TARGET_EITHER"
5452   "
5453   if (TARGET_ARM)
5454     {
5455       if (can_create_pseudo_p ())
5456         {
5457           if (GET_CODE (operands[0]) == MEM)
5458             {
5459               if (arm_arch4)
5460                 {
5461                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5462                   DONE;
5463                 }
5464               if (GET_CODE (operands[1]) == CONST_INT)
5465                 emit_insn (gen_storeinthi (operands[0], operands[1]));
5466               else
5467                 {
5468                   if (GET_CODE (operands[1]) == MEM)
5469                     operands[1] = force_reg (HImode, operands[1]);
5470                   if (BYTES_BIG_ENDIAN)
5471                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
5472                   else
5473                    emit_insn (gen_storehi (operands[1], operands[0]));
5474                 }
5475               DONE;
5476             }
5477           /* Sign extend a constant, and keep it in an SImode reg.  */
5478           else if (GET_CODE (operands[1]) == CONST_INT)
5479             {
5480               rtx reg = gen_reg_rtx (SImode);
5481               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5482
5483               /* If the constant is already valid, leave it alone.  */
5484               if (!const_ok_for_arm (val))
5485                 {
5486                   /* If setting all the top bits will make the constant 
5487                      loadable in a single instruction, then set them.  
5488                      Otherwise, sign extend the number.  */
5489
5490                   if (const_ok_for_arm (~(val | ~0xffff)))
5491                     val |= ~0xffff;
5492                   else if (val & 0x8000)
5493                     val |= ~0xffff;
5494                 }
5495
5496               emit_insn (gen_movsi (reg, GEN_INT (val)));
5497               operands[1] = gen_lowpart (HImode, reg);
5498             }
5499           else if (arm_arch4 && optimize && can_create_pseudo_p ()
5500                    && GET_CODE (operands[1]) == MEM)
5501             {
5502               rtx reg = gen_reg_rtx (SImode);
5503
5504               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5505               operands[1] = gen_lowpart (HImode, reg);
5506             }
5507           else if (!arm_arch4)
5508             {
5509               if (GET_CODE (operands[1]) == MEM)
5510                 {
5511                   rtx base;
5512                   rtx offset = const0_rtx;
5513                   rtx reg = gen_reg_rtx (SImode);
5514
5515                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
5516                        || (GET_CODE (base) == PLUS
5517                            && (GET_CODE (offset = XEXP (base, 1))
5518                                == CONST_INT)
5519                            && ((INTVAL(offset) & 1) != 1)
5520                            && GET_CODE (base = XEXP (base, 0)) == REG))
5521                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
5522                     {
5523                       rtx new_rtx;
5524
5525                       new_rtx = widen_memory_access (operands[1], SImode,
5526                                                      ((INTVAL (offset) & ~3)
5527                                                       - INTVAL (offset)));
5528                       emit_insn (gen_movsi (reg, new_rtx));
5529                       if (((INTVAL (offset) & 2) != 0)
5530                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
5531                         {
5532                           rtx reg2 = gen_reg_rtx (SImode);
5533
5534                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
5535                           reg = reg2;
5536                         }
5537                     }
5538                   else
5539                     emit_insn (gen_movhi_bytes (reg, operands[1]));
5540
5541                   operands[1] = gen_lowpart (HImode, reg);
5542                }
5543            }
5544         }
5545       /* Handle loading a large integer during reload.  */
5546       else if (GET_CODE (operands[1]) == CONST_INT
5547                && !const_ok_for_arm (INTVAL (operands[1]))
5548                && !const_ok_for_arm (~INTVAL (operands[1])))
5549         {
5550           /* Writing a constant to memory needs a scratch, which should
5551              be handled with SECONDARY_RELOADs.  */
5552           gcc_assert (GET_CODE (operands[0]) == REG);
5553
5554           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5555           emit_insn (gen_movsi (operands[0], operands[1]));
5556           DONE;
5557        }
5558     }
5559   else if (TARGET_THUMB2)
5560     {
5561       /* Thumb-2 can do everything except mem=mem and mem=const easily.  */
5562       if (can_create_pseudo_p ())
5563         {
5564           if (GET_CODE (operands[0]) != REG)
5565             operands[1] = force_reg (HImode, operands[1]);
5566           /* Zero extend a constant, and keep it in an SImode reg.  */
5567           else if (GET_CODE (operands[1]) == CONST_INT)
5568             {
5569               rtx reg = gen_reg_rtx (SImode);
5570               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5571
5572               emit_insn (gen_movsi (reg, GEN_INT (val)));
5573               operands[1] = gen_lowpart (HImode, reg);
5574             }
5575         }
5576     }
5577   else /* TARGET_THUMB1 */
5578     {
5579       if (can_create_pseudo_p ())
5580         {
5581           if (GET_CODE (operands[1]) == CONST_INT)
5582             {
5583               rtx reg = gen_reg_rtx (SImode);
5584
5585               emit_insn (gen_movsi (reg, operands[1]));
5586               operands[1] = gen_lowpart (HImode, reg);
5587             }
5588
5589           /* ??? We shouldn't really get invalid addresses here, but this can
5590              happen if we are passed a SP (never OK for HImode/QImode) or 
5591              virtual register (also rejected as illegitimate for HImode/QImode)
5592              relative address.  */
5593           /* ??? This should perhaps be fixed elsewhere, for instance, in
5594              fixup_stack_1, by checking for other kinds of invalid addresses,
5595              e.g. a bare reference to a virtual register.  This may confuse the
5596              alpha though, which must handle this case differently.  */
5597           if (GET_CODE (operands[0]) == MEM
5598               && !memory_address_p (GET_MODE (operands[0]),
5599                                     XEXP (operands[0], 0)))
5600             operands[0]
5601               = replace_equiv_address (operands[0],
5602                                        copy_to_reg (XEXP (operands[0], 0)));
5603    
5604           if (GET_CODE (operands[1]) == MEM
5605               && !memory_address_p (GET_MODE (operands[1]),
5606                                     XEXP (operands[1], 0)))
5607             operands[1]
5608               = replace_equiv_address (operands[1],
5609                                        copy_to_reg (XEXP (operands[1], 0)));
5610
5611           if (GET_CODE (operands[1]) == MEM && optimize > 0)
5612             {
5613               rtx reg = gen_reg_rtx (SImode);
5614
5615               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5616               operands[1] = gen_lowpart (HImode, reg);
5617             }
5618
5619           if (GET_CODE (operands[0]) == MEM)
5620             operands[1] = force_reg (HImode, operands[1]);
5621         }
5622       else if (GET_CODE (operands[1]) == CONST_INT
5623                 && !satisfies_constraint_I (operands[1]))
5624         {
5625           /* Handle loading a large integer during reload.  */
5626
5627           /* Writing a constant to memory needs a scratch, which should
5628              be handled with SECONDARY_RELOADs.  */
5629           gcc_assert (GET_CODE (operands[0]) == REG);
5630
5631           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5632           emit_insn (gen_movsi (operands[0], operands[1]));
5633           DONE;
5634         }
5635     }
5636   "
5637 )
5638
5639 (define_insn "*thumb1_movhi_insn"
5640   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5641         (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
5642   "TARGET_THUMB1
5643    && (   register_operand (operands[0], HImode)
5644        || register_operand (operands[1], HImode))"
5645   "*
5646   switch (which_alternative)
5647     {
5648     case 0: return \"add        %0, %1, #0\";
5649     case 2: return \"strh       %1, %0\";
5650     case 3: return \"mov        %0, %1\";
5651     case 4: return \"mov        %0, %1\";
5652     case 5: return \"mov        %0, %1\";
5653     default: gcc_unreachable ();
5654     case 1:
5655       /* The stack pointer can end up being taken as an index register.
5656           Catch this case here and deal with it.  */
5657       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
5658           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
5659           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
5660         {
5661           rtx ops[2];
5662           ops[0] = operands[0];
5663           ops[1] = XEXP (XEXP (operands[1], 0), 0);
5664       
5665           output_asm_insn (\"mov        %0, %1\", ops);
5666
5667           XEXP (XEXP (operands[1], 0), 0) = operands[0];
5668     
5669         }
5670       return \"ldrh     %0, %1\";
5671     }"
5672   [(set_attr "length" "2,4,2,2,2,2")
5673    (set_attr "type" "*,load1,store1,*,*,*")]
5674 )
5675
5676
5677 (define_expand "movhi_bytes"
5678   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
5679    (set (match_dup 3)
5680         (zero_extend:SI (match_dup 6)))
5681    (set (match_operand:SI 0 "" "")
5682          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
5683   "TARGET_ARM"
5684   "
5685   {
5686     rtx mem1, mem2;
5687     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5688
5689     mem1 = change_address (operands[1], QImode, addr);
5690     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
5691     operands[0] = gen_lowpart (SImode, operands[0]);
5692     operands[1] = mem1;
5693     operands[2] = gen_reg_rtx (SImode);
5694     operands[3] = gen_reg_rtx (SImode);
5695     operands[6] = mem2;
5696
5697     if (BYTES_BIG_ENDIAN)
5698       {
5699         operands[4] = operands[2];
5700         operands[5] = operands[3];
5701       }
5702     else
5703       {
5704         operands[4] = operands[3];
5705         operands[5] = operands[2];
5706       }
5707   }"
5708 )
5709
5710 (define_expand "movhi_bigend"
5711   [(set (match_dup 2)
5712         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
5713                    (const_int 16)))
5714    (set (match_dup 3)
5715         (ashiftrt:SI (match_dup 2) (const_int 16)))
5716    (set (match_operand:HI 0 "s_register_operand" "")
5717         (match_dup 4))]
5718   "TARGET_ARM"
5719   "
5720   operands[2] = gen_reg_rtx (SImode);
5721   operands[3] = gen_reg_rtx (SImode);
5722   operands[4] = gen_lowpart (HImode, operands[3]);
5723   "
5724 )
5725
5726 ;; Pattern to recognize insn generated default case above
5727 (define_insn "*movhi_insn_arch4"
5728   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
5729         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
5730   "TARGET_ARM
5731    && arm_arch4
5732    && (GET_CODE (operands[1]) != CONST_INT
5733        || const_ok_for_arm (INTVAL (operands[1]))
5734        || const_ok_for_arm (~INTVAL (operands[1])))"
5735   "@
5736    mov%?\\t%0, %1\\t%@ movhi
5737    mvn%?\\t%0, #%B1\\t%@ movhi
5738    str%(h%)\\t%1, %0\\t%@ movhi
5739    ldr%(h%)\\t%0, %1\\t%@ movhi"
5740   [(set_attr "type" "*,*,store1,load1")
5741    (set_attr "predicable" "yes")
5742    (set_attr "pool_range" "*,*,*,256")
5743    (set_attr "neg_pool_range" "*,*,*,244")]
5744 )
5745
5746 (define_insn "*movhi_bytes"
5747   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
5748         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
5749   "TARGET_ARM"
5750   "@
5751    mov%?\\t%0, %1\\t%@ movhi
5752    mvn%?\\t%0, #%B1\\t%@ movhi"
5753   [(set_attr "predicable" "yes")]
5754 )
5755
5756 (define_expand "thumb_movhi_clobber"
5757   [(set (match_operand:HI     0 "memory_operand"   "")
5758         (match_operand:HI     1 "register_operand" ""))
5759    (clobber (match_operand:DI 2 "register_operand" ""))]
5760   "TARGET_THUMB1"
5761   "
5762   if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
5763       && REGNO (operands[1]) <= LAST_LO_REGNUM)
5764     {
5765       emit_insn (gen_movhi (operands[0], operands[1]));
5766       DONE;
5767     }
5768   /* XXX Fixme, need to handle other cases here as well.  */
5769   gcc_unreachable ();
5770   "
5771 )
5772         
5773 ;; We use a DImode scratch because we may occasionally need an additional
5774 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
5775 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
5776 (define_expand "reload_outhi"
5777   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
5778               (match_operand:HI 1 "s_register_operand"        "r")
5779               (match_operand:DI 2 "s_register_operand"        "=&l")])]
5780   "TARGET_EITHER"
5781   "if (TARGET_ARM)
5782      arm_reload_out_hi (operands);
5783    else
5784      thumb_reload_out_hi (operands);
5785   DONE;
5786   "
5787 )
5788
5789 (define_expand "reload_inhi"
5790   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
5791               (match_operand:HI 1 "arm_reload_memory_operand" "o")
5792               (match_operand:DI 2 "s_register_operand" "=&r")])]
5793   "TARGET_EITHER"
5794   "
5795   if (TARGET_ARM)
5796     arm_reload_in_hi (operands);
5797   else
5798     thumb_reload_out_hi (operands);
5799   DONE;
5800 ")
5801
5802 (define_expand "movqi"
5803   [(set (match_operand:QI 0 "general_operand" "")
5804         (match_operand:QI 1 "general_operand" ""))]
5805   "TARGET_EITHER"
5806   "
5807   /* Everything except mem = const or mem = mem can be done easily */
5808
5809   if (can_create_pseudo_p ())
5810     {
5811       if (GET_CODE (operands[1]) == CONST_INT)
5812         {
5813           rtx reg = gen_reg_rtx (SImode);
5814
5815           emit_insn (gen_movsi (reg, operands[1]));
5816           operands[1] = gen_lowpart (QImode, reg);
5817         }
5818
5819       if (TARGET_THUMB)
5820         {
5821           /* ??? We shouldn't really get invalid addresses here, but this can
5822              happen if we are passed a SP (never OK for HImode/QImode) or
5823              virtual register (also rejected as illegitimate for HImode/QImode)
5824              relative address.  */
5825           /* ??? This should perhaps be fixed elsewhere, for instance, in
5826              fixup_stack_1, by checking for other kinds of invalid addresses,
5827              e.g. a bare reference to a virtual register.  This may confuse the
5828              alpha though, which must handle this case differently.  */
5829           if (GET_CODE (operands[0]) == MEM
5830               && !memory_address_p (GET_MODE (operands[0]),
5831                                      XEXP (operands[0], 0)))
5832             operands[0]
5833               = replace_equiv_address (operands[0],
5834                                        copy_to_reg (XEXP (operands[0], 0)));
5835           if (GET_CODE (operands[1]) == MEM
5836               && !memory_address_p (GET_MODE (operands[1]),
5837                                     XEXP (operands[1], 0)))
5838              operands[1]
5839                = replace_equiv_address (operands[1],
5840                                         copy_to_reg (XEXP (operands[1], 0)));
5841         }
5842
5843       if (GET_CODE (operands[1]) == MEM && optimize > 0)
5844         {
5845           rtx reg = gen_reg_rtx (SImode);
5846
5847           emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5848           operands[1] = gen_lowpart (QImode, reg);
5849         }
5850
5851       if (GET_CODE (operands[0]) == MEM)
5852         operands[1] = force_reg (QImode, operands[1]);
5853     }
5854   else if (TARGET_THUMB
5855            && GET_CODE (operands[1]) == CONST_INT
5856            && !satisfies_constraint_I (operands[1]))
5857     {
5858       /* Handle loading a large integer during reload.  */
5859
5860       /* Writing a constant to memory needs a scratch, which should
5861          be handled with SECONDARY_RELOADs.  */
5862       gcc_assert (GET_CODE (operands[0]) == REG);
5863
5864       operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5865       emit_insn (gen_movsi (operands[0], operands[1]));
5866       DONE;
5867     }
5868   "
5869 )
5870
5871
5872 (define_insn "*arm_movqi_insn"
5873   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5874         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5875   "TARGET_32BIT
5876    && (   register_operand (operands[0], QImode)
5877        || register_operand (operands[1], QImode))"
5878   "@
5879    mov%?\\t%0, %1
5880    mvn%?\\t%0, #%B1
5881    ldr%(b%)\\t%0, %1
5882    str%(b%)\\t%1, %0"
5883   [(set_attr "type" "*,*,load1,store1")
5884    (set_attr "predicable" "yes")]
5885 )
5886
5887 (define_insn "*thumb1_movqi_insn"
5888   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5889         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
5890   "TARGET_THUMB1
5891    && (   register_operand (operands[0], QImode)
5892        || register_operand (operands[1], QImode))"
5893   "@
5894    add\\t%0, %1, #0
5895    ldrb\\t%0, %1
5896    strb\\t%1, %0
5897    mov\\t%0, %1
5898    mov\\t%0, %1
5899    mov\\t%0, %1"
5900   [(set_attr "length" "2")
5901    (set_attr "type" "*,load1,store1,*,*,*")
5902    (set_attr "pool_range" "*,32,*,*,*,*")]
5903 )
5904
5905 ;; HFmode moves
5906 (define_expand "movhf"
5907   [(set (match_operand:HF 0 "general_operand" "")
5908         (match_operand:HF 1 "general_operand" ""))]
5909   "TARGET_EITHER"
5910   "
5911   if (TARGET_32BIT)
5912     {
5913       if (GET_CODE (operands[0]) == MEM)
5914         operands[1] = force_reg (HFmode, operands[1]);
5915     }
5916   else /* TARGET_THUMB1 */
5917     {
5918       if (can_create_pseudo_p ())
5919         {
5920            if (GET_CODE (operands[0]) != REG)
5921              operands[1] = force_reg (HFmode, operands[1]);
5922         }
5923     }
5924   "
5925 )
5926
5927 (define_insn "*arm32_movhf"
5928   [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
5929         (match_operand:HF 1 "general_operand"      " m,r,r,F"))]
5930   "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_NEON_FP16)
5931    && (   s_register_operand (operands[0], HFmode)
5932        || s_register_operand (operands[1], HFmode))"
5933   "*
5934   switch (which_alternative)
5935     {
5936     case 0:     /* ARM register from memory */
5937       return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
5938     case 1:     /* memory from ARM register */
5939       return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
5940     case 2:     /* ARM register from ARM register */
5941       return \"mov%?\\t%0, %1\\t%@ __fp16\";
5942     case 3:     /* ARM register from constant */
5943       {
5944         REAL_VALUE_TYPE r;
5945         long bits;
5946         rtx ops[4];
5947
5948         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
5949         bits = real_to_target (NULL, &r, HFmode);
5950         ops[0] = operands[0];
5951         ops[1] = GEN_INT (bits);
5952         ops[2] = GEN_INT (bits & 0xff00);
5953         ops[3] = GEN_INT (bits & 0x00ff);
5954
5955         if (arm_arch_thumb2)
5956           output_asm_insn (\"movw%?\\t%0, %1\", ops);
5957         else
5958           output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
5959         return \"\";
5960        }
5961     default:
5962       gcc_unreachable ();
5963     }
5964   "
5965   [(set_attr "conds" "unconditional")
5966    (set_attr "type" "load1,store1,*,*")
5967    (set_attr "length" "4,4,4,8")
5968    (set_attr "predicable" "yes")
5969    ]
5970 )
5971
5972 (define_insn "*thumb1_movhf"
5973   [(set (match_operand:HF     0 "nonimmediate_operand" "=l,l,m,*r,*h")
5974         (match_operand:HF     1 "general_operand"      "l,mF,l,*h,*r"))]
5975   "TARGET_THUMB1
5976    && (   s_register_operand (operands[0], HFmode) 
5977        || s_register_operand (operands[1], HFmode))"
5978   "*
5979   switch (which_alternative)
5980     {
5981     case 1:
5982       {
5983         rtx addr;
5984         gcc_assert (GET_CODE(operands[1]) == MEM);
5985         addr = XEXP (operands[1], 0);
5986         if (GET_CODE (addr) == LABEL_REF
5987             || (GET_CODE (addr) == CONST
5988                 && GET_CODE (XEXP (addr, 0)) == PLUS
5989                 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF
5990                 && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT))
5991           {
5992             /* Constant pool entry.  */
5993             return \"ldr\\t%0, %1\";
5994           }
5995         return \"ldrh\\t%0, %1\";
5996       }
5997     case 2: return \"strh\\t%1, %0\";
5998     default: return \"mov\\t%0, %1\";
5999     }
6000   "
6001   [(set_attr "length" "2")
6002    (set_attr "type" "*,load1,store1,*,*")
6003    (set_attr "pool_range" "*,1020,*,*,*")]
6004 )
6005
6006 (define_expand "movsf"
6007   [(set (match_operand:SF 0 "general_operand" "")
6008         (match_operand:SF 1 "general_operand" ""))]
6009   "TARGET_EITHER"
6010   "
6011   if (TARGET_32BIT)
6012     {
6013       if (GET_CODE (operands[0]) == MEM)
6014         operands[1] = force_reg (SFmode, operands[1]);
6015     }
6016   else /* TARGET_THUMB1 */
6017     {
6018       if (can_create_pseudo_p ())
6019         {
6020            if (GET_CODE (operands[0]) != REG)
6021              operands[1] = force_reg (SFmode, operands[1]);
6022         }
6023     }
6024   "
6025 )
6026
6027 ;; Transform a floating-point move of a constant into a core register into
6028 ;; an SImode operation.
6029 (define_split
6030   [(set (match_operand:SF 0 "arm_general_register_operand" "")
6031         (match_operand:SF 1 "immediate_operand" ""))]
6032   "TARGET_32BIT
6033    && reload_completed
6034    && GET_CODE (operands[1]) == CONST_DOUBLE"
6035   [(set (match_dup 2) (match_dup 3))]
6036   "
6037   operands[2] = gen_lowpart (SImode, operands[0]);
6038   operands[3] = gen_lowpart (SImode, operands[1]);
6039   if (operands[2] == 0 || operands[3] == 0)
6040     FAIL;
6041   "
6042 )
6043
6044 (define_insn "*arm_movsf_soft_insn"
6045   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6046         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
6047   "TARGET_ARM
6048    && TARGET_SOFT_FLOAT
6049    && (GET_CODE (operands[0]) != MEM
6050        || register_operand (operands[1], SFmode))"
6051   "@
6052    mov%?\\t%0, %1
6053    ldr%?\\t%0, %1\\t%@ float
6054    str%?\\t%1, %0\\t%@ float"
6055   [(set_attr "length" "4,4,4")
6056    (set_attr "predicable" "yes")
6057    (set_attr "type" "*,load1,store1")
6058    (set_attr "pool_range" "*,4096,*")
6059    (set_attr "neg_pool_range" "*,4084,*")]
6060 )
6061
6062 ;;; ??? This should have alternatives for constants.
6063 (define_insn "*thumb1_movsf_insn"
6064   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
6065         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
6066   "TARGET_THUMB1
6067    && (   register_operand (operands[0], SFmode) 
6068        || register_operand (operands[1], SFmode))"
6069   "@
6070    add\\t%0, %1, #0
6071    ldmia\\t%1, {%0}
6072    stmia\\t%0, {%1}
6073    ldr\\t%0, %1
6074    str\\t%1, %0
6075    mov\\t%0, %1
6076    mov\\t%0, %1"
6077   [(set_attr "length" "2")
6078    (set_attr "type" "*,load1,store1,load1,store1,*,*")
6079    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
6080 )
6081
6082 (define_expand "movdf"
6083   [(set (match_operand:DF 0 "general_operand" "")
6084         (match_operand:DF 1 "general_operand" ""))]
6085   "TARGET_EITHER"
6086   "
6087   if (TARGET_32BIT)
6088     {
6089       if (GET_CODE (operands[0]) == MEM)
6090         operands[1] = force_reg (DFmode, operands[1]);
6091     }
6092   else /* TARGET_THUMB */
6093     {
6094       if (can_create_pseudo_p ())
6095         {
6096           if (GET_CODE (operands[0]) != REG)
6097             operands[1] = force_reg (DFmode, operands[1]);
6098         }
6099     }
6100   "
6101 )
6102
6103 ;; Reloading a df mode value stored in integer regs to memory can require a
6104 ;; scratch reg.
6105 (define_expand "reload_outdf"
6106   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
6107    (match_operand:DF 1 "s_register_operand" "r")
6108    (match_operand:SI 2 "s_register_operand" "=&r")]
6109   "TARGET_32BIT"
6110   "
6111   {
6112     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
6113
6114     if (code == REG)
6115       operands[2] = XEXP (operands[0], 0);
6116     else if (code == POST_INC || code == PRE_DEC)
6117       {
6118         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6119         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6120         emit_insn (gen_movdi (operands[0], operands[1]));
6121         DONE;
6122       }
6123     else if (code == PRE_INC)
6124       {
6125         rtx reg = XEXP (XEXP (operands[0], 0), 0);
6126
6127         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6128         operands[2] = reg;
6129       }
6130     else if (code == POST_DEC)
6131       operands[2] = XEXP (XEXP (operands[0], 0), 0);
6132     else
6133       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6134                              XEXP (XEXP (operands[0], 0), 1)));
6135
6136     emit_insn (gen_rtx_SET (VOIDmode,
6137                             replace_equiv_address (operands[0], operands[2]),
6138                             operands[1]));
6139
6140     if (code == POST_DEC)
6141       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6142
6143     DONE;
6144   }"
6145 )
6146
6147 (define_insn "*movdf_soft_insn"
6148   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
6149         (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
6150   "TARGET_ARM && TARGET_SOFT_FLOAT
6151    && (   register_operand (operands[0], DFmode)
6152        || register_operand (operands[1], DFmode))"
6153   "*
6154   switch (which_alternative)
6155     {
6156     case 0:
6157     case 1:
6158     case 2:
6159       return \"#\";
6160     default:
6161       return output_move_double (operands);
6162     }
6163   "
6164   [(set_attr "length" "8,12,16,8,8")
6165    (set_attr "type" "*,*,*,load2,store2")
6166    (set_attr "pool_range" "1020")
6167    (set_attr "neg_pool_range" "1008")]
6168 )
6169
6170 ;;; ??? This should have alternatives for constants.
6171 ;;; ??? This was originally identical to the movdi_insn pattern.
6172 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
6173 ;;; thumb_reorg with a memory reference.
6174 (define_insn "*thumb_movdf_insn"
6175   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
6176         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
6177   "TARGET_THUMB1
6178    && (   register_operand (operands[0], DFmode)
6179        || register_operand (operands[1], DFmode))"
6180   "*
6181   switch (which_alternative)
6182     {
6183     default:
6184     case 0:
6185       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6186         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
6187       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
6188     case 1:
6189       return \"ldmia\\t%1, {%0, %H0}\";
6190     case 2:
6191       return \"stmia\\t%0, {%1, %H1}\";
6192     case 3:
6193       return thumb_load_double_from_address (operands);
6194     case 4:
6195       operands[2] = gen_rtx_MEM (SImode,
6196                                  plus_constant (XEXP (operands[0], 0), 4));
6197       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
6198       return \"\";
6199     case 5:
6200       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6201         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
6202       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
6203     }
6204   "
6205   [(set_attr "length" "4,2,2,6,4,4")
6206    (set_attr "type" "*,load2,store2,load2,store2,*")
6207    (set_attr "pool_range" "*,*,*,1020,*,*")]
6208 )
6209
6210 (define_expand "movxf"
6211   [(set (match_operand:XF 0 "general_operand" "")
6212         (match_operand:XF 1 "general_operand" ""))]
6213   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
6214   "
6215   if (GET_CODE (operands[0]) == MEM)
6216     operands[1] = force_reg (XFmode, operands[1]);
6217   "
6218 )
6219
6220 \f
6221
6222 ;; load- and store-multiple insns
6223 ;; The arm can load/store any set of registers, provided that they are in
6224 ;; ascending order; but that is beyond GCC so stick with what it knows.
6225
6226 (define_expand "load_multiple"
6227   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6228                           (match_operand:SI 1 "" ""))
6229                      (use (match_operand:SI 2 "" ""))])]
6230   "TARGET_32BIT"
6231 {
6232   HOST_WIDE_INT offset = 0;
6233
6234   /* Support only fixed point registers.  */
6235   if (GET_CODE (operands[2]) != CONST_INT
6236       || INTVAL (operands[2]) > 14
6237       || INTVAL (operands[2]) < 2
6238       || GET_CODE (operands[1]) != MEM
6239       || GET_CODE (operands[0]) != REG
6240       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6241       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
6242     FAIL;
6243
6244   operands[3]
6245     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
6246                              force_reg (SImode, XEXP (operands[1], 0)),
6247                              TRUE, FALSE, operands[1], &offset);
6248 })
6249
6250 ;; Load multiple with write-back
6251
6252 (define_insn "*ldmsi_postinc4"
6253   [(match_parallel 0 "load_multiple_operation"
6254     [(set (match_operand:SI 1 "s_register_operand" "=r")
6255           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6256                    (const_int 16)))
6257      (set (match_operand:SI 3 "arm_hard_register_operand" "")
6258           (mem:SI (match_dup 2)))
6259      (set (match_operand:SI 4 "arm_hard_register_operand" "")
6260           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
6261      (set (match_operand:SI 5 "arm_hard_register_operand" "")
6262           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
6263      (set (match_operand:SI 6 "arm_hard_register_operand" "")
6264           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
6265   "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
6266   "ldm%(ia%)\\t%1!, {%3, %4, %5, %6}"
6267   [(set_attr "type" "load4")
6268    (set_attr "predicable" "yes")]
6269 )
6270
6271 (define_insn "*ldmsi_postinc4_thumb1"
6272   [(match_parallel 0 "load_multiple_operation"
6273     [(set (match_operand:SI 1 "s_register_operand" "=l")
6274           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6275                    (const_int 16)))
6276      (set (match_operand:SI 3 "arm_hard_register_operand" "")
6277           (mem:SI (match_dup 2)))
6278      (set (match_operand:SI 4 "arm_hard_register_operand" "")
6279           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
6280      (set (match_operand:SI 5 "arm_hard_register_operand" "")
6281           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
6282      (set (match_operand:SI 6 "arm_hard_register_operand" "")
6283           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
6284   "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
6285   "ldmia\\t%1!, {%3, %4, %5, %6}"
6286   [(set_attr "type" "load4")]
6287 )
6288
6289 (define_insn "*ldmsi_postinc3"
6290   [(match_parallel 0 "load_multiple_operation"
6291     [(set (match_operand:SI 1 "s_register_operand" "=r")
6292           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6293                    (const_int 12)))
6294      (set (match_operand:SI 3 "arm_hard_register_operand" "")
6295           (mem:SI (match_dup 2)))
6296      (set (match_operand:SI 4 "arm_hard_register_operand" "")
6297           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
6298      (set (match_operand:SI 5 "arm_hard_register_operand" "")
6299           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
6300   "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6301   "ldm%(ia%)\\t%1!, {%3, %4, %5}"
6302   [(set_attr "type" "load3")
6303    (set_attr "predicable" "yes")]
6304 )
6305
6306 (define_insn "*ldmsi_postinc2"
6307   [(match_parallel 0 "load_multiple_operation"
6308     [(set (match_operand:SI 1 "s_register_operand" "=r")
6309           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6310                    (const_int 8)))
6311      (set (match_operand:SI 3 "arm_hard_register_operand" "")
6312           (mem:SI (match_dup 2)))
6313      (set (match_operand:SI 4 "arm_hard_register_operand" "")
6314           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
6315   "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6316   "ldm%(ia%)\\t%1!, {%3, %4}"
6317   [(set_attr "type" "load2")
6318    (set_attr "predicable" "yes")]
6319 )
6320
6321 ;; Ordinary load multiple
6322
6323 (define_insn "*ldmsi4"
6324   [(match_parallel 0 "load_multiple_operation"
6325     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
6326           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
6327      (set (match_operand:SI 3 "arm_hard_register_operand" "")
6328           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
6329      (set (match_operand:SI 4 "arm_hard_register_operand" "")
6330           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
6331      (set (match_operand:SI 5 "arm_hard_register_operand" "")
6332           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
6333   "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6334   "ldm%(ia%)\\t%1, {%2, %3, %4, %5}"
6335   [(set_attr "type" "load4")
6336    (set_attr "predicable" "yes")]
6337 )
6338
6339 (define_insn "*ldmsi3"
6340   [(match_parallel 0 "load_multiple_operation"
6341     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
6342           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
6343      (set (match_operand:SI 3 "arm_hard_register_operand" "")
6344           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
6345      (set (match_operand:SI 4 "arm_hard_register_operand" "")
6346           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
6347   "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6348   "ldm%(ia%)\\t%1, {%2, %3, %4}"
6349   [(set_attr "type" "load3")
6350    (set_attr "predicable" "yes")]
6351 )
6352
6353 (define_insn "*ldmsi2"
6354   [(match_parallel 0 "load_multiple_operation"
6355     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
6356           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
6357      (set (match_operand:SI 3 "arm_hard_register_operand" "")
6358           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
6359   "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
6360   "ldm%(ia%)\\t%1, {%2, %3}"
6361   [(set_attr "type" "load2")
6362    (set_attr "predicable" "yes")]
6363 )
6364
6365 (define_expand "store_multiple"
6366   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6367                           (match_operand:SI 1 "" ""))
6368                      (use (match_operand:SI 2 "" ""))])]
6369   "TARGET_32BIT"
6370 {
6371   HOST_WIDE_INT offset = 0;
6372
6373   /* Support only fixed point registers.  */
6374   if (GET_CODE (operands[2]) != CONST_INT
6375       || INTVAL (operands[2]) > 14
6376       || INTVAL (operands[2]) < 2
6377       || GET_CODE (operands[1]) != REG
6378       || GET_CODE (operands[0]) != MEM
6379       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6380       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
6381     FAIL;
6382
6383   operands[3]
6384     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
6385                               force_reg (SImode, XEXP (operands[0], 0)),
6386                               TRUE, FALSE, operands[0], &offset);
6387 })
6388
6389 ;; Store multiple with write-back
6390
6391 (define_insn "*stmsi_postinc4"
6392   [(match_parallel 0 "store_multiple_operation"
6393     [(set (match_operand:SI 1 "s_register_operand" "=r")
6394           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6395                    (const_int 16)))
6396      (set (mem:SI (match_dup 2))
6397           (match_operand:SI 3 "arm_hard_register_operand" ""))
6398      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6399           (match_operand:SI 4 "arm_hard_register_operand" ""))
6400      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6401           (match_operand:SI 5 "arm_hard_register_operand" ""))
6402      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
6403           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
6404   "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
6405   "stm%(ia%)\\t%1!, {%3, %4, %5, %6}"
6406   [(set_attr "predicable" "yes")
6407    (set_attr "type" "store4")]
6408 )
6409
6410 (define_insn "*stmsi_postinc4_thumb1"
6411   [(match_parallel 0 "store_multiple_operation"
6412     [(set (match_operand:SI 1 "s_register_operand" "=l")
6413           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6414                    (const_int 16)))
6415      (set (mem:SI (match_dup 2))
6416           (match_operand:SI 3 "arm_hard_register_operand" ""))
6417      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6418           (match_operand:SI 4 "arm_hard_register_operand" ""))
6419      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6420           (match_operand:SI 5 "arm_hard_register_operand" ""))
6421      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
6422           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
6423   "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
6424   "stmia\\t%1!, {%3, %4, %5, %6}"
6425   [(set_attr "type" "store4")]
6426 )
6427
6428 (define_insn "*stmsi_postinc3"
6429   [(match_parallel 0 "store_multiple_operation"
6430     [(set (match_operand:SI 1 "s_register_operand" "=r")
6431           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6432                    (const_int 12)))
6433      (set (mem:SI (match_dup 2))
6434           (match_operand:SI 3 "arm_hard_register_operand" ""))
6435      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6436           (match_operand:SI 4 "arm_hard_register_operand" ""))
6437      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6438           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
6439   "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6440   "stm%(ia%)\\t%1!, {%3, %4, %5}"
6441   [(set_attr "predicable" "yes")
6442    (set_attr "type" "store3")]
6443 )
6444
6445 (define_insn "*stmsi_postinc2"
6446   [(match_parallel 0 "store_multiple_operation"
6447     [(set (match_operand:SI 1 "s_register_operand" "=r")
6448           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
6449                    (const_int 8)))
6450      (set (mem:SI (match_dup 2))
6451           (match_operand:SI 3 "arm_hard_register_operand" ""))
6452      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6453           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
6454   "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6455   "stm%(ia%)\\t%1!, {%3, %4}"
6456   [(set_attr "predicable" "yes")
6457    (set_attr "type" "store2")]
6458 )
6459
6460 ;; Ordinary store multiple
6461
6462 (define_insn "*stmsi4"
6463   [(match_parallel 0 "store_multiple_operation"
6464     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6465           (match_operand:SI 2 "arm_hard_register_operand" ""))
6466      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6467           (match_operand:SI 3 "arm_hard_register_operand" ""))
6468      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
6469           (match_operand:SI 4 "arm_hard_register_operand" ""))
6470      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
6471           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
6472   "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
6473   "stm%(ia%)\\t%1, {%2, %3, %4, %5}"
6474   [(set_attr "predicable" "yes")
6475    (set_attr "type" "store4")]
6476 )
6477
6478 (define_insn "*stmsi3"
6479   [(match_parallel 0 "store_multiple_operation"
6480     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6481           (match_operand:SI 2 "arm_hard_register_operand" ""))
6482      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6483           (match_operand:SI 3 "arm_hard_register_operand" ""))
6484      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
6485           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
6486   "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
6487   "stm%(ia%)\\t%1, {%2, %3, %4}"
6488   [(set_attr "predicable" "yes")
6489    (set_attr "type" "store3")]
6490 )
6491
6492 (define_insn "*stmsi2"
6493   [(match_parallel 0 "store_multiple_operation"
6494     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6495           (match_operand:SI 2 "arm_hard_register_operand" ""))
6496      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
6497           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
6498   "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
6499   "stm%(ia%)\\t%1, {%2, %3}"
6500   [(set_attr "predicable" "yes")
6501    (set_attr "type" "store2")]
6502 )
6503
6504 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
6505 ;; We could let this apply for blocks of less than this, but it clobbers so
6506 ;; many registers that there is then probably a better way.
6507
6508 (define_expand "movmemqi"
6509   [(match_operand:BLK 0 "general_operand" "")
6510    (match_operand:BLK 1 "general_operand" "")
6511    (match_operand:SI 2 "const_int_operand" "")
6512    (match_operand:SI 3 "const_int_operand" "")]
6513   "TARGET_EITHER"
6514   "
6515   if (TARGET_32BIT)
6516     {
6517       if (arm_gen_movmemqi (operands))
6518         DONE;
6519       FAIL;
6520     }
6521   else /* TARGET_THUMB1 */
6522     {
6523       if (   INTVAL (operands[3]) != 4
6524           || INTVAL (operands[2]) > 48)
6525         FAIL;
6526
6527       thumb_expand_movmemqi (operands);
6528       DONE;
6529     }
6530   "
6531 )
6532
6533 ;; Thumb block-move insns
6534
6535 (define_insn "movmem12b"
6536   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6537         (mem:SI (match_operand:SI 3 "register_operand" "1")))
6538    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6539         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6540    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6541         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
6542    (set (match_operand:SI 0 "register_operand" "=l")
6543         (plus:SI (match_dup 2) (const_int 12)))
6544    (set (match_operand:SI 1 "register_operand" "=l")
6545         (plus:SI (match_dup 3) (const_int 12)))
6546    (clobber (match_scratch:SI 4 "=&l"))
6547    (clobber (match_scratch:SI 5 "=&l"))
6548    (clobber (match_scratch:SI 6 "=&l"))]
6549   "TARGET_THUMB1"
6550   "* return thumb_output_move_mem_multiple (3, operands);"
6551   [(set_attr "length" "4")
6552    ; This isn't entirely accurate...  It loads as well, but in terms of
6553    ; scheduling the following insn it is better to consider it as a store
6554    (set_attr "type" "store3")]
6555 )
6556
6557 (define_insn "movmem8b"
6558   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6559         (mem:SI (match_operand:SI 3 "register_operand" "1")))
6560    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6561         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6562    (set (match_operand:SI 0 "register_operand" "=l")
6563         (plus:SI (match_dup 2) (const_int 8)))
6564    (set (match_operand:SI 1 "register_operand" "=l")
6565         (plus:SI (match_dup 3) (const_int 8)))
6566    (clobber (match_scratch:SI 4 "=&l"))
6567    (clobber (match_scratch:SI 5 "=&l"))]
6568   "TARGET_THUMB1"
6569   "* return thumb_output_move_mem_multiple (2, operands);"
6570   [(set_attr "length" "4")
6571    ; This isn't entirely accurate...  It loads as well, but in terms of
6572    ; scheduling the following insn it is better to consider it as a store
6573    (set_attr "type" "store2")]
6574 )
6575
6576 \f
6577
6578 ;; Compare & branch insns
6579 ;; The range calculations are based as follows:
6580 ;; For forward branches, the address calculation returns the address of
6581 ;; the next instruction.  This is 2 beyond the branch instruction.
6582 ;; For backward branches, the address calculation returns the address of
6583 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
6584 ;; instruction for the shortest sequence, and 4 before the branch instruction
6585 ;; if we have to jump around an unconditional branch.
6586 ;; To the basic branch range the PC offset must be added (this is +4).
6587 ;; So for forward branches we have 
6588 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6589 ;; And for backward branches we have 
6590 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6591 ;;
6592 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6593 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
6594
6595 (define_expand "cbranchsi4"
6596   [(set (pc) (if_then_else
6597               (match_operator 0 "arm_comparison_operator"
6598                [(match_operand:SI 1 "s_register_operand" "")
6599                 (match_operand:SI 2 "nonmemory_operand" "")])
6600               (label_ref (match_operand 3 "" ""))
6601               (pc)))]
6602   "TARGET_THUMB1 || TARGET_32BIT"
6603   "
6604   if (!TARGET_THUMB1)
6605     {
6606       if (!arm_add_operand (operands[2], SImode))
6607         operands[2] = force_reg (SImode, operands[2]);
6608       emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6609                                       operands[3]));
6610       DONE;
6611     }
6612   if (thumb1_cmpneg_operand (operands[2], SImode))
6613     {
6614       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6615                                               operands[3], operands[0]));
6616       DONE;
6617     }
6618   if (!thumb1_cmp_operand (operands[2], SImode))
6619     operands[2] = force_reg (SImode, operands[2]);
6620   ")
6621
6622 (define_expand "cbranchsf4"
6623   [(set (pc) (if_then_else
6624               (match_operator 0 "arm_comparison_operator"
6625                [(match_operand:SF 1 "s_register_operand" "")
6626                 (match_operand:SF 2 "arm_float_compare_operand" "")])
6627               (label_ref (match_operand 3 "" ""))
6628               (pc)))]
6629   "TARGET_32BIT && TARGET_HARD_FLOAT"
6630   "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6631                                    operands[3])); DONE;"
6632 )
6633
6634 (define_expand "cbranchdf4"
6635   [(set (pc) (if_then_else
6636               (match_operator 0 "arm_comparison_operator"
6637                [(match_operand:DF 1 "s_register_operand" "")
6638                 (match_operand:DF 2 "arm_float_compare_operand" "")])
6639               (label_ref (match_operand 3 "" ""))
6640               (pc)))]
6641   "TARGET_32BIT && TARGET_HARD_FLOAT"
6642   "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6643                                    operands[3])); DONE;"
6644 )
6645
6646 ;; this uses the Cirrus DI compare instruction
6647 (define_expand "cbranchdi4"
6648   [(set (pc) (if_then_else
6649               (match_operator 0 "arm_comparison_operator"
6650                [(match_operand:DI 1 "cirrus_fp_register" "")
6651                 (match_operand:DI 2 "cirrus_fp_register" "")])
6652               (label_ref (match_operand 3 "" ""))
6653               (pc)))]
6654   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6655   "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6656                                    operands[3])); DONE;"
6657 )
6658
6659 (define_insn "*cbranchsi4_insn"
6660   [(set (pc) (if_then_else
6661               (match_operator 0 "arm_comparison_operator"
6662                [(match_operand:SI 1 "s_register_operand" "l,*h")
6663                 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
6664               (label_ref (match_operand 3 "" ""))
6665               (pc)))]
6666   "TARGET_THUMB1"
6667   "*
6668   output_asm_insn (\"cmp\\t%1, %2\", operands);
6669
6670   switch (get_attr_length (insn))
6671     {
6672     case 4:  return \"b%d0\\t%l3\";
6673     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6674     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6675     }
6676   "
6677   [(set (attr "far_jump")
6678         (if_then_else
6679             (eq_attr "length" "8")
6680             (const_string "yes")
6681             (const_string "no")))
6682    (set (attr "length") 
6683         (if_then_else
6684             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6685                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6686             (const_int 4)
6687             (if_then_else
6688                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6689                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6690                 (const_int 6)
6691                 (const_int 8))))]
6692 )
6693
6694 (define_insn "cbranchsi4_scratch"
6695   [(set (pc) (if_then_else
6696               (match_operator 4 "arm_comparison_operator"
6697                [(match_operand:SI 1 "s_register_operand" "l,0")
6698                 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
6699               (label_ref (match_operand 3 "" ""))
6700               (pc)))
6701    (clobber (match_scratch:SI 0 "=l,l"))]
6702   "TARGET_THUMB1"
6703   "*
6704   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
6705
6706   switch (get_attr_length (insn))
6707     {
6708     case 4:  return \"b%d4\\t%l3\";
6709     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6710     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6711     }
6712   "
6713   [(set (attr "far_jump")
6714         (if_then_else
6715             (eq_attr "length" "8")
6716             (const_string "yes")
6717             (const_string "no")))
6718    (set (attr "length") 
6719         (if_then_else
6720             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6721                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6722             (const_int 4)
6723             (if_then_else
6724                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6725                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6726                 (const_int 6)
6727                 (const_int 8))))]
6728 )
6729 (define_insn "*movsi_cbranchsi4"
6730   [(set (pc)
6731         (if_then_else
6732          (match_operator 3 "arm_comparison_operator"
6733           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
6734            (const_int 0)])
6735          (label_ref (match_operand 2 "" ""))
6736          (pc)))
6737    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
6738         (match_dup 1))]
6739   "TARGET_THUMB1"
6740   "*{
6741   if (which_alternative == 0)
6742     output_asm_insn (\"cmp\t%0, #0\", operands);
6743   else if (which_alternative == 1)
6744     output_asm_insn (\"sub\t%0, %1, #0\", operands);
6745   else
6746     {
6747       output_asm_insn (\"cmp\t%1, #0\", operands);
6748       if (which_alternative == 2)
6749         output_asm_insn (\"mov\t%0, %1\", operands);
6750       else
6751         output_asm_insn (\"str\t%1, %0\", operands);
6752     }
6753   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
6754     {
6755     case 4:  return \"b%d3\\t%l2\";
6756     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6757     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
6758     }
6759   }"
6760   [(set (attr "far_jump")
6761         (if_then_else
6762             (ior (and (gt (symbol_ref ("which_alternative"))
6763                           (const_int 1))
6764                       (eq_attr "length" "8"))
6765                  (eq_attr "length" "10"))
6766             (const_string "yes")
6767             (const_string "no")))
6768    (set (attr "length")
6769      (if_then_else
6770        (le (symbol_ref ("which_alternative"))
6771                        (const_int 1))
6772        (if_then_else
6773          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6774               (le (minus (match_dup 2) (pc)) (const_int 256)))
6775          (const_int 4)
6776          (if_then_else
6777            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6778                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6779            (const_int 6)
6780            (const_int 8)))
6781        (if_then_else
6782          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
6783               (le (minus (match_dup 2) (pc)) (const_int 256)))
6784          (const_int 6)
6785          (if_then_else
6786            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
6787                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6788            (const_int 8)
6789            (const_int 10)))))]
6790 )
6791
6792 (define_insn "*negated_cbranchsi4"
6793   [(set (pc)
6794         (if_then_else
6795          (match_operator 0 "equality_operator"
6796           [(match_operand:SI 1 "s_register_operand" "l")
6797            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
6798          (label_ref (match_operand 3 "" ""))
6799          (pc)))]
6800   "TARGET_THUMB1"
6801   "*
6802   output_asm_insn (\"cmn\\t%1, %2\", operands);
6803   switch (get_attr_length (insn))
6804     {
6805     case 4:  return \"b%d0\\t%l3\";
6806     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6807     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6808     }
6809   "
6810   [(set (attr "far_jump")
6811         (if_then_else
6812             (eq_attr "length" "8")
6813             (const_string "yes")
6814             (const_string "no")))
6815    (set (attr "length") 
6816         (if_then_else
6817             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6818                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6819             (const_int 4)
6820             (if_then_else
6821                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6822                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6823                 (const_int 6)
6824                 (const_int 8))))]
6825 )
6826
6827 (define_insn "*tbit_cbranch"
6828   [(set (pc)
6829         (if_then_else
6830          (match_operator 0 "equality_operator"
6831           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6832                             (const_int 1)
6833                             (match_operand:SI 2 "const_int_operand" "i"))
6834            (const_int 0)])
6835          (label_ref (match_operand 3 "" ""))
6836          (pc)))
6837    (clobber (match_scratch:SI 4 "=l"))]
6838   "TARGET_THUMB1"
6839   "*
6840   {
6841   rtx op[3];
6842   op[0] = operands[4];
6843   op[1] = operands[1];
6844   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
6845
6846   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6847   switch (get_attr_length (insn))
6848     {
6849     case 4:  return \"b%d0\\t%l3\";
6850     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6851     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6852     }
6853   }"
6854   [(set (attr "far_jump")
6855         (if_then_else
6856             (eq_attr "length" "8")
6857             (const_string "yes")
6858             (const_string "no")))
6859    (set (attr "length") 
6860         (if_then_else
6861             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6862                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6863             (const_int 4)
6864             (if_then_else
6865                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6866                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6867                 (const_int 6)
6868                 (const_int 8))))]
6869 )
6870   
6871 (define_insn "*tlobits_cbranch"
6872   [(set (pc)
6873         (if_then_else
6874          (match_operator 0 "equality_operator"
6875           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6876                             (match_operand:SI 2 "const_int_operand" "i")
6877                             (const_int 0))
6878            (const_int 0)])
6879          (label_ref (match_operand 3 "" ""))
6880          (pc)))
6881    (clobber (match_scratch:SI 4 "=l"))]
6882   "TARGET_THUMB1"
6883   "*
6884   {
6885   rtx op[3];
6886   op[0] = operands[4];
6887   op[1] = operands[1];
6888   op[2] = GEN_INT (32 - INTVAL (operands[2]));
6889
6890   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6891   switch (get_attr_length (insn))
6892     {
6893     case 4:  return \"b%d0\\t%l3\";
6894     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6895     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6896     }
6897   }"
6898   [(set (attr "far_jump")
6899         (if_then_else
6900             (eq_attr "length" "8")
6901             (const_string "yes")
6902             (const_string "no")))
6903    (set (attr "length") 
6904         (if_then_else
6905             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6906                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6907             (const_int 4)
6908             (if_then_else
6909                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6910                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6911                 (const_int 6)
6912                 (const_int 8))))]
6913 )
6914   
6915 (define_insn "*tstsi3_cbranch"
6916   [(set (pc)
6917         (if_then_else
6918          (match_operator 3 "equality_operator"
6919           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
6920                    (match_operand:SI 1 "s_register_operand" "l"))
6921            (const_int 0)])
6922          (label_ref (match_operand 2 "" ""))
6923          (pc)))]
6924   "TARGET_THUMB1"
6925   "*
6926   {
6927   output_asm_insn (\"tst\\t%0, %1\", operands);
6928   switch (get_attr_length (insn))
6929     {
6930     case 4:  return \"b%d3\\t%l2\";
6931     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6932     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
6933     }
6934   }"
6935   [(set (attr "far_jump")
6936         (if_then_else
6937             (eq_attr "length" "8")
6938             (const_string "yes")
6939             (const_string "no")))
6940    (set (attr "length") 
6941         (if_then_else
6942             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6943                  (le (minus (match_dup 2) (pc)) (const_int 256)))
6944             (const_int 4)
6945             (if_then_else
6946                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6947                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
6948                 (const_int 6)
6949                 (const_int 8))))]
6950 )
6951   
6952 (define_insn "*andsi3_cbranch"
6953   [(set (pc)
6954         (if_then_else
6955          (match_operator 5 "equality_operator"
6956           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6957                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6958            (const_int 0)])
6959          (label_ref (match_operand 4 "" ""))
6960          (pc)))
6961    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6962         (and:SI (match_dup 2) (match_dup 3)))
6963    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6964   "TARGET_THUMB1"
6965   "*
6966   {
6967   if (which_alternative == 0)
6968     output_asm_insn (\"and\\t%0, %3\", operands);
6969   else if (which_alternative == 1)
6970     {
6971       output_asm_insn (\"and\\t%1, %3\", operands);
6972       output_asm_insn (\"mov\\t%0, %1\", operands);
6973     }
6974   else
6975     {
6976       output_asm_insn (\"and\\t%1, %3\", operands);
6977       output_asm_insn (\"str\\t%1, %0\", operands);
6978     }
6979
6980   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6981     {
6982     case 4:  return \"b%d5\\t%l4\";
6983     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6984     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6985     }
6986   }"
6987   [(set (attr "far_jump")
6988         (if_then_else
6989             (ior (and (eq (symbol_ref ("which_alternative"))
6990                           (const_int 0))
6991                       (eq_attr "length" "8"))
6992                  (eq_attr "length" "10"))
6993             (const_string "yes")
6994             (const_string "no")))
6995    (set (attr "length")
6996      (if_then_else
6997        (eq (symbol_ref ("which_alternative"))
6998                        (const_int 0))
6999        (if_then_else
7000          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7001               (le (minus (match_dup 4) (pc)) (const_int 256)))
7002          (const_int 4)
7003          (if_then_else
7004            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7005                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7006            (const_int 6)
7007            (const_int 8)))
7008        (if_then_else
7009          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7010               (le (minus (match_dup 4) (pc)) (const_int 256)))
7011          (const_int 6)
7012          (if_then_else
7013            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7014                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7015            (const_int 8)
7016            (const_int 10)))))]
7017 )
7018
7019 (define_insn "*orrsi3_cbranch_scratch"
7020   [(set (pc)
7021         (if_then_else
7022          (match_operator 4 "equality_operator"
7023           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
7024                    (match_operand:SI 2 "s_register_operand" "l"))
7025            (const_int 0)])
7026          (label_ref (match_operand 3 "" ""))
7027          (pc)))
7028    (clobber (match_scratch:SI 0 "=l"))]
7029   "TARGET_THUMB1"
7030   "*
7031   {
7032   output_asm_insn (\"orr\\t%0, %2\", operands);
7033   switch (get_attr_length (insn))
7034     {
7035     case 4:  return \"b%d4\\t%l3\";
7036     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7037     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7038     }
7039   }"
7040   [(set (attr "far_jump")
7041         (if_then_else
7042             (eq_attr "length" "8")
7043             (const_string "yes")
7044             (const_string "no")))
7045    (set (attr "length") 
7046         (if_then_else
7047             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7048                  (le (minus (match_dup 3) (pc)) (const_int 256)))
7049             (const_int 4)
7050             (if_then_else
7051                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7052                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
7053                 (const_int 6)
7054                 (const_int 8))))]
7055 )
7056   
7057 (define_insn "*orrsi3_cbranch"
7058   [(set (pc)
7059         (if_then_else
7060          (match_operator 5 "equality_operator"
7061           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
7062                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7063            (const_int 0)])
7064          (label_ref (match_operand 4 "" ""))
7065          (pc)))
7066    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
7067         (ior:SI (match_dup 2) (match_dup 3)))
7068    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
7069   "TARGET_THUMB1"
7070   "*
7071   {
7072   if (which_alternative == 0)
7073     output_asm_insn (\"orr\\t%0, %3\", operands);
7074   else if (which_alternative == 1)
7075     {
7076       output_asm_insn (\"orr\\t%1, %3\", operands);
7077       output_asm_insn (\"mov\\t%0, %1\", operands);
7078     }
7079   else
7080     {
7081       output_asm_insn (\"orr\\t%1, %3\", operands);
7082       output_asm_insn (\"str\\t%1, %0\", operands);
7083     }
7084
7085   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7086     {
7087     case 4:  return \"b%d5\\t%l4\";
7088     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7089     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7090     }
7091   }"
7092   [(set (attr "far_jump")
7093         (if_then_else
7094             (ior (and (eq (symbol_ref ("which_alternative"))
7095                           (const_int 0))
7096                       (eq_attr "length" "8"))
7097                  (eq_attr "length" "10"))
7098             (const_string "yes")
7099             (const_string "no")))
7100    (set (attr "length")
7101      (if_then_else
7102        (eq (symbol_ref ("which_alternative"))
7103                        (const_int 0))
7104        (if_then_else
7105          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7106               (le (minus (match_dup 4) (pc)) (const_int 256)))
7107          (const_int 4)
7108          (if_then_else
7109            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7110                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7111            (const_int 6)
7112            (const_int 8)))
7113        (if_then_else
7114          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7115               (le (minus (match_dup 4) (pc)) (const_int 256)))
7116          (const_int 6)
7117          (if_then_else
7118            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7119                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7120            (const_int 8)
7121            (const_int 10)))))]
7122 )
7123
7124 (define_insn "*xorsi3_cbranch_scratch"
7125   [(set (pc)
7126         (if_then_else
7127          (match_operator 4 "equality_operator"
7128           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
7129                    (match_operand:SI 2 "s_register_operand" "l"))
7130            (const_int 0)])
7131          (label_ref (match_operand 3 "" ""))
7132          (pc)))
7133    (clobber (match_scratch:SI 0 "=l"))]
7134   "TARGET_THUMB1"
7135   "*
7136   {
7137   output_asm_insn (\"eor\\t%0, %2\", operands);
7138   switch (get_attr_length (insn))
7139     {
7140     case 4:  return \"b%d4\\t%l3\";
7141     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7142     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7143     }
7144   }"
7145   [(set (attr "far_jump")
7146         (if_then_else
7147             (eq_attr "length" "8")
7148             (const_string "yes")
7149             (const_string "no")))
7150    (set (attr "length") 
7151         (if_then_else
7152             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7153                  (le (minus (match_dup 3) (pc)) (const_int 256)))
7154             (const_int 4)
7155             (if_then_else
7156                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7157                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
7158                 (const_int 6)
7159                 (const_int 8))))]
7160 )
7161   
7162 (define_insn "*xorsi3_cbranch"
7163   [(set (pc)
7164         (if_then_else
7165          (match_operator 5 "equality_operator"
7166           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
7167                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7168            (const_int 0)])
7169          (label_ref (match_operand 4 "" ""))
7170          (pc)))
7171    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
7172         (xor:SI (match_dup 2) (match_dup 3)))
7173    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
7174   "TARGET_THUMB1"
7175   "*
7176   {
7177   if (which_alternative == 0)
7178     output_asm_insn (\"eor\\t%0, %3\", operands);
7179   else if (which_alternative == 1)
7180     {
7181       output_asm_insn (\"eor\\t%1, %3\", operands);
7182       output_asm_insn (\"mov\\t%0, %1\", operands);
7183     }
7184   else
7185     {
7186       output_asm_insn (\"eor\\t%1, %3\", operands);
7187       output_asm_insn (\"str\\t%1, %0\", operands);
7188     }
7189
7190   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7191     {
7192     case 4:  return \"b%d5\\t%l4\";
7193     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7194     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7195     }
7196   }"
7197   [(set (attr "far_jump")
7198         (if_then_else
7199             (ior (and (eq (symbol_ref ("which_alternative"))
7200                           (const_int 0))
7201                       (eq_attr "length" "8"))
7202                  (eq_attr "length" "10"))
7203             (const_string "yes")
7204             (const_string "no")))
7205    (set (attr "length")
7206      (if_then_else
7207        (eq (symbol_ref ("which_alternative"))
7208                        (const_int 0))
7209        (if_then_else
7210          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7211               (le (minus (match_dup 4) (pc)) (const_int 256)))
7212          (const_int 4)
7213          (if_then_else
7214            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7215                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7216            (const_int 6)
7217            (const_int 8)))
7218        (if_then_else
7219          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7220               (le (minus (match_dup 4) (pc)) (const_int 256)))
7221          (const_int 6)
7222          (if_then_else
7223            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7224                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7225            (const_int 8)
7226            (const_int 10)))))]
7227 )
7228
7229 (define_insn "*bicsi3_cbranch_scratch"
7230   [(set (pc)
7231         (if_then_else
7232          (match_operator 4 "equality_operator"
7233           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
7234                    (match_operand:SI 1 "s_register_operand" "0"))
7235            (const_int 0)])
7236          (label_ref (match_operand 3 "" ""))
7237          (pc)))
7238    (clobber (match_scratch:SI 0 "=l"))]
7239   "TARGET_THUMB1"
7240   "*
7241   {
7242   output_asm_insn (\"bic\\t%0, %2\", operands);
7243   switch (get_attr_length (insn))
7244     {
7245     case 4:  return \"b%d4\\t%l3\";
7246     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7247     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7248     }
7249   }"
7250   [(set (attr "far_jump")
7251         (if_then_else
7252             (eq_attr "length" "8")
7253             (const_string "yes")
7254             (const_string "no")))
7255    (set (attr "length") 
7256         (if_then_else
7257             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7258                  (le (minus (match_dup 3) (pc)) (const_int 256)))
7259             (const_int 4)
7260             (if_then_else
7261                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7262                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
7263                 (const_int 6)
7264                 (const_int 8))))]
7265 )
7266   
7267 (define_insn "*bicsi3_cbranch"
7268   [(set (pc)
7269         (if_then_else
7270          (match_operator 5 "equality_operator"
7271           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
7272                    (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
7273            (const_int 0)])
7274          (label_ref (match_operand 4 "" ""))
7275          (pc)))
7276    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
7277         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
7278    (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
7279   "TARGET_THUMB1"
7280   "*
7281   {
7282   if (which_alternative == 0)
7283     output_asm_insn (\"bic\\t%0, %3\", operands);
7284   else if (which_alternative <= 2)
7285     {
7286       output_asm_insn (\"bic\\t%1, %3\", operands);
7287       /* It's ok if OP0 is a lo-reg, even though the mov will set the
7288          conditions again, since we're only testing for equality.  */
7289       output_asm_insn (\"mov\\t%0, %1\", operands);
7290     }
7291   else
7292     {
7293       output_asm_insn (\"bic\\t%1, %3\", operands);
7294       output_asm_insn (\"str\\t%1, %0\", operands);
7295     }
7296
7297   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7298     {
7299     case 4:  return \"b%d5\\t%l4\";
7300     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7301     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7302     }
7303   }"
7304   [(set (attr "far_jump")
7305         (if_then_else
7306             (ior (and (eq (symbol_ref ("which_alternative"))
7307                           (const_int 0))
7308                       (eq_attr "length" "8"))
7309                  (eq_attr "length" "10"))
7310             (const_string "yes")
7311             (const_string "no")))
7312    (set (attr "length")
7313      (if_then_else
7314        (eq (symbol_ref ("which_alternative"))
7315                        (const_int 0))
7316        (if_then_else
7317          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7318               (le (minus (match_dup 4) (pc)) (const_int 256)))
7319          (const_int 4)
7320          (if_then_else
7321            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7322                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7323            (const_int 6)
7324            (const_int 8)))
7325        (if_then_else
7326          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7327               (le (minus (match_dup 4) (pc)) (const_int 256)))
7328          (const_int 6)
7329          (if_then_else
7330            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7331                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7332            (const_int 8)
7333            (const_int 10)))))]
7334 )
7335
7336 (define_insn "*cbranchne_decr1"
7337   [(set (pc)
7338         (if_then_else (match_operator 3 "equality_operator"
7339                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
7340                         (const_int 0)])
7341                       (label_ref (match_operand 4 "" ""))
7342                       (pc)))
7343    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
7344         (plus:SI (match_dup 2) (const_int -1)))
7345    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
7346   "TARGET_THUMB1"
7347   "*
7348    {
7349      rtx cond[2];
7350      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
7351                                 ? GEU : LTU),
7352                                VOIDmode, operands[2], const1_rtx);
7353      cond[1] = operands[4];
7354
7355      if (which_alternative == 0)
7356        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
7357      else if (which_alternative == 1)
7358        {
7359          /* We must provide an alternative for a hi reg because reload 
7360             cannot handle output reloads on a jump instruction, but we
7361             can't subtract into that.  Fortunately a mov from lo to hi
7362             does not clobber the condition codes.  */
7363          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7364          output_asm_insn (\"mov\\t%0, %1\", operands);
7365        }
7366      else
7367        {
7368          /* Similarly, but the target is memory.  */
7369          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7370          output_asm_insn (\"str\\t%1, %0\", operands);
7371        }
7372
7373      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7374        {
7375          case 4:
7376            output_asm_insn (\"b%d0\\t%l1\", cond);
7377            return \"\";
7378          case 6:
7379            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
7380            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
7381          default:
7382            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
7383            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7384        }
7385    }
7386   "
7387   [(set (attr "far_jump")
7388         (if_then_else
7389             (ior (and (eq (symbol_ref ("which_alternative"))
7390                           (const_int 0))
7391                       (eq_attr "length" "8"))
7392                  (eq_attr "length" "10"))
7393             (const_string "yes")
7394             (const_string "no")))
7395    (set_attr_alternative "length"
7396       [
7397        ;; Alternative 0
7398        (if_then_else
7399          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7400               (le (minus (match_dup 4) (pc)) (const_int 256)))
7401          (const_int 4)
7402          (if_then_else
7403            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7404                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7405            (const_int 6)
7406            (const_int 8)))
7407        ;; Alternative 1
7408        (if_then_else
7409          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7410               (le (minus (match_dup 4) (pc)) (const_int 256)))
7411          (const_int 6)
7412          (if_then_else
7413            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7414                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7415            (const_int 8)
7416            (const_int 10)))
7417        ;; Alternative 2
7418        (if_then_else
7419          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7420               (le (minus (match_dup 4) (pc)) (const_int 256)))
7421          (const_int 6)
7422          (if_then_else
7423            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7424                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7425            (const_int 8)
7426            (const_int 10)))
7427        ;; Alternative 3
7428        (if_then_else
7429          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7430               (le (minus (match_dup 4) (pc)) (const_int 256)))
7431          (const_int 6)
7432          (if_then_else
7433            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7434                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7435            (const_int 8)
7436            (const_int 10)))])]
7437 )
7438
7439 (define_insn "*addsi3_cbranch"
7440   [(set (pc)
7441         (if_then_else
7442          (match_operator 4 "arm_comparison_operator"
7443           [(plus:SI
7444             (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
7445             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
7446            (const_int 0)])
7447          (label_ref (match_operand 5 "" ""))
7448          (pc)))
7449    (set
7450     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
7451     (plus:SI (match_dup 2) (match_dup 3)))
7452    (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
7453   "TARGET_THUMB1
7454    && (GET_CODE (operands[4]) == EQ
7455        || GET_CODE (operands[4]) == NE
7456        || GET_CODE (operands[4]) == GE
7457        || GET_CODE (operands[4]) == LT)"
7458   "*
7459    {
7460      rtx cond[3];
7461
7462      
7463      cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
7464      cond[1] = operands[2];
7465      cond[2] = operands[3];
7466
7467      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
7468        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
7469      else
7470        output_asm_insn (\"add\\t%0, %1, %2\", cond);
7471
7472      if (which_alternative >= 3
7473          && which_alternative < 4)
7474        output_asm_insn (\"mov\\t%0, %1\", operands);
7475      else if (which_alternative >= 4)
7476        output_asm_insn (\"str\\t%1, %0\", operands);
7477
7478      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
7479        {
7480          case 4:
7481            return \"b%d4\\t%l5\";
7482          case 6:
7483            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7484          default:
7485            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7486        }
7487    }
7488   "
7489   [(set (attr "far_jump")
7490         (if_then_else
7491             (ior (and (lt (symbol_ref ("which_alternative"))
7492                           (const_int 3))
7493                       (eq_attr "length" "8"))
7494                  (eq_attr "length" "10"))
7495             (const_string "yes")
7496             (const_string "no")))
7497    (set (attr "length")
7498      (if_then_else
7499        (lt (symbol_ref ("which_alternative"))
7500                        (const_int 3))
7501        (if_then_else
7502          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7503               (le (minus (match_dup 5) (pc)) (const_int 256)))
7504          (const_int 4)
7505          (if_then_else
7506            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7507                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7508            (const_int 6)
7509            (const_int 8)))
7510        (if_then_else
7511          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7512               (le (minus (match_dup 5) (pc)) (const_int 256)))
7513          (const_int 6)
7514          (if_then_else
7515            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7516                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7517            (const_int 8)
7518            (const_int 10)))))]
7519 )
7520
7521 (define_insn "*addsi3_cbranch_scratch"
7522   [(set (pc)
7523         (if_then_else
7524          (match_operator 3 "arm_comparison_operator"
7525           [(plus:SI
7526             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
7527             (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
7528            (const_int 0)])
7529          (label_ref (match_operand 4 "" ""))
7530          (pc)))
7531    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
7532   "TARGET_THUMB1
7533    && (GET_CODE (operands[3]) == EQ
7534        || GET_CODE (operands[3]) == NE
7535        || GET_CODE (operands[3]) == GE
7536        || GET_CODE (operands[3]) == LT)"
7537   "*
7538    {
7539      switch (which_alternative)
7540        {
7541        case 0:
7542          output_asm_insn (\"cmp\t%1, #%n2\", operands);
7543          break;
7544        case 1:
7545          output_asm_insn (\"cmn\t%1, %2\", operands);
7546          break;
7547        case 2:
7548          if (INTVAL (operands[2]) < 0)
7549            output_asm_insn (\"sub\t%0, %1, %2\", operands);
7550          else
7551            output_asm_insn (\"add\t%0, %1, %2\", operands);
7552          break;
7553        case 3:
7554          if (INTVAL (operands[2]) < 0)
7555            output_asm_insn (\"sub\t%0, %0, %2\", operands);
7556          else
7557            output_asm_insn (\"add\t%0, %0, %2\", operands);
7558          break;
7559        }
7560
7561      switch (get_attr_length (insn))
7562        {
7563          case 4:
7564            return \"b%d3\\t%l4\";
7565          case 6:
7566            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7567          default:
7568            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7569        }
7570    }
7571   "
7572   [(set (attr "far_jump")
7573         (if_then_else
7574             (eq_attr "length" "8")
7575             (const_string "yes")
7576             (const_string "no")))
7577    (set (attr "length")
7578        (if_then_else
7579          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7580               (le (minus (match_dup 4) (pc)) (const_int 256)))
7581          (const_int 4)
7582          (if_then_else
7583            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7584                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7585            (const_int 6)
7586            (const_int 8))))]
7587 )
7588
7589 (define_insn "*subsi3_cbranch"
7590   [(set (pc)
7591         (if_then_else
7592          (match_operator 4 "arm_comparison_operator"
7593           [(minus:SI
7594             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
7595             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
7596            (const_int 0)])
7597          (label_ref (match_operand 5 "" ""))
7598          (pc)))
7599    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
7600         (minus:SI (match_dup 2) (match_dup 3)))
7601    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
7602   "TARGET_THUMB1
7603    && (GET_CODE (operands[4]) == EQ
7604        || GET_CODE (operands[4]) == NE
7605        || GET_CODE (operands[4]) == GE
7606        || GET_CODE (operands[4]) == LT)"
7607   "*
7608    {
7609      if (which_alternative == 0)
7610        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
7611      else if (which_alternative == 1)
7612        {
7613          /* We must provide an alternative for a hi reg because reload 
7614             cannot handle output reloads on a jump instruction, but we
7615             can't subtract into that.  Fortunately a mov from lo to hi
7616             does not clobber the condition codes.  */
7617          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
7618          output_asm_insn (\"mov\\t%0, %1\", operands);
7619        }
7620      else
7621        {
7622          /* Similarly, but the target is memory.  */
7623          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
7624          output_asm_insn (\"str\\t%1, %0\", operands);
7625        }
7626
7627      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
7628        {
7629          case 4:
7630            return \"b%d4\\t%l5\";
7631          case 6:
7632            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7633          default:
7634            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7635        }
7636    }
7637   "
7638   [(set (attr "far_jump")
7639         (if_then_else
7640             (ior (and (eq (symbol_ref ("which_alternative"))
7641                           (const_int 0))
7642                       (eq_attr "length" "8"))
7643                  (eq_attr "length" "10"))
7644             (const_string "yes")
7645             (const_string "no")))
7646    (set (attr "length")
7647      (if_then_else
7648        (eq (symbol_ref ("which_alternative"))
7649                        (const_int 0))
7650        (if_then_else
7651          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7652               (le (minus (match_dup 5) (pc)) (const_int 256)))
7653          (const_int 4)
7654          (if_then_else
7655            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7656                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7657            (const_int 6)
7658            (const_int 8)))
7659        (if_then_else
7660          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7661               (le (minus (match_dup 5) (pc)) (const_int 256)))
7662          (const_int 6)
7663          (if_then_else
7664            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7665                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7666            (const_int 8)
7667            (const_int 10)))))]
7668 )
7669
7670 (define_insn "*subsi3_cbranch_scratch"
7671   [(set (pc)
7672         (if_then_else
7673          (match_operator 0 "arm_comparison_operator"
7674           [(minus:SI (match_operand:SI 1 "register_operand" "l")
7675                      (match_operand:SI 2 "nonmemory_operand" "l"))
7676            (const_int 0)])
7677          (label_ref (match_operand 3 "" ""))
7678          (pc)))]
7679   "TARGET_THUMB1
7680    && (GET_CODE (operands[0]) == EQ
7681        || GET_CODE (operands[0]) == NE
7682        || GET_CODE (operands[0]) == GE
7683        || GET_CODE (operands[0]) == LT)"
7684   "*
7685   output_asm_insn (\"cmp\\t%1, %2\", operands);
7686   switch (get_attr_length (insn))
7687     {
7688     case 4:  return \"b%d0\\t%l3\";
7689     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7690     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7691     }
7692   "
7693   [(set (attr "far_jump")
7694         (if_then_else
7695             (eq_attr "length" "8")
7696             (const_string "yes")
7697             (const_string "no")))
7698    (set (attr "length") 
7699         (if_then_else
7700             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7701                  (le (minus (match_dup 3) (pc)) (const_int 256)))
7702             (const_int 4)
7703             (if_then_else
7704                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7705                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
7706                 (const_int 6)
7707                 (const_int 8))))]
7708 )
7709
7710 ;; Comparison and test insns
7711
7712 (define_insn "*arm_cmpsi_insn"
7713   [(set (reg:CC CC_REGNUM)
7714         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
7715                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
7716   "TARGET_32BIT"
7717   "@
7718    cmp%?\\t%0, %1
7719    cmn%?\\t%0, #%n1"
7720   [(set_attr "conds" "set")]
7721 )
7722
7723 (define_insn "*arm_cmpsi_shiftsi"
7724   [(set (reg:CC CC_REGNUM)
7725         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
7726                     (match_operator:SI  3 "shift_operator"
7727                      [(match_operand:SI 1 "s_register_operand" "r")
7728                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
7729   "TARGET_ARM"
7730   "cmp%?\\t%0, %1%S3"
7731   [(set_attr "conds" "set")
7732    (set_attr "shift" "1")
7733    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
7734                       (const_string "alu_shift")
7735                       (const_string "alu_shift_reg")))]
7736 )
7737
7738 (define_insn "*arm_cmpsi_shiftsi_swp"
7739   [(set (reg:CC_SWP CC_REGNUM)
7740         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
7741                          [(match_operand:SI 1 "s_register_operand" "r")
7742                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
7743                         (match_operand:SI 0 "s_register_operand" "r")))]
7744   "TARGET_ARM"
7745   "cmp%?\\t%0, %1%S3"
7746   [(set_attr "conds" "set")
7747    (set_attr "shift" "1")
7748    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
7749                       (const_string "alu_shift")
7750                       (const_string "alu_shift_reg")))]
7751 )
7752
7753 (define_insn "*arm_cmpsi_negshiftsi_si"
7754   [(set (reg:CC_Z CC_REGNUM)
7755         (compare:CC_Z
7756          (neg:SI (match_operator:SI 1 "shift_operator"
7757                     [(match_operand:SI 2 "s_register_operand" "r")
7758                      (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7759          (match_operand:SI 0 "s_register_operand" "r")))]
7760   "TARGET_ARM"
7761   "cmn%?\\t%0, %2%S1"
7762   [(set_attr "conds" "set")
7763    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7764                                     (const_string "alu_shift")
7765                                     (const_string "alu_shift_reg")))]
7766 )
7767
7768 ;; Cirrus SF compare instruction
7769 (define_insn "*cirrus_cmpsf"
7770   [(set (reg:CCFP CC_REGNUM)
7771         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
7772                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
7773   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7774   "cfcmps%?\\tr15, %V0, %V1"
7775   [(set_attr "type"   "mav_farith")
7776    (set_attr "cirrus" "compare")]
7777 )
7778
7779 ;; Cirrus DF compare instruction
7780 (define_insn "*cirrus_cmpdf"
7781   [(set (reg:CCFP CC_REGNUM)
7782         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
7783                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
7784   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7785   "cfcmpd%?\\tr15, %V0, %V1"
7786   [(set_attr "type"   "mav_farith")
7787    (set_attr "cirrus" "compare")]
7788 )
7789
7790 (define_insn "*cirrus_cmpdi"
7791   [(set (reg:CC CC_REGNUM)
7792         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
7793                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
7794   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7795   "cfcmp64%?\\tr15, %V0, %V1"
7796   [(set_attr "type"   "mav_farith")
7797    (set_attr "cirrus" "compare")]
7798 )
7799
7800 ; This insn allows redundant compares to be removed by cse, nothing should
7801 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7802 ; is deleted later on. The match_dup will match the mode here, so that
7803 ; mode changes of the condition codes aren't lost by this even though we don't
7804 ; specify what they are.
7805
7806 (define_insn "*deleted_compare"
7807   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
7808   "TARGET_32BIT"
7809   "\\t%@ deleted compare"
7810   [(set_attr "conds" "set")
7811    (set_attr "length" "0")]
7812 )
7813
7814 \f
7815 ;; Conditional branch insns
7816
7817 (define_expand "cbranch_cc"
7818   [(set (pc)
7819         (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7820                                             (match_operand 2 "" "")])
7821                       (label_ref (match_operand 3 "" ""))
7822                       (pc)))]
7823   "TARGET_32BIT"
7824   "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
7825                                       operands[1], operands[2]);
7826    operands[2] = const0_rtx;"
7827 )
7828
7829 ;;
7830 ;; Patterns to match conditional branch insns.
7831 ;;
7832
7833 (define_insn "*arm_cond_branch"
7834   [(set (pc)
7835         (if_then_else (match_operator 1 "arm_comparison_operator"
7836                        [(match_operand 2 "cc_register" "") (const_int 0)])
7837                       (label_ref (match_operand 0 "" ""))
7838                       (pc)))]
7839   "TARGET_32BIT"
7840   "*
7841   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7842     {
7843       arm_ccfsm_state += 2;
7844       return \"\";
7845     }
7846   return \"b%d1\\t%l0\";
7847   "
7848   [(set_attr "conds" "use")
7849    (set_attr "type" "branch")]
7850 )
7851
7852 (define_insn "*arm_cond_branch_reversed"
7853   [(set (pc)
7854         (if_then_else (match_operator 1 "arm_comparison_operator"
7855                        [(match_operand 2 "cc_register" "") (const_int 0)])
7856                       (pc)
7857                       (label_ref (match_operand 0 "" ""))))]
7858   "TARGET_32BIT"
7859   "*
7860   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7861     {
7862       arm_ccfsm_state += 2;
7863       return \"\";
7864     }
7865   return \"b%D1\\t%l0\";
7866   "
7867   [(set_attr "conds" "use")
7868    (set_attr "type" "branch")]
7869 )
7870
7871 \f
7872
7873 ; scc insns
7874
7875 (define_expand "cstore_cc"
7876   [(set (match_operand:SI 0 "s_register_operand" "")
7877         (match_operator:SI 1 "" [(match_operand 2 "" "")
7878                                  (match_operand 3 "" "")]))]
7879   "TARGET_32BIT"
7880   "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
7881                                       operands[2], operands[3]);
7882    operands[3] = const0_rtx;"
7883 )
7884
7885 (define_insn "*mov_scc"
7886   [(set (match_operand:SI 0 "s_register_operand" "=r")
7887         (match_operator:SI 1 "arm_comparison_operator"
7888          [(match_operand 2 "cc_register" "") (const_int 0)]))]
7889   "TARGET_ARM"
7890   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7891   [(set_attr "conds" "use")
7892    (set_attr "length" "8")]
7893 )
7894
7895 (define_insn "*mov_negscc"
7896   [(set (match_operand:SI 0 "s_register_operand" "=r")
7897         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7898                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7899   "TARGET_ARM"
7900   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7901   [(set_attr "conds" "use")
7902    (set_attr "length" "8")]
7903 )
7904
7905 (define_insn "*mov_notscc"
7906   [(set (match_operand:SI 0 "s_register_operand" "=r")
7907         (not:SI (match_operator:SI 1 "arm_comparison_operator"
7908                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7909   "TARGET_ARM"
7910   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7911   [(set_attr "conds" "use")
7912    (set_attr "length" "8")]
7913 )
7914
7915 (define_expand "cstoresi4"
7916   [(set (match_operand:SI 0 "s_register_operand" "")
7917         (match_operator:SI 1 "arm_comparison_operator"
7918          [(match_operand:SI 2 "s_register_operand" "")
7919           (match_operand:SI 3 "reg_or_int_operand" "")]))]
7920   "TARGET_32BIT || TARGET_THUMB1"
7921   "{
7922   rtx op3, scratch, scratch2;
7923
7924   if (!TARGET_THUMB1)
7925     {
7926       if (!arm_add_operand (operands[3], SImode))
7927         operands[3] = force_reg (SImode, operands[3]);
7928       emit_insn (gen_cstore_cc (operands[0], operands[1],
7929                                 operands[2], operands[3]));
7930       DONE;
7931     }
7932
7933   if (operands[3] == const0_rtx)
7934     {
7935       switch (GET_CODE (operands[1]))
7936         {
7937         case EQ:
7938           emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
7939           break;
7940
7941         case NE:
7942           emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
7943           break;
7944
7945         case LE:
7946           scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7947                                   NULL_RTX, 0, OPTAB_WIDEN);
7948           scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7949                                   NULL_RTX, 0, OPTAB_WIDEN);
7950           expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7951                         operands[0], 1, OPTAB_WIDEN);
7952           break;
7953
7954         case GE:
7955           scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7956                                  NULL_RTX, 1);
7957           expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7958                         NULL_RTX, 1, OPTAB_WIDEN);
7959           break;
7960
7961         case GT:
7962           scratch = expand_binop (SImode, ashr_optab, operands[2],
7963                                   GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7964           scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7965                                   NULL_RTX, 0, OPTAB_WIDEN);
7966           expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7967                         0, OPTAB_WIDEN);
7968           break;
7969
7970         /* LT is handled by generic code.  No need for unsigned with 0.  */
7971         default:
7972           FAIL;
7973         }
7974       DONE;
7975     }
7976
7977   switch (GET_CODE (operands[1]))
7978     {
7979     case EQ:
7980       scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7981                               NULL_RTX, 0, OPTAB_WIDEN);
7982       emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
7983       break;
7984
7985     case NE:
7986       scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7987                               NULL_RTX, 0, OPTAB_WIDEN);
7988       emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
7989       break;
7990
7991     case LE:
7992       op3 = force_reg (SImode, operands[3]);
7993
7994       scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7995                               NULL_RTX, 1, OPTAB_WIDEN);
7996       scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7997                               NULL_RTX, 0, OPTAB_WIDEN);
7998       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
7999                                           op3, operands[2]));
8000       break;
8001
8002     case GE:
8003       op3 = operands[3];
8004       if (!thumb1_cmp_operand (op3, SImode))
8005         op3 = force_reg (SImode, op3);
8006       scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
8007                               NULL_RTX, 0, OPTAB_WIDEN);
8008       scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
8009                                NULL_RTX, 1, OPTAB_WIDEN);
8010       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
8011                                           operands[2], op3));
8012       break;
8013
8014     case LEU:
8015       op3 = force_reg (SImode, operands[3]);
8016       scratch = force_reg (SImode, const0_rtx);
8017       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
8018                                           op3, operands[2]));
8019       break;
8020
8021     case GEU:
8022       op3 = operands[3];
8023       if (!thumb1_cmp_operand (op3, SImode))
8024         op3 = force_reg (SImode, op3);
8025       scratch = force_reg (SImode, const0_rtx);
8026       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
8027                                           operands[2], op3));
8028       break;
8029
8030     case LTU:
8031       op3 = operands[3];
8032       if (!thumb1_cmp_operand (op3, SImode))
8033         op3 = force_reg (SImode, op3);
8034       scratch = gen_reg_rtx (SImode);
8035       emit_insn (gen_cstoresi_nltu_thumb1 (scratch, operands[2], op3));
8036       emit_insn (gen_negsi2 (operands[0], scratch));
8037       break;
8038
8039     case GTU:
8040       op3 = force_reg (SImode, operands[3]);
8041       scratch = gen_reg_rtx (SImode);
8042       emit_insn (gen_cstoresi_nltu_thumb1 (scratch, op3, operands[2]));
8043       emit_insn (gen_negsi2 (operands[0], scratch));
8044       break;
8045
8046     /* No good sequences for GT, LT.  */
8047     default:
8048       FAIL;
8049     }
8050   DONE;
8051 }")
8052
8053 (define_expand "cstoresf4"
8054   [(set (match_operand:SI 0 "s_register_operand" "")
8055         (match_operator:SI 1 "arm_comparison_operator"
8056          [(match_operand:SF 2 "s_register_operand" "")
8057           (match_operand:SF 3 "arm_float_compare_operand" "")]))]
8058   "TARGET_32BIT && TARGET_HARD_FLOAT"
8059   "emit_insn (gen_cstore_cc (operands[0], operands[1],
8060                              operands[2], operands[3])); DONE;"
8061 )
8062
8063 (define_expand "cstoredf4"
8064   [(set (match_operand:SI 0 "s_register_operand" "")
8065         (match_operator:SI 1 "arm_comparison_operator"
8066          [(match_operand:DF 2 "s_register_operand" "")
8067           (match_operand:DF 3 "arm_float_compare_operand" "")]))]
8068   "TARGET_32BIT && TARGET_HARD_FLOAT"
8069   "emit_insn (gen_cstore_cc (operands[0], operands[1],
8070                              operands[2], operands[3])); DONE;"
8071 )
8072
8073 ;; this uses the Cirrus DI compare instruction
8074 (define_expand "cstoredi4"
8075   [(set (match_operand:SI 0 "s_register_operand" "")
8076         (match_operator:SI 1 "arm_comparison_operator"
8077          [(match_operand:DI 2 "cirrus_fp_register" "")
8078           (match_operand:DI 3 "cirrus_fp_register" "")]))]
8079   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
8080   "emit_insn (gen_cstore_cc (operands[0], operands[1],
8081                              operands[2], operands[3])); DONE;"
8082 )
8083
8084
8085 (define_expand "cstoresi_eq0_thumb1"
8086   [(parallel
8087     [(set (match_operand:SI 0 "s_register_operand" "")
8088           (eq:SI (match_operand:SI 1 "s_register_operand" "")
8089                  (const_int 0)))
8090      (clobber (match_dup:SI 2))])]
8091   "TARGET_THUMB1"
8092   "operands[2] = gen_reg_rtx (SImode);"
8093 )
8094
8095 (define_expand "cstoresi_ne0_thumb1"
8096   [(parallel
8097     [(set (match_operand:SI 0 "s_register_operand" "")
8098           (ne:SI (match_operand:SI 1 "s_register_operand" "")
8099                  (const_int 0)))
8100      (clobber (match_dup:SI 2))])]
8101   "TARGET_THUMB1"
8102   "operands[2] = gen_reg_rtx (SImode);"
8103 )
8104
8105 (define_insn "*cstoresi_eq0_thumb1_insn"
8106   [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
8107         (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
8108                (const_int 0)))
8109    (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
8110   "TARGET_THUMB1"
8111   "@
8112    neg\\t%0, %1\;adc\\t%0, %0, %1
8113    neg\\t%2, %1\;adc\\t%0, %1, %2"
8114   [(set_attr "length" "4")]
8115 )
8116
8117 (define_insn "*cstoresi_ne0_thumb1_insn"
8118   [(set (match_operand:SI 0 "s_register_operand" "=l")
8119         (ne:SI (match_operand:SI 1 "s_register_operand" "0")
8120                (const_int 0)))
8121    (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
8122   "TARGET_THUMB1"
8123   "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
8124   [(set_attr "length" "4")]
8125 )
8126
8127 (define_insn "cstoresi_nltu_thumb1"
8128   [(set (match_operand:SI 0 "s_register_operand" "=l,l")
8129         (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
8130                         (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
8131   "TARGET_THUMB1"
8132   "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
8133   [(set_attr "length" "4")]
8134 )
8135
8136 ;; Used as part of the expansion of thumb les sequence.
8137 (define_insn "thumb1_addsi3_addgeu"
8138   [(set (match_operand:SI 0 "s_register_operand" "=l")
8139         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8140                           (match_operand:SI 2 "s_register_operand" "l"))
8141                  (geu:SI (match_operand:SI 3 "s_register_operand" "l")
8142                          (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
8143   "TARGET_THUMB1"
8144   "cmp\\t%3, %4\;adc\\t%0, %1, %2"
8145   [(set_attr "length" "4")]
8146 )
8147
8148 \f
8149 ;; Conditional move insns
8150
8151 (define_expand "movsicc"
8152   [(set (match_operand:SI 0 "s_register_operand" "")
8153         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
8154                          (match_operand:SI 2 "arm_not_operand" "")
8155                          (match_operand:SI 3 "arm_not_operand" "")))]
8156   "TARGET_32BIT"
8157   "
8158   {
8159     enum rtx_code code = GET_CODE (operands[1]);
8160     rtx ccreg;
8161
8162     if (code == UNEQ || code == LTGT)
8163       FAIL;
8164
8165     ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8166                                  XEXP (operands[1], 1));
8167     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
8168   }"
8169 )
8170
8171 (define_expand "movsfcc"
8172   [(set (match_operand:SF 0 "s_register_operand" "")
8173         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
8174                          (match_operand:SF 2 "s_register_operand" "")
8175                          (match_operand:SF 3 "nonmemory_operand" "")))]
8176   "TARGET_32BIT && TARGET_HARD_FLOAT"
8177   "
8178   {
8179     enum rtx_code code = GET_CODE (operands[1]);
8180     rtx ccreg;
8181
8182     if (code == UNEQ || code == LTGT)
8183       FAIL;
8184
8185     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
8186        Otherwise, ensure it is a valid FP add operand */
8187     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
8188         || (!arm_float_add_operand (operands[3], SFmode)))
8189       operands[3] = force_reg (SFmode, operands[3]);
8190
8191     ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8192                                  XEXP (operands[1], 1));
8193     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
8194   }"
8195 )
8196
8197 (define_expand "movdfcc"
8198   [(set (match_operand:DF 0 "s_register_operand" "")
8199         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
8200                          (match_operand:DF 2 "s_register_operand" "")
8201                          (match_operand:DF 3 "arm_float_add_operand" "")))]
8202   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8203   "
8204   {
8205     enum rtx_code code = GET_CODE (operands[1]);
8206     rtx ccreg;
8207
8208     if (code == UNEQ || code == LTGT)
8209       FAIL;
8210
8211     ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8212                                  XEXP (operands[1], 1));
8213     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
8214   }"
8215 )
8216
8217 (define_insn "*movsicc_insn"
8218   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8219         (if_then_else:SI
8220          (match_operator 3 "arm_comparison_operator"
8221           [(match_operand 4 "cc_register" "") (const_int 0)])
8222          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
8223          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
8224   "TARGET_ARM"
8225   "@
8226    mov%D3\\t%0, %2
8227    mvn%D3\\t%0, #%B2
8228    mov%d3\\t%0, %1
8229    mvn%d3\\t%0, #%B1
8230    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
8231    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
8232    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
8233    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
8234   [(set_attr "length" "4,4,4,4,8,8,8,8")
8235    (set_attr "conds" "use")]
8236 )
8237
8238 (define_insn "*movsfcc_soft_insn"
8239   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8240         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8241                           [(match_operand 4 "cc_register" "") (const_int 0)])
8242                          (match_operand:SF 1 "s_register_operand" "0,r")
8243                          (match_operand:SF 2 "s_register_operand" "r,0")))]
8244   "TARGET_ARM && TARGET_SOFT_FLOAT"
8245   "@
8246    mov%D3\\t%0, %2
8247    mov%d3\\t%0, %1"
8248   [(set_attr "conds" "use")]
8249 )
8250
8251 \f
8252 ;; Jump and linkage insns
8253
8254 (define_expand "jump"
8255   [(set (pc)
8256         (label_ref (match_operand 0 "" "")))]
8257   "TARGET_EITHER"
8258   ""
8259 )
8260
8261 (define_insn "*arm_jump"
8262   [(set (pc)
8263         (label_ref (match_operand 0 "" "")))]
8264   "TARGET_32BIT"
8265   "*
8266   {
8267     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
8268       {
8269         arm_ccfsm_state += 2;
8270         return \"\";
8271       }
8272     return \"b%?\\t%l0\";
8273   }
8274   "
8275   [(set_attr "predicable" "yes")]
8276 )
8277
8278 (define_insn "*thumb_jump"
8279   [(set (pc)
8280         (label_ref (match_operand 0 "" "")))]
8281   "TARGET_THUMB1"
8282   "*
8283   if (get_attr_length (insn) == 2)
8284     return \"b\\t%l0\";
8285   return \"bl\\t%l0\\t%@ far jump\";
8286   "
8287   [(set (attr "far_jump")
8288         (if_then_else
8289             (eq_attr "length" "4")
8290             (const_string "yes")
8291             (const_string "no")))
8292    (set (attr "length") 
8293         (if_then_else
8294             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8295                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
8296             (const_int 2)
8297             (const_int 4)))]
8298 )
8299
8300 (define_expand "call"
8301   [(parallel [(call (match_operand 0 "memory_operand" "")
8302                     (match_operand 1 "general_operand" ""))
8303               (use (match_operand 2 "" ""))
8304               (clobber (reg:SI LR_REGNUM))])]
8305   "TARGET_EITHER"
8306   "
8307   {
8308     rtx callee, pat;
8309     
8310     /* In an untyped call, we can get NULL for operand 2.  */
8311     if (operands[2] == NULL_RTX)
8312       operands[2] = const0_rtx;
8313       
8314     /* Decide if we should generate indirect calls by loading the
8315        32-bit address of the callee into a register before performing the
8316        branch and link.  */
8317     callee = XEXP (operands[0], 0);
8318     if (GET_CODE (callee) == SYMBOL_REF
8319         ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8320         : !REG_P (callee))
8321       XEXP (operands[0], 0) = force_reg (Pmode, callee);
8322
8323     pat = gen_call_internal (operands[0], operands[1], operands[2]);
8324     arm_emit_call_insn (pat, XEXP (operands[0], 0));
8325     DONE;
8326   }"
8327 )
8328
8329 (define_expand "call_internal"
8330   [(parallel [(call (match_operand 0 "memory_operand" "")
8331                     (match_operand 1 "general_operand" ""))
8332               (use (match_operand 2 "" ""))
8333               (clobber (reg:SI LR_REGNUM))])])
8334
8335 (define_insn "*call_reg_armv5"
8336   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8337          (match_operand 1 "" ""))
8338    (use (match_operand 2 "" ""))
8339    (clobber (reg:SI LR_REGNUM))]
8340   "TARGET_ARM && arm_arch5"
8341   "blx%?\\t%0"
8342   [(set_attr "type" "call")]
8343 )
8344
8345 (define_insn "*call_reg_arm"
8346   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8347          (match_operand 1 "" ""))
8348    (use (match_operand 2 "" ""))
8349    (clobber (reg:SI LR_REGNUM))]
8350   "TARGET_ARM && !arm_arch5"
8351   "*
8352   return output_call (operands);
8353   "
8354   ;; length is worst case, normally it is only two
8355   [(set_attr "length" "12")
8356    (set_attr "type" "call")]
8357 )
8358
8359 (define_insn "*call_mem"
8360   [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
8361          (match_operand 1 "" ""))
8362    (use (match_operand 2 "" ""))
8363    (clobber (reg:SI LR_REGNUM))]
8364   "TARGET_ARM"
8365   "*
8366   return output_call_mem (operands);
8367   "
8368   [(set_attr "length" "12")
8369    (set_attr "type" "call")]
8370 )
8371
8372 (define_insn "*call_reg_thumb1_v5"
8373   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8374          (match_operand 1 "" ""))
8375    (use (match_operand 2 "" ""))
8376    (clobber (reg:SI LR_REGNUM))]
8377   "TARGET_THUMB1 && arm_arch5"
8378   "blx\\t%0"
8379   [(set_attr "length" "2")
8380    (set_attr "type" "call")]
8381 )
8382
8383 (define_insn "*call_reg_thumb1"
8384   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8385          (match_operand 1 "" ""))
8386    (use (match_operand 2 "" ""))
8387    (clobber (reg:SI LR_REGNUM))]
8388   "TARGET_THUMB1 && !arm_arch5"
8389   "*
8390   {
8391     if (!TARGET_CALLER_INTERWORKING)
8392       return thumb_call_via_reg (operands[0]);
8393     else if (operands[1] == const0_rtx)
8394       return \"bl\\t%__interwork_call_via_%0\";
8395     else if (frame_pointer_needed)
8396       return \"bl\\t%__interwork_r7_call_via_%0\";
8397     else
8398       return \"bl\\t%__interwork_r11_call_via_%0\";
8399   }"
8400   [(set_attr "type" "call")]
8401 )
8402
8403 (define_expand "call_value"
8404   [(parallel [(set (match_operand       0 "" "")
8405                    (call (match_operand 1 "memory_operand" "")
8406                          (match_operand 2 "general_operand" "")))
8407               (use (match_operand 3 "" ""))
8408               (clobber (reg:SI LR_REGNUM))])]
8409   "TARGET_EITHER"
8410   "
8411   {
8412     rtx pat, callee;
8413     
8414     /* In an untyped call, we can get NULL for operand 2.  */
8415     if (operands[3] == 0)
8416       operands[3] = const0_rtx;
8417       
8418     /* Decide if we should generate indirect calls by loading the
8419        32-bit address of the callee into a register before performing the
8420        branch and link.  */
8421     callee = XEXP (operands[1], 0);
8422     if (GET_CODE (callee) == SYMBOL_REF
8423         ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8424         : !REG_P (callee))
8425       XEXP (operands[1], 0) = force_reg (Pmode, callee);
8426
8427     pat = gen_call_value_internal (operands[0], operands[1],
8428                                    operands[2], operands[3]);
8429     arm_emit_call_insn (pat, XEXP (operands[1], 0));
8430     DONE;
8431   }"
8432 )
8433
8434 (define_expand "call_value_internal"
8435   [(parallel [(set (match_operand       0 "" "")
8436                    (call (match_operand 1 "memory_operand" "")
8437                          (match_operand 2 "general_operand" "")))
8438               (use (match_operand 3 "" ""))
8439               (clobber (reg:SI LR_REGNUM))])])
8440
8441 (define_insn "*call_value_reg_armv5"
8442   [(set (match_operand 0 "" "")
8443         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8444               (match_operand 2 "" "")))
8445    (use (match_operand 3 "" ""))
8446    (clobber (reg:SI LR_REGNUM))]
8447   "TARGET_ARM && arm_arch5"
8448   "blx%?\\t%1"
8449   [(set_attr "type" "call")]
8450 )
8451
8452 (define_insn "*call_value_reg_arm"
8453   [(set (match_operand 0 "" "")
8454         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8455               (match_operand 2 "" "")))
8456    (use (match_operand 3 "" ""))
8457    (clobber (reg:SI LR_REGNUM))]
8458   "TARGET_ARM && !arm_arch5"
8459   "*
8460   return output_call (&operands[1]);
8461   "
8462   [(set_attr "length" "12")
8463    (set_attr "type" "call")]
8464 )
8465
8466 (define_insn "*call_value_mem"
8467   [(set (match_operand 0 "" "")
8468         (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
8469               (match_operand 2 "" "")))
8470    (use (match_operand 3 "" ""))
8471    (clobber (reg:SI LR_REGNUM))]
8472   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
8473   "*
8474   return output_call_mem (&operands[1]);
8475   "
8476   [(set_attr "length" "12")
8477    (set_attr "type" "call")]
8478 )
8479
8480 (define_insn "*call_value_reg_thumb1_v5"
8481   [(set (match_operand 0 "" "")
8482         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8483               (match_operand 2 "" "")))
8484    (use (match_operand 3 "" ""))
8485    (clobber (reg:SI LR_REGNUM))]
8486   "TARGET_THUMB1 && arm_arch5"
8487   "blx\\t%1"
8488   [(set_attr "length" "2")
8489    (set_attr "type" "call")]
8490 )
8491
8492 (define_insn "*call_value_reg_thumb1"
8493   [(set (match_operand 0 "" "")
8494         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8495               (match_operand 2 "" "")))
8496    (use (match_operand 3 "" ""))
8497    (clobber (reg:SI LR_REGNUM))]
8498   "TARGET_THUMB1 && !arm_arch5"
8499   "*
8500   {
8501     if (!TARGET_CALLER_INTERWORKING)
8502       return thumb_call_via_reg (operands[1]);
8503     else if (operands[2] == const0_rtx)
8504       return \"bl\\t%__interwork_call_via_%1\";
8505     else if (frame_pointer_needed)
8506       return \"bl\\t%__interwork_r7_call_via_%1\";
8507     else
8508       return \"bl\\t%__interwork_r11_call_via_%1\";
8509   }"
8510   [(set_attr "type" "call")]
8511 )
8512
8513 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8514 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8515
8516 (define_insn "*call_symbol"
8517   [(call (mem:SI (match_operand:SI 0 "" ""))
8518          (match_operand 1 "" ""))
8519    (use (match_operand 2 "" ""))
8520    (clobber (reg:SI LR_REGNUM))]
8521   "TARGET_ARM
8522    && (GET_CODE (operands[0]) == SYMBOL_REF)
8523    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
8524   "*
8525   {
8526     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
8527   }"
8528   [(set_attr "type" "call")]
8529 )
8530
8531 (define_insn "*call_value_symbol"
8532   [(set (match_operand 0 "" "")
8533         (call (mem:SI (match_operand:SI 1 "" ""))
8534         (match_operand:SI 2 "" "")))
8535    (use (match_operand 3 "" ""))
8536    (clobber (reg:SI LR_REGNUM))]
8537   "TARGET_ARM
8538    && (GET_CODE (operands[1]) == SYMBOL_REF)
8539    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
8540   "*
8541   {
8542     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
8543   }"
8544   [(set_attr "type" "call")]
8545 )
8546
8547 (define_insn "*call_insn"
8548   [(call (mem:SI (match_operand:SI 0 "" ""))
8549          (match_operand:SI 1 "" ""))
8550    (use (match_operand 2 "" ""))
8551    (clobber (reg:SI LR_REGNUM))]
8552   "TARGET_THUMB
8553    && GET_CODE (operands[0]) == SYMBOL_REF
8554    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
8555   "bl\\t%a0"
8556   [(set_attr "length" "4")
8557    (set_attr "type" "call")]
8558 )
8559
8560 (define_insn "*call_value_insn"
8561   [(set (match_operand 0 "" "")
8562         (call (mem:SI (match_operand 1 "" ""))
8563               (match_operand 2 "" "")))
8564    (use (match_operand 3 "" ""))
8565    (clobber (reg:SI LR_REGNUM))]
8566   "TARGET_THUMB
8567    && GET_CODE (operands[1]) == SYMBOL_REF
8568    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
8569   "bl\\t%a1"
8570   [(set_attr "length" "4")
8571    (set_attr "type" "call")]
8572 )
8573
8574 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
8575 (define_expand "sibcall"
8576   [(parallel [(call (match_operand 0 "memory_operand" "")
8577                     (match_operand 1 "general_operand" ""))
8578               (return)
8579               (use (match_operand 2 "" ""))])]
8580   "TARGET_ARM"
8581   "
8582   {
8583     if (operands[2] == NULL_RTX)
8584       operands[2] = const0_rtx;
8585   }"
8586 )
8587
8588 (define_expand "sibcall_value"
8589   [(parallel [(set (match_operand 0 "" "")
8590                    (call (match_operand 1 "memory_operand" "")
8591                          (match_operand 2 "general_operand" "")))
8592               (return)
8593               (use (match_operand 3 "" ""))])]
8594   "TARGET_ARM"
8595   "
8596   {
8597     if (operands[3] == NULL_RTX)
8598       operands[3] = const0_rtx;
8599   }"
8600 )
8601
8602 (define_insn "*sibcall_insn"
8603  [(call (mem:SI (match_operand:SI 0 "" "X"))
8604         (match_operand 1 "" ""))
8605   (return)
8606   (use (match_operand 2 "" ""))]
8607   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
8608   "*
8609   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8610   "
8611   [(set_attr "type" "call")]
8612 )
8613
8614 (define_insn "*sibcall_value_insn"
8615  [(set (match_operand 0 "" "")
8616        (call (mem:SI (match_operand:SI 1 "" "X"))
8617              (match_operand 2 "" "")))
8618   (return)
8619   (use (match_operand 3 "" ""))]
8620   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
8621   "*
8622   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8623   "
8624   [(set_attr "type" "call")]
8625 )
8626
8627 ;; Often the return insn will be the same as loading from memory, so set attr
8628 (define_insn "return"
8629   [(return)]
8630   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
8631   "*
8632   {
8633     if (arm_ccfsm_state == 2)
8634       {
8635         arm_ccfsm_state += 2;
8636         return \"\";
8637       }
8638     return output_return_instruction (const_true_rtx, TRUE, FALSE);
8639   }"
8640   [(set_attr "type" "load1")
8641    (set_attr "length" "12")
8642    (set_attr "predicable" "yes")]
8643 )
8644
8645 (define_insn "*cond_return"
8646   [(set (pc)
8647         (if_then_else (match_operator 0 "arm_comparison_operator"
8648                        [(match_operand 1 "cc_register" "") (const_int 0)])
8649                       (return)
8650                       (pc)))]
8651   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
8652   "*
8653   {
8654     if (arm_ccfsm_state == 2)
8655       {
8656         arm_ccfsm_state += 2;
8657         return \"\";
8658       }
8659     return output_return_instruction (operands[0], TRUE, FALSE);
8660   }"
8661   [(set_attr "conds" "use")
8662    (set_attr "length" "12")
8663    (set_attr "type" "load1")]
8664 )
8665
8666 (define_insn "*cond_return_inverted"
8667   [(set (pc)
8668         (if_then_else (match_operator 0 "arm_comparison_operator"
8669                        [(match_operand 1 "cc_register" "") (const_int 0)])
8670                       (pc)
8671                       (return)))]
8672   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
8673   "*
8674   {
8675     if (arm_ccfsm_state == 2)
8676       {
8677         arm_ccfsm_state += 2;
8678         return \"\";
8679       }
8680     return output_return_instruction (operands[0], TRUE, TRUE);
8681   }"
8682   [(set_attr "conds" "use")
8683    (set_attr "length" "12")
8684    (set_attr "type" "load1")]
8685 )
8686
8687 ;; Generate a sequence of instructions to determine if the processor is
8688 ;; in 26-bit or 32-bit mode, and return the appropriate return address
8689 ;; mask.
8690
8691 (define_expand "return_addr_mask"
8692   [(set (match_dup 1)
8693       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8694                        (const_int 0)))
8695    (set (match_operand:SI 0 "s_register_operand" "")
8696       (if_then_else:SI (eq (match_dup 1) (const_int 0))
8697                        (const_int -1)
8698                        (const_int 67108860)))] ; 0x03fffffc
8699   "TARGET_ARM"
8700   "
8701   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
8702   ")
8703
8704 (define_insn "*check_arch2"
8705   [(set (match_operand:CC_NOOV 0 "cc_register" "")
8706       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8707                        (const_int 0)))]
8708   "TARGET_ARM"
8709   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8710   [(set_attr "length" "8")
8711    (set_attr "conds" "set")]
8712 )
8713
8714 ;; Call subroutine returning any type.
8715
8716 (define_expand "untyped_call"
8717   [(parallel [(call (match_operand 0 "" "")
8718                     (const_int 0))
8719               (match_operand 1 "" "")
8720               (match_operand 2 "" "")])]
8721   "TARGET_EITHER"
8722   "
8723   {
8724     int i;
8725     rtx par = gen_rtx_PARALLEL (VOIDmode,
8726                                 rtvec_alloc (XVECLEN (operands[2], 0)));
8727     rtx addr = gen_reg_rtx (Pmode);
8728     rtx mem;
8729     int size = 0;
8730
8731     emit_move_insn (addr, XEXP (operands[1], 0));
8732     mem = change_address (operands[1], BLKmode, addr);
8733
8734     for (i = 0; i < XVECLEN (operands[2], 0); i++)
8735       {
8736         rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
8737
8738         /* Default code only uses r0 as a return value, but we could
8739            be using anything up to 4 registers.  */
8740         if (REGNO (src) == R0_REGNUM)
8741           src = gen_rtx_REG (TImode, R0_REGNUM);
8742
8743         XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8744                                                  GEN_INT (size));
8745         size += GET_MODE_SIZE (GET_MODE (src));
8746       }
8747
8748     emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8749                                     const0_rtx));
8750
8751     size = 0;
8752
8753     for (i = 0; i < XVECLEN (par, 0); i++)
8754       {
8755         HOST_WIDE_INT offset = 0;
8756         rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8757
8758         if (size != 0)
8759           emit_move_insn (addr, plus_constant (addr, size));
8760
8761         mem = change_address (mem, GET_MODE (reg), NULL);
8762         if (REGNO (reg) == R0_REGNUM)
8763           {
8764             /* On thumb we have to use a write-back instruction.  */
8765             emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
8766                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8767             size = TARGET_ARM ? 16 : 0;
8768           }
8769         else
8770           {
8771             emit_move_insn (mem, reg);
8772             size = GET_MODE_SIZE (GET_MODE (reg));
8773           }
8774       }
8775
8776     /* The optimizer does not know that the call sets the function value
8777        registers we stored in the result block.  We avoid problems by
8778        claiming that all hard registers are used and clobbered at this
8779        point.  */
8780     emit_insn (gen_blockage ());
8781
8782     DONE;
8783   }"
8784 )
8785
8786 (define_expand "untyped_return"
8787   [(match_operand:BLK 0 "memory_operand" "")
8788    (match_operand 1 "" "")]
8789   "TARGET_EITHER"
8790   "
8791   {
8792     int i;
8793     rtx addr = gen_reg_rtx (Pmode);
8794     rtx mem;
8795     int size = 0;
8796
8797     emit_move_insn (addr, XEXP (operands[0], 0));
8798     mem = change_address (operands[0], BLKmode, addr);
8799
8800     for (i = 0; i < XVECLEN (operands[1], 0); i++)
8801       {
8802         HOST_WIDE_INT offset = 0;
8803         rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8804
8805         if (size != 0)
8806           emit_move_insn (addr, plus_constant (addr, size));
8807
8808         mem = change_address (mem, GET_MODE (reg), NULL);
8809         if (REGNO (reg) == R0_REGNUM)
8810           {
8811             /* On thumb we have to use a write-back instruction.  */
8812             emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
8813                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8814             size = TARGET_ARM ? 16 : 0;
8815           }
8816         else
8817           {
8818             emit_move_insn (reg, mem);
8819             size = GET_MODE_SIZE (GET_MODE (reg));
8820           }
8821       }
8822
8823     /* Emit USE insns before the return.  */
8824     for (i = 0; i < XVECLEN (operands[1], 0); i++)
8825       emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
8826
8827     /* Construct the return.  */
8828     expand_naked_return ();
8829
8830     DONE;
8831   }"
8832 )
8833
8834 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8835 ;; all of memory.  This blocks insns from being moved across this point.
8836
8837 (define_insn "blockage"
8838   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
8839   "TARGET_EITHER"
8840   ""
8841   [(set_attr "length" "0")
8842    (set_attr "type" "block")]
8843 )
8844
8845 (define_expand "casesi"
8846   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
8847    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
8848    (match_operand:SI 2 "const_int_operand" "")  ; total range
8849    (match_operand:SI 3 "" "")                   ; table label
8850    (match_operand:SI 4 "" "")]                  ; Out of range label
8851   "TARGET_32BIT || optimize_size || flag_pic"
8852   "
8853   {
8854     enum insn_code code;
8855     if (operands[1] != const0_rtx)
8856       {
8857         rtx reg = gen_reg_rtx (SImode);
8858
8859         emit_insn (gen_addsi3 (reg, operands[0],
8860                                GEN_INT (-INTVAL (operands[1]))));
8861         operands[0] = reg;
8862       }
8863
8864     if (TARGET_ARM)
8865       code = CODE_FOR_arm_casesi_internal;
8866     else if (TARGET_THUMB1)
8867       code = CODE_FOR_thumb1_casesi_internal_pic;
8868     else if (flag_pic)
8869       code = CODE_FOR_thumb2_casesi_internal_pic;
8870     else
8871       code = CODE_FOR_thumb2_casesi_internal;
8872
8873     if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8874       operands[2] = force_reg (SImode, operands[2]);
8875
8876     emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8877                                           operands[3], operands[4]));
8878     DONE;
8879   }"
8880 )
8881
8882 ;; The USE in this pattern is needed to tell flow analysis that this is
8883 ;; a CASESI insn.  It has no other purpose.
8884 (define_insn "arm_casesi_internal"
8885   [(parallel [(set (pc)
8886                (if_then_else
8887                 (leu (match_operand:SI 0 "s_register_operand" "r")
8888                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
8889                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8890                                  (label_ref (match_operand 2 "" ""))))
8891                 (label_ref (match_operand 3 "" ""))))
8892               (clobber (reg:CC CC_REGNUM))
8893               (use (label_ref (match_dup 2)))])]
8894   "TARGET_ARM"
8895   "*
8896     if (flag_pic)
8897       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8898     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8899   "
8900   [(set_attr "conds" "clob")
8901    (set_attr "length" "12")]
8902 )
8903
8904 (define_expand "thumb1_casesi_internal_pic"
8905   [(match_operand:SI 0 "s_register_operand" "")
8906    (match_operand:SI 1 "thumb1_cmp_operand" "")
8907    (match_operand 2 "" "")
8908    (match_operand 3 "" "")]
8909   "TARGET_THUMB1"
8910   {
8911     rtx reg0;
8912     rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[1]);
8913     emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[1],
8914                                     operands[3]));
8915     reg0 = gen_rtx_REG (SImode, 0);
8916     emit_move_insn (reg0, operands[0]);
8917     emit_jump_insn (gen_thumb1_casesi_dispatch (operands[2]/*, operands[3]*/));
8918     DONE;
8919   }
8920 )
8921
8922 (define_insn "thumb1_casesi_dispatch"
8923   [(parallel [(set (pc) (unspec [(reg:SI 0)
8924                                  (label_ref (match_operand 0 "" ""))
8925 ;;                               (label_ref (match_operand 1 "" ""))
8926 ]
8927                          UNSPEC_THUMB1_CASESI))
8928               (clobber (reg:SI IP_REGNUM))
8929               (clobber (reg:SI LR_REGNUM))])]
8930   "TARGET_THUMB1"
8931   "* return thumb1_output_casesi(operands);"
8932   [(set_attr "length" "4")]
8933 )
8934
8935 (define_expand "indirect_jump"
8936   [(set (pc)
8937         (match_operand:SI 0 "s_register_operand" ""))]
8938   "TARGET_EITHER"
8939   "
8940   /* Thumb-2 doesn't have mov pc, reg.  Explicitly set the low bit of the
8941      address and use bx.  */
8942   if (TARGET_THUMB2)
8943     {
8944       rtx tmp;
8945       tmp = gen_reg_rtx (SImode);
8946       emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8947       operands[0] = tmp;
8948     }
8949   "
8950 )
8951
8952 ;; NB Never uses BX.
8953 (define_insn "*arm_indirect_jump"
8954   [(set (pc)
8955         (match_operand:SI 0 "s_register_operand" "r"))]
8956   "TARGET_ARM"
8957   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
8958   [(set_attr "predicable" "yes")]
8959 )
8960
8961 (define_insn "*load_indirect_jump"
8962   [(set (pc)
8963         (match_operand:SI 0 "memory_operand" "m"))]
8964   "TARGET_ARM"
8965   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
8966   [(set_attr "type" "load1")
8967    (set_attr "pool_range" "4096")
8968    (set_attr "neg_pool_range" "4084")
8969    (set_attr "predicable" "yes")]
8970 )
8971
8972 ;; NB Never uses BX.
8973 (define_insn "*thumb1_indirect_jump"
8974   [(set (pc)
8975         (match_operand:SI 0 "register_operand" "l*r"))]
8976   "TARGET_THUMB1"
8977   "mov\\tpc, %0"
8978   [(set_attr "conds" "clob")
8979    (set_attr "length" "2")]
8980 )
8981
8982 \f
8983 ;; Misc insns
8984
8985 (define_insn "nop"
8986   [(const_int 0)]
8987   "TARGET_EITHER"
8988   "*
8989   if (TARGET_UNIFIED_ASM)
8990     return \"nop\";
8991   if (TARGET_ARM)
8992     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8993   return  \"mov\\tr8, r8\";
8994   "
8995   [(set (attr "length")
8996         (if_then_else (eq_attr "is_thumb" "yes")
8997                       (const_int 2)
8998                       (const_int 4)))]
8999 )
9000
9001 \f
9002 ;; Patterns to allow combination of arithmetic, cond code and shifts
9003
9004 (define_insn "*arith_shiftsi"
9005   [(set (match_operand:SI 0 "s_register_operand" "=r")
9006         (match_operator:SI 1 "shiftable_operator"
9007           [(match_operator:SI 3 "shift_operator"
9008              [(match_operand:SI 4 "s_register_operand" "r")
9009               (match_operand:SI 5 "reg_or_int_operand" "rI")])
9010            (match_operand:SI 2 "s_register_operand" "r")]))]
9011   "TARGET_ARM"
9012   "%i1%?\\t%0, %2, %4%S3"
9013   [(set_attr "predicable" "yes")
9014    (set_attr "shift" "4")
9015    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
9016                       (const_string "alu_shift")
9017                       (const_string "alu_shift_reg")))]
9018 )
9019
9020 (define_split
9021   [(set (match_operand:SI 0 "s_register_operand" "")
9022         (match_operator:SI 1 "shiftable_operator"
9023          [(match_operator:SI 2 "shiftable_operator"
9024            [(match_operator:SI 3 "shift_operator"
9025              [(match_operand:SI 4 "s_register_operand" "")
9026               (match_operand:SI 5 "reg_or_int_operand" "")])
9027             (match_operand:SI 6 "s_register_operand" "")])
9028           (match_operand:SI 7 "arm_rhs_operand" "")]))
9029    (clobber (match_operand:SI 8 "s_register_operand" ""))]
9030   "TARGET_ARM"
9031   [(set (match_dup 8)
9032         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9033                          (match_dup 6)]))
9034    (set (match_dup 0)
9035         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
9036   "")
9037
9038 (define_insn "*arith_shiftsi_compare0"
9039   [(set (reg:CC_NOOV CC_REGNUM)
9040         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
9041                           [(match_operator:SI 3 "shift_operator"
9042                             [(match_operand:SI 4 "s_register_operand" "r")
9043                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
9044                            (match_operand:SI 2 "s_register_operand" "r")])
9045                          (const_int 0)))
9046    (set (match_operand:SI 0 "s_register_operand" "=r")
9047         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9048                          (match_dup 2)]))]
9049   "TARGET_ARM"
9050   "%i1%.\\t%0, %2, %4%S3"
9051   [(set_attr "conds" "set")
9052    (set_attr "shift" "4")
9053    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
9054                       (const_string "alu_shift")
9055                       (const_string "alu_shift_reg")))]
9056 )
9057
9058 (define_insn "*arith_shiftsi_compare0_scratch"
9059   [(set (reg:CC_NOOV CC_REGNUM)
9060         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
9061                           [(match_operator:SI 3 "shift_operator"
9062                             [(match_operand:SI 4 "s_register_operand" "r")
9063                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
9064                            (match_operand:SI 2 "s_register_operand" "r")])
9065                          (const_int 0)))
9066    (clobber (match_scratch:SI 0 "=r"))]
9067   "TARGET_ARM"
9068   "%i1%.\\t%0, %2, %4%S3"
9069   [(set_attr "conds" "set")
9070    (set_attr "shift" "4")
9071    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
9072                       (const_string "alu_shift")
9073                       (const_string "alu_shift_reg")))]
9074 )
9075
9076 (define_insn "*sub_shiftsi"
9077   [(set (match_operand:SI 0 "s_register_operand" "=r")
9078         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
9079                   (match_operator:SI 2 "shift_operator"
9080                    [(match_operand:SI 3 "s_register_operand" "r")
9081                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
9082   "TARGET_ARM"
9083   "sub%?\\t%0, %1, %3%S2"
9084   [(set_attr "predicable" "yes")
9085    (set_attr "shift" "3")
9086    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
9087                       (const_string "alu_shift")
9088                       (const_string "alu_shift_reg")))]
9089 )
9090
9091 (define_insn "*sub_shiftsi_compare0"
9092   [(set (reg:CC_NOOV CC_REGNUM)
9093         (compare:CC_NOOV
9094          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
9095                    (match_operator:SI 2 "shift_operator"
9096                     [(match_operand:SI 3 "s_register_operand" "r")
9097                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
9098          (const_int 0)))
9099    (set (match_operand:SI 0 "s_register_operand" "=r")
9100         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9101                                                  (match_dup 4)])))]
9102   "TARGET_ARM"
9103   "sub%.\\t%0, %1, %3%S2"
9104   [(set_attr "conds" "set")
9105    (set_attr "shift" "3")
9106    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
9107                       (const_string "alu_shift")
9108                       (const_string "alu_shift_reg")))]
9109 )
9110
9111 (define_insn "*sub_shiftsi_compare0_scratch"
9112   [(set (reg:CC_NOOV CC_REGNUM)
9113         (compare:CC_NOOV
9114          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
9115                    (match_operator:SI 2 "shift_operator"
9116                     [(match_operand:SI 3 "s_register_operand" "r")
9117                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
9118          (const_int 0)))
9119    (clobber (match_scratch:SI 0 "=r"))]
9120   "TARGET_ARM"
9121   "sub%.\\t%0, %1, %3%S2"
9122   [(set_attr "conds" "set")
9123    (set_attr "shift" "3")
9124    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
9125                       (const_string "alu_shift")
9126                       (const_string "alu_shift_reg")))]
9127 )
9128
9129 \f
9130
9131 (define_insn "*and_scc"
9132   [(set (match_operand:SI 0 "s_register_operand" "=r")
9133         (and:SI (match_operator:SI 1 "arm_comparison_operator"
9134                  [(match_operand 3 "cc_register" "") (const_int 0)])
9135                 (match_operand:SI 2 "s_register_operand" "r")))]
9136   "TARGET_ARM"
9137   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
9138   [(set_attr "conds" "use")
9139    (set_attr "length" "8")]
9140 )
9141
9142 (define_insn "*ior_scc"
9143   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9144         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
9145                  [(match_operand 3 "cc_register" "") (const_int 0)])
9146                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
9147   "TARGET_ARM"
9148   "@
9149    orr%d2\\t%0, %1, #1
9150    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
9151   [(set_attr "conds" "use")
9152    (set_attr "length" "4,8")]
9153 )
9154
9155 (define_insn "*compare_scc"
9156   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9157         (match_operator:SI 1 "arm_comparison_operator"
9158          [(match_operand:SI 2 "s_register_operand" "r,r")
9159           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
9160    (clobber (reg:CC CC_REGNUM))]
9161   "TARGET_ARM"
9162   "*
9163     if (operands[3] == const0_rtx)
9164       {
9165         if (GET_CODE (operands[1]) == LT)
9166           return \"mov\\t%0, %2, lsr #31\";
9167
9168         if (GET_CODE (operands[1]) == GE)
9169           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
9170
9171         if (GET_CODE (operands[1]) == EQ)
9172           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
9173       }
9174
9175     if (GET_CODE (operands[1]) == NE)
9176       {
9177         if (which_alternative == 1)
9178           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
9179         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
9180       }
9181     if (which_alternative == 1)
9182       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9183     else
9184       output_asm_insn (\"cmp\\t%2, %3\", operands);
9185     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
9186   "
9187   [(set_attr "conds" "clob")
9188    (set_attr "length" "12")]
9189 )
9190
9191 (define_insn "*cond_move"
9192   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9193         (if_then_else:SI (match_operator 3 "equality_operator"
9194                           [(match_operator 4 "arm_comparison_operator"
9195                             [(match_operand 5 "cc_register" "") (const_int 0)])
9196                            (const_int 0)])
9197                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9198                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
9199   "TARGET_ARM"
9200   "*
9201     if (GET_CODE (operands[3]) == NE)
9202       {
9203         if (which_alternative != 1)
9204           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
9205         if (which_alternative != 0)
9206           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
9207         return \"\";
9208       }
9209     if (which_alternative != 0)
9210       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9211     if (which_alternative != 1)
9212       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
9213     return \"\";
9214   "
9215   [(set_attr "conds" "use")
9216    (set_attr "length" "4,4,8")]
9217 )
9218
9219 (define_insn "*cond_arith"
9220   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9221         (match_operator:SI 5 "shiftable_operator" 
9222          [(match_operator:SI 4 "arm_comparison_operator"
9223            [(match_operand:SI 2 "s_register_operand" "r,r")
9224             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9225           (match_operand:SI 1 "s_register_operand" "0,?r")]))
9226    (clobber (reg:CC CC_REGNUM))]
9227   "TARGET_ARM"
9228   "*
9229     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
9230       return \"%i5\\t%0, %1, %2, lsr #31\";
9231
9232     output_asm_insn (\"cmp\\t%2, %3\", operands);
9233     if (GET_CODE (operands[5]) == AND)
9234       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
9235     else if (GET_CODE (operands[5]) == MINUS)
9236       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
9237     else if (which_alternative != 0)
9238       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9239     return \"%i5%d4\\t%0, %1, #1\";
9240   "
9241   [(set_attr "conds" "clob")
9242    (set_attr "length" "12")]
9243 )
9244
9245 (define_insn "*cond_sub"
9246   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9247         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
9248                   (match_operator:SI 4 "arm_comparison_operator"
9249                    [(match_operand:SI 2 "s_register_operand" "r,r")
9250                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
9251    (clobber (reg:CC CC_REGNUM))]
9252   "TARGET_ARM"
9253   "*
9254     output_asm_insn (\"cmp\\t%2, %3\", operands);
9255     if (which_alternative != 0)
9256       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9257     return \"sub%d4\\t%0, %1, #1\";
9258   "
9259   [(set_attr "conds" "clob")
9260    (set_attr "length" "8,12")]
9261 )
9262
9263 ;; ??? Is it worth using these conditional patterns in Thumb-2 mode?
9264 (define_insn "*cmp_ite0"
9265   [(set (match_operand 6 "dominant_cc_register" "")
9266         (compare
9267          (if_then_else:SI
9268           (match_operator 4 "arm_comparison_operator"
9269            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9270             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9271           (match_operator:SI 5 "arm_comparison_operator"
9272            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9273             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
9274           (const_int 0))
9275          (const_int 0)))]
9276   "TARGET_ARM"
9277   "*
9278   {
9279     static const char * const opcodes[4][2] =
9280     {
9281       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9282        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9283       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9284        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9285       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9286        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9287       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9288        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9289     };
9290     int swap =
9291       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9292
9293     return opcodes[which_alternative][swap];
9294   }"
9295   [(set_attr "conds" "set")
9296    (set_attr "length" "8")]
9297 )
9298
9299 (define_insn "*cmp_ite1"
9300   [(set (match_operand 6 "dominant_cc_register" "")
9301         (compare
9302          (if_then_else:SI
9303           (match_operator 4 "arm_comparison_operator"
9304            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9305             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9306           (match_operator:SI 5 "arm_comparison_operator"
9307            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9308             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
9309           (const_int 1))
9310          (const_int 0)))]
9311   "TARGET_ARM"
9312   "*
9313   {
9314     static const char * const opcodes[4][2] =
9315     {
9316       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
9317        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9318       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
9319        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9320       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
9321        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9322       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
9323        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9324     };
9325     int swap =
9326       comparison_dominates_p (GET_CODE (operands[5]),
9327                               reverse_condition (GET_CODE (operands[4])));
9328
9329     return opcodes[which_alternative][swap];
9330   }"
9331   [(set_attr "conds" "set")
9332    (set_attr "length" "8")]
9333 )
9334
9335 (define_insn "*cmp_and"
9336   [(set (match_operand 6 "dominant_cc_register" "")
9337         (compare
9338          (and:SI
9339           (match_operator 4 "arm_comparison_operator"
9340            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9341             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9342           (match_operator:SI 5 "arm_comparison_operator"
9343            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9344             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9345          (const_int 0)))]
9346   "TARGET_ARM"
9347   "*
9348   {
9349     static const char *const opcodes[4][2] =
9350     {
9351       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9352        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9353       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9354        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9355       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9356        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9357       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9358        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9359     };
9360     int swap =
9361       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9362
9363     return opcodes[which_alternative][swap];
9364   }"
9365   [(set_attr "conds" "set")
9366    (set_attr "predicable" "no")
9367    (set_attr "length" "8")]
9368 )
9369
9370 (define_insn "*cmp_ior"
9371   [(set (match_operand 6 "dominant_cc_register" "")
9372         (compare
9373          (ior:SI
9374           (match_operator 4 "arm_comparison_operator"
9375            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9376             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9377           (match_operator:SI 5 "arm_comparison_operator"
9378            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9379             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9380          (const_int 0)))]
9381   "TARGET_ARM"
9382   "*
9383 {
9384   static const char *const opcodes[4][2] =
9385   {
9386     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
9387      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9388     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
9389      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9390     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
9391      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9392     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
9393      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9394   };
9395   int swap =
9396     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9397
9398   return opcodes[which_alternative][swap];
9399 }
9400 "
9401   [(set_attr "conds" "set")
9402    (set_attr "length" "8")]
9403 )
9404
9405 (define_insn_and_split "*ior_scc_scc"
9406   [(set (match_operand:SI 0 "s_register_operand" "=r")
9407         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9408                  [(match_operand:SI 1 "s_register_operand" "r")
9409                   (match_operand:SI 2 "arm_add_operand" "rIL")])
9410                 (match_operator:SI 6 "arm_comparison_operator"
9411                  [(match_operand:SI 4 "s_register_operand" "r")
9412                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
9413    (clobber (reg:CC CC_REGNUM))]
9414   "TARGET_ARM
9415    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9416        != CCmode)"
9417   "#"
9418   "TARGET_ARM && reload_completed"
9419   [(set (match_dup 7)
9420         (compare
9421          (ior:SI
9422           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9423           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9424          (const_int 0)))
9425    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9426   "operands[7]
9427      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9428                                                   DOM_CC_X_OR_Y),
9429                     CC_REGNUM);"
9430   [(set_attr "conds" "clob")
9431    (set_attr "length" "16")])
9432
9433 ; If the above pattern is followed by a CMP insn, then the compare is 
9434 ; redundant, since we can rework the conditional instruction that follows.
9435 (define_insn_and_split "*ior_scc_scc_cmp"
9436   [(set (match_operand 0 "dominant_cc_register" "")
9437         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9438                           [(match_operand:SI 1 "s_register_operand" "r")
9439                            (match_operand:SI 2 "arm_add_operand" "rIL")])
9440                          (match_operator:SI 6 "arm_comparison_operator"
9441                           [(match_operand:SI 4 "s_register_operand" "r")
9442                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
9443                  (const_int 0)))
9444    (set (match_operand:SI 7 "s_register_operand" "=r")
9445         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9446                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9447   "TARGET_ARM"
9448   "#"
9449   "TARGET_ARM && reload_completed"
9450   [(set (match_dup 0)
9451         (compare
9452          (ior:SI
9453           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9454           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9455          (const_int 0)))
9456    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9457   ""
9458   [(set_attr "conds" "set")
9459    (set_attr "length" "16")])
9460
9461 (define_insn_and_split "*and_scc_scc"
9462   [(set (match_operand:SI 0 "s_register_operand" "=r")
9463         (and:SI (match_operator:SI 3 "arm_comparison_operator"
9464                  [(match_operand:SI 1 "s_register_operand" "r")
9465                   (match_operand:SI 2 "arm_add_operand" "rIL")])
9466                 (match_operator:SI 6 "arm_comparison_operator"
9467                  [(match_operand:SI 4 "s_register_operand" "r")
9468                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
9469    (clobber (reg:CC CC_REGNUM))]
9470   "TARGET_ARM
9471    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9472        != CCmode)"
9473   "#"
9474   "TARGET_ARM && reload_completed
9475    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9476        != CCmode)"
9477   [(set (match_dup 7)
9478         (compare
9479          (and:SI
9480           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9481           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9482          (const_int 0)))
9483    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9484   "operands[7]
9485      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9486                                                   DOM_CC_X_AND_Y),
9487                     CC_REGNUM);"
9488   [(set_attr "conds" "clob")
9489    (set_attr "length" "16")])
9490
9491 ; If the above pattern is followed by a CMP insn, then the compare is 
9492 ; redundant, since we can rework the conditional instruction that follows.
9493 (define_insn_and_split "*and_scc_scc_cmp"
9494   [(set (match_operand 0 "dominant_cc_register" "")
9495         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9496                           [(match_operand:SI 1 "s_register_operand" "r")
9497                            (match_operand:SI 2 "arm_add_operand" "rIL")])
9498                          (match_operator:SI 6 "arm_comparison_operator"
9499                           [(match_operand:SI 4 "s_register_operand" "r")
9500                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
9501                  (const_int 0)))
9502    (set (match_operand:SI 7 "s_register_operand" "=r")
9503         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9504                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9505   "TARGET_ARM"
9506   "#"
9507   "TARGET_ARM && reload_completed"
9508   [(set (match_dup 0)
9509         (compare
9510          (and:SI
9511           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9512           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9513          (const_int 0)))
9514    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9515   ""
9516   [(set_attr "conds" "set")
9517    (set_attr "length" "16")])
9518
9519 ;; If there is no dominance in the comparison, then we can still save an
9520 ;; instruction in the AND case, since we can know that the second compare
9521 ;; need only zero the value if false (if true, then the value is already
9522 ;; correct).
9523 (define_insn_and_split "*and_scc_scc_nodom"
9524   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
9525         (and:SI (match_operator:SI 3 "arm_comparison_operator"
9526                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
9527                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9528                 (match_operator:SI 6 "arm_comparison_operator"
9529                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
9530                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9531    (clobber (reg:CC CC_REGNUM))]
9532   "TARGET_ARM
9533    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9534        == CCmode)"
9535   "#"
9536   "TARGET_ARM && reload_completed"
9537   [(parallel [(set (match_dup 0)
9538                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9539               (clobber (reg:CC CC_REGNUM))])
9540    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9541    (set (match_dup 0)
9542         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9543                          (match_dup 0)
9544                          (const_int 0)))]
9545   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9546                                               operands[4], operands[5]),
9547                               CC_REGNUM);
9548    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9549                                   operands[5]);"
9550   [(set_attr "conds" "clob")
9551    (set_attr "length" "20")])
9552
9553 (define_split
9554   [(set (reg:CC_NOOV CC_REGNUM)
9555         (compare:CC_NOOV (ior:SI
9556                           (and:SI (match_operand:SI 0 "s_register_operand" "")
9557                                   (const_int 1))
9558                           (match_operator:SI 1 "arm_comparison_operator"
9559                            [(match_operand:SI 2 "s_register_operand" "")
9560                             (match_operand:SI 3 "arm_add_operand" "")]))
9561                          (const_int 0)))
9562    (clobber (match_operand:SI 4 "s_register_operand" ""))]
9563   "TARGET_ARM"
9564   [(set (match_dup 4)
9565         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9566                 (match_dup 0)))
9567    (set (reg:CC_NOOV CC_REGNUM)
9568         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9569                          (const_int 0)))]
9570   "")
9571
9572 (define_split
9573   [(set (reg:CC_NOOV CC_REGNUM)
9574         (compare:CC_NOOV (ior:SI
9575                           (match_operator:SI 1 "arm_comparison_operator"
9576                            [(match_operand:SI 2 "s_register_operand" "")
9577                             (match_operand:SI 3 "arm_add_operand" "")])
9578                           (and:SI (match_operand:SI 0 "s_register_operand" "")
9579                                   (const_int 1)))
9580                          (const_int 0)))
9581    (clobber (match_operand:SI 4 "s_register_operand" ""))]
9582   "TARGET_ARM"
9583   [(set (match_dup 4)
9584         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9585                 (match_dup 0)))
9586    (set (reg:CC_NOOV CC_REGNUM)
9587         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9588                          (const_int 0)))]
9589   "")
9590 ;; ??? The conditional patterns above need checking for Thumb-2 usefulness
9591
9592 (define_insn "*negscc"
9593   [(set (match_operand:SI 0 "s_register_operand" "=r")
9594         (neg:SI (match_operator 3 "arm_comparison_operator"
9595                  [(match_operand:SI 1 "s_register_operand" "r")
9596                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
9597    (clobber (reg:CC CC_REGNUM))]
9598   "TARGET_ARM"
9599   "*
9600   if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
9601     return \"mov\\t%0, %1, asr #31\";
9602
9603   if (GET_CODE (operands[3]) == NE)
9604     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9605
9606   output_asm_insn (\"cmp\\t%1, %2\", operands);
9607   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9608   return \"mvn%d3\\t%0, #0\";
9609   "
9610   [(set_attr "conds" "clob")
9611    (set_attr "length" "12")]
9612 )
9613
9614 (define_insn "movcond"
9615   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9616         (if_then_else:SI
9617          (match_operator 5 "arm_comparison_operator"
9618           [(match_operand:SI 3 "s_register_operand" "r,r,r")
9619            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9620          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9621          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
9622    (clobber (reg:CC CC_REGNUM))]
9623   "TARGET_ARM"
9624   "*
9625   if (GET_CODE (operands[5]) == LT
9626       && (operands[4] == const0_rtx))
9627     {
9628       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9629         {
9630           if (operands[2] == const0_rtx)
9631             return \"and\\t%0, %1, %3, asr #31\";
9632           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9633         }
9634       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9635         {
9636           if (operands[1] == const0_rtx)
9637             return \"bic\\t%0, %2, %3, asr #31\";
9638           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9639         }
9640       /* The only case that falls through to here is when both ops 1 & 2
9641          are constants.  */
9642     }
9643
9644   if (GET_CODE (operands[5]) == GE
9645       && (operands[4] == const0_rtx))
9646     {
9647       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9648         {
9649           if (operands[2] == const0_rtx)
9650             return \"bic\\t%0, %1, %3, asr #31\";
9651           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9652         }
9653       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9654         {
9655           if (operands[1] == const0_rtx)
9656             return \"and\\t%0, %2, %3, asr #31\";
9657           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9658         }
9659       /* The only case that falls through to here is when both ops 1 & 2
9660          are constants.  */
9661     }
9662   if (GET_CODE (operands[4]) == CONST_INT
9663       && !const_ok_for_arm (INTVAL (operands[4])))
9664     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9665   else
9666     output_asm_insn (\"cmp\\t%3, %4\", operands);
9667   if (which_alternative != 0)
9668     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9669   if (which_alternative != 1)
9670     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9671   return \"\";
9672   "
9673   [(set_attr "conds" "clob")
9674    (set_attr "length" "8,8,12")]
9675 )
9676
9677 ;; ??? The patterns below need checking for Thumb-2 usefulness.
9678
9679 (define_insn "*ifcompare_plus_move"
9680   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9681         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9682                           [(match_operand:SI 4 "s_register_operand" "r,r")
9683                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9684                          (plus:SI
9685                           (match_operand:SI 2 "s_register_operand" "r,r")
9686                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
9687                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9688    (clobber (reg:CC CC_REGNUM))]
9689   "TARGET_ARM"
9690   "#"
9691   [(set_attr "conds" "clob")
9692    (set_attr "length" "8,12")]
9693 )
9694
9695 (define_insn "*if_plus_move"
9696   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9697         (if_then_else:SI
9698          (match_operator 4 "arm_comparison_operator"
9699           [(match_operand 5 "cc_register" "") (const_int 0)])
9700          (plus:SI
9701           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9702           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9703          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
9704   "TARGET_ARM"
9705   "@
9706    add%d4\\t%0, %2, %3
9707    sub%d4\\t%0, %2, #%n3
9708    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
9709    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
9710   [(set_attr "conds" "use")
9711    (set_attr "length" "4,4,8,8")
9712    (set_attr "type" "*,*,*,*")]
9713 )
9714
9715 (define_insn "*ifcompare_move_plus"
9716   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9717         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9718                           [(match_operand:SI 4 "s_register_operand" "r,r")
9719                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9720                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9721                          (plus:SI
9722                           (match_operand:SI 2 "s_register_operand" "r,r")
9723                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
9724    (clobber (reg:CC CC_REGNUM))]
9725   "TARGET_ARM"
9726   "#"
9727   [(set_attr "conds" "clob")
9728    (set_attr "length" "8,12")]
9729 )
9730
9731 (define_insn "*if_move_plus"
9732   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9733         (if_then_else:SI
9734          (match_operator 4 "arm_comparison_operator"
9735           [(match_operand 5 "cc_register" "") (const_int 0)])
9736          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
9737          (plus:SI
9738           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9739           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
9740   "TARGET_ARM"
9741   "@
9742    add%D4\\t%0, %2, %3
9743    sub%D4\\t%0, %2, #%n3
9744    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
9745    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
9746   [(set_attr "conds" "use")
9747    (set_attr "length" "4,4,8,8")
9748    (set_attr "type" "*,*,*,*")]
9749 )
9750
9751 (define_insn "*ifcompare_arith_arith"
9752   [(set (match_operand:SI 0 "s_register_operand" "=r")
9753         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
9754                           [(match_operand:SI 5 "s_register_operand" "r")
9755                            (match_operand:SI 6 "arm_add_operand" "rIL")])
9756                          (match_operator:SI 8 "shiftable_operator"
9757                           [(match_operand:SI 1 "s_register_operand" "r")
9758                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
9759                          (match_operator:SI 7 "shiftable_operator"
9760                           [(match_operand:SI 3 "s_register_operand" "r")
9761                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
9762    (clobber (reg:CC CC_REGNUM))]
9763   "TARGET_ARM"
9764   "#"
9765   [(set_attr "conds" "clob")
9766    (set_attr "length" "12")]
9767 )
9768
9769 (define_insn "*if_arith_arith"
9770   [(set (match_operand:SI 0 "s_register_operand" "=r")
9771         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
9772                           [(match_operand 8 "cc_register" "") (const_int 0)])
9773                          (match_operator:SI 6 "shiftable_operator"
9774                           [(match_operand:SI 1 "s_register_operand" "r")
9775                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
9776                          (match_operator:SI 7 "shiftable_operator"
9777                           [(match_operand:SI 3 "s_register_operand" "r")
9778                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
9779   "TARGET_ARM"
9780   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
9781   [(set_attr "conds" "use")
9782    (set_attr "length" "8")]
9783 )
9784
9785 (define_insn "*ifcompare_arith_move"
9786   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9787         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9788                           [(match_operand:SI 2 "s_register_operand" "r,r")
9789                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9790                          (match_operator:SI 7 "shiftable_operator"
9791                           [(match_operand:SI 4 "s_register_operand" "r,r")
9792                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
9793                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9794    (clobber (reg:CC CC_REGNUM))]
9795   "TARGET_ARM"
9796   "*
9797   /* If we have an operation where (op x 0) is the identity operation and
9798      the conditional operator is LT or GE and we are comparing against zero and
9799      everything is in registers then we can do this in two instructions.  */
9800   if (operands[3] == const0_rtx
9801       && GET_CODE (operands[7]) != AND
9802       && GET_CODE (operands[5]) == REG
9803       && GET_CODE (operands[1]) == REG 
9804       && REGNO (operands[1]) == REGNO (operands[4])
9805       && REGNO (operands[4]) != REGNO (operands[0]))
9806     {
9807       if (GET_CODE (operands[6]) == LT)
9808         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9809       else if (GET_CODE (operands[6]) == GE)
9810         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9811     }
9812   if (GET_CODE (operands[3]) == CONST_INT
9813       && !const_ok_for_arm (INTVAL (operands[3])))
9814     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9815   else
9816     output_asm_insn (\"cmp\\t%2, %3\", operands);
9817   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9818   if (which_alternative != 0)
9819     return \"mov%D6\\t%0, %1\";
9820   return \"\";
9821   "
9822   [(set_attr "conds" "clob")
9823    (set_attr "length" "8,12")]
9824 )
9825
9826 (define_insn "*if_arith_move"
9827   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9828         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9829                           [(match_operand 6 "cc_register" "") (const_int 0)])
9830                          (match_operator:SI 5 "shiftable_operator"
9831                           [(match_operand:SI 2 "s_register_operand" "r,r")
9832                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9833                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
9834   "TARGET_ARM"
9835   "@
9836    %I5%d4\\t%0, %2, %3
9837    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
9838   [(set_attr "conds" "use")
9839    (set_attr "length" "4,8")
9840    (set_attr "type" "*,*")]
9841 )
9842
9843 (define_insn "*ifcompare_move_arith"
9844   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9845         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9846                           [(match_operand:SI 4 "s_register_operand" "r,r")
9847                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9848                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9849                          (match_operator:SI 7 "shiftable_operator"
9850                           [(match_operand:SI 2 "s_register_operand" "r,r")
9851                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
9852    (clobber (reg:CC CC_REGNUM))]
9853   "TARGET_ARM"
9854   "*
9855   /* If we have an operation where (op x 0) is the identity operation and
9856      the conditional operator is LT or GE and we are comparing against zero and
9857      everything is in registers then we can do this in two instructions */
9858   if (operands[5] == const0_rtx
9859       && GET_CODE (operands[7]) != AND
9860       && GET_CODE (operands[3]) == REG
9861       && GET_CODE (operands[1]) == REG 
9862       && REGNO (operands[1]) == REGNO (operands[2])
9863       && REGNO (operands[2]) != REGNO (operands[0]))
9864     {
9865       if (GET_CODE (operands[6]) == GE)
9866         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9867       else if (GET_CODE (operands[6]) == LT)
9868         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9869     }
9870
9871   if (GET_CODE (operands[5]) == CONST_INT
9872       && !const_ok_for_arm (INTVAL (operands[5])))
9873     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9874   else
9875     output_asm_insn (\"cmp\\t%4, %5\", operands);
9876
9877   if (which_alternative != 0)
9878     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
9879   return \"%I7%D6\\t%0, %2, %3\";
9880   "
9881   [(set_attr "conds" "clob")
9882    (set_attr "length" "8,12")]
9883 )
9884
9885 (define_insn "*if_move_arith"
9886   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9887         (if_then_else:SI
9888          (match_operator 4 "arm_comparison_operator"
9889           [(match_operand 6 "cc_register" "") (const_int 0)])
9890          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9891          (match_operator:SI 5 "shiftable_operator"
9892           [(match_operand:SI 2 "s_register_operand" "r,r")
9893            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
9894   "TARGET_ARM"
9895   "@
9896    %I5%D4\\t%0, %2, %3
9897    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
9898   [(set_attr "conds" "use")
9899    (set_attr "length" "4,8")
9900    (set_attr "type" "*,*")]
9901 )
9902
9903 (define_insn "*ifcompare_move_not"
9904   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9905         (if_then_else:SI
9906          (match_operator 5 "arm_comparison_operator"
9907           [(match_operand:SI 3 "s_register_operand" "r,r")
9908            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9909          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9910          (not:SI
9911           (match_operand:SI 2 "s_register_operand" "r,r"))))
9912    (clobber (reg:CC CC_REGNUM))]
9913   "TARGET_ARM"
9914   "#"
9915   [(set_attr "conds" "clob")
9916    (set_attr "length" "8,12")]
9917 )
9918
9919 (define_insn "*if_move_not"
9920   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9921         (if_then_else:SI
9922          (match_operator 4 "arm_comparison_operator"
9923           [(match_operand 3 "cc_register" "") (const_int 0)])
9924          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9925          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9926   "TARGET_ARM"
9927   "@
9928    mvn%D4\\t%0, %2
9929    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9930    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
9931   [(set_attr "conds" "use")
9932    (set_attr "length" "4,8,8")]
9933 )
9934
9935 (define_insn "*ifcompare_not_move"
9936   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9937         (if_then_else:SI 
9938          (match_operator 5 "arm_comparison_operator"
9939           [(match_operand:SI 3 "s_register_operand" "r,r")
9940            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9941          (not:SI
9942           (match_operand:SI 2 "s_register_operand" "r,r"))
9943          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9944    (clobber (reg:CC CC_REGNUM))]
9945   "TARGET_ARM"
9946   "#"
9947   [(set_attr "conds" "clob")
9948    (set_attr "length" "8,12")]
9949 )
9950
9951 (define_insn "*if_not_move"
9952   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9953         (if_then_else:SI
9954          (match_operator 4 "arm_comparison_operator"
9955           [(match_operand 3 "cc_register" "") (const_int 0)])
9956          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9957          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9958   "TARGET_ARM"
9959   "@
9960    mvn%d4\\t%0, %2
9961    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9962    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
9963   [(set_attr "conds" "use")
9964    (set_attr "length" "4,8,8")]
9965 )
9966
9967 (define_insn "*ifcompare_shift_move"
9968   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9969         (if_then_else:SI
9970          (match_operator 6 "arm_comparison_operator"
9971           [(match_operand:SI 4 "s_register_operand" "r,r")
9972            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9973          (match_operator:SI 7 "shift_operator"
9974           [(match_operand:SI 2 "s_register_operand" "r,r")
9975            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9976          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9977    (clobber (reg:CC CC_REGNUM))]
9978   "TARGET_ARM"
9979   "#"
9980   [(set_attr "conds" "clob")
9981    (set_attr "length" "8,12")]
9982 )
9983
9984 (define_insn "*if_shift_move"
9985   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9986         (if_then_else:SI
9987          (match_operator 5 "arm_comparison_operator"
9988           [(match_operand 6 "cc_register" "") (const_int 0)])
9989          (match_operator:SI 4 "shift_operator"
9990           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9991            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9992          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9993   "TARGET_ARM"
9994   "@
9995    mov%d5\\t%0, %2%S4
9996    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9997    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
9998   [(set_attr "conds" "use")
9999    (set_attr "shift" "2")
10000    (set_attr "length" "4,8,8")
10001    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
10002                       (const_string "alu_shift")
10003                       (const_string "alu_shift_reg")))]
10004 )
10005
10006 (define_insn "*ifcompare_move_shift"
10007   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10008         (if_then_else:SI
10009          (match_operator 6 "arm_comparison_operator"
10010           [(match_operand:SI 4 "s_register_operand" "r,r")
10011            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10012          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10013          (match_operator:SI 7 "shift_operator"
10014           [(match_operand:SI 2 "s_register_operand" "r,r")
10015            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
10016    (clobber (reg:CC CC_REGNUM))]
10017   "TARGET_ARM"
10018   "#"
10019   [(set_attr "conds" "clob")
10020    (set_attr "length" "8,12")]
10021 )
10022
10023 (define_insn "*if_move_shift"
10024   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10025         (if_then_else:SI
10026          (match_operator 5 "arm_comparison_operator"
10027           [(match_operand 6 "cc_register" "") (const_int 0)])
10028          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10029          (match_operator:SI 4 "shift_operator"
10030           [(match_operand:SI 2 "s_register_operand" "r,r,r")
10031            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
10032   "TARGET_ARM"
10033   "@
10034    mov%D5\\t%0, %2%S4
10035    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
10036    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
10037   [(set_attr "conds" "use")
10038    (set_attr "shift" "2")
10039    (set_attr "length" "4,8,8")
10040    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
10041                       (const_string "alu_shift")
10042                       (const_string "alu_shift_reg")))]
10043 )
10044
10045 (define_insn "*ifcompare_shift_shift"
10046   [(set (match_operand:SI 0 "s_register_operand" "=r")
10047         (if_then_else:SI
10048          (match_operator 7 "arm_comparison_operator"
10049           [(match_operand:SI 5 "s_register_operand" "r")
10050            (match_operand:SI 6 "arm_add_operand" "rIL")])
10051          (match_operator:SI 8 "shift_operator"
10052           [(match_operand:SI 1 "s_register_operand" "r")
10053            (match_operand:SI 2 "arm_rhs_operand" "rM")])
10054          (match_operator:SI 9 "shift_operator"
10055           [(match_operand:SI 3 "s_register_operand" "r")
10056            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
10057    (clobber (reg:CC CC_REGNUM))]
10058   "TARGET_ARM"
10059   "#"
10060   [(set_attr "conds" "clob")
10061    (set_attr "length" "12")]
10062 )
10063
10064 (define_insn "*if_shift_shift"
10065   [(set (match_operand:SI 0 "s_register_operand" "=r")
10066         (if_then_else:SI
10067          (match_operator 5 "arm_comparison_operator"
10068           [(match_operand 8 "cc_register" "") (const_int 0)])
10069          (match_operator:SI 6 "shift_operator"
10070           [(match_operand:SI 1 "s_register_operand" "r")
10071            (match_operand:SI 2 "arm_rhs_operand" "rM")])
10072          (match_operator:SI 7 "shift_operator"
10073           [(match_operand:SI 3 "s_register_operand" "r")
10074            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
10075   "TARGET_ARM"
10076   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
10077   [(set_attr "conds" "use")
10078    (set_attr "shift" "1")
10079    (set_attr "length" "8")
10080    (set (attr "type") (if_then_else
10081                         (and (match_operand 2 "const_int_operand" "")
10082                              (match_operand 4 "const_int_operand" ""))
10083                       (const_string "alu_shift")
10084                       (const_string "alu_shift_reg")))]
10085 )
10086
10087 (define_insn "*ifcompare_not_arith"
10088   [(set (match_operand:SI 0 "s_register_operand" "=r")
10089         (if_then_else:SI
10090          (match_operator 6 "arm_comparison_operator"
10091           [(match_operand:SI 4 "s_register_operand" "r")
10092            (match_operand:SI 5 "arm_add_operand" "rIL")])
10093          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10094          (match_operator:SI 7 "shiftable_operator"
10095           [(match_operand:SI 2 "s_register_operand" "r")
10096            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
10097    (clobber (reg:CC CC_REGNUM))]
10098   "TARGET_ARM"
10099   "#"
10100   [(set_attr "conds" "clob")
10101    (set_attr "length" "12")]
10102 )
10103
10104 (define_insn "*if_not_arith"
10105   [(set (match_operand:SI 0 "s_register_operand" "=r")
10106         (if_then_else:SI
10107          (match_operator 5 "arm_comparison_operator"
10108           [(match_operand 4 "cc_register" "") (const_int 0)])
10109          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10110          (match_operator:SI 6 "shiftable_operator"
10111           [(match_operand:SI 2 "s_register_operand" "r")
10112            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
10113   "TARGET_ARM"
10114   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
10115   [(set_attr "conds" "use")
10116    (set_attr "length" "8")]
10117 )
10118
10119 (define_insn "*ifcompare_arith_not"
10120   [(set (match_operand:SI 0 "s_register_operand" "=r")
10121         (if_then_else:SI
10122          (match_operator 6 "arm_comparison_operator"
10123           [(match_operand:SI 4 "s_register_operand" "r")
10124            (match_operand:SI 5 "arm_add_operand" "rIL")])
10125          (match_operator:SI 7 "shiftable_operator"
10126           [(match_operand:SI 2 "s_register_operand" "r")
10127            (match_operand:SI 3 "arm_rhs_operand" "rI")])
10128          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
10129    (clobber (reg:CC CC_REGNUM))]
10130   "TARGET_ARM"
10131   "#"
10132   [(set_attr "conds" "clob")
10133    (set_attr "length" "12")]
10134 )
10135
10136 (define_insn "*if_arith_not"
10137   [(set (match_operand:SI 0 "s_register_operand" "=r")
10138         (if_then_else:SI
10139          (match_operator 5 "arm_comparison_operator"
10140           [(match_operand 4 "cc_register" "") (const_int 0)])
10141          (match_operator:SI 6 "shiftable_operator"
10142           [(match_operand:SI 2 "s_register_operand" "r")
10143            (match_operand:SI 3 "arm_rhs_operand" "rI")])
10144          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
10145   "TARGET_ARM"
10146   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
10147   [(set_attr "conds" "use")
10148    (set_attr "length" "8")]
10149 )
10150
10151 (define_insn "*ifcompare_neg_move"
10152   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10153         (if_then_else:SI
10154          (match_operator 5 "arm_comparison_operator"
10155           [(match_operand:SI 3 "s_register_operand" "r,r")
10156            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10157          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10158          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
10159    (clobber (reg:CC CC_REGNUM))]
10160   "TARGET_ARM"
10161   "#"
10162   [(set_attr "conds" "clob")
10163    (set_attr "length" "8,12")]
10164 )
10165
10166 (define_insn "*if_neg_move"
10167   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10168         (if_then_else:SI
10169          (match_operator 4 "arm_comparison_operator"
10170           [(match_operand 3 "cc_register" "") (const_int 0)])
10171          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10172          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
10173   "TARGET_ARM"
10174   "@
10175    rsb%d4\\t%0, %2, #0
10176    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
10177    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
10178   [(set_attr "conds" "use")
10179    (set_attr "length" "4,8,8")]
10180 )
10181
10182 (define_insn "*ifcompare_move_neg"
10183   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10184         (if_then_else:SI
10185          (match_operator 5 "arm_comparison_operator"
10186           [(match_operand:SI 3 "s_register_operand" "r,r")
10187            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10188          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10189          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
10190    (clobber (reg:CC CC_REGNUM))]
10191   "TARGET_ARM"
10192   "#"
10193   [(set_attr "conds" "clob")
10194    (set_attr "length" "8,12")]
10195 )
10196
10197 (define_insn "*if_move_neg"
10198   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10199         (if_then_else:SI
10200          (match_operator 4 "arm_comparison_operator"
10201           [(match_operand 3 "cc_register" "") (const_int 0)])
10202          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10203          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
10204   "TARGET_ARM"
10205   "@
10206    rsb%D4\\t%0, %2, #0
10207    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
10208    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
10209   [(set_attr "conds" "use")
10210    (set_attr "length" "4,8,8")]
10211 )
10212
10213 (define_insn "*arith_adjacentmem"
10214   [(set (match_operand:SI 0 "s_register_operand" "=r")
10215         (match_operator:SI 1 "shiftable_operator"
10216          [(match_operand:SI 2 "memory_operand" "m")
10217           (match_operand:SI 3 "memory_operand" "m")]))
10218    (clobber (match_scratch:SI 4 "=r"))]
10219   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
10220   "*
10221   {
10222     rtx ldm[3];
10223     rtx arith[4];
10224     rtx base_reg;
10225     HOST_WIDE_INT val1 = 0, val2 = 0;
10226
10227     if (REGNO (operands[0]) > REGNO (operands[4]))
10228       {
10229         ldm[1] = operands[4];
10230         ldm[2] = operands[0];
10231       }
10232     else
10233       {
10234         ldm[1] = operands[0];
10235         ldm[2] = operands[4];
10236       }
10237
10238     base_reg = XEXP (operands[2], 0);
10239
10240     if (!REG_P (base_reg))
10241       {
10242         val1 = INTVAL (XEXP (base_reg, 1));
10243         base_reg = XEXP (base_reg, 0);
10244       }
10245
10246     if (!REG_P (XEXP (operands[3], 0)))
10247       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
10248
10249     arith[0] = operands[0];
10250     arith[3] = operands[1];
10251
10252     if (val1 < val2)
10253       {
10254         arith[1] = ldm[1];
10255         arith[2] = ldm[2];
10256       }
10257     else
10258       {
10259         arith[1] = ldm[2];
10260         arith[2] = ldm[1];
10261       }
10262
10263     ldm[0] = base_reg;
10264     if (val1 !=0 && val2 != 0)
10265       {
10266         rtx ops[3];
10267
10268         if (val1 == 4 || val2 == 4)
10269           /* Other val must be 8, since we know they are adjacent and neither
10270              is zero.  */
10271           output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
10272         else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
10273           {
10274             ldm[0] = ops[0] = operands[4];
10275             ops[1] = base_reg;
10276             ops[2] = GEN_INT (val1);
10277             output_add_immediate (ops);
10278             if (val1 < val2)
10279               output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
10280             else
10281               output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
10282           }
10283         else
10284           {
10285             /* Offset is out of range for a single add, so use two ldr.  */
10286             ops[0] = ldm[1];
10287             ops[1] = base_reg;
10288             ops[2] = GEN_INT (val1);
10289             output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10290             ops[0] = ldm[2];
10291             ops[2] = GEN_INT (val2);
10292             output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10293           }
10294       }
10295     else if (val1 != 0)
10296       {
10297         if (val1 < val2)
10298           output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
10299         else
10300           output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
10301       }
10302     else
10303       {
10304         if (val1 < val2)
10305           output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
10306         else
10307           output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
10308       }
10309     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10310     return \"\";
10311   }"
10312   [(set_attr "length" "12")
10313    (set_attr "predicable" "yes")
10314    (set_attr "type" "load1")]
10315 )
10316
10317 ; This pattern is never tried by combine, so do it as a peephole
10318
10319 (define_peephole2
10320   [(set (match_operand:SI 0 "arm_general_register_operand" "")
10321         (match_operand:SI 1 "arm_general_register_operand" ""))
10322    (set (reg:CC CC_REGNUM)
10323         (compare:CC (match_dup 1) (const_int 0)))]
10324   "TARGET_ARM"
10325   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10326               (set (match_dup 0) (match_dup 1))])]
10327   ""
10328 )
10329
10330 ; Peepholes to spot possible load- and store-multiples, if the ordering is
10331 ; reversed, check that the memory references aren't volatile.
10332
10333 (define_peephole
10334   [(set (match_operand:SI 0 "s_register_operand" "=rk")
10335         (match_operand:SI 4 "memory_operand" "m"))
10336    (set (match_operand:SI 1 "s_register_operand" "=rk")
10337         (match_operand:SI 5 "memory_operand" "m"))
10338    (set (match_operand:SI 2 "s_register_operand" "=rk")
10339         (match_operand:SI 6 "memory_operand" "m"))
10340    (set (match_operand:SI 3 "s_register_operand" "=rk")
10341         (match_operand:SI 7 "memory_operand" "m"))]
10342   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
10343   "*
10344   return emit_ldm_seq (operands, 4);
10345   "
10346 )
10347
10348 (define_peephole
10349   [(set (match_operand:SI 0 "s_register_operand" "=rk")
10350         (match_operand:SI 3 "memory_operand" "m"))
10351    (set (match_operand:SI 1 "s_register_operand" "=rk")
10352         (match_operand:SI 4 "memory_operand" "m"))
10353    (set (match_operand:SI 2 "s_register_operand" "=rk")
10354         (match_operand:SI 5 "memory_operand" "m"))]
10355   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
10356   "*
10357   return emit_ldm_seq (operands, 3);
10358   "
10359 )
10360
10361 (define_peephole
10362   [(set (match_operand:SI 0 "s_register_operand" "=rk")
10363         (match_operand:SI 2 "memory_operand" "m"))
10364    (set (match_operand:SI 1 "s_register_operand" "=rk")
10365         (match_operand:SI 3 "memory_operand" "m"))]
10366   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
10367   "*
10368   return emit_ldm_seq (operands, 2);
10369   "
10370 )
10371
10372 (define_peephole
10373   [(set (match_operand:SI 4 "memory_operand" "=m")
10374         (match_operand:SI 0 "s_register_operand" "rk"))
10375    (set (match_operand:SI 5 "memory_operand" "=m")
10376         (match_operand:SI 1 "s_register_operand" "rk"))
10377    (set (match_operand:SI 6 "memory_operand" "=m")
10378         (match_operand:SI 2 "s_register_operand" "rk"))
10379    (set (match_operand:SI 7 "memory_operand" "=m")
10380         (match_operand:SI 3 "s_register_operand" "rk"))]
10381   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
10382   "*
10383   return emit_stm_seq (operands, 4);
10384   "
10385 )
10386
10387 (define_peephole
10388   [(set (match_operand:SI 3 "memory_operand" "=m")
10389         (match_operand:SI 0 "s_register_operand" "rk"))
10390    (set (match_operand:SI 4 "memory_operand" "=m")
10391         (match_operand:SI 1 "s_register_operand" "rk"))
10392    (set (match_operand:SI 5 "memory_operand" "=m")
10393         (match_operand:SI 2 "s_register_operand" "rk"))]
10394   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
10395   "*
10396   return emit_stm_seq (operands, 3);
10397   "
10398 )
10399
10400 (define_peephole
10401   [(set (match_operand:SI 2 "memory_operand" "=m")
10402         (match_operand:SI 0 "s_register_operand" "rk"))
10403    (set (match_operand:SI 3 "memory_operand" "=m")
10404         (match_operand:SI 1 "s_register_operand" "rk"))]
10405   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
10406   "*
10407   return emit_stm_seq (operands, 2);
10408   "
10409 )
10410
10411 (define_split
10412   [(set (match_operand:SI 0 "s_register_operand" "")
10413         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10414                        (const_int 0))
10415                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
10416                          [(match_operand:SI 3 "s_register_operand" "")
10417                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
10418    (clobber (match_operand:SI 5 "s_register_operand" ""))]
10419   "TARGET_ARM"
10420   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10421    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10422                               (match_dup 5)))]
10423   ""
10424 )
10425
10426 ;; This split can be used because CC_Z mode implies that the following
10427 ;; branch will be an equality, or an unsigned inequality, so the sign
10428 ;; extension is not needed.
10429
10430 (define_split
10431   [(set (reg:CC_Z CC_REGNUM)
10432         (compare:CC_Z
10433          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
10434                     (const_int 24))
10435          (match_operand 1 "const_int_operand" "")))
10436    (clobber (match_scratch:SI 2 ""))]
10437   "TARGET_ARM
10438    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10439        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
10440   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
10441    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
10442   "
10443   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
10444   "
10445 )
10446 ;; ??? Check the patterns above for Thumb-2 usefulness
10447
10448 (define_expand "prologue"
10449   [(clobber (const_int 0))]
10450   "TARGET_EITHER"
10451   "if (TARGET_32BIT)
10452      arm_expand_prologue ();
10453    else
10454      thumb1_expand_prologue ();
10455   DONE;
10456   "
10457 )
10458
10459 (define_expand "epilogue"
10460   [(clobber (const_int 0))]
10461   "TARGET_EITHER"
10462   "
10463   if (crtl->calls_eh_return)
10464     emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
10465   if (TARGET_THUMB1)
10466     thumb1_expand_epilogue ();
10467   else if (USE_RETURN_INSN (FALSE))
10468     {
10469       emit_jump_insn (gen_return ());
10470       DONE;
10471     }
10472   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10473         gen_rtvec (1,
10474                 gen_rtx_RETURN (VOIDmode)),
10475         VUNSPEC_EPILOGUE));
10476   DONE;
10477   "
10478 )
10479
10480 ;; Note - although unspec_volatile's USE all hard registers,
10481 ;; USEs are ignored after relaod has completed.  Thus we need
10482 ;; to add an unspec of the link register to ensure that flow
10483 ;; does not think that it is unused by the sibcall branch that
10484 ;; will replace the standard function epilogue.
10485 (define_insn "sibcall_epilogue"
10486   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
10487               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10488   "TARGET_32BIT"
10489   "*
10490   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
10491     return output_return_instruction (const_true_rtx, FALSE, FALSE);
10492   return arm_output_epilogue (next_nonnote_insn (insn));
10493   "
10494 ;; Length is absolute worst case
10495   [(set_attr "length" "44")
10496    (set_attr "type" "block")
10497    ;; We don't clobber the conditions, but the potential length of this
10498    ;; operation is sufficient to make conditionalizing the sequence 
10499    ;; unlikely to be profitable.
10500    (set_attr "conds" "clob")]
10501 )
10502
10503 (define_insn "*epilogue_insns"
10504   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
10505   "TARGET_EITHER"
10506   "*
10507   if (TARGET_32BIT)
10508     return arm_output_epilogue (NULL);
10509   else /* TARGET_THUMB1 */
10510     return thumb_unexpanded_epilogue ();
10511   "
10512   ; Length is absolute worst case
10513   [(set_attr "length" "44")
10514    (set_attr "type" "block")
10515    ;; We don't clobber the conditions, but the potential length of this
10516    ;; operation is sufficient to make conditionalizing the sequence 
10517    ;; unlikely to be profitable.
10518    (set_attr "conds" "clob")]
10519 )
10520
10521 (define_expand "eh_epilogue"
10522   [(use (match_operand:SI 0 "register_operand" ""))
10523    (use (match_operand:SI 1 "register_operand" ""))
10524    (use (match_operand:SI 2 "register_operand" ""))]
10525   "TARGET_EITHER"
10526   "
10527   {
10528     cfun->machine->eh_epilogue_sp_ofs = operands[1];
10529     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10530       {
10531         rtx ra = gen_rtx_REG (Pmode, 2);
10532
10533         emit_move_insn (ra, operands[2]);
10534         operands[2] = ra;
10535       }
10536     /* This is a hack -- we may have crystalized the function type too
10537        early.  */
10538     cfun->machine->func_type = 0;
10539   }"
10540 )
10541
10542 ;; This split is only used during output to reduce the number of patterns
10543 ;; that need assembler instructions adding to them.  We allowed the setting
10544 ;; of the conditions to be implicit during rtl generation so that
10545 ;; the conditional compare patterns would work.  However this conflicts to
10546 ;; some extent with the conditional data operations, so we have to split them
10547 ;; up again here.
10548
10549 ;; ??? Need to audit these splitters for Thumb-2.  Why isn't normal
10550 ;; conditional execution sufficient?
10551
10552 (define_split
10553   [(set (match_operand:SI 0 "s_register_operand" "")
10554         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10555                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10556                          (match_dup 0)
10557                          (match_operand 4 "" "")))
10558    (clobber (reg:CC CC_REGNUM))]
10559   "TARGET_ARM && reload_completed"
10560   [(set (match_dup 5) (match_dup 6))
10561    (cond_exec (match_dup 7)
10562               (set (match_dup 0) (match_dup 4)))]
10563   "
10564   {
10565     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10566                                              operands[2], operands[3]);
10567     enum rtx_code rc = GET_CODE (operands[1]);
10568
10569     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10570     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10571     if (mode == CCFPmode || mode == CCFPEmode)
10572       rc = reverse_condition_maybe_unordered (rc);
10573     else
10574       rc = reverse_condition (rc);
10575
10576     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10577   }"
10578 )
10579
10580 (define_split
10581   [(set (match_operand:SI 0 "s_register_operand" "")
10582         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10583                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10584                          (match_operand 4 "" "")
10585                          (match_dup 0)))
10586    (clobber (reg:CC CC_REGNUM))]
10587   "TARGET_ARM && reload_completed"
10588   [(set (match_dup 5) (match_dup 6))
10589    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10590               (set (match_dup 0) (match_dup 4)))]
10591   "
10592   {
10593     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10594                                              operands[2], operands[3]);
10595
10596     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10597     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10598   }"
10599 )
10600
10601 (define_split
10602   [(set (match_operand:SI 0 "s_register_operand" "")
10603         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10604                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10605                          (match_operand 4 "" "")
10606                          (match_operand 5 "" "")))
10607    (clobber (reg:CC CC_REGNUM))]
10608   "TARGET_ARM && reload_completed"
10609   [(set (match_dup 6) (match_dup 7))
10610    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10611               (set (match_dup 0) (match_dup 4)))
10612    (cond_exec (match_dup 8)
10613               (set (match_dup 0) (match_dup 5)))]
10614   "
10615   {
10616     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10617                                              operands[2], operands[3]);
10618     enum rtx_code rc = GET_CODE (operands[1]);
10619
10620     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10621     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10622     if (mode == CCFPmode || mode == CCFPEmode)
10623       rc = reverse_condition_maybe_unordered (rc);
10624     else
10625       rc = reverse_condition (rc);
10626
10627     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10628   }"
10629 )
10630
10631 (define_split
10632   [(set (match_operand:SI 0 "s_register_operand" "")
10633         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10634                           [(match_operand:SI 2 "s_register_operand" "")
10635                            (match_operand:SI 3 "arm_add_operand" "")])
10636                          (match_operand:SI 4 "arm_rhs_operand" "")
10637                          (not:SI
10638                           (match_operand:SI 5 "s_register_operand" ""))))
10639    (clobber (reg:CC CC_REGNUM))]
10640   "TARGET_ARM && reload_completed"
10641   [(set (match_dup 6) (match_dup 7))
10642    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10643               (set (match_dup 0) (match_dup 4)))
10644    (cond_exec (match_dup 8)
10645               (set (match_dup 0) (not:SI (match_dup 5))))]
10646   "
10647   {
10648     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10649                                              operands[2], operands[3]);
10650     enum rtx_code rc = GET_CODE (operands[1]);
10651
10652     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10653     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10654     if (mode == CCFPmode || mode == CCFPEmode)
10655       rc = reverse_condition_maybe_unordered (rc);
10656     else
10657       rc = reverse_condition (rc);
10658
10659     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10660   }"
10661 )
10662
10663 (define_insn "*cond_move_not"
10664   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10665         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10666                           [(match_operand 3 "cc_register" "") (const_int 0)])
10667                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10668                          (not:SI
10669                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
10670   "TARGET_ARM"
10671   "@
10672    mvn%D4\\t%0, %2
10673    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
10674   [(set_attr "conds" "use")
10675    (set_attr "length" "4,8")]
10676 )
10677
10678 ;; The next two patterns occur when an AND operation is followed by a
10679 ;; scc insn sequence 
10680
10681 (define_insn "*sign_extract_onebit"
10682   [(set (match_operand:SI 0 "s_register_operand" "=r")
10683         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10684                          (const_int 1)
10685                          (match_operand:SI 2 "const_int_operand" "n")))
10686     (clobber (reg:CC CC_REGNUM))]
10687   "TARGET_ARM"
10688   "*
10689     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10690     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10691     return \"mvnne\\t%0, #0\";
10692   "
10693   [(set_attr "conds" "clob")
10694    (set_attr "length" "8")]
10695 )
10696
10697 (define_insn "*not_signextract_onebit"
10698   [(set (match_operand:SI 0 "s_register_operand" "=r")
10699         (not:SI
10700          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10701                           (const_int 1)
10702                           (match_operand:SI 2 "const_int_operand" "n"))))
10703    (clobber (reg:CC CC_REGNUM))]
10704   "TARGET_ARM"
10705   "*
10706     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10707     output_asm_insn (\"tst\\t%1, %2\", operands);
10708     output_asm_insn (\"mvneq\\t%0, #0\", operands);
10709     return \"movne\\t%0, #0\";
10710   "
10711   [(set_attr "conds" "clob")
10712    (set_attr "length" "12")]
10713 )
10714 ;; ??? The above patterns need auditing for Thumb-2
10715
10716 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
10717 ;; expressions.  For simplicity, the first register is also in the unspec
10718 ;; part.
10719 (define_insn "*push_multi"
10720   [(match_parallel 2 "multi_register_push"
10721     [(set (match_operand:BLK 0 "memory_operand" "=m")
10722           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
10723                       UNSPEC_PUSH_MULT))])]
10724   "TARGET_32BIT"
10725   "*
10726   {
10727     int num_saves = XVECLEN (operands[2], 0);
10728      
10729     /* For the StrongARM at least it is faster to
10730        use STR to store only a single register.
10731        In Thumb mode always use push, and the assembler will pick
10732        something appropriate.  */
10733     if (num_saves == 1 && TARGET_ARM)
10734       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10735     else
10736       {
10737         int i;
10738         char pattern[100];
10739
10740         if (TARGET_ARM)
10741             strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10742         else
10743             strcpy (pattern, \"push\\t{%1\");
10744
10745         for (i = 1; i < num_saves; i++)
10746           {
10747             strcat (pattern, \", %|\");
10748             strcat (pattern,
10749                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10750           }
10751
10752         strcat (pattern, \"}\");
10753         output_asm_insn (pattern, operands);
10754       }
10755
10756     return \"\";
10757   }"
10758   [(set_attr "type" "store4")]
10759 )
10760
10761 (define_insn "stack_tie"
10762   [(set (mem:BLK (scratch))
10763         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10764                      (match_operand:SI 1 "s_register_operand" "rk")]
10765                     UNSPEC_PRLG_STK))]
10766   ""
10767   ""
10768   [(set_attr "length" "0")]
10769 )
10770
10771 ;; Similarly for the floating point registers
10772 (define_insn "*push_fp_multi"
10773   [(match_parallel 2 "multi_register_push"
10774     [(set (match_operand:BLK 0 "memory_operand" "=m")
10775           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10776                       UNSPEC_PUSH_MULT))])]
10777   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
10778   "*
10779   {
10780     char pattern[100];
10781
10782     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10783     output_asm_insn (pattern, operands);
10784     return \"\";
10785   }"
10786   [(set_attr "type" "f_store")]
10787 )
10788
10789 ;; Special patterns for dealing with the constant pool
10790
10791 (define_insn "align_4"
10792   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10793   "TARGET_EITHER"
10794   "*
10795   assemble_align (32);
10796   return \"\";
10797   "
10798 )
10799
10800 (define_insn "align_8"
10801   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10802   "TARGET_EITHER"
10803   "*
10804   assemble_align (64);
10805   return \"\";
10806   "
10807 )
10808
10809 (define_insn "consttable_end"
10810   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10811   "TARGET_EITHER"
10812   "*
10813   making_const_table = FALSE;
10814   return \"\";
10815   "
10816 )
10817
10818 (define_insn "consttable_1"
10819   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10820   "TARGET_THUMB1"
10821   "*
10822   making_const_table = TRUE;
10823   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10824   assemble_zeros (3);
10825   return \"\";
10826   "
10827   [(set_attr "length" "4")]
10828 )
10829
10830 (define_insn "consttable_2"
10831   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10832   "TARGET_THUMB1"
10833   "*
10834   making_const_table = TRUE;
10835   gcc_assert (GET_MODE_CLASS (GET_MODE (operands[0])) != MODE_FLOAT);
10836   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10837   assemble_zeros (2);
10838   return \"\";
10839   "
10840   [(set_attr "length" "4")]
10841 )
10842
10843 (define_insn "consttable_4"
10844   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10845   "TARGET_EITHER"
10846   "*
10847   {
10848     rtx x = operands[0];
10849     making_const_table = TRUE;
10850     switch (GET_MODE_CLASS (GET_MODE (x)))
10851       {
10852       case MODE_FLOAT:
10853         if (GET_MODE (x) == HFmode)
10854           arm_emit_fp16_const (x);
10855         else
10856           {
10857             REAL_VALUE_TYPE r;
10858             REAL_VALUE_FROM_CONST_DOUBLE (r, x);
10859             assemble_real (r, GET_MODE (x), BITS_PER_WORD);
10860           }
10861         break;
10862       default:
10863         assemble_integer (x, 4, BITS_PER_WORD, 1);
10864         mark_symbol_refs_as_used (x);
10865         break;
10866       }
10867     return \"\";
10868   }"
10869   [(set_attr "length" "4")]
10870 )
10871
10872 (define_insn "consttable_8"
10873   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10874   "TARGET_EITHER"
10875   "*
10876   {
10877     making_const_table = TRUE;
10878     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10879       {
10880        case MODE_FLOAT:
10881         {
10882           REAL_VALUE_TYPE r;
10883           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10884           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10885           break;
10886         }
10887       default:
10888         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10889         break;
10890       }
10891     return \"\";
10892   }"
10893   [(set_attr "length" "8")]
10894 )
10895
10896 (define_insn "consttable_16"
10897   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
10898   "TARGET_EITHER"
10899   "*
10900   {
10901     making_const_table = TRUE;
10902     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10903       {
10904        case MODE_FLOAT:
10905         {
10906           REAL_VALUE_TYPE r;
10907           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10908           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10909           break;
10910         }
10911       default:
10912         assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
10913         break;
10914       }
10915     return \"\";
10916   }"
10917   [(set_attr "length" "16")]
10918 )
10919
10920 ;; Miscellaneous Thumb patterns
10921
10922 (define_expand "tablejump"
10923   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10924               (use (label_ref (match_operand 1 "" "")))])]
10925   "TARGET_THUMB1"
10926   "
10927   if (flag_pic)
10928     {
10929       /* Hopefully, CSE will eliminate this copy.  */
10930       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10931       rtx reg2 = gen_reg_rtx (SImode);
10932
10933       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10934       operands[0] = reg2;
10935     }
10936   "
10937 )
10938
10939 ;; NB never uses BX.
10940 (define_insn "*thumb1_tablejump"
10941   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10942    (use (label_ref (match_operand 1 "" "")))]
10943   "TARGET_THUMB1"
10944   "mov\\t%|pc, %0"
10945   [(set_attr "length" "2")]
10946 )
10947
10948 ;; V5 Instructions,
10949
10950 (define_insn "clzsi2"
10951   [(set (match_operand:SI 0 "s_register_operand" "=r")
10952         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10953   "TARGET_32BIT && arm_arch5"
10954   "clz%?\\t%0, %1"
10955   [(set_attr "predicable" "yes")
10956    (set_attr "insn" "clz")])
10957
10958 ;; V5E instructions.
10959
10960 (define_insn "prefetch"
10961   [(prefetch (match_operand:SI 0 "address_operand" "p")
10962              (match_operand:SI 1 "" "")
10963              (match_operand:SI 2 "" ""))]
10964   "TARGET_32BIT && arm_arch5e"
10965   "pld\\t%a0")
10966
10967 ;; General predication pattern
10968
10969 (define_cond_exec
10970   [(match_operator 0 "arm_comparison_operator"
10971     [(match_operand 1 "cc_register" "")
10972      (const_int 0)])]
10973   "TARGET_32BIT"
10974   ""
10975 )
10976
10977 (define_insn "prologue_use"
10978   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10979   ""
10980   "%@ %0 needed for prologue"
10981   [(set_attr "length" "0")]
10982 )
10983
10984
10985 ;; Patterns for exception handling
10986
10987 (define_expand "eh_return"
10988   [(use (match_operand 0 "general_operand" ""))]
10989   "TARGET_EITHER"
10990   "
10991   {
10992     if (TARGET_32BIT)
10993       emit_insn (gen_arm_eh_return (operands[0]));
10994     else
10995       emit_insn (gen_thumb_eh_return (operands[0]));
10996     DONE;
10997   }"
10998 )
10999                                    
11000 ;; We can't expand this before we know where the link register is stored.
11001 (define_insn_and_split "arm_eh_return"
11002   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
11003                     VUNSPEC_EH_RETURN)
11004    (clobber (match_scratch:SI 1 "=&r"))]
11005   "TARGET_ARM"
11006   "#"
11007   "&& reload_completed"
11008   [(const_int 0)]
11009   "
11010   {
11011     arm_set_return_address (operands[0], operands[1]);
11012     DONE;
11013   }"
11014 )
11015
11016 (define_insn_and_split "thumb_eh_return"
11017   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
11018                     VUNSPEC_EH_RETURN)
11019    (clobber (match_scratch:SI 1 "=&l"))]
11020   "TARGET_THUMB1"
11021   "#"
11022   "&& reload_completed"
11023   [(const_int 0)]
11024   "
11025   {
11026     thumb_set_return_address (operands[0], operands[1]);
11027     DONE;
11028   }"
11029 )
11030
11031 \f
11032 ;; TLS support
11033
11034 (define_insn "load_tp_hard"
11035   [(set (match_operand:SI 0 "register_operand" "=r")
11036         (unspec:SI [(const_int 0)] UNSPEC_TLS))]
11037   "TARGET_HARD_TP"
11038   "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
11039   [(set_attr "predicable" "yes")]
11040 )
11041
11042 ;; Doesn't clobber R1-R3.  Must use r0 for the first operand.
11043 (define_insn "load_tp_soft"
11044   [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
11045    (clobber (reg:SI LR_REGNUM))
11046    (clobber (reg:SI IP_REGNUM))
11047    (clobber (reg:CC CC_REGNUM))]
11048   "TARGET_SOFT_TP"
11049   "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
11050   [(set_attr "conds" "clob")]
11051 )
11052
11053 ;; Load the FPA co-processor patterns
11054 (include "fpa.md")
11055 ;; Load the Maverick co-processor patterns
11056 (include "cirrus.md")
11057 ;; Vector bits common to IWMMXT and Neon
11058 (include "vec-common.md")
11059 ;; Load the Intel Wireless Multimedia Extension patterns
11060 (include "iwmmxt.md")
11061 ;; Load the VFP co-processor patterns
11062 (include "vfp.md")
11063 ;; Thumb-2 patterns
11064 (include "thumb2.md")
11065 ;; Neon patterns
11066 (include "neon.md")
11067