OSDN Git Service

arm: Use REG_CFA_REGISTER instead of UNSPEC_STACK_ALIGN.
[pf3gnuchains/gcc-fork.git] / gcc / config / arm / arm.md
1 ;;- Machine description for ARM for GNU compiler
2 ;;  Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;;  2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
4 ;;  Free Software Foundation, Inc.
5 ;;  Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
6 ;;  and Martin Simmons (@harleqn.co.uk).
7 ;;  More major hacks by Richard Earnshaw (rearnsha@arm.com).
8
9 ;; This file is part of GCC.
10
11 ;; GCC is free software; you can redistribute it and/or modify it
12 ;; under the terms of the GNU General Public License as published
13 ;; by the Free Software Foundation; either version 3, or (at your
14 ;; option) any later version.
15
16 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
17 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
19 ;; License for more details.
20
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GCC; see the file COPYING3.  If not see
23 ;; <http://www.gnu.org/licenses/>.
24
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26
27 \f
28 ;;---------------------------------------------------------------------------
29 ;; Constants
30
31 ;; Register numbers
32 (define_constants
33   [(R0_REGNUM        0)         ; First CORE register
34    (R1_REGNUM        1)         ; Second CORE register
35    (IP_REGNUM       12)         ; Scratch register
36    (SP_REGNUM       13)         ; Stack pointer
37    (LR_REGNUM       14)         ; Return address register
38    (PC_REGNUM       15)         ; Program counter
39    (CC_REGNUM       24)         ; Condition code pseudo register
40    (LAST_ARM_REGNUM 15)         ;
41    (FPA_F0_REGNUM   16)         ; FIRST_FPA_REGNUM
42    (FPA_F7_REGNUM   23)         ; LAST_FPA_REGNUM
43   ]
44 )
45 ;; 3rd operand to select_dominance_cc_mode
46 (define_constants
47   [(DOM_CC_X_AND_Y  0)
48    (DOM_CC_NX_OR_Y  1)
49    (DOM_CC_X_OR_Y   2)
50   ]
51 )
52
53 ;; UNSPEC Usage:
54 ;; Note: sin and cos are no-longer used.
55 ;; Unspec enumerators for Neon are defined in neon.md.
56
57 (define_c_enum "unspec" [
58   UNSPEC_SIN            ; `sin' operation (MODE_FLOAT):
59                         ;   operand 0 is the result,
60                         ;   operand 1 the parameter.
61   UNPSEC_COS            ; `cos' operation (MODE_FLOAT):
62                         ;   operand 0 is the result,
63                         ;   operand 1 the parameter.
64   UNSPEC_PUSH_MULT      ; `push multiple' operation:
65                         ;   operand 0 is the first register,
66                         ;   subsequent registers are in parallel (use ...)
67                         ;   expressions.
68   UNSPEC_PIC_SYM        ; A symbol that has been treated properly for pic
69                         ; usage, that is, we will add the pic_register
70                         ; value to it before trying to dereference it.
71   UNSPEC_PIC_BASE       ; Add PC and all but the last operand together,
72                         ; The last operand is the number of a PIC_LABEL
73                         ; that points at the containing instruction.
74   UNSPEC_PRLG_STK       ; A special barrier that prevents frame accesses
75                         ; being scheduled before the stack adjustment insn.
76   UNSPEC_PROLOGUE_USE   ; As USE insns are not meaningful after reload,
77                         ; this unspec is used to prevent the deletion of
78                         ; instructions setting registers for EH handling
79                         ; and stack frame generation.  Operand 0 is the
80                         ; register to "use".
81   UNSPEC_CHECK_ARCH     ; Set CCs to indicate 26-bit or 32-bit mode.
82   UNSPEC_WSHUFH         ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
83   UNSPEC_WACC           ; Used by the intrinsic form of the iWMMXt WACC instruction.
84   UNSPEC_TMOVMSK        ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
85   UNSPEC_WSAD           ; Used by the intrinsic form of the iWMMXt WSAD instruction.
86   UNSPEC_WSADZ          ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
87   UNSPEC_WMACS          ; Used by the intrinsic form of the iWMMXt WMACS instruction.
88   UNSPEC_WMACU          ; Used by the intrinsic form of the iWMMXt WMACU instruction.
89   UNSPEC_WMACSZ         ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
90   UNSPEC_WMACUZ         ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
91   UNSPEC_CLRDI          ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
92   UNSPEC_WMADDS         ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
93   UNSPEC_WMADDU         ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
94   UNSPEC_TLS            ; A symbol that has been treated properly for TLS usage.
95   UNSPEC_PIC_LABEL      ; A label used for PIC access that does not appear in the
96                         ; instruction stream.
97   UNSPEC_PIC_OFFSET     ; A symbolic 12-bit OFFSET that has been treated
98                         ; correctly for PIC usage.
99   UNSPEC_GOTSYM_OFF     ; The offset of the start of the GOT from a
100                         ; a given symbolic address.
101   UNSPEC_THUMB1_CASESI  ; A Thumb1 compressed dispatch-table call.
102   UNSPEC_RBIT           ; rbit operation.
103   UNSPEC_SYMBOL_OFFSET  ; The offset of the start of the symbol from
104                         ; another symbolic address.
105   UNSPEC_MEMORY_BARRIER ; Represent a memory barrier.
106 ])
107
108 ;; UNSPEC_VOLATILE Usage:
109
110 (define_c_enum "unspecv" [
111   VUNSPEC_BLOCKAGE      ; `blockage' insn to prevent scheduling across an
112                         ;   insn in the code.
113   VUNSPEC_EPILOGUE      ; `epilogue' insn, used to represent any part of the
114                         ;   instruction epilogue sequence that isn't expanded
115                         ;   into normal RTL.  Used for both normal and sibcall
116                         ;   epilogues.
117   VUNSPEC_THUMB1_INTERWORK ; `prologue_thumb1_interwork' insn, used to swap
118                         ;   modes from arm to thumb.
119   VUNSPEC_ALIGN         ; `align' insn.  Used at the head of a minipool table
120                         ;   for inlined constants.
121   VUNSPEC_POOL_END      ; `end-of-table'.  Used to mark the end of a minipool
122                         ;   table.
123   VUNSPEC_POOL_1        ; `pool-entry(1)'.  An entry in the constant pool for
124                         ;   an 8-bit object.
125   VUNSPEC_POOL_2        ; `pool-entry(2)'.  An entry in the constant pool for
126                         ;   a 16-bit object.
127   VUNSPEC_POOL_4        ; `pool-entry(4)'.  An entry in the constant pool for
128                         ;   a 32-bit object.
129   VUNSPEC_POOL_8        ; `pool-entry(8)'.  An entry in the constant pool for
130                         ;   a 64-bit object.
131   VUNSPEC_POOL_16       ; `pool-entry(16)'.  An entry in the constant pool for
132                         ;   a 128-bit object.
133   VUNSPEC_TMRC          ; Used by the iWMMXt TMRC instruction.
134   VUNSPEC_TMCR          ; Used by the iWMMXt TMCR instruction.
135   VUNSPEC_ALIGN8        ; 8-byte alignment version of VUNSPEC_ALIGN
136   VUNSPEC_WCMP_EQ       ; Used by the iWMMXt WCMPEQ instructions
137   VUNSPEC_WCMP_GTU      ; Used by the iWMMXt WCMPGTU instructions
138   VUNSPEC_WCMP_GT       ; Used by the iwMMXT WCMPGT instructions
139   VUNSPEC_EH_RETURN     ; Use to override the return address for exception
140                         ; handling.
141   VUNSPEC_SYNC_COMPARE_AND_SWAP    ; Represent an atomic compare swap.
142   VUNSPEC_SYNC_LOCK                ; Represent a sync_lock_test_and_set.
143   VUNSPEC_SYNC_OP                  ; Represent a sync_<op>
144   VUNSPEC_SYNC_NEW_OP              ; Represent a sync_new_<op>
145   VUNSPEC_SYNC_OLD_OP              ; Represent a sync_old_<op>
146 ])
147 \f
148 ;;---------------------------------------------------------------------------
149 ;; Attributes
150
151 ;; Processor type.  This is created automatically from arm-cores.def.
152 (include "arm-tune.md")
153
154 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
155 ; generating ARM code.  This is used to control the length of some insn
156 ; patterns that share the same RTL in both ARM and Thumb code.
157 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
158
159 ; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6.
160 (define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6")))
161
162 ; IS_THUMB1 is set to 'yes' iff we are generating Thumb-1 code.
163 (define_attr "is_thumb1" "no,yes" (const (symbol_ref "thumb1_code")))
164
165 ;; Operand number of an input operand that is shifted.  Zero if the
166 ;; given instruction does not shift one of its input operands.
167 (define_attr "shift" "" (const_int 0))
168
169 ; Floating Point Unit.  If we only have floating point emulation, then there
170 ; is no point in scheduling the floating point insns.  (Well, for best
171 ; performance we should try and group them together).
172 (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
173   (const (symbol_ref "arm_fpu_attr")))
174
175 (define_attr "sync_result"          "none,0,1,2,3,4,5" (const_string "none"))
176 (define_attr "sync_memory"          "none,0,1,2,3,4,5" (const_string "none"))
177 (define_attr "sync_required_value"  "none,0,1,2,3,4,5" (const_string "none"))
178 (define_attr "sync_new_value"       "none,0,1,2,3,4,5" (const_string "none"))
179 (define_attr "sync_t1"              "none,0,1,2,3,4,5" (const_string "none"))
180 (define_attr "sync_t2"              "none,0,1,2,3,4,5" (const_string "none"))
181 (define_attr "sync_release_barrier" "yes,no"           (const_string "yes"))
182 (define_attr "sync_op"              "none,add,sub,ior,xor,and,nand"
183                                     (const_string "none"))
184
185 ; LENGTH of an instruction (in bytes)
186 (define_attr "length" ""
187   (cond [(not (eq_attr "sync_memory" "none"))
188            (symbol_ref "arm_sync_loop_insns (insn, operands) * 4")
189         ] (const_int 4)))
190
191 ; The architecture which supports the instruction (or alternative).
192 ; This can be "a" for ARM, "t" for either of the Thumbs, "32" for
193 ; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode.  "v6"
194 ; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without
195 ; arm_arch6.  This attribute is used to compute attribute "enabled",
196 ; use type "any" to enable an alternative in all cases.
197 (define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,onlya8,nota8"
198   (const_string "any"))
199
200 (define_attr "arch_enabled" "no,yes"
201   (cond [(eq_attr "arch" "any")
202          (const_string "yes")
203
204          (and (eq_attr "arch" "a")
205               (ne (symbol_ref "TARGET_ARM") (const_int 0)))
206          (const_string "yes")
207
208          (and (eq_attr "arch" "t")
209               (ne (symbol_ref "TARGET_THUMB") (const_int 0)))
210          (const_string "yes")
211
212          (and (eq_attr "arch" "t1")
213               (ne (symbol_ref "TARGET_THUMB1") (const_int 0)))
214          (const_string "yes")
215
216          (and (eq_attr "arch" "t2")
217               (ne (symbol_ref "TARGET_THUMB2") (const_int 0)))
218          (const_string "yes")
219
220          (and (eq_attr "arch" "32")
221               (ne (symbol_ref "TARGET_32BIT") (const_int 0)))
222          (const_string "yes")
223
224          (and (eq_attr "arch" "v6")
225               (ne (symbol_ref "(TARGET_32BIT && arm_arch6)") (const_int 0)))
226          (const_string "yes")
227
228          (and (eq_attr "arch" "nov6")
229               (ne (symbol_ref "(TARGET_32BIT && !arm_arch6)") (const_int 0)))
230          (const_string "yes")
231
232          (and (eq_attr "arch" "onlya8")
233               (eq_attr "tune" "cortexa8"))
234          (const_string "yes")
235
236          (and (eq_attr "arch" "nota8")
237               (not (eq_attr "tune" "cortexa8")))
238          (const_string "yes")]
239         (const_string "no")))
240
241 ; Allows an insn to disable certain alternatives for reasons other than
242 ; arch support.
243 (define_attr "insn_enabled" "no,yes"
244   (const_string "yes"))
245
246 ; Enable all alternatives that are both arch_enabled and insn_enabled.
247  (define_attr "enabled" "no,yes"
248    (if_then_else (eq_attr "insn_enabled" "yes")
249                (if_then_else (eq_attr "arch_enabled" "yes")
250                              (const_string "yes")
251                              (const_string "no"))
252                 (const_string "no")))
253
254 ; POOL_RANGE is how far away from a constant pool entry that this insn
255 ; can be placed.  If the distance is zero, then this insn will never
256 ; reference the pool.
257 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
258 ; before its address.
259 (define_attr "arm_pool_range" "" (const_int 0))
260 (define_attr "thumb2_pool_range" "" (const_int 0))
261 (define_attr "arm_neg_pool_range" "" (const_int 0))
262 (define_attr "thumb2_neg_pool_range" "" (const_int 0))
263
264 (define_attr "pool_range" ""
265   (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_pool_range")]
266         (attr "arm_pool_range")))
267 (define_attr "neg_pool_range" ""
268   (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_neg_pool_range")]
269         (attr "arm_neg_pool_range")))
270
271 ; An assembler sequence may clobber the condition codes without us knowing.
272 ; If such an insn references the pool, then we have no way of knowing how,
273 ; so use the most conservative value for pool_range.
274 (define_asm_attributes
275  [(set_attr "conds" "clob")
276   (set_attr "length" "4")
277   (set_attr "pool_range" "250")])
278
279 ;; The instruction used to implement a particular pattern.  This
280 ;; information is used by pipeline descriptions to provide accurate
281 ;; scheduling information.
282
283 (define_attr "insn"
284         "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"
285         (const_string "other"))
286
287 ; TYPE attribute is used to detect floating point instructions which, if
288 ; running on a co-processor can run in parallel with other, basic instructions
289 ; If write-buffer scheduling is enabled then it can also be used in the
290 ; scheduling of writes.
291
292 ; Classification of each insn
293 ; Note: vfp.md has different meanings for some of these, and some further
294 ; types as well.  See that file for details.
295 ; alu           any alu  instruction that doesn't hit memory or fp
296 ;               regs or have a shifted source operand
297 ; alu_shift     any data instruction that doesn't hit memory or fp
298 ;               regs, but has a source operand shifted by a constant
299 ; alu_shift_reg any data instruction that doesn't hit memory or fp
300 ;               regs, but has a source operand shifted by a register value
301 ; mult          a multiply instruction
302 ; block         blockage insn, this blocks all functional units
303 ; float         a floating point arithmetic operation (subject to expansion)
304 ; fdivd         DFmode floating point division
305 ; fdivs         SFmode floating point division
306 ; fmul          Floating point multiply
307 ; ffmul         Fast floating point multiply
308 ; farith        Floating point arithmetic (4 cycle)
309 ; ffarith       Fast floating point arithmetic (2 cycle)
310 ; float_em      a floating point arithmetic operation that is normally emulated
311 ;               even on a machine with an fpa.
312 ; f_fpa_load    a floating point load from memory. Only for the FPA.
313 ; f_fpa_store   a floating point store to memory. Only for the FPA.
314 ; f_load[sd]    A single/double load from memory. Used for VFP unit.
315 ; f_store[sd]   A single/double store to memory. Used for VFP unit.
316 ; f_flag        a transfer of co-processor flags to the CPSR
317 ; f_mem_r       a transfer of a floating point register to a real reg via mem
318 ; r_mem_f       the reverse of f_mem_r
319 ; f_2_r         fast transfer float to arm (no memory needed)
320 ; r_2_f         fast transfer arm to float
321 ; f_cvt         convert floating<->integral
322 ; branch        a branch
323 ; call          a subroutine call
324 ; load_byte     load byte(s) from memory to arm registers
325 ; load1         load 1 word from memory to arm registers
326 ; load2         load 2 words from memory to arm registers
327 ; load3         load 3 words from memory to arm registers
328 ; load4         load 4 words from memory to arm registers
329 ; store         store 1 word to memory from arm registers
330 ; store2        store 2 words
331 ; store3        store 3 words
332 ; store4        store 4 (or more) words
333 ;  Additions for Cirrus Maverick co-processor:
334 ; mav_farith    Floating point arithmetic (4 cycle)
335 ; mav_dmult     Double multiplies (7 cycle)
336 ;
337
338 (define_attr "type"
339         "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_fpa_load,f_fpa_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"
340         (if_then_else 
341          (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
342          (const_string "mult")
343          (const_string "alu")))
344
345 ; Load scheduling, set from the arm_ld_sched variable
346 ; initialized by arm_option_override()
347 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
348
349 ;; Classification of NEON instructions for scheduling purposes.
350 ;; Do not set this attribute and the "type" attribute together in
351 ;; any one instruction pattern.
352 (define_attr "neon_type"
353    "neon_int_1,\
354    neon_int_2,\
355    neon_int_3,\
356    neon_int_4,\
357    neon_int_5,\
358    neon_vqneg_vqabs,\
359    neon_vmov,\
360    neon_vaba,\
361    neon_vsma,\
362    neon_vaba_qqq,\
363    neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
364    neon_mul_qqq_8_16_32_ddd_32,\
365    neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,\
366    neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
367    neon_mla_qqq_8_16,\
368    neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,\
369    neon_mla_qqq_32_qqd_32_scalar,\
370    neon_mul_ddd_16_scalar_32_16_long_scalar,\
371    neon_mul_qqd_32_scalar,\
372    neon_mla_ddd_16_scalar_qdd_32_16_long_scalar,\
373    neon_shift_1,\
374    neon_shift_2,\
375    neon_shift_3,\
376    neon_vshl_ddd,\
377    neon_vqshl_vrshl_vqrshl_qqq,\
378    neon_vsra_vrsra,\
379    neon_fp_vadd_ddd_vabs_dd,\
380    neon_fp_vadd_qqq_vabs_qq,\
381    neon_fp_vsum,\
382    neon_fp_vmul_ddd,\
383    neon_fp_vmul_qqd,\
384    neon_fp_vmla_ddd,\
385    neon_fp_vmla_qqq,\
386    neon_fp_vmla_ddd_scalar,\
387    neon_fp_vmla_qqq_scalar,\
388    neon_fp_vrecps_vrsqrts_ddd,\
389    neon_fp_vrecps_vrsqrts_qqq,\
390    neon_bp_simple,\
391    neon_bp_2cycle,\
392    neon_bp_3cycle,\
393    neon_ldr,\
394    neon_str,\
395    neon_vld1_1_2_regs,\
396    neon_vld1_3_4_regs,\
397    neon_vld2_2_regs_vld1_vld2_all_lanes,\
398    neon_vld2_4_regs,\
399    neon_vld3_vld4,\
400    neon_vst1_1_2_regs_vst2_2_regs,\
401    neon_vst1_3_4_regs,\
402    neon_vst2_4_regs_vst3_vst4,\
403    neon_vst3_vst4,\
404    neon_vld1_vld2_lane,\
405    neon_vld3_vld4_lane,\
406    neon_vst1_vst2_lane,\
407    neon_vst3_vst4_lane,\
408    neon_vld3_vld4_all_lanes,\
409    neon_mcr,\
410    neon_mcr_2_mcrr,\
411    neon_mrc,\
412    neon_mrrc,\
413    neon_ldm_2,\
414    neon_stm_2,\
415    none"
416  (const_string "none"))
417
418 ; condition codes: this one is used by final_prescan_insn to speed up
419 ; conditionalizing instructions.  It saves having to scan the rtl to see if
420 ; it uses or alters the condition codes.
421
422 ; USE means that the condition codes are used by the insn in the process of
423 ;   outputting code, this means (at present) that we can't use the insn in
424 ;   inlined branches
425 ;
426 ; SET means that the purpose of the insn is to set the condition codes in a
427 ;   well defined manner.
428 ;
429 ; CLOB means that the condition codes are altered in an undefined manner, if
430 ;   they are altered at all
431 ;
432 ; UNCONDITIONAL means the instruction can not be conditionally executed and
433 ;   that the instruction does not use or alter the condition codes.
434 ;
435 ; NOCOND means that the instruction does not use or alter the condition
436 ;   codes but can be converted into a conditionally exectuted instruction.
437
438 (define_attr "conds" "use,set,clob,unconditional,nocond"
439         (if_then_else
440          (ior (eq_attr "is_thumb1" "yes")
441               (eq_attr "type" "call"))
442          (const_string "clob")
443          (if_then_else (eq_attr "neon_type" "none")
444           (const_string "nocond")
445           (const_string "unconditional"))))
446
447 ; Predicable means that the insn can be conditionally executed based on
448 ; an automatically added predicate (additional patterns are generated by 
449 ; gen...).  We default to 'no' because no Thumb patterns match this rule
450 ; and not all ARM patterns do.
451 (define_attr "predicable" "no,yes" (const_string "no"))
452
453 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
454 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
455 ; suffer blockages enough to warrant modelling this (and it can adversely
456 ; affect the schedule).
457 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
458
459 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
460 ; to stall the processor.  Used with model_wbuf above.
461 (define_attr "write_conflict" "no,yes"
462   (if_then_else (eq_attr "type"
463                  "block,float_em,f_fpa_load,f_fpa_store,f_mem_r,r_mem_f,call,load1")
464                 (const_string "yes")
465                 (const_string "no")))
466
467 ; Classify the insns into those that take one cycle and those that take more
468 ; than one on the main cpu execution unit.
469 (define_attr "core_cycles" "single,multi"
470   (if_then_else (eq_attr "type"
471                  "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
472                 (const_string "single")
473                 (const_string "multi")))
474
475 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
476 ;; distant label.  Only applicable to Thumb code.
477 (define_attr "far_jump" "yes,no" (const_string "no"))
478
479
480 ;; The number of machine instructions this pattern expands to.
481 ;; Used for Thumb-2 conditional execution.
482 (define_attr "ce_count" "" (const_int 1))
483
484 ;;---------------------------------------------------------------------------
485 ;; Mode iterators
486
487 (include "iterators.md")
488
489 ;;---------------------------------------------------------------------------
490 ;; Predicates
491
492 (include "predicates.md")
493 (include "constraints.md")
494
495 ;;---------------------------------------------------------------------------
496 ;; Pipeline descriptions
497
498 (define_attr "tune_cortexr4" "yes,no"
499   (const (if_then_else
500           (eq_attr "tune" "cortexr4,cortexr4f,cortexr5")
501           (const_string "yes")
502           (const_string "no"))))
503
504 ;; True if the generic scheduling description should be used.
505
506 (define_attr "generic_sched" "yes,no"
507   (const (if_then_else
508           (ior (eq_attr "tune" "fa526,fa626,fa606te,fa626te,fmp626,fa726te,arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa5,cortexa8,cortexa9,cortexm4")
509                (eq_attr "tune_cortexr4" "yes"))
510           (const_string "no")
511           (const_string "yes"))))
512
513 (define_attr "generic_vfp" "yes,no"
514   (const (if_then_else
515           (and (eq_attr "fpu" "vfp")
516                (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa8,cortexa9,cortexm4")
517                (eq_attr "tune_cortexr4" "no"))
518           (const_string "yes")
519           (const_string "no"))))
520
521 (include "arm-generic.md")
522 (include "arm926ejs.md")
523 (include "arm1020e.md")
524 (include "arm1026ejs.md")
525 (include "arm1136jfs.md")
526 (include "fa526.md")
527 (include "fa606te.md")
528 (include "fa626te.md")
529 (include "fmp626.md")
530 (include "fa726te.md")
531 (include "cortex-a5.md")
532 (include "cortex-a8.md")
533 (include "cortex-a9.md")
534 (include "cortex-r4.md")
535 (include "cortex-r4f.md")
536 (include "cortex-m4.md")
537 (include "cortex-m4-fpu.md")
538 (include "vfp11.md")
539
540 \f
541 ;;---------------------------------------------------------------------------
542 ;; Insn patterns
543 ;;
544 ;; Addition insns.
545
546 ;; Note: For DImode insns, there is normally no reason why operands should
547 ;; not be in the same register, what we don't want is for something being
548 ;; written to partially overlap something that is an input.
549 ;; Cirrus 64bit additions should not be split because we have a native
550 ;; 64bit addition instructions.
551
552 (define_expand "adddi3"
553  [(parallel
554    [(set (match_operand:DI           0 "s_register_operand" "")
555           (plus:DI (match_operand:DI 1 "s_register_operand" "")
556                    (match_operand:DI 2 "s_register_operand" "")))
557     (clobber (reg:CC CC_REGNUM))])]
558   "TARGET_EITHER"
559   "
560   if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
561     {
562       if (!cirrus_fp_register (operands[0], DImode))
563         operands[0] = force_reg (DImode, operands[0]);
564       if (!cirrus_fp_register (operands[1], DImode))
565         operands[1] = force_reg (DImode, operands[1]);
566       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
567       DONE;
568     }
569
570   if (TARGET_THUMB1)
571     {
572       if (GET_CODE (operands[1]) != REG)
573         operands[1] = force_reg (DImode, operands[1]);
574       if (GET_CODE (operands[2]) != REG)
575         operands[2] = force_reg (DImode, operands[2]);
576      }
577   "
578 )
579
580 (define_insn "*thumb1_adddi3"
581   [(set (match_operand:DI          0 "register_operand" "=l")
582         (plus:DI (match_operand:DI 1 "register_operand" "%0")
583                  (match_operand:DI 2 "register_operand" "l")))
584    (clobber (reg:CC CC_REGNUM))
585   ]
586   "TARGET_THUMB1"
587   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
588   [(set_attr "length" "4")]
589 )
590
591 (define_insn_and_split "*arm_adddi3"
592   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
593         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
594                  (match_operand:DI 2 "s_register_operand" "r,  0")))
595    (clobber (reg:CC CC_REGNUM))]
596   "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK) && !TARGET_NEON"
597   "#"
598   "TARGET_32BIT && reload_completed
599    && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
600   [(parallel [(set (reg:CC_C CC_REGNUM)
601                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
602                                  (match_dup 1)))
603               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
604    (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
605                                (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
606   "
607   {
608     operands[3] = gen_highpart (SImode, operands[0]);
609     operands[0] = gen_lowpart (SImode, operands[0]);
610     operands[4] = gen_highpart (SImode, operands[1]);
611     operands[1] = gen_lowpart (SImode, operands[1]);
612     operands[5] = gen_highpart (SImode, operands[2]);
613     operands[2] = gen_lowpart (SImode, operands[2]);
614   }"
615   [(set_attr "conds" "clob")
616    (set_attr "length" "8")]
617 )
618
619 (define_insn_and_split "*adddi_sesidi_di"
620   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
621         (plus:DI (sign_extend:DI
622                   (match_operand:SI 2 "s_register_operand" "r,r"))
623                  (match_operand:DI 1 "s_register_operand" "0,r")))
624    (clobber (reg:CC CC_REGNUM))]
625   "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
626   "#"
627   "TARGET_32BIT && reload_completed"
628   [(parallel [(set (reg:CC_C CC_REGNUM)
629                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
630                                  (match_dup 1)))
631               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
632    (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
633                                                      (const_int 31))
634                                         (match_dup 4))
635                                (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
636   "
637   {
638     operands[3] = gen_highpart (SImode, operands[0]);
639     operands[0] = gen_lowpart (SImode, operands[0]);
640     operands[4] = gen_highpart (SImode, operands[1]);
641     operands[1] = gen_lowpart (SImode, operands[1]);
642     operands[2] = gen_lowpart (SImode, operands[2]);
643   }"
644   [(set_attr "conds" "clob")
645    (set_attr "length" "8")]
646 )
647
648 (define_insn_and_split "*adddi_zesidi_di"
649   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
650         (plus:DI (zero_extend:DI
651                   (match_operand:SI 2 "s_register_operand" "r,r"))
652                  (match_operand:DI 1 "s_register_operand" "0,r")))
653    (clobber (reg:CC CC_REGNUM))]
654   "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
655   "#"
656   "TARGET_32BIT && reload_completed"
657   [(parallel [(set (reg:CC_C CC_REGNUM)
658                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
659                                  (match_dup 1)))
660               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
661    (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
662                                (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
663   "
664   {
665     operands[3] = gen_highpart (SImode, operands[0]);
666     operands[0] = gen_lowpart (SImode, operands[0]);
667     operands[4] = gen_highpart (SImode, operands[1]);
668     operands[1] = gen_lowpart (SImode, operands[1]);
669     operands[2] = gen_lowpart (SImode, operands[2]);
670   }"
671   [(set_attr "conds" "clob")
672    (set_attr "length" "8")]
673 )
674
675 (define_expand "addsi3"
676   [(set (match_operand:SI          0 "s_register_operand" "")
677         (plus:SI (match_operand:SI 1 "s_register_operand" "")
678                  (match_operand:SI 2 "reg_or_int_operand" "")))]
679   "TARGET_EITHER"
680   "
681   if (TARGET_32BIT && GET_CODE (operands[2]) == CONST_INT)
682     {
683       arm_split_constant (PLUS, SImode, NULL_RTX,
684                           INTVAL (operands[2]), operands[0], operands[1],
685                           optimize && can_create_pseudo_p ());
686       DONE;
687     }
688   "
689 )
690
691 ; If there is a scratch available, this will be faster than synthesizing the
692 ; addition.
693 (define_peephole2
694   [(match_scratch:SI 3 "r")
695    (set (match_operand:SI          0 "arm_general_register_operand" "")
696         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
697                  (match_operand:SI 2 "const_int_operand"  "")))]
698   "TARGET_32BIT &&
699    !(const_ok_for_arm (INTVAL (operands[2]))
700      || const_ok_for_arm (-INTVAL (operands[2])))
701     && const_ok_for_arm (~INTVAL (operands[2]))"
702   [(set (match_dup 3) (match_dup 2))
703    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
704   ""
705 )
706
707 ;; The r/r/k alternative is required when reloading the address
708 ;;  (plus (reg rN) (reg sp)) into (reg rN).  In this case reload will
709 ;; put the duplicated register first, and not try the commutative version.
710 (define_insn_and_split "*arm_addsi3"
711   [(set (match_operand:SI          0 "s_register_operand" "=r, k,r,r, k,r")
712         (plus:SI (match_operand:SI 1 "s_register_operand" "%rk,k,r,rk,k,rk")
713                  (match_operand:SI 2 "reg_or_int_operand" "rI,rI,k,L, L,?n")))]
714   "TARGET_32BIT"
715   "@
716    add%?\\t%0, %1, %2
717    add%?\\t%0, %1, %2
718    add%?\\t%0, %2, %1
719    sub%?\\t%0, %1, #%n2
720    sub%?\\t%0, %1, #%n2
721    #"
722   "TARGET_32BIT
723    && GET_CODE (operands[2]) == CONST_INT
724    && !(const_ok_for_arm (INTVAL (operands[2]))
725         || const_ok_for_arm (-INTVAL (operands[2])))
726    && (reload_completed || !arm_eliminable_register (operands[1]))"
727   [(clobber (const_int 0))]
728   "
729   arm_split_constant (PLUS, SImode, curr_insn,
730                       INTVAL (operands[2]), operands[0],
731                       operands[1], 0);
732   DONE;
733   "
734   [(set_attr "length" "4,4,4,4,4,16")
735    (set_attr "predicable" "yes")]
736 )
737
738 (define_insn_and_split "*thumb1_addsi3"
739   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*rk,*hk,l,k,l,l,l")
740         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,k,k,0,l,k")
741                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,M,O,Pa,Pb,Pc")))]
742   "TARGET_THUMB1"
743   "*
744    static const char * const asms[] = 
745    {
746      \"add\\t%0, %0, %2\",
747      \"sub\\t%0, %0, #%n2\",
748      \"add\\t%0, %1, %2\",
749      \"add\\t%0, %0, %2\",
750      \"add\\t%0, %0, %2\",
751      \"add\\t%0, %1, %2\",
752      \"add\\t%0, %1, %2\",
753      \"#\",
754      \"#\",
755      \"#\"
756    };
757    if ((which_alternative == 2 || which_alternative == 6)
758        && GET_CODE (operands[2]) == CONST_INT
759        && INTVAL (operands[2]) < 0)
760      return \"sub\\t%0, %1, #%n2\";
761    return asms[which_alternative];
762   "
763   "&& reload_completed && CONST_INT_P (operands[2])
764    && ((operands[1] != stack_pointer_rtx
765         && (INTVAL (operands[2]) > 255 || INTVAL (operands[2]) < -255))
766        || (operands[1] == stack_pointer_rtx
767            && INTVAL (operands[2]) > 1020))"
768   [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
769    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
770   {
771     HOST_WIDE_INT offset = INTVAL (operands[2]);
772     if (operands[1] == stack_pointer_rtx)
773       offset -= 1020;
774     else
775       {
776         if (offset > 255)
777           offset = 255;
778         else if (offset < -255)
779           offset = -255;
780       }
781     operands[3] = GEN_INT (offset);
782     operands[2] = GEN_INT (INTVAL (operands[2]) - offset);
783   }
784   [(set_attr "length" "2,2,2,2,2,2,2,4,4,4")]
785 )
786
787 ;; Reloading and elimination of the frame pointer can
788 ;; sometimes cause this optimization to be missed.
789 (define_peephole2
790   [(set (match_operand:SI 0 "arm_general_register_operand" "")
791         (match_operand:SI 1 "const_int_operand" ""))
792    (set (match_dup 0)
793         (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
794   "TARGET_THUMB1
795    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
796    && (INTVAL (operands[1]) & 3) == 0"
797   [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
798   ""
799 )
800
801 (define_insn "addsi3_compare0"
802   [(set (reg:CC_NOOV CC_REGNUM)
803         (compare:CC_NOOV
804          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
805                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
806          (const_int 0)))
807    (set (match_operand:SI 0 "s_register_operand" "=r,r")
808         (plus:SI (match_dup 1) (match_dup 2)))]
809   "TARGET_ARM"
810   "@
811    add%.\\t%0, %1, %2
812    sub%.\\t%0, %1, #%n2"
813   [(set_attr "conds" "set")]
814 )
815
816 (define_insn "*addsi3_compare0_scratch"
817   [(set (reg:CC_NOOV CC_REGNUM)
818         (compare:CC_NOOV
819          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
820                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
821          (const_int 0)))]
822   "TARGET_ARM"
823   "@
824    cmn%?\\t%0, %1
825    cmp%?\\t%0, #%n1"
826   [(set_attr "conds" "set")]
827 )
828
829 (define_insn "*compare_negsi_si"
830   [(set (reg:CC_Z CC_REGNUM)
831         (compare:CC_Z
832          (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
833          (match_operand:SI 1 "s_register_operand" "r")))]
834   "TARGET_32BIT"
835   "cmn%?\\t%1, %0"
836   [(set_attr "conds" "set")]
837 )
838
839 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
840 ;; addend is a constant.
841 (define_insn "*cmpsi2_addneg"
842   [(set (reg:CC CC_REGNUM)
843         (compare:CC
844          (match_operand:SI 1 "s_register_operand" "r,r")
845          (match_operand:SI 2 "arm_addimm_operand" "L,I")))
846    (set (match_operand:SI 0 "s_register_operand" "=r,r")
847         (plus:SI (match_dup 1)
848                  (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
849   "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
850   "@
851    add%.\\t%0, %1, %3
852    sub%.\\t%0, %1, #%n3"
853   [(set_attr "conds" "set")]
854 )
855
856 ;; Convert the sequence
857 ;;  sub  rd, rn, #1
858 ;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
859 ;;  bne  dest
860 ;; into
861 ;;  subs rd, rn, #1
862 ;;  bcs  dest   ((unsigned)rn >= 1)
863 ;; similarly for the beq variant using bcc.
864 ;; This is a common looping idiom (while (n--))
865 (define_peephole2
866   [(set (match_operand:SI 0 "arm_general_register_operand" "")
867         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
868                  (const_int -1)))
869    (set (match_operand 2 "cc_register" "")
870         (compare (match_dup 0) (const_int -1)))
871    (set (pc)
872         (if_then_else (match_operator 3 "equality_operator"
873                        [(match_dup 2) (const_int 0)])
874                       (match_operand 4 "" "")
875                       (match_operand 5 "" "")))]
876   "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
877   [(parallel[
878     (set (match_dup 2)
879          (compare:CC
880           (match_dup 1) (const_int 1)))
881     (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
882    (set (pc)
883         (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
884                       (match_dup 4)
885                       (match_dup 5)))]
886   "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
887    operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
888                                   ? GEU : LTU),
889                                  VOIDmode, 
890                                  operands[2], const0_rtx);"
891 )
892
893 ;; The next four insns work because they compare the result with one of
894 ;; the operands, and we know that the use of the condition code is
895 ;; either GEU or LTU, so we can use the carry flag from the addition
896 ;; instead of doing the compare a second time.
897 (define_insn "*addsi3_compare_op1"
898   [(set (reg:CC_C CC_REGNUM)
899         (compare:CC_C
900          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
901                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
902          (match_dup 1)))
903    (set (match_operand:SI 0 "s_register_operand" "=r,r")
904         (plus:SI (match_dup 1) (match_dup 2)))]
905   "TARGET_32BIT"
906   "@
907    add%.\\t%0, %1, %2
908    sub%.\\t%0, %1, #%n2"
909   [(set_attr "conds" "set")]
910 )
911
912 (define_insn "*addsi3_compare_op2"
913   [(set (reg:CC_C CC_REGNUM)
914         (compare:CC_C
915          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
916                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
917          (match_dup 2)))
918    (set (match_operand:SI 0 "s_register_operand" "=r,r")
919         (plus:SI (match_dup 1) (match_dup 2)))]
920   "TARGET_32BIT"
921   "@
922    add%.\\t%0, %1, %2
923    sub%.\\t%0, %1, #%n2"
924   [(set_attr "conds" "set")]
925 )
926
927 (define_insn "*compare_addsi2_op0"
928   [(set (reg:CC_C CC_REGNUM)
929         (compare:CC_C
930          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
931                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
932          (match_dup 0)))]
933   "TARGET_32BIT"
934   "@
935    cmn%?\\t%0, %1
936    cmp%?\\t%0, #%n1"
937   [(set_attr "conds" "set")]
938 )
939
940 (define_insn "*compare_addsi2_op1"
941   [(set (reg:CC_C CC_REGNUM)
942         (compare:CC_C
943          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
944                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
945          (match_dup 1)))]
946   "TARGET_32BIT"
947   "@
948    cmn%?\\t%0, %1
949    cmp%?\\t%0, #%n1"
950   [(set_attr "conds" "set")]
951 )
952
953 (define_insn "*addsi3_carryin_<optab>"
954   [(set (match_operand:SI 0 "s_register_operand" "=r")
955         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
956                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
957                  (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
958   "TARGET_32BIT"
959   "adc%?\\t%0, %1, %2"
960   [(set_attr "conds" "use")]
961 )
962
963 (define_insn "*addsi3_carryin_alt2_<optab>"
964   [(set (match_operand:SI 0 "s_register_operand" "=r")
965         (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
966                           (match_operand:SI 1 "s_register_operand" "%r"))
967                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
968   "TARGET_32BIT"
969   "adc%?\\t%0, %1, %2"
970   [(set_attr "conds" "use")]
971 )
972
973 (define_insn "*addsi3_carryin_shift_<optab>"
974   [(set (match_operand:SI 0 "s_register_operand" "=r")
975         (plus:SI (plus:SI
976                   (match_operator:SI 2 "shift_operator"
977                     [(match_operand:SI 3 "s_register_operand" "r")
978                      (match_operand:SI 4 "reg_or_int_operand" "rM")])
979                   (match_operand:SI 1 "s_register_operand" "r"))
980                  (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
981   "TARGET_32BIT"
982   "adc%?\\t%0, %1, %3%S2"
983   [(set_attr "conds" "use")
984    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
985                       (const_string "alu_shift")
986                       (const_string "alu_shift_reg")))]
987 )
988
989 (define_insn "*addsi3_carryin_clobercc_<optab>"
990   [(set (match_operand:SI 0 "s_register_operand" "=r")
991         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
992                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
993                  (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))
994    (clobber (reg:CC CC_REGNUM))]
995    "TARGET_32BIT"
996    "adc%.\\t%0, %1, %2"
997    [(set_attr "conds" "set")]
998 )
999
1000 (define_expand "incscc"
1001   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1002         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
1003                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
1004                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
1005   "TARGET_32BIT"
1006   ""
1007 )
1008
1009 (define_insn "*arm_incscc"
1010   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1011         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
1012                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
1013                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
1014   "TARGET_ARM"
1015   "@
1016   add%d2\\t%0, %1, #1
1017   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
1018   [(set_attr "conds" "use")
1019    (set_attr "length" "4,8")]
1020 )
1021
1022 ; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
1023 (define_split
1024   [(set (match_operand:SI 0 "s_register_operand" "")
1025         (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
1026                             (match_operand:SI 2 "s_register_operand" ""))
1027                  (const_int -1)))
1028    (clobber (match_operand:SI 3 "s_register_operand" ""))]
1029   "TARGET_32BIT"
1030   [(set (match_dup 3) (match_dup 1))
1031    (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
1032   "
1033   operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
1034 ")
1035
1036 (define_expand "addsf3"
1037   [(set (match_operand:SF          0 "s_register_operand" "")
1038         (plus:SF (match_operand:SF 1 "s_register_operand" "")
1039                  (match_operand:SF 2 "arm_float_add_operand" "")))]
1040   "TARGET_32BIT && TARGET_HARD_FLOAT"
1041   "
1042   if (TARGET_MAVERICK
1043       && !cirrus_fp_register (operands[2], SFmode))
1044     operands[2] = force_reg (SFmode, operands[2]);
1045 ")
1046
1047 (define_expand "adddf3"
1048   [(set (match_operand:DF          0 "s_register_operand" "")
1049         (plus:DF (match_operand:DF 1 "s_register_operand" "")
1050                  (match_operand:DF 2 "arm_float_add_operand" "")))]
1051   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
1052   "
1053   if (TARGET_MAVERICK
1054       && !cirrus_fp_register (operands[2], DFmode))
1055     operands[2] = force_reg (DFmode, operands[2]);
1056 ")
1057
1058 (define_expand "subdi3"
1059  [(parallel
1060    [(set (match_operand:DI            0 "s_register_operand" "")
1061           (minus:DI (match_operand:DI 1 "s_register_operand" "")
1062                     (match_operand:DI 2 "s_register_operand" "")))
1063     (clobber (reg:CC CC_REGNUM))])]
1064   "TARGET_EITHER"
1065   "
1066   if (TARGET_HARD_FLOAT && TARGET_MAVERICK
1067       && TARGET_32BIT
1068       && cirrus_fp_register (operands[0], DImode)
1069       && cirrus_fp_register (operands[1], DImode))
1070     {
1071       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
1072       DONE;
1073     }
1074
1075   if (TARGET_THUMB1)
1076     {
1077       if (GET_CODE (operands[1]) != REG)
1078         operands[1] = force_reg (DImode, operands[1]);
1079       if (GET_CODE (operands[2]) != REG)
1080         operands[2] = force_reg (DImode, operands[2]);
1081      }  
1082   "
1083 )
1084
1085 (define_insn "*arm_subdi3"
1086   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
1087         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
1088                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
1089    (clobber (reg:CC CC_REGNUM))]
1090   "TARGET_32BIT && !TARGET_NEON"
1091   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
1092   [(set_attr "conds" "clob")
1093    (set_attr "length" "8")]
1094 )
1095
1096 (define_insn "*thumb_subdi3"
1097   [(set (match_operand:DI           0 "register_operand" "=l")
1098         (minus:DI (match_operand:DI 1 "register_operand"  "0")
1099                   (match_operand:DI 2 "register_operand"  "l")))
1100    (clobber (reg:CC CC_REGNUM))]
1101   "TARGET_THUMB1"
1102   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
1103   [(set_attr "length" "4")]
1104 )
1105
1106 (define_insn "*subdi_di_zesidi"
1107   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
1108         (minus:DI (match_operand:DI 1 "s_register_operand"  "0,r")
1109                   (zero_extend:DI
1110                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
1111    (clobber (reg:CC CC_REGNUM))]
1112   "TARGET_32BIT"
1113   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
1114   [(set_attr "conds" "clob")
1115    (set_attr "length" "8")]
1116 )
1117
1118 (define_insn "*subdi_di_sesidi"
1119   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
1120         (minus:DI (match_operand:DI  1 "s_register_operand"  "0,r")
1121                   (sign_extend:DI
1122                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
1123    (clobber (reg:CC CC_REGNUM))]
1124   "TARGET_32BIT"
1125   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
1126   [(set_attr "conds" "clob")
1127    (set_attr "length" "8")]
1128 )
1129
1130 (define_insn "*subdi_zesidi_di"
1131   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
1132         (minus:DI (zero_extend:DI
1133                    (match_operand:SI 2 "s_register_operand"  "r,r"))
1134                   (match_operand:DI  1 "s_register_operand" "0,r")))
1135    (clobber (reg:CC CC_REGNUM))]
1136   "TARGET_ARM"
1137   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
1138   [(set_attr "conds" "clob")
1139    (set_attr "length" "8")]
1140 )
1141
1142 (define_insn "*subdi_sesidi_di"
1143   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
1144         (minus:DI (sign_extend:DI
1145                    (match_operand:SI 2 "s_register_operand"   "r,r"))
1146                   (match_operand:DI  1 "s_register_operand"  "0,r")))
1147    (clobber (reg:CC CC_REGNUM))]
1148   "TARGET_ARM"
1149   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
1150   [(set_attr "conds" "clob")
1151    (set_attr "length" "8")]
1152 )
1153
1154 (define_insn "*subdi_zesidi_zesidi"
1155   [(set (match_operand:DI            0 "s_register_operand" "=r")
1156         (minus:DI (zero_extend:DI
1157                    (match_operand:SI 1 "s_register_operand"  "r"))
1158                   (zero_extend:DI
1159                    (match_operand:SI 2 "s_register_operand"  "r"))))
1160    (clobber (reg:CC CC_REGNUM))]
1161   "TARGET_32BIT"
1162   "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
1163   [(set_attr "conds" "clob")
1164    (set_attr "length" "8")]
1165 )
1166
1167 (define_expand "subsi3"
1168   [(set (match_operand:SI           0 "s_register_operand" "")
1169         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1170                   (match_operand:SI 2 "s_register_operand" "")))]
1171   "TARGET_EITHER"
1172   "
1173   if (GET_CODE (operands[1]) == CONST_INT)
1174     {
1175       if (TARGET_32BIT)
1176         {
1177           arm_split_constant (MINUS, SImode, NULL_RTX,
1178                               INTVAL (operands[1]), operands[0],
1179                               operands[2], optimize && can_create_pseudo_p ());
1180           DONE;
1181         }
1182       else /* TARGET_THUMB1 */
1183         operands[1] = force_reg (SImode, operands[1]);
1184     }
1185   "
1186 )
1187
1188 (define_insn "thumb1_subsi3_insn"
1189   [(set (match_operand:SI           0 "register_operand" "=l")
1190         (minus:SI (match_operand:SI 1 "register_operand" "l")
1191                   (match_operand:SI 2 "reg_or_int_operand" "lPd")))]
1192   "TARGET_THUMB1"
1193   "sub\\t%0, %1, %2"
1194   [(set_attr "length" "2")
1195    (set_attr "conds" "set")])
1196
1197 ; ??? Check Thumb-2 split length
1198 (define_insn_and_split "*arm_subsi3_insn"
1199   [(set (match_operand:SI           0 "s_register_operand" "=r,r,rk,r,r")
1200         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,r,k,?n,r")
1201                   (match_operand:SI 2 "reg_or_int_operand" "r,rI,r, r,?n")))]
1202   "TARGET_32BIT"
1203   "@
1204    rsb%?\\t%0, %2, %1
1205    sub%?\\t%0, %1, %2
1206    sub%?\\t%0, %1, %2
1207    #
1208    #"
1209   "&& ((GET_CODE (operands[1]) == CONST_INT
1210         && !const_ok_for_arm (INTVAL (operands[1])))
1211        || (GET_CODE (operands[2]) == CONST_INT
1212            && !const_ok_for_arm (INTVAL (operands[2]))))"
1213   [(clobber (const_int 0))]
1214   "
1215   arm_split_constant (MINUS, SImode, curr_insn,
1216                       INTVAL (operands[1]), operands[0], operands[2], 0);
1217   DONE;
1218   "
1219   [(set_attr "length" "4,4,4,16,16")
1220    (set_attr "predicable" "yes")]
1221 )
1222
1223 (define_peephole2
1224   [(match_scratch:SI 3 "r")
1225    (set (match_operand:SI 0 "arm_general_register_operand" "")
1226         (minus:SI (match_operand:SI 1 "const_int_operand" "")
1227                   (match_operand:SI 2 "arm_general_register_operand" "")))]
1228   "TARGET_32BIT
1229    && !const_ok_for_arm (INTVAL (operands[1]))
1230    && const_ok_for_arm (~INTVAL (operands[1]))"
1231   [(set (match_dup 3) (match_dup 1))
1232    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1233   ""
1234 )
1235
1236 (define_insn "*subsi3_compare0"
1237   [(set (reg:CC_NOOV CC_REGNUM)
1238         (compare:CC_NOOV
1239          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1240                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1241          (const_int 0)))
1242    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1243         (minus:SI (match_dup 1) (match_dup 2)))]
1244   "TARGET_32BIT"
1245   "@
1246    sub%.\\t%0, %1, %2
1247    rsb%.\\t%0, %2, %1"
1248   [(set_attr "conds" "set")]
1249 )
1250
1251 (define_insn "*subsi3_compare"
1252   [(set (reg:CC CC_REGNUM)
1253         (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,I")
1254                     (match_operand:SI 2 "arm_rhs_operand" "rI,r")))
1255    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1256         (minus:SI (match_dup 1) (match_dup 2)))]
1257   "TARGET_32BIT"
1258   "@
1259    sub%.\\t%0, %1, %2
1260    rsb%.\\t%0, %2, %1"
1261   [(set_attr "conds" "set")]
1262 )
1263
1264 (define_expand "decscc"
1265   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1266         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1267                   (match_operator:SI 2 "arm_comparison_operator"
1268                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1269   "TARGET_32BIT"
1270   ""
1271 )
1272
1273 (define_insn "*arm_decscc"
1274   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1275         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1276                   (match_operator:SI 2 "arm_comparison_operator"
1277                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1278   "TARGET_ARM"
1279   "@
1280    sub%d2\\t%0, %1, #1
1281    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1282   [(set_attr "conds" "use")
1283    (set_attr "length" "*,8")]
1284 )
1285
1286 (define_expand "subsf3"
1287   [(set (match_operand:SF           0 "s_register_operand" "")
1288         (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1289                   (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1290   "TARGET_32BIT && TARGET_HARD_FLOAT"
1291   "
1292   if (TARGET_MAVERICK)
1293     {
1294       if (!cirrus_fp_register (operands[1], SFmode))
1295         operands[1] = force_reg (SFmode, operands[1]);
1296       if (!cirrus_fp_register (operands[2], SFmode))
1297         operands[2] = force_reg (SFmode, operands[2]);
1298     }
1299 ")
1300
1301 (define_expand "subdf3"
1302   [(set (match_operand:DF           0 "s_register_operand" "")
1303         (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1304                   (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1305   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
1306   "
1307   if (TARGET_MAVERICK)
1308     {
1309        if (!cirrus_fp_register (operands[1], DFmode))
1310          operands[1] = force_reg (DFmode, operands[1]);
1311        if (!cirrus_fp_register (operands[2], DFmode))
1312          operands[2] = force_reg (DFmode, operands[2]);
1313     }
1314 ")
1315
1316 \f
1317 ;; Multiplication insns
1318
1319 (define_expand "mulsi3"
1320   [(set (match_operand:SI          0 "s_register_operand" "")
1321         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1322                  (match_operand:SI 1 "s_register_operand" "")))]
1323   "TARGET_EITHER"
1324   ""
1325 )
1326
1327 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1328 (define_insn "*arm_mulsi3"
1329   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1330         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1331                  (match_operand:SI 1 "s_register_operand" "%0,r")))]
1332   "TARGET_32BIT && !arm_arch6"
1333   "mul%?\\t%0, %2, %1"
1334   [(set_attr "insn" "mul")
1335    (set_attr "predicable" "yes")]
1336 )
1337
1338 (define_insn "*arm_mulsi3_v6"
1339   [(set (match_operand:SI          0 "s_register_operand" "=r")
1340         (mult:SI (match_operand:SI 1 "s_register_operand" "r")
1341                  (match_operand:SI 2 "s_register_operand" "r")))]
1342   "TARGET_32BIT && arm_arch6"
1343   "mul%?\\t%0, %1, %2"
1344   [(set_attr "insn" "mul")
1345    (set_attr "predicable" "yes")]
1346 )
1347
1348 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1349 ; 1 and 2; are the same, because reload will make operand 0 match 
1350 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1351 ; this by adding another alternative to match this case, and then `reload' 
1352 ; it ourselves.  This alternative must come first.
1353 (define_insn "*thumb_mulsi3"
1354   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1355         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1356                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1357   "TARGET_THUMB1 && !arm_arch6"
1358   "*
1359   if (which_alternative < 2)
1360     return \"mov\\t%0, %1\;mul\\t%0, %2\";
1361   else
1362     return \"mul\\t%0, %2\";
1363   "
1364   [(set_attr "length" "4,4,2")
1365    (set_attr "insn" "mul")]
1366 )
1367
1368 (define_insn "*thumb_mulsi3_v6"
1369   [(set (match_operand:SI          0 "register_operand" "=l,l,l")
1370         (mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
1371                  (match_operand:SI 2 "register_operand" "l,0,0")))]
1372   "TARGET_THUMB1 && arm_arch6"
1373   "@
1374    mul\\t%0, %2
1375    mul\\t%0, %1
1376    mul\\t%0, %1"
1377   [(set_attr "length" "2")
1378    (set_attr "insn" "mul")]
1379 )
1380
1381 (define_insn "*mulsi3_compare0"
1382   [(set (reg:CC_NOOV CC_REGNUM)
1383         (compare:CC_NOOV (mult:SI
1384                           (match_operand:SI 2 "s_register_operand" "r,r")
1385                           (match_operand:SI 1 "s_register_operand" "%0,r"))
1386                          (const_int 0)))
1387    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1388         (mult:SI (match_dup 2) (match_dup 1)))]
1389   "TARGET_ARM && !arm_arch6"
1390   "mul%.\\t%0, %2, %1"
1391   [(set_attr "conds" "set")
1392    (set_attr "insn" "muls")]
1393 )
1394
1395 (define_insn "*mulsi3_compare0_v6"
1396   [(set (reg:CC_NOOV CC_REGNUM)
1397         (compare:CC_NOOV (mult:SI
1398                           (match_operand:SI 2 "s_register_operand" "r")
1399                           (match_operand:SI 1 "s_register_operand" "r"))
1400                          (const_int 0)))
1401    (set (match_operand:SI 0 "s_register_operand" "=r")
1402         (mult:SI (match_dup 2) (match_dup 1)))]
1403   "TARGET_ARM && arm_arch6 && optimize_size"
1404   "mul%.\\t%0, %2, %1"
1405   [(set_attr "conds" "set")
1406    (set_attr "insn" "muls")]
1407 )
1408
1409 (define_insn "*mulsi_compare0_scratch"
1410   [(set (reg:CC_NOOV CC_REGNUM)
1411         (compare:CC_NOOV (mult:SI
1412                           (match_operand:SI 2 "s_register_operand" "r,r")
1413                           (match_operand:SI 1 "s_register_operand" "%0,r"))
1414                          (const_int 0)))
1415    (clobber (match_scratch:SI 0 "=&r,&r"))]
1416   "TARGET_ARM && !arm_arch6"
1417   "mul%.\\t%0, %2, %1"
1418   [(set_attr "conds" "set")
1419    (set_attr "insn" "muls")]
1420 )
1421
1422 (define_insn "*mulsi_compare0_scratch_v6"
1423   [(set (reg:CC_NOOV CC_REGNUM)
1424         (compare:CC_NOOV (mult:SI
1425                           (match_operand:SI 2 "s_register_operand" "r")
1426                           (match_operand:SI 1 "s_register_operand" "r"))
1427                          (const_int 0)))
1428    (clobber (match_scratch:SI 0 "=r"))]
1429   "TARGET_ARM && arm_arch6 && optimize_size"
1430   "mul%.\\t%0, %2, %1"
1431   [(set_attr "conds" "set")
1432    (set_attr "insn" "muls")]
1433 )
1434
1435 ;; Unnamed templates to match MLA instruction.
1436
1437 (define_insn "*mulsi3addsi"
1438   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1439         (plus:SI
1440           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1441                    (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1442           (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
1443   "TARGET_32BIT && !arm_arch6"
1444   "mla%?\\t%0, %2, %1, %3"
1445   [(set_attr "insn" "mla")
1446    (set_attr "predicable" "yes")]
1447 )
1448
1449 (define_insn "*mulsi3addsi_v6"
1450   [(set (match_operand:SI 0 "s_register_operand" "=r")
1451         (plus:SI
1452           (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1453                    (match_operand:SI 1 "s_register_operand" "r"))
1454           (match_operand:SI 3 "s_register_operand" "r")))]
1455   "TARGET_32BIT && arm_arch6"
1456   "mla%?\\t%0, %2, %1, %3"
1457   [(set_attr "insn" "mla")
1458    (set_attr "predicable" "yes")]
1459 )
1460
1461 (define_insn "*mulsi3addsi_compare0"
1462   [(set (reg:CC_NOOV CC_REGNUM)
1463         (compare:CC_NOOV
1464          (plus:SI (mult:SI
1465                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1466                    (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1467                   (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
1468          (const_int 0)))
1469    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1470         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1471                  (match_dup 3)))]
1472   "TARGET_ARM && arm_arch6"
1473   "mla%.\\t%0, %2, %1, %3"
1474   [(set_attr "conds" "set")
1475    (set_attr "insn" "mlas")]
1476 )
1477
1478 (define_insn "*mulsi3addsi_compare0_v6"
1479   [(set (reg:CC_NOOV CC_REGNUM)
1480         (compare:CC_NOOV
1481          (plus:SI (mult:SI
1482                    (match_operand:SI 2 "s_register_operand" "r")
1483                    (match_operand:SI 1 "s_register_operand" "r"))
1484                   (match_operand:SI 3 "s_register_operand" "r"))
1485          (const_int 0)))
1486    (set (match_operand:SI 0 "s_register_operand" "=r")
1487         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1488                  (match_dup 3)))]
1489   "TARGET_ARM && arm_arch6 && optimize_size"
1490   "mla%.\\t%0, %2, %1, %3"
1491   [(set_attr "conds" "set")
1492    (set_attr "insn" "mlas")]
1493 )
1494
1495 (define_insn "*mulsi3addsi_compare0_scratch"
1496   [(set (reg:CC_NOOV CC_REGNUM)
1497         (compare:CC_NOOV
1498          (plus:SI (mult:SI
1499                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1500                    (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1501                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1502          (const_int 0)))
1503    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1504   "TARGET_ARM && !arm_arch6"
1505   "mla%.\\t%0, %2, %1, %3"
1506   [(set_attr "conds" "set")
1507    (set_attr "insn" "mlas")]
1508 )
1509
1510 (define_insn "*mulsi3addsi_compare0_scratch_v6"
1511   [(set (reg:CC_NOOV CC_REGNUM)
1512         (compare:CC_NOOV
1513          (plus:SI (mult:SI
1514                    (match_operand:SI 2 "s_register_operand" "r")
1515                    (match_operand:SI 1 "s_register_operand" "r"))
1516                   (match_operand:SI 3 "s_register_operand" "r"))
1517          (const_int 0)))
1518    (clobber (match_scratch:SI 0 "=r"))]
1519   "TARGET_ARM && arm_arch6 && optimize_size"
1520   "mla%.\\t%0, %2, %1, %3"
1521   [(set_attr "conds" "set")
1522    (set_attr "insn" "mlas")]
1523 )
1524
1525 (define_insn "*mulsi3subsi"
1526   [(set (match_operand:SI 0 "s_register_operand" "=r")
1527         (minus:SI
1528           (match_operand:SI 3 "s_register_operand" "r")
1529           (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1530                    (match_operand:SI 1 "s_register_operand" "r"))))]
1531   "TARGET_32BIT && arm_arch_thumb2"
1532   "mls%?\\t%0, %2, %1, %3"
1533   [(set_attr "insn" "mla")
1534    (set_attr "predicable" "yes")]
1535 )
1536
1537 (define_expand "maddsidi4"
1538   [(set (match_operand:DI 0 "s_register_operand" "")
1539         (plus:DI
1540          (mult:DI
1541           (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1542           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1543          (match_operand:DI 3 "s_register_operand" "")))]
1544   "TARGET_32BIT && arm_arch3m"
1545   "")
1546
1547 (define_insn "*mulsidi3adddi"
1548   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1549         (plus:DI
1550          (mult:DI
1551           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1552           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1553          (match_operand:DI 1 "s_register_operand" "0")))]
1554   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1555   "smlal%?\\t%Q0, %R0, %3, %2"
1556   [(set_attr "insn" "smlal")
1557    (set_attr "predicable" "yes")]
1558 )
1559
1560 (define_insn "*mulsidi3adddi_v6"
1561   [(set (match_operand:DI 0 "s_register_operand" "=r")
1562         (plus:DI
1563          (mult:DI
1564           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1565           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1566          (match_operand:DI 1 "s_register_operand" "0")))]
1567   "TARGET_32BIT && arm_arch6"
1568   "smlal%?\\t%Q0, %R0, %3, %2"
1569   [(set_attr "insn" "smlal")
1570    (set_attr "predicable" "yes")]
1571 )
1572
1573 ;; 32x32->64 widening multiply.
1574 ;; As with mulsi3, the only difference between the v3-5 and v6+
1575 ;; versions of these patterns is the requirement that the output not
1576 ;; overlap the inputs, but that still means we have to have a named
1577 ;; expander and two different starred insns.
1578
1579 (define_expand "mulsidi3"
1580   [(set (match_operand:DI 0 "s_register_operand" "")
1581         (mult:DI
1582          (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1583          (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1584   "TARGET_32BIT && arm_arch3m"
1585   ""
1586 )
1587
1588 (define_insn "*mulsidi3_nov6"
1589   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1590         (mult:DI
1591          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1592          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1593   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1594   "smull%?\\t%Q0, %R0, %1, %2"
1595   [(set_attr "insn" "smull")
1596    (set_attr "predicable" "yes")]
1597 )
1598
1599 (define_insn "*mulsidi3_v6"
1600   [(set (match_operand:DI 0 "s_register_operand" "=r")
1601         (mult:DI
1602          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1603          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1604   "TARGET_32BIT && arm_arch6"
1605   "smull%?\\t%Q0, %R0, %1, %2"
1606   [(set_attr "insn" "smull")
1607    (set_attr "predicable" "yes")]
1608 )
1609
1610 (define_expand "umulsidi3"
1611   [(set (match_operand:DI 0 "s_register_operand" "")
1612         (mult:DI
1613          (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1614          (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1615   "TARGET_32BIT && arm_arch3m"
1616   ""
1617 )
1618
1619 (define_insn "*umulsidi3_nov6"
1620   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1621         (mult:DI
1622          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1623          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1624   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1625   "umull%?\\t%Q0, %R0, %1, %2"
1626   [(set_attr "insn" "umull")
1627    (set_attr "predicable" "yes")]
1628 )
1629
1630 (define_insn "*umulsidi3_v6"
1631   [(set (match_operand:DI 0 "s_register_operand" "=r")
1632         (mult:DI
1633          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1634          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1635   "TARGET_32BIT && arm_arch6"
1636   "umull%?\\t%Q0, %R0, %1, %2"
1637   [(set_attr "insn" "umull")
1638    (set_attr "predicable" "yes")]
1639 )
1640
1641 (define_expand "umaddsidi4"
1642   [(set (match_operand:DI 0 "s_register_operand" "")
1643         (plus:DI
1644          (mult:DI
1645           (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1646           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1647          (match_operand:DI 3 "s_register_operand" "")))]
1648   "TARGET_32BIT && arm_arch3m"
1649   "")
1650
1651 (define_insn "*umulsidi3adddi"
1652   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1653         (plus:DI
1654          (mult:DI
1655           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1656           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1657          (match_operand:DI 1 "s_register_operand" "0")))]
1658   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1659   "umlal%?\\t%Q0, %R0, %3, %2"
1660   [(set_attr "insn" "umlal")
1661    (set_attr "predicable" "yes")]
1662 )
1663
1664 (define_insn "*umulsidi3adddi_v6"
1665   [(set (match_operand:DI 0 "s_register_operand" "=r")
1666         (plus:DI
1667          (mult:DI
1668           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1669           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1670          (match_operand:DI 1 "s_register_operand" "0")))]
1671   "TARGET_32BIT && arm_arch6"
1672   "umlal%?\\t%Q0, %R0, %3, %2"
1673   [(set_attr "insn" "umlal")
1674    (set_attr "predicable" "yes")]
1675 )
1676
1677 (define_expand "smulsi3_highpart"
1678   [(parallel
1679     [(set (match_operand:SI 0 "s_register_operand" "")
1680           (truncate:SI
1681            (lshiftrt:DI
1682             (mult:DI
1683              (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1684              (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1685             (const_int 32))))
1686      (clobber (match_scratch:SI 3 ""))])]
1687   "TARGET_32BIT && arm_arch3m"
1688   ""
1689 )
1690
1691 (define_insn "*smulsi3_highpart_nov6"
1692   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1693         (truncate:SI
1694          (lshiftrt:DI
1695           (mult:DI
1696            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
1697            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1698           (const_int 32))))
1699    (clobber (match_scratch:SI 3 "=&r,&r"))]
1700   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1701   "smull%?\\t%3, %0, %2, %1"
1702   [(set_attr "insn" "smull")
1703    (set_attr "predicable" "yes")]
1704 )
1705
1706 (define_insn "*smulsi3_highpart_v6"
1707   [(set (match_operand:SI 0 "s_register_operand" "=r")
1708         (truncate:SI
1709          (lshiftrt:DI
1710           (mult:DI
1711            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1712            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1713           (const_int 32))))
1714    (clobber (match_scratch:SI 3 "=r"))]
1715   "TARGET_32BIT && arm_arch6"
1716   "smull%?\\t%3, %0, %2, %1"
1717   [(set_attr "insn" "smull")
1718    (set_attr "predicable" "yes")]
1719 )
1720
1721 (define_expand "umulsi3_highpart"
1722   [(parallel
1723     [(set (match_operand:SI 0 "s_register_operand" "")
1724           (truncate:SI
1725            (lshiftrt:DI
1726             (mult:DI
1727              (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1728               (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1729             (const_int 32))))
1730      (clobber (match_scratch:SI 3 ""))])]
1731   "TARGET_32BIT && arm_arch3m"
1732   ""
1733 )
1734
1735 (define_insn "*umulsi3_highpart_nov6"
1736   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1737         (truncate:SI
1738          (lshiftrt:DI
1739           (mult:DI
1740            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
1741            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1742           (const_int 32))))
1743    (clobber (match_scratch:SI 3 "=&r,&r"))]
1744   "TARGET_32BIT && arm_arch3m && !arm_arch6"
1745   "umull%?\\t%3, %0, %2, %1"
1746   [(set_attr "insn" "umull")
1747    (set_attr "predicable" "yes")]
1748 )
1749
1750 (define_insn "*umulsi3_highpart_v6"
1751   [(set (match_operand:SI 0 "s_register_operand" "=r")
1752         (truncate:SI
1753          (lshiftrt:DI
1754           (mult:DI
1755            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1756            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1757           (const_int 32))))
1758    (clobber (match_scratch:SI 3 "=r"))]
1759   "TARGET_32BIT && arm_arch6"
1760   "umull%?\\t%3, %0, %2, %1"
1761   [(set_attr "insn" "umull")
1762    (set_attr "predicable" "yes")]
1763 )
1764
1765 (define_insn "mulhisi3"
1766   [(set (match_operand:SI 0 "s_register_operand" "=r")
1767         (mult:SI (sign_extend:SI
1768                   (match_operand:HI 1 "s_register_operand" "%r"))
1769                  (sign_extend:SI
1770                   (match_operand:HI 2 "s_register_operand" "r"))))]
1771   "TARGET_DSP_MULTIPLY"
1772   "smulbb%?\\t%0, %1, %2"
1773   [(set_attr "insn" "smulxy")
1774    (set_attr "predicable" "yes")]
1775 )
1776
1777 (define_insn "*mulhisi3tb"
1778   [(set (match_operand:SI 0 "s_register_operand" "=r")
1779         (mult:SI (ashiftrt:SI
1780                   (match_operand:SI 1 "s_register_operand" "r")
1781                   (const_int 16))
1782                  (sign_extend:SI
1783                   (match_operand:HI 2 "s_register_operand" "r"))))]
1784   "TARGET_DSP_MULTIPLY"
1785   "smultb%?\\t%0, %1, %2"
1786   [(set_attr "insn" "smulxy")
1787    (set_attr "predicable" "yes")]
1788 )
1789
1790 (define_insn "*mulhisi3bt"
1791   [(set (match_operand:SI 0 "s_register_operand" "=r")
1792         (mult:SI (sign_extend:SI
1793                   (match_operand:HI 1 "s_register_operand" "r"))
1794                  (ashiftrt:SI
1795                   (match_operand:SI 2 "s_register_operand" "r")
1796                   (const_int 16))))]
1797   "TARGET_DSP_MULTIPLY"
1798   "smulbt%?\\t%0, %1, %2"
1799   [(set_attr "insn" "smulxy")
1800    (set_attr "predicable" "yes")]
1801 )
1802
1803 (define_insn "*mulhisi3tt"
1804   [(set (match_operand:SI 0 "s_register_operand" "=r")
1805         (mult:SI (ashiftrt:SI
1806                   (match_operand:SI 1 "s_register_operand" "r")
1807                   (const_int 16))
1808                  (ashiftrt:SI
1809                   (match_operand:SI 2 "s_register_operand" "r")
1810                   (const_int 16))))]
1811   "TARGET_DSP_MULTIPLY"
1812   "smultt%?\\t%0, %1, %2"
1813   [(set_attr "insn" "smulxy")
1814    (set_attr "predicable" "yes")]
1815 )
1816
1817 (define_insn "maddhisi4"
1818   [(set (match_operand:SI 0 "s_register_operand" "=r")
1819         (plus:SI (mult:SI (sign_extend:SI
1820                            (match_operand:HI 1 "s_register_operand" "r"))
1821                           (sign_extend:SI
1822                            (match_operand:HI 2 "s_register_operand" "r")))
1823                  (match_operand:SI 3 "s_register_operand" "r")))]
1824   "TARGET_DSP_MULTIPLY"
1825   "smlabb%?\\t%0, %1, %2, %3"
1826   [(set_attr "insn" "smlaxy")
1827    (set_attr "predicable" "yes")]
1828 )
1829
1830 ;; Note: there is no maddhisi4ibt because this one is canonical form
1831 (define_insn "*maddhisi4tb"
1832   [(set (match_operand:SI 0 "s_register_operand" "=r")
1833         (plus:SI (mult:SI (ashiftrt:SI
1834                            (match_operand:SI 1 "s_register_operand" "r")
1835                            (const_int 16))
1836                           (sign_extend:SI
1837                            (match_operand:HI 2 "s_register_operand" "r")))
1838                  (match_operand:SI 3 "s_register_operand" "r")))]
1839   "TARGET_DSP_MULTIPLY"
1840   "smlatb%?\\t%0, %1, %2, %3"
1841   [(set_attr "insn" "smlaxy")
1842    (set_attr "predicable" "yes")]
1843 )
1844
1845 (define_insn "*maddhisi4tt"
1846   [(set (match_operand:SI 0 "s_register_operand" "=r")
1847         (plus:SI (mult:SI (ashiftrt:SI
1848                            (match_operand:SI 1 "s_register_operand" "r")
1849                            (const_int 16))
1850                           (ashiftrt:SI
1851                            (match_operand:SI 2 "s_register_operand" "r")
1852                            (const_int 16)))
1853                  (match_operand:SI 3 "s_register_operand" "r")))]
1854   "TARGET_DSP_MULTIPLY"
1855   "smlatt%?\\t%0, %1, %2, %3"
1856   [(set_attr "insn" "smlaxy")
1857    (set_attr "predicable" "yes")]
1858 )
1859
1860 (define_insn "*maddhidi4"
1861   [(set (match_operand:DI 0 "s_register_operand" "=r")
1862         (plus:DI
1863           (mult:DI (sign_extend:DI
1864                     (match_operand:HI 1 "s_register_operand" "r"))
1865                    (sign_extend:DI
1866                     (match_operand:HI 2 "s_register_operand" "r")))
1867           (match_operand:DI 3 "s_register_operand" "0")))]
1868   "TARGET_DSP_MULTIPLY"
1869   "smlalbb%?\\t%Q0, %R0, %1, %2"
1870   [(set_attr "insn" "smlalxy")
1871    (set_attr "predicable" "yes")])
1872
1873 ;; Note: there is no maddhidi4ibt because this one is canonical form
1874 (define_insn "*maddhidi4tb"
1875   [(set (match_operand:DI 0 "s_register_operand" "=r")
1876         (plus:DI
1877           (mult:DI (sign_extend:DI
1878                     (ashiftrt:SI
1879                      (match_operand:SI 1 "s_register_operand" "r")
1880                      (const_int 16)))
1881                    (sign_extend:DI
1882                     (match_operand:HI 2 "s_register_operand" "r")))
1883           (match_operand:DI 3 "s_register_operand" "0")))]
1884   "TARGET_DSP_MULTIPLY"
1885   "smlaltb%?\\t%Q0, %R0, %1, %2"
1886   [(set_attr "insn" "smlalxy")
1887    (set_attr "predicable" "yes")])
1888
1889 (define_insn "*maddhidi4tt"
1890   [(set (match_operand:DI 0 "s_register_operand" "=r")
1891         (plus:DI
1892           (mult:DI (sign_extend:DI
1893                     (ashiftrt:SI
1894                      (match_operand:SI 1 "s_register_operand" "r")
1895                      (const_int 16)))
1896                    (sign_extend:DI
1897                     (ashiftrt:SI
1898                      (match_operand:SI 2 "s_register_operand" "r")
1899                      (const_int 16))))
1900           (match_operand:DI 3 "s_register_operand" "0")))]
1901   "TARGET_DSP_MULTIPLY"
1902   "smlaltt%?\\t%Q0, %R0, %1, %2"
1903   [(set_attr "insn" "smlalxy")
1904    (set_attr "predicable" "yes")])
1905
1906 (define_expand "mulsf3"
1907   [(set (match_operand:SF          0 "s_register_operand" "")
1908         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1909                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1910   "TARGET_32BIT && TARGET_HARD_FLOAT"
1911   "
1912   if (TARGET_MAVERICK
1913       && !cirrus_fp_register (operands[2], SFmode))
1914     operands[2] = force_reg (SFmode, operands[2]);
1915 ")
1916
1917 (define_expand "muldf3"
1918   [(set (match_operand:DF          0 "s_register_operand" "")
1919         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1920                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1921   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
1922   "
1923   if (TARGET_MAVERICK
1924       && !cirrus_fp_register (operands[2], DFmode))
1925     operands[2] = force_reg (DFmode, operands[2]);
1926 ")
1927 \f
1928 ;; Division insns
1929
1930 (define_expand "divsf3"
1931   [(set (match_operand:SF 0 "s_register_operand" "")
1932         (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1933                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1934   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1935   "")
1936
1937 (define_expand "divdf3"
1938   [(set (match_operand:DF 0 "s_register_operand" "")
1939         (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1940                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1941   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
1942   "")
1943 \f
1944 ;; Modulo insns
1945
1946 (define_expand "modsf3"
1947   [(set (match_operand:SF 0 "s_register_operand" "")
1948         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1949                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1950   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
1951   "")
1952
1953 (define_expand "moddf3"
1954   [(set (match_operand:DF 0 "s_register_operand" "")
1955         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1956                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1957   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
1958   "")
1959 \f
1960 ;; Boolean and,ior,xor insns
1961
1962 ;; Split up double word logical operations
1963
1964 ;; Split up simple DImode logical operations.  Simply perform the logical
1965 ;; operation on the upper and lower halves of the registers.
1966 (define_split
1967   [(set (match_operand:DI 0 "s_register_operand" "")
1968         (match_operator:DI 6 "logical_binary_operator"
1969           [(match_operand:DI 1 "s_register_operand" "")
1970            (match_operand:DI 2 "s_register_operand" "")]))]
1971   "TARGET_32BIT && reload_completed
1972    && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
1973    && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1974   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1975    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1976   "
1977   {
1978     operands[3] = gen_highpart (SImode, operands[0]);
1979     operands[0] = gen_lowpart (SImode, operands[0]);
1980     operands[4] = gen_highpart (SImode, operands[1]);
1981     operands[1] = gen_lowpart (SImode, operands[1]);
1982     operands[5] = gen_highpart (SImode, operands[2]);
1983     operands[2] = gen_lowpart (SImode, operands[2]);
1984   }"
1985 )
1986
1987 (define_split
1988   [(set (match_operand:DI 0 "s_register_operand" "")
1989         (match_operator:DI 6 "logical_binary_operator"
1990           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1991            (match_operand:DI 1 "s_register_operand" "")]))]
1992   "TARGET_32BIT && reload_completed"
1993   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1994    (set (match_dup 3) (match_op_dup:SI 6
1995                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1996                          (match_dup 4)]))]
1997   "
1998   {
1999     operands[3] = gen_highpart (SImode, operands[0]);
2000     operands[0] = gen_lowpart (SImode, operands[0]);
2001     operands[4] = gen_highpart (SImode, operands[1]);
2002     operands[1] = gen_lowpart (SImode, operands[1]);
2003     operands[5] = gen_highpart (SImode, operands[2]);
2004     operands[2] = gen_lowpart (SImode, operands[2]);
2005   }"
2006 )
2007
2008 ;; The zero extend of operand 2 means we can just copy the high part of
2009 ;; operand1 into operand0.
2010 (define_split
2011   [(set (match_operand:DI 0 "s_register_operand" "")
2012         (ior:DI
2013           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2014           (match_operand:DI 1 "s_register_operand" "")))]
2015   "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
2016   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
2017    (set (match_dup 3) (match_dup 4))]
2018   "
2019   {
2020     operands[4] = gen_highpart (SImode, operands[1]);
2021     operands[3] = gen_highpart (SImode, operands[0]);
2022     operands[0] = gen_lowpart (SImode, operands[0]);
2023     operands[1] = gen_lowpart (SImode, operands[1]);
2024   }"
2025 )
2026
2027 ;; The zero extend of operand 2 means we can just copy the high part of
2028 ;; operand1 into operand0.
2029 (define_split
2030   [(set (match_operand:DI 0 "s_register_operand" "")
2031         (xor:DI
2032           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2033           (match_operand:DI 1 "s_register_operand" "")))]
2034   "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
2035   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
2036    (set (match_dup 3) (match_dup 4))]
2037   "
2038   {
2039     operands[4] = gen_highpart (SImode, operands[1]);
2040     operands[3] = gen_highpart (SImode, operands[0]);
2041     operands[0] = gen_lowpart (SImode, operands[0]);
2042     operands[1] = gen_lowpart (SImode, operands[1]);
2043   }"
2044 )
2045
2046 (define_expand "anddi3"
2047   [(set (match_operand:DI         0 "s_register_operand" "")
2048         (and:DI (match_operand:DI 1 "s_register_operand" "")
2049                 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
2050   "TARGET_32BIT"
2051   ""
2052 )
2053
2054 (define_insn "*anddi3_insn"
2055   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2056         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2057                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2058   "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
2059   "#"
2060   [(set_attr "length" "8")]
2061 )
2062
2063 (define_insn_and_split "*anddi_zesidi_di"
2064   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2065         (and:DI (zero_extend:DI
2066                  (match_operand:SI 2 "s_register_operand" "r,r"))
2067                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2068   "TARGET_32BIT"
2069   "#"
2070   "TARGET_32BIT && reload_completed"
2071   ; The zero extend of operand 2 clears the high word of the output
2072   ; operand.
2073   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
2074    (set (match_dup 3) (const_int 0))]
2075   "
2076   {
2077     operands[3] = gen_highpart (SImode, operands[0]);
2078     operands[0] = gen_lowpart (SImode, operands[0]);
2079     operands[1] = gen_lowpart (SImode, operands[1]);
2080   }"
2081   [(set_attr "length" "8")]
2082 )
2083
2084 (define_insn "*anddi_sesdi_di"
2085   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
2086         (and:DI (sign_extend:DI
2087                  (match_operand:SI 2 "s_register_operand" "r,r"))
2088                 (match_operand:DI  1 "s_register_operand" "0,r")))]
2089   "TARGET_32BIT"
2090   "#"
2091   [(set_attr "length" "8")]
2092 )
2093
2094 (define_expand "andsi3"
2095   [(set (match_operand:SI         0 "s_register_operand" "")
2096         (and:SI (match_operand:SI 1 "s_register_operand" "")
2097                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2098   "TARGET_EITHER"
2099   "
2100   if (TARGET_32BIT)
2101     {
2102       if (GET_CODE (operands[2]) == CONST_INT)
2103         {
2104           if (INTVAL (operands[2]) == 255 && arm_arch6)
2105             {
2106               operands[1] = convert_to_mode (QImode, operands[1], 1);
2107               emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2108                                                          operands[1]));
2109             }
2110           else
2111             arm_split_constant (AND, SImode, NULL_RTX,
2112                                 INTVAL (operands[2]), operands[0],
2113                                 operands[1],
2114                                 optimize && can_create_pseudo_p ());
2115
2116           DONE;
2117         }
2118     }
2119   else /* TARGET_THUMB1 */
2120     {
2121       if (GET_CODE (operands[2]) != CONST_INT)
2122         {
2123           rtx tmp = force_reg (SImode, operands[2]);
2124           if (rtx_equal_p (operands[0], operands[1]))
2125             operands[2] = tmp;
2126           else
2127             {
2128               operands[2] = operands[1];
2129               operands[1] = tmp;
2130             }
2131         }
2132       else
2133         {
2134           int i;
2135           
2136           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
2137             {
2138               operands[2] = force_reg (SImode,
2139                                        GEN_INT (~INTVAL (operands[2])));
2140               
2141               emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
2142               
2143               DONE;
2144             }
2145
2146           for (i = 9; i <= 31; i++)
2147             {
2148               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
2149                 {
2150                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2151                                         const0_rtx));
2152                   DONE;
2153                 }
2154               else if ((((HOST_WIDE_INT) 1) << i) - 1
2155                        == ~INTVAL (operands[2]))
2156                 {
2157                   rtx shift = GEN_INT (i);
2158                   rtx reg = gen_reg_rtx (SImode);
2159                 
2160                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2161                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2162                   
2163                   DONE;
2164                 }
2165             }
2166
2167           operands[2] = force_reg (SImode, operands[2]);
2168         }
2169     }
2170   "
2171 )
2172
2173 ; ??? Check split length for Thumb-2
2174 (define_insn_and_split "*arm_andsi3_insn"
2175   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
2176         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2177                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
2178   "TARGET_32BIT"
2179   "@
2180    and%?\\t%0, %1, %2
2181    bic%?\\t%0, %1, #%B2
2182    #"
2183   "TARGET_32BIT
2184    && GET_CODE (operands[2]) == CONST_INT
2185    && !(const_ok_for_arm (INTVAL (operands[2]))
2186         || const_ok_for_arm (~INTVAL (operands[2])))"
2187   [(clobber (const_int 0))]
2188   "
2189   arm_split_constant  (AND, SImode, curr_insn, 
2190                        INTVAL (operands[2]), operands[0], operands[1], 0);
2191   DONE;
2192   "
2193   [(set_attr "length" "4,4,16")
2194    (set_attr "predicable" "yes")]
2195 )
2196
2197 (define_insn "*thumb1_andsi3_insn"
2198   [(set (match_operand:SI         0 "register_operand" "=l")
2199         (and:SI (match_operand:SI 1 "register_operand" "%0")
2200                 (match_operand:SI 2 "register_operand" "l")))]
2201   "TARGET_THUMB1"
2202   "and\\t%0, %2"
2203   [(set_attr "length" "2")
2204    (set_attr "conds" "set")])
2205
2206 (define_insn "*andsi3_compare0"
2207   [(set (reg:CC_NOOV CC_REGNUM)
2208         (compare:CC_NOOV
2209          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
2210                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
2211          (const_int 0)))
2212    (set (match_operand:SI          0 "s_register_operand" "=r,r")
2213         (and:SI (match_dup 1) (match_dup 2)))]
2214   "TARGET_32BIT"
2215   "@
2216    and%.\\t%0, %1, %2
2217    bic%.\\t%0, %1, #%B2"
2218   [(set_attr "conds" "set")]
2219 )
2220
2221 (define_insn "*andsi3_compare0_scratch"
2222   [(set (reg:CC_NOOV CC_REGNUM)
2223         (compare:CC_NOOV
2224          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
2225                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
2226          (const_int 0)))
2227    (clobber (match_scratch:SI 2 "=X,r"))]
2228   "TARGET_32BIT"
2229   "@
2230    tst%?\\t%0, %1
2231    bic%.\\t%2, %0, #%B1"
2232   [(set_attr "conds" "set")]
2233 )
2234
2235 (define_insn "*zeroextractsi_compare0_scratch"
2236   [(set (reg:CC_NOOV CC_REGNUM)
2237         (compare:CC_NOOV (zero_extract:SI
2238                           (match_operand:SI 0 "s_register_operand" "r")
2239                           (match_operand 1 "const_int_operand" "n")
2240                           (match_operand 2 "const_int_operand" "n"))
2241                          (const_int 0)))]
2242   "TARGET_32BIT
2243   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2244       && INTVAL (operands[1]) > 0 
2245       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2246       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
2247   "*
2248   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2249                          << INTVAL (operands[2]));
2250   output_asm_insn (\"tst%?\\t%0, %1\", operands);
2251   return \"\";
2252   "
2253   [(set_attr "conds" "set")]
2254 )
2255
2256 (define_insn_and_split "*ne_zeroextractsi"
2257   [(set (match_operand:SI 0 "s_register_operand" "=r")
2258         (ne:SI (zero_extract:SI
2259                 (match_operand:SI 1 "s_register_operand" "r")
2260                 (match_operand:SI 2 "const_int_operand" "n")
2261                 (match_operand:SI 3 "const_int_operand" "n"))
2262                (const_int 0)))
2263    (clobber (reg:CC CC_REGNUM))]
2264   "TARGET_32BIT
2265    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2266        && INTVAL (operands[2]) > 0 
2267        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2268        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2269   "#"
2270   "TARGET_32BIT
2271    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2272        && INTVAL (operands[2]) > 0 
2273        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2274        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2275   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2276                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2277                                     (const_int 0)))
2278               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2279    (set (match_dup 0)
2280         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2281                          (match_dup 0) (const_int 1)))]
2282   "
2283   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2284                          << INTVAL (operands[3])); 
2285   "
2286   [(set_attr "conds" "clob")
2287    (set (attr "length")
2288         (if_then_else (eq_attr "is_thumb" "yes")
2289                       (const_int 12)
2290                       (const_int 8)))]
2291 )
2292
2293 (define_insn_and_split "*ne_zeroextractsi_shifted"
2294   [(set (match_operand:SI 0 "s_register_operand" "=r")
2295         (ne:SI (zero_extract:SI
2296                 (match_operand:SI 1 "s_register_operand" "r")
2297                 (match_operand:SI 2 "const_int_operand" "n")
2298                 (const_int 0))
2299                (const_int 0)))
2300    (clobber (reg:CC CC_REGNUM))]
2301   "TARGET_ARM"
2302   "#"
2303   "TARGET_ARM"
2304   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2305                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2306                                     (const_int 0)))
2307               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2308    (set (match_dup 0)
2309         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2310                          (match_dup 0) (const_int 1)))]
2311   "
2312   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2313   "
2314   [(set_attr "conds" "clob")
2315    (set_attr "length" "8")]
2316 )
2317
2318 (define_insn_and_split "*ite_ne_zeroextractsi"
2319   [(set (match_operand:SI 0 "s_register_operand" "=r")
2320         (if_then_else:SI (ne (zero_extract:SI
2321                               (match_operand:SI 1 "s_register_operand" "r")
2322                               (match_operand:SI 2 "const_int_operand" "n")
2323                               (match_operand:SI 3 "const_int_operand" "n"))
2324                              (const_int 0))
2325                          (match_operand:SI 4 "arm_not_operand" "rIK")
2326                          (const_int 0)))
2327    (clobber (reg:CC CC_REGNUM))]
2328   "TARGET_ARM
2329    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2330        && INTVAL (operands[2]) > 0 
2331        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2332        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2333    && !reg_overlap_mentioned_p (operands[0], operands[4])"
2334   "#"
2335   "TARGET_ARM
2336    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2337        && INTVAL (operands[2]) > 0 
2338        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2339        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2340    && !reg_overlap_mentioned_p (operands[0], operands[4])"
2341   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2342                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2343                                     (const_int 0)))
2344               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2345    (set (match_dup 0)
2346         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2347                          (match_dup 0) (match_dup 4)))]
2348   "
2349   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2350                          << INTVAL (operands[3])); 
2351   "
2352   [(set_attr "conds" "clob")
2353    (set_attr "length" "8")]
2354 )
2355
2356 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2357   [(set (match_operand:SI 0 "s_register_operand" "=r")
2358         (if_then_else:SI (ne (zero_extract:SI
2359                               (match_operand:SI 1 "s_register_operand" "r")
2360                               (match_operand:SI 2 "const_int_operand" "n")
2361                               (const_int 0))
2362                              (const_int 0))
2363                          (match_operand:SI 3 "arm_not_operand" "rIK")
2364                          (const_int 0)))
2365    (clobber (reg:CC CC_REGNUM))]
2366   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2367   "#"
2368   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2369   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2370                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2371                                     (const_int 0)))
2372               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2373    (set (match_dup 0)
2374         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2375                          (match_dup 0) (match_dup 3)))]
2376   "
2377   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2378   "
2379   [(set_attr "conds" "clob")
2380    (set_attr "length" "8")]
2381 )
2382
2383 (define_split
2384   [(set (match_operand:SI 0 "s_register_operand" "")
2385         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
2386                          (match_operand:SI 2 "const_int_operand" "")
2387                          (match_operand:SI 3 "const_int_operand" "")))
2388    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2389   "TARGET_THUMB1"
2390   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
2391    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
2392   "{
2393      HOST_WIDE_INT temp = INTVAL (operands[2]);
2394
2395      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2396      operands[3] = GEN_INT (32 - temp);
2397    }"
2398 )
2399
2400 ;; ??? Use Thumb-2 has bitfield insert/extract instructions.
2401 (define_split
2402   [(set (match_operand:SI 0 "s_register_operand" "")
2403         (match_operator:SI 1 "shiftable_operator"
2404          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2405                            (match_operand:SI 3 "const_int_operand" "")
2406                            (match_operand:SI 4 "const_int_operand" ""))
2407           (match_operand:SI 5 "s_register_operand" "")]))
2408    (clobber (match_operand:SI 6 "s_register_operand" ""))]
2409   "TARGET_ARM"
2410   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2411    (set (match_dup 0)
2412         (match_op_dup 1
2413          [(lshiftrt:SI (match_dup 6) (match_dup 4))
2414           (match_dup 5)]))]
2415   "{
2416      HOST_WIDE_INT temp = INTVAL (operands[3]);
2417
2418      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2419      operands[4] = GEN_INT (32 - temp);
2420    }"
2421 )
2422   
2423 (define_split
2424   [(set (match_operand:SI 0 "s_register_operand" "")
2425         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2426                          (match_operand:SI 2 "const_int_operand" "")
2427                          (match_operand:SI 3 "const_int_operand" "")))]
2428   "TARGET_THUMB1"
2429   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2430    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2431   "{
2432      HOST_WIDE_INT temp = INTVAL (operands[2]);
2433
2434      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2435      operands[3] = GEN_INT (32 - temp);
2436    }"
2437 )
2438
2439 (define_split
2440   [(set (match_operand:SI 0 "s_register_operand" "")
2441         (match_operator:SI 1 "shiftable_operator"
2442          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2443                            (match_operand:SI 3 "const_int_operand" "")
2444                            (match_operand:SI 4 "const_int_operand" ""))
2445           (match_operand:SI 5 "s_register_operand" "")]))
2446    (clobber (match_operand:SI 6 "s_register_operand" ""))]
2447   "TARGET_ARM"
2448   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2449    (set (match_dup 0)
2450         (match_op_dup 1
2451          [(ashiftrt:SI (match_dup 6) (match_dup 4))
2452           (match_dup 5)]))]
2453   "{
2454      HOST_WIDE_INT temp = INTVAL (operands[3]);
2455
2456      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2457      operands[4] = GEN_INT (32 - temp);
2458    }"
2459 )
2460   
2461 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
2462 ;;; represented by the bitfield, then this will produce incorrect results.
2463 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
2464 ;;; which have a real bit-field insert instruction, the truncation happens
2465 ;;; in the bit-field insert instruction itself.  Since arm does not have a
2466 ;;; bit-field insert instruction, we would have to emit code here to truncate
2467 ;;; the value before we insert.  This loses some of the advantage of having
2468 ;;; this insv pattern, so this pattern needs to be reevalutated.
2469
2470 (define_expand "insv"
2471   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
2472                          (match_operand:SI 1 "general_operand" "")
2473                          (match_operand:SI 2 "general_operand" ""))
2474         (match_operand:SI 3 "reg_or_int_operand" ""))]
2475   "TARGET_ARM || arm_arch_thumb2"
2476   "
2477   {
2478     int start_bit = INTVAL (operands[2]);
2479     int width = INTVAL (operands[1]);
2480     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2481     rtx target, subtarget;
2482
2483     if (arm_arch_thumb2)
2484       {
2485         bool use_bfi = TRUE;
2486
2487         if (GET_CODE (operands[3]) == CONST_INT)
2488           {
2489             HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2490
2491             if (val == 0)
2492               {
2493                 emit_insn (gen_insv_zero (operands[0], operands[1],
2494                                           operands[2]));
2495                 DONE;
2496               }
2497
2498             /* See if the set can be done with a single orr instruction.  */
2499             if (val == mask && const_ok_for_arm (val << start_bit))
2500               use_bfi = FALSE;
2501           }
2502           
2503         if (use_bfi)
2504           {
2505             if (GET_CODE (operands[3]) != REG)
2506               operands[3] = force_reg (SImode, operands[3]);
2507
2508             emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2509                                     operands[3]));
2510             DONE;
2511           }
2512       }
2513
2514     target = copy_rtx (operands[0]);
2515     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
2516        subreg as the final target.  */
2517     if (GET_CODE (target) == SUBREG)
2518       {
2519         subtarget = gen_reg_rtx (SImode);
2520         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2521             < GET_MODE_SIZE (SImode))
2522           target = SUBREG_REG (target);
2523       }
2524     else
2525       subtarget = target;    
2526
2527     if (GET_CODE (operands[3]) == CONST_INT)
2528       {
2529         /* Since we are inserting a known constant, we may be able to
2530            reduce the number of bits that we have to clear so that
2531            the mask becomes simple.  */
2532         /* ??? This code does not check to see if the new mask is actually
2533            simpler.  It may not be.  */
2534         rtx op1 = gen_reg_rtx (SImode);
2535         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
2536            start of this pattern.  */
2537         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2538         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2539
2540         emit_insn (gen_andsi3 (op1, operands[0],
2541                                gen_int_mode (~mask2, SImode)));
2542         emit_insn (gen_iorsi3 (subtarget, op1,
2543                                gen_int_mode (op3_value << start_bit, SImode)));
2544       }
2545     else if (start_bit == 0
2546              && !(const_ok_for_arm (mask)
2547                   || const_ok_for_arm (~mask)))
2548       {
2549         /* A Trick, since we are setting the bottom bits in the word,
2550            we can shift operand[3] up, operand[0] down, OR them together
2551            and rotate the result back again.  This takes 3 insns, and
2552            the third might be mergeable into another op.  */
2553         /* The shift up copes with the possibility that operand[3] is
2554            wider than the bitfield.  */
2555         rtx op0 = gen_reg_rtx (SImode);
2556         rtx op1 = gen_reg_rtx (SImode);
2557
2558         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2559         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2560         emit_insn (gen_iorsi3  (op1, op1, op0));
2561         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2562       }
2563     else if ((width + start_bit == 32)
2564              && !(const_ok_for_arm (mask)
2565                   || const_ok_for_arm (~mask)))
2566       {
2567         /* Similar trick, but slightly less efficient.  */
2568
2569         rtx op0 = gen_reg_rtx (SImode);
2570         rtx op1 = gen_reg_rtx (SImode);
2571
2572         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2573         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2574         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2575         emit_insn (gen_iorsi3 (subtarget, op1, op0));
2576       }
2577     else
2578       {
2579         rtx op0 = gen_int_mode (mask, SImode);
2580         rtx op1 = gen_reg_rtx (SImode);
2581         rtx op2 = gen_reg_rtx (SImode);
2582
2583         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2584           {
2585             rtx tmp = gen_reg_rtx (SImode);
2586
2587             emit_insn (gen_movsi (tmp, op0));
2588             op0 = tmp;
2589           }
2590
2591         /* Mask out any bits in operand[3] that are not needed.  */
2592            emit_insn (gen_andsi3 (op1, operands[3], op0));
2593
2594         if (GET_CODE (op0) == CONST_INT
2595             && (const_ok_for_arm (mask << start_bit)
2596                 || const_ok_for_arm (~(mask << start_bit))))
2597           {
2598             op0 = gen_int_mode (~(mask << start_bit), SImode);
2599             emit_insn (gen_andsi3 (op2, operands[0], op0));
2600           }
2601         else
2602           {
2603             if (GET_CODE (op0) == CONST_INT)
2604               {
2605                 rtx tmp = gen_reg_rtx (SImode);
2606
2607                 emit_insn (gen_movsi (tmp, op0));
2608                 op0 = tmp;
2609               }
2610
2611             if (start_bit != 0)
2612               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
2613             
2614             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2615           }
2616
2617         if (start_bit != 0)
2618           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
2619
2620         emit_insn (gen_iorsi3 (subtarget, op1, op2));
2621       }
2622
2623     if (subtarget != target)
2624       {
2625         /* If TARGET is still a SUBREG, then it must be wider than a word,
2626            so we must be careful only to set the subword we were asked to.  */
2627         if (GET_CODE (target) == SUBREG)
2628           emit_move_insn (target, subtarget);
2629         else
2630           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2631       }
2632
2633     DONE;
2634   }"
2635 )
2636
2637 (define_insn "insv_zero"
2638   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2639                          (match_operand:SI 1 "const_int_operand" "M")
2640                          (match_operand:SI 2 "const_int_operand" "M"))
2641         (const_int 0))]
2642   "arm_arch_thumb2"
2643   "bfc%?\t%0, %2, %1"
2644   [(set_attr "length" "4")
2645    (set_attr "predicable" "yes")]
2646 )
2647
2648 (define_insn "insv_t2"
2649   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2650                          (match_operand:SI 1 "const_int_operand" "M")
2651                          (match_operand:SI 2 "const_int_operand" "M"))
2652         (match_operand:SI 3 "s_register_operand" "r"))]
2653   "arm_arch_thumb2"
2654   "bfi%?\t%0, %3, %2, %1"
2655   [(set_attr "length" "4")
2656    (set_attr "predicable" "yes")]
2657 )
2658
2659 ; constants for op 2 will never be given to these patterns.
2660 (define_insn_and_split "*anddi_notdi_di"
2661   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2662         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2663                 (match_operand:DI 2 "s_register_operand" "r,0")))]
2664   "TARGET_32BIT"
2665   "#"
2666   "TARGET_32BIT && reload_completed
2667    && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2668    && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2669   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2670    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2671   "
2672   {
2673     operands[3] = gen_highpart (SImode, operands[0]);
2674     operands[0] = gen_lowpart (SImode, operands[0]);
2675     operands[4] = gen_highpart (SImode, operands[1]);
2676     operands[1] = gen_lowpart (SImode, operands[1]);
2677     operands[5] = gen_highpart (SImode, operands[2]);
2678     operands[2] = gen_lowpart (SImode, operands[2]);
2679   }"
2680   [(set_attr "length" "8")
2681    (set_attr "predicable" "yes")]
2682 )
2683   
2684 (define_insn_and_split "*anddi_notzesidi_di"
2685   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2686         (and:DI (not:DI (zero_extend:DI
2687                          (match_operand:SI 2 "s_register_operand" "r,r")))
2688                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2689   "TARGET_32BIT"
2690   "@
2691    bic%?\\t%Q0, %Q1, %2
2692    #"
2693   ; (not (zero_extend ...)) allows us to just copy the high word from
2694   ; operand1 to operand0.
2695   "TARGET_32BIT
2696    && reload_completed
2697    && operands[0] != operands[1]"
2698   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2699    (set (match_dup 3) (match_dup 4))]
2700   "
2701   {
2702     operands[3] = gen_highpart (SImode, operands[0]);
2703     operands[0] = gen_lowpart (SImode, operands[0]);
2704     operands[4] = gen_highpart (SImode, operands[1]);
2705     operands[1] = gen_lowpart (SImode, operands[1]);
2706   }"
2707   [(set_attr "length" "4,8")
2708    (set_attr "predicable" "yes")]
2709 )
2710   
2711 (define_insn_and_split "*anddi_notsesidi_di"
2712   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2713         (and:DI (not:DI (sign_extend:DI
2714                          (match_operand:SI 2 "s_register_operand" "r,r")))
2715                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2716   "TARGET_32BIT"
2717   "#"
2718   "TARGET_32BIT && reload_completed"
2719   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2720    (set (match_dup 3) (and:SI (not:SI
2721                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2722                                (match_dup 4)))]
2723   "
2724   {
2725     operands[3] = gen_highpart (SImode, operands[0]);
2726     operands[0] = gen_lowpart (SImode, operands[0]);
2727     operands[4] = gen_highpart (SImode, operands[1]);
2728     operands[1] = gen_lowpart (SImode, operands[1]);
2729   }"
2730   [(set_attr "length" "8")
2731    (set_attr "predicable" "yes")]
2732 )
2733   
2734 (define_insn "andsi_notsi_si"
2735   [(set (match_operand:SI 0 "s_register_operand" "=r")
2736         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2737                 (match_operand:SI 1 "s_register_operand" "r")))]
2738   "TARGET_32BIT"
2739   "bic%?\\t%0, %1, %2"
2740   [(set_attr "predicable" "yes")]
2741 )
2742
2743 (define_insn "thumb1_bicsi3"
2744   [(set (match_operand:SI                 0 "register_operand" "=l")
2745         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2746                 (match_operand:SI         2 "register_operand" "0")))]
2747   "TARGET_THUMB1"
2748   "bic\\t%0, %1"
2749   [(set_attr "length" "2")
2750    (set_attr "conds" "set")])
2751
2752 (define_insn "andsi_not_shiftsi_si"
2753   [(set (match_operand:SI 0 "s_register_operand" "=r")
2754         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2755                          [(match_operand:SI 2 "s_register_operand" "r")
2756                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2757                 (match_operand:SI 1 "s_register_operand" "r")))]
2758   "TARGET_ARM"
2759   "bic%?\\t%0, %1, %2%S4"
2760   [(set_attr "predicable" "yes")
2761    (set_attr "shift" "2")
2762    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2763                       (const_string "alu_shift")
2764                       (const_string "alu_shift_reg")))]
2765 )
2766
2767 (define_insn "*andsi_notsi_si_compare0"
2768   [(set (reg:CC_NOOV CC_REGNUM)
2769         (compare:CC_NOOV
2770          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2771                  (match_operand:SI 1 "s_register_operand" "r"))
2772          (const_int 0)))
2773    (set (match_operand:SI 0 "s_register_operand" "=r")
2774         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2775   "TARGET_32BIT"
2776   "bic%.\\t%0, %1, %2"
2777   [(set_attr "conds" "set")]
2778 )
2779
2780 (define_insn "*andsi_notsi_si_compare0_scratch"
2781   [(set (reg:CC_NOOV CC_REGNUM)
2782         (compare:CC_NOOV
2783          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2784                  (match_operand:SI 1 "s_register_operand" "r"))
2785          (const_int 0)))
2786    (clobber (match_scratch:SI 0 "=r"))]
2787   "TARGET_32BIT"
2788   "bic%.\\t%0, %1, %2"
2789   [(set_attr "conds" "set")]
2790 )
2791
2792 (define_expand "iordi3"
2793   [(set (match_operand:DI         0 "s_register_operand" "")
2794         (ior:DI (match_operand:DI 1 "s_register_operand" "")
2795                 (match_operand:DI 2 "neon_logic_op2" "")))]
2796   "TARGET_32BIT"
2797   ""
2798 )
2799
2800 (define_insn "*iordi3_insn"
2801   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2802         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2803                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2804   "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
2805   "#"
2806   [(set_attr "length" "8")
2807    (set_attr "predicable" "yes")]
2808 )
2809
2810 (define_insn "*iordi_zesidi_di"
2811   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2812         (ior:DI (zero_extend:DI
2813                  (match_operand:SI 2 "s_register_operand" "r,r"))
2814                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2815   "TARGET_32BIT"
2816   "@
2817    orr%?\\t%Q0, %Q1, %2
2818    #"
2819   [(set_attr "length" "4,8")
2820    (set_attr "predicable" "yes")]
2821 )
2822
2823 (define_insn "*iordi_sesidi_di"
2824   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2825         (ior:DI (sign_extend:DI
2826                  (match_operand:SI 2 "s_register_operand" "r,r"))
2827                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2828   "TARGET_32BIT"
2829   "#"
2830   [(set_attr "length" "8")
2831    (set_attr "predicable" "yes")]
2832 )
2833
2834 (define_expand "iorsi3"
2835   [(set (match_operand:SI         0 "s_register_operand" "")
2836         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2837                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2838   "TARGET_EITHER"
2839   "
2840   if (GET_CODE (operands[2]) == CONST_INT)
2841     {
2842       if (TARGET_32BIT)
2843         {
2844           arm_split_constant (IOR, SImode, NULL_RTX,
2845                               INTVAL (operands[2]), operands[0], operands[1],
2846                               optimize && can_create_pseudo_p ());
2847           DONE;
2848         }
2849       else /* TARGET_THUMB1 */
2850         {
2851           rtx tmp = force_reg (SImode, operands[2]);
2852           if (rtx_equal_p (operands[0], operands[1]))
2853             operands[2] = tmp;
2854           else
2855             {
2856               operands[2] = operands[1];
2857               operands[1] = tmp;
2858             }
2859         }
2860     }
2861   "
2862 )
2863
2864 (define_insn_and_split "*iorsi3_insn"
2865   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2866         (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
2867                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
2868   "TARGET_32BIT"
2869   "@
2870    orr%?\\t%0, %1, %2
2871    orn%?\\t%0, %1, #%B2
2872    #"
2873   "TARGET_32BIT
2874    && GET_CODE (operands[2]) == CONST_INT
2875    && !(const_ok_for_arm (INTVAL (operands[2]))
2876         || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
2877   [(clobber (const_int 0))]
2878 {
2879   arm_split_constant (IOR, SImode, curr_insn, 
2880                       INTVAL (operands[2]), operands[0], operands[1], 0);
2881   DONE;
2882 }
2883   [(set_attr "length" "4,4,16")
2884    (set_attr "arch" "32,t2,32")
2885    (set_attr "predicable" "yes")])
2886
2887 (define_insn "*thumb1_iorsi3_insn"
2888   [(set (match_operand:SI         0 "register_operand" "=l")
2889         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2890                 (match_operand:SI 2 "register_operand" "l")))]
2891   "TARGET_THUMB1"
2892   "orr\\t%0, %2"
2893   [(set_attr "length" "2")
2894    (set_attr "conds" "set")])
2895
2896 (define_peephole2
2897   [(match_scratch:SI 3 "r")
2898    (set (match_operand:SI 0 "arm_general_register_operand" "")
2899         (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2900                 (match_operand:SI 2 "const_int_operand" "")))]
2901   "TARGET_ARM
2902    && !const_ok_for_arm (INTVAL (operands[2]))
2903    && const_ok_for_arm (~INTVAL (operands[2]))"
2904   [(set (match_dup 3) (match_dup 2))
2905    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2906   ""
2907 )
2908
2909 (define_insn "*iorsi3_compare0"
2910   [(set (reg:CC_NOOV CC_REGNUM)
2911         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2912                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2913                          (const_int 0)))
2914    (set (match_operand:SI 0 "s_register_operand" "=r")
2915         (ior:SI (match_dup 1) (match_dup 2)))]
2916   "TARGET_32BIT"
2917   "orr%.\\t%0, %1, %2"
2918   [(set_attr "conds" "set")]
2919 )
2920
2921 (define_insn "*iorsi3_compare0_scratch"
2922   [(set (reg:CC_NOOV CC_REGNUM)
2923         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2924                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2925                          (const_int 0)))
2926    (clobber (match_scratch:SI 0 "=r"))]
2927   "TARGET_32BIT"
2928   "orr%.\\t%0, %1, %2"
2929   [(set_attr "conds" "set")]
2930 )
2931
2932 (define_expand "xordi3"
2933   [(set (match_operand:DI         0 "s_register_operand" "")
2934         (xor:DI (match_operand:DI 1 "s_register_operand" "")
2935                 (match_operand:DI 2 "s_register_operand" "")))]
2936   "TARGET_32BIT"
2937   ""
2938 )
2939
2940 (define_insn "*xordi3_insn"
2941   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2942         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2943                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2944   "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
2945   "#"
2946   [(set_attr "length" "8")
2947    (set_attr "predicable" "yes")]
2948 )
2949
2950 (define_insn "*xordi_zesidi_di"
2951   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2952         (xor:DI (zero_extend:DI
2953                  (match_operand:SI 2 "s_register_operand" "r,r"))
2954                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2955   "TARGET_32BIT"
2956   "@
2957    eor%?\\t%Q0, %Q1, %2
2958    #"
2959   [(set_attr "length" "4,8")
2960    (set_attr "predicable" "yes")]
2961 )
2962
2963 (define_insn "*xordi_sesidi_di"
2964   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2965         (xor:DI (sign_extend:DI
2966                  (match_operand:SI 2 "s_register_operand" "r,r"))
2967                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2968   "TARGET_32BIT"
2969   "#"
2970   [(set_attr "length" "8")
2971    (set_attr "predicable" "yes")]
2972 )
2973
2974 (define_expand "xorsi3"
2975   [(set (match_operand:SI         0 "s_register_operand" "")
2976         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2977                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2978   "TARGET_EITHER"
2979   "if (GET_CODE (operands[2]) == CONST_INT)
2980     {
2981       if (TARGET_32BIT)
2982         {
2983           arm_split_constant (XOR, SImode, NULL_RTX,
2984                               INTVAL (operands[2]), operands[0], operands[1],
2985                               optimize && can_create_pseudo_p ());
2986           DONE;
2987         }
2988       else /* TARGET_THUMB1 */
2989         {
2990           rtx tmp = force_reg (SImode, operands[2]);
2991           if (rtx_equal_p (operands[0], operands[1]))
2992             operands[2] = tmp;
2993           else
2994             {
2995               operands[2] = operands[1];
2996               operands[1] = tmp;
2997             }
2998         }
2999     }"
3000 )
3001
3002 (define_insn "*arm_xorsi3"
3003   [(set (match_operand:SI         0 "s_register_operand" "=r")
3004         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
3005                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
3006   "TARGET_32BIT"
3007   "eor%?\\t%0, %1, %2"
3008   [(set_attr "predicable" "yes")]
3009 )
3010
3011 (define_insn "*thumb1_xorsi3_insn"
3012   [(set (match_operand:SI         0 "register_operand" "=l")
3013         (xor:SI (match_operand:SI 1 "register_operand" "%0")
3014                 (match_operand:SI 2 "register_operand" "l")))]
3015   "TARGET_THUMB1"
3016   "eor\\t%0, %2"
3017   [(set_attr "length" "2")
3018    (set_attr "conds" "set")])
3019
3020 (define_insn "*xorsi3_compare0"
3021   [(set (reg:CC_NOOV CC_REGNUM)
3022         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
3023                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
3024                          (const_int 0)))
3025    (set (match_operand:SI 0 "s_register_operand" "=r")
3026         (xor:SI (match_dup 1) (match_dup 2)))]
3027   "TARGET_32BIT"
3028   "eor%.\\t%0, %1, %2"
3029   [(set_attr "conds" "set")]
3030 )
3031
3032 (define_insn "*xorsi3_compare0_scratch"
3033   [(set (reg:CC_NOOV CC_REGNUM)
3034         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
3035                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
3036                          (const_int 0)))]
3037   "TARGET_32BIT"
3038   "teq%?\\t%0, %1"
3039   [(set_attr "conds" "set")]
3040 )
3041
3042 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
3043 ; (NOT D) we can sometimes merge the final NOT into one of the following
3044 ; insns.
3045
3046 (define_split
3047   [(set (match_operand:SI 0 "s_register_operand" "")
3048         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
3049                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
3050                 (match_operand:SI 3 "arm_rhs_operand" "")))
3051    (clobber (match_operand:SI 4 "s_register_operand" ""))]
3052   "TARGET_32BIT"
3053   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
3054                               (not:SI (match_dup 3))))
3055    (set (match_dup 0) (not:SI (match_dup 4)))]
3056   ""
3057 )
3058
3059 (define_insn "*andsi_iorsi3_notsi"
3060   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
3061         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
3062                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
3063                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
3064   "TARGET_32BIT"
3065   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
3066   [(set_attr "length" "8")
3067    (set_attr "ce_count" "2")
3068    (set_attr "predicable" "yes")]
3069 )
3070
3071 ; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
3072 ; insns are available?
3073 (define_split
3074   [(set (match_operand:SI 0 "s_register_operand" "")
3075         (match_operator:SI 1 "logical_binary_operator"
3076          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3077                            (match_operand:SI 3 "const_int_operand" "")
3078                            (match_operand:SI 4 "const_int_operand" ""))
3079           (match_operator:SI 9 "logical_binary_operator"
3080            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3081                          (match_operand:SI 6 "const_int_operand" ""))
3082             (match_operand:SI 7 "s_register_operand" "")])]))
3083    (clobber (match_operand:SI 8 "s_register_operand" ""))]
3084   "TARGET_32BIT
3085    && GET_CODE (operands[1]) == GET_CODE (operands[9])
3086    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3087   [(set (match_dup 8)
3088         (match_op_dup 1
3089          [(ashift:SI (match_dup 2) (match_dup 4))
3090           (match_dup 5)]))
3091    (set (match_dup 0)
3092         (match_op_dup 1
3093          [(lshiftrt:SI (match_dup 8) (match_dup 6))
3094           (match_dup 7)]))]
3095   "
3096   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3097 ")
3098
3099 (define_split
3100   [(set (match_operand:SI 0 "s_register_operand" "")
3101         (match_operator:SI 1 "logical_binary_operator"
3102          [(match_operator:SI 9 "logical_binary_operator"
3103            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3104                          (match_operand:SI 6 "const_int_operand" ""))
3105             (match_operand:SI 7 "s_register_operand" "")])
3106           (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3107                            (match_operand:SI 3 "const_int_operand" "")
3108                            (match_operand:SI 4 "const_int_operand" ""))]))
3109    (clobber (match_operand:SI 8 "s_register_operand" ""))]
3110   "TARGET_32BIT
3111    && GET_CODE (operands[1]) == GET_CODE (operands[9])
3112    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3113   [(set (match_dup 8)
3114         (match_op_dup 1
3115          [(ashift:SI (match_dup 2) (match_dup 4))
3116           (match_dup 5)]))
3117    (set (match_dup 0)
3118         (match_op_dup 1
3119          [(lshiftrt:SI (match_dup 8) (match_dup 6))
3120           (match_dup 7)]))]
3121   "
3122   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3123 ")
3124
3125 (define_split
3126   [(set (match_operand:SI 0 "s_register_operand" "")
3127         (match_operator:SI 1 "logical_binary_operator"
3128          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3129                            (match_operand:SI 3 "const_int_operand" "")
3130                            (match_operand:SI 4 "const_int_operand" ""))
3131           (match_operator:SI 9 "logical_binary_operator"
3132            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3133                          (match_operand:SI 6 "const_int_operand" ""))
3134             (match_operand:SI 7 "s_register_operand" "")])]))
3135    (clobber (match_operand:SI 8 "s_register_operand" ""))]
3136   "TARGET_32BIT
3137    && GET_CODE (operands[1]) == GET_CODE (operands[9])
3138    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3139   [(set (match_dup 8)
3140         (match_op_dup 1
3141          [(ashift:SI (match_dup 2) (match_dup 4))
3142           (match_dup 5)]))
3143    (set (match_dup 0)
3144         (match_op_dup 1
3145          [(ashiftrt:SI (match_dup 8) (match_dup 6))
3146           (match_dup 7)]))]
3147   "
3148   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3149 ")
3150
3151 (define_split
3152   [(set (match_operand:SI 0 "s_register_operand" "")
3153         (match_operator:SI 1 "logical_binary_operator"
3154          [(match_operator:SI 9 "logical_binary_operator"
3155            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3156                          (match_operand:SI 6 "const_int_operand" ""))
3157             (match_operand:SI 7 "s_register_operand" "")])
3158           (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3159                            (match_operand:SI 3 "const_int_operand" "")
3160                            (match_operand:SI 4 "const_int_operand" ""))]))
3161    (clobber (match_operand:SI 8 "s_register_operand" ""))]
3162   "TARGET_32BIT
3163    && GET_CODE (operands[1]) == GET_CODE (operands[9])
3164    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3165   [(set (match_dup 8)
3166         (match_op_dup 1
3167          [(ashift:SI (match_dup 2) (match_dup 4))
3168           (match_dup 5)]))
3169    (set (match_dup 0)
3170         (match_op_dup 1
3171          [(ashiftrt:SI (match_dup 8) (match_dup 6))
3172           (match_dup 7)]))]
3173   "
3174   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3175 ")
3176 \f
3177
3178 ;; Minimum and maximum insns
3179
3180 (define_expand "smaxsi3"
3181   [(parallel [
3182     (set (match_operand:SI 0 "s_register_operand" "")
3183          (smax:SI (match_operand:SI 1 "s_register_operand" "")
3184                   (match_operand:SI 2 "arm_rhs_operand" "")))
3185     (clobber (reg:CC CC_REGNUM))])]
3186   "TARGET_32BIT"
3187   "
3188   if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
3189     {
3190       /* No need for a clobber of the condition code register here.  */
3191       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3192                               gen_rtx_SMAX (SImode, operands[1],
3193                                             operands[2])));
3194       DONE;
3195     }
3196 ")
3197
3198 (define_insn "*smax_0"
3199   [(set (match_operand:SI 0 "s_register_operand" "=r")
3200         (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3201                  (const_int 0)))]
3202   "TARGET_32BIT"
3203   "bic%?\\t%0, %1, %1, asr #31"
3204   [(set_attr "predicable" "yes")]
3205 )
3206
3207 (define_insn "*smax_m1"
3208   [(set (match_operand:SI 0 "s_register_operand" "=r")
3209         (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3210                  (const_int -1)))]
3211   "TARGET_32BIT"
3212   "orr%?\\t%0, %1, %1, asr #31"
3213   [(set_attr "predicable" "yes")]
3214 )
3215
3216 (define_insn "*arm_smax_insn"
3217   [(set (match_operand:SI          0 "s_register_operand" "=r,r")
3218         (smax:SI (match_operand:SI 1 "s_register_operand"  "%0,?r")
3219                  (match_operand:SI 2 "arm_rhs_operand"    "rI,rI")))
3220    (clobber (reg:CC CC_REGNUM))]
3221   "TARGET_ARM"
3222   "@
3223    cmp\\t%1, %2\;movlt\\t%0, %2
3224    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
3225   [(set_attr "conds" "clob")
3226    (set_attr "length" "8,12")]
3227 )
3228
3229 (define_expand "sminsi3"
3230   [(parallel [
3231     (set (match_operand:SI 0 "s_register_operand" "")
3232          (smin:SI (match_operand:SI 1 "s_register_operand" "")
3233                   (match_operand:SI 2 "arm_rhs_operand" "")))
3234     (clobber (reg:CC CC_REGNUM))])]
3235   "TARGET_32BIT"
3236   "
3237   if (operands[2] == const0_rtx)
3238     {
3239       /* No need for a clobber of the condition code register here.  */
3240       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3241                               gen_rtx_SMIN (SImode, operands[1],
3242                                             operands[2])));
3243       DONE;
3244     }
3245 ")
3246
3247 (define_insn "*smin_0"
3248   [(set (match_operand:SI 0 "s_register_operand" "=r")
3249         (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3250                  (const_int 0)))]
3251   "TARGET_32BIT"
3252   "and%?\\t%0, %1, %1, asr #31"
3253   [(set_attr "predicable" "yes")]
3254 )
3255
3256 (define_insn "*arm_smin_insn"
3257   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3258         (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3259                  (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
3260    (clobber (reg:CC CC_REGNUM))]
3261   "TARGET_ARM"
3262   "@
3263    cmp\\t%1, %2\;movge\\t%0, %2
3264    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
3265   [(set_attr "conds" "clob")
3266    (set_attr "length" "8,12")]
3267 )
3268
3269 (define_expand "umaxsi3"
3270   [(parallel [
3271     (set (match_operand:SI 0 "s_register_operand" "")
3272          (umax:SI (match_operand:SI 1 "s_register_operand" "")
3273                   (match_operand:SI 2 "arm_rhs_operand" "")))
3274     (clobber (reg:CC CC_REGNUM))])]
3275   "TARGET_32BIT"
3276   ""
3277 )
3278
3279 (define_insn "*arm_umaxsi3"
3280   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3281         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3282                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
3283    (clobber (reg:CC CC_REGNUM))]
3284   "TARGET_ARM"
3285   "@
3286    cmp\\t%1, %2\;movcc\\t%0, %2
3287    cmp\\t%1, %2\;movcs\\t%0, %1
3288    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
3289   [(set_attr "conds" "clob")
3290    (set_attr "length" "8,8,12")]
3291 )
3292
3293 (define_expand "uminsi3"
3294   [(parallel [
3295     (set (match_operand:SI 0 "s_register_operand" "")
3296          (umin:SI (match_operand:SI 1 "s_register_operand" "")
3297                   (match_operand:SI 2 "arm_rhs_operand" "")))
3298     (clobber (reg:CC CC_REGNUM))])]
3299   "TARGET_32BIT"
3300   ""
3301 )
3302
3303 (define_insn "*arm_uminsi3"
3304   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3305         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3306                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
3307    (clobber (reg:CC CC_REGNUM))]
3308   "TARGET_ARM"
3309   "@
3310    cmp\\t%1, %2\;movcs\\t%0, %2
3311    cmp\\t%1, %2\;movcc\\t%0, %1
3312    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
3313   [(set_attr "conds" "clob")
3314    (set_attr "length" "8,8,12")]
3315 )
3316
3317 (define_insn "*store_minmaxsi"
3318   [(set (match_operand:SI 0 "memory_operand" "=m")
3319         (match_operator:SI 3 "minmax_operator"
3320          [(match_operand:SI 1 "s_register_operand" "r")
3321           (match_operand:SI 2 "s_register_operand" "r")]))
3322    (clobber (reg:CC CC_REGNUM))]
3323   "TARGET_32BIT"
3324   "*
3325   operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3326                                 operands[1], operands[2]);
3327   output_asm_insn (\"cmp\\t%1, %2\", operands);
3328   if (TARGET_THUMB2)
3329     output_asm_insn (\"ite\t%d3\", operands);
3330   output_asm_insn (\"str%d3\\t%1, %0\", operands);
3331   output_asm_insn (\"str%D3\\t%2, %0\", operands);
3332   return \"\";
3333   "
3334   [(set_attr "conds" "clob")
3335    (set (attr "length")
3336         (if_then_else (eq_attr "is_thumb" "yes")
3337                       (const_int 14)
3338                       (const_int 12)))
3339    (set_attr "type" "store1")]
3340 )
3341
3342 ; Reject the frame pointer in operand[1], since reloading this after
3343 ; it has been eliminated can cause carnage.
3344 (define_insn "*minmax_arithsi"
3345   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3346         (match_operator:SI 4 "shiftable_operator"
3347          [(match_operator:SI 5 "minmax_operator"
3348            [(match_operand:SI 2 "s_register_operand" "r,r")
3349             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3350           (match_operand:SI 1 "s_register_operand" "0,?r")]))
3351    (clobber (reg:CC CC_REGNUM))]
3352   "TARGET_32BIT && !arm_eliminable_register (operands[1])"
3353   "*
3354   {
3355     enum rtx_code code = GET_CODE (operands[4]);
3356     bool need_else;
3357
3358     if (which_alternative != 0 || operands[3] != const0_rtx
3359         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
3360       need_else = true;
3361     else
3362       need_else = false;
3363
3364     operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3365                                   operands[2], operands[3]);
3366     output_asm_insn (\"cmp\\t%2, %3\", operands);
3367     if (TARGET_THUMB2)
3368       {
3369         if (need_else)
3370           output_asm_insn (\"ite\\t%d5\", operands);
3371         else
3372           output_asm_insn (\"it\\t%d5\", operands);
3373       }
3374     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
3375     if (need_else)
3376       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3377     return \"\";
3378   }"
3379   [(set_attr "conds" "clob")
3380    (set (attr "length")
3381         (if_then_else (eq_attr "is_thumb" "yes")
3382                       (const_int 14)
3383                       (const_int 12)))]
3384 )
3385
3386 \f
3387 ;; Shift and rotation insns
3388
3389 (define_expand "ashldi3"
3390   [(set (match_operand:DI            0 "s_register_operand" "")
3391         (ashift:DI (match_operand:DI 1 "s_register_operand" "")
3392                    (match_operand:SI 2 "reg_or_int_operand" "")))]
3393   "TARGET_32BIT"
3394   "
3395   if (GET_CODE (operands[2]) == CONST_INT)
3396     {
3397       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3398         {
3399           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3400           DONE;
3401         }
3402         /* Ideally we shouldn't fail here if we could know that operands[1] 
3403            ends up already living in an iwmmxt register. Otherwise it's
3404            cheaper to have the alternate code being generated than moving
3405            values to iwmmxt regs and back.  */
3406         FAIL;
3407     }
3408   else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
3409     FAIL;
3410   "
3411 )
3412
3413 (define_insn "arm_ashldi3_1bit"
3414   [(set (match_operand:DI            0 "s_register_operand" "=r,&r")
3415         (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
3416                    (const_int 1)))
3417    (clobber (reg:CC CC_REGNUM))]
3418   "TARGET_32BIT"
3419   "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
3420   [(set_attr "conds" "clob")
3421    (set_attr "length" "8")]
3422 )
3423
3424 (define_expand "ashlsi3"
3425   [(set (match_operand:SI            0 "s_register_operand" "")
3426         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3427                    (match_operand:SI 2 "arm_rhs_operand" "")))]
3428   "TARGET_EITHER"
3429   "
3430   if (GET_CODE (operands[2]) == CONST_INT
3431       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3432     {
3433       emit_insn (gen_movsi (operands[0], const0_rtx));
3434       DONE;
3435     }
3436   "
3437 )
3438
3439 (define_insn "*thumb1_ashlsi3"
3440   [(set (match_operand:SI            0 "register_operand" "=l,l")
3441         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
3442                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
3443   "TARGET_THUMB1"
3444   "lsl\\t%0, %1, %2"
3445   [(set_attr "length" "2")
3446    (set_attr "conds" "set")])
3447
3448 (define_expand "ashrdi3"
3449   [(set (match_operand:DI              0 "s_register_operand" "")
3450         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3451                      (match_operand:SI 2 "reg_or_int_operand" "")))]
3452   "TARGET_32BIT"
3453   "
3454   if (GET_CODE (operands[2]) == CONST_INT)
3455     {
3456       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3457         {
3458           emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3459           DONE;
3460         }
3461         /* Ideally we shouldn't fail here if we could know that operands[1] 
3462            ends up already living in an iwmmxt register. Otherwise it's
3463            cheaper to have the alternate code being generated than moving
3464            values to iwmmxt regs and back.  */
3465         FAIL;
3466     }
3467   else if (!TARGET_REALLY_IWMMXT)
3468     FAIL;
3469   "
3470 )
3471
3472 (define_insn "arm_ashrdi3_1bit"
3473   [(set (match_operand:DI              0 "s_register_operand" "=r,&r")
3474         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
3475                      (const_int 1)))
3476    (clobber (reg:CC CC_REGNUM))]
3477   "TARGET_32BIT"
3478   "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
3479   [(set_attr "conds" "clob")
3480    (set_attr "insn" "mov")
3481    (set_attr "length" "8")]
3482 )
3483
3484 (define_expand "ashrsi3"
3485   [(set (match_operand:SI              0 "s_register_operand" "")
3486         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3487                      (match_operand:SI 2 "arm_rhs_operand" "")))]
3488   "TARGET_EITHER"
3489   "
3490   if (GET_CODE (operands[2]) == CONST_INT
3491       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3492     operands[2] = GEN_INT (31);
3493   "
3494 )
3495
3496 (define_insn "*thumb1_ashrsi3"
3497   [(set (match_operand:SI              0 "register_operand" "=l,l")
3498         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3499                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
3500   "TARGET_THUMB1"
3501   "asr\\t%0, %1, %2"
3502   [(set_attr "length" "2")
3503    (set_attr "conds" "set")])
3504
3505 (define_expand "lshrdi3"
3506   [(set (match_operand:DI              0 "s_register_operand" "")
3507         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3508                      (match_operand:SI 2 "reg_or_int_operand" "")))]
3509   "TARGET_32BIT"
3510   "
3511   if (GET_CODE (operands[2]) == CONST_INT)
3512     {
3513       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3514         {
3515           emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3516           DONE;
3517         }
3518         /* Ideally we shouldn't fail here if we could know that operands[1] 
3519            ends up already living in an iwmmxt register. Otherwise it's
3520            cheaper to have the alternate code being generated than moving
3521            values to iwmmxt regs and back.  */
3522         FAIL;
3523     }
3524   else if (!TARGET_REALLY_IWMMXT)
3525     FAIL;
3526   "
3527 )
3528
3529 (define_insn "arm_lshrdi3_1bit"
3530   [(set (match_operand:DI              0 "s_register_operand" "=r,&r")
3531         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
3532                      (const_int 1)))
3533    (clobber (reg:CC CC_REGNUM))]
3534   "TARGET_32BIT"
3535   "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
3536   [(set_attr "conds" "clob")
3537    (set_attr "insn" "mov")
3538    (set_attr "length" "8")]
3539 )
3540
3541 (define_expand "lshrsi3"
3542   [(set (match_operand:SI              0 "s_register_operand" "")
3543         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3544                      (match_operand:SI 2 "arm_rhs_operand" "")))]
3545   "TARGET_EITHER"
3546   "
3547   if (GET_CODE (operands[2]) == CONST_INT
3548       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3549     {
3550       emit_insn (gen_movsi (operands[0], const0_rtx));
3551       DONE;
3552     }
3553   "
3554 )
3555
3556 (define_insn "*thumb1_lshrsi3"
3557   [(set (match_operand:SI              0 "register_operand" "=l,l")
3558         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3559                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
3560   "TARGET_THUMB1"
3561   "lsr\\t%0, %1, %2"
3562   [(set_attr "length" "2")
3563    (set_attr "conds" "set")])
3564
3565 (define_expand "rotlsi3"
3566   [(set (match_operand:SI              0 "s_register_operand" "")
3567         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3568                      (match_operand:SI 2 "reg_or_int_operand" "")))]
3569   "TARGET_32BIT"
3570   "
3571   if (GET_CODE (operands[2]) == CONST_INT)
3572     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3573   else
3574     {
3575       rtx reg = gen_reg_rtx (SImode);
3576       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3577       operands[2] = reg;
3578     }
3579   "
3580 )
3581
3582 (define_expand "rotrsi3"
3583   [(set (match_operand:SI              0 "s_register_operand" "")
3584         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3585                      (match_operand:SI 2 "arm_rhs_operand" "")))]
3586   "TARGET_EITHER"
3587   "
3588   if (TARGET_32BIT)
3589     {
3590       if (GET_CODE (operands[2]) == CONST_INT
3591           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3592         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3593     }
3594   else /* TARGET_THUMB1 */
3595     {
3596       if (GET_CODE (operands [2]) == CONST_INT)
3597         operands [2] = force_reg (SImode, operands[2]);
3598     }
3599   "
3600 )
3601
3602 (define_insn "*thumb1_rotrsi3"
3603   [(set (match_operand:SI              0 "register_operand" "=l")
3604         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
3605                      (match_operand:SI 2 "register_operand" "l")))]
3606   "TARGET_THUMB1"
3607   "ror\\t%0, %0, %2"
3608   [(set_attr "length" "2")]
3609 )
3610
3611 (define_insn "*arm_shiftsi3"
3612   [(set (match_operand:SI   0 "s_register_operand" "=r")
3613         (match_operator:SI  3 "shift_operator"
3614          [(match_operand:SI 1 "s_register_operand"  "r")
3615           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
3616   "TARGET_32BIT"
3617   "* return arm_output_shift(operands, 0);"
3618   [(set_attr "predicable" "yes")
3619    (set_attr "shift" "1")
3620    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3621                       (const_string "alu_shift")
3622                       (const_string "alu_shift_reg")))]
3623 )
3624
3625 (define_insn "*shiftsi3_compare0"
3626   [(set (reg:CC_NOOV CC_REGNUM)
3627         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3628                           [(match_operand:SI 1 "s_register_operand" "r")
3629                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
3630                          (const_int 0)))
3631    (set (match_operand:SI 0 "s_register_operand" "=r")
3632         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
3633   "TARGET_32BIT"
3634   "* return arm_output_shift(operands, 1);"
3635   [(set_attr "conds" "set")
3636    (set_attr "shift" "1")
3637    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3638                       (const_string "alu_shift")
3639                       (const_string "alu_shift_reg")))]
3640 )
3641
3642 (define_insn "*shiftsi3_compare0_scratch"
3643   [(set (reg:CC_NOOV CC_REGNUM)
3644         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3645                           [(match_operand:SI 1 "s_register_operand" "r")
3646                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
3647                          (const_int 0)))
3648    (clobber (match_scratch:SI 0 "=r"))]
3649   "TARGET_32BIT"
3650   "* return arm_output_shift(operands, 1);"
3651   [(set_attr "conds" "set")
3652    (set_attr "shift" "1")]
3653 )
3654
3655 (define_insn "*not_shiftsi"
3656   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3657         (not:SI (match_operator:SI 3 "shift_operator"
3658                  [(match_operand:SI 1 "s_register_operand" "r,r")
3659                   (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
3660   "TARGET_32BIT"
3661   "mvn%?\\t%0, %1%S3"
3662   [(set_attr "predicable" "yes")
3663    (set_attr "shift" "1")
3664    (set_attr "insn" "mvn")
3665    (set_attr "arch" "32,a")
3666    (set_attr "type" "alu_shift,alu_shift_reg")])
3667
3668 (define_insn "*not_shiftsi_compare0"
3669   [(set (reg:CC_NOOV CC_REGNUM)
3670         (compare:CC_NOOV
3671          (not:SI (match_operator:SI 3 "shift_operator"
3672                   [(match_operand:SI 1 "s_register_operand" "r,r")
3673                    (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3674          (const_int 0)))
3675    (set (match_operand:SI 0 "s_register_operand" "=r,r")
3676         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
3677   "TARGET_32BIT"
3678   "mvn%.\\t%0, %1%S3"
3679   [(set_attr "conds" "set")
3680    (set_attr "shift" "1")
3681    (set_attr "insn" "mvn")
3682    (set_attr "arch" "32,a")
3683    (set_attr "type" "alu_shift,alu_shift_reg")])
3684
3685 (define_insn "*not_shiftsi_compare0_scratch"
3686   [(set (reg:CC_NOOV CC_REGNUM)
3687         (compare:CC_NOOV
3688          (not:SI (match_operator:SI 3 "shift_operator"
3689                   [(match_operand:SI 1 "s_register_operand" "r,r")
3690                    (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3691          (const_int 0)))
3692    (clobber (match_scratch:SI 0 "=r,r"))]
3693   "TARGET_32BIT"
3694   "mvn%.\\t%0, %1%S3"
3695   [(set_attr "conds" "set")
3696    (set_attr "shift" "1")
3697    (set_attr "insn" "mvn")
3698    (set_attr "arch" "32,a")
3699    (set_attr "type" "alu_shift,alu_shift_reg")])
3700
3701 ;; We don't really have extzv, but defining this using shifts helps
3702 ;; to reduce register pressure later on.
3703
3704 (define_expand "extzv"
3705   [(set (match_dup 4)
3706         (ashift:SI (match_operand:SI   1 "register_operand" "")
3707                    (match_operand:SI   2 "const_int_operand" "")))
3708    (set (match_operand:SI              0 "register_operand" "")
3709         (lshiftrt:SI (match_dup 4)
3710                      (match_operand:SI 3 "const_int_operand" "")))]
3711   "TARGET_THUMB1 || arm_arch_thumb2"
3712   "
3713   {
3714     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3715     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3716     
3717     if (arm_arch_thumb2)
3718       {
3719         emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
3720                                  operands[3]));
3721         DONE;
3722       }
3723
3724     operands[3] = GEN_INT (rshift);
3725     
3726     if (lshift == 0)
3727       {
3728         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3729         DONE;
3730       }
3731       
3732     operands[2] = GEN_INT (lshift);
3733     operands[4] = gen_reg_rtx (SImode);
3734   }"
3735 )
3736
3737 (define_insn "extv"
3738   [(set (match_operand:SI 0 "s_register_operand" "=r")
3739         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3740                          (match_operand:SI 2 "const_int_operand" "M")
3741                          (match_operand:SI 3 "const_int_operand" "M")))]
3742   "arm_arch_thumb2"
3743   "sbfx%?\t%0, %1, %3, %2"
3744   [(set_attr "length" "4")
3745    (set_attr "predicable" "yes")]
3746 )
3747
3748 (define_insn "extzv_t2"
3749   [(set (match_operand:SI 0 "s_register_operand" "=r")
3750         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3751                          (match_operand:SI 2 "const_int_operand" "M")
3752                          (match_operand:SI 3 "const_int_operand" "M")))]
3753   "arm_arch_thumb2"
3754   "ubfx%?\t%0, %1, %3, %2"
3755   [(set_attr "length" "4")
3756    (set_attr "predicable" "yes")]
3757 )
3758
3759
3760 ;; Division instructions
3761 (define_insn "divsi3"
3762   [(set (match_operand:SI         0 "s_register_operand" "=r")
3763         (div:SI (match_operand:SI 1 "s_register_operand"  "r")
3764                 (match_operand:SI 2 "s_register_operand"  "r")))]
3765   "TARGET_IDIV"
3766   "sdiv%?\t%0, %1, %2"
3767   [(set_attr "predicable" "yes")
3768    (set_attr "insn" "sdiv")]
3769 )
3770
3771 (define_insn "udivsi3"
3772   [(set (match_operand:SI          0 "s_register_operand" "=r")
3773         (udiv:SI (match_operand:SI 1 "s_register_operand"  "r")
3774                  (match_operand:SI 2 "s_register_operand"  "r")))]
3775   "TARGET_IDIV"
3776   "udiv%?\t%0, %1, %2"
3777   [(set_attr "predicable" "yes")
3778    (set_attr "insn" "udiv")]
3779 )
3780
3781 \f
3782 ;; Unary arithmetic insns
3783
3784 (define_expand "negdi2"
3785  [(parallel
3786    [(set (match_operand:DI 0 "s_register_operand" "")
3787          (neg:DI (match_operand:DI 1 "s_register_operand" "")))
3788     (clobber (reg:CC CC_REGNUM))])]
3789   "TARGET_EITHER"
3790   ""
3791 )
3792
3793 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
3794 ;; The first alternative allows the common case of a *full* overlap.
3795 (define_insn "*arm_negdi2"
3796   [(set (match_operand:DI         0 "s_register_operand" "=r,&r")
3797         (neg:DI (match_operand:DI 1 "s_register_operand"  "0,r")))
3798    (clobber (reg:CC CC_REGNUM))]
3799   "TARGET_ARM"
3800   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
3801   [(set_attr "conds" "clob")
3802    (set_attr "length" "8")]
3803 )
3804
3805 (define_insn "*thumb1_negdi2"
3806   [(set (match_operand:DI 0 "register_operand" "=&l")
3807         (neg:DI (match_operand:DI 1 "register_operand" "l")))
3808    (clobber (reg:CC CC_REGNUM))]
3809   "TARGET_THUMB1"
3810   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
3811   [(set_attr "length" "6")]
3812 )
3813
3814 (define_expand "negsi2"
3815   [(set (match_operand:SI         0 "s_register_operand" "")
3816         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
3817   "TARGET_EITHER"
3818   ""
3819 )
3820
3821 (define_insn "*arm_negsi2"
3822   [(set (match_operand:SI         0 "s_register_operand" "=r")
3823         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
3824   "TARGET_32BIT"
3825   "rsb%?\\t%0, %1, #0"
3826   [(set_attr "predicable" "yes")]
3827 )
3828
3829 (define_insn "*thumb1_negsi2"
3830   [(set (match_operand:SI         0 "register_operand" "=l")
3831         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
3832   "TARGET_THUMB1"
3833   "neg\\t%0, %1"
3834   [(set_attr "length" "2")]
3835 )
3836
3837 (define_expand "negsf2"
3838   [(set (match_operand:SF         0 "s_register_operand" "")
3839         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
3840   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3841   ""
3842 )
3843
3844 (define_expand "negdf2"
3845   [(set (match_operand:DF         0 "s_register_operand" "")
3846         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
3847   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
3848   "")
3849
3850 ;; abssi2 doesn't really clobber the condition codes if a different register
3851 ;; is being set.  To keep things simple, assume during rtl manipulations that
3852 ;; it does, but tell the final scan operator the truth.  Similarly for
3853 ;; (neg (abs...))
3854
3855 (define_expand "abssi2"
3856   [(parallel
3857     [(set (match_operand:SI         0 "s_register_operand" "")
3858           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3859      (clobber (match_dup 2))])]
3860   "TARGET_EITHER"
3861   "
3862   if (TARGET_THUMB1)
3863     operands[2] = gen_rtx_SCRATCH (SImode);
3864   else
3865     operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
3866 ")
3867
3868 (define_insn "*arm_abssi2"
3869   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3870         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3871    (clobber (reg:CC CC_REGNUM))]
3872   "TARGET_ARM"
3873   "@
3874    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3875    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3876   [(set_attr "conds" "clob,*")
3877    (set_attr "shift" "1")
3878    ;; predicable can't be set based on the variant, so left as no
3879    (set_attr "length" "8")]
3880 )
3881
3882 (define_insn_and_split "*thumb1_abssi2"
3883   [(set (match_operand:SI 0 "s_register_operand" "=l")
3884         (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
3885    (clobber (match_scratch:SI 2 "=&l"))]
3886   "TARGET_THUMB1"
3887   "#"
3888   "TARGET_THUMB1 && reload_completed"
3889   [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3890    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
3891    (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3892   ""
3893   [(set_attr "length" "6")]
3894 )
3895
3896 (define_insn "*arm_neg_abssi2"
3897   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3898         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3899    (clobber (reg:CC CC_REGNUM))]
3900   "TARGET_ARM"
3901   "@
3902    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3903    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3904   [(set_attr "conds" "clob,*")
3905    (set_attr "shift" "1")
3906    ;; predicable can't be set based on the variant, so left as no
3907    (set_attr "length" "8")]
3908 )
3909
3910 (define_insn_and_split "*thumb1_neg_abssi2"
3911   [(set (match_operand:SI 0 "s_register_operand" "=l")
3912         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
3913    (clobber (match_scratch:SI 2 "=&l"))]
3914   "TARGET_THUMB1"
3915   "#"
3916   "TARGET_THUMB1 && reload_completed"
3917   [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3918    (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
3919    (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3920   ""
3921   [(set_attr "length" "6")]
3922 )
3923
3924 (define_expand "abssf2"
3925   [(set (match_operand:SF         0 "s_register_operand" "")
3926         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3927   "TARGET_32BIT && TARGET_HARD_FLOAT"
3928   "")
3929
3930 (define_expand "absdf2"
3931   [(set (match_operand:DF         0 "s_register_operand" "")
3932         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3933   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
3934   "")
3935
3936 (define_expand "sqrtsf2"
3937   [(set (match_operand:SF 0 "s_register_operand" "")
3938         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3939   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3940   "")
3941
3942 (define_expand "sqrtdf2"
3943   [(set (match_operand:DF 0 "s_register_operand" "")
3944         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3945   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
3946   "")
3947
3948 (define_insn_and_split "one_cmpldi2"
3949   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3950         (not:DI (match_operand:DI 1 "s_register_operand" "0,r")))]
3951   "TARGET_32BIT"
3952   "#"
3953   "TARGET_32BIT && reload_completed"
3954   [(set (match_dup 0) (not:SI (match_dup 1)))
3955    (set (match_dup 2) (not:SI (match_dup 3)))]
3956   "
3957   {
3958     operands[2] = gen_highpart (SImode, operands[0]);
3959     operands[0] = gen_lowpart (SImode, operands[0]);
3960     operands[3] = gen_highpart (SImode, operands[1]);
3961     operands[1] = gen_lowpart (SImode, operands[1]);
3962   }"
3963   [(set_attr "length" "8")
3964    (set_attr "predicable" "yes")]
3965 )
3966
3967 (define_expand "one_cmplsi2"
3968   [(set (match_operand:SI         0 "s_register_operand" "")
3969         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3970   "TARGET_EITHER"
3971   ""
3972 )
3973
3974 (define_insn "*arm_one_cmplsi2"
3975   [(set (match_operand:SI         0 "s_register_operand" "=r")
3976         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3977   "TARGET_32BIT"
3978   "mvn%?\\t%0, %1"
3979   [(set_attr "predicable" "yes")
3980    (set_attr "insn" "mvn")]
3981 )
3982
3983 (define_insn "*thumb1_one_cmplsi2"
3984   [(set (match_operand:SI         0 "register_operand" "=l")
3985         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3986   "TARGET_THUMB1"
3987   "mvn\\t%0, %1"
3988   [(set_attr "length" "2")
3989    (set_attr "insn" "mvn")]
3990 )
3991
3992 (define_insn "*notsi_compare0"
3993   [(set (reg:CC_NOOV CC_REGNUM)
3994         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3995                          (const_int 0)))
3996    (set (match_operand:SI 0 "s_register_operand" "=r")
3997         (not:SI (match_dup 1)))]
3998   "TARGET_32BIT"
3999   "mvn%.\\t%0, %1"
4000   [(set_attr "conds" "set")
4001    (set_attr "insn" "mvn")]
4002 )
4003
4004 (define_insn "*notsi_compare0_scratch"
4005   [(set (reg:CC_NOOV CC_REGNUM)
4006         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4007                          (const_int 0)))
4008    (clobber (match_scratch:SI 0 "=r"))]
4009   "TARGET_32BIT"
4010   "mvn%.\\t%0, %1"
4011   [(set_attr "conds" "set")
4012    (set_attr "insn" "mvn")]
4013 )
4014 \f
4015 ;; Fixed <--> Floating conversion insns
4016
4017 (define_expand "floatsihf2"
4018   [(set (match_operand:HF           0 "general_operand" "")
4019         (float:HF (match_operand:SI 1 "general_operand" "")))]
4020   "TARGET_EITHER"
4021   "
4022   {
4023     rtx op1 = gen_reg_rtx (SFmode);
4024     expand_float (op1, operands[1], 0);
4025     op1 = convert_to_mode (HFmode, op1, 0);
4026     emit_move_insn (operands[0], op1);
4027     DONE;
4028   }"
4029 )
4030
4031 (define_expand "floatdihf2"
4032   [(set (match_operand:HF           0 "general_operand" "")
4033         (float:HF (match_operand:DI 1 "general_operand" "")))]
4034   "TARGET_EITHER"
4035   "
4036   {
4037     rtx op1 = gen_reg_rtx (SFmode);
4038     expand_float (op1, operands[1], 0);
4039     op1 = convert_to_mode (HFmode, op1, 0);
4040     emit_move_insn (operands[0], op1);
4041     DONE;
4042   }"
4043 )
4044
4045 (define_expand "floatsisf2"
4046   [(set (match_operand:SF           0 "s_register_operand" "")
4047         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
4048   "TARGET_32BIT && TARGET_HARD_FLOAT"
4049   "
4050   if (TARGET_MAVERICK)
4051     {
4052       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
4053       DONE;
4054     }
4055 ")
4056
4057 (define_expand "floatsidf2"
4058   [(set (match_operand:DF           0 "s_register_operand" "")
4059         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
4060   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
4061   "
4062   if (TARGET_MAVERICK)
4063     {
4064       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
4065       DONE;
4066     }
4067 ")
4068
4069 (define_expand "fix_trunchfsi2"
4070   [(set (match_operand:SI         0 "general_operand" "")
4071         (fix:SI (fix:HF (match_operand:HF 1 "general_operand"  ""))))]
4072   "TARGET_EITHER"
4073   "
4074   {
4075     rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4076     expand_fix (operands[0], op1, 0);
4077     DONE;
4078   }"
4079 )
4080
4081 (define_expand "fix_trunchfdi2"
4082   [(set (match_operand:DI         0 "general_operand" "")
4083         (fix:DI (fix:HF (match_operand:HF 1 "general_operand"  ""))))]
4084   "TARGET_EITHER"
4085   "
4086   {
4087     rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4088     expand_fix (operands[0], op1, 0);
4089     DONE;
4090   }"
4091 )
4092
4093 (define_expand "fix_truncsfsi2"
4094   [(set (match_operand:SI         0 "s_register_operand" "")
4095         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
4096   "TARGET_32BIT && TARGET_HARD_FLOAT"
4097   "
4098   if (TARGET_MAVERICK)
4099     {
4100       if (!cirrus_fp_register (operands[0], SImode))
4101         operands[0] = force_reg (SImode, operands[0]);
4102       if (!cirrus_fp_register (operands[1], SFmode))
4103         operands[1] = force_reg (SFmode, operands[0]);
4104       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
4105       DONE;
4106     }
4107 ")
4108
4109 (define_expand "fix_truncdfsi2"
4110   [(set (match_operand:SI         0 "s_register_operand" "")
4111         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
4112   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
4113   "
4114   if (TARGET_MAVERICK)
4115     {
4116       if (!cirrus_fp_register (operands[1], DFmode))
4117         operands[1] = force_reg (DFmode, operands[0]);
4118       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
4119       DONE;
4120     }
4121 ")
4122
4123 ;; Truncation insns
4124
4125 (define_expand "truncdfsf2"
4126   [(set (match_operand:SF  0 "s_register_operand" "")
4127         (float_truncate:SF
4128          (match_operand:DF 1 "s_register_operand" "")))]
4129   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
4130   ""
4131 )
4132
4133 /* DFmode -> HFmode conversions have to go through SFmode.  */
4134 (define_expand "truncdfhf2"
4135   [(set (match_operand:HF  0 "general_operand" "")
4136         (float_truncate:HF
4137          (match_operand:DF 1 "general_operand" "")))]
4138   "TARGET_EITHER"
4139   "
4140   {
4141     rtx op1;
4142     op1 = convert_to_mode (SFmode, operands[1], 0);
4143     op1 = convert_to_mode (HFmode, op1, 0);
4144     emit_move_insn (operands[0], op1);
4145     DONE;
4146   }"
4147 )
4148 \f
4149 ;; Zero and sign extension instructions.
4150
4151 (define_insn "zero_extend<mode>di2"
4152   [(set (match_operand:DI 0 "s_register_operand" "=r")
4153         (zero_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
4154                                             "<qhs_extenddi_cstr>")))]
4155   "TARGET_32BIT <qhs_zextenddi_cond>"
4156   "#"
4157   [(set_attr "length" "8")
4158    (set_attr "ce_count" "2")
4159    (set_attr "predicable" "yes")]
4160 )
4161
4162 (define_insn "extend<mode>di2"
4163   [(set (match_operand:DI 0 "s_register_operand" "=r")
4164         (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
4165                                             "<qhs_extenddi_cstr>")))]
4166   "TARGET_32BIT <qhs_sextenddi_cond>"
4167   "#"
4168   [(set_attr "length" "8")
4169    (set_attr "ce_count" "2")
4170    (set_attr "shift" "1")
4171    (set_attr "predicable" "yes")]
4172 )
4173
4174 ;; Splits for all extensions to DImode
4175 (define_split
4176   [(set (match_operand:DI 0 "s_register_operand" "")
4177         (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
4178   "TARGET_32BIT"
4179   [(set (match_dup 0) (match_dup 1))]
4180 {
4181   rtx lo_part = gen_lowpart (SImode, operands[0]);
4182   enum machine_mode src_mode = GET_MODE (operands[1]);
4183
4184   if (REG_P (operands[0])
4185       && !reg_overlap_mentioned_p (operands[0], operands[1]))
4186     emit_clobber (operands[0]);
4187   if (!REG_P (lo_part) || src_mode != SImode
4188       || !rtx_equal_p (lo_part, operands[1]))
4189     {
4190       if (src_mode == SImode)
4191         emit_move_insn (lo_part, operands[1]);
4192       else
4193         emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4194                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
4195       operands[1] = lo_part;
4196     }
4197   operands[0] = gen_highpart (SImode, operands[0]);
4198   operands[1] = const0_rtx;
4199 })
4200
4201 (define_split
4202   [(set (match_operand:DI 0 "s_register_operand" "")
4203         (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
4204   "TARGET_32BIT"
4205   [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
4206 {
4207   rtx lo_part = gen_lowpart (SImode, operands[0]);
4208   enum machine_mode src_mode = GET_MODE (operands[1]);
4209
4210   if (REG_P (operands[0])
4211       && !reg_overlap_mentioned_p (operands[0], operands[1]))
4212     emit_clobber (operands[0]);
4213
4214   if (!REG_P (lo_part) || src_mode != SImode
4215       || !rtx_equal_p (lo_part, operands[1]))
4216     {
4217       if (src_mode == SImode)
4218         emit_move_insn (lo_part, operands[1]);
4219       else
4220         emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4221                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4222       operands[1] = lo_part;
4223     }
4224   operands[0] = gen_highpart (SImode, operands[0]);
4225 })
4226
4227 (define_expand "zero_extendhisi2"
4228   [(set (match_operand:SI 0 "s_register_operand" "")
4229         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
4230   "TARGET_EITHER"
4231 {
4232   if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
4233     {
4234       emit_insn (gen_movhi_bytes (operands[0], operands[1]));
4235       DONE;
4236     }
4237   if (!arm_arch6 && !MEM_P (operands[1]))
4238     {
4239       rtx t = gen_lowpart (SImode, operands[1]);
4240       rtx tmp = gen_reg_rtx (SImode);
4241       emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4242       emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
4243       DONE;
4244     }
4245 })
4246
4247 (define_split
4248   [(set (match_operand:SI 0 "s_register_operand" "")
4249         (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
4250   "!TARGET_THUMB2 && !arm_arch6"
4251   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4252    (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4253 {
4254   operands[2] = gen_lowpart (SImode, operands[1]);
4255 })
4256
4257 (define_insn "*thumb1_zero_extendhisi2"
4258   [(set (match_operand:SI 0 "register_operand" "=l,l")
4259         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
4260   "TARGET_THUMB1"
4261 {
4262   rtx mem;
4263
4264   if (which_alternative == 0 && arm_arch6)
4265     return "uxth\t%0, %1";
4266   if (which_alternative == 0)
4267     return "#";
4268
4269   mem = XEXP (operands[1], 0);
4270
4271   if (GET_CODE (mem) == CONST)
4272     mem = XEXP (mem, 0);
4273     
4274   if (GET_CODE (mem) == PLUS)
4275     {
4276       rtx a = XEXP (mem, 0);
4277
4278       /* This can happen due to bugs in reload.  */
4279       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
4280         {
4281           rtx ops[2];
4282           ops[0] = operands[0];
4283           ops[1] = a;
4284       
4285           output_asm_insn ("mov\t%0, %1", ops);
4286
4287           XEXP (mem, 0) = operands[0];
4288        }
4289     }
4290     
4291   return "ldrh\t%0, %1";
4292 }
4293   [(set_attr_alternative "length"
4294                          [(if_then_else (eq_attr "is_arch6" "yes")
4295                                        (const_int 2) (const_int 4))
4296                          (const_int 4)])
4297    (set_attr "type" "alu_shift,load_byte")]
4298 )
4299
4300 (define_insn "*arm_zero_extendhisi2"
4301   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4302         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4303   "TARGET_ARM && arm_arch4 && !arm_arch6"
4304   "@
4305    #
4306    ldr%(h%)\\t%0, %1"
4307   [(set_attr "type" "alu_shift,load_byte")
4308    (set_attr "predicable" "yes")]
4309 )
4310
4311 (define_insn "*arm_zero_extendhisi2_v6"
4312   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4313         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4314   "TARGET_ARM && arm_arch6"
4315   "@
4316    uxth%?\\t%0, %1
4317    ldr%(h%)\\t%0, %1"
4318   [(set_attr "type" "alu_shift,load_byte")
4319    (set_attr "predicable" "yes")]
4320 )
4321
4322 (define_insn "*arm_zero_extendhisi2addsi"
4323   [(set (match_operand:SI 0 "s_register_operand" "=r")
4324         (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4325                  (match_operand:SI 2 "s_register_operand" "r")))]
4326   "TARGET_INT_SIMD"
4327   "uxtah%?\\t%0, %2, %1"
4328   [(set_attr "type" "alu_shift")
4329    (set_attr "predicable" "yes")]
4330 )
4331
4332 (define_expand "zero_extendqisi2"
4333   [(set (match_operand:SI 0 "s_register_operand" "")
4334         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
4335   "TARGET_EITHER"
4336 {
4337   if (TARGET_ARM && !arm_arch6 && GET_CODE (operands[1]) != MEM)
4338     {
4339       emit_insn (gen_andsi3 (operands[0],
4340                              gen_lowpart (SImode, operands[1]),
4341                                           GEN_INT (255)));
4342       DONE;
4343     }
4344   if (!arm_arch6 && !MEM_P (operands[1]))
4345     {
4346       rtx t = gen_lowpart (SImode, operands[1]);
4347       rtx tmp = gen_reg_rtx (SImode);
4348       emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4349       emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
4350       DONE;
4351     }
4352 })
4353
4354 (define_split
4355   [(set (match_operand:SI 0 "s_register_operand" "")
4356         (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
4357   "!arm_arch6"
4358   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4359    (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
4360 {
4361   operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4362   if (TARGET_ARM)
4363     {
4364       emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
4365       DONE;
4366     }
4367 })
4368
4369 (define_insn "*thumb1_zero_extendqisi2"
4370   [(set (match_operand:SI 0 "register_operand" "=l,l")
4371         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
4372   "TARGET_THUMB1 && !arm_arch6"
4373   "@
4374    #
4375    ldrb\\t%0, %1"
4376   [(set_attr "length" "4,2")
4377    (set_attr "type" "alu_shift,load_byte")
4378    (set_attr "pool_range" "*,32")]
4379 )
4380
4381 (define_insn "*thumb1_zero_extendqisi2_v6"
4382   [(set (match_operand:SI 0 "register_operand" "=l,l")
4383         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
4384   "TARGET_THUMB1 && arm_arch6"
4385   "@
4386    uxtb\\t%0, %1
4387    ldrb\\t%0, %1"
4388   [(set_attr "length" "2")
4389    (set_attr "type" "alu_shift,load_byte")]
4390 )
4391
4392 (define_insn "*arm_zero_extendqisi2"
4393   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4394         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4395   "TARGET_ARM && !arm_arch6"
4396   "@
4397    #
4398    ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
4399   [(set_attr "length" "8,4")
4400    (set_attr "type" "alu_shift,load_byte")
4401    (set_attr "predicable" "yes")]
4402 )
4403
4404 (define_insn "*arm_zero_extendqisi2_v6"
4405   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4406         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4407   "TARGET_ARM && arm_arch6"
4408   "@
4409    uxtb%(%)\\t%0, %1
4410    ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
4411   [(set_attr "type" "alu_shift,load_byte")
4412    (set_attr "predicable" "yes")]
4413 )
4414
4415 (define_insn "*arm_zero_extendqisi2addsi"
4416   [(set (match_operand:SI 0 "s_register_operand" "=r")
4417         (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4418                  (match_operand:SI 2 "s_register_operand" "r")))]
4419   "TARGET_INT_SIMD"
4420   "uxtab%?\\t%0, %2, %1"
4421   [(set_attr "predicable" "yes")
4422    (set_attr "insn" "xtab")
4423    (set_attr "type" "alu_shift")]
4424 )
4425
4426 (define_split
4427   [(set (match_operand:SI 0 "s_register_operand" "")
4428         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
4429    (clobber (match_operand:SI 2 "s_register_operand" ""))]
4430   "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
4431   [(set (match_dup 2) (match_dup 1))
4432    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4433   ""
4434 )
4435
4436 (define_split
4437   [(set (match_operand:SI 0 "s_register_operand" "")
4438         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
4439    (clobber (match_operand:SI 2 "s_register_operand" ""))]
4440   "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
4441   [(set (match_dup 2) (match_dup 1))
4442    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4443   ""
4444 )
4445
4446
4447 (define_split
4448   [(set (match_operand:SI 0 "s_register_operand" "")
4449         (ior_xor:SI (and:SI (ashift:SI
4450                              (match_operand:SI 1 "s_register_operand" "")
4451                              (match_operand:SI 2 "const_int_operand" ""))
4452                             (match_operand:SI 3 "const_int_operand" ""))
4453                     (zero_extend:SI
4454                      (match_operator 5 "subreg_lowpart_operator"
4455                       [(match_operand:SI 4 "s_register_operand" "")]))))]
4456   "TARGET_32BIT
4457    && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
4458        == (GET_MODE_MASK (GET_MODE (operands[5]))
4459            & (GET_MODE_MASK (GET_MODE (operands[5]))
4460               << (INTVAL (operands[2])))))"
4461   [(set (match_dup 0) (ior_xor:SI (ashift:SI (match_dup 1) (match_dup 2))
4462                                   (match_dup 4)))
4463    (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
4464   "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
4465 )
4466
4467 (define_insn "*compareqi_eq0"
4468   [(set (reg:CC_Z CC_REGNUM)
4469         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
4470                          (const_int 0)))]
4471   "TARGET_32BIT"
4472   "tst\\t%0, #255"
4473   [(set_attr "conds" "set")]
4474 )
4475
4476 (define_expand "extendhisi2"
4477   [(set (match_operand:SI 0 "s_register_operand" "")
4478         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
4479   "TARGET_EITHER"
4480 {
4481   if (TARGET_THUMB1)
4482     {
4483       emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
4484       DONE;
4485     }
4486   if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
4487     {
4488       emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
4489       DONE;
4490     }
4491
4492   if (!arm_arch6 && !MEM_P (operands[1]))
4493     {
4494       rtx t = gen_lowpart (SImode, operands[1]);
4495       rtx tmp = gen_reg_rtx (SImode);
4496       emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4497       emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
4498       DONE;
4499     }
4500 })
4501
4502 (define_split
4503   [(parallel
4504     [(set (match_operand:SI 0 "register_operand" "")
4505           (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
4506      (clobber (match_scratch:SI 2 ""))])]
4507   "!arm_arch6"
4508   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4509    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4510 {
4511   operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4512 })
4513
4514 ;; We used to have an early-clobber on the scratch register here.
4515 ;; However, there's a bug somewhere in reload which means that this
4516 ;; can be partially ignored during spill allocation if the memory
4517 ;; address also needs reloading; this causes us to die later on when
4518 ;; we try to verify the operands.  Fortunately, we don't really need
4519 ;; the early-clobber: we can always use operand 0 if operand 2
4520 ;; overlaps the address.
4521 (define_insn "thumb1_extendhisi2"
4522   [(set (match_operand:SI 0 "register_operand" "=l,l")
4523         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
4524    (clobber (match_scratch:SI 2 "=X,l"))]
4525   "TARGET_THUMB1"
4526   "*
4527   {
4528     rtx ops[4];
4529     rtx mem;
4530
4531     if (which_alternative == 0 && !arm_arch6)
4532       return \"#\";
4533     if (which_alternative == 0)
4534       return \"sxth\\t%0, %1\";
4535
4536     mem = XEXP (operands[1], 0);
4537
4538     /* This code used to try to use 'V', and fix the address only if it was
4539        offsettable, but this fails for e.g. REG+48 because 48 is outside the
4540        range of QImode offsets, and offsettable_address_p does a QImode
4541        address check.  */
4542        
4543     if (GET_CODE (mem) == CONST)
4544       mem = XEXP (mem, 0);
4545     
4546     if (GET_CODE (mem) == LABEL_REF)
4547       return \"ldr\\t%0, %1\";
4548     
4549     if (GET_CODE (mem) == PLUS)
4550       {
4551         rtx a = XEXP (mem, 0);
4552         rtx b = XEXP (mem, 1);
4553
4554         if (GET_CODE (a) == LABEL_REF
4555             && GET_CODE (b) == CONST_INT)
4556           return \"ldr\\t%0, %1\";
4557
4558         if (GET_CODE (b) == REG)
4559           return \"ldrsh\\t%0, %1\";
4560           
4561         ops[1] = a;
4562         ops[2] = b;
4563       }
4564     else
4565       {
4566         ops[1] = mem;
4567         ops[2] = const0_rtx;
4568       }
4569       
4570     gcc_assert (GET_CODE (ops[1]) == REG);
4571
4572     ops[0] = operands[0];
4573     if (reg_mentioned_p (operands[2], ops[1]))
4574       ops[3] = ops[0];
4575     else
4576       ops[3] = operands[2];
4577     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4578     return \"\";
4579   }"
4580   [(set_attr_alternative "length"
4581                          [(if_then_else (eq_attr "is_arch6" "yes")
4582                                         (const_int 2) (const_int 4))
4583                           (const_int 4)])
4584    (set_attr "type" "alu_shift,load_byte")
4585    (set_attr "pool_range" "*,1020")]
4586 )
4587
4588 ;; This pattern will only be used when ldsh is not available
4589 (define_expand "extendhisi2_mem"
4590   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4591    (set (match_dup 3)
4592         (zero_extend:SI (match_dup 7)))
4593    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4594    (set (match_operand:SI 0 "" "")
4595         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
4596   "TARGET_ARM"
4597   "
4598   {
4599     rtx mem1, mem2;
4600     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4601
4602     mem1 = change_address (operands[1], QImode, addr);
4603     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
4604     operands[0] = gen_lowpart (SImode, operands[0]);
4605     operands[1] = mem1;
4606     operands[2] = gen_reg_rtx (SImode);
4607     operands[3] = gen_reg_rtx (SImode);
4608     operands[6] = gen_reg_rtx (SImode);
4609     operands[7] = mem2;
4610
4611     if (BYTES_BIG_ENDIAN)
4612       {
4613         operands[4] = operands[2];
4614         operands[5] = operands[3];
4615       }
4616     else
4617       {
4618         operands[4] = operands[3];
4619         operands[5] = operands[2];
4620       }
4621   }"
4622 )
4623
4624 (define_split
4625   [(set (match_operand:SI 0 "register_operand" "")
4626         (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
4627   "!arm_arch6"
4628   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4629    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4630 {
4631   operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4632 })
4633
4634 (define_insn "*arm_extendhisi2"
4635   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4636         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4637   "TARGET_ARM && arm_arch4 && !arm_arch6"
4638   "@
4639    #
4640    ldr%(sh%)\\t%0, %1"
4641   [(set_attr "length" "8,4")
4642    (set_attr "type" "alu_shift,load_byte")
4643    (set_attr "predicable" "yes")
4644    (set_attr "pool_range" "*,256")
4645    (set_attr "neg_pool_range" "*,244")]
4646 )
4647
4648 ;; ??? Check Thumb-2 pool range
4649 (define_insn "*arm_extendhisi2_v6"
4650   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4651         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4652   "TARGET_32BIT && arm_arch6"
4653   "@
4654    sxth%?\\t%0, %1
4655    ldr%(sh%)\\t%0, %1"
4656   [(set_attr "type" "alu_shift,load_byte")
4657    (set_attr "predicable" "yes")
4658    (set_attr "pool_range" "*,256")
4659    (set_attr "neg_pool_range" "*,244")]
4660 )
4661
4662 (define_insn "*arm_extendhisi2addsi"
4663   [(set (match_operand:SI 0 "s_register_operand" "=r")
4664         (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4665                  (match_operand:SI 2 "s_register_operand" "r")))]
4666   "TARGET_INT_SIMD"
4667   "sxtah%?\\t%0, %2, %1"
4668 )
4669
4670 (define_expand "extendqihi2"
4671   [(set (match_dup 2)
4672         (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
4673                    (const_int 24)))
4674    (set (match_operand:HI 0 "s_register_operand" "")
4675         (ashiftrt:SI (match_dup 2)
4676                      (const_int 24)))]
4677   "TARGET_ARM"
4678   "
4679   {
4680     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
4681       {
4682         emit_insn (gen_rtx_SET (VOIDmode,
4683                                 operands[0],
4684                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
4685         DONE;
4686       }
4687     if (!s_register_operand (operands[1], QImode))
4688       operands[1] = copy_to_mode_reg (QImode, operands[1]);
4689     operands[0] = gen_lowpart (SImode, operands[0]);
4690     operands[1] = gen_lowpart (SImode, operands[1]);
4691     operands[2] = gen_reg_rtx (SImode);
4692   }"
4693 )
4694
4695 (define_insn "*arm_extendqihi_insn"
4696   [(set (match_operand:HI 0 "s_register_operand" "=r")
4697         (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
4698   "TARGET_ARM && arm_arch4"
4699   "ldr%(sb%)\\t%0, %1"
4700   [(set_attr "type" "load_byte")
4701    (set_attr "predicable" "yes")
4702    (set_attr "pool_range" "256")
4703    (set_attr "neg_pool_range" "244")]
4704 )
4705
4706 (define_expand "extendqisi2"
4707   [(set (match_operand:SI 0 "s_register_operand" "")
4708         (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
4709   "TARGET_EITHER"
4710 {
4711   if (!arm_arch4 && MEM_P (operands[1]))
4712     operands[1] = copy_to_mode_reg (QImode, operands[1]);
4713
4714   if (!arm_arch6 && !MEM_P (operands[1]))
4715     {
4716       rtx t = gen_lowpart (SImode, operands[1]);
4717       rtx tmp = gen_reg_rtx (SImode);
4718       emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4719       emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
4720       DONE;
4721     }
4722 })
4723
4724 (define_split
4725   [(set (match_operand:SI 0 "register_operand" "")
4726         (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
4727   "!arm_arch6"
4728   [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4729    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
4730 {
4731   operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4732 })
4733
4734 (define_insn "*arm_extendqisi"
4735   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4736         (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
4737   "TARGET_ARM && arm_arch4 && !arm_arch6"
4738   "@
4739    #
4740    ldr%(sb%)\\t%0, %1"
4741   [(set_attr "length" "8,4")
4742    (set_attr "type" "alu_shift,load_byte")
4743    (set_attr "predicable" "yes")
4744    (set_attr "pool_range" "*,256")
4745    (set_attr "neg_pool_range" "*,244")]
4746 )
4747
4748 (define_insn "*arm_extendqisi_v6"
4749   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4750         (sign_extend:SI
4751          (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
4752   "TARGET_ARM && arm_arch6"
4753   "@
4754    sxtb%?\\t%0, %1
4755    ldr%(sb%)\\t%0, %1"
4756   [(set_attr "type" "alu_shift,load_byte")
4757    (set_attr "predicable" "yes")
4758    (set_attr "pool_range" "*,256")
4759    (set_attr "neg_pool_range" "*,244")]
4760 )
4761
4762 (define_insn "*arm_extendqisi2addsi"
4763   [(set (match_operand:SI 0 "s_register_operand" "=r")
4764         (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4765                  (match_operand:SI 2 "s_register_operand" "r")))]
4766   "TARGET_INT_SIMD"
4767   "sxtab%?\\t%0, %2, %1"
4768   [(set_attr "type" "alu_shift")
4769    (set_attr "insn" "xtab")
4770    (set_attr "predicable" "yes")]
4771 )
4772
4773 (define_split
4774   [(set (match_operand:SI 0 "register_operand" "")
4775         (sign_extend:SI (match_operand:QI 1 "memory_operand" "")))]
4776   "TARGET_THUMB1 && reload_completed"
4777   [(set (match_dup 0) (match_dup 2))
4778    (set (match_dup 0) (sign_extend:SI (match_dup 3)))]
4779 {
4780   rtx addr = XEXP (operands[1], 0);
4781
4782   if (GET_CODE (addr) == CONST)
4783     addr = XEXP (addr, 0);
4784
4785   if (GET_CODE (addr) == PLUS
4786       && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
4787     /* No split necessary.  */
4788     FAIL;
4789
4790   if (GET_CODE (addr) == PLUS
4791       && !REG_P (XEXP (addr, 0)) && !REG_P (XEXP (addr, 1)))
4792     FAIL;
4793
4794   if (reg_overlap_mentioned_p (operands[0], addr))
4795     {
4796       rtx t = gen_lowpart (QImode, operands[0]);
4797       emit_move_insn (t, operands[1]);
4798       emit_insn (gen_thumb1_extendqisi2 (operands[0], t));
4799       DONE;
4800     }
4801
4802   if (REG_P (addr))
4803     {
4804       addr = gen_rtx_PLUS (Pmode, addr, operands[0]);
4805       operands[2] = const0_rtx;
4806     }
4807   else if (GET_CODE (addr) != PLUS)
4808     FAIL;
4809   else if (REG_P (XEXP (addr, 0)))
4810     {
4811       operands[2] = XEXP (addr, 1);
4812       addr = gen_rtx_PLUS (Pmode, XEXP (addr, 0), operands[0]);
4813     }
4814   else
4815     {
4816       operands[2] = XEXP (addr, 0);
4817       addr = gen_rtx_PLUS (Pmode, XEXP (addr, 1), operands[0]);
4818     }
4819
4820   operands[3] = change_address (operands[1], QImode, addr);
4821 })
4822
4823 (define_peephole2
4824   [(set (match_operand:SI 0 "register_operand" "")
4825         (plus:SI (match_dup 0) (match_operand 1 "const_int_operand")))
4826    (set (match_operand:SI 2 "register_operand" "") (const_int 0))
4827    (set (match_operand:SI 3 "register_operand" "")
4828         (sign_extend:SI (match_operand:QI 4 "memory_operand" "")))]
4829   "TARGET_THUMB1
4830    && GET_CODE (XEXP (operands[4], 0)) == PLUS
4831    && rtx_equal_p (operands[0], XEXP (XEXP (operands[4], 0), 0))
4832    && rtx_equal_p (operands[2], XEXP (XEXP (operands[4], 0), 1))
4833    && (peep2_reg_dead_p (3, operands[0])
4834        || rtx_equal_p (operands[0], operands[3]))
4835    && (peep2_reg_dead_p (3, operands[2])
4836        || rtx_equal_p (operands[2], operands[3]))"
4837   [(set (match_dup 2) (match_dup 1))
4838    (set (match_dup 3) (sign_extend:SI (match_dup 4)))]
4839 {
4840   rtx addr = gen_rtx_PLUS (Pmode, operands[0], operands[2]);
4841   operands[4] = change_address (operands[4], QImode, addr);
4842 })
4843
4844 (define_insn "thumb1_extendqisi2"
4845   [(set (match_operand:SI 0 "register_operand" "=l,l,l")
4846         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
4847   "TARGET_THUMB1"
4848 {
4849   rtx addr;
4850
4851   if (which_alternative == 0 && arm_arch6)
4852     return "sxtb\\t%0, %1";
4853   if (which_alternative == 0)
4854     return "#";
4855
4856   addr = XEXP (operands[1], 0);
4857   if (GET_CODE (addr) == PLUS
4858       && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
4859     return "ldrsb\\t%0, %1";
4860       
4861   return "#";
4862 }
4863   [(set_attr_alternative "length"
4864                          [(if_then_else (eq_attr "is_arch6" "yes")
4865                                         (const_int 2) (const_int 4))
4866                           (const_int 2)
4867                           (if_then_else (eq_attr "is_arch6" "yes")
4868                                         (const_int 4) (const_int 6))])
4869    (set_attr "type" "alu_shift,load_byte,load_byte")]
4870 )
4871
4872 (define_expand "extendsfdf2"
4873   [(set (match_operand:DF                  0 "s_register_operand" "")
4874         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
4875   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
4876   ""
4877 )
4878
4879 /* HFmode -> DFmode conversions have to go through SFmode.  */
4880 (define_expand "extendhfdf2"
4881   [(set (match_operand:DF                  0 "general_operand" "")
4882         (float_extend:DF (match_operand:HF 1 "general_operand"  "")))]
4883   "TARGET_EITHER"
4884   "
4885   {
4886     rtx op1;
4887     op1 = convert_to_mode (SFmode, operands[1], 0);
4888     op1 = convert_to_mode (DFmode, op1, 0);
4889     emit_insn (gen_movdf (operands[0], op1));
4890     DONE;
4891   }"
4892 )
4893 \f
4894 ;; Move insns (including loads and stores)
4895
4896 ;; XXX Just some ideas about movti.
4897 ;; I don't think these are a good idea on the arm, there just aren't enough
4898 ;; registers
4899 ;;(define_expand "loadti"
4900 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
4901 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
4902 ;;  "" "")
4903
4904 ;;(define_expand "storeti"
4905 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4906 ;;      (match_operand:TI 1 "s_register_operand" ""))]
4907 ;;  "" "")
4908
4909 ;;(define_expand "movti"
4910 ;;  [(set (match_operand:TI 0 "general_operand" "")
4911 ;;      (match_operand:TI 1 "general_operand" ""))]
4912 ;;  ""
4913 ;;  "
4914 ;;{
4915 ;;  rtx insn;
4916 ;;
4917 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4918 ;;    operands[1] = copy_to_reg (operands[1]);
4919 ;;  if (GET_CODE (operands[0]) == MEM)
4920 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4921 ;;  else if (GET_CODE (operands[1]) == MEM)
4922 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4923 ;;  else
4924 ;;    FAIL;
4925 ;;
4926 ;;  emit_insn (insn);
4927 ;;  DONE;
4928 ;;}")
4929
4930 ;; Recognize garbage generated above.
4931
4932 ;;(define_insn ""
4933 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4934 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4935 ;;  ""
4936 ;;  "*
4937 ;;  {
4938 ;;    register mem = (which_alternative < 3);
4939 ;;    register const char *template;
4940 ;;
4941 ;;    operands[mem] = XEXP (operands[mem], 0);
4942 ;;    switch (which_alternative)
4943 ;;      {
4944 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4945 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
4946 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
4947 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
4948 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
4949 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
4950 ;;      }
4951 ;;    output_asm_insn (template, operands);
4952 ;;    return \"\";
4953 ;;  }")
4954
4955 (define_expand "movdi"
4956   [(set (match_operand:DI 0 "general_operand" "")
4957         (match_operand:DI 1 "general_operand" ""))]
4958   "TARGET_EITHER"
4959   "
4960   if (can_create_pseudo_p ())
4961     {
4962       if (GET_CODE (operands[0]) != REG)
4963         operands[1] = force_reg (DImode, operands[1]);
4964     }
4965   "
4966 )
4967
4968 (define_insn "*arm_movdi"
4969   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4970         (match_operand:DI 1 "di_operand"              "rDa,Db,Dc,mi,r"))]
4971   "TARGET_32BIT
4972    && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4973    && !TARGET_IWMMXT
4974    && (   register_operand (operands[0], DImode)
4975        || register_operand (operands[1], DImode))"
4976   "*
4977   switch (which_alternative)
4978     {
4979     case 0:
4980     case 1:
4981     case 2:
4982       return \"#\";
4983     default:
4984       return output_move_double (operands);
4985     }
4986   "
4987   [(set_attr "length" "8,12,16,8,8")
4988    (set_attr "type" "*,*,*,load2,store2")
4989    (set_attr "arm_pool_range" "*,*,*,1020,*")
4990    (set_attr "arm_neg_pool_range" "*,*,*,1008,*")
4991    (set_attr "thumb2_pool_range" "*,*,*,4096,*")
4992    (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
4993 )
4994
4995 (define_split
4996   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4997         (match_operand:ANY64 1 "const_double_operand" ""))]
4998   "TARGET_32BIT
4999    && reload_completed
5000    && (arm_const_double_inline_cost (operands[1])
5001        <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
5002   [(const_int 0)]
5003   "
5004   arm_split_constant (SET, SImode, curr_insn,
5005                       INTVAL (gen_lowpart (SImode, operands[1])),
5006                       gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
5007   arm_split_constant (SET, SImode, curr_insn,
5008                       INTVAL (gen_highpart_mode (SImode,
5009                                                  GET_MODE (operands[0]),
5010                                                  operands[1])),
5011                       gen_highpart (SImode, operands[0]), NULL_RTX, 0);
5012   DONE;
5013   "
5014 )
5015
5016 ; If optimizing for size, or if we have load delay slots, then 
5017 ; we want to split the constant into two separate operations. 
5018 ; In both cases this may split a trivial part into a single data op
5019 ; leaving a single complex constant to load.  We can also get longer
5020 ; offsets in a LDR which means we get better chances of sharing the pool
5021 ; entries.  Finally, we can normally do a better job of scheduling
5022 ; LDR instructions than we can with LDM.
5023 ; This pattern will only match if the one above did not.
5024 (define_split
5025   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5026         (match_operand:ANY64 1 "const_double_operand" ""))]
5027   "TARGET_ARM && reload_completed
5028    && arm_const_double_by_parts (operands[1])"
5029   [(set (match_dup 0) (match_dup 1))
5030    (set (match_dup 2) (match_dup 3))]
5031   "
5032   operands[2] = gen_highpart (SImode, operands[0]);
5033   operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
5034                                    operands[1]);
5035   operands[0] = gen_lowpart (SImode, operands[0]);
5036   operands[1] = gen_lowpart (SImode, operands[1]);
5037   "
5038 )
5039
5040 (define_split
5041   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5042         (match_operand:ANY64 1 "arm_general_register_operand" ""))]
5043   "TARGET_EITHER && reload_completed"
5044   [(set (match_dup 0) (match_dup 1))
5045    (set (match_dup 2) (match_dup 3))]
5046   "
5047   operands[2] = gen_highpart (SImode, operands[0]);
5048   operands[3] = gen_highpart (SImode, operands[1]);
5049   operands[0] = gen_lowpart (SImode, operands[0]);
5050   operands[1] = gen_lowpart (SImode, operands[1]);
5051
5052   /* Handle a partial overlap.  */
5053   if (rtx_equal_p (operands[0], operands[3]))
5054     {
5055       rtx tmp0 = operands[0];
5056       rtx tmp1 = operands[1];
5057
5058       operands[0] = operands[2];
5059       operands[1] = operands[3];
5060       operands[2] = tmp0;
5061       operands[3] = tmp1;
5062     }
5063   "
5064 )
5065
5066 ;; We can't actually do base+index doubleword loads if the index and
5067 ;; destination overlap.  Split here so that we at least have chance to
5068 ;; schedule.
5069 (define_split
5070   [(set (match_operand:DI 0 "s_register_operand" "")
5071         (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
5072                          (match_operand:SI 2 "s_register_operand" ""))))]
5073   "TARGET_LDRD
5074   && reg_overlap_mentioned_p (operands[0], operands[1])
5075   && reg_overlap_mentioned_p (operands[0], operands[2])"
5076   [(set (match_dup 4)
5077         (plus:SI (match_dup 1)
5078                  (match_dup 2)))
5079    (set (match_dup 0)
5080         (mem:DI (match_dup 4)))]
5081   "
5082   operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
5083   "
5084 )
5085
5086 ;;; ??? This should have alternatives for constants.
5087 ;;; ??? This was originally identical to the movdf_insn pattern.
5088 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
5089 ;;; thumb_reorg with a memory reference.
5090 (define_insn "*thumb1_movdi_insn"
5091   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
5092         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
5093   "TARGET_THUMB1
5094    && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
5095    && (   register_operand (operands[0], DImode)
5096        || register_operand (operands[1], DImode))"
5097   "*
5098   {
5099   switch (which_alternative)
5100     {
5101     default:
5102     case 0:
5103       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5104         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
5105       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
5106     case 1:
5107       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
5108     case 2:
5109       operands[1] = GEN_INT (- INTVAL (operands[1]));
5110       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
5111     case 3:
5112       return \"ldmia\\t%1, {%0, %H0}\";
5113     case 4:
5114       return \"stmia\\t%0, {%1, %H1}\";
5115     case 5:
5116       return thumb_load_double_from_address (operands);
5117     case 6:
5118       operands[2] = gen_rtx_MEM (SImode,
5119                              plus_constant (XEXP (operands[0], 0), 4));
5120       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5121       return \"\";
5122     case 7:
5123       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5124         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5125       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5126     }
5127   }"
5128   [(set_attr "length" "4,4,6,2,2,6,4,4")
5129    (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
5130    (set_attr "insn" "*,mov,*,*,*,*,*,mov")
5131    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
5132 )
5133
5134 (define_expand "movsi"
5135   [(set (match_operand:SI 0 "general_operand" "")
5136         (match_operand:SI 1 "general_operand" ""))]
5137   "TARGET_EITHER"
5138   "
5139   {
5140   rtx base, offset, tmp;
5141
5142   if (TARGET_32BIT)
5143     {
5144       /* Everything except mem = const or mem = mem can be done easily.  */
5145       if (GET_CODE (operands[0]) == MEM)
5146         operands[1] = force_reg (SImode, operands[1]);
5147       if (arm_general_register_operand (operands[0], SImode)
5148           && GET_CODE (operands[1]) == CONST_INT
5149           && !(const_ok_for_arm (INTVAL (operands[1]))
5150                || const_ok_for_arm (~INTVAL (operands[1]))))
5151         {
5152            arm_split_constant (SET, SImode, NULL_RTX,
5153                                INTVAL (operands[1]), operands[0], NULL_RTX,
5154                                optimize && can_create_pseudo_p ());
5155           DONE;
5156         }
5157
5158       if (TARGET_USE_MOVT && !target_word_relocations
5159           && GET_CODE (operands[1]) == SYMBOL_REF
5160           && !flag_pic && !arm_tls_referenced_p (operands[1]))
5161         {
5162           arm_emit_movpair (operands[0], operands[1]);
5163           DONE;
5164         }
5165     }
5166   else /* TARGET_THUMB1...  */
5167     {
5168       if (can_create_pseudo_p ())
5169         {
5170           if (GET_CODE (operands[0]) != REG)
5171             operands[1] = force_reg (SImode, operands[1]);
5172         }
5173     }
5174
5175   if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
5176     {
5177       split_const (operands[1], &base, &offset);
5178       if (GET_CODE (base) == SYMBOL_REF
5179           && !offset_within_block_p (base, INTVAL (offset)))
5180         {
5181           tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5182           emit_move_insn (tmp, base);
5183           emit_insn (gen_addsi3 (operands[0], tmp, offset));
5184           DONE;
5185         }
5186     }
5187
5188   /* Recognize the case where operand[1] is a reference to thread-local
5189      data and load its address to a register.  */
5190   if (arm_tls_referenced_p (operands[1]))
5191     {
5192       rtx tmp = operands[1];
5193       rtx addend = NULL;
5194
5195       if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
5196         {
5197           addend = XEXP (XEXP (tmp, 0), 1);
5198           tmp = XEXP (XEXP (tmp, 0), 0);
5199         }
5200
5201       gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
5202       gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
5203
5204       tmp = legitimize_tls_address (tmp,
5205                                     !can_create_pseudo_p () ? operands[0] : 0);
5206       if (addend)
5207         {
5208           tmp = gen_rtx_PLUS (SImode, tmp, addend);
5209           tmp = force_operand (tmp, operands[0]);
5210         }
5211       operands[1] = tmp;
5212     }
5213   else if (flag_pic
5214            && (CONSTANT_P (operands[1])
5215                || symbol_mentioned_p (operands[1])
5216                || label_mentioned_p (operands[1])))
5217       operands[1] = legitimize_pic_address (operands[1], SImode,
5218                                             (!can_create_pseudo_p ()
5219                                              ? operands[0]
5220                                              : 0));
5221   }
5222   "
5223 )
5224
5225 ;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5226 ;; LO_SUM adds in the high bits.  Fortunately these are opaque operations
5227 ;; so this does not matter.
5228 (define_insn "*arm_movt"
5229   [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5230         (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5231                    (match_operand:SI 2 "general_operand"      "i")))]
5232   "arm_arch_thumb2"
5233   "movt%?\t%0, #:upper16:%c2"
5234   [(set_attr "predicable" "yes")
5235    (set_attr "length" "4")]
5236 )
5237
5238 (define_insn "*arm_movsi_insn"
5239   [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
5240         (match_operand:SI 1 "general_operand"      "rk, I,K,j,mi,rk"))]
5241   "TARGET_ARM && ! TARGET_IWMMXT
5242    && !(TARGET_HARD_FLOAT && TARGET_VFP)
5243    && (   register_operand (operands[0], SImode)
5244        || register_operand (operands[1], SImode))"
5245   "@
5246    mov%?\\t%0, %1
5247    mov%?\\t%0, %1
5248    mvn%?\\t%0, #%B1
5249    movw%?\\t%0, %1
5250    ldr%?\\t%0, %1
5251    str%?\\t%1, %0"
5252   [(set_attr "type" "*,*,*,*,load1,store1")
5253    (set_attr "insn" "mov,mov,mvn,mov,*,*")
5254    (set_attr "predicable" "yes")
5255    (set_attr "pool_range" "*,*,*,*,4096,*")
5256    (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
5257 )
5258
5259 (define_split
5260   [(set (match_operand:SI 0 "arm_general_register_operand" "")
5261         (match_operand:SI 1 "const_int_operand" ""))]
5262   "TARGET_32BIT
5263   && (!(const_ok_for_arm (INTVAL (operands[1]))
5264         || const_ok_for_arm (~INTVAL (operands[1]))))"
5265   [(clobber (const_int 0))]
5266   "
5267   arm_split_constant (SET, SImode, NULL_RTX, 
5268                       INTVAL (operands[1]), operands[0], NULL_RTX, 0);
5269   DONE;
5270   "
5271 )
5272
5273 (define_insn "*thumb1_movsi_insn"
5274   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*l*h*k")
5275         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*l*h*k"))]
5276   "TARGET_THUMB1
5277    && (   register_operand (operands[0], SImode) 
5278        || register_operand (operands[1], SImode))"
5279   "@
5280    mov  %0, %1
5281    mov  %0, %1
5282    #
5283    #
5284    ldmia\\t%1, {%0}
5285    stmia\\t%0, {%1}
5286    ldr\\t%0, %1
5287    str\\t%1, %0
5288    mov\\t%0, %1"
5289   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
5290    (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
5291    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")
5292    (set_attr "conds" "set,clob,*,*,nocond,nocond,nocond,nocond,nocond")])
5293
5294 (define_split 
5295   [(set (match_operand:SI 0 "register_operand" "")
5296         (match_operand:SI 1 "const_int_operand" ""))]
5297   "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
5298   [(set (match_dup 2) (match_dup 1))
5299    (set (match_dup 0) (neg:SI (match_dup 2)))]
5300   "
5301   {
5302     operands[1] = GEN_INT (- INTVAL (operands[1]));
5303     operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5304   }"
5305 )
5306
5307 (define_split 
5308   [(set (match_operand:SI 0 "register_operand" "")
5309         (match_operand:SI 1 "const_int_operand" ""))]
5310   "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
5311   [(set (match_dup 2) (match_dup 1))
5312    (set (match_dup 0) (ashift:SI (match_dup 2) (match_dup 3)))]
5313   "
5314   {
5315     unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu;
5316     unsigned HOST_WIDE_INT mask = 0xff;
5317     int i;
5318     
5319     for (i = 0; i < 25; i++)
5320       if ((val & (mask << i)) == val)
5321         break;
5322
5323     /* Don't split if the shift is zero.  */
5324     if (i == 0)
5325       FAIL;
5326
5327     operands[1] = GEN_INT (val >> i);
5328     operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5329     operands[3] = GEN_INT (i);
5330   }"
5331 )
5332
5333 ;; When generating pic, we need to load the symbol offset into a register.
5334 ;; So that the optimizer does not confuse this with a normal symbol load
5335 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
5336 ;; since that is the only type of relocation we can use.
5337
5338 ;; Wrap calculation of the whole PIC address in a single pattern for the
5339 ;; benefit of optimizers, particularly, PRE and HOIST.  Calculation of
5340 ;; a PIC address involves two loads from memory, so we want to CSE it
5341 ;; as often as possible.
5342 ;; This pattern will be split into one of the pic_load_addr_* patterns
5343 ;; and a move after GCSE optimizations.
5344 ;;
5345 ;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
5346 (define_expand "calculate_pic_address"
5347   [(set (match_operand:SI 0 "register_operand" "")
5348         (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5349                          (unspec:SI [(match_operand:SI 2 "" "")]
5350                                     UNSPEC_PIC_SYM))))]
5351   "flag_pic"
5352 )
5353
5354 ;; Split calculate_pic_address into pic_load_addr_* and a move.
5355 (define_split
5356   [(set (match_operand:SI 0 "register_operand" "")
5357         (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5358                          (unspec:SI [(match_operand:SI 2 "" "")]
5359                                     UNSPEC_PIC_SYM))))]
5360   "flag_pic"
5361   [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
5362    (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
5363   "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
5364 )
5365
5366 ;; The rather odd constraints on the following are to force reload to leave
5367 ;; the insn alone, and to force the minipool generation pass to then move
5368 ;; the GOT symbol to memory.
5369
5370 (define_insn "pic_load_addr_32bit"
5371   [(set (match_operand:SI 0 "s_register_operand" "=r")
5372         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
5373   "TARGET_32BIT && flag_pic"
5374   "ldr%?\\t%0, %1"
5375   [(set_attr "type" "load1")
5376    (set_attr "pool_range" "4096")
5377    (set (attr "neg_pool_range")
5378         (if_then_else (eq_attr "is_thumb" "no")
5379                       (const_int 4084)
5380                       (const_int 0)))]
5381 )
5382
5383 (define_insn "pic_load_addr_thumb1"
5384   [(set (match_operand:SI 0 "s_register_operand" "=l")
5385         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
5386   "TARGET_THUMB1 && flag_pic"
5387   "ldr\\t%0, %1"
5388   [(set_attr "type" "load1")
5389    (set (attr "pool_range") (const_int 1024))]
5390 )
5391
5392 (define_insn "pic_add_dot_plus_four"
5393   [(set (match_operand:SI 0 "register_operand" "=r")
5394         (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5395                     (const_int 4)
5396                     (match_operand 2 "" "")]
5397                    UNSPEC_PIC_BASE))]
5398   "TARGET_THUMB"
5399   "*
5400   (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5401                                      INTVAL (operands[2]));
5402   return \"add\\t%0, %|pc\";
5403   "
5404   [(set_attr "length" "2")]
5405 )
5406
5407 (define_insn "pic_add_dot_plus_eight"
5408   [(set (match_operand:SI 0 "register_operand" "=r")
5409         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5410                     (const_int 8)
5411                     (match_operand 2 "" "")]
5412                    UNSPEC_PIC_BASE))]
5413   "TARGET_ARM"
5414   "*
5415     (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5416                                        INTVAL (operands[2]));
5417     return \"add%?\\t%0, %|pc, %1\";
5418   "
5419   [(set_attr "predicable" "yes")]
5420 )
5421
5422 (define_insn "tls_load_dot_plus_eight"
5423   [(set (match_operand:SI 0 "register_operand" "=r")
5424         (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5425                             (const_int 8)
5426                             (match_operand 2 "" "")]
5427                            UNSPEC_PIC_BASE)))]
5428   "TARGET_ARM"
5429   "*
5430     (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5431                                        INTVAL (operands[2]));
5432     return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5433   "
5434   [(set_attr "predicable" "yes")]
5435 )
5436
5437 ;; PIC references to local variables can generate pic_add_dot_plus_eight
5438 ;; followed by a load.  These sequences can be crunched down to
5439 ;; tls_load_dot_plus_eight by a peephole.
5440
5441 (define_peephole2
5442   [(set (match_operand:SI 0 "register_operand" "")
5443         (unspec:SI [(match_operand:SI 3 "register_operand" "")
5444                     (const_int 8)
5445                     (match_operand 1 "" "")]
5446                    UNSPEC_PIC_BASE))
5447    (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
5448   "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
5449   [(set (match_dup 2)
5450         (mem:SI (unspec:SI [(match_dup 3)
5451                             (const_int 8)
5452                             (match_dup 1)]
5453                            UNSPEC_PIC_BASE)))]
5454   ""
5455 )
5456
5457 (define_insn "pic_offset_arm"
5458   [(set (match_operand:SI 0 "register_operand" "=r")
5459         (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5460                          (unspec:SI [(match_operand:SI 2 "" "X")]
5461                                     UNSPEC_PIC_OFFSET))))]
5462   "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5463   "ldr%?\\t%0, [%1,%2]"
5464   [(set_attr "type" "load1")]
5465 )
5466
5467 (define_expand "builtin_setjmp_receiver"
5468   [(label_ref (match_operand 0 "" ""))]
5469   "flag_pic"
5470   "
5471 {
5472   /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5473      register.  */
5474   if (arm_pic_register != INVALID_REGNUM)
5475     arm_load_pic_register (1UL << 3);
5476   DONE;
5477 }")
5478
5479 ;; If copying one reg to another we can set the condition codes according to
5480 ;; its value.  Such a move is common after a return from subroutine and the
5481 ;; result is being tested against zero.
5482
5483 (define_insn "*movsi_compare0"
5484   [(set (reg:CC CC_REGNUM)
5485         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5486                     (const_int 0)))
5487    (set (match_operand:SI 0 "s_register_operand" "=r,r")
5488         (match_dup 1))]
5489   "TARGET_32BIT"
5490   "@
5491    cmp%?\\t%0, #0
5492    sub%.\\t%0, %1, #0"
5493   [(set_attr "conds" "set")]
5494 )
5495
5496 ;; Subroutine to store a half word from a register into memory.
5497 ;; Operand 0 is the source register (HImode)
5498 ;; Operand 1 is the destination address in a register (SImode)
5499
5500 ;; In both this routine and the next, we must be careful not to spill
5501 ;; a memory address of reg+large_const into a separate PLUS insn, since this
5502 ;; can generate unrecognizable rtl.
5503
5504 (define_expand "storehi"
5505   [;; store the low byte
5506    (set (match_operand 1 "" "") (match_dup 3))
5507    ;; extract the high byte
5508    (set (match_dup 2)
5509         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
5510    ;; store the high byte
5511    (set (match_dup 4) (match_dup 5))]
5512   "TARGET_ARM"
5513   "
5514   {
5515     rtx op1 = operands[1];
5516     rtx addr = XEXP (op1, 0);
5517     enum rtx_code code = GET_CODE (addr);
5518
5519     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5520         || code == MINUS)
5521       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
5522
5523     operands[4] = adjust_address (op1, QImode, 1);
5524     operands[1] = adjust_address (operands[1], QImode, 0);
5525     operands[3] = gen_lowpart (QImode, operands[0]);
5526     operands[0] = gen_lowpart (SImode, operands[0]);
5527     operands[2] = gen_reg_rtx (SImode);
5528     operands[5] = gen_lowpart (QImode, operands[2]);
5529   }"
5530 )
5531
5532 (define_expand "storehi_bigend"
5533   [(set (match_dup 4) (match_dup 3))
5534    (set (match_dup 2)
5535         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
5536    (set (match_operand 1 "" "") (match_dup 5))]
5537   "TARGET_ARM"
5538   "
5539   {
5540     rtx op1 = operands[1];
5541     rtx addr = XEXP (op1, 0);
5542     enum rtx_code code = GET_CODE (addr);
5543
5544     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5545         || code == MINUS)
5546       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
5547
5548     operands[4] = adjust_address (op1, QImode, 1);
5549     operands[1] = adjust_address (operands[1], QImode, 0);
5550     operands[3] = gen_lowpart (QImode, operands[0]);
5551     operands[0] = gen_lowpart (SImode, operands[0]);
5552     operands[2] = gen_reg_rtx (SImode);
5553     operands[5] = gen_lowpart (QImode, operands[2]);
5554   }"
5555 )
5556
5557 ;; Subroutine to store a half word integer constant into memory.
5558 (define_expand "storeinthi"
5559   [(set (match_operand 0 "" "")
5560         (match_operand 1 "" ""))
5561    (set (match_dup 3) (match_dup 2))]
5562   "TARGET_ARM"
5563   "
5564   {
5565     HOST_WIDE_INT value = INTVAL (operands[1]);
5566     rtx addr = XEXP (operands[0], 0);
5567     rtx op0 = operands[0];
5568     enum rtx_code code = GET_CODE (addr);
5569
5570     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5571         || code == MINUS)
5572       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
5573
5574     operands[1] = gen_reg_rtx (SImode);
5575     if (BYTES_BIG_ENDIAN)
5576       {
5577         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5578         if ((value & 255) == ((value >> 8) & 255))
5579           operands[2] = operands[1];
5580         else
5581           {
5582             operands[2] = gen_reg_rtx (SImode);
5583             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5584           }
5585       }
5586     else
5587       {
5588         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5589         if ((value & 255) == ((value >> 8) & 255))
5590           operands[2] = operands[1];
5591         else
5592           {
5593             operands[2] = gen_reg_rtx (SImode);
5594             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5595           }
5596       }
5597
5598     operands[3] = adjust_address (op0, QImode, 1);
5599     operands[0] = adjust_address (operands[0], QImode, 0);
5600     operands[2] = gen_lowpart (QImode, operands[2]);
5601     operands[1] = gen_lowpart (QImode, operands[1]);
5602   }"
5603 )
5604
5605 (define_expand "storehi_single_op"
5606   [(set (match_operand:HI 0 "memory_operand" "")
5607         (match_operand:HI 1 "general_operand" ""))]
5608   "TARGET_32BIT && arm_arch4"
5609   "
5610   if (!s_register_operand (operands[1], HImode))
5611     operands[1] = copy_to_mode_reg (HImode, operands[1]);
5612   "
5613 )
5614
5615 (define_expand "movhi"
5616   [(set (match_operand:HI 0 "general_operand" "")
5617         (match_operand:HI 1 "general_operand" ""))]
5618   "TARGET_EITHER"
5619   "
5620   if (TARGET_ARM)
5621     {
5622       if (can_create_pseudo_p ())
5623         {
5624           if (GET_CODE (operands[0]) == MEM)
5625             {
5626               if (arm_arch4)
5627                 {
5628                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5629                   DONE;
5630                 }
5631               if (GET_CODE (operands[1]) == CONST_INT)
5632                 emit_insn (gen_storeinthi (operands[0], operands[1]));
5633               else
5634                 {
5635                   if (GET_CODE (operands[1]) == MEM)
5636                     operands[1] = force_reg (HImode, operands[1]);
5637                   if (BYTES_BIG_ENDIAN)
5638                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
5639                   else
5640                    emit_insn (gen_storehi (operands[1], operands[0]));
5641                 }
5642               DONE;
5643             }
5644           /* Sign extend a constant, and keep it in an SImode reg.  */
5645           else if (GET_CODE (operands[1]) == CONST_INT)
5646             {
5647               rtx reg = gen_reg_rtx (SImode);
5648               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5649
5650               /* If the constant is already valid, leave it alone.  */
5651               if (!const_ok_for_arm (val))
5652                 {
5653                   /* If setting all the top bits will make the constant 
5654                      loadable in a single instruction, then set them.  
5655                      Otherwise, sign extend the number.  */
5656
5657                   if (const_ok_for_arm (~(val | ~0xffff)))
5658                     val |= ~0xffff;
5659                   else if (val & 0x8000)
5660                     val |= ~0xffff;
5661                 }
5662
5663               emit_insn (gen_movsi (reg, GEN_INT (val)));
5664               operands[1] = gen_lowpart (HImode, reg);
5665             }
5666           else if (arm_arch4 && optimize && can_create_pseudo_p ()
5667                    && GET_CODE (operands[1]) == MEM)
5668             {
5669               rtx reg = gen_reg_rtx (SImode);
5670
5671               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5672               operands[1] = gen_lowpart (HImode, reg);
5673             }
5674           else if (!arm_arch4)
5675             {
5676               if (GET_CODE (operands[1]) == MEM)
5677                 {
5678                   rtx base;
5679                   rtx offset = const0_rtx;
5680                   rtx reg = gen_reg_rtx (SImode);
5681
5682                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
5683                        || (GET_CODE (base) == PLUS
5684                            && (GET_CODE (offset = XEXP (base, 1))
5685                                == CONST_INT)
5686                            && ((INTVAL(offset) & 1) != 1)
5687                            && GET_CODE (base = XEXP (base, 0)) == REG))
5688                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
5689                     {
5690                       rtx new_rtx;
5691
5692                       new_rtx = widen_memory_access (operands[1], SImode,
5693                                                      ((INTVAL (offset) & ~3)
5694                                                       - INTVAL (offset)));
5695                       emit_insn (gen_movsi (reg, new_rtx));
5696                       if (((INTVAL (offset) & 2) != 0)
5697                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
5698                         {
5699                           rtx reg2 = gen_reg_rtx (SImode);
5700
5701                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
5702                           reg = reg2;
5703                         }
5704                     }
5705                   else
5706                     emit_insn (gen_movhi_bytes (reg, operands[1]));
5707
5708                   operands[1] = gen_lowpart (HImode, reg);
5709                }
5710            }
5711         }
5712       /* Handle loading a large integer during reload.  */
5713       else if (GET_CODE (operands[1]) == CONST_INT
5714                && !const_ok_for_arm (INTVAL (operands[1]))
5715                && !const_ok_for_arm (~INTVAL (operands[1])))
5716         {
5717           /* Writing a constant to memory needs a scratch, which should
5718              be handled with SECONDARY_RELOADs.  */
5719           gcc_assert (GET_CODE (operands[0]) == REG);
5720
5721           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5722           emit_insn (gen_movsi (operands[0], operands[1]));
5723           DONE;
5724        }
5725     }
5726   else if (TARGET_THUMB2)
5727     {
5728       /* Thumb-2 can do everything except mem=mem and mem=const easily.  */
5729       if (can_create_pseudo_p ())
5730         {
5731           if (GET_CODE (operands[0]) != REG)
5732             operands[1] = force_reg (HImode, operands[1]);
5733           /* Zero extend a constant, and keep it in an SImode reg.  */
5734           else if (GET_CODE (operands[1]) == CONST_INT)
5735             {
5736               rtx reg = gen_reg_rtx (SImode);
5737               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5738
5739               emit_insn (gen_movsi (reg, GEN_INT (val)));
5740               operands[1] = gen_lowpart (HImode, reg);
5741             }
5742         }
5743     }
5744   else /* TARGET_THUMB1 */
5745     {
5746       if (can_create_pseudo_p ())
5747         {
5748           if (GET_CODE (operands[1]) == CONST_INT)
5749             {
5750               rtx reg = gen_reg_rtx (SImode);
5751
5752               emit_insn (gen_movsi (reg, operands[1]));
5753               operands[1] = gen_lowpart (HImode, reg);
5754             }
5755
5756           /* ??? We shouldn't really get invalid addresses here, but this can
5757              happen if we are passed a SP (never OK for HImode/QImode) or 
5758              virtual register (also rejected as illegitimate for HImode/QImode)
5759              relative address.  */
5760           /* ??? This should perhaps be fixed elsewhere, for instance, in
5761              fixup_stack_1, by checking for other kinds of invalid addresses,
5762              e.g. a bare reference to a virtual register.  This may confuse the
5763              alpha though, which must handle this case differently.  */
5764           if (GET_CODE (operands[0]) == MEM
5765               && !memory_address_p (GET_MODE (operands[0]),
5766                                     XEXP (operands[0], 0)))
5767             operands[0]
5768               = replace_equiv_address (operands[0],
5769                                        copy_to_reg (XEXP (operands[0], 0)));
5770    
5771           if (GET_CODE (operands[1]) == MEM
5772               && !memory_address_p (GET_MODE (operands[1]),
5773                                     XEXP (operands[1], 0)))
5774             operands[1]
5775               = replace_equiv_address (operands[1],
5776                                        copy_to_reg (XEXP (operands[1], 0)));
5777
5778           if (GET_CODE (operands[1]) == MEM && optimize > 0)
5779             {
5780               rtx reg = gen_reg_rtx (SImode);
5781
5782               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5783               operands[1] = gen_lowpart (HImode, reg);
5784             }
5785
5786           if (GET_CODE (operands[0]) == MEM)
5787             operands[1] = force_reg (HImode, operands[1]);
5788         }
5789       else if (GET_CODE (operands[1]) == CONST_INT
5790                 && !satisfies_constraint_I (operands[1]))
5791         {
5792           /* Handle loading a large integer during reload.  */
5793
5794           /* Writing a constant to memory needs a scratch, which should
5795              be handled with SECONDARY_RELOADs.  */
5796           gcc_assert (GET_CODE (operands[0]) == REG);
5797
5798           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5799           emit_insn (gen_movsi (operands[0], operands[1]));
5800           DONE;
5801         }
5802     }
5803   "
5804 )
5805
5806 (define_insn "*thumb1_movhi_insn"
5807   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5808         (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
5809   "TARGET_THUMB1
5810    && (   register_operand (operands[0], HImode)
5811        || register_operand (operands[1], HImode))"
5812   "*
5813   switch (which_alternative)
5814     {
5815     case 0: return \"add        %0, %1, #0\";
5816     case 2: return \"strh       %1, %0\";
5817     case 3: return \"mov        %0, %1\";
5818     case 4: return \"mov        %0, %1\";
5819     case 5: return \"mov        %0, %1\";
5820     default: gcc_unreachable ();
5821     case 1:
5822       /* The stack pointer can end up being taken as an index register.
5823           Catch this case here and deal with it.  */
5824       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
5825           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
5826           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
5827         {
5828           rtx ops[2];
5829           ops[0] = operands[0];
5830           ops[1] = XEXP (XEXP (operands[1], 0), 0);
5831       
5832           output_asm_insn (\"mov        %0, %1\", ops);
5833
5834           XEXP (XEXP (operands[1], 0), 0) = operands[0];
5835     
5836         }
5837       return \"ldrh     %0, %1\";
5838     }"
5839   [(set_attr "length" "2,4,2,2,2,2")
5840    (set_attr "type" "*,load1,store1,*,*,*")
5841    (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
5842
5843
5844 (define_expand "movhi_bytes"
5845   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
5846    (set (match_dup 3)
5847         (zero_extend:SI (match_dup 6)))
5848    (set (match_operand:SI 0 "" "")
5849          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
5850   "TARGET_ARM"
5851   "
5852   {
5853     rtx mem1, mem2;
5854     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5855
5856     mem1 = change_address (operands[1], QImode, addr);
5857     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
5858     operands[0] = gen_lowpart (SImode, operands[0]);
5859     operands[1] = mem1;
5860     operands[2] = gen_reg_rtx (SImode);
5861     operands[3] = gen_reg_rtx (SImode);
5862     operands[6] = mem2;
5863
5864     if (BYTES_BIG_ENDIAN)
5865       {
5866         operands[4] = operands[2];
5867         operands[5] = operands[3];
5868       }
5869     else
5870       {
5871         operands[4] = operands[3];
5872         operands[5] = operands[2];
5873       }
5874   }"
5875 )
5876
5877 (define_expand "movhi_bigend"
5878   [(set (match_dup 2)
5879         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
5880                    (const_int 16)))
5881    (set (match_dup 3)
5882         (ashiftrt:SI (match_dup 2) (const_int 16)))
5883    (set (match_operand:HI 0 "s_register_operand" "")
5884         (match_dup 4))]
5885   "TARGET_ARM"
5886   "
5887   operands[2] = gen_reg_rtx (SImode);
5888   operands[3] = gen_reg_rtx (SImode);
5889   operands[4] = gen_lowpart (HImode, operands[3]);
5890   "
5891 )
5892
5893 ;; Pattern to recognize insn generated default case above
5894 (define_insn "*movhi_insn_arch4"
5895   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
5896         (match_operand:HI 1 "general_operand"      "rI,K,r,mi"))]
5897   "TARGET_ARM
5898    && arm_arch4
5899    && (register_operand (operands[0], HImode)
5900        || register_operand (operands[1], HImode))"
5901   "@
5902    mov%?\\t%0, %1\\t%@ movhi
5903    mvn%?\\t%0, #%B1\\t%@ movhi
5904    str%(h%)\\t%1, %0\\t%@ movhi
5905    ldr%(h%)\\t%0, %1\\t%@ movhi"
5906   [(set_attr "type" "*,*,store1,load1")
5907    (set_attr "predicable" "yes")
5908    (set_attr "insn" "mov,mvn,*,*")
5909    (set_attr "pool_range" "*,*,*,256")
5910    (set_attr "neg_pool_range" "*,*,*,244")]
5911 )
5912
5913 (define_insn "*movhi_bytes"
5914   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
5915         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
5916   "TARGET_ARM"
5917   "@
5918    mov%?\\t%0, %1\\t%@ movhi
5919    mvn%?\\t%0, #%B1\\t%@ movhi"
5920   [(set_attr "predicable" "yes")
5921    (set_attr "insn" "mov,mvn")]
5922 )
5923
5924 (define_expand "thumb_movhi_clobber"
5925   [(set (match_operand:HI     0 "memory_operand"   "")
5926         (match_operand:HI     1 "register_operand" ""))
5927    (clobber (match_operand:DI 2 "register_operand" ""))]
5928   "TARGET_THUMB1"
5929   "
5930   if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
5931       && REGNO (operands[1]) <= LAST_LO_REGNUM)
5932     {
5933       emit_insn (gen_movhi (operands[0], operands[1]));
5934       DONE;
5935     }
5936   /* XXX Fixme, need to handle other cases here as well.  */
5937   gcc_unreachable ();
5938   "
5939 )
5940         
5941 ;; We use a DImode scratch because we may occasionally need an additional
5942 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
5943 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
5944 (define_expand "reload_outhi"
5945   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
5946               (match_operand:HI 1 "s_register_operand"        "r")
5947               (match_operand:DI 2 "s_register_operand"        "=&l")])]
5948   "TARGET_EITHER"
5949   "if (TARGET_ARM)
5950      arm_reload_out_hi (operands);
5951    else
5952      thumb_reload_out_hi (operands);
5953   DONE;
5954   "
5955 )
5956
5957 (define_expand "reload_inhi"
5958   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
5959               (match_operand:HI 1 "arm_reload_memory_operand" "o")
5960               (match_operand:DI 2 "s_register_operand" "=&r")])]
5961   "TARGET_EITHER"
5962   "
5963   if (TARGET_ARM)
5964     arm_reload_in_hi (operands);
5965   else
5966     thumb_reload_out_hi (operands);
5967   DONE;
5968 ")
5969
5970 (define_expand "movqi"
5971   [(set (match_operand:QI 0 "general_operand" "")
5972         (match_operand:QI 1 "general_operand" ""))]
5973   "TARGET_EITHER"
5974   "
5975   /* Everything except mem = const or mem = mem can be done easily */
5976
5977   if (can_create_pseudo_p ())
5978     {
5979       if (GET_CODE (operands[1]) == CONST_INT)
5980         {
5981           rtx reg = gen_reg_rtx (SImode);
5982
5983           /* For thumb we want an unsigned immediate, then we are more likely 
5984              to be able to use a movs insn.  */
5985           if (TARGET_THUMB)
5986             operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
5987
5988           emit_insn (gen_movsi (reg, operands[1]));
5989           operands[1] = gen_lowpart (QImode, reg);
5990         }
5991
5992       if (TARGET_THUMB)
5993         {
5994           /* ??? We shouldn't really get invalid addresses here, but this can
5995              happen if we are passed a SP (never OK for HImode/QImode) or
5996              virtual register (also rejected as illegitimate for HImode/QImode)
5997              relative address.  */
5998           /* ??? This should perhaps be fixed elsewhere, for instance, in
5999              fixup_stack_1, by checking for other kinds of invalid addresses,
6000              e.g. a bare reference to a virtual register.  This may confuse the
6001              alpha though, which must handle this case differently.  */
6002           if (GET_CODE (operands[0]) == MEM
6003               && !memory_address_p (GET_MODE (operands[0]),
6004                                      XEXP (operands[0], 0)))
6005             operands[0]
6006               = replace_equiv_address (operands[0],
6007                                        copy_to_reg (XEXP (operands[0], 0)));
6008           if (GET_CODE (operands[1]) == MEM
6009               && !memory_address_p (GET_MODE (operands[1]),
6010                                     XEXP (operands[1], 0)))
6011              operands[1]
6012                = replace_equiv_address (operands[1],
6013                                         copy_to_reg (XEXP (operands[1], 0)));
6014         }
6015
6016       if (GET_CODE (operands[1]) == MEM && optimize > 0)
6017         {
6018           rtx reg = gen_reg_rtx (SImode);
6019
6020           emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
6021           operands[1] = gen_lowpart (QImode, reg);
6022         }
6023
6024       if (GET_CODE (operands[0]) == MEM)
6025         operands[1] = force_reg (QImode, operands[1]);
6026     }
6027   else if (TARGET_THUMB
6028            && GET_CODE (operands[1]) == CONST_INT
6029            && !satisfies_constraint_I (operands[1]))
6030     {
6031       /* Handle loading a large integer during reload.  */
6032
6033       /* Writing a constant to memory needs a scratch, which should
6034          be handled with SECONDARY_RELOADs.  */
6035       gcc_assert (GET_CODE (operands[0]) == REG);
6036
6037       operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6038       emit_insn (gen_movsi (operands[0], operands[1]));
6039       DONE;
6040     }
6041   "
6042 )
6043
6044
6045 (define_insn "*arm_movqi_insn"
6046   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,l,Uu,r,m")
6047         (match_operand:QI 1 "general_operand" "rI,K,Uu,l,m,r"))]
6048   "TARGET_32BIT
6049    && (   register_operand (operands[0], QImode)
6050        || register_operand (operands[1], QImode))"
6051   "@
6052    mov%?\\t%0, %1
6053    mvn%?\\t%0, #%B1
6054    ldr%(b%)\\t%0, %1
6055    str%(b%)\\t%1, %0
6056    ldr%(b%)\\t%0, %1
6057    str%(b%)\\t%1, %0"
6058   [(set_attr "type" "*,*,load1,store1,load1,store1")
6059    (set_attr "insn" "mov,mvn,*,*,*,*")
6060    (set_attr "predicable" "yes")
6061    (set_attr "arch" "any,any,t2,t2,any,any")
6062    (set_attr "length" "4,4,2,2,4,4")]
6063 )
6064
6065 (define_insn "*thumb1_movqi_insn"
6066   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
6067         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
6068   "TARGET_THUMB1
6069    && (   register_operand (operands[0], QImode)
6070        || register_operand (operands[1], QImode))"
6071   "@
6072    add\\t%0, %1, #0
6073    ldrb\\t%0, %1
6074    strb\\t%1, %0
6075    mov\\t%0, %1
6076    mov\\t%0, %1
6077    mov\\t%0, %1"
6078   [(set_attr "length" "2")
6079    (set_attr "type" "*,load1,store1,*,*,*")
6080    (set_attr "insn" "*,*,*,mov,mov,mov")
6081    (set_attr "pool_range" "*,32,*,*,*,*")
6082    (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
6083
6084 ;; HFmode moves
6085 (define_expand "movhf"
6086   [(set (match_operand:HF 0 "general_operand" "")
6087         (match_operand:HF 1 "general_operand" ""))]
6088   "TARGET_EITHER"
6089   "
6090   if (TARGET_32BIT)
6091     {
6092       if (GET_CODE (operands[0]) == MEM)
6093         operands[1] = force_reg (HFmode, operands[1]);
6094     }
6095   else /* TARGET_THUMB1 */
6096     {
6097       if (can_create_pseudo_p ())
6098         {
6099            if (GET_CODE (operands[0]) != REG)
6100              operands[1] = force_reg (HFmode, operands[1]);
6101         }
6102     }
6103   "
6104 )
6105
6106 (define_insn "*arm32_movhf"
6107   [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6108         (match_operand:HF 1 "general_operand"      " m,r,r,F"))]
6109   "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16)
6110    && (   s_register_operand (operands[0], HFmode)
6111        || s_register_operand (operands[1], HFmode))"
6112   "*
6113   switch (which_alternative)
6114     {
6115     case 0:     /* ARM register from memory */
6116       return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
6117     case 1:     /* memory from ARM register */
6118       return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
6119     case 2:     /* ARM register from ARM register */
6120       return \"mov%?\\t%0, %1\\t%@ __fp16\";
6121     case 3:     /* ARM register from constant */
6122       {
6123         REAL_VALUE_TYPE r;
6124         long bits;
6125         rtx ops[4];
6126
6127         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
6128         bits = real_to_target (NULL, &r, HFmode);
6129         ops[0] = operands[0];
6130         ops[1] = GEN_INT (bits);
6131         ops[2] = GEN_INT (bits & 0xff00);
6132         ops[3] = GEN_INT (bits & 0x00ff);
6133
6134         if (arm_arch_thumb2)
6135           output_asm_insn (\"movw%?\\t%0, %1\", ops);
6136         else
6137           output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6138         return \"\";
6139        }
6140     default:
6141       gcc_unreachable ();
6142     }
6143   "
6144   [(set_attr "conds" "unconditional")
6145    (set_attr "type" "load1,store1,*,*")
6146    (set_attr "insn" "*,*,mov,mov")
6147    (set_attr "length" "4,4,4,8")
6148    (set_attr "predicable" "yes")]
6149 )
6150
6151 (define_insn "*thumb1_movhf"
6152   [(set (match_operand:HF     0 "nonimmediate_operand" "=l,l,m,*r,*h")
6153         (match_operand:HF     1 "general_operand"      "l,mF,l,*h,*r"))]
6154   "TARGET_THUMB1
6155    && (   s_register_operand (operands[0], HFmode) 
6156        || s_register_operand (operands[1], HFmode))"
6157   "*
6158   switch (which_alternative)
6159     {
6160     case 1:
6161       {
6162         rtx addr;
6163         gcc_assert (GET_CODE(operands[1]) == MEM);
6164         addr = XEXP (operands[1], 0);
6165         if (GET_CODE (addr) == LABEL_REF
6166             || (GET_CODE (addr) == CONST
6167                 && GET_CODE (XEXP (addr, 0)) == PLUS
6168                 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF
6169                 && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT))
6170           {
6171             /* Constant pool entry.  */
6172             return \"ldr\\t%0, %1\";
6173           }
6174         return \"ldrh\\t%0, %1\";
6175       }
6176     case 2: return \"strh\\t%1, %0\";
6177     default: return \"mov\\t%0, %1\";
6178     }
6179   "
6180   [(set_attr "length" "2")
6181    (set_attr "type" "*,load1,store1,*,*")
6182    (set_attr "insn" "mov,*,*,mov,mov")
6183    (set_attr "pool_range" "*,1020,*,*,*")
6184    (set_attr "conds" "clob,nocond,nocond,nocond,nocond")])
6185
6186 (define_expand "movsf"
6187   [(set (match_operand:SF 0 "general_operand" "")
6188         (match_operand:SF 1 "general_operand" ""))]
6189   "TARGET_EITHER"
6190   "
6191   if (TARGET_32BIT)
6192     {
6193       if (GET_CODE (operands[0]) == MEM)
6194         operands[1] = force_reg (SFmode, operands[1]);
6195     }
6196   else /* TARGET_THUMB1 */
6197     {
6198       if (can_create_pseudo_p ())
6199         {
6200            if (GET_CODE (operands[0]) != REG)
6201              operands[1] = force_reg (SFmode, operands[1]);
6202         }
6203     }
6204   "
6205 )
6206
6207 ;; Transform a floating-point move of a constant into a core register into
6208 ;; an SImode operation.
6209 (define_split
6210   [(set (match_operand:SF 0 "arm_general_register_operand" "")
6211         (match_operand:SF 1 "immediate_operand" ""))]
6212   "TARGET_EITHER
6213    && reload_completed
6214    && GET_CODE (operands[1]) == CONST_DOUBLE"
6215   [(set (match_dup 2) (match_dup 3))]
6216   "
6217   operands[2] = gen_lowpart (SImode, operands[0]);
6218   operands[3] = gen_lowpart (SImode, operands[1]);
6219   if (operands[2] == 0 || operands[3] == 0)
6220     FAIL;
6221   "
6222 )
6223
6224 (define_insn "*arm_movsf_soft_insn"
6225   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6226         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
6227   "TARGET_32BIT
6228    && TARGET_SOFT_FLOAT
6229    && (GET_CODE (operands[0]) != MEM
6230        || register_operand (operands[1], SFmode))"
6231   "@
6232    mov%?\\t%0, %1
6233    ldr%?\\t%0, %1\\t%@ float
6234    str%?\\t%1, %0\\t%@ float"
6235   [(set_attr "predicable" "yes")
6236    (set_attr "type" "*,load1,store1")
6237    (set_attr "insn" "mov,*,*")
6238    (set_attr "pool_range" "*,4096,*")
6239    (set_attr "arm_neg_pool_range" "*,4084,*")
6240    (set_attr "thumb2_neg_pool_range" "*,0,*")]
6241 )
6242
6243 ;;; ??? This should have alternatives for constants.
6244 (define_insn "*thumb1_movsf_insn"
6245   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
6246         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
6247   "TARGET_THUMB1
6248    && (   register_operand (operands[0], SFmode) 
6249        || register_operand (operands[1], SFmode))"
6250   "@
6251    add\\t%0, %1, #0
6252    ldmia\\t%1, {%0}
6253    stmia\\t%0, {%1}
6254    ldr\\t%0, %1
6255    str\\t%1, %0
6256    mov\\t%0, %1
6257    mov\\t%0, %1"
6258   [(set_attr "length" "2")
6259    (set_attr "type" "*,load1,store1,load1,store1,*,*")
6260    (set_attr "pool_range" "*,*,*,1020,*,*,*")
6261    (set_attr "insn" "*,*,*,*,*,mov,mov")
6262    (set_attr "conds" "clob,nocond,nocond,nocond,nocond,nocond,nocond")]
6263 )
6264
6265 (define_expand "movdf"
6266   [(set (match_operand:DF 0 "general_operand" "")
6267         (match_operand:DF 1 "general_operand" ""))]
6268   "TARGET_EITHER"
6269   "
6270   if (TARGET_32BIT)
6271     {
6272       if (GET_CODE (operands[0]) == MEM)
6273         operands[1] = force_reg (DFmode, operands[1]);
6274     }
6275   else /* TARGET_THUMB */
6276     {
6277       if (can_create_pseudo_p ())
6278         {
6279           if (GET_CODE (operands[0]) != REG)
6280             operands[1] = force_reg (DFmode, operands[1]);
6281         }
6282     }
6283   "
6284 )
6285
6286 ;; Reloading a df mode value stored in integer regs to memory can require a
6287 ;; scratch reg.
6288 (define_expand "reload_outdf"
6289   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
6290    (match_operand:DF 1 "s_register_operand" "r")
6291    (match_operand:SI 2 "s_register_operand" "=&r")]
6292   "TARGET_THUMB2"
6293   "
6294   {
6295     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
6296
6297     if (code == REG)
6298       operands[2] = XEXP (operands[0], 0);
6299     else if (code == POST_INC || code == PRE_DEC)
6300       {
6301         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6302         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6303         emit_insn (gen_movdi (operands[0], operands[1]));
6304         DONE;
6305       }
6306     else if (code == PRE_INC)
6307       {
6308         rtx reg = XEXP (XEXP (operands[0], 0), 0);
6309
6310         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6311         operands[2] = reg;
6312       }
6313     else if (code == POST_DEC)
6314       operands[2] = XEXP (XEXP (operands[0], 0), 0);
6315     else
6316       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6317                              XEXP (XEXP (operands[0], 0), 1)));
6318
6319     emit_insn (gen_rtx_SET (VOIDmode,
6320                             replace_equiv_address (operands[0], operands[2]),
6321                             operands[1]));
6322
6323     if (code == POST_DEC)
6324       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6325
6326     DONE;
6327   }"
6328 )
6329
6330 (define_insn "*movdf_soft_insn"
6331   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
6332         (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
6333   "TARGET_32BIT && TARGET_SOFT_FLOAT
6334    && (   register_operand (operands[0], DFmode)
6335        || register_operand (operands[1], DFmode))"
6336   "*
6337   switch (which_alternative)
6338     {
6339     case 0:
6340     case 1:
6341     case 2:
6342       return \"#\";
6343     default:
6344       return output_move_double (operands);
6345     }
6346   "
6347   [(set_attr "length" "8,12,16,8,8")
6348    (set_attr "type" "*,*,*,load2,store2")
6349    (set_attr "pool_range" "*,*,*,1020,*")
6350    (set_attr "arm_neg_pool_range" "*,*,*,1008,*")
6351    (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
6352 )
6353
6354 ;;; ??? This should have alternatives for constants.
6355 ;;; ??? This was originally identical to the movdi_insn pattern.
6356 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
6357 ;;; thumb_reorg with a memory reference.
6358 (define_insn "*thumb_movdf_insn"
6359   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
6360         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
6361   "TARGET_THUMB1
6362    && (   register_operand (operands[0], DFmode)
6363        || register_operand (operands[1], DFmode))"
6364   "*
6365   switch (which_alternative)
6366     {
6367     default:
6368     case 0:
6369       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6370         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
6371       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
6372     case 1:
6373       return \"ldmia\\t%1, {%0, %H0}\";
6374     case 2:
6375       return \"stmia\\t%0, {%1, %H1}\";
6376     case 3:
6377       return thumb_load_double_from_address (operands);
6378     case 4:
6379       operands[2] = gen_rtx_MEM (SImode,
6380                                  plus_constant (XEXP (operands[0], 0), 4));
6381       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
6382       return \"\";
6383     case 5:
6384       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6385         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
6386       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
6387     }
6388   "
6389   [(set_attr "length" "4,2,2,6,4,4")
6390    (set_attr "type" "*,load2,store2,load2,store2,*")
6391    (set_attr "insn" "*,*,*,*,*,mov")
6392    (set_attr "pool_range" "*,*,*,1020,*,*")]
6393 )
6394
6395 (define_expand "movxf"
6396   [(set (match_operand:XF 0 "general_operand" "")
6397         (match_operand:XF 1 "general_operand" ""))]
6398   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
6399   "
6400   if (GET_CODE (operands[0]) == MEM)
6401     operands[1] = force_reg (XFmode, operands[1]);
6402   "
6403 )
6404
6405 \f
6406
6407 ;; load- and store-multiple insns
6408 ;; The arm can load/store any set of registers, provided that they are in
6409 ;; ascending order, but these expanders assume a contiguous set.
6410
6411 (define_expand "load_multiple"
6412   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6413                           (match_operand:SI 1 "" ""))
6414                      (use (match_operand:SI 2 "" ""))])]
6415   "TARGET_32BIT"
6416 {
6417   HOST_WIDE_INT offset = 0;
6418
6419   /* Support only fixed point registers.  */
6420   if (GET_CODE (operands[2]) != CONST_INT
6421       || INTVAL (operands[2]) > 14
6422       || INTVAL (operands[2]) < 2
6423       || GET_CODE (operands[1]) != MEM
6424       || GET_CODE (operands[0]) != REG
6425       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6426       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
6427     FAIL;
6428
6429   operands[3]
6430     = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
6431                              INTVAL (operands[2]),
6432                              force_reg (SImode, XEXP (operands[1], 0)),
6433                              FALSE, operands[1], &offset);
6434 })
6435
6436 (define_expand "store_multiple"
6437   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6438                           (match_operand:SI 1 "" ""))
6439                      (use (match_operand:SI 2 "" ""))])]
6440   "TARGET_32BIT"
6441 {
6442   HOST_WIDE_INT offset = 0;
6443
6444   /* Support only fixed point registers.  */
6445   if (GET_CODE (operands[2]) != CONST_INT
6446       || INTVAL (operands[2]) > 14
6447       || INTVAL (operands[2]) < 2
6448       || GET_CODE (operands[1]) != REG
6449       || GET_CODE (operands[0]) != MEM
6450       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6451       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
6452     FAIL;
6453
6454   operands[3]
6455     = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
6456                               INTVAL (operands[2]),
6457                               force_reg (SImode, XEXP (operands[0], 0)),
6458                               FALSE, operands[0], &offset);
6459 })
6460
6461
6462 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
6463 ;; We could let this apply for blocks of less than this, but it clobbers so
6464 ;; many registers that there is then probably a better way.
6465
6466 (define_expand "movmemqi"
6467   [(match_operand:BLK 0 "general_operand" "")
6468    (match_operand:BLK 1 "general_operand" "")
6469    (match_operand:SI 2 "const_int_operand" "")
6470    (match_operand:SI 3 "const_int_operand" "")]
6471   "TARGET_EITHER"
6472   "
6473   if (TARGET_32BIT)
6474     {
6475       if (arm_gen_movmemqi (operands))
6476         DONE;
6477       FAIL;
6478     }
6479   else /* TARGET_THUMB1 */
6480     {
6481       if (   INTVAL (operands[3]) != 4
6482           || INTVAL (operands[2]) > 48)
6483         FAIL;
6484
6485       thumb_expand_movmemqi (operands);
6486       DONE;
6487     }
6488   "
6489 )
6490
6491 ;; Thumb block-move insns
6492
6493 (define_insn "movmem12b"
6494   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6495         (mem:SI (match_operand:SI 3 "register_operand" "1")))
6496    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6497         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6498    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6499         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
6500    (set (match_operand:SI 0 "register_operand" "=l")
6501         (plus:SI (match_dup 2) (const_int 12)))
6502    (set (match_operand:SI 1 "register_operand" "=l")
6503         (plus:SI (match_dup 3) (const_int 12)))
6504    (clobber (match_scratch:SI 4 "=&l"))
6505    (clobber (match_scratch:SI 5 "=&l"))
6506    (clobber (match_scratch:SI 6 "=&l"))]
6507   "TARGET_THUMB1"
6508   "* return thumb_output_move_mem_multiple (3, operands);"
6509   [(set_attr "length" "4")
6510    ; This isn't entirely accurate...  It loads as well, but in terms of
6511    ; scheduling the following insn it is better to consider it as a store
6512    (set_attr "type" "store3")]
6513 )
6514
6515 (define_insn "movmem8b"
6516   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6517         (mem:SI (match_operand:SI 3 "register_operand" "1")))
6518    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6519         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6520    (set (match_operand:SI 0 "register_operand" "=l")
6521         (plus:SI (match_dup 2) (const_int 8)))
6522    (set (match_operand:SI 1 "register_operand" "=l")
6523         (plus:SI (match_dup 3) (const_int 8)))
6524    (clobber (match_scratch:SI 4 "=&l"))
6525    (clobber (match_scratch:SI 5 "=&l"))]
6526   "TARGET_THUMB1"
6527   "* return thumb_output_move_mem_multiple (2, operands);"
6528   [(set_attr "length" "4")
6529    ; This isn't entirely accurate...  It loads as well, but in terms of
6530    ; scheduling the following insn it is better to consider it as a store
6531    (set_attr "type" "store2")]
6532 )
6533
6534 \f
6535
6536 ;; Compare & branch insns
6537 ;; The range calculations are based as follows:
6538 ;; For forward branches, the address calculation returns the address of
6539 ;; the next instruction.  This is 2 beyond the branch instruction.
6540 ;; For backward branches, the address calculation returns the address of
6541 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
6542 ;; instruction for the shortest sequence, and 4 before the branch instruction
6543 ;; if we have to jump around an unconditional branch.
6544 ;; To the basic branch range the PC offset must be added (this is +4).
6545 ;; So for forward branches we have 
6546 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6547 ;; And for backward branches we have 
6548 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6549 ;;
6550 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6551 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
6552
6553 (define_expand "cbranchsi4"
6554   [(set (pc) (if_then_else
6555               (match_operator 0 "arm_comparison_operator"
6556                [(match_operand:SI 1 "s_register_operand" "")
6557                 (match_operand:SI 2 "nonmemory_operand" "")])
6558               (label_ref (match_operand 3 "" ""))
6559               (pc)))]
6560   "TARGET_THUMB1 || TARGET_32BIT"
6561   "
6562   if (!TARGET_THUMB1)
6563     {
6564       if (!arm_add_operand (operands[2], SImode))
6565         operands[2] = force_reg (SImode, operands[2]);
6566       emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6567                                       operands[3]));
6568       DONE;
6569     }
6570   if (thumb1_cmpneg_operand (operands[2], SImode))
6571     {
6572       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6573                                               operands[3], operands[0]));
6574       DONE;
6575     }
6576   if (!thumb1_cmp_operand (operands[2], SImode))
6577     operands[2] = force_reg (SImode, operands[2]);
6578   ")
6579
6580 ;; A pattern to recognize a special situation and optimize for it.
6581 ;; On the thumb, zero-extension from memory is preferrable to sign-extension
6582 ;; due to the available addressing modes.  Hence, convert a signed comparison
6583 ;; with zero into an unsigned comparison with 127 if possible.
6584 (define_expand "cbranchqi4"
6585   [(set (pc) (if_then_else
6586               (match_operator 0 "lt_ge_comparison_operator"
6587                [(match_operand:QI 1 "memory_operand" "")
6588                 (match_operand:QI 2 "const0_operand" "")])
6589               (label_ref (match_operand 3 "" ""))
6590               (pc)))]
6591   "TARGET_THUMB1"
6592 {
6593   rtx xops[4];
6594   xops[1] = gen_reg_rtx (SImode);
6595   emit_insn (gen_zero_extendqisi2 (xops[1], operands[1]));
6596   xops[2] = GEN_INT (127);
6597   xops[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]) == GE ? LEU : GTU,
6598                             VOIDmode, xops[1], xops[2]);
6599   xops[3] = operands[3];
6600   emit_insn (gen_cbranchsi4 (xops[0], xops[1], xops[2], xops[3]));
6601   DONE;
6602 })
6603
6604 (define_expand "cbranchsf4"
6605   [(set (pc) (if_then_else
6606               (match_operator 0 "arm_comparison_operator"
6607                [(match_operand:SF 1 "s_register_operand" "")
6608                 (match_operand:SF 2 "arm_float_compare_operand" "")])
6609               (label_ref (match_operand 3 "" ""))
6610               (pc)))]
6611   "TARGET_32BIT && TARGET_HARD_FLOAT"
6612   "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6613                                    operands[3])); DONE;"
6614 )
6615
6616 (define_expand "cbranchdf4"
6617   [(set (pc) (if_then_else
6618               (match_operator 0 "arm_comparison_operator"
6619                [(match_operand:DF 1 "s_register_operand" "")
6620                 (match_operand:DF 2 "arm_float_compare_operand" "")])
6621               (label_ref (match_operand 3 "" ""))
6622               (pc)))]
6623   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
6624   "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6625                                    operands[3])); DONE;"
6626 )
6627
6628 (define_expand "cbranchdi4"
6629   [(set (pc) (if_then_else
6630               (match_operator 0 "arm_comparison_operator"
6631                [(match_operand:DI 1 "cmpdi_operand" "")
6632                 (match_operand:DI 2 "cmpdi_operand" "")])
6633               (label_ref (match_operand 3 "" ""))
6634               (pc)))]
6635   "TARGET_32BIT"
6636   "{
6637      rtx swap = NULL_RTX;
6638      enum rtx_code code = GET_CODE (operands[0]);
6639
6640      /* We should not have two constants.  */
6641      gcc_assert (GET_MODE (operands[1]) == DImode
6642                  || GET_MODE (operands[2]) == DImode);
6643
6644     /* Flip unimplemented DImode comparisons to a form that
6645        arm_gen_compare_reg can handle.  */
6646      switch (code)
6647      {
6648      case GT:
6649        swap = gen_rtx_LT (VOIDmode, operands[2], operands[1]); break;
6650      case LE:
6651        swap = gen_rtx_GE (VOIDmode, operands[2], operands[1]); break;
6652      case GTU:
6653        swap = gen_rtx_LTU (VOIDmode, operands[2], operands[1]); break;
6654      case LEU:
6655        swap = gen_rtx_GEU (VOIDmode, operands[2], operands[1]); break;
6656      default:
6657        break;
6658      }
6659      if (swap)
6660        emit_jump_insn (gen_cbranch_cc (swap, operands[2], operands[1],
6661                                        operands[3]));
6662      else
6663        emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6664                                        operands[3]));
6665      DONE;
6666    }"
6667 )
6668
6669 (define_insn "cbranchsi4_insn"
6670   [(set (pc) (if_then_else
6671               (match_operator 0 "arm_comparison_operator"
6672                [(match_operand:SI 1 "s_register_operand" "l,l*h")
6673                 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
6674               (label_ref (match_operand 3 "" ""))
6675               (pc)))]
6676   "TARGET_THUMB1"
6677 {
6678   rtx t = cfun->machine->thumb1_cc_insn;
6679   if (t != NULL_RTX)
6680     {
6681       if (!rtx_equal_p (cfun->machine->thumb1_cc_op0, operands[1])
6682           || !rtx_equal_p (cfun->machine->thumb1_cc_op1, operands[2]))
6683         t = NULL_RTX;
6684       if (cfun->machine->thumb1_cc_mode == CC_NOOVmode)
6685         {
6686           if (!noov_comparison_operator (operands[0], VOIDmode))
6687             t = NULL_RTX;
6688         }
6689       else if (cfun->machine->thumb1_cc_mode != CCmode)
6690         t = NULL_RTX;
6691     }
6692   if (t == NULL_RTX)
6693     {
6694       output_asm_insn ("cmp\t%1, %2", operands);
6695       cfun->machine->thumb1_cc_insn = insn;
6696       cfun->machine->thumb1_cc_op0 = operands[1];
6697       cfun->machine->thumb1_cc_op1 = operands[2];
6698       cfun->machine->thumb1_cc_mode = CCmode;
6699     }
6700   else
6701     /* Ensure we emit the right type of condition code on the jump.  */
6702     XEXP (operands[0], 0) = gen_rtx_REG (cfun->machine->thumb1_cc_mode,
6703                                          CC_REGNUM);
6704
6705   switch (get_attr_length (insn))
6706     {
6707     case 4:  return \"b%d0\\t%l3\";
6708     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6709     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6710     }
6711 }
6712   [(set (attr "far_jump")
6713         (if_then_else
6714             (eq_attr "length" "8")
6715             (const_string "yes")
6716             (const_string "no")))
6717    (set (attr "length") 
6718         (if_then_else
6719             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6720                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6721             (const_int 4)
6722             (if_then_else
6723                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6724                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6725                 (const_int 6)
6726                 (const_int 8))))]
6727 )
6728
6729 (define_insn "cbranchsi4_scratch"
6730   [(set (pc) (if_then_else
6731               (match_operator 4 "arm_comparison_operator"
6732                [(match_operand:SI 1 "s_register_operand" "l,0")
6733                 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
6734               (label_ref (match_operand 3 "" ""))
6735               (pc)))
6736    (clobber (match_scratch:SI 0 "=l,l"))]
6737   "TARGET_THUMB1"
6738   "*
6739   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
6740
6741   switch (get_attr_length (insn))
6742     {
6743     case 4:  return \"b%d4\\t%l3\";
6744     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6745     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6746     }
6747   "
6748   [(set (attr "far_jump")
6749         (if_then_else
6750             (eq_attr "length" "8")
6751             (const_string "yes")
6752             (const_string "no")))
6753    (set (attr "length") 
6754         (if_then_else
6755             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6756                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6757             (const_int 4)
6758             (if_then_else
6759                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6760                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6761                 (const_int 6)
6762                 (const_int 8))))]
6763 )
6764
6765 ;; Two peepholes to generate subtract of 0 instead of a move if the
6766 ;; condition codes will be useful.
6767 (define_peephole2
6768   [(set (match_operand:SI 0 "low_register_operand" "")
6769         (match_operand:SI 1 "low_register_operand" ""))
6770    (set (pc)
6771         (if_then_else (match_operator 2 "arm_comparison_operator"
6772                        [(match_dup 1) (const_int 0)])
6773                       (label_ref (match_operand 3 "" ""))
6774                       (pc)))]
6775   "TARGET_THUMB1"
6776   [(set (match_dup 0) (minus:SI (match_dup 1) (const_int 0)))
6777    (set (pc)
6778         (if_then_else (match_op_dup 2 [(match_dup 0) (const_int 0)])
6779                       (label_ref (match_dup 3))
6780                       (pc)))]
6781   "")
6782
6783 ;; Sigh!  This variant shouldn't be needed, but combine often fails to
6784 ;; merge cases like this because the op1 is a hard register in
6785 ;; arm_class_likely_spilled_p.
6786 (define_peephole2
6787   [(set (match_operand:SI 0 "low_register_operand" "")
6788         (match_operand:SI 1 "low_register_operand" ""))
6789    (set (pc)
6790         (if_then_else (match_operator 2 "arm_comparison_operator"
6791                        [(match_dup 0) (const_int 0)])
6792                       (label_ref (match_operand 3 "" ""))
6793                       (pc)))]
6794   "TARGET_THUMB1"
6795   [(set (match_dup 0) (minus:SI (match_dup 1) (const_int 0)))
6796    (set (pc)
6797         (if_then_else (match_op_dup 2 [(match_dup 0) (const_int 0)])
6798                       (label_ref (match_dup 3))
6799                       (pc)))]
6800   "")
6801
6802 (define_insn "*negated_cbranchsi4"
6803   [(set (pc)
6804         (if_then_else
6805          (match_operator 0 "equality_operator"
6806           [(match_operand:SI 1 "s_register_operand" "l")
6807            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
6808          (label_ref (match_operand 3 "" ""))
6809          (pc)))]
6810   "TARGET_THUMB1"
6811   "*
6812   output_asm_insn (\"cmn\\t%1, %2\", operands);
6813   switch (get_attr_length (insn))
6814     {
6815     case 4:  return \"b%d0\\t%l3\";
6816     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6817     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6818     }
6819   "
6820   [(set (attr "far_jump")
6821         (if_then_else
6822             (eq_attr "length" "8")
6823             (const_string "yes")
6824             (const_string "no")))
6825    (set (attr "length") 
6826         (if_then_else
6827             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6828                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6829             (const_int 4)
6830             (if_then_else
6831                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6832                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6833                 (const_int 6)
6834                 (const_int 8))))]
6835 )
6836
6837 (define_insn "*tbit_cbranch"
6838   [(set (pc)
6839         (if_then_else
6840          (match_operator 0 "equality_operator"
6841           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6842                             (const_int 1)
6843                             (match_operand:SI 2 "const_int_operand" "i"))
6844            (const_int 0)])
6845          (label_ref (match_operand 3 "" ""))
6846          (pc)))
6847    (clobber (match_scratch:SI 4 "=l"))]
6848   "TARGET_THUMB1"
6849   "*
6850   {
6851   rtx op[3];
6852   op[0] = operands[4];
6853   op[1] = operands[1];
6854   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
6855
6856   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6857   switch (get_attr_length (insn))
6858     {
6859     case 4:  return \"b%d0\\t%l3\";
6860     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6861     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6862     }
6863   }"
6864   [(set (attr "far_jump")
6865         (if_then_else
6866             (eq_attr "length" "8")
6867             (const_string "yes")
6868             (const_string "no")))
6869    (set (attr "length") 
6870         (if_then_else
6871             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6872                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6873             (const_int 4)
6874             (if_then_else
6875                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6876                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6877                 (const_int 6)
6878                 (const_int 8))))]
6879 )
6880   
6881 (define_insn "*tlobits_cbranch"
6882   [(set (pc)
6883         (if_then_else
6884          (match_operator 0 "equality_operator"
6885           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6886                             (match_operand:SI 2 "const_int_operand" "i")
6887                             (const_int 0))
6888            (const_int 0)])
6889          (label_ref (match_operand 3 "" ""))
6890          (pc)))
6891    (clobber (match_scratch:SI 4 "=l"))]
6892   "TARGET_THUMB1"
6893   "*
6894   {
6895   rtx op[3];
6896   op[0] = operands[4];
6897   op[1] = operands[1];
6898   op[2] = GEN_INT (32 - INTVAL (operands[2]));
6899
6900   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6901   switch (get_attr_length (insn))
6902     {
6903     case 4:  return \"b%d0\\t%l3\";
6904     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6905     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6906     }
6907   }"
6908   [(set (attr "far_jump")
6909         (if_then_else
6910             (eq_attr "length" "8")
6911             (const_string "yes")
6912             (const_string "no")))
6913    (set (attr "length") 
6914         (if_then_else
6915             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6916                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6917             (const_int 4)
6918             (if_then_else
6919                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6920                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6921                 (const_int 6)
6922                 (const_int 8))))]
6923 )
6924
6925 (define_insn "*tstsi3_cbranch"
6926   [(set (pc)
6927         (if_then_else
6928          (match_operator 3 "equality_operator"
6929           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
6930                    (match_operand:SI 1 "s_register_operand" "l"))
6931            (const_int 0)])
6932          (label_ref (match_operand 2 "" ""))
6933          (pc)))]
6934   "TARGET_THUMB1"
6935   "*
6936   {
6937   output_asm_insn (\"tst\\t%0, %1\", operands);
6938   switch (get_attr_length (insn))
6939     {
6940     case 4:  return \"b%d3\\t%l2\";
6941     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6942     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
6943     }
6944   }"
6945   [(set (attr "far_jump")
6946         (if_then_else
6947             (eq_attr "length" "8")
6948             (const_string "yes")
6949             (const_string "no")))
6950    (set (attr "length") 
6951         (if_then_else
6952             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6953                  (le (minus (match_dup 2) (pc)) (const_int 256)))
6954             (const_int 4)
6955             (if_then_else
6956                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6957                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
6958                 (const_int 6)
6959                 (const_int 8))))]
6960 )
6961   
6962 (define_insn "*cbranchne_decr1"
6963   [(set (pc)
6964         (if_then_else (match_operator 3 "equality_operator"
6965                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6966                         (const_int 0)])
6967                       (label_ref (match_operand 4 "" ""))
6968                       (pc)))
6969    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6970         (plus:SI (match_dup 2) (const_int -1)))
6971    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6972   "TARGET_THUMB1"
6973   "*
6974    {
6975      rtx cond[2];
6976      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6977                                 ? GEU : LTU),
6978                                VOIDmode, operands[2], const1_rtx);
6979      cond[1] = operands[4];
6980
6981      if (which_alternative == 0)
6982        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6983      else if (which_alternative == 1)
6984        {
6985          /* We must provide an alternative for a hi reg because reload 
6986             cannot handle output reloads on a jump instruction, but we
6987             can't subtract into that.  Fortunately a mov from lo to hi
6988             does not clobber the condition codes.  */
6989          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6990          output_asm_insn (\"mov\\t%0, %1\", operands);
6991        }
6992      else
6993        {
6994          /* Similarly, but the target is memory.  */
6995          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6996          output_asm_insn (\"str\\t%1, %0\", operands);
6997        }
6998
6999      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7000        {
7001          case 4:
7002            output_asm_insn (\"b%d0\\t%l1\", cond);
7003            return \"\";
7004          case 6:
7005            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
7006            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
7007          default:
7008            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
7009            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7010        }
7011    }
7012   "
7013   [(set (attr "far_jump")
7014         (if_then_else
7015             (ior (and (eq (symbol_ref ("which_alternative"))
7016                           (const_int 0))
7017                       (eq_attr "length" "8"))
7018                  (eq_attr "length" "10"))
7019             (const_string "yes")
7020             (const_string "no")))
7021    (set_attr_alternative "length"
7022       [
7023        ;; Alternative 0
7024        (if_then_else
7025          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7026               (le (minus (match_dup 4) (pc)) (const_int 256)))
7027          (const_int 4)
7028          (if_then_else
7029            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7030                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7031            (const_int 6)
7032            (const_int 8)))
7033        ;; Alternative 1
7034        (if_then_else
7035          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7036               (le (minus (match_dup 4) (pc)) (const_int 256)))
7037          (const_int 6)
7038          (if_then_else
7039            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7040                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7041            (const_int 8)
7042            (const_int 10)))
7043        ;; Alternative 2
7044        (if_then_else
7045          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7046               (le (minus (match_dup 4) (pc)) (const_int 256)))
7047          (const_int 6)
7048          (if_then_else
7049            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7050                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7051            (const_int 8)
7052            (const_int 10)))
7053        ;; Alternative 3
7054        (if_then_else
7055          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7056               (le (minus (match_dup 4) (pc)) (const_int 256)))
7057          (const_int 6)
7058          (if_then_else
7059            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7060                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7061            (const_int 8)
7062            (const_int 10)))])]
7063 )
7064
7065 (define_insn "*addsi3_cbranch"
7066   [(set (pc)
7067         (if_then_else
7068          (match_operator 4 "arm_comparison_operator"
7069           [(plus:SI
7070             (match_operand:SI 2 "s_register_operand" "%0,l,*l,1,1,1")
7071             (match_operand:SI 3 "reg_or_int_operand" "IJ,lL,*l,lIJ,lIJ,lIJ"))
7072            (const_int 0)])
7073          (label_ref (match_operand 5 "" ""))
7074          (pc)))
7075    (set
7076     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
7077     (plus:SI (match_dup 2) (match_dup 3)))
7078    (clobber (match_scratch:SI 1 "=X,X,l,l,&l,&l"))]
7079   "TARGET_THUMB1
7080    && (GET_CODE (operands[4]) == EQ
7081        || GET_CODE (operands[4]) == NE
7082        || GET_CODE (operands[4]) == GE
7083        || GET_CODE (operands[4]) == LT)"
7084   "*
7085    {
7086      rtx cond[3];
7087
7088      cond[0] = (which_alternative < 2) ? operands[0] : operands[1];
7089      cond[1] = operands[2];
7090      cond[2] = operands[3];
7091
7092      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
7093        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
7094      else
7095        output_asm_insn (\"add\\t%0, %1, %2\", cond);
7096
7097      if (which_alternative >= 2
7098          && which_alternative < 4)
7099        output_asm_insn (\"mov\\t%0, %1\", operands);
7100      else if (which_alternative >= 4)
7101        output_asm_insn (\"str\\t%1, %0\", operands);
7102
7103      switch (get_attr_length (insn) - ((which_alternative >= 2) ? 2 : 0))
7104        {
7105          case 4:
7106            return \"b%d4\\t%l5\";
7107          case 6:
7108            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7109          default:
7110            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7111        }
7112    }
7113   "
7114   [(set (attr "far_jump")
7115         (if_then_else
7116             (ior (and (lt (symbol_ref ("which_alternative"))
7117                           (const_int 2))
7118                       (eq_attr "length" "8"))
7119                  (eq_attr "length" "10"))
7120             (const_string "yes")
7121             (const_string "no")))
7122    (set (attr "length")
7123      (if_then_else
7124        (lt (symbol_ref ("which_alternative"))
7125                        (const_int 2))
7126        (if_then_else
7127          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7128               (le (minus (match_dup 5) (pc)) (const_int 256)))
7129          (const_int 4)
7130          (if_then_else
7131            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7132                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7133            (const_int 6)
7134            (const_int 8)))
7135        (if_then_else
7136          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7137               (le (minus (match_dup 5) (pc)) (const_int 256)))
7138          (const_int 6)
7139          (if_then_else
7140            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7141                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7142            (const_int 8)
7143            (const_int 10)))))]
7144 )
7145
7146 (define_insn "*addsi3_cbranch_scratch"
7147   [(set (pc)
7148         (if_then_else
7149          (match_operator 3 "arm_comparison_operator"
7150           [(plus:SI
7151             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
7152             (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
7153            (const_int 0)])
7154          (label_ref (match_operand 4 "" ""))
7155          (pc)))
7156    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
7157   "TARGET_THUMB1
7158    && (GET_CODE (operands[3]) == EQ
7159        || GET_CODE (operands[3]) == NE
7160        || GET_CODE (operands[3]) == GE
7161        || GET_CODE (operands[3]) == LT)"
7162   "*
7163    {
7164      switch (which_alternative)
7165        {
7166        case 0:
7167          output_asm_insn (\"cmp\t%1, #%n2\", operands);
7168          break;
7169        case 1:
7170          output_asm_insn (\"cmn\t%1, %2\", operands);
7171          break;
7172        case 2:
7173          if (INTVAL (operands[2]) < 0)
7174            output_asm_insn (\"sub\t%0, %1, %2\", operands);
7175          else
7176            output_asm_insn (\"add\t%0, %1, %2\", operands);
7177          break;
7178        case 3:
7179          if (INTVAL (operands[2]) < 0)
7180            output_asm_insn (\"sub\t%0, %0, %2\", operands);
7181          else
7182            output_asm_insn (\"add\t%0, %0, %2\", operands);
7183          break;
7184        }
7185
7186      switch (get_attr_length (insn))
7187        {
7188          case 4:
7189            return \"b%d3\\t%l4\";
7190          case 6:
7191            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7192          default:
7193            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7194        }
7195    }
7196   "
7197   [(set (attr "far_jump")
7198         (if_then_else
7199             (eq_attr "length" "8")
7200             (const_string "yes")
7201             (const_string "no")))
7202    (set (attr "length")
7203        (if_then_else
7204          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7205               (le (minus (match_dup 4) (pc)) (const_int 256)))
7206          (const_int 4)
7207          (if_then_else
7208            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7209                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7210            (const_int 6)
7211            (const_int 8))))]
7212 )
7213
7214
7215 ;; Comparison and test insns
7216
7217 (define_insn "*arm_cmpsi_insn"
7218   [(set (reg:CC CC_REGNUM)
7219         (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r")
7220                     (match_operand:SI 1 "arm_add_operand"    "Py,r,rI,L")))]
7221   "TARGET_32BIT"
7222   "@
7223    cmp%?\\t%0, %1
7224    cmp%?\\t%0, %1
7225    cmp%?\\t%0, %1
7226    cmn%?\\t%0, #%n1"
7227   [(set_attr "conds" "set")
7228    (set_attr "arch" "t2,t2,any,any")
7229    (set_attr "length" "2,2,4,4")]
7230 )
7231
7232 (define_insn "*cmpsi_shiftsi"
7233   [(set (reg:CC CC_REGNUM)
7234         (compare:CC (match_operand:SI   0 "s_register_operand" "r,r")
7235                     (match_operator:SI  3 "shift_operator"
7236                      [(match_operand:SI 1 "s_register_operand" "r,r")
7237                       (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
7238   "TARGET_32BIT"
7239   "cmp%?\\t%0, %1%S3"
7240   [(set_attr "conds" "set")
7241    (set_attr "shift" "1")
7242    (set_attr "arch" "32,a")
7243    (set_attr "type" "alu_shift,alu_shift_reg")])
7244
7245 (define_insn "*cmpsi_shiftsi_swp"
7246   [(set (reg:CC_SWP CC_REGNUM)
7247         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
7248                          [(match_operand:SI 1 "s_register_operand" "r,r")
7249                           (match_operand:SI 2 "shift_amount_operand" "M,rM")])
7250                         (match_operand:SI 0 "s_register_operand" "r,r")))]
7251   "TARGET_32BIT"
7252   "cmp%?\\t%0, %1%S3"
7253   [(set_attr "conds" "set")
7254    (set_attr "shift" "1")
7255    (set_attr "arch" "32,a")
7256    (set_attr "type" "alu_shift,alu_shift_reg")])
7257
7258 (define_insn "*arm_cmpsi_negshiftsi_si"
7259   [(set (reg:CC_Z CC_REGNUM)
7260         (compare:CC_Z
7261          (neg:SI (match_operator:SI 1 "shift_operator"
7262                     [(match_operand:SI 2 "s_register_operand" "r")
7263                      (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7264          (match_operand:SI 0 "s_register_operand" "r")))]
7265   "TARGET_ARM"
7266   "cmn%?\\t%0, %2%S1"
7267   [(set_attr "conds" "set")
7268    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7269                                     (const_string "alu_shift")
7270                                     (const_string "alu_shift_reg")))]
7271 )
7272
7273 ;; DImode comparisons.  The generic code generates branches that
7274 ;; if-conversion can not reduce to a conditional compare, so we do
7275 ;; that directly.
7276
7277 (define_insn "*arm_cmpdi_insn"
7278   [(set (reg:CC_NCV CC_REGNUM)
7279         (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
7280                         (match_operand:DI 1 "arm_di_operand"       "rDi")))
7281    (clobber (match_scratch:SI 2 "=r"))]
7282   "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
7283   "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
7284   [(set_attr "conds" "set")
7285    (set_attr "length" "8")]
7286 )
7287
7288 (define_insn "*arm_cmpdi_unsigned"
7289   [(set (reg:CC_CZ CC_REGNUM)
7290         (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "r")
7291                        (match_operand:DI 1 "arm_di_operand"     "rDi")))]
7292   "TARGET_ARM"
7293   "cmp%?\\t%R0, %R1\;cmpeq\\t%Q0, %Q1"
7294   [(set_attr "conds" "set")
7295    (set_attr "length" "8")]
7296 )
7297
7298 (define_insn "*arm_cmpdi_zero"
7299   [(set (reg:CC_Z CC_REGNUM)
7300         (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
7301                       (const_int 0)))
7302    (clobber (match_scratch:SI 1 "=r"))]
7303   "TARGET_32BIT"
7304   "orr%.\\t%1, %Q0, %R0"
7305   [(set_attr "conds" "set")]
7306 )
7307
7308 (define_insn "*thumb_cmpdi_zero"
7309   [(set (reg:CC_Z CC_REGNUM)
7310         (compare:CC_Z (match_operand:DI 0 "s_register_operand" "l")
7311                       (const_int 0)))
7312    (clobber (match_scratch:SI 1 "=l"))]
7313   "TARGET_THUMB1"
7314   "orr\\t%1, %Q0, %R0"
7315   [(set_attr "conds" "set")
7316    (set_attr "length" "2")]
7317 )
7318
7319 ;; Cirrus SF compare instruction
7320 (define_insn "*cirrus_cmpsf"
7321   [(set (reg:CCFP CC_REGNUM)
7322         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
7323                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
7324   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7325   "cfcmps%?\\tr15, %V0, %V1"
7326   [(set_attr "type"   "mav_farith")
7327    (set_attr "cirrus" "compare")]
7328 )
7329
7330 ;; Cirrus DF compare instruction
7331 (define_insn "*cirrus_cmpdf"
7332   [(set (reg:CCFP CC_REGNUM)
7333         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
7334                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
7335   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7336   "cfcmpd%?\\tr15, %V0, %V1"
7337   [(set_attr "type"   "mav_farith")
7338    (set_attr "cirrus" "compare")]
7339 )
7340
7341 (define_insn "*cirrus_cmpdi"
7342   [(set (reg:CC CC_REGNUM)
7343         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
7344                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
7345   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7346   "cfcmp64%?\\tr15, %V0, %V1"
7347   [(set_attr "type"   "mav_farith")
7348    (set_attr "cirrus" "compare")]
7349 )
7350
7351 ; This insn allows redundant compares to be removed by cse, nothing should
7352 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7353 ; is deleted later on. The match_dup will match the mode here, so that
7354 ; mode changes of the condition codes aren't lost by this even though we don't
7355 ; specify what they are.
7356
7357 (define_insn "*deleted_compare"
7358   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
7359   "TARGET_32BIT"
7360   "\\t%@ deleted compare"
7361   [(set_attr "conds" "set")
7362    (set_attr "length" "0")]
7363 )
7364
7365 \f
7366 ;; Conditional branch insns
7367
7368 (define_expand "cbranch_cc"
7369   [(set (pc)
7370         (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7371                                             (match_operand 2 "" "")])
7372                       (label_ref (match_operand 3 "" ""))
7373                       (pc)))]
7374   "TARGET_32BIT"
7375   "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
7376                                       operands[1], operands[2]);
7377    operands[2] = const0_rtx;"
7378 )
7379
7380 ;;
7381 ;; Patterns to match conditional branch insns.
7382 ;;
7383
7384 (define_insn "*arm_cond_branch"
7385   [(set (pc)
7386         (if_then_else (match_operator 1 "arm_comparison_operator"
7387                        [(match_operand 2 "cc_register" "") (const_int 0)])
7388                       (label_ref (match_operand 0 "" ""))
7389                       (pc)))]
7390   "TARGET_32BIT"
7391   "*
7392   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7393     {
7394       arm_ccfsm_state += 2;
7395       return \"\";
7396     }
7397   return \"b%d1\\t%l0\";
7398   "
7399   [(set_attr "conds" "use")
7400    (set_attr "type" "branch")
7401    (set (attr "length")
7402         (if_then_else
7403            (and (ne (symbol_ref "TARGET_THUMB2") (const_int 0))
7404                 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7405                      (le (minus (match_dup 0) (pc)) (const_int 256))))
7406            (const_int 2)
7407            (const_int 4)))]
7408 )
7409
7410 (define_insn "*arm_cond_branch_reversed"
7411   [(set (pc)
7412         (if_then_else (match_operator 1 "arm_comparison_operator"
7413                        [(match_operand 2 "cc_register" "") (const_int 0)])
7414                       (pc)
7415                       (label_ref (match_operand 0 "" ""))))]
7416   "TARGET_32BIT"
7417   "*
7418   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7419     {
7420       arm_ccfsm_state += 2;
7421       return \"\";
7422     }
7423   return \"b%D1\\t%l0\";
7424   "
7425   [(set_attr "conds" "use")
7426    (set_attr "type" "branch")
7427    (set (attr "length")
7428         (if_then_else
7429            (and (ne (symbol_ref "TARGET_THUMB2") (const_int 0))
7430                 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7431                      (le (minus (match_dup 0) (pc)) (const_int 256))))
7432            (const_int 2)
7433            (const_int 4)))]
7434 )
7435
7436 \f
7437
7438 ; scc insns
7439
7440 (define_expand "cstore_cc"
7441   [(set (match_operand:SI 0 "s_register_operand" "")
7442         (match_operator:SI 1 "" [(match_operand 2 "" "")
7443                                  (match_operand 3 "" "")]))]
7444   "TARGET_32BIT"
7445   "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
7446                                       operands[2], operands[3]);
7447    operands[3] = const0_rtx;"
7448 )
7449
7450 (define_insn "*mov_scc"
7451   [(set (match_operand:SI 0 "s_register_operand" "=r")
7452         (match_operator:SI 1 "arm_comparison_operator"
7453          [(match_operand 2 "cc_register" "") (const_int 0)]))]
7454   "TARGET_ARM"
7455   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7456   [(set_attr "conds" "use")
7457    (set_attr "insn" "mov")
7458    (set_attr "length" "8")]
7459 )
7460
7461 (define_insn "*mov_negscc"
7462   [(set (match_operand:SI 0 "s_register_operand" "=r")
7463         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7464                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7465   "TARGET_ARM"
7466   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7467   [(set_attr "conds" "use")
7468    (set_attr "insn" "mov")
7469    (set_attr "length" "8")]
7470 )
7471
7472 (define_insn "*mov_notscc"
7473   [(set (match_operand:SI 0 "s_register_operand" "=r")
7474         (not:SI (match_operator:SI 1 "arm_comparison_operator"
7475                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7476   "TARGET_ARM"
7477   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7478   [(set_attr "conds" "use")
7479    (set_attr "insn" "mov")
7480    (set_attr "length" "8")]
7481 )
7482
7483 (define_expand "cstoresi4"
7484   [(set (match_operand:SI 0 "s_register_operand" "")
7485         (match_operator:SI 1 "arm_comparison_operator"
7486          [(match_operand:SI 2 "s_register_operand" "")
7487           (match_operand:SI 3 "reg_or_int_operand" "")]))]
7488   "TARGET_32BIT || TARGET_THUMB1"
7489   "{
7490   rtx op3, scratch, scratch2;
7491
7492   if (!TARGET_THUMB1)
7493     {
7494       if (!arm_add_operand (operands[3], SImode))
7495         operands[3] = force_reg (SImode, operands[3]);
7496       emit_insn (gen_cstore_cc (operands[0], operands[1],
7497                                 operands[2], operands[3]));
7498       DONE;
7499     }
7500
7501   if (operands[3] == const0_rtx)
7502     {
7503       switch (GET_CODE (operands[1]))
7504         {
7505         case EQ:
7506           emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
7507           break;
7508
7509         case NE:
7510           emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
7511           break;
7512
7513         case LE:
7514           scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7515                                   NULL_RTX, 0, OPTAB_WIDEN);
7516           scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7517                                   NULL_RTX, 0, OPTAB_WIDEN);
7518           expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7519                         operands[0], 1, OPTAB_WIDEN);
7520           break;
7521
7522         case GE:
7523           scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7524                                  NULL_RTX, 1);
7525           expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7526                         NULL_RTX, 1, OPTAB_WIDEN);
7527           break;
7528
7529         case GT:
7530           scratch = expand_binop (SImode, ashr_optab, operands[2],
7531                                   GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7532           scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7533                                   NULL_RTX, 0, OPTAB_WIDEN);
7534           expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7535                         0, OPTAB_WIDEN);
7536           break;
7537
7538         /* LT is handled by generic code.  No need for unsigned with 0.  */
7539         default:
7540           FAIL;
7541         }
7542       DONE;
7543     }
7544
7545   switch (GET_CODE (operands[1]))
7546     {
7547     case EQ:
7548       scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7549                               NULL_RTX, 0, OPTAB_WIDEN);
7550       emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
7551       break;
7552
7553     case NE:
7554       scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7555                               NULL_RTX, 0, OPTAB_WIDEN);
7556       emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
7557       break;
7558
7559     case LE:
7560       op3 = force_reg (SImode, operands[3]);
7561
7562       scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7563                               NULL_RTX, 1, OPTAB_WIDEN);
7564       scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7565                               NULL_RTX, 0, OPTAB_WIDEN);
7566       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
7567                                           op3, operands[2]));
7568       break;
7569
7570     case GE:
7571       op3 = operands[3];
7572       if (!thumb1_cmp_operand (op3, SImode))
7573         op3 = force_reg (SImode, op3);
7574       scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7575                               NULL_RTX, 0, OPTAB_WIDEN);
7576       scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7577                                NULL_RTX, 1, OPTAB_WIDEN);
7578       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
7579                                           operands[2], op3));
7580       break;
7581
7582     case LEU:
7583       op3 = force_reg (SImode, operands[3]);
7584       scratch = force_reg (SImode, const0_rtx);
7585       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
7586                                           op3, operands[2]));
7587       break;
7588
7589     case GEU:
7590       op3 = operands[3];
7591       if (!thumb1_cmp_operand (op3, SImode))
7592         op3 = force_reg (SImode, op3);
7593       scratch = force_reg (SImode, const0_rtx);
7594       emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
7595                                           operands[2], op3));
7596       break;
7597
7598     case LTU:
7599       op3 = operands[3];
7600       if (!thumb1_cmp_operand (op3, SImode))
7601         op3 = force_reg (SImode, op3);
7602       scratch = gen_reg_rtx (SImode);
7603       emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
7604       break;
7605
7606     case GTU:
7607       op3 = force_reg (SImode, operands[3]);
7608       scratch = gen_reg_rtx (SImode);
7609       emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
7610       break;
7611
7612     /* No good sequences for GT, LT.  */
7613     default:
7614       FAIL;
7615     }
7616   DONE;
7617 }")
7618
7619 (define_expand "cstoresf4"
7620   [(set (match_operand:SI 0 "s_register_operand" "")
7621         (match_operator:SI 1 "arm_comparison_operator"
7622          [(match_operand:SF 2 "s_register_operand" "")
7623           (match_operand:SF 3 "arm_float_compare_operand" "")]))]
7624   "TARGET_32BIT && TARGET_HARD_FLOAT"
7625   "emit_insn (gen_cstore_cc (operands[0], operands[1],
7626                              operands[2], operands[3])); DONE;"
7627 )
7628
7629 (define_expand "cstoredf4"
7630   [(set (match_operand:SI 0 "s_register_operand" "")
7631         (match_operator:SI 1 "arm_comparison_operator"
7632          [(match_operand:DF 2 "s_register_operand" "")
7633           (match_operand:DF 3 "arm_float_compare_operand" "")]))]
7634   "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
7635   "emit_insn (gen_cstore_cc (operands[0], operands[1],
7636                              operands[2], operands[3])); DONE;"
7637 )
7638
7639 (define_expand "cstoredi4"
7640   [(set (match_operand:SI 0 "s_register_operand" "")
7641         (match_operator:SI 1 "arm_comparison_operator"
7642          [(match_operand:DI 2 "cmpdi_operand" "")
7643           (match_operand:DI 3 "cmpdi_operand" "")]))]
7644   "TARGET_32BIT"
7645   "{
7646      rtx swap = NULL_RTX;
7647      enum rtx_code code = GET_CODE (operands[1]);
7648
7649      /* We should not have two constants.  */
7650      gcc_assert (GET_MODE (operands[2]) == DImode
7651                  || GET_MODE (operands[3]) == DImode);
7652
7653     /* Flip unimplemented DImode comparisons to a form that
7654        arm_gen_compare_reg can handle.  */
7655      switch (code)
7656      {
7657      case GT:
7658        swap = gen_rtx_LT (VOIDmode, operands[3], operands[2]); break;
7659      case LE:
7660        swap = gen_rtx_GE (VOIDmode, operands[3], operands[2]); break;
7661      case GTU:
7662        swap = gen_rtx_LTU (VOIDmode, operands[3], operands[2]); break;
7663      case LEU:
7664        swap = gen_rtx_GEU (VOIDmode, operands[3], operands[2]); break;
7665      default:
7666        break;
7667      }
7668      if (swap)
7669        emit_insn (gen_cstore_cc (operands[0], swap, operands[3],
7670                                  operands[2]));
7671      else
7672        emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
7673                                  operands[3]));
7674      DONE;
7675    }"
7676 )
7677
7678 (define_expand "cstoresi_eq0_thumb1"
7679   [(parallel
7680     [(set (match_operand:SI 0 "s_register_operand" "")
7681           (eq:SI (match_operand:SI 1 "s_register_operand" "")
7682                  (const_int 0)))
7683      (clobber (match_dup:SI 2))])]
7684   "TARGET_THUMB1"
7685   "operands[2] = gen_reg_rtx (SImode);"
7686 )
7687
7688 (define_expand "cstoresi_ne0_thumb1"
7689   [(parallel
7690     [(set (match_operand:SI 0 "s_register_operand" "")
7691           (ne:SI (match_operand:SI 1 "s_register_operand" "")
7692                  (const_int 0)))
7693      (clobber (match_dup:SI 2))])]
7694   "TARGET_THUMB1"
7695   "operands[2] = gen_reg_rtx (SImode);"
7696 )
7697
7698 (define_insn "*cstoresi_eq0_thumb1_insn"
7699   [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
7700         (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
7701                (const_int 0)))
7702    (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
7703   "TARGET_THUMB1"
7704   "@
7705    neg\\t%0, %1\;adc\\t%0, %0, %1
7706    neg\\t%2, %1\;adc\\t%0, %1, %2"
7707   [(set_attr "length" "4")]
7708 )
7709
7710 (define_insn "*cstoresi_ne0_thumb1_insn"
7711   [(set (match_operand:SI 0 "s_register_operand" "=l")
7712         (ne:SI (match_operand:SI 1 "s_register_operand" "0")
7713                (const_int 0)))
7714    (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
7715   "TARGET_THUMB1"
7716   "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
7717   [(set_attr "length" "4")]
7718 )
7719
7720 ;; Used as part of the expansion of thumb ltu and gtu sequences
7721 (define_insn "cstoresi_nltu_thumb1"
7722   [(set (match_operand:SI 0 "s_register_operand" "=l,l")
7723         (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
7724                         (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
7725   "TARGET_THUMB1"
7726   "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
7727   [(set_attr "length" "4")]
7728 )
7729
7730 (define_insn_and_split "cstoresi_ltu_thumb1"
7731   [(set (match_operand:SI 0 "s_register_operand" "=l,l")
7732         (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
7733                 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")))]
7734   "TARGET_THUMB1"
7735   "#"
7736   "TARGET_THUMB1"
7737   [(set (match_dup 3)
7738         (neg:SI (ltu:SI (match_dup 1) (match_dup 2))))
7739    (set (match_dup 0) (neg:SI (match_dup 3)))]
7740   "operands[3] = gen_reg_rtx (SImode);"
7741   [(set_attr "length" "4")]
7742 )
7743
7744 ;; Used as part of the expansion of thumb les sequence.
7745 (define_insn "thumb1_addsi3_addgeu"
7746   [(set (match_operand:SI 0 "s_register_operand" "=l")
7747         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7748                           (match_operand:SI 2 "s_register_operand" "l"))
7749                  (geu:SI (match_operand:SI 3 "s_register_operand" "l")
7750                          (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
7751   "TARGET_THUMB1"
7752   "cmp\\t%3, %4\;adc\\t%0, %1, %2"
7753   [(set_attr "length" "4")]
7754 )
7755
7756 \f
7757 ;; Conditional move insns
7758
7759 (define_expand "movsicc"
7760   [(set (match_operand:SI 0 "s_register_operand" "")
7761         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7762                          (match_operand:SI 2 "arm_not_operand" "")
7763                          (match_operand:SI 3 "arm_not_operand" "")))]
7764   "TARGET_32BIT"
7765   "
7766   {
7767     enum rtx_code code = GET_CODE (operands[1]);
7768     rtx ccreg;
7769
7770     if (code == UNEQ || code == LTGT)
7771       FAIL;
7772
7773     ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7774                                  XEXP (operands[1], 1));
7775     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7776   }"
7777 )
7778
7779 (define_expand "movsfcc"
7780   [(set (match_operand:SF 0 "s_register_operand" "")
7781         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7782                          (match_operand:SF 2 "s_register_operand" "")
7783                          (match_operand:SF 3 "nonmemory_operand" "")))]
7784   "TARGET_32BIT && TARGET_HARD_FLOAT"
7785   "
7786   {
7787     enum rtx_code code = GET_CODE (operands[1]);
7788     rtx ccreg;
7789
7790     if (code == UNEQ || code == LTGT)
7791       FAIL;
7792
7793     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
7794        Otherwise, ensure it is a valid FP add operand */
7795     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7796         || (!arm_float_add_operand (operands[3], SFmode)))
7797       operands[3] = force_reg (SFmode, operands[3]);
7798
7799     ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7800                                  XEXP (operands[1], 1));
7801     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7802   }"
7803 )
7804
7805 (define_expand "movdfcc"
7806   [(set (match_operand:DF 0 "s_register_operand" "")
7807         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7808                          (match_operand:DF 2 "s_register_operand" "")
7809                          (match_operand:DF 3 "arm_float_add_operand" "")))]
7810   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
7811   "
7812   {
7813     enum rtx_code code = GET_CODE (operands[1]);
7814     rtx ccreg;
7815
7816     if (code == UNEQ || code == LTGT)
7817       FAIL;
7818
7819     ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7820                                  XEXP (operands[1], 1));
7821     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7822   }"
7823 )
7824
7825 (define_insn "*movsicc_insn"
7826   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7827         (if_then_else:SI
7828          (match_operator 3 "arm_comparison_operator"
7829           [(match_operand 4 "cc_register" "") (const_int 0)])
7830          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7831          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7832   "TARGET_ARM"
7833   "@
7834    mov%D3\\t%0, %2
7835    mvn%D3\\t%0, #%B2
7836    mov%d3\\t%0, %1
7837    mvn%d3\\t%0, #%B1
7838    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7839    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7840    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7841    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7842   [(set_attr "length" "4,4,4,4,8,8,8,8")
7843    (set_attr "conds" "use")
7844    (set_attr "insn" "mov,mvn,mov,mvn,mov,mov,mvn,mvn")]
7845 )
7846
7847 (define_insn "*movsfcc_soft_insn"
7848   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7849         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7850                           [(match_operand 4 "cc_register" "") (const_int 0)])
7851                          (match_operand:SF 1 "s_register_operand" "0,r")
7852                          (match_operand:SF 2 "s_register_operand" "r,0")))]
7853   "TARGET_ARM && TARGET_SOFT_FLOAT"
7854   "@
7855    mov%D3\\t%0, %2
7856    mov%d3\\t%0, %1"
7857   [(set_attr "conds" "use")
7858    (set_attr "insn" "mov")]
7859 )
7860
7861 \f
7862 ;; Jump and linkage insns
7863
7864 (define_expand "jump"
7865   [(set (pc)
7866         (label_ref (match_operand 0 "" "")))]
7867   "TARGET_EITHER"
7868   ""
7869 )
7870
7871 (define_insn "*arm_jump"
7872   [(set (pc)
7873         (label_ref (match_operand 0 "" "")))]
7874   "TARGET_32BIT"
7875   "*
7876   {
7877     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7878       {
7879         arm_ccfsm_state += 2;
7880         return \"\";
7881       }
7882     return \"b%?\\t%l0\";
7883   }
7884   "
7885   [(set_attr "predicable" "yes")
7886    (set (attr "length")
7887         (if_then_else
7888            (and (ne (symbol_ref "TARGET_THUMB2") (const_int 0))
7889                 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7890                      (le (minus (match_dup 0) (pc)) (const_int 2048))))
7891            (const_int 2)
7892            (const_int 4)))]
7893 )
7894
7895 (define_insn "*thumb_jump"
7896   [(set (pc)
7897         (label_ref (match_operand 0 "" "")))]
7898   "TARGET_THUMB1"
7899   "*
7900   if (get_attr_length (insn) == 2)
7901     return \"b\\t%l0\";
7902   return \"bl\\t%l0\\t%@ far jump\";
7903   "
7904   [(set (attr "far_jump")
7905         (if_then_else
7906             (eq_attr "length" "4")
7907             (const_string "yes")
7908             (const_string "no")))
7909    (set (attr "length") 
7910         (if_then_else
7911             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7912                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
7913             (const_int 2)
7914             (const_int 4)))]
7915 )
7916
7917 (define_expand "call"
7918   [(parallel [(call (match_operand 0 "memory_operand" "")
7919                     (match_operand 1 "general_operand" ""))
7920               (use (match_operand 2 "" ""))
7921               (clobber (reg:SI LR_REGNUM))])]
7922   "TARGET_EITHER"
7923   "
7924   {
7925     rtx callee, pat;
7926     
7927     /* In an untyped call, we can get NULL for operand 2.  */
7928     if (operands[2] == NULL_RTX)
7929       operands[2] = const0_rtx;
7930       
7931     /* Decide if we should generate indirect calls by loading the
7932        32-bit address of the callee into a register before performing the
7933        branch and link.  */
7934     callee = XEXP (operands[0], 0);
7935     if (GET_CODE (callee) == SYMBOL_REF
7936         ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7937         : !REG_P (callee))
7938       XEXP (operands[0], 0) = force_reg (Pmode, callee);
7939
7940     pat = gen_call_internal (operands[0], operands[1], operands[2]);
7941     arm_emit_call_insn (pat, XEXP (operands[0], 0));
7942     DONE;
7943   }"
7944 )
7945
7946 (define_expand "call_internal"
7947   [(parallel [(call (match_operand 0 "memory_operand" "")
7948                     (match_operand 1 "general_operand" ""))
7949               (use (match_operand 2 "" ""))
7950               (clobber (reg:SI LR_REGNUM))])])
7951
7952 (define_insn "*call_reg_armv5"
7953   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7954          (match_operand 1 "" ""))
7955    (use (match_operand 2 "" ""))
7956    (clobber (reg:SI LR_REGNUM))]
7957   "TARGET_ARM && arm_arch5"
7958   "blx%?\\t%0"
7959   [(set_attr "type" "call")]
7960 )
7961
7962 (define_insn "*call_reg_arm"
7963   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7964          (match_operand 1 "" ""))
7965    (use (match_operand 2 "" ""))
7966    (clobber (reg:SI LR_REGNUM))]
7967   "TARGET_ARM && !arm_arch5"
7968   "*
7969   return output_call (operands);
7970   "
7971   ;; length is worst case, normally it is only two
7972   [(set_attr "length" "12")
7973    (set_attr "type" "call")]
7974 )
7975
7976
7977 ;; Note: not used for armv5+ because the sequence used (ldr pc, ...) is not
7978 ;; considered a function call by the branch predictor of some cores (PR40887).
7979 ;; Falls back to blx rN (*call_reg_armv5).
7980
7981 (define_insn "*call_mem"
7982   [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
7983          (match_operand 1 "" ""))
7984    (use (match_operand 2 "" ""))
7985    (clobber (reg:SI LR_REGNUM))]
7986   "TARGET_ARM && !arm_arch5"
7987   "*
7988   return output_call_mem (operands);
7989   "
7990   [(set_attr "length" "12")
7991    (set_attr "type" "call")]
7992 )
7993
7994 (define_insn "*call_reg_thumb1_v5"
7995   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7996          (match_operand 1 "" ""))
7997    (use (match_operand 2 "" ""))
7998    (clobber (reg:SI LR_REGNUM))]
7999   "TARGET_THUMB1 && arm_arch5"
8000   "blx\\t%0"
8001   [(set_attr "length" "2")
8002    (set_attr "type" "call")]
8003 )
8004
8005 (define_insn "*call_reg_thumb1"
8006   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8007          (match_operand 1 "" ""))
8008    (use (match_operand 2 "" ""))
8009    (clobber (reg:SI LR_REGNUM))]
8010   "TARGET_THUMB1 && !arm_arch5"
8011   "*
8012   {
8013     if (!TARGET_CALLER_INTERWORKING)
8014       return thumb_call_via_reg (operands[0]);
8015     else if (operands[1] == const0_rtx)
8016       return \"bl\\t%__interwork_call_via_%0\";
8017     else if (frame_pointer_needed)
8018       return \"bl\\t%__interwork_r7_call_via_%0\";
8019     else
8020       return \"bl\\t%__interwork_r11_call_via_%0\";
8021   }"
8022   [(set_attr "type" "call")]
8023 )
8024
8025 (define_expand "call_value"
8026   [(parallel [(set (match_operand       0 "" "")
8027                    (call (match_operand 1 "memory_operand" "")
8028                          (match_operand 2 "general_operand" "")))
8029               (use (match_operand 3 "" ""))
8030               (clobber (reg:SI LR_REGNUM))])]
8031   "TARGET_EITHER"
8032   "
8033   {
8034     rtx pat, callee;
8035     
8036     /* In an untyped call, we can get NULL for operand 2.  */
8037     if (operands[3] == 0)
8038       operands[3] = const0_rtx;
8039       
8040     /* Decide if we should generate indirect calls by loading the
8041        32-bit address of the callee into a register before performing the
8042        branch and link.  */
8043     callee = XEXP (operands[1], 0);
8044     if (GET_CODE (callee) == SYMBOL_REF
8045         ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8046         : !REG_P (callee))
8047       XEXP (operands[1], 0) = force_reg (Pmode, callee);
8048
8049     pat = gen_call_value_internal (operands[0], operands[1],
8050                                    operands[2], operands[3]);
8051     arm_emit_call_insn (pat, XEXP (operands[1], 0));
8052     DONE;
8053   }"
8054 )
8055
8056 (define_expand "call_value_internal"
8057   [(parallel [(set (match_operand       0 "" "")
8058                    (call (match_operand 1 "memory_operand" "")
8059                          (match_operand 2 "general_operand" "")))
8060               (use (match_operand 3 "" ""))
8061               (clobber (reg:SI LR_REGNUM))])])
8062
8063 (define_insn "*call_value_reg_armv5"
8064   [(set (match_operand 0 "" "")
8065         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8066               (match_operand 2 "" "")))
8067    (use (match_operand 3 "" ""))
8068    (clobber (reg:SI LR_REGNUM))]
8069   "TARGET_ARM && arm_arch5"
8070   "blx%?\\t%1"
8071   [(set_attr "type" "call")]
8072 )
8073
8074 (define_insn "*call_value_reg_arm"
8075   [(set (match_operand 0 "" "")
8076         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8077               (match_operand 2 "" "")))
8078    (use (match_operand 3 "" ""))
8079    (clobber (reg:SI LR_REGNUM))]
8080   "TARGET_ARM && !arm_arch5"
8081   "*
8082   return output_call (&operands[1]);
8083   "
8084   [(set_attr "length" "12")
8085    (set_attr "type" "call")]
8086 )
8087
8088 ;; Note: see *call_mem
8089
8090 (define_insn "*call_value_mem"
8091   [(set (match_operand 0 "" "")
8092         (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
8093               (match_operand 2 "" "")))
8094    (use (match_operand 3 "" ""))
8095    (clobber (reg:SI LR_REGNUM))]
8096   "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
8097   "*
8098   return output_call_mem (&operands[1]);
8099   "
8100   [(set_attr "length" "12")
8101    (set_attr "type" "call")]
8102 )
8103
8104 (define_insn "*call_value_reg_thumb1_v5"
8105   [(set (match_operand 0 "" "")
8106         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8107               (match_operand 2 "" "")))
8108    (use (match_operand 3 "" ""))
8109    (clobber (reg:SI LR_REGNUM))]
8110   "TARGET_THUMB1 && arm_arch5"
8111   "blx\\t%1"
8112   [(set_attr "length" "2")
8113    (set_attr "type" "call")]
8114 )
8115
8116 (define_insn "*call_value_reg_thumb1"
8117   [(set (match_operand 0 "" "")
8118         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8119               (match_operand 2 "" "")))
8120    (use (match_operand 3 "" ""))
8121    (clobber (reg:SI LR_REGNUM))]
8122   "TARGET_THUMB1 && !arm_arch5"
8123   "*
8124   {
8125     if (!TARGET_CALLER_INTERWORKING)
8126       return thumb_call_via_reg (operands[1]);
8127     else if (operands[2] == const0_rtx)
8128       return \"bl\\t%__interwork_call_via_%1\";
8129     else if (frame_pointer_needed)
8130       return \"bl\\t%__interwork_r7_call_via_%1\";
8131     else
8132       return \"bl\\t%__interwork_r11_call_via_%1\";
8133   }"
8134   [(set_attr "type" "call")]
8135 )
8136
8137 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8138 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8139
8140 (define_insn "*call_symbol"
8141   [(call (mem:SI (match_operand:SI 0 "" ""))
8142          (match_operand 1 "" ""))
8143    (use (match_operand 2 "" ""))
8144    (clobber (reg:SI LR_REGNUM))]
8145   "TARGET_32BIT
8146    && (GET_CODE (operands[0]) == SYMBOL_REF)
8147    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
8148   "*
8149   {
8150     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
8151   }"
8152   [(set_attr "type" "call")]
8153 )
8154
8155 (define_insn "*call_value_symbol"
8156   [(set (match_operand 0 "" "")
8157         (call (mem:SI (match_operand:SI 1 "" ""))
8158         (match_operand:SI 2 "" "")))
8159    (use (match_operand 3 "" ""))
8160    (clobber (reg:SI LR_REGNUM))]
8161   "TARGET_32BIT
8162    && (GET_CODE (operands[1]) == SYMBOL_REF)
8163    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
8164   "*
8165   {
8166     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
8167   }"
8168   [(set_attr "type" "call")]
8169 )
8170
8171 (define_insn "*call_insn"
8172   [(call (mem:SI (match_operand:SI 0 "" ""))
8173          (match_operand:SI 1 "" ""))
8174    (use (match_operand 2 "" ""))
8175    (clobber (reg:SI LR_REGNUM))]
8176   "TARGET_THUMB1
8177    && GET_CODE (operands[0]) == SYMBOL_REF
8178    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
8179   "bl\\t%a0"
8180   [(set_attr "length" "4")
8181    (set_attr "type" "call")]
8182 )
8183
8184 (define_insn "*call_value_insn"
8185   [(set (match_operand 0 "" "")
8186         (call (mem:SI (match_operand 1 "" ""))
8187               (match_operand 2 "" "")))
8188    (use (match_operand 3 "" ""))
8189    (clobber (reg:SI LR_REGNUM))]
8190   "TARGET_THUMB1
8191    && GET_CODE (operands[1]) == SYMBOL_REF
8192    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
8193   "bl\\t%a1"
8194   [(set_attr "length" "4")
8195    (set_attr "type" "call")]
8196 )
8197
8198 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
8199 (define_expand "sibcall"
8200   [(parallel [(call (match_operand 0 "memory_operand" "")
8201                     (match_operand 1 "general_operand" ""))
8202               (return)
8203               (use (match_operand 2 "" ""))])]
8204   "TARGET_32BIT"
8205   "
8206   {
8207     if (operands[2] == NULL_RTX)
8208       operands[2] = const0_rtx;
8209   }"
8210 )
8211
8212 (define_expand "sibcall_value"
8213   [(parallel [(set (match_operand 0 "" "")
8214                    (call (match_operand 1 "memory_operand" "")
8215                          (match_operand 2 "general_operand" "")))
8216               (return)
8217               (use (match_operand 3 "" ""))])]
8218   "TARGET_32BIT"
8219   "
8220   {
8221     if (operands[3] == NULL_RTX)
8222       operands[3] = const0_rtx;
8223   }"
8224 )
8225
8226 (define_insn "*sibcall_insn"
8227  [(call (mem:SI (match_operand:SI 0 "" "X"))
8228         (match_operand 1 "" ""))
8229   (return)
8230   (use (match_operand 2 "" ""))]
8231   "TARGET_32BIT && GET_CODE (operands[0]) == SYMBOL_REF"
8232   "*
8233   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8234   "
8235   [(set_attr "type" "call")]
8236 )
8237
8238 (define_insn "*sibcall_value_insn"
8239  [(set (match_operand 0 "" "")
8240        (call (mem:SI (match_operand:SI 1 "" "X"))
8241              (match_operand 2 "" "")))
8242   (return)
8243   (use (match_operand 3 "" ""))]
8244   "TARGET_32BIT && GET_CODE (operands[1]) == SYMBOL_REF"
8245   "*
8246   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8247   "
8248   [(set_attr "type" "call")]
8249 )
8250
8251 (define_expand "return"
8252   [(return)]
8253   "TARGET_32BIT && USE_RETURN_INSN (FALSE)"
8254   "")
8255
8256 ;; Often the return insn will be the same as loading from memory, so set attr
8257 (define_insn "*arm_return"
8258   [(return)]
8259   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
8260   "*
8261   {
8262     if (arm_ccfsm_state == 2)
8263       {
8264         arm_ccfsm_state += 2;
8265         return \"\";
8266       }
8267     return output_return_instruction (const_true_rtx, TRUE, FALSE);
8268   }"
8269   [(set_attr "type" "load1")
8270    (set_attr "length" "12")
8271    (set_attr "predicable" "yes")]
8272 )
8273
8274 (define_insn "*cond_return"
8275   [(set (pc)
8276         (if_then_else (match_operator 0 "arm_comparison_operator"
8277                        [(match_operand 1 "cc_register" "") (const_int 0)])
8278                       (return)
8279                       (pc)))]
8280   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
8281   "*
8282   {
8283     if (arm_ccfsm_state == 2)
8284       {
8285         arm_ccfsm_state += 2;
8286         return \"\";
8287       }
8288     return output_return_instruction (operands[0], TRUE, FALSE);
8289   }"
8290   [(set_attr "conds" "use")
8291    (set_attr "length" "12")
8292    (set_attr "type" "load1")]
8293 )
8294
8295 (define_insn "*cond_return_inverted"
8296   [(set (pc)
8297         (if_then_else (match_operator 0 "arm_comparison_operator"
8298                        [(match_operand 1 "cc_register" "") (const_int 0)])
8299                       (pc)
8300                       (return)))]
8301   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
8302   "*
8303   {
8304     if (arm_ccfsm_state == 2)
8305       {
8306         arm_ccfsm_state += 2;
8307         return \"\";
8308       }
8309     return output_return_instruction (operands[0], TRUE, TRUE);
8310   }"
8311   [(set_attr "conds" "use")
8312    (set_attr "length" "12")
8313    (set_attr "type" "load1")]
8314 )
8315
8316 ;; Generate a sequence of instructions to determine if the processor is
8317 ;; in 26-bit or 32-bit mode, and return the appropriate return address
8318 ;; mask.
8319
8320 (define_expand "return_addr_mask"
8321   [(set (match_dup 1)
8322       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8323                        (const_int 0)))
8324    (set (match_operand:SI 0 "s_register_operand" "")
8325       (if_then_else:SI (eq (match_dup 1) (const_int 0))
8326                        (const_int -1)
8327                        (const_int 67108860)))] ; 0x03fffffc
8328   "TARGET_ARM"
8329   "
8330   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
8331   ")
8332
8333 (define_insn "*check_arch2"
8334   [(set (match_operand:CC_NOOV 0 "cc_register" "")
8335       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8336                        (const_int 0)))]
8337   "TARGET_ARM"
8338   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8339   [(set_attr "length" "8")
8340    (set_attr "conds" "set")]
8341 )
8342
8343 ;; Call subroutine returning any type.
8344
8345 (define_expand "untyped_call"
8346   [(parallel [(call (match_operand 0 "" "")
8347                     (const_int 0))
8348               (match_operand 1 "" "")
8349               (match_operand 2 "" "")])]
8350   "TARGET_EITHER"
8351   "
8352   {
8353     int i;
8354     rtx par = gen_rtx_PARALLEL (VOIDmode,
8355                                 rtvec_alloc (XVECLEN (operands[2], 0)));
8356     rtx addr = gen_reg_rtx (Pmode);
8357     rtx mem;
8358     int size = 0;
8359
8360     emit_move_insn (addr, XEXP (operands[1], 0));
8361     mem = change_address (operands[1], BLKmode, addr);
8362
8363     for (i = 0; i < XVECLEN (operands[2], 0); i++)
8364       {
8365         rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
8366
8367         /* Default code only uses r0 as a return value, but we could
8368            be using anything up to 4 registers.  */
8369         if (REGNO (src) == R0_REGNUM)
8370           src = gen_rtx_REG (TImode, R0_REGNUM);
8371
8372         XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8373                                                  GEN_INT (size));
8374         size += GET_MODE_SIZE (GET_MODE (src));
8375       }
8376
8377     emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8378                                     const0_rtx));
8379
8380     size = 0;
8381
8382     for (i = 0; i < XVECLEN (par, 0); i++)
8383       {
8384         HOST_WIDE_INT offset = 0;
8385         rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8386
8387         if (size != 0)
8388           emit_move_insn (addr, plus_constant (addr, size));
8389
8390         mem = change_address (mem, GET_MODE (reg), NULL);
8391         if (REGNO (reg) == R0_REGNUM)
8392           {
8393             /* On thumb we have to use a write-back instruction.  */
8394             emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8395                        TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8396             size = TARGET_ARM ? 16 : 0;
8397           }
8398         else
8399           {
8400             emit_move_insn (mem, reg);
8401             size = GET_MODE_SIZE (GET_MODE (reg));
8402           }
8403       }
8404
8405     /* The optimizer does not know that the call sets the function value
8406        registers we stored in the result block.  We avoid problems by
8407        claiming that all hard registers are used and clobbered at this
8408        point.  */
8409     emit_insn (gen_blockage ());
8410
8411     DONE;
8412   }"
8413 )
8414
8415 (define_expand "untyped_return"
8416   [(match_operand:BLK 0 "memory_operand" "")
8417    (match_operand 1 "" "")]
8418   "TARGET_EITHER"
8419   "
8420   {
8421     int i;
8422     rtx addr = gen_reg_rtx (Pmode);
8423     rtx mem;
8424     int size = 0;
8425
8426     emit_move_insn (addr, XEXP (operands[0], 0));
8427     mem = change_address (operands[0], BLKmode, addr);
8428
8429     for (i = 0; i < XVECLEN (operands[1], 0); i++)
8430       {
8431         HOST_WIDE_INT offset = 0;
8432         rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8433
8434         if (size != 0)
8435           emit_move_insn (addr, plus_constant (addr, size));
8436
8437         mem = change_address (mem, GET_MODE (reg), NULL);
8438         if (REGNO (reg) == R0_REGNUM)
8439           {
8440             /* On thumb we have to use a write-back instruction.  */
8441             emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8442                        TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8443             size = TARGET_ARM ? 16 : 0;
8444           }
8445         else
8446           {
8447             emit_move_insn (reg, mem);
8448             size = GET_MODE_SIZE (GET_MODE (reg));
8449           }
8450       }
8451
8452     /* Emit USE insns before the return.  */
8453     for (i = 0; i < XVECLEN (operands[1], 0); i++)
8454       emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
8455
8456     /* Construct the return.  */
8457     expand_naked_return ();
8458
8459     DONE;
8460   }"
8461 )
8462
8463 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8464 ;; all of memory.  This blocks insns from being moved across this point.
8465
8466 (define_insn "blockage"
8467   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
8468   "TARGET_EITHER"
8469   ""
8470   [(set_attr "length" "0")
8471    (set_attr "type" "block")]
8472 )
8473
8474 (define_expand "casesi"
8475   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
8476    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
8477    (match_operand:SI 2 "const_int_operand" "")  ; total range
8478    (match_operand:SI 3 "" "")                   ; table label
8479    (match_operand:SI 4 "" "")]                  ; Out of range label
8480   "TARGET_32BIT || optimize_size || flag_pic"
8481   "
8482   {
8483     enum insn_code code;
8484     if (operands[1] != const0_rtx)
8485       {
8486         rtx reg = gen_reg_rtx (SImode);
8487
8488         emit_insn (gen_addsi3 (reg, operands[0],
8489                                gen_int_mode (-INTVAL (operands[1]),
8490                                              SImode)));
8491         operands[0] = reg;
8492       }
8493
8494     if (TARGET_ARM)
8495       code = CODE_FOR_arm_casesi_internal;
8496     else if (TARGET_THUMB1)
8497       code = CODE_FOR_thumb1_casesi_internal_pic;
8498     else if (flag_pic)
8499       code = CODE_FOR_thumb2_casesi_internal_pic;
8500     else
8501       code = CODE_FOR_thumb2_casesi_internal;
8502
8503     if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8504       operands[2] = force_reg (SImode, operands[2]);
8505
8506     emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8507                                           operands[3], operands[4]));
8508     DONE;
8509   }"
8510 )
8511
8512 ;; The USE in this pattern is needed to tell flow analysis that this is
8513 ;; a CASESI insn.  It has no other purpose.
8514 (define_insn "arm_casesi_internal"
8515   [(parallel [(set (pc)
8516                (if_then_else
8517                 (leu (match_operand:SI 0 "s_register_operand" "r")
8518                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
8519                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8520                                  (label_ref (match_operand 2 "" ""))))
8521                 (label_ref (match_operand 3 "" ""))))
8522               (clobber (reg:CC CC_REGNUM))
8523               (use (label_ref (match_dup 2)))])]
8524   "TARGET_ARM"
8525   "*
8526     if (flag_pic)
8527       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8528     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8529   "
8530   [(set_attr "conds" "clob")
8531    (set_attr "length" "12")]
8532 )
8533
8534 (define_expand "thumb1_casesi_internal_pic"
8535   [(match_operand:SI 0 "s_register_operand" "")
8536    (match_operand:SI 1 "thumb1_cmp_operand" "")
8537    (match_operand 2 "" "")
8538    (match_operand 3 "" "")]
8539   "TARGET_THUMB1"
8540   {
8541     rtx reg0;
8542     rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[1]);
8543     emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[1],
8544                                     operands[3]));
8545     reg0 = gen_rtx_REG (SImode, 0);
8546     emit_move_insn (reg0, operands[0]);
8547     emit_jump_insn (gen_thumb1_casesi_dispatch (operands[2]/*, operands[3]*/));
8548     DONE;
8549   }
8550 )
8551
8552 (define_insn "thumb1_casesi_dispatch"
8553   [(parallel [(set (pc) (unspec [(reg:SI 0)
8554                                  (label_ref (match_operand 0 "" ""))
8555 ;;                               (label_ref (match_operand 1 "" ""))
8556 ]
8557                          UNSPEC_THUMB1_CASESI))
8558               (clobber (reg:SI IP_REGNUM))
8559               (clobber (reg:SI LR_REGNUM))])]
8560   "TARGET_THUMB1"
8561   "* return thumb1_output_casesi(operands);"
8562   [(set_attr "length" "4")]
8563 )
8564
8565 (define_expand "indirect_jump"
8566   [(set (pc)
8567         (match_operand:SI 0 "s_register_operand" ""))]
8568   "TARGET_EITHER"
8569   "
8570   /* Thumb-2 doesn't have mov pc, reg.  Explicitly set the low bit of the
8571      address and use bx.  */
8572   if (TARGET_THUMB2)
8573     {
8574       rtx tmp;
8575       tmp = gen_reg_rtx (SImode);
8576       emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8577       operands[0] = tmp;
8578     }
8579   "
8580 )
8581
8582 ;; NB Never uses BX.
8583 (define_insn "*arm_indirect_jump"
8584   [(set (pc)
8585         (match_operand:SI 0 "s_register_operand" "r"))]
8586   "TARGET_ARM"
8587   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
8588   [(set_attr "predicable" "yes")]
8589 )
8590
8591 (define_insn "*load_indirect_jump"
8592   [(set (pc)
8593         (match_operand:SI 0 "memory_operand" "m"))]
8594   "TARGET_ARM"
8595   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
8596   [(set_attr "type" "load1")
8597    (set_attr "pool_range" "4096")
8598    (set_attr "neg_pool_range" "4084")
8599    (set_attr "predicable" "yes")]
8600 )
8601
8602 ;; NB Never uses BX.
8603 (define_insn "*thumb1_indirect_jump"
8604   [(set (pc)
8605         (match_operand:SI 0 "register_operand" "l*r"))]
8606   "TARGET_THUMB1"
8607   "mov\\tpc, %0"
8608   [(set_attr "conds" "clob")
8609    (set_attr "length" "2")]
8610 )
8611
8612 \f
8613 ;; Misc insns
8614
8615 (define_insn "nop"
8616   [(const_int 0)]
8617   "TARGET_EITHER"
8618   "*
8619   if (TARGET_UNIFIED_ASM)
8620     return \"nop\";
8621   if (TARGET_ARM)
8622     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8623   return  \"mov\\tr8, r8\";
8624   "
8625   [(set (attr "length")
8626         (if_then_else (eq_attr "is_thumb" "yes")
8627                       (const_int 2)
8628                       (const_int 4)))]
8629 )
8630
8631 \f
8632 ;; Patterns to allow combination of arithmetic, cond code and shifts
8633
8634 (define_insn "*arith_shiftsi"
8635   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8636         (match_operator:SI 1 "shiftable_operator"
8637           [(match_operator:SI 3 "shift_operator"
8638              [(match_operand:SI 4 "s_register_operand" "r,r,r,r")
8639               (match_operand:SI 5 "shift_amount_operand" "M,M,M,r")])
8640            (match_operand:SI 2 "s_register_operand" "rk,rk,r,rk")]))]
8641   "TARGET_32BIT"
8642   "%i1%?\\t%0, %2, %4%S3"
8643   [(set_attr "predicable" "yes")
8644    (set_attr "shift" "4")
8645    (set_attr "arch" "a,t2,t2,a")
8646    ;; Thumb2 doesn't allow the stack pointer to be used for 
8647    ;; operand1 for all operations other than add and sub. In this case 
8648    ;; the minus operation is a candidate for an rsub and hence needs
8649    ;; to be disabled.
8650    ;; We have to make sure to disable the fourth alternative if
8651    ;; the shift_operator is MULT, since otherwise the insn will
8652    ;; also match a multiply_accumulate pattern and validate_change
8653    ;; will allow a replacement of the constant with a register
8654    ;; despite the checks done in shift_operator.
8655    (set_attr_alternative "insn_enabled"
8656                          [(const_string "yes")
8657                           (if_then_else
8658                            (match_operand:SI 1 "add_operator" "")
8659                            (const_string "yes") (const_string "no"))
8660                           (const_string "yes")
8661                           (if_then_else
8662                            (match_operand:SI 3 "mult_operator" "")
8663                            (const_string "no") (const_string "yes"))])
8664    (set_attr "type" "alu_shift,alu_shift,alu_shift,alu_shift_reg")])
8665
8666 (define_split
8667   [(set (match_operand:SI 0 "s_register_operand" "")
8668         (match_operator:SI 1 "shiftable_operator"
8669          [(match_operator:SI 2 "shiftable_operator"
8670            [(match_operator:SI 3 "shift_operator"
8671              [(match_operand:SI 4 "s_register_operand" "")
8672               (match_operand:SI 5 "reg_or_int_operand" "")])
8673             (match_operand:SI 6 "s_register_operand" "")])
8674           (match_operand:SI 7 "arm_rhs_operand" "")]))
8675    (clobber (match_operand:SI 8 "s_register_operand" ""))]
8676   "TARGET_32BIT"
8677   [(set (match_dup 8)
8678         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8679                          (match_dup 6)]))
8680    (set (match_dup 0)
8681         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8682   "")
8683
8684 (define_insn "*arith_shiftsi_compare0"
8685   [(set (reg:CC_NOOV CC_REGNUM)
8686         (compare:CC_NOOV
8687          (match_operator:SI 1 "shiftable_operator"
8688           [(match_operator:SI 3 "shift_operator"
8689             [(match_operand:SI 4 "s_register_operand" "r,r")
8690              (match_operand:SI 5 "shift_amount_operand" "M,r")])
8691            (match_operand:SI 2 "s_register_operand" "r,r")])
8692          (const_int 0)))
8693    (set (match_operand:SI 0 "s_register_operand" "=r,r")
8694         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8695                          (match_dup 2)]))]
8696   "TARGET_32BIT"
8697   "%i1%.\\t%0, %2, %4%S3"
8698   [(set_attr "conds" "set")
8699    (set_attr "shift" "4")
8700    (set_attr "arch" "32,a")
8701    (set_attr "type" "alu_shift,alu_shift_reg")])
8702
8703 (define_insn "*arith_shiftsi_compare0_scratch"
8704   [(set (reg:CC_NOOV CC_REGNUM)
8705         (compare:CC_NOOV
8706          (match_operator:SI 1 "shiftable_operator"
8707           [(match_operator:SI 3 "shift_operator"
8708             [(match_operand:SI 4 "s_register_operand" "r,r")
8709              (match_operand:SI 5 "shift_amount_operand" "M,r")])
8710            (match_operand:SI 2 "s_register_operand" "r,r")])
8711          (const_int 0)))
8712    (clobber (match_scratch:SI 0 "=r,r"))]
8713   "TARGET_32BIT"
8714   "%i1%.\\t%0, %2, %4%S3"
8715   [(set_attr "conds" "set")
8716    (set_attr "shift" "4")
8717    (set_attr "arch" "32,a")
8718    (set_attr "type" "alu_shift,alu_shift_reg")])
8719
8720 (define_insn "*sub_shiftsi"
8721   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8722         (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
8723                   (match_operator:SI 2 "shift_operator"
8724                    [(match_operand:SI 3 "s_register_operand" "r,r")
8725                     (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
8726   "TARGET_32BIT"
8727   "sub%?\\t%0, %1, %3%S2"
8728   [(set_attr "predicable" "yes")
8729    (set_attr "shift" "3")
8730    (set_attr "arch" "32,a")
8731    (set_attr "type" "alu_shift,alu_shift_reg")])
8732
8733 (define_insn "*sub_shiftsi_compare0"
8734   [(set (reg:CC_NOOV CC_REGNUM)
8735         (compare:CC_NOOV
8736          (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
8737                    (match_operator:SI 2 "shift_operator"
8738                     [(match_operand:SI 3 "s_register_operand" "r,r")
8739                      (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
8740          (const_int 0)))
8741    (set (match_operand:SI 0 "s_register_operand" "=r,r")
8742         (minus:SI (match_dup 1)
8743                   (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
8744   "TARGET_32BIT"
8745   "sub%.\\t%0, %1, %3%S2"
8746   [(set_attr "conds" "set")
8747    (set_attr "shift" "3")
8748    (set_attr "arch" "32,a")
8749    (set_attr "type" "alu_shift,alu_shift_reg")])
8750
8751 (define_insn "*sub_shiftsi_compare0_scratch"
8752   [(set (reg:CC_NOOV CC_REGNUM)
8753         (compare:CC_NOOV
8754          (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
8755                    (match_operator:SI 2 "shift_operator"
8756                     [(match_operand:SI 3 "s_register_operand" "r,r")
8757                      (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
8758          (const_int 0)))
8759    (clobber (match_scratch:SI 0 "=r,r"))]
8760   "TARGET_32BIT"
8761   "sub%.\\t%0, %1, %3%S2"
8762   [(set_attr "conds" "set")
8763    (set_attr "shift" "3")
8764    (set_attr "arch" "32,a")
8765    (set_attr "type" "alu_shift,alu_shift_reg")])
8766 \f
8767
8768 (define_insn "*and_scc"
8769   [(set (match_operand:SI 0 "s_register_operand" "=r")
8770         (and:SI (match_operator:SI 1 "arm_comparison_operator"
8771                  [(match_operand 3 "cc_register" "") (const_int 0)])
8772                 (match_operand:SI 2 "s_register_operand" "r")))]
8773   "TARGET_ARM"
8774   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8775   [(set_attr "conds" "use")
8776    (set_attr "insn" "mov")
8777    (set_attr "length" "8")]
8778 )
8779
8780 (define_insn "*ior_scc"
8781   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8782         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8783                  [(match_operand 3 "cc_register" "") (const_int 0)])
8784                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8785   "TARGET_ARM"
8786   "@
8787    orr%d2\\t%0, %1, #1
8788    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8789   [(set_attr "conds" "use")
8790    (set_attr "length" "4,8")]
8791 )
8792
8793 ; A series of splitters for the compare_scc pattern below.  Note that
8794 ; order is important.
8795 (define_split
8796   [(set (match_operand:SI 0 "s_register_operand" "")
8797         (lt:SI (match_operand:SI 1 "s_register_operand" "")
8798                (const_int 0)))
8799    (clobber (reg:CC CC_REGNUM))]
8800   "TARGET_32BIT && reload_completed"
8801   [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
8802
8803 (define_split
8804   [(set (match_operand:SI 0 "s_register_operand" "")
8805         (ge:SI (match_operand:SI 1 "s_register_operand" "")
8806                (const_int 0)))
8807    (clobber (reg:CC CC_REGNUM))]
8808   "TARGET_32BIT && reload_completed"
8809   [(set (match_dup 0) (not:SI (match_dup 1)))
8810    (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
8811
8812 (define_split
8813   [(set (match_operand:SI 0 "s_register_operand" "")
8814         (eq:SI (match_operand:SI 1 "s_register_operand" "")
8815                (const_int 0)))
8816    (clobber (reg:CC CC_REGNUM))]
8817   "TARGET_32BIT && reload_completed"
8818   [(parallel
8819     [(set (reg:CC CC_REGNUM)
8820           (compare:CC (const_int 1) (match_dup 1)))
8821      (set (match_dup 0)
8822           (minus:SI (const_int 1) (match_dup 1)))])
8823    (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
8824               (set (match_dup 0) (const_int 0)))])
8825
8826 (define_split
8827   [(set (match_operand:SI 0 "s_register_operand" "")
8828         (ne:SI (match_operand:SI 1 "s_register_operand" "")
8829                (match_operand:SI 2 "const_int_operand" "")))
8830    (clobber (reg:CC CC_REGNUM))]
8831   "TARGET_32BIT && reload_completed"
8832   [(parallel
8833     [(set (reg:CC CC_REGNUM)
8834           (compare:CC (match_dup 1) (match_dup 2)))
8835      (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
8836    (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
8837               (set (match_dup 0) (const_int 1)))]
8838 {
8839   operands[3] = GEN_INT (-INTVAL (operands[2]));
8840 })
8841
8842 (define_split
8843   [(set (match_operand:SI 0 "s_register_operand" "")
8844         (ne:SI (match_operand:SI 1 "s_register_operand" "")
8845                (match_operand:SI 2 "arm_add_operand" "")))
8846    (clobber (reg:CC CC_REGNUM))]
8847   "TARGET_32BIT && reload_completed"
8848   [(parallel
8849     [(set (reg:CC_NOOV CC_REGNUM)
8850           (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
8851                            (const_int 0)))
8852      (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
8853    (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
8854               (set (match_dup 0) (const_int 1)))])
8855
8856 (define_insn_and_split "*compare_scc"
8857   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8858         (match_operator:SI 1 "arm_comparison_operator"
8859          [(match_operand:SI 2 "s_register_operand" "r,r")
8860           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8861    (clobber (reg:CC CC_REGNUM))]
8862   "TARGET_32BIT"
8863   "#"
8864   "&& reload_completed"
8865   [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
8866    (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
8867    (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
8868 {
8869   rtx tmp1;
8870   enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8871                                            operands[2], operands[3]);
8872   enum rtx_code rc = GET_CODE (operands[1]);
8873
8874   tmp1 = gen_rtx_REG (mode, CC_REGNUM);
8875
8876   operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8877   if (mode == CCFPmode || mode == CCFPEmode)
8878     rc = reverse_condition_maybe_unordered (rc);
8879   else
8880     rc = reverse_condition (rc);
8881   operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8882 })
8883
8884 ;; Attempt to improve the sequence generated by the compare_scc splitters
8885 ;; not to use conditional execution.
8886 (define_peephole2
8887   [(set (reg:CC CC_REGNUM)
8888         (compare:CC (match_operand:SI 1 "register_operand" "")
8889                     (match_operand:SI 2 "arm_rhs_operand" "")))
8890    (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8891               (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8892    (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8893               (set (match_dup 0) (const_int 1)))
8894    (match_scratch:SI 3 "r")]
8895   "TARGET_32BIT"
8896   [(parallel
8897     [(set (reg:CC CC_REGNUM)
8898           (compare:CC (match_dup 1) (match_dup 2)))
8899      (set (match_dup 3) (minus:SI (match_dup 1) (match_dup 2)))])
8900    (parallel
8901     [(set (reg:CC CC_REGNUM)
8902           (compare:CC (const_int 0) (match_dup 3)))
8903      (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
8904    (parallel
8905     [(set (match_dup 0)
8906           (plus:SI (plus:SI (match_dup 0) (match_dup 3))
8907                    (geu:SI (reg:CC CC_REGNUM) (const_int 0))))
8908      (clobber (reg:CC CC_REGNUM))])])
8909
8910 (define_insn "*cond_move"
8911   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8912         (if_then_else:SI (match_operator 3 "equality_operator"
8913                           [(match_operator 4 "arm_comparison_operator"
8914                             [(match_operand 5 "cc_register" "") (const_int 0)])
8915                            (const_int 0)])
8916                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8917                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8918   "TARGET_ARM"
8919   "*
8920     if (GET_CODE (operands[3]) == NE)
8921       {
8922         if (which_alternative != 1)
8923           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8924         if (which_alternative != 0)
8925           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8926         return \"\";
8927       }
8928     if (which_alternative != 0)
8929       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8930     if (which_alternative != 1)
8931       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8932     return \"\";
8933   "
8934   [(set_attr "conds" "use")
8935    (set_attr "insn" "mov")
8936    (set_attr "length" "4,4,8")]
8937 )
8938
8939 (define_insn "*cond_arith"
8940   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8941         (match_operator:SI 5 "shiftable_operator" 
8942          [(match_operator:SI 4 "arm_comparison_operator"
8943            [(match_operand:SI 2 "s_register_operand" "r,r")
8944             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8945           (match_operand:SI 1 "s_register_operand" "0,?r")]))
8946    (clobber (reg:CC CC_REGNUM))]
8947   "TARGET_ARM"
8948   "*
8949     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8950       return \"%i5\\t%0, %1, %2, lsr #31\";
8951
8952     output_asm_insn (\"cmp\\t%2, %3\", operands);
8953     if (GET_CODE (operands[5]) == AND)
8954       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8955     else if (GET_CODE (operands[5]) == MINUS)
8956       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8957     else if (which_alternative != 0)
8958       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8959     return \"%i5%d4\\t%0, %1, #1\";
8960   "
8961   [(set_attr "conds" "clob")
8962    (set_attr "length" "12")]
8963 )
8964
8965 (define_insn "*cond_sub"
8966   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8967         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8968                   (match_operator:SI 4 "arm_comparison_operator"
8969                    [(match_operand:SI 2 "s_register_operand" "r,r")
8970                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8971    (clobber (reg:CC CC_REGNUM))]
8972   "TARGET_ARM"
8973   "*
8974     output_asm_insn (\"cmp\\t%2, %3\", operands);
8975     if (which_alternative != 0)
8976       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8977     return \"sub%d4\\t%0, %1, #1\";
8978   "
8979   [(set_attr "conds" "clob")
8980    (set_attr "length" "8,12")]
8981 )
8982
8983 ;; ??? Is it worth using these conditional patterns in Thumb-2 mode?
8984 (define_insn "*cmp_ite0"
8985   [(set (match_operand 6 "dominant_cc_register" "")
8986         (compare
8987          (if_then_else:SI
8988           (match_operator 4 "arm_comparison_operator"
8989            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8990             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8991           (match_operator:SI 5 "arm_comparison_operator"
8992            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8993             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8994           (const_int 0))
8995          (const_int 0)))]
8996   "TARGET_ARM"
8997   "*
8998   {
8999     static const char * const opcodes[4][2] =
9000     {
9001       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9002        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9003       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9004        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9005       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9006        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9007       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9008        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9009     };
9010     int swap =
9011       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9012
9013     return opcodes[which_alternative][swap];
9014   }"
9015   [(set_attr "conds" "set")
9016    (set_attr "length" "8")]
9017 )
9018
9019 (define_insn "*cmp_ite1"
9020   [(set (match_operand 6 "dominant_cc_register" "")
9021         (compare
9022          (if_then_else:SI
9023           (match_operator 4 "arm_comparison_operator"
9024            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9025             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9026           (match_operator:SI 5 "arm_comparison_operator"
9027            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9028             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
9029           (const_int 1))
9030          (const_int 0)))]
9031   "TARGET_ARM"
9032   "*
9033   {
9034     static const char * const opcodes[4][2] =
9035     {
9036       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
9037        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9038       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
9039        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9040       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
9041        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9042       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
9043        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9044     };
9045     int swap =
9046       comparison_dominates_p (GET_CODE (operands[5]),
9047                               reverse_condition (GET_CODE (operands[4])));
9048
9049     return opcodes[which_alternative][swap];
9050   }"
9051   [(set_attr "conds" "set")
9052    (set_attr "length" "8")]
9053 )
9054
9055 (define_insn "*cmp_and"
9056   [(set (match_operand 6 "dominant_cc_register" "")
9057         (compare
9058          (and:SI
9059           (match_operator 4 "arm_comparison_operator"
9060            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9061             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9062           (match_operator:SI 5 "arm_comparison_operator"
9063            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9064             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9065          (const_int 0)))]
9066   "TARGET_ARM"
9067   "*
9068   {
9069     static const char *const opcodes[4][2] =
9070     {
9071       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
9072        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
9073       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
9074        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
9075       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
9076        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
9077       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
9078        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
9079     };
9080     int swap =
9081       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9082
9083     return opcodes[which_alternative][swap];
9084   }"
9085   [(set_attr "conds" "set")
9086    (set_attr "predicable" "no")
9087    (set_attr "length" "8")]
9088 )
9089
9090 (define_insn "*cmp_ior"
9091   [(set (match_operand 6 "dominant_cc_register" "")
9092         (compare
9093          (ior:SI
9094           (match_operator 4 "arm_comparison_operator"
9095            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
9096             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
9097           (match_operator:SI 5 "arm_comparison_operator"
9098            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
9099             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
9100          (const_int 0)))]
9101   "TARGET_ARM"
9102   "*
9103 {
9104   static const char *const opcodes[4][2] =
9105   {
9106     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
9107      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
9108     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
9109      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
9110     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
9111      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
9112     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
9113      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
9114   };
9115   int swap =
9116     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9117
9118   return opcodes[which_alternative][swap];
9119 }
9120 "
9121   [(set_attr "conds" "set")
9122    (set_attr "length" "8")]
9123 )
9124
9125 (define_insn_and_split "*ior_scc_scc"
9126   [(set (match_operand:SI 0 "s_register_operand" "=r")
9127         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9128                  [(match_operand:SI 1 "s_register_operand" "r")
9129                   (match_operand:SI 2 "arm_add_operand" "rIL")])
9130                 (match_operator:SI 6 "arm_comparison_operator"
9131                  [(match_operand:SI 4 "s_register_operand" "r")
9132                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
9133    (clobber (reg:CC CC_REGNUM))]
9134   "TARGET_ARM
9135    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9136        != CCmode)"
9137   "#"
9138   "TARGET_ARM && reload_completed"
9139   [(set (match_dup 7)
9140         (compare
9141          (ior:SI
9142           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9143           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9144          (const_int 0)))
9145    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9146   "operands[7]
9147      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9148                                                   DOM_CC_X_OR_Y),
9149                     CC_REGNUM);"
9150   [(set_attr "conds" "clob")
9151    (set_attr "length" "16")])
9152
9153 ; If the above pattern is followed by a CMP insn, then the compare is 
9154 ; redundant, since we can rework the conditional instruction that follows.
9155 (define_insn_and_split "*ior_scc_scc_cmp"
9156   [(set (match_operand 0 "dominant_cc_register" "")
9157         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9158                           [(match_operand:SI 1 "s_register_operand" "r")
9159                            (match_operand:SI 2 "arm_add_operand" "rIL")])
9160                          (match_operator:SI 6 "arm_comparison_operator"
9161                           [(match_operand:SI 4 "s_register_operand" "r")
9162                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
9163                  (const_int 0)))
9164    (set (match_operand:SI 7 "s_register_operand" "=r")
9165         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9166                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9167   "TARGET_ARM"
9168   "#"
9169   "TARGET_ARM && reload_completed"
9170   [(set (match_dup 0)
9171         (compare
9172          (ior:SI
9173           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9174           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9175          (const_int 0)))
9176    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9177   ""
9178   [(set_attr "conds" "set")
9179    (set_attr "length" "16")])
9180
9181 (define_insn_and_split "*and_scc_scc"
9182   [(set (match_operand:SI 0 "s_register_operand" "=r")
9183         (and:SI (match_operator:SI 3 "arm_comparison_operator"
9184                  [(match_operand:SI 1 "s_register_operand" "r")
9185                   (match_operand:SI 2 "arm_add_operand" "rIL")])
9186                 (match_operator:SI 6 "arm_comparison_operator"
9187                  [(match_operand:SI 4 "s_register_operand" "r")
9188                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
9189    (clobber (reg:CC CC_REGNUM))]
9190   "TARGET_ARM
9191    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9192        != CCmode)"
9193   "#"
9194   "TARGET_ARM && reload_completed
9195    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9196        != CCmode)"
9197   [(set (match_dup 7)
9198         (compare
9199          (and:SI
9200           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9201           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9202          (const_int 0)))
9203    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9204   "operands[7]
9205      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9206                                                   DOM_CC_X_AND_Y),
9207                     CC_REGNUM);"
9208   [(set_attr "conds" "clob")
9209    (set_attr "length" "16")])
9210
9211 ; If the above pattern is followed by a CMP insn, then the compare is 
9212 ; redundant, since we can rework the conditional instruction that follows.
9213 (define_insn_and_split "*and_scc_scc_cmp"
9214   [(set (match_operand 0 "dominant_cc_register" "")
9215         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9216                           [(match_operand:SI 1 "s_register_operand" "r")
9217                            (match_operand:SI 2 "arm_add_operand" "rIL")])
9218                          (match_operator:SI 6 "arm_comparison_operator"
9219                           [(match_operand:SI 4 "s_register_operand" "r")
9220                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
9221                  (const_int 0)))
9222    (set (match_operand:SI 7 "s_register_operand" "=r")
9223         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9224                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9225   "TARGET_ARM"
9226   "#"
9227   "TARGET_ARM && reload_completed"
9228   [(set (match_dup 0)
9229         (compare
9230          (and:SI
9231           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9232           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9233          (const_int 0)))
9234    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9235   ""
9236   [(set_attr "conds" "set")
9237    (set_attr "length" "16")])
9238
9239 ;; If there is no dominance in the comparison, then we can still save an
9240 ;; instruction in the AND case, since we can know that the second compare
9241 ;; need only zero the value if false (if true, then the value is already
9242 ;; correct).
9243 (define_insn_and_split "*and_scc_scc_nodom"
9244   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
9245         (and:SI (match_operator:SI 3 "arm_comparison_operator"
9246                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
9247                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9248                 (match_operator:SI 6 "arm_comparison_operator"
9249                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
9250                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9251    (clobber (reg:CC CC_REGNUM))]
9252   "TARGET_ARM
9253    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9254        == CCmode)"
9255   "#"
9256   "TARGET_ARM && reload_completed"
9257   [(parallel [(set (match_dup 0)
9258                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9259               (clobber (reg:CC CC_REGNUM))])
9260    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9261    (set (match_dup 0)
9262         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9263                          (match_dup 0)
9264                          (const_int 0)))]
9265   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9266                                               operands[4], operands[5]),
9267                               CC_REGNUM);
9268    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9269                                   operands[5]);"
9270   [(set_attr "conds" "clob")
9271    (set_attr "length" "20")])
9272
9273 (define_split
9274   [(set (reg:CC_NOOV CC_REGNUM)
9275         (compare:CC_NOOV (ior:SI
9276                           (and:SI (match_operand:SI 0 "s_register_operand" "")
9277                                   (const_int 1))
9278                           (match_operator:SI 1 "arm_comparison_operator"
9279                            [(match_operand:SI 2 "s_register_operand" "")
9280                             (match_operand:SI 3 "arm_add_operand" "")]))
9281                          (const_int 0)))
9282    (clobber (match_operand:SI 4 "s_register_operand" ""))]
9283   "TARGET_ARM"
9284   [(set (match_dup 4)
9285         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9286                 (match_dup 0)))
9287    (set (reg:CC_NOOV CC_REGNUM)
9288         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9289                          (const_int 0)))]
9290   "")
9291
9292 (define_split
9293   [(set (reg:CC_NOOV CC_REGNUM)
9294         (compare:CC_NOOV (ior:SI
9295                           (match_operator:SI 1 "arm_comparison_operator"
9296                            [(match_operand:SI 2 "s_register_operand" "")
9297                             (match_operand:SI 3 "arm_add_operand" "")])
9298                           (and:SI (match_operand:SI 0 "s_register_operand" "")
9299                                   (const_int 1)))
9300                          (const_int 0)))
9301    (clobber (match_operand:SI 4 "s_register_operand" ""))]
9302   "TARGET_ARM"
9303   [(set (match_dup 4)
9304         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9305                 (match_dup 0)))
9306    (set (reg:CC_NOOV CC_REGNUM)
9307         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9308                          (const_int 0)))]
9309   "")
9310 ;; ??? The conditional patterns above need checking for Thumb-2 usefulness
9311
9312 (define_insn "*negscc"
9313   [(set (match_operand:SI 0 "s_register_operand" "=r")
9314         (neg:SI (match_operator 3 "arm_comparison_operator"
9315                  [(match_operand:SI 1 "s_register_operand" "r")
9316                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
9317    (clobber (reg:CC CC_REGNUM))]
9318   "TARGET_ARM"
9319   "*
9320   if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
9321     return \"mov\\t%0, %1, asr #31\";
9322
9323   if (GET_CODE (operands[3]) == NE)
9324     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9325
9326   output_asm_insn (\"cmp\\t%1, %2\", operands);
9327   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9328   return \"mvn%d3\\t%0, #0\";
9329   "
9330   [(set_attr "conds" "clob")
9331    (set_attr "length" "12")]
9332 )
9333
9334 (define_insn "movcond"
9335   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9336         (if_then_else:SI
9337          (match_operator 5 "arm_comparison_operator"
9338           [(match_operand:SI 3 "s_register_operand" "r,r,r")
9339            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9340          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9341          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
9342    (clobber (reg:CC CC_REGNUM))]
9343   "TARGET_ARM"
9344   "*
9345   if (GET_CODE (operands[5]) == LT
9346       && (operands[4] == const0_rtx))
9347     {
9348       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9349         {
9350           if (operands[2] == const0_rtx)
9351             return \"and\\t%0, %1, %3, asr #31\";
9352           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9353         }
9354       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9355         {
9356           if (operands[1] == const0_rtx)
9357             return \"bic\\t%0, %2, %3, asr #31\";
9358           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9359         }
9360       /* The only case that falls through to here is when both ops 1 & 2
9361          are constants.  */
9362     }
9363
9364   if (GET_CODE (operands[5]) == GE
9365       && (operands[4] == const0_rtx))
9366     {
9367       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9368         {
9369           if (operands[2] == const0_rtx)
9370             return \"bic\\t%0, %1, %3, asr #31\";
9371           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9372         }
9373       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9374         {
9375           if (operands[1] == const0_rtx)
9376             return \"and\\t%0, %2, %3, asr #31\";
9377           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9378         }
9379       /* The only case that falls through to here is when both ops 1 & 2
9380          are constants.  */
9381     }
9382   if (GET_CODE (operands[4]) == CONST_INT
9383       && !const_ok_for_arm (INTVAL (operands[4])))
9384     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9385   else
9386     output_asm_insn (\"cmp\\t%3, %4\", operands);
9387   if (which_alternative != 0)
9388     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9389   if (which_alternative != 1)
9390     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9391   return \"\";
9392   "
9393   [(set_attr "conds" "clob")
9394    (set_attr "length" "8,8,12")]
9395 )
9396
9397 ;; ??? The patterns below need checking for Thumb-2 usefulness.
9398
9399 (define_insn "*ifcompare_plus_move"
9400   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9401         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9402                           [(match_operand:SI 4 "s_register_operand" "r,r")
9403                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9404                          (plus:SI
9405                           (match_operand:SI 2 "s_register_operand" "r,r")
9406                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
9407                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9408    (clobber (reg:CC CC_REGNUM))]
9409   "TARGET_ARM"
9410   "#"
9411   [(set_attr "conds" "clob")
9412    (set_attr "length" "8,12")]
9413 )
9414
9415 (define_insn "*if_plus_move"
9416   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9417         (if_then_else:SI
9418          (match_operator 4 "arm_comparison_operator"
9419           [(match_operand 5 "cc_register" "") (const_int 0)])
9420          (plus:SI
9421           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9422           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9423          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
9424   "TARGET_ARM"
9425   "@
9426    add%d4\\t%0, %2, %3
9427    sub%d4\\t%0, %2, #%n3
9428    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
9429    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
9430   [(set_attr "conds" "use")
9431    (set_attr "length" "4,4,8,8")
9432    (set_attr "type" "*,*,*,*")]
9433 )
9434
9435 (define_insn "*ifcompare_move_plus"
9436   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9437         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9438                           [(match_operand:SI 4 "s_register_operand" "r,r")
9439                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9440                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9441                          (plus:SI
9442                           (match_operand:SI 2 "s_register_operand" "r,r")
9443                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
9444    (clobber (reg:CC CC_REGNUM))]
9445   "TARGET_ARM"
9446   "#"
9447   [(set_attr "conds" "clob")
9448    (set_attr "length" "8,12")]
9449 )
9450
9451 (define_insn "*if_move_plus"
9452   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9453         (if_then_else:SI
9454          (match_operator 4 "arm_comparison_operator"
9455           [(match_operand 5 "cc_register" "") (const_int 0)])
9456          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
9457          (plus:SI
9458           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9459           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
9460   "TARGET_ARM"
9461   "@
9462    add%D4\\t%0, %2, %3
9463    sub%D4\\t%0, %2, #%n3
9464    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
9465    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
9466   [(set_attr "conds" "use")
9467    (set_attr "length" "4,4,8,8")
9468    (set_attr "type" "*,*,*,*")]
9469 )
9470
9471 (define_insn "*ifcompare_arith_arith"
9472   [(set (match_operand:SI 0 "s_register_operand" "=r")
9473         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
9474                           [(match_operand:SI 5 "s_register_operand" "r")
9475                            (match_operand:SI 6 "arm_add_operand" "rIL")])
9476                          (match_operator:SI 8 "shiftable_operator"
9477                           [(match_operand:SI 1 "s_register_operand" "r")
9478                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
9479                          (match_operator:SI 7 "shiftable_operator"
9480                           [(match_operand:SI 3 "s_register_operand" "r")
9481                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
9482    (clobber (reg:CC CC_REGNUM))]
9483   "TARGET_ARM"
9484   "#"
9485   [(set_attr "conds" "clob")
9486    (set_attr "length" "12")]
9487 )
9488
9489 (define_insn "*if_arith_arith"
9490   [(set (match_operand:SI 0 "s_register_operand" "=r")
9491         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
9492                           [(match_operand 8 "cc_register" "") (const_int 0)])
9493                          (match_operator:SI 6 "shiftable_operator"
9494                           [(match_operand:SI 1 "s_register_operand" "r")
9495                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
9496                          (match_operator:SI 7 "shiftable_operator"
9497                           [(match_operand:SI 3 "s_register_operand" "r")
9498                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
9499   "TARGET_ARM"
9500   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
9501   [(set_attr "conds" "use")
9502    (set_attr "length" "8")]
9503 )
9504
9505 (define_insn "*ifcompare_arith_move"
9506   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9507         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9508                           [(match_operand:SI 2 "s_register_operand" "r,r")
9509                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9510                          (match_operator:SI 7 "shiftable_operator"
9511                           [(match_operand:SI 4 "s_register_operand" "r,r")
9512                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
9513                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9514    (clobber (reg:CC CC_REGNUM))]
9515   "TARGET_ARM"
9516   "*
9517   /* If we have an operation where (op x 0) is the identity operation and
9518      the conditional operator is LT or GE and we are comparing against zero and
9519      everything is in registers then we can do this in two instructions.  */
9520   if (operands[3] == const0_rtx
9521       && GET_CODE (operands[7]) != AND
9522       && GET_CODE (operands[5]) == REG
9523       && GET_CODE (operands[1]) == REG 
9524       && REGNO (operands[1]) == REGNO (operands[4])
9525       && REGNO (operands[4]) != REGNO (operands[0]))
9526     {
9527       if (GET_CODE (operands[6]) == LT)
9528         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9529       else if (GET_CODE (operands[6]) == GE)
9530         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9531     }
9532   if (GET_CODE (operands[3]) == CONST_INT
9533       && !const_ok_for_arm (INTVAL (operands[3])))
9534     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9535   else
9536     output_asm_insn (\"cmp\\t%2, %3\", operands);
9537   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9538   if (which_alternative != 0)
9539     return \"mov%D6\\t%0, %1\";
9540   return \"\";
9541   "
9542   [(set_attr "conds" "clob")
9543    (set_attr "length" "8,12")]
9544 )
9545
9546 (define_insn "*if_arith_move"
9547   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9548         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9549                           [(match_operand 6 "cc_register" "") (const_int 0)])
9550                          (match_operator:SI 5 "shiftable_operator"
9551                           [(match_operand:SI 2 "s_register_operand" "r,r")
9552                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9553                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
9554   "TARGET_ARM"
9555   "@
9556    %I5%d4\\t%0, %2, %3
9557    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
9558   [(set_attr "conds" "use")
9559    (set_attr "length" "4,8")
9560    (set_attr "type" "*,*")]
9561 )
9562
9563 (define_insn "*ifcompare_move_arith"
9564   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9565         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9566                           [(match_operand:SI 4 "s_register_operand" "r,r")
9567                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9568                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9569                          (match_operator:SI 7 "shiftable_operator"
9570                           [(match_operand:SI 2 "s_register_operand" "r,r")
9571                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
9572    (clobber (reg:CC CC_REGNUM))]
9573   "TARGET_ARM"
9574   "*
9575   /* If we have an operation where (op x 0) is the identity operation and
9576      the conditional operator is LT or GE and we are comparing against zero and
9577      everything is in registers then we can do this in two instructions */
9578   if (operands[5] == const0_rtx
9579       && GET_CODE (operands[7]) != AND
9580       && GET_CODE (operands[3]) == REG
9581       && GET_CODE (operands[1]) == REG 
9582       && REGNO (operands[1]) == REGNO (operands[2])
9583       && REGNO (operands[2]) != REGNO (operands[0]))
9584     {
9585       if (GET_CODE (operands[6]) == GE)
9586         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9587       else if (GET_CODE (operands[6]) == LT)
9588         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9589     }
9590
9591   if (GET_CODE (operands[5]) == CONST_INT
9592       && !const_ok_for_arm (INTVAL (operands[5])))
9593     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9594   else
9595     output_asm_insn (\"cmp\\t%4, %5\", operands);
9596
9597   if (which_alternative != 0)
9598     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
9599   return \"%I7%D6\\t%0, %2, %3\";
9600   "
9601   [(set_attr "conds" "clob")
9602    (set_attr "length" "8,12")]
9603 )
9604
9605 (define_insn "*if_move_arith"
9606   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9607         (if_then_else:SI
9608          (match_operator 4 "arm_comparison_operator"
9609           [(match_operand 6 "cc_register" "") (const_int 0)])
9610          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9611          (match_operator:SI 5 "shiftable_operator"
9612           [(match_operand:SI 2 "s_register_operand" "r,r")
9613            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
9614   "TARGET_ARM"
9615   "@
9616    %I5%D4\\t%0, %2, %3
9617    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
9618   [(set_attr "conds" "use")
9619    (set_attr "length" "4,8")
9620    (set_attr "type" "*,*")]
9621 )
9622
9623 (define_insn "*ifcompare_move_not"
9624   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9625         (if_then_else:SI
9626          (match_operator 5 "arm_comparison_operator"
9627           [(match_operand:SI 3 "s_register_operand" "r,r")
9628            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9629          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9630          (not:SI
9631           (match_operand:SI 2 "s_register_operand" "r,r"))))
9632    (clobber (reg:CC CC_REGNUM))]
9633   "TARGET_ARM"
9634   "#"
9635   [(set_attr "conds" "clob")
9636    (set_attr "length" "8,12")]
9637 )
9638
9639 (define_insn "*if_move_not"
9640   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9641         (if_then_else:SI
9642          (match_operator 4 "arm_comparison_operator"
9643           [(match_operand 3 "cc_register" "") (const_int 0)])
9644          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9645          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9646   "TARGET_ARM"
9647   "@
9648    mvn%D4\\t%0, %2
9649    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9650    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
9651   [(set_attr "conds" "use")
9652    (set_attr "insn" "mvn")
9653    (set_attr "length" "4,8,8")]
9654 )
9655
9656 (define_insn "*ifcompare_not_move"
9657   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9658         (if_then_else:SI 
9659          (match_operator 5 "arm_comparison_operator"
9660           [(match_operand:SI 3 "s_register_operand" "r,r")
9661            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9662          (not:SI
9663           (match_operand:SI 2 "s_register_operand" "r,r"))
9664          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9665    (clobber (reg:CC CC_REGNUM))]
9666   "TARGET_ARM"
9667   "#"
9668   [(set_attr "conds" "clob")
9669    (set_attr "length" "8,12")]
9670 )
9671
9672 (define_insn "*if_not_move"
9673   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9674         (if_then_else:SI
9675          (match_operator 4 "arm_comparison_operator"
9676           [(match_operand 3 "cc_register" "") (const_int 0)])
9677          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9678          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9679   "TARGET_ARM"
9680   "@
9681    mvn%d4\\t%0, %2
9682    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9683    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
9684   [(set_attr "conds" "use")
9685    (set_attr "insn" "mvn")
9686    (set_attr "length" "4,8,8")]
9687 )
9688
9689 (define_insn "*ifcompare_shift_move"
9690   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9691         (if_then_else:SI
9692          (match_operator 6 "arm_comparison_operator"
9693           [(match_operand:SI 4 "s_register_operand" "r,r")
9694            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9695          (match_operator:SI 7 "shift_operator"
9696           [(match_operand:SI 2 "s_register_operand" "r,r")
9697            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9698          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9699    (clobber (reg:CC CC_REGNUM))]
9700   "TARGET_ARM"
9701   "#"
9702   [(set_attr "conds" "clob")
9703    (set_attr "length" "8,12")]
9704 )
9705
9706 (define_insn "*if_shift_move"
9707   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9708         (if_then_else:SI
9709          (match_operator 5 "arm_comparison_operator"
9710           [(match_operand 6 "cc_register" "") (const_int 0)])
9711          (match_operator:SI 4 "shift_operator"
9712           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9713            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9714          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9715   "TARGET_ARM"
9716   "@
9717    mov%d5\\t%0, %2%S4
9718    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9719    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
9720   [(set_attr "conds" "use")
9721    (set_attr "shift" "2")
9722    (set_attr "length" "4,8,8")
9723    (set_attr "insn" "mov")
9724    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9725                       (const_string "alu_shift")
9726                       (const_string "alu_shift_reg")))]
9727 )
9728
9729 (define_insn "*ifcompare_move_shift"
9730   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9731         (if_then_else:SI
9732          (match_operator 6 "arm_comparison_operator"
9733           [(match_operand:SI 4 "s_register_operand" "r,r")
9734            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9735          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9736          (match_operator:SI 7 "shift_operator"
9737           [(match_operand:SI 2 "s_register_operand" "r,r")
9738            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
9739    (clobber (reg:CC CC_REGNUM))]
9740   "TARGET_ARM"
9741   "#"
9742   [(set_attr "conds" "clob")
9743    (set_attr "length" "8,12")]
9744 )
9745
9746 (define_insn "*if_move_shift"
9747   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9748         (if_then_else:SI
9749          (match_operator 5 "arm_comparison_operator"
9750           [(match_operand 6 "cc_register" "") (const_int 0)])
9751          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9752          (match_operator:SI 4 "shift_operator"
9753           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9754            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
9755   "TARGET_ARM"
9756   "@
9757    mov%D5\\t%0, %2%S4
9758    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9759    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
9760   [(set_attr "conds" "use")
9761    (set_attr "shift" "2")
9762    (set_attr "length" "4,8,8")
9763    (set_attr "insn" "mov")
9764    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9765                       (const_string "alu_shift")
9766                       (const_string "alu_shift_reg")))]
9767 )
9768
9769 (define_insn "*ifcompare_shift_shift"
9770   [(set (match_operand:SI 0 "s_register_operand" "=r")
9771         (if_then_else:SI
9772          (match_operator 7 "arm_comparison_operator"
9773           [(match_operand:SI 5 "s_register_operand" "r")
9774            (match_operand:SI 6 "arm_add_operand" "rIL")])
9775          (match_operator:SI 8 "shift_operator"
9776           [(match_operand:SI 1 "s_register_operand" "r")
9777            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9778          (match_operator:SI 9 "shift_operator"
9779           [(match_operand:SI 3 "s_register_operand" "r")
9780            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
9781    (clobber (reg:CC CC_REGNUM))]
9782   "TARGET_ARM"
9783   "#"
9784   [(set_attr "conds" "clob")
9785    (set_attr "length" "12")]
9786 )
9787
9788 (define_insn "*if_shift_shift"
9789   [(set (match_operand:SI 0 "s_register_operand" "=r")
9790         (if_then_else:SI
9791          (match_operator 5 "arm_comparison_operator"
9792           [(match_operand 8 "cc_register" "") (const_int 0)])
9793          (match_operator:SI 6 "shift_operator"
9794           [(match_operand:SI 1 "s_register_operand" "r")
9795            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9796          (match_operator:SI 7 "shift_operator"
9797           [(match_operand:SI 3 "s_register_operand" "r")
9798            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
9799   "TARGET_ARM"
9800   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
9801   [(set_attr "conds" "use")
9802    (set_attr "shift" "1")
9803    (set_attr "length" "8")
9804    (set_attr "insn" "mov")
9805    (set (attr "type") (if_then_else
9806                         (and (match_operand 2 "const_int_operand" "")
9807                              (match_operand 4 "const_int_operand" ""))
9808                       (const_string "alu_shift")
9809                       (const_string "alu_shift_reg")))]
9810 )
9811
9812 (define_insn "*ifcompare_not_arith"
9813   [(set (match_operand:SI 0 "s_register_operand" "=r")
9814         (if_then_else:SI
9815          (match_operator 6 "arm_comparison_operator"
9816           [(match_operand:SI 4 "s_register_operand" "r")
9817            (match_operand:SI 5 "arm_add_operand" "rIL")])
9818          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9819          (match_operator:SI 7 "shiftable_operator"
9820           [(match_operand:SI 2 "s_register_operand" "r")
9821            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
9822    (clobber (reg:CC CC_REGNUM))]
9823   "TARGET_ARM"
9824   "#"
9825   [(set_attr "conds" "clob")
9826    (set_attr "length" "12")]
9827 )
9828
9829 (define_insn "*if_not_arith"
9830   [(set (match_operand:SI 0 "s_register_operand" "=r")
9831         (if_then_else:SI
9832          (match_operator 5 "arm_comparison_operator"
9833           [(match_operand 4 "cc_register" "") (const_int 0)])
9834          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9835          (match_operator:SI 6 "shiftable_operator"
9836           [(match_operand:SI 2 "s_register_operand" "r")
9837            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
9838   "TARGET_ARM"
9839   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
9840   [(set_attr "conds" "use")
9841    (set_attr "insn" "mvn")
9842    (set_attr "length" "8")]
9843 )
9844
9845 (define_insn "*ifcompare_arith_not"
9846   [(set (match_operand:SI 0 "s_register_operand" "=r")
9847         (if_then_else:SI
9848          (match_operator 6 "arm_comparison_operator"
9849           [(match_operand:SI 4 "s_register_operand" "r")
9850            (match_operand:SI 5 "arm_add_operand" "rIL")])
9851          (match_operator:SI 7 "shiftable_operator"
9852           [(match_operand:SI 2 "s_register_operand" "r")
9853            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9854          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9855    (clobber (reg:CC CC_REGNUM))]
9856   "TARGET_ARM"
9857   "#"
9858   [(set_attr "conds" "clob")
9859    (set_attr "length" "12")]
9860 )
9861
9862 (define_insn "*if_arith_not"
9863   [(set (match_operand:SI 0 "s_register_operand" "=r")
9864         (if_then_else:SI
9865          (match_operator 5 "arm_comparison_operator"
9866           [(match_operand 4 "cc_register" "") (const_int 0)])
9867          (match_operator:SI 6 "shiftable_operator"
9868           [(match_operand:SI 2 "s_register_operand" "r")
9869            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9870          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9871   "TARGET_ARM"
9872   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9873   [(set_attr "conds" "use")
9874    (set_attr "insn" "mvn")
9875    (set_attr "length" "8")]
9876 )
9877
9878 (define_insn "*ifcompare_neg_move"
9879   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9880         (if_then_else:SI
9881          (match_operator 5 "arm_comparison_operator"
9882           [(match_operand:SI 3 "s_register_operand" "r,r")
9883            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9884          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9885          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9886    (clobber (reg:CC CC_REGNUM))]
9887   "TARGET_ARM"
9888   "#"
9889   [(set_attr "conds" "clob")
9890    (set_attr "length" "8,12")]
9891 )
9892
9893 (define_insn "*if_neg_move"
9894   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9895         (if_then_else:SI
9896          (match_operator 4 "arm_comparison_operator"
9897           [(match_operand 3 "cc_register" "") (const_int 0)])
9898          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9899          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9900   "TARGET_ARM"
9901   "@
9902    rsb%d4\\t%0, %2, #0
9903    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9904    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9905   [(set_attr "conds" "use")
9906    (set_attr "length" "4,8,8")]
9907 )
9908
9909 (define_insn "*ifcompare_move_neg"
9910   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9911         (if_then_else:SI
9912          (match_operator 5 "arm_comparison_operator"
9913           [(match_operand:SI 3 "s_register_operand" "r,r")
9914            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9915          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9916          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9917    (clobber (reg:CC CC_REGNUM))]
9918   "TARGET_ARM"
9919   "#"
9920   [(set_attr "conds" "clob")
9921    (set_attr "length" "8,12")]
9922 )
9923
9924 (define_insn "*if_move_neg"
9925   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9926         (if_then_else:SI
9927          (match_operator 4 "arm_comparison_operator"
9928           [(match_operand 3 "cc_register" "") (const_int 0)])
9929          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9930          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9931   "TARGET_ARM"
9932   "@
9933    rsb%D4\\t%0, %2, #0
9934    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9935    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9936   [(set_attr "conds" "use")
9937    (set_attr "length" "4,8,8")]
9938 )
9939
9940 (define_insn "*arith_adjacentmem"
9941   [(set (match_operand:SI 0 "s_register_operand" "=r")
9942         (match_operator:SI 1 "shiftable_operator"
9943          [(match_operand:SI 2 "memory_operand" "m")
9944           (match_operand:SI 3 "memory_operand" "m")]))
9945    (clobber (match_scratch:SI 4 "=r"))]
9946   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9947   "*
9948   {
9949     rtx ldm[3];
9950     rtx arith[4];
9951     rtx base_reg;
9952     HOST_WIDE_INT val1 = 0, val2 = 0;
9953
9954     if (REGNO (operands[0]) > REGNO (operands[4]))
9955       {
9956         ldm[1] = operands[4];
9957         ldm[2] = operands[0];
9958       }
9959     else
9960       {
9961         ldm[1] = operands[0];
9962         ldm[2] = operands[4];
9963       }
9964
9965     base_reg = XEXP (operands[2], 0);
9966
9967     if (!REG_P (base_reg))
9968       {
9969         val1 = INTVAL (XEXP (base_reg, 1));
9970         base_reg = XEXP (base_reg, 0);
9971       }
9972
9973     if (!REG_P (XEXP (operands[3], 0)))
9974       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9975
9976     arith[0] = operands[0];
9977     arith[3] = operands[1];
9978
9979     if (val1 < val2)
9980       {
9981         arith[1] = ldm[1];
9982         arith[2] = ldm[2];
9983       }
9984     else
9985       {
9986         arith[1] = ldm[2];
9987         arith[2] = ldm[1];
9988       }
9989
9990     ldm[0] = base_reg;
9991     if (val1 !=0 && val2 != 0)
9992       {
9993         rtx ops[3];
9994
9995         if (val1 == 4 || val2 == 4)
9996           /* Other val must be 8, since we know they are adjacent and neither
9997              is zero.  */
9998           output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
9999         else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
10000           {
10001             ldm[0] = ops[0] = operands[4];
10002             ops[1] = base_reg;
10003             ops[2] = GEN_INT (val1);
10004             output_add_immediate (ops);
10005             if (val1 < val2)
10006               output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
10007             else
10008               output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
10009           }
10010         else
10011           {
10012             /* Offset is out of range for a single add, so use two ldr.  */
10013             ops[0] = ldm[1];
10014             ops[1] = base_reg;
10015             ops[2] = GEN_INT (val1);
10016             output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10017             ops[0] = ldm[2];
10018             ops[2] = GEN_INT (val2);
10019             output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10020           }
10021       }
10022     else if (val1 != 0)
10023       {
10024         if (val1 < val2)
10025           output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
10026         else
10027           output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
10028       }
10029     else
10030       {
10031         if (val1 < val2)
10032           output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
10033         else
10034           output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
10035       }
10036     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10037     return \"\";
10038   }"
10039   [(set_attr "length" "12")
10040    (set_attr "predicable" "yes")
10041    (set_attr "type" "load1")]
10042 )
10043
10044 ; This pattern is never tried by combine, so do it as a peephole
10045
10046 (define_peephole2
10047   [(set (match_operand:SI 0 "arm_general_register_operand" "")
10048         (match_operand:SI 1 "arm_general_register_operand" ""))
10049    (set (reg:CC CC_REGNUM)
10050         (compare:CC (match_dup 1) (const_int 0)))]
10051   "TARGET_ARM"
10052   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10053               (set (match_dup 0) (match_dup 1))])]
10054   ""
10055 )
10056
10057 (define_split
10058   [(set (match_operand:SI 0 "s_register_operand" "")
10059         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10060                        (const_int 0))
10061                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
10062                          [(match_operand:SI 3 "s_register_operand" "")
10063                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
10064    (clobber (match_operand:SI 5 "s_register_operand" ""))]
10065   "TARGET_ARM"
10066   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10067    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10068                               (match_dup 5)))]
10069   ""
10070 )
10071
10072 ;; This split can be used because CC_Z mode implies that the following
10073 ;; branch will be an equality, or an unsigned inequality, so the sign
10074 ;; extension is not needed.
10075
10076 (define_split
10077   [(set (reg:CC_Z CC_REGNUM)
10078         (compare:CC_Z
10079          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
10080                     (const_int 24))
10081          (match_operand 1 "const_int_operand" "")))
10082    (clobber (match_scratch:SI 2 ""))]
10083   "TARGET_ARM
10084    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10085        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
10086   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
10087    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
10088   "
10089   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
10090   "
10091 )
10092 ;; ??? Check the patterns above for Thumb-2 usefulness
10093
10094 (define_expand "prologue"
10095   [(clobber (const_int 0))]
10096   "TARGET_EITHER"
10097   "if (TARGET_32BIT)
10098      arm_expand_prologue ();
10099    else
10100      thumb1_expand_prologue ();
10101   DONE;
10102   "
10103 )
10104
10105 (define_expand "epilogue"
10106   [(clobber (const_int 0))]
10107   "TARGET_EITHER"
10108   "
10109   if (crtl->calls_eh_return)
10110     emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
10111   if (TARGET_THUMB1)
10112     thumb1_expand_epilogue ();
10113   else if (USE_RETURN_INSN (FALSE))
10114     {
10115       emit_jump_insn (gen_return ());
10116       DONE;
10117     }
10118   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10119         gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
10120   DONE;
10121   "
10122 )
10123
10124 (define_insn "prologue_thumb1_interwork"
10125   [(unspec_volatile [(const_int 0)] VUNSPEC_THUMB1_INTERWORK)]
10126   "TARGET_THUMB1"
10127   "* return thumb1_output_interwork ();"
10128   [(set_attr "length" "8")]
10129 )
10130
10131 ;; Note - although unspec_volatile's USE all hard registers,
10132 ;; USEs are ignored after relaod has completed.  Thus we need
10133 ;; to add an unspec of the link register to ensure that flow
10134 ;; does not think that it is unused by the sibcall branch that
10135 ;; will replace the standard function epilogue.
10136 (define_insn "sibcall_epilogue"
10137   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
10138               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10139   "TARGET_32BIT"
10140   "*
10141   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
10142     return output_return_instruction (const_true_rtx, FALSE, FALSE);
10143   return arm_output_epilogue (next_nonnote_insn (insn));
10144   "
10145 ;; Length is absolute worst case
10146   [(set_attr "length" "44")
10147    (set_attr "type" "block")
10148    ;; We don't clobber the conditions, but the potential length of this
10149    ;; operation is sufficient to make conditionalizing the sequence 
10150    ;; unlikely to be profitable.
10151    (set_attr "conds" "clob")]
10152 )
10153
10154 (define_insn "*epilogue_insns"
10155   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
10156   "TARGET_EITHER"
10157   "*
10158   if (TARGET_32BIT)
10159     return arm_output_epilogue (NULL);
10160   else /* TARGET_THUMB1 */
10161     return thumb_unexpanded_epilogue ();
10162   "
10163   ; Length is absolute worst case
10164   [(set_attr "length" "44")
10165    (set_attr "type" "block")
10166    ;; We don't clobber the conditions, but the potential length of this
10167    ;; operation is sufficient to make conditionalizing the sequence 
10168    ;; unlikely to be profitable.
10169    (set_attr "conds" "clob")]
10170 )
10171
10172 (define_expand "eh_epilogue"
10173   [(use (match_operand:SI 0 "register_operand" ""))
10174    (use (match_operand:SI 1 "register_operand" ""))
10175    (use (match_operand:SI 2 "register_operand" ""))]
10176   "TARGET_EITHER"
10177   "
10178   {
10179     cfun->machine->eh_epilogue_sp_ofs = operands[1];
10180     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10181       {
10182         rtx ra = gen_rtx_REG (Pmode, 2);
10183
10184         emit_move_insn (ra, operands[2]);
10185         operands[2] = ra;
10186       }
10187     /* This is a hack -- we may have crystalized the function type too
10188        early.  */
10189     cfun->machine->func_type = 0;
10190   }"
10191 )
10192
10193 ;; This split is only used during output to reduce the number of patterns
10194 ;; that need assembler instructions adding to them.  We allowed the setting
10195 ;; of the conditions to be implicit during rtl generation so that
10196 ;; the conditional compare patterns would work.  However this conflicts to
10197 ;; some extent with the conditional data operations, so we have to split them
10198 ;; up again here.
10199
10200 ;; ??? Need to audit these splitters for Thumb-2.  Why isn't normal
10201 ;; conditional execution sufficient?
10202
10203 (define_split
10204   [(set (match_operand:SI 0 "s_register_operand" "")
10205         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10206                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10207                          (match_dup 0)
10208                          (match_operand 4 "" "")))
10209    (clobber (reg:CC CC_REGNUM))]
10210   "TARGET_ARM && reload_completed"
10211   [(set (match_dup 5) (match_dup 6))
10212    (cond_exec (match_dup 7)
10213               (set (match_dup 0) (match_dup 4)))]
10214   "
10215   {
10216     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10217                                              operands[2], operands[3]);
10218     enum rtx_code rc = GET_CODE (operands[1]);
10219
10220     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10221     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10222     if (mode == CCFPmode || mode == CCFPEmode)
10223       rc = reverse_condition_maybe_unordered (rc);
10224     else
10225       rc = reverse_condition (rc);
10226
10227     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10228   }"
10229 )
10230
10231 (define_split
10232   [(set (match_operand:SI 0 "s_register_operand" "")
10233         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10234                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10235                          (match_operand 4 "" "")
10236                          (match_dup 0)))
10237    (clobber (reg:CC CC_REGNUM))]
10238   "TARGET_ARM && reload_completed"
10239   [(set (match_dup 5) (match_dup 6))
10240    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10241               (set (match_dup 0) (match_dup 4)))]
10242   "
10243   {
10244     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10245                                              operands[2], operands[3]);
10246
10247     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10248     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10249   }"
10250 )
10251
10252 (define_split
10253   [(set (match_operand:SI 0 "s_register_operand" "")
10254         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10255                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10256                          (match_operand 4 "" "")
10257                          (match_operand 5 "" "")))
10258    (clobber (reg:CC CC_REGNUM))]
10259   "TARGET_ARM && reload_completed"
10260   [(set (match_dup 6) (match_dup 7))
10261    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10262               (set (match_dup 0) (match_dup 4)))
10263    (cond_exec (match_dup 8)
10264               (set (match_dup 0) (match_dup 5)))]
10265   "
10266   {
10267     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10268                                              operands[2], operands[3]);
10269     enum rtx_code rc = GET_CODE (operands[1]);
10270
10271     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10272     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10273     if (mode == CCFPmode || mode == CCFPEmode)
10274       rc = reverse_condition_maybe_unordered (rc);
10275     else
10276       rc = reverse_condition (rc);
10277
10278     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10279   }"
10280 )
10281
10282 (define_split
10283   [(set (match_operand:SI 0 "s_register_operand" "")
10284         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10285                           [(match_operand:SI 2 "s_register_operand" "")
10286                            (match_operand:SI 3 "arm_add_operand" "")])
10287                          (match_operand:SI 4 "arm_rhs_operand" "")
10288                          (not:SI
10289                           (match_operand:SI 5 "s_register_operand" ""))))
10290    (clobber (reg:CC CC_REGNUM))]
10291   "TARGET_ARM && reload_completed"
10292   [(set (match_dup 6) (match_dup 7))
10293    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10294               (set (match_dup 0) (match_dup 4)))
10295    (cond_exec (match_dup 8)
10296               (set (match_dup 0) (not:SI (match_dup 5))))]
10297   "
10298   {
10299     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10300                                              operands[2], operands[3]);
10301     enum rtx_code rc = GET_CODE (operands[1]);
10302
10303     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10304     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10305     if (mode == CCFPmode || mode == CCFPEmode)
10306       rc = reverse_condition_maybe_unordered (rc);
10307     else
10308       rc = reverse_condition (rc);
10309
10310     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10311   }"
10312 )
10313
10314 (define_insn "*cond_move_not"
10315   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10316         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10317                           [(match_operand 3 "cc_register" "") (const_int 0)])
10318                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10319                          (not:SI
10320                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
10321   "TARGET_ARM"
10322   "@
10323    mvn%D4\\t%0, %2
10324    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
10325   [(set_attr "conds" "use")
10326    (set_attr "insn" "mvn")
10327    (set_attr "length" "4,8")]
10328 )
10329
10330 ;; The next two patterns occur when an AND operation is followed by a
10331 ;; scc insn sequence 
10332
10333 (define_insn "*sign_extract_onebit"
10334   [(set (match_operand:SI 0 "s_register_operand" "=r")
10335         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10336                          (const_int 1)
10337                          (match_operand:SI 2 "const_int_operand" "n")))
10338     (clobber (reg:CC CC_REGNUM))]
10339   "TARGET_ARM"
10340   "*
10341     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10342     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10343     return \"mvnne\\t%0, #0\";
10344   "
10345   [(set_attr "conds" "clob")
10346    (set_attr "length" "8")]
10347 )
10348
10349 (define_insn "*not_signextract_onebit"
10350   [(set (match_operand:SI 0 "s_register_operand" "=r")
10351         (not:SI
10352          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10353                           (const_int 1)
10354                           (match_operand:SI 2 "const_int_operand" "n"))))
10355    (clobber (reg:CC CC_REGNUM))]
10356   "TARGET_ARM"
10357   "*
10358     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10359     output_asm_insn (\"tst\\t%1, %2\", operands);
10360     output_asm_insn (\"mvneq\\t%0, #0\", operands);
10361     return \"movne\\t%0, #0\";
10362   "
10363   [(set_attr "conds" "clob")
10364    (set_attr "length" "12")]
10365 )
10366 ;; ??? The above patterns need auditing for Thumb-2
10367
10368 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
10369 ;; expressions.  For simplicity, the first register is also in the unspec
10370 ;; part.
10371 ;; To avoid the usage of GNU extension, the length attribute is computed
10372 ;; in a C function arm_attr_length_push_multi.
10373 (define_insn "*push_multi"
10374   [(match_parallel 2 "multi_register_push"
10375     [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
10376           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
10377                       UNSPEC_PUSH_MULT))])]
10378   ""
10379   "*
10380   {
10381     int num_saves = XVECLEN (operands[2], 0);
10382      
10383     /* For the StrongARM at least it is faster to
10384        use STR to store only a single register.
10385        In Thumb mode always use push, and the assembler will pick
10386        something appropriate.  */
10387     if (num_saves == 1 && TARGET_ARM)
10388       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10389     else
10390       {
10391         int i;
10392         char pattern[100];
10393
10394         if (TARGET_ARM)
10395             strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10396         else
10397             strcpy (pattern, \"push\\t{%1\");
10398
10399         for (i = 1; i < num_saves; i++)
10400           {
10401             strcat (pattern, \", %|\");
10402             strcat (pattern,
10403                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10404           }
10405
10406         strcat (pattern, \"}\");
10407         output_asm_insn (pattern, operands);
10408       }
10409
10410     return \"\";
10411   }"
10412   [(set_attr "type" "store4")
10413    (set (attr "length")
10414         (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
10415 )
10416
10417 (define_insn "stack_tie"
10418   [(set (mem:BLK (scratch))
10419         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10420                      (match_operand:SI 1 "s_register_operand" "rk")]
10421                     UNSPEC_PRLG_STK))]
10422   ""
10423   ""
10424   [(set_attr "length" "0")]
10425 )
10426
10427 ;; Similarly for the floating point registers
10428 (define_insn "*push_fp_multi"
10429   [(match_parallel 2 "multi_register_push"
10430     [(set (match_operand:BLK 0 "memory_operand" "=m")
10431           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "")]
10432                       UNSPEC_PUSH_MULT))])]
10433   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
10434   "*
10435   {
10436     char pattern[100];
10437
10438     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10439     output_asm_insn (pattern, operands);
10440     return \"\";
10441   }"
10442   [(set_attr "type" "f_fpa_store")]
10443 )
10444
10445 ;; Special patterns for dealing with the constant pool
10446
10447 (define_insn "align_4"
10448   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10449   "TARGET_EITHER"
10450   "*
10451   assemble_align (32);
10452   return \"\";
10453   "
10454 )
10455
10456 (define_insn "align_8"
10457   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10458   "TARGET_EITHER"
10459   "*
10460   assemble_align (64);
10461   return \"\";
10462   "
10463 )
10464
10465 (define_insn "consttable_end"
10466   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10467   "TARGET_EITHER"
10468   "*
10469   making_const_table = FALSE;
10470   return \"\";
10471   "
10472 )
10473
10474 (define_insn "consttable_1"
10475   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10476   "TARGET_THUMB1"
10477   "*
10478   making_const_table = TRUE;
10479   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10480   assemble_zeros (3);
10481   return \"\";
10482   "
10483   [(set_attr "length" "4")]
10484 )
10485
10486 (define_insn "consttable_2"
10487   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10488   "TARGET_THUMB1"
10489   "*
10490   making_const_table = TRUE;
10491   gcc_assert (GET_MODE_CLASS (GET_MODE (operands[0])) != MODE_FLOAT);
10492   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10493   assemble_zeros (2);
10494   return \"\";
10495   "
10496   [(set_attr "length" "4")]
10497 )
10498
10499 (define_insn "consttable_4"
10500   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10501   "TARGET_EITHER"
10502   "*
10503   {
10504     rtx x = operands[0];
10505     making_const_table = TRUE;
10506     switch (GET_MODE_CLASS (GET_MODE (x)))
10507       {
10508       case MODE_FLOAT:
10509         if (GET_MODE (x) == HFmode)
10510           arm_emit_fp16_const (x);
10511         else
10512           {
10513             REAL_VALUE_TYPE r;
10514             REAL_VALUE_FROM_CONST_DOUBLE (r, x);
10515             assemble_real (r, GET_MODE (x), BITS_PER_WORD);
10516           }
10517         break;
10518       default:
10519         /* XXX: Sometimes gcc does something really dumb and ends up with
10520            a HIGH in a constant pool entry, usually because it's trying to
10521            load into a VFP register.  We know this will always be used in
10522            combination with a LO_SUM which ignores the high bits, so just
10523            strip off the HIGH.  */
10524         if (GET_CODE (x) == HIGH)
10525           x = XEXP (x, 0);
10526         assemble_integer (x, 4, BITS_PER_WORD, 1);
10527         mark_symbol_refs_as_used (x);
10528         break;
10529       }
10530     return \"\";
10531   }"
10532   [(set_attr "length" "4")]
10533 )
10534
10535 (define_insn "consttable_8"
10536   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10537   "TARGET_EITHER"
10538   "*
10539   {
10540     making_const_table = TRUE;
10541     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10542       {
10543        case MODE_FLOAT:
10544         {
10545           REAL_VALUE_TYPE r;
10546           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10547           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10548           break;
10549         }
10550       default:
10551         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10552         break;
10553       }
10554     return \"\";
10555   }"
10556   [(set_attr "length" "8")]
10557 )
10558
10559 (define_insn "consttable_16"
10560   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
10561   "TARGET_EITHER"
10562   "*
10563   {
10564     making_const_table = TRUE;
10565     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10566       {
10567        case MODE_FLOAT:
10568         {
10569           REAL_VALUE_TYPE r;
10570           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10571           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10572           break;
10573         }
10574       default:
10575         assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
10576         break;
10577       }
10578     return \"\";
10579   }"
10580   [(set_attr "length" "16")]
10581 )
10582
10583 ;; Miscellaneous Thumb patterns
10584
10585 (define_expand "tablejump"
10586   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10587               (use (label_ref (match_operand 1 "" "")))])]
10588   "TARGET_THUMB1"
10589   "
10590   if (flag_pic)
10591     {
10592       /* Hopefully, CSE will eliminate this copy.  */
10593       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10594       rtx reg2 = gen_reg_rtx (SImode);
10595
10596       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10597       operands[0] = reg2;
10598     }
10599   "
10600 )
10601
10602 ;; NB never uses BX.
10603 (define_insn "*thumb1_tablejump"
10604   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10605    (use (label_ref (match_operand 1 "" "")))]
10606   "TARGET_THUMB1"
10607   "mov\\t%|pc, %0"
10608   [(set_attr "length" "2")]
10609 )
10610
10611 ;; V5 Instructions,
10612
10613 (define_insn "clzsi2"
10614   [(set (match_operand:SI 0 "s_register_operand" "=r")
10615         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10616   "TARGET_32BIT && arm_arch5"
10617   "clz%?\\t%0, %1"
10618   [(set_attr "predicable" "yes")
10619    (set_attr "insn" "clz")])
10620
10621 (define_insn "rbitsi2"
10622   [(set (match_operand:SI 0 "s_register_operand" "=r")
10623         (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
10624   "TARGET_32BIT && arm_arch_thumb2"
10625   "rbit%?\\t%0, %1"
10626   [(set_attr "predicable" "yes")
10627    (set_attr "insn" "clz")])
10628
10629 (define_expand "ctzsi2"
10630  [(set (match_operand:SI           0 "s_register_operand" "")
10631        (ctz:SI (match_operand:SI  1 "s_register_operand" "")))]
10632   "TARGET_32BIT && arm_arch_thumb2"
10633   "
10634    {
10635      rtx tmp = gen_reg_rtx (SImode); 
10636      emit_insn (gen_rbitsi2 (tmp, operands[1]));
10637      emit_insn (gen_clzsi2 (operands[0], tmp));
10638    }
10639    DONE;
10640   "
10641 )
10642
10643 ;; V5E instructions.
10644
10645 (define_insn "prefetch"
10646   [(prefetch (match_operand:SI 0 "address_operand" "p")
10647              (match_operand:SI 1 "" "")
10648              (match_operand:SI 2 "" ""))]
10649   "TARGET_32BIT && arm_arch5e"
10650   "pld\\t%a0")
10651
10652 ;; General predication pattern
10653
10654 (define_cond_exec
10655   [(match_operator 0 "arm_comparison_operator"
10656     [(match_operand 1 "cc_register" "")
10657      (const_int 0)])]
10658   "TARGET_32BIT"
10659   ""
10660 )
10661
10662 (define_insn "prologue_use"
10663   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10664   ""
10665   "%@ %0 needed for prologue"
10666   [(set_attr "length" "0")]
10667 )
10668
10669
10670 ;; Patterns for exception handling
10671
10672 (define_expand "eh_return"
10673   [(use (match_operand 0 "general_operand" ""))]
10674   "TARGET_EITHER"
10675   "
10676   {
10677     if (TARGET_32BIT)
10678       emit_insn (gen_arm_eh_return (operands[0]));
10679     else
10680       emit_insn (gen_thumb_eh_return (operands[0]));
10681     DONE;
10682   }"
10683 )
10684                                    
10685 ;; We can't expand this before we know where the link register is stored.
10686 (define_insn_and_split "arm_eh_return"
10687   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10688                     VUNSPEC_EH_RETURN)
10689    (clobber (match_scratch:SI 1 "=&r"))]
10690   "TARGET_ARM"
10691   "#"
10692   "&& reload_completed"
10693   [(const_int 0)]
10694   "
10695   {
10696     arm_set_return_address (operands[0], operands[1]);
10697     DONE;
10698   }"
10699 )
10700
10701 (define_insn_and_split "thumb_eh_return"
10702   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10703                     VUNSPEC_EH_RETURN)
10704    (clobber (match_scratch:SI 1 "=&l"))]
10705   "TARGET_THUMB1"
10706   "#"
10707   "&& reload_completed"
10708   [(const_int 0)]
10709   "
10710   {
10711     thumb_set_return_address (operands[0], operands[1]);
10712     DONE;
10713   }"
10714 )
10715
10716 \f
10717 ;; TLS support
10718
10719 (define_insn "load_tp_hard"
10720   [(set (match_operand:SI 0 "register_operand" "=r")
10721         (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10722   "TARGET_HARD_TP"
10723   "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
10724   [(set_attr "predicable" "yes")]
10725 )
10726
10727 ;; Doesn't clobber R1-R3.  Must use r0 for the first operand.
10728 (define_insn "load_tp_soft"
10729   [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10730    (clobber (reg:SI LR_REGNUM))
10731    (clobber (reg:SI IP_REGNUM))
10732    (clobber (reg:CC CC_REGNUM))]
10733   "TARGET_SOFT_TP"
10734   "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
10735   [(set_attr "conds" "clob")]
10736 )
10737
10738 ;; tls descriptor call
10739 (define_insn "tlscall"
10740   [(set (reg:SI R0_REGNUM)
10741         (unspec:SI [(reg:SI R0_REGNUM)
10742                     (match_operand:SI 0 "" "X")
10743                     (match_operand 1 "" "")] UNSPEC_TLS))
10744    (clobber (reg:SI R1_REGNUM))
10745    (clobber (reg:SI LR_REGNUM))
10746    (clobber (reg:SI CC_REGNUM))]
10747   "TARGET_GNU2_TLS"
10748   {
10749     targetm.asm_out.internal_label (asm_out_file, "LPIC",
10750                                     INTVAL (operands[1]));
10751     return "bl\\t%c0(tlscall)";
10752   }
10753   [(set_attr "conds" "clob")
10754    (set_attr "length" "4")]
10755 )
10756
10757 ;;
10758
10759 ;; We only care about the lower 16 bits of the constant 
10760 ;; being inserted into the upper 16 bits of the register.
10761 (define_insn "*arm_movtas_ze" 
10762   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
10763                    (const_int 16)
10764                    (const_int 16))
10765         (match_operand:SI 1 "const_int_operand" ""))]
10766   "arm_arch_thumb2"
10767   "movt%?\t%0, %L1"
10768  [(set_attr "predicable" "yes")
10769    (set_attr "length" "4")]
10770 )
10771
10772 (define_insn "*arm_rev"
10773   [(set (match_operand:SI 0 "s_register_operand" "=r")
10774         (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
10775   "TARGET_32BIT && arm_arch6"
10776   "rev%?\t%0, %1"
10777   [(set_attr "predicable" "yes")
10778    (set_attr "length" "4")]
10779 )
10780
10781 (define_insn "*thumb1_rev"
10782   [(set (match_operand:SI 0 "s_register_operand" "=l")
10783         (bswap:SI (match_operand:SI 1 "s_register_operand" "l")))]
10784   "TARGET_THUMB1 && arm_arch6"
10785    "rev\t%0, %1"
10786   [(set_attr "length" "2")]
10787 )
10788
10789 (define_expand "arm_legacy_rev"
10790   [(set (match_operand:SI 2 "s_register_operand" "")
10791         (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
10792                              (const_int 16))
10793                 (match_dup 1)))
10794    (set (match_dup 2)
10795         (lshiftrt:SI (match_dup 2)
10796                      (const_int 8)))
10797    (set (match_operand:SI 3 "s_register_operand" "")
10798         (rotatert:SI (match_dup 1)
10799                      (const_int 8)))
10800    (set (match_dup 2)
10801         (and:SI (match_dup 2)
10802                 (const_int -65281)))
10803    (set (match_operand:SI 0 "s_register_operand" "")
10804         (xor:SI (match_dup 3)
10805                 (match_dup 2)))]
10806   "TARGET_32BIT"
10807   ""
10808 )
10809
10810 ;; Reuse temporaries to keep register pressure down.
10811 (define_expand "thumb_legacy_rev"
10812   [(set (match_operand:SI 2 "s_register_operand" "")
10813      (ashift:SI (match_operand:SI 1 "s_register_operand" "")
10814                 (const_int 24)))
10815    (set (match_operand:SI 3 "s_register_operand" "")
10816      (lshiftrt:SI (match_dup 1)
10817                   (const_int 24)))
10818    (set (match_dup 3)
10819      (ior:SI (match_dup 3)
10820              (match_dup 2)))
10821    (set (match_operand:SI 4 "s_register_operand" "")
10822      (const_int 16))
10823    (set (match_operand:SI 5 "s_register_operand" "")
10824      (rotatert:SI (match_dup 1)
10825                   (match_dup 4)))
10826    (set (match_dup 2)
10827      (ashift:SI (match_dup 5)
10828                 (const_int 24)))
10829    (set (match_dup 5)
10830      (lshiftrt:SI (match_dup 5)
10831                   (const_int 24)))
10832    (set (match_dup 5)
10833      (ior:SI (match_dup 5)
10834              (match_dup 2)))
10835    (set (match_dup 5)
10836      (rotatert:SI (match_dup 5)
10837                   (match_dup 4)))
10838    (set (match_operand:SI 0 "s_register_operand" "")
10839      (ior:SI (match_dup 5)
10840              (match_dup 3)))]
10841   "TARGET_THUMB"
10842   ""
10843 )
10844
10845 (define_expand "bswapsi2"
10846   [(set (match_operand:SI 0 "s_register_operand" "=r")
10847         (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
10848 "TARGET_EITHER && (arm_arch6 || !optimize_size)"
10849 "
10850     if (!arm_arch6)
10851       {
10852         rtx op2 = gen_reg_rtx (SImode);
10853         rtx op3 = gen_reg_rtx (SImode);
10854
10855         if (TARGET_THUMB)
10856           {
10857             rtx op4 = gen_reg_rtx (SImode);
10858             rtx op5 = gen_reg_rtx (SImode);
10859
10860             emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
10861                                              op2, op3, op4, op5));
10862           }
10863         else
10864           {
10865             emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
10866                                            op2, op3));
10867           }
10868
10869         DONE;
10870       }
10871   "
10872 )
10873
10874 ;; Load the load/store multiple patterns
10875 (include "ldmstm.md")
10876 ;; Load the FPA co-processor patterns
10877 (include "fpa.md")
10878 ;; Load the Maverick co-processor patterns
10879 (include "cirrus.md")
10880 ;; Vector bits common to IWMMXT and Neon
10881 (include "vec-common.md")
10882 ;; Load the Intel Wireless Multimedia Extension patterns
10883 (include "iwmmxt.md")
10884 ;; Load the VFP co-processor patterns
10885 (include "vfp.md")
10886 ;; Thumb-2 patterns
10887 (include "thumb2.md")
10888 ;; Neon patterns
10889 (include "neon.md")
10890 ;; Synchronization Primitives
10891 (include "sync.md")