PR target/14040
[official-gcc.git] / gcc / config / arm / arm.md
blob7255b325997ee99c351b210dd0b6b367ac95f9e1
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  Free Software Foundation, Inc.
4 ;;  Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
5 ;;  and Martin Simmons (@harleqn.co.uk).
6 ;;  More major hacks by Richard Earnshaw (rearnsha@arm.com).
8 ;; This file is part of GCC.
10 ;; GCC is free software; you can redistribute it and/or modify it
11 ;; under the terms of the GNU General Public License as published
12 ;; by the Free Software Foundation; either version 2, or (at your
13 ;; option) any later version.
15 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
16 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
18 ;; License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GCC; see the file COPYING.  If not, write to
22 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
28 ;;---------------------------------------------------------------------------
29 ;; Constants
31 ;; Register numbers
32 (define_constants
33   [(IP_REGNUM       12)         ; Scratch register
34    (SP_REGNUM       13)         ; Stack pointer
35    (LR_REGNUM       14)         ; Return address register
36    (PC_REGNUM       15)         ; Program counter
37    (CC_REGNUM       24)         ; Condition code pseudo register
38    (LAST_ARM_REGNUM 15)
39   ]
41 ;; 3rd operand to select_dominance_cc_mode
42 (define_constants
43   [(DOM_CC_X_AND_Y  0)
44    (DOM_CC_NX_OR_Y  1)
45    (DOM_CC_X_OR_Y   2)
46   ]
49 ;; UNSPEC Usage:
50 ;; Note: sin and cos are no-longer used.
52 (define_constants
53   [(UNSPEC_SIN       0) ; `sin' operation (MODE_FLOAT):
54                         ;   operand 0 is the result,
55                         ;   operand 1 the parameter.
56    (UNPSEC_COS       1) ; `cos' operation (MODE_FLOAT):
57                         ;   operand 0 is the result,
58                         ;   operand 1 the parameter.
59    (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
60                         ;   operand 0 is the first register,
61                         ;   subsequent registers are in parallel (use ...)
62                         ;   expressions.
63    (UNSPEC_PIC_SYM   3) ; A symbol that has been treated properly for pic
64                         ;   usage, that is, we will add the pic_register
65                         ;   value to it before trying to dereference it.
66    (UNSPEC_PIC_BASE  4) ; Adding the PC value to the offset to the
67                         ;   GLOBAL_OFFSET_TABLE.  The operation is fully
68                         ;   described by the RTL but must be wrapped to
69                         ;   prevent combine from trying to rip it apart.
70    (UNSPEC_PRLG_STK  5) ; A special barrier that prevents frame accesses 
71                         ;   being scheduled before the stack adjustment insn.
72    (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
73                         ; this unspec is used to prevent the deletion of
74                         ; instructions setting registers for EH handling
75                         ; and stack frame generation.  Operand 0 is the
76                         ; register to "use".
77    (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
78    (UNSPEC_WSHUFH    8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
79    (UNSPEC_WACC      9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
80    (UNSPEC_TMOVMSK  10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
81    (UNSPEC_WSAD     11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
82    (UNSPEC_WSADZ    12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
83    (UNSPEC_WMACS    13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
84    (UNSPEC_WMACU    14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
85    (UNSPEC_WMACSZ   15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
86    (UNSPEC_WMACUZ   16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
87    (UNSPEC_CLRDI    17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
88    (UNSPEC_WMADDS   18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
89    (UNSPEC_WMADDU   19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
90   ]
93 ;; UNSPEC_VOLATILE Usage:
95 (define_constants
96   [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
97                         ;   insn in the code.
98    (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
99                         ;   instruction epilogue sequence that isn't expanded
100                         ;   into normal RTL.  Used for both normal and sibcall
101                         ;   epilogues.
102    (VUNSPEC_ALIGN    2) ; `align' insn.  Used at the head of a minipool table 
103                         ;   for inlined constants.
104    (VUNSPEC_POOL_END 3) ; `end-of-table'.  Used to mark the end of a minipool
105                         ;   table.
106    (VUNSPEC_POOL_1   4) ; `pool-entry(1)'.  An entry in the constant pool for
107                         ;   an 8-bit object.
108    (VUNSPEC_POOL_2   5) ; `pool-entry(2)'.  An entry in the constant pool for
109                         ;   a 16-bit object.
110    (VUNSPEC_POOL_4   6) ; `pool-entry(4)'.  An entry in the constant pool for
111                         ;   a 32-bit object.
112    (VUNSPEC_POOL_8   7) ; `pool-entry(8)'.  An entry in the constant pool for
113                         ;   a 64-bit object.
114    (VUNSPEC_TMRC     8) ; Used by the iWMMXt TMRC instruction.
115    (VUNSPEC_TMCR     9) ; Used by the iWMMXt TMCR instruction.
116    (VUNSPEC_ALIGN8   10) ; 8-byte alignment version of VUNSPEC_ALIGN
117    (VUNSPEC_WCMP_EQ  11) ; Used by the iWMMXt WCMPEQ instructions
118    (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
119    (VUNSPEC_WCMP_GT  13) ; Used by the iwMMXT WCMPGT instructions
120   ]
123 ;;---------------------------------------------------------------------------
124 ;; Attributes
126 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
127 ; generating ARM code.  This is used to control the length of some insn
128 ; patterns that share the same RTL in both ARM and Thumb code.
129 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
131 ; PROG_MODE attribute is used to determine whether condition codes are
132 ; clobbered by a call insn: they are if in prog32 mode.  This is controlled
133 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
134 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
136 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
137 ; scheduling decisions for the load unit and the multiplier.
138 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
140 ; IS_XSCALE is set to 'yes' when compiling for XScale.
141 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
143 ;; Operand number of an input operand that is shifted.  Zero if the
144 ;; given instruction does not shift one of its input operands.
145 (define_attr "shift" "" (const_int 0))
147 ; Floating Point Unit.  If we only have floating point emulation, then there
148 ; is no point in scheduling the floating point insns.  (Well, for best
149 ; performance we should try and group them together).
150 (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
151   (const (symbol_ref "arm_fpu_attr")))
153 ; LENGTH of an instruction (in bytes)
154 (define_attr "length" "" (const_int 4))
156 ; POOL_RANGE is how far away from a constant pool entry that this insn
157 ; can be placed.  If the distance is zero, then this insn will never
158 ; reference the pool.
159 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
160 ; before its address.
161 (define_attr "pool_range" "" (const_int 0))
162 (define_attr "neg_pool_range" "" (const_int 0))
164 ; An assembler sequence may clobber the condition codes without us knowing.
165 ; If such an insn references the pool, then we have no way of knowing how,
166 ; so use the most conservative value for pool_range.
167 (define_asm_attributes
168  [(set_attr "conds" "clob")
169   (set_attr "length" "4")
170   (set_attr "pool_range" "250")])
172 ;; The instruction used to implement a particular pattern.  This
173 ;; information is used by pipeline descriptions to provide accurate
174 ;; scheduling information.
176 (define_attr "insn"
177         "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,other"
178         (const_string "other"))
180 ; TYPE attribute is used to detect floating point instructions which, if
181 ; running on a co-processor can run in parallel with other, basic instructions
182 ; If write-buffer scheduling is enabled then it can also be used in the
183 ; scheduling of writes.
185 ; Classification of each insn
186 ; alu           any alu  instruction that doesn't hit memory or fp
187 ;               regs or have a shifted source operand
188 ; alu_shift     any data instruction that doesn't hit memory or fp
189 ;               regs, but has a source operand shifted by a constant
190 ; alu_shift_reg any data instruction that doesn't hit memory or fp
191 ;               regs, but has a source operand shifted by a register value
192 ; mult          a multiply instruction
193 ; block         blockage insn, this blocks all functional units
194 ; float         a floating point arithmetic operation (subject to expansion)
195 ; fdivd         DFmode floating point division
196 ; fdivs         SFmode floating point division
197 ; fmul          Floating point multiply
198 ; ffmul         Fast floating point multiply
199 ; farith        Floating point arithmetic (4 cycle)
200 ; ffarith       Fast floating point arithmetic (2 cycle)
201 ; float_em      a floating point arithmetic operation that is normally emulated
202 ;               even on a machine with an fpa.
203 ; f_load        a floating point load from memory
204 ; f_store       a floating point store to memory
205 ; f_mem_r       a transfer of a floating point register to a real reg via mem
206 ; r_mem_f       the reverse of f_mem_r
207 ; f_2_r         fast transfer float to arm (no memory needed)
208 ; r_2_f         fast transfer arm to float
209 ; branch        a branch
210 ; call          a subroutine call
211 ; load_byte     load byte(s) from memory to arm registers
212 ; load1         load 1 word from memory to arm registers
213 ; load2         load 2 words from memory to arm registers
214 ; load3         load 3 words from memory to arm registers
215 ; load4         load 4 words from memory to arm registers
216 ; store         store 1 word to memory from arm registers
217 ; store2        store 2 words
218 ; store3        store 3 words
219 ; store4        store 4 (or more) words
220 ;  Additions for Cirrus Maverick co-processor:
221 ; mav_farith    Floating point arithmetic (4 cycle)
222 ; mav_dmult     Double multiplies (7 cycle)
224 (define_attr "type"
225         "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,float_em,f_load,f_store,f_mem_r,r_mem_f,f_2_r,r_2_f,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult" 
226         (if_then_else 
227          (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
228          (const_string "mult")
229          (const_string "alu")))
231 ; Load scheduling, set from the arm_ld_sched variable
232 ; initialized by arm_override_options() 
233 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
235 ; condition codes: this one is used by final_prescan_insn to speed up
236 ; conditionalizing instructions.  It saves having to scan the rtl to see if
237 ; it uses or alters the condition codes.
239 ; USE means that the condition codes are used by the insn in the process of
240 ;   outputting code, this means (at present) that we can't use the insn in
241 ;   inlined branches
243 ; SET means that the purpose of the insn is to set the condition codes in a
244 ;   well defined manner.
246 ; CLOB means that the condition codes are altered in an undefined manner, if
247 ;   they are altered at all
249 ; JUMP_CLOB is used when the condition cannot be represented by a single
250 ;   instruction (UNEQ and LTGT).  These cannot be predicated.
252 ; NOCOND means that the condition codes are neither altered nor affect the
253 ;   output of this insn
255 (define_attr "conds" "use,set,clob,jump_clob,nocond"
256         (if_then_else (eq_attr "type" "call")
257          (if_then_else (eq_attr "prog_mode" "prog32")
258           (const_string "clob") (const_string "nocond"))
259          (const_string "nocond")))
261 ; Predicable means that the insn can be conditionally executed based on
262 ; an automatically added predicate (additional patterns are generated by 
263 ; gen...).  We default to 'no' because no Thumb patterns match this rule
264 ; and not all ARM patterns do.
265 (define_attr "predicable" "no,yes" (const_string "no"))
267 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
268 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
269 ; suffer blockages enough to warrant modelling this (and it can adversely
270 ; affect the schedule).
271 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
273 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
274 ; to stall the processor.  Used with model_wbuf above.
275 (define_attr "write_conflict" "no,yes"
276   (if_then_else (eq_attr "type"
277                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
278                 (const_string "yes")
279                 (const_string "no")))
281 ; Classify the insns into those that take one cycle and those that take more
282 ; than one on the main cpu execution unit.
283 (define_attr "core_cycles" "single,multi"
284   (if_then_else (eq_attr "type"
285                  "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
286                 (const_string "single")
287                 (const_string "multi")))
289 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
290 ;; distant label.  Only applicable to Thumb code.
291 (define_attr "far_jump" "yes,no" (const_string "no"))
293 ;;---------------------------------------------------------------------------
294 ;; Pipeline descriptions
296 ;; Processor type.  This attribute must exactly match the table in 
297 ;; arm-cores.def.
298 (define_attr "tune" 
299              "arm2,arm250,arm3,arm6,arm60,arm600,arm610,arm620,arm7,arm7m,arm7d,arm7dm,arm7di,arm7dmi,arm70,arm700,arm700i,arm710,arm720,arm710c,arm7100,arm7500,arm7500fe,arm7tdmi,arm710t,arm720t,arm740t,arm8,arm810,arm9,arm920,arm920t,arm940t,arm9tdmi,arm9e,ep9312,strongarm,strongarm110,strongarm1100,strongarm1110,arm10tdmi,arm1020t,arm926ejs,arm1026ejs,xscale,iwmmxt,arm1136js,arm1136jfs"
300              (const (symbol_ref "arm_tune")))
302 ;; True if the generic scheduling description should be used.
304 (define_attr "generic_sched" "yes,no"
305         (if_then_else 
306          (eq_attr "tune" "arm926ejs,arm1026ejs,arm1136js,arm1136jfs") 
307          (const_string "no")
308          (const_string "yes")))
309         
310 (include "arm-generic.md")
311 (include "arm926ejs.md")
312 (include "arm1026ejs.md")
313 (include "arm1136jfs.md")
316 ;;---------------------------------------------------------------------------
317 ;; Insn patterns
319 ;; Addition insns.
321 ;; Note: For DImode insns, there is normally no reason why operands should
322 ;; not be in the same register, what we don't want is for something being
323 ;; written to partially overlap something that is an input.
324 ;; Cirrus 64bit additions should not be split because we have a native
325 ;; 64bit addition instructions.
327 (define_expand "adddi3"
328  [(parallel
329    [(set (match_operand:DI           0 "s_register_operand" "")
330           (plus:DI (match_operand:DI 1 "s_register_operand" "")
331                    (match_operand:DI 2 "s_register_operand" "")))
332     (clobber (reg:CC CC_REGNUM))])]
333   "TARGET_EITHER"
334   "
335   if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
336     {
337       if (!cirrus_fp_register (operands[0], DImode))
338         operands[0] = force_reg (DImode, operands[0]);
339       if (!cirrus_fp_register (operands[1], DImode))
340         operands[1] = force_reg (DImode, operands[1]);
341       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
342       DONE;
343     }
345   if (TARGET_THUMB)
346     {
347       if (GET_CODE (operands[1]) != REG)
348         operands[1] = force_reg (SImode, operands[1]);
349       if (GET_CODE (operands[2]) != REG)
350         operands[2] = force_reg (SImode, operands[2]);
351      }
352   "
355 (define_insn "*thumb_adddi3"
356   [(set (match_operand:DI          0 "register_operand" "=l")
357         (plus:DI (match_operand:DI 1 "register_operand" "%0")
358                  (match_operand:DI 2 "register_operand" "l")))
359    (clobber (reg:CC CC_REGNUM))
360   ]
361   "TARGET_THUMB"
362   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
363   [(set_attr "length" "4")]
366 (define_insn_and_split "*arm_adddi3"
367   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
368         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
369                  (match_operand:DI 2 "s_register_operand" "r,  0")))
370    (clobber (reg:CC CC_REGNUM))]
371   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
372   "#"
373   "TARGET_ARM && reload_completed"
374   [(parallel [(set (reg:CC_C CC_REGNUM)
375                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
376                                  (match_dup 1)))
377               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
378    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
379                                (plus:SI (match_dup 4) (match_dup 5))))]
380   "
381   {
382     operands[3] = gen_highpart (SImode, operands[0]);
383     operands[0] = gen_lowpart (SImode, operands[0]);
384     operands[4] = gen_highpart (SImode, operands[1]);
385     operands[1] = gen_lowpart (SImode, operands[1]);
386     operands[5] = gen_highpart (SImode, operands[2]);
387     operands[2] = gen_lowpart (SImode, operands[2]);
388   }"
389   [(set_attr "conds" "clob")
390    (set_attr "length" "8")]
393 (define_insn_and_split "*adddi_sesidi_di"
394   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
395         (plus:DI (sign_extend:DI
396                   (match_operand:SI 2 "s_register_operand" "r,r"))
397                  (match_operand:DI 1 "s_register_operand" "r,0")))
398    (clobber (reg:CC CC_REGNUM))]
399   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
400   "#"
401   "TARGET_ARM && reload_completed"
402   [(parallel [(set (reg:CC_C CC_REGNUM)
403                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
404                                  (match_dup 1)))
405               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
406    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
407                                (plus:SI (ashiftrt:SI (match_dup 2)
408                                                      (const_int 31))
409                                         (match_dup 4))))]
410   "
411   {
412     operands[3] = gen_highpart (SImode, operands[0]);
413     operands[0] = gen_lowpart (SImode, operands[0]);
414     operands[4] = gen_highpart (SImode, operands[1]);
415     operands[1] = gen_lowpart (SImode, operands[1]);
416     operands[2] = gen_lowpart (SImode, operands[2]);
417   }"
418   [(set_attr "conds" "clob")
419    (set_attr "length" "8")]
422 (define_insn_and_split "*adddi_zesidi_di"
423   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
424         (plus:DI (zero_extend:DI
425                   (match_operand:SI 2 "s_register_operand" "r,r"))
426                  (match_operand:DI 1 "s_register_operand" "r,0")))
427    (clobber (reg:CC CC_REGNUM))]
428   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
429   "#"
430   "TARGET_ARM && reload_completed"
431   [(parallel [(set (reg:CC_C CC_REGNUM)
432                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
433                                  (match_dup 1)))
434               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
435    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
436                                (plus:SI (match_dup 4) (const_int 0))))]
437   "
438   {
439     operands[3] = gen_highpart (SImode, operands[0]);
440     operands[0] = gen_lowpart (SImode, operands[0]);
441     operands[4] = gen_highpart (SImode, operands[1]);
442     operands[1] = gen_lowpart (SImode, operands[1]);
443     operands[2] = gen_lowpart (SImode, operands[2]);
444   }"
445   [(set_attr "conds" "clob")
446    (set_attr "length" "8")]
449 (define_expand "addsi3"
450   [(set (match_operand:SI          0 "s_register_operand" "")
451         (plus:SI (match_operand:SI 1 "s_register_operand" "")
452                  (match_operand:SI 2 "reg_or_int_operand" "")))]
453   "TARGET_EITHER"
454   "
455   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
456     {
457       arm_split_constant (PLUS, SImode, NULL_RTX,
458                           INTVAL (operands[2]), operands[0], operands[1],
459                           (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
460       DONE;
461     }
462   "
465 ; If there is a scratch available, this will be faster than synthesizing the
466 ; addition.
467 (define_peephole2
468   [(match_scratch:SI 3 "r")
469    (set (match_operand:SI          0 "s_register_operand" "")
470         (plus:SI (match_operand:SI 1 "s_register_operand" "")
471                  (match_operand:SI 2 "const_int_operand"  "")))]
472   "TARGET_ARM &&
473    !(const_ok_for_arm (INTVAL (operands[2]))
474      || const_ok_for_arm (-INTVAL (operands[2])))
475     && const_ok_for_arm (~INTVAL (operands[2]))"
476   [(set (match_dup 3) (match_dup 2))
477    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
478   ""
481 (define_insn_and_split "*arm_addsi3"
482   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
483         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
484                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
485   "TARGET_ARM"
486   "@
487    add%?\\t%0, %1, %2
488    sub%?\\t%0, %1, #%n2
489    #"
490   "TARGET_ARM &&
491    GET_CODE (operands[2]) == CONST_INT
492    && !(const_ok_for_arm (INTVAL (operands[2]))
493         || const_ok_for_arm (-INTVAL (operands[2])))"
494   [(clobber (const_int 0))]
495   "
496   arm_split_constant (PLUS, SImode, curr_insn,
497                       INTVAL (operands[2]), operands[0],
498                       operands[1], 0);
499   DONE;
500   "
501   [(set_attr "length" "4,4,16")
502    (set_attr "predicable" "yes")]
505 ;; Register group 'k' is a single register group containing only the stack
506 ;; register.  Trying to reload it will always fail catastrophically,
507 ;; so never allow those alternatives to match if reloading is needed.
509 (define_insn "*thumb_addsi3"
510   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
511         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
512                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
513   "TARGET_THUMB"
514   "*
515    static const char * const asms[] = 
516    {
517      \"add\\t%0, %0, %2\",
518      \"sub\\t%0, %0, #%n2\",
519      \"add\\t%0, %1, %2\",
520      \"add\\t%0, %0, %2\",
521      \"add\\t%0, %0, %2\",
522      \"add\\t%0, %1, %2\",
523      \"add\\t%0, %1, %2\"
524    };
525    if ((which_alternative == 2 || which_alternative == 6)
526        && GET_CODE (operands[2]) == CONST_INT
527        && INTVAL (operands[2]) < 0)
528      return \"sub\\t%0, %1, #%n2\";
529    return asms[which_alternative];
530   "
531   [(set_attr "length" "2")]
534 ;; Reloading and elimination of the frame pointer can
535 ;; sometimes cause this optimization to be missed.
536 (define_peephole2
537   [(set (match_operand:SI 0 "register_operand" "")
538         (match_operand:SI 1 "const_int_operand" ""))
539    (set (match_dup 0)
540         (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))]
541   "TARGET_THUMB
542    && REGNO (operands[2]) == STACK_POINTER_REGNUM 
543    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
544    && (INTVAL (operands[1]) & 3) == 0"
545   [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
546   ""
549 (define_insn "*addsi3_compare0"
550   [(set (reg:CC_NOOV CC_REGNUM)
551         (compare:CC_NOOV
552          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
553                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
554          (const_int 0)))
555    (set (match_operand:SI 0 "s_register_operand" "=r,r")
556         (plus:SI (match_dup 1) (match_dup 2)))]
557   "TARGET_ARM"
558   "@
559    add%?s\\t%0, %1, %2
560    sub%?s\\t%0, %1, #%n2"
561   [(set_attr "conds" "set")]
564 (define_insn "*addsi3_compare0_scratch"
565   [(set (reg:CC_NOOV CC_REGNUM)
566         (compare:CC_NOOV
567          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
568                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
569          (const_int 0)))]
570   "TARGET_ARM"
571   "@
572    cmn%?\\t%0, %1
573    cmp%?\\t%0, #%n1"
574   [(set_attr "conds" "set")]
577 ;; These patterns are the same ones as the two regular addsi3_compare0
578 ;; patterns, except we write them slightly different - the combiner
579 ;; tends to generate them this way.
580 (define_insn "*addsi3_compare0_for_combiner"
581   [(set (reg:CC CC_REGNUM)
582         (compare:CC
583          (match_operand:SI 1 "s_register_operand" "r,r")
584          (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
585    (set (match_operand:SI 0 "s_register_operand" "=r,r")
586         (plus:SI (match_dup 1) (match_dup 2)))]
587   "TARGET_ARM"
588   "@
589    add%?s\\t%0, %1, %2
590    sub%?s\\t%0, %1, #%n2"
591   [(set_attr "conds" "set")]
594 (define_insn "*addsi3_compare0_scratch_for_combiner"
595   [(set (reg:CC CC_REGNUM)
596         (compare:CC
597          (match_operand:SI 0 "s_register_operand" "r,r")
598          (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
599   "TARGET_ARM"
600   "@
601    cmn%?\\t%0, %1
602    cmp%?\\t%0, #%n1"
603   [(set_attr "conds" "set")]
606 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
607 ;; addend is a constant.
608 (define_insn "*cmpsi2_addneg"
609   [(set (reg:CC CC_REGNUM)
610         (compare:CC
611          (match_operand:SI 1 "s_register_operand" "r,r")
612          (match_operand:SI 2 "arm_addimm_operand" "I,L")))
613    (set (match_operand:SI 0 "s_register_operand" "=r,r")
614         (plus:SI (match_dup 1)
615                  (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
616   "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
617   "@
618    sub%?s\\t%0, %1, %2
619    add%?s\\t%0, %1, #%n2"
620   [(set_attr "conds" "set")]
623 ;; Convert the sequence
624 ;;  sub  rd, rn, #1
625 ;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
626 ;;  bne  dest
627 ;; into
628 ;;  subs rd, rn, #1
629 ;;  bcs  dest   ((unsigned)rn >= 1)
630 ;; similarly for the beq variant using bcc.
631 ;; This is a common looping idiom (while (n--))
632 (define_peephole2
633   [(set (match_operand:SI 0 "s_register_operand" "")
634         (plus:SI (match_operand:SI 1 "s_register_operand" "")
635                  (const_int -1)))
636    (set (match_operand 2 "cc_register" "")
637         (compare (match_dup 0) (const_int -1)))
638    (set (pc)
639         (if_then_else (match_operator 3 "equality_operator"
640                        [(match_dup 2) (const_int 0)])
641                       (match_operand 4 "" "")
642                       (match_operand 5 "" "")))]
643   "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
644   [(parallel[
645     (set (match_dup 2)
646          (compare:CC
647           (match_dup 1) (const_int 1)))
648     (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
649    (set (pc)
650         (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
651                       (match_dup 4)
652                       (match_dup 5)))]
653   "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
654    operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
655                                   ? GEU : LTU),
656                                  VOIDmode, 
657                                  operands[2], const0_rtx);"
660 ;; The next four insns work because they compare the result with one of
661 ;; the operands, and we know that the use of the condition code is
662 ;; either GEU or LTU, so we can use the carry flag from the addition
663 ;; instead of doing the compare a second time.
664 (define_insn "*addsi3_compare_op1"
665   [(set (reg:CC_C CC_REGNUM)
666         (compare:CC_C
667          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
668                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
669          (match_dup 1)))
670    (set (match_operand:SI 0 "s_register_operand" "=r,r")
671         (plus:SI (match_dup 1) (match_dup 2)))]
672   "TARGET_ARM"
673   "@
674    add%?s\\t%0, %1, %2
675    sub%?s\\t%0, %1, #%n2"
676   [(set_attr "conds" "set")]
679 (define_insn "*addsi3_compare_op2"
680   [(set (reg:CC_C CC_REGNUM)
681         (compare:CC_C
682          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
683                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
684          (match_dup 2)))
685    (set (match_operand:SI 0 "s_register_operand" "=r,r")
686         (plus:SI (match_dup 1) (match_dup 2)))]
687   "TARGET_ARM"
688   "@
689    add%?s\\t%0, %1, %2
690    sub%?s\\t%0, %1, #%n2"
691   [(set_attr "conds" "set")]
694 (define_insn "*compare_addsi2_op0"
695   [(set (reg:CC_C CC_REGNUM)
696         (compare:CC_C
697          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
698                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
699          (match_dup 0)))]
700   "TARGET_ARM"
701   "@
702    cmn%?\\t%0, %1
703    cmp%?\\t%0, #%n1"
704   [(set_attr "conds" "set")]
707 (define_insn "*compare_addsi2_op1"
708   [(set (reg:CC_C CC_REGNUM)
709         (compare:CC_C
710          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
711                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
712          (match_dup 1)))]
713   "TARGET_ARM"
714   "@
715    cmn%?\\t%0, %1
716    cmp%?\\t%0, #%n1"
717   [(set_attr "conds" "set")]
720 (define_insn "*addsi3_carryin"
721   [(set (match_operand:SI 0 "s_register_operand" "=r")
722         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
723                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
724                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
725   "TARGET_ARM"
726   "adc%?\\t%0, %1, %2"
727   [(set_attr "conds" "use")]
730 (define_insn "*addsi3_carryin_shift"
731   [(set (match_operand:SI 0 "s_register_operand" "=r")
732         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
733                  (plus:SI
734                    (match_operator:SI 2 "shift_operator"
735                       [(match_operand:SI 3 "s_register_operand" "r")
736                        (match_operand:SI 4 "reg_or_int_operand" "rM")])
737                     (match_operand:SI 1 "s_register_operand" "r"))))]
738   "TARGET_ARM"
739   "adc%?\\t%0, %1, %3%S2"
740   [(set_attr "conds" "use")
741    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
742                       (const_string "alu_shift")
743                       (const_string "alu_shift_reg")))]
746 (define_insn "*addsi3_carryin_alt1"
747   [(set (match_operand:SI 0 "s_register_operand" "=r")
748         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
749                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
750                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
751   "TARGET_ARM"
752   "adc%?\\t%0, %1, %2"
753   [(set_attr "conds" "use")]
756 (define_insn "*addsi3_carryin_alt2"
757   [(set (match_operand:SI 0 "s_register_operand" "=r")
758         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
759                           (match_operand:SI 1 "s_register_operand" "r"))
760                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
761   "TARGET_ARM"
762   "adc%?\\t%0, %1, %2"
763   [(set_attr "conds" "use")]
766 (define_insn "*addsi3_carryin_alt3"
767   [(set (match_operand:SI 0 "s_register_operand" "=r")
768         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
769                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
770                  (match_operand:SI 1 "s_register_operand" "r")))]
771   "TARGET_ARM"
772   "adc%?\\t%0, %1, %2"
773   [(set_attr "conds" "use")]
776 (define_insn "incscc"
777   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
778         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
779                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
780                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
781   "TARGET_ARM"
782   "@
783   add%d2\\t%0, %1, #1
784   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
785   [(set_attr "conds" "use")
786    (set_attr "length" "4,8")]
789 ; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
790 (define_split
791   [(set (match_operand:SI 0 "s_register_operand" "")
792         (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
793                             (match_operand:SI 2 "s_register_operand" ""))
794                  (const_int -1)))
795    (clobber (match_operand:SI 3 "s_register_operand" ""))]
796   "TARGET_ARM"
797   [(set (match_dup 3) (match_dup 1))
798    (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
799   "
800   operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
803 (define_expand "addsf3"
804   [(set (match_operand:SF          0 "s_register_operand" "")
805         (plus:SF (match_operand:SF 1 "s_register_operand" "")
806                  (match_operand:SF 2 "arm_float_add_operand" "")))]
807   "TARGET_ARM && TARGET_HARD_FLOAT"
808   "
809   if (TARGET_MAVERICK
810       && !cirrus_fp_register (operands[2], SFmode))
811     operands[2] = force_reg (SFmode, operands[2]);
814 (define_expand "adddf3"
815   [(set (match_operand:DF          0 "s_register_operand" "")
816         (plus:DF (match_operand:DF 1 "s_register_operand" "")
817                  (match_operand:DF 2 "arm_float_add_operand" "")))]
818   "TARGET_ARM && TARGET_HARD_FLOAT"
819   "
820   if (TARGET_MAVERICK
821       && !cirrus_fp_register (operands[2], DFmode))
822     operands[2] = force_reg (DFmode, operands[2]);
825 (define_expand "subdi3"
826  [(parallel
827    [(set (match_operand:DI            0 "s_register_operand" "")
828           (minus:DI (match_operand:DI 1 "s_register_operand" "")
829                     (match_operand:DI 2 "s_register_operand" "")))
830     (clobber (reg:CC CC_REGNUM))])]
831   "TARGET_EITHER"
832   "
833   if (TARGET_HARD_FLOAT && TARGET_MAVERICK
834       && TARGET_ARM
835       && cirrus_fp_register (operands[0], DImode)
836       && cirrus_fp_register (operands[1], DImode))
837     {
838       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
839       DONE;
840     }
842   if (TARGET_THUMB)
843     {
844       if (GET_CODE (operands[1]) != REG)
845         operands[1] = force_reg (SImode, operands[1]);
846       if (GET_CODE (operands[2]) != REG)
847         operands[2] = force_reg (SImode, operands[2]);
848      }  
849   "
852 (define_insn "*arm_subdi3"
853   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
854         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
855                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
856    (clobber (reg:CC CC_REGNUM))]
857   "TARGET_ARM"
858   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
859   [(set_attr "conds" "clob")
860    (set_attr "length" "8")]
863 (define_insn "*thumb_subdi3"
864   [(set (match_operand:DI           0 "register_operand" "=l")
865         (minus:DI (match_operand:DI 1 "register_operand"  "0")
866                   (match_operand:DI 2 "register_operand"  "l")))
867    (clobber (reg:CC CC_REGNUM))]
868   "TARGET_THUMB"
869   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
870   [(set_attr "length" "4")]
873 (define_insn "*subdi_di_zesidi"
874   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
875         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
876                   (zero_extend:DI
877                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
878    (clobber (reg:CC CC_REGNUM))]
879   "TARGET_ARM"
880   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
881   [(set_attr "conds" "clob")
882    (set_attr "length" "8")]
885 (define_insn "*subdi_di_sesidi"
886   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
887         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
888                   (sign_extend:DI
889                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
890    (clobber (reg:CC CC_REGNUM))]
891   "TARGET_ARM"
892   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
893   [(set_attr "conds" "clob")
894    (set_attr "length" "8")]
897 (define_insn "*subdi_zesidi_di"
898   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
899         (minus:DI (zero_extend:DI
900                    (match_operand:SI 2 "s_register_operand"  "r,r"))
901                   (match_operand:DI  1 "s_register_operand" "?r,0")))
902    (clobber (reg:CC CC_REGNUM))]
903   "TARGET_ARM"
904   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
905   [(set_attr "conds" "clob")
906    (set_attr "length" "8")]
909 (define_insn "*subdi_sesidi_di"
910   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
911         (minus:DI (sign_extend:DI
912                    (match_operand:SI 2 "s_register_operand"   "r,r"))
913                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
914    (clobber (reg:CC CC_REGNUM))]
915   "TARGET_ARM"
916   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
917   [(set_attr "conds" "clob")
918    (set_attr "length" "8")]
921 (define_insn "*subdi_zesidi_zesidi"
922   [(set (match_operand:DI            0 "s_register_operand" "=r")
923         (minus:DI (zero_extend:DI
924                    (match_operand:SI 1 "s_register_operand"  "r"))
925                   (zero_extend:DI
926                    (match_operand:SI 2 "s_register_operand"  "r"))))
927    (clobber (reg:CC CC_REGNUM))]
928   "TARGET_ARM"
929   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
930   [(set_attr "conds" "clob")
931    (set_attr "length" "8")]
934 (define_expand "subsi3"
935   [(set (match_operand:SI           0 "s_register_operand" "")
936         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
937                   (match_operand:SI 2 "s_register_operand" "")))]
938   "TARGET_EITHER"
939   "
940   if (GET_CODE (operands[1]) == CONST_INT)
941     {
942       if (TARGET_ARM)
943         {
944           arm_split_constant (MINUS, SImode, NULL_RTX,
945                               INTVAL (operands[1]), operands[0],
946                               operands[2],
947                               (no_new_pseudos ? 0
948                                :  preserve_subexpressions_p ()));
949           DONE;
950         }
951       else /* TARGET_THUMB */
952         operands[1] = force_reg (SImode, operands[1]);
953     }
954   "
957 (define_insn "*thumb_subsi3_insn"
958   [(set (match_operand:SI           0 "register_operand" "=l")
959         (minus:SI (match_operand:SI 1 "register_operand" "l")
960                   (match_operand:SI 2 "register_operand" "l")))]
961   "TARGET_THUMB"
962   "sub\\t%0, %1, %2"
963   [(set_attr "length" "2")]
966 (define_insn_and_split "*arm_subsi3_insn"
967   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
968         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
969                   (match_operand:SI 2 "s_register_operand" "r,r")))]
970   "TARGET_ARM"
971   "@
972    rsb%?\\t%0, %2, %1
973    #"
974   "TARGET_ARM
975    && GET_CODE (operands[1]) == CONST_INT
976    && !const_ok_for_arm (INTVAL (operands[1]))"
977   [(clobber (const_int 0))]
978   "
979   arm_split_constant (MINUS, SImode, curr_insn,
980                       INTVAL (operands[1]), operands[0], operands[2], 0);
981   DONE;
982   "
983   [(set_attr "length" "4,16")
984    (set_attr "predicable" "yes")]
987 (define_peephole2
988   [(match_scratch:SI 3 "r")
989    (set (match_operand:SI           0 "s_register_operand" "")
990         (minus:SI (match_operand:SI 1 "const_int_operand" "")
991                   (match_operand:SI 2 "s_register_operand" "")))]
992   "TARGET_ARM
993    && !const_ok_for_arm (INTVAL (operands[1]))
994    && const_ok_for_arm (~INTVAL (operands[1]))"
995   [(set (match_dup 3) (match_dup 1))
996    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
997   ""
1000 (define_insn "*subsi3_compare0"
1001   [(set (reg:CC_NOOV CC_REGNUM)
1002         (compare:CC_NOOV
1003          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1004                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1005          (const_int 0)))
1006    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1007         (minus:SI (match_dup 1) (match_dup 2)))]
1008   "TARGET_ARM"
1009   "@
1010    sub%?s\\t%0, %1, %2
1011    rsb%?s\\t%0, %2, %1"
1012   [(set_attr "conds" "set")]
1015 (define_insn "decscc"
1016   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1017         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1018                   (match_operator:SI 2 "arm_comparison_operator"
1019                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1020   "TARGET_ARM"
1021   "@
1022    sub%d2\\t%0, %1, #1
1023    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1024   [(set_attr "conds" "use")
1025    (set_attr "length" "*,8")]
1028 (define_expand "subsf3"
1029   [(set (match_operand:SF           0 "s_register_operand" "")
1030         (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1031                   (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1032   "TARGET_ARM && TARGET_HARD_FLOAT"
1033   "
1034   if (TARGET_MAVERICK)
1035     {
1036       if (!cirrus_fp_register (operands[1], SFmode))
1037         operands[1] = force_reg (SFmode, operands[1]);
1038       if (!cirrus_fp_register (operands[2], SFmode))
1039         operands[2] = force_reg (SFmode, operands[2]);
1040     }
1043 (define_expand "subdf3"
1044   [(set (match_operand:DF           0 "s_register_operand" "")
1045         (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1046                   (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1047   "TARGET_ARM && TARGET_HARD_FLOAT"
1048   "
1049   if (TARGET_MAVERICK)
1050     {
1051        if (!cirrus_fp_register (operands[1], DFmode))
1052          operands[1] = force_reg (DFmode, operands[1]);
1053        if (!cirrus_fp_register (operands[2], DFmode))
1054          operands[2] = force_reg (DFmode, operands[2]);
1055     }
1059 ;; Multiplication insns
1061 (define_expand "mulsi3"
1062   [(set (match_operand:SI          0 "s_register_operand" "")
1063         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1064                  (match_operand:SI 1 "s_register_operand" "")))]
1065   "TARGET_EITHER"
1066   ""
1069 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1070 (define_insn "*arm_mulsi3"
1071   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1072         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1073                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1074   "TARGET_ARM"
1075   "mul%?\\t%0, %2, %1"
1076   [(set_attr "insn" "mul")
1077    (set_attr "predicable" "yes")]
1080 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1081 ; 1 and 2; are the same, because reload will make operand 0 match 
1082 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1083 ; this by adding another alternative to match this case, and then `reload' 
1084 ; it ourselves.  This alternative must come first.
1085 (define_insn "*thumb_mulsi3"
1086   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1087         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1088                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1089   "TARGET_THUMB"
1090   "*
1091   if (which_alternative < 2)
1092     return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1093   else
1094     return \"mul\\t%0, %0, %2\";
1095   "
1096   [(set_attr "length" "4,4,2")
1097    (set_attr "insn" "mul")]
1100 (define_insn "*mulsi3_compare0"
1101   [(set (reg:CC_NOOV CC_REGNUM)
1102         (compare:CC_NOOV (mult:SI
1103                           (match_operand:SI 2 "s_register_operand" "r,r")
1104                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1105                          (const_int 0)))
1106    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1107         (mult:SI (match_dup 2) (match_dup 1)))]
1108   "TARGET_ARM && !arm_arch_xscale"
1109   "mul%?s\\t%0, %2, %1"
1110   [(set_attr "conds" "set")
1111    (set_attr "insn" "muls")]
1114 (define_insn "*mulsi_compare0_scratch"
1115   [(set (reg:CC_NOOV CC_REGNUM)
1116         (compare:CC_NOOV (mult:SI
1117                           (match_operand:SI 2 "s_register_operand" "r,r")
1118                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1119                          (const_int 0)))
1120    (clobber (match_scratch:SI 0 "=&r,&r"))]
1121   "TARGET_ARM && !arm_arch_xscale"
1122   "mul%?s\\t%0, %2, %1"
1123   [(set_attr "conds" "set")
1124    (set_attr "insn" "muls")]
1127 ;; Unnamed templates to match MLA instruction.
1129 (define_insn "*mulsi3addsi"
1130   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1131         (plus:SI
1132           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1133                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1134           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1135   "TARGET_ARM"
1136   "mla%?\\t%0, %2, %1, %3"
1137   [(set_attr "insn" "mla")
1138    (set_attr "predicable" "yes")]
1141 (define_insn "*mulsi3addsi_compare0"
1142   [(set (reg:CC_NOOV CC_REGNUM)
1143         (compare:CC_NOOV
1144          (plus:SI (mult:SI
1145                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1146                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1147                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1148          (const_int 0)))
1149    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1150         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1151                  (match_dup 3)))]
1152   "TARGET_ARM && !arm_arch_xscale"
1153   "mla%?s\\t%0, %2, %1, %3"
1154   [(set_attr "conds" "set")
1155    (set_attr "insn" "mlas")]
1158 (define_insn "*mulsi3addsi_compare0_scratch"
1159   [(set (reg:CC_NOOV CC_REGNUM)
1160         (compare:CC_NOOV
1161          (plus:SI (mult:SI
1162                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1163                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1164                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1165          (const_int 0)))
1166    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1167   "TARGET_ARM && !arm_arch_xscale"
1168   "mla%?s\\t%0, %2, %1, %3"
1169   [(set_attr "conds" "set")
1170    (set_attr "insn" "mlas")]
1173 ;; Unnamed template to match long long multiply-accumulate (smlal)
1175 (define_insn "*mulsidi3adddi"
1176   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1177         (plus:DI
1178          (mult:DI
1179           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1180           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1181          (match_operand:DI 1 "s_register_operand" "0")))]
1182   "TARGET_ARM && arm_arch3m"
1183   "smlal%?\\t%Q0, %R0, %3, %2"
1184   [(set_attr "insn" "smlal")
1185    (set_attr "predicable" "yes")]
1188 (define_insn "mulsidi3"
1189   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1190         (mult:DI
1191          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1192          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1193   "TARGET_ARM && arm_arch3m"
1194   "smull%?\\t%Q0, %R0, %1, %2"
1195   [(set_attr "insn" "smull")
1196    (set_attr "predicable" "yes")]
1199 (define_insn "umulsidi3"
1200   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1201         (mult:DI
1202          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1203          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1204   "TARGET_ARM && arm_arch3m"
1205   "umull%?\\t%Q0, %R0, %1, %2"
1206   [(set_attr "insn" "umull")
1207    (set_attr "predicable" "yes")]
1210 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1212 (define_insn "*umulsidi3adddi"
1213   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1214         (plus:DI
1215          (mult:DI
1216           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1217           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1218          (match_operand:DI 1 "s_register_operand" "0")))]
1219   "TARGET_ARM && arm_arch3m"
1220   "umlal%?\\t%Q0, %R0, %3, %2"
1221   [(set_attr "insn" "umlal")
1222    (set_attr "predicable" "yes")]
1225 (define_insn "smulsi3_highpart"
1226   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1227         (truncate:SI
1228          (lshiftrt:DI
1229           (mult:DI
1230            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1231            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1232           (const_int 32))))
1233    (clobber (match_scratch:SI 3 "=&r,&r"))]
1234   "TARGET_ARM && arm_arch3m"
1235   "smull%?\\t%3, %0, %2, %1"
1236   [(set_attr "insn" "smull")
1237    (set_attr "predicable" "yes")]
1240 (define_insn "umulsi3_highpart"
1241   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1242         (truncate:SI
1243          (lshiftrt:DI
1244           (mult:DI
1245            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1246            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1247           (const_int 32))))
1248    (clobber (match_scratch:SI 3 "=&r,&r"))]
1249   "TARGET_ARM && arm_arch3m"
1250   "umull%?\\t%3, %0, %2, %1"
1251   [(set_attr "insn" "umull")
1252    (set_attr "predicable" "yes")]
1255 (define_insn "mulhisi3"
1256   [(set (match_operand:SI 0 "s_register_operand" "=r")
1257         (mult:SI (sign_extend:SI
1258                   (match_operand:HI 1 "s_register_operand" "%r"))
1259                  (sign_extend:SI
1260                   (match_operand:HI 2 "s_register_operand" "r"))))]
1261   "TARGET_ARM && arm_arch5e"
1262   "smulbb%?\\t%0, %1, %2"
1263   [(set_attr "insn" "smulxy")
1264    (set_attr "predicable" "yes")]
1267 (define_insn "*mulhisi3tb"
1268   [(set (match_operand:SI 0 "s_register_operand" "=r")
1269         (mult:SI (ashiftrt:SI
1270                   (match_operand:SI 1 "s_register_operand" "r")
1271                   (const_int 16))
1272                  (sign_extend:SI
1273                   (match_operand:HI 2 "s_register_operand" "r"))))]
1274   "TARGET_ARM && arm_arch5e"
1275   "smultb%?\\t%0, %1, %2"
1276   [(set_attr "insn" "smulxy")
1277    (set_attr "predicable" "yes")]
1280 (define_insn "*mulhisi3bt"
1281   [(set (match_operand:SI 0 "s_register_operand" "=r")
1282         (mult:SI (sign_extend:SI
1283                   (match_operand:HI 1 "s_register_operand" "r"))
1284                  (ashiftrt:SI
1285                   (match_operand:SI 2 "s_register_operand" "r")
1286                   (const_int 16))))]
1287   "TARGET_ARM && arm_arch5e"
1288   "smulbt%?\\t%0, %1, %2"
1289   [(set_attr "insn" "smulxy")
1290    (set_attr "predicable" "yes")]
1293 (define_insn "*mulhisi3tt"
1294   [(set (match_operand:SI 0 "s_register_operand" "=r")
1295         (mult:SI (ashiftrt:SI
1296                   (match_operand:SI 1 "s_register_operand" "r")
1297                   (const_int 16))
1298                  (ashiftrt:SI
1299                   (match_operand:SI 2 "s_register_operand" "r")
1300                   (const_int 16))))]
1301   "TARGET_ARM && arm_arch5e"
1302   "smultt%?\\t%0, %1, %2"
1303   [(set_attr "insn" "smulxy")
1304    (set_attr "predicable" "yes")]
1307 (define_insn "*mulhisi3addsi"
1308   [(set (match_operand:SI 0 "s_register_operand" "=r")
1309         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1310                  (mult:SI (sign_extend:SI
1311                            (match_operand:HI 2 "s_register_operand" "%r"))
1312                           (sign_extend:SI
1313                            (match_operand:HI 3 "s_register_operand" "r")))))]
1314   "TARGET_ARM && arm_arch5e"
1315   "smlabb%?\\t%0, %2, %3, %1"
1316   [(set_attr "insn" "smlaxy")
1317    (set_attr "predicable" "yes")]
1320 (define_insn "*mulhidi3adddi"
1321   [(set (match_operand:DI 0 "s_register_operand" "=r")
1322         (plus:DI
1323           (match_operand:DI 1 "s_register_operand" "0")
1324           (mult:DI (sign_extend:DI
1325                     (match_operand:HI 2 "s_register_operand" "%r"))
1326                    (sign_extend:DI
1327                     (match_operand:HI 3 "s_register_operand" "r")))))]
1328   "TARGET_ARM && arm_arch5e"
1329   "smlalbb%?\\t%Q0, %R0, %2, %3"
1330   [(set_attr "insn" "smlalxy")
1331    (set_attr "predicable" "yes")])
1333 (define_expand "mulsf3"
1334   [(set (match_operand:SF          0 "s_register_operand" "")
1335         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1336                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1337   "TARGET_ARM && TARGET_HARD_FLOAT"
1338   "
1339   if (TARGET_MAVERICK
1340       && !cirrus_fp_register (operands[2], SFmode))
1341     operands[2] = force_reg (SFmode, operands[2]);
1344 (define_expand "muldf3"
1345   [(set (match_operand:DF          0 "s_register_operand" "")
1346         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1347                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1348   "TARGET_ARM && TARGET_HARD_FLOAT"
1349   "
1350   if (TARGET_MAVERICK
1351       && !cirrus_fp_register (operands[2], DFmode))
1352     operands[2] = force_reg (DFmode, operands[2]);
1355 ;; Division insns
1357 (define_expand "divsf3"
1358   [(set (match_operand:SF 0 "s_register_operand" "")
1359         (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1360                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1361   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1362   "")
1364 (define_expand "divdf3"
1365   [(set (match_operand:DF 0 "s_register_operand" "")
1366         (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1367                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1368   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1369   "")
1371 ;; Modulo insns
1373 (define_expand "modsf3"
1374   [(set (match_operand:SF 0 "s_register_operand" "")
1375         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1376                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1377   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1378   "")
1380 (define_expand "moddf3"
1381   [(set (match_operand:DF 0 "s_register_operand" "")
1382         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1383                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1384   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1385   "")
1387 ;; Boolean and,ior,xor insns
1389 ;; Split up double word logical operations
1391 ;; Split up simple DImode logical operations.  Simply perform the logical
1392 ;; operation on the upper and lower halves of the registers.
1393 (define_split
1394   [(set (match_operand:DI 0 "s_register_operand" "")
1395         (match_operator:DI 6 "logical_binary_operator"
1396           [(match_operand:DI 1 "s_register_operand" "")
1397            (match_operand:DI 2 "s_register_operand" "")]))]
1398   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1399   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1400    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1401   "
1402   {
1403     operands[3] = gen_highpart (SImode, operands[0]);
1404     operands[0] = gen_lowpart (SImode, operands[0]);
1405     operands[4] = gen_highpart (SImode, operands[1]);
1406     operands[1] = gen_lowpart (SImode, operands[1]);
1407     operands[5] = gen_highpart (SImode, operands[2]);
1408     operands[2] = gen_lowpart (SImode, operands[2]);
1409   }"
1412 (define_split
1413   [(set (match_operand:DI 0 "s_register_operand" "")
1414         (match_operator:DI 6 "logical_binary_operator"
1415           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1416            (match_operand:DI 1 "s_register_operand" "")]))]
1417   "TARGET_ARM && reload_completed"
1418   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1419    (set (match_dup 3) (match_op_dup:SI 6
1420                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1421                          (match_dup 4)]))]
1422   "
1423   {
1424     operands[3] = gen_highpart (SImode, operands[0]);
1425     operands[0] = gen_lowpart (SImode, operands[0]);
1426     operands[4] = gen_highpart (SImode, operands[1]);
1427     operands[1] = gen_lowpart (SImode, operands[1]);
1428     operands[5] = gen_highpart (SImode, operands[2]);
1429     operands[2] = gen_lowpart (SImode, operands[2]);
1430   }"
1433 ;; The zero extend of operand 2 means we can just copy the high part of
1434 ;; operand1 into operand0.
1435 (define_split
1436   [(set (match_operand:DI 0 "s_register_operand" "")
1437         (ior:DI
1438           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1439           (match_operand:DI 1 "s_register_operand" "")))]
1440   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1441   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1442    (set (match_dup 3) (match_dup 4))]
1443   "
1444   {
1445     operands[4] = gen_highpart (SImode, operands[1]);
1446     operands[3] = gen_highpart (SImode, operands[0]);
1447     operands[0] = gen_lowpart (SImode, operands[0]);
1448     operands[1] = gen_lowpart (SImode, operands[1]);
1449   }"
1452 ;; The zero extend of operand 2 means we can just copy the high part of
1453 ;; operand1 into operand0.
1454 (define_split
1455   [(set (match_operand:DI 0 "s_register_operand" "")
1456         (xor:DI
1457           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1458           (match_operand:DI 1 "s_register_operand" "")))]
1459   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1460   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1461    (set (match_dup 3) (match_dup 4))]
1462   "
1463   {
1464     operands[4] = gen_highpart (SImode, operands[1]);
1465     operands[3] = gen_highpart (SImode, operands[0]);
1466     operands[0] = gen_lowpart (SImode, operands[0]);
1467     operands[1] = gen_lowpart (SImode, operands[1]);
1468   }"
1471 (define_insn "anddi3"
1472   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1473         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1474                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1475   "TARGET_ARM && ! TARGET_IWMMXT"
1476   "#"
1477   [(set_attr "length" "8")]
1480 (define_insn_and_split "*anddi_zesidi_di"
1481   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1482         (and:DI (zero_extend:DI
1483                  (match_operand:SI 2 "s_register_operand" "r,r"))
1484                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1485   "TARGET_ARM"
1486   "#"
1487   "TARGET_ARM && reload_completed"
1488   ; The zero extend of operand 2 clears the high word of the output
1489   ; operand.
1490   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1491    (set (match_dup 3) (const_int 0))]
1492   "
1493   {
1494     operands[3] = gen_highpart (SImode, operands[0]);
1495     operands[0] = gen_lowpart (SImode, operands[0]);
1496     operands[1] = gen_lowpart (SImode, operands[1]);
1497   }"
1498   [(set_attr "length" "8")]
1501 (define_insn "*anddi_sesdi_di"
1502   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1503         (and:DI (sign_extend:DI
1504                  (match_operand:SI 2 "s_register_operand" "r,r"))
1505                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1506   "TARGET_ARM"
1507   "#"
1508   [(set_attr "length" "8")]
1511 (define_expand "andsi3"
1512   [(set (match_operand:SI         0 "s_register_operand" "")
1513         (and:SI (match_operand:SI 1 "s_register_operand" "")
1514                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1515   "TARGET_EITHER"
1516   "
1517   if (TARGET_ARM)
1518     {
1519       if (GET_CODE (operands[2]) == CONST_INT)
1520         {
1521           arm_split_constant (AND, SImode, NULL_RTX,
1522                               INTVAL (operands[2]), operands[0],
1523                               operands[1],
1524                               (no_new_pseudos
1525                                ? 0 : preserve_subexpressions_p ()));
1526           DONE;
1527         }
1528     }
1529   else /* TARGET_THUMB */
1530     {
1531       if (GET_CODE (operands[2]) != CONST_INT)
1532         operands[2] = force_reg (SImode, operands[2]);
1533       else
1534         {
1535           int i;
1536           
1537           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1538             {
1539               operands[2] = force_reg (SImode,
1540                                        GEN_INT (~INTVAL (operands[2])));
1541               
1542               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1543               
1544               DONE;
1545             }
1547           for (i = 9; i <= 31; i++)
1548             {
1549               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1550                 {
1551                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1552                                         const0_rtx));
1553                   DONE;
1554                 }
1555               else if ((((HOST_WIDE_INT) 1) << i) - 1
1556                        == ~INTVAL (operands[2]))
1557                 {
1558                   rtx shift = GEN_INT (i);
1559                   rtx reg = gen_reg_rtx (SImode);
1560                 
1561                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1562                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1563                   
1564                   DONE;
1565                 }
1566             }
1568           operands[2] = force_reg (SImode, operands[2]);
1569         }
1570     }
1571   "
1574 (define_insn_and_split "*arm_andsi3_insn"
1575   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1576         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1577                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1578   "TARGET_ARM"
1579   "@
1580    and%?\\t%0, %1, %2
1581    bic%?\\t%0, %1, #%B2
1582    #"
1583   "TARGET_ARM
1584    && GET_CODE (operands[2]) == CONST_INT
1585    && !(const_ok_for_arm (INTVAL (operands[2]))
1586         || const_ok_for_arm (~INTVAL (operands[2])))"
1587   [(clobber (const_int 0))]
1588   "
1589   arm_split_constant  (AND, SImode, curr_insn, 
1590                        INTVAL (operands[2]), operands[0], operands[1], 0);
1591   DONE;
1592   "
1593   [(set_attr "length" "4,4,16")
1594    (set_attr "predicable" "yes")]
1597 (define_insn "*thumb_andsi3_insn"
1598   [(set (match_operand:SI         0 "register_operand" "=l")
1599         (and:SI (match_operand:SI 1 "register_operand" "%0")
1600                 (match_operand:SI 2 "register_operand" "l")))]
1601   "TARGET_THUMB"
1602   "and\\t%0, %0, %2"
1603   [(set_attr "length" "2")]
1606 (define_insn "*andsi3_compare0"
1607   [(set (reg:CC_NOOV CC_REGNUM)
1608         (compare:CC_NOOV
1609          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1610                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1611          (const_int 0)))
1612    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1613         (and:SI (match_dup 1) (match_dup 2)))]
1614   "TARGET_ARM"
1615   "@
1616    and%?s\\t%0, %1, %2
1617    bic%?s\\t%0, %1, #%B2"
1618   [(set_attr "conds" "set")]
1621 (define_insn "*andsi3_compare0_scratch"
1622   [(set (reg:CC_NOOV CC_REGNUM)
1623         (compare:CC_NOOV
1624          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1625                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1626          (const_int 0)))
1627    (clobber (match_scratch:SI 2 "=X,r"))]
1628   "TARGET_ARM"
1629   "@
1630    tst%?\\t%0, %1
1631    bic%?s\\t%2, %0, #%B1"
1632   [(set_attr "conds" "set")]
1635 (define_insn "*zeroextractsi_compare0_scratch"
1636   [(set (reg:CC_NOOV CC_REGNUM)
1637         (compare:CC_NOOV (zero_extract:SI
1638                           (match_operand:SI 0 "s_register_operand" "r")
1639                           (match_operand 1 "const_int_operand" "n")
1640                           (match_operand 2 "const_int_operand" "n"))
1641                          (const_int 0)))]
1642   "TARGET_ARM
1643   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1644       && INTVAL (operands[1]) > 0 
1645       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1646       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1647   "*
1648   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1649                          << INTVAL (operands[2]));
1650   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1651   return \"\";
1652   "
1653   [(set_attr "conds" "set")]
1656 (define_insn "*ne_zeroextractsi"
1657   [(set (match_operand:SI 0 "s_register_operand" "=r")
1658         (ne:SI (zero_extract:SI
1659                 (match_operand:SI 1 "s_register_operand" "r")
1660                 (match_operand:SI 2 "const_int_operand" "n")
1661                 (match_operand:SI 3 "const_int_operand" "n"))
1662                (const_int 0)))
1663    (clobber (reg:CC CC_REGNUM))]
1664   "TARGET_ARM
1665    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1666        && INTVAL (operands[2]) > 0 
1667        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1668        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1669   "*
1670   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1671                          << INTVAL (operands[3]));
1672   output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1673   return \"movne\\t%0, #1\";
1674   "
1675   [(set_attr "conds" "clob")
1676    (set_attr "length" "8")]
1679 (define_split
1680   [(set (match_operand:SI 0 "s_register_operand" "")
1681         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1682                          (match_operand:SI 2 "const_int_operand" "")
1683                          (match_operand:SI 3 "const_int_operand" "")))
1684    (clobber (match_operand:SI 4 "s_register_operand" ""))]
1685   "TARGET_THUMB"
1686   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1687    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1688   "{
1689      HOST_WIDE_INT temp = INTVAL (operands[2]);
1691      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1692      operands[3] = GEN_INT (32 - temp);
1693    }"
1696 (define_split
1697   [(set (match_operand:SI 0 "s_register_operand" "")
1698         (match_operator:SI 1 "shiftable_operator"
1699          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1700                            (match_operand:SI 3 "const_int_operand" "")
1701                            (match_operand:SI 4 "const_int_operand" ""))
1702           (match_operand:SI 5 "s_register_operand" "")]))
1703    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1704   "TARGET_ARM"
1705   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1706    (set (match_dup 0)
1707         (match_op_dup 1
1708          [(lshiftrt:SI (match_dup 6) (match_dup 4))
1709           (match_dup 5)]))]
1710   "{
1711      HOST_WIDE_INT temp = INTVAL (operands[3]);
1713      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1714      operands[4] = GEN_INT (32 - temp);
1715    }"
1717   
1718 (define_split
1719   [(set (match_operand:SI 0 "s_register_operand" "")
1720         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1721                          (match_operand:SI 2 "const_int_operand" "")
1722                          (match_operand:SI 3 "const_int_operand" "")))]
1723   "TARGET_THUMB"
1724   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1725    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1726   "{
1727      HOST_WIDE_INT temp = INTVAL (operands[2]);
1729      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1730      operands[3] = GEN_INT (32 - temp);
1731    }"
1734 (define_split
1735   [(set (match_operand:SI 0 "s_register_operand" "")
1736         (match_operator:SI 1 "shiftable_operator"
1737          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1738                            (match_operand:SI 3 "const_int_operand" "")
1739                            (match_operand:SI 4 "const_int_operand" ""))
1740           (match_operand:SI 5 "s_register_operand" "")]))
1741    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1742   "TARGET_ARM"
1743   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1744    (set (match_dup 0)
1745         (match_op_dup 1
1746          [(ashiftrt:SI (match_dup 6) (match_dup 4))
1747           (match_dup 5)]))]
1748   "{
1749      HOST_WIDE_INT temp = INTVAL (operands[3]);
1751      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1752      operands[4] = GEN_INT (32 - temp);
1753    }"
1755   
1756 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1757 ;;; represented by the bitfield, then this will produce incorrect results.
1758 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1759 ;;; which have a real bit-field insert instruction, the truncation happens
1760 ;;; in the bit-field insert instruction itself.  Since arm does not have a
1761 ;;; bit-field insert instruction, we would have to emit code here to truncate
1762 ;;; the value before we insert.  This loses some of the advantage of having
1763 ;;; this insv pattern, so this pattern needs to be reevalutated.
1765 (define_expand "insv"
1766   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1767                          (match_operand:SI 1 "general_operand" "")
1768                          (match_operand:SI 2 "general_operand" ""))
1769         (match_operand:SI 3 "reg_or_int_operand" ""))]
1770   "TARGET_ARM"
1771   "
1772   {
1773     int start_bit = INTVAL (operands[2]);
1774     int width = INTVAL (operands[1]);
1775     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1776     rtx target, subtarget;
1778     target = operands[0];
1779     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1780        subreg as the final target.  */
1781     if (GET_CODE (target) == SUBREG)
1782       {
1783         subtarget = gen_reg_rtx (SImode);
1784         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1785             < GET_MODE_SIZE (SImode))
1786           target = SUBREG_REG (target);
1787       }
1788     else
1789       subtarget = target;    
1791     if (GET_CODE (operands[3]) == CONST_INT)
1792       {
1793         /* Since we are inserting a known constant, we may be able to
1794            reduce the number of bits that we have to clear so that
1795            the mask becomes simple.  */
1796         /* ??? This code does not check to see if the new mask is actually
1797            simpler.  It may not be.  */
1798         rtx op1 = gen_reg_rtx (SImode);
1799         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1800            start of this pattern.  */
1801         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1802         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1804         emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1805         emit_insn (gen_iorsi3 (subtarget, op1,
1806                                GEN_INT (op3_value << start_bit)));
1807       }
1808     else if (start_bit == 0
1809              && !(const_ok_for_arm (mask)
1810                   || const_ok_for_arm (~mask)))
1811       {
1812         /* A Trick, since we are setting the bottom bits in the word,
1813            we can shift operand[3] up, operand[0] down, OR them together
1814            and rotate the result back again.  This takes 3 insns, and
1815            the third might be mergeable into another op.  */
1816         /* The shift up copes with the possibility that operand[3] is
1817            wider than the bitfield.  */
1818         rtx op0 = gen_reg_rtx (SImode);
1819         rtx op1 = gen_reg_rtx (SImode);
1821         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1822         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1823         emit_insn (gen_iorsi3  (op1, op1, op0));
1824         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1825       }
1826     else if ((width + start_bit == 32)
1827              && !(const_ok_for_arm (mask)
1828                   || const_ok_for_arm (~mask)))
1829       {
1830         /* Similar trick, but slightly less efficient.  */
1832         rtx op0 = gen_reg_rtx (SImode);
1833         rtx op1 = gen_reg_rtx (SImode);
1835         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1836         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1837         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1838         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1839       }
1840     else
1841       {
1842         rtx op0 = GEN_INT (mask);
1843         rtx op1 = gen_reg_rtx (SImode);
1844         rtx op2 = gen_reg_rtx (SImode);
1846         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1847           {
1848             rtx tmp = gen_reg_rtx (SImode);
1850             emit_insn (gen_movsi (tmp, op0));
1851             op0 = tmp;
1852           }
1854         /* Mask out any bits in operand[3] that are not needed.  */
1855            emit_insn (gen_andsi3 (op1, operands[3], op0));
1857         if (GET_CODE (op0) == CONST_INT
1858             && (const_ok_for_arm (mask << start_bit)
1859                 || const_ok_for_arm (~(mask << start_bit))))
1860           {
1861             op0 = GEN_INT (~(mask << start_bit));
1862             emit_insn (gen_andsi3 (op2, operands[0], op0));
1863           }
1864         else
1865           {
1866             if (GET_CODE (op0) == CONST_INT)
1867               {
1868                 rtx tmp = gen_reg_rtx (SImode);
1870                 emit_insn (gen_movsi (tmp, op0));
1871                 op0 = tmp;
1872               }
1874             if (start_bit != 0)
1875               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1876             
1877             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1878           }
1880         if (start_bit != 0)
1881           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1883         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1884       }
1886     if (subtarget != target)
1887       {
1888         /* If TARGET is still a SUBREG, then it must be wider than a word,
1889            so we must be careful only to set the subword we were asked to.  */
1890         if (GET_CODE (target) == SUBREG)
1891           emit_move_insn (target, subtarget);
1892         else
1893           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1894       }
1896     DONE;
1897   }"
1900 ; constants for op 2 will never be given to these patterns.
1901 (define_insn_and_split "*anddi_notdi_di"
1902   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1903         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1904                 (match_operand:DI 2 "s_register_operand" "0,r")))]
1905   "TARGET_ARM"
1906   "#"
1907   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1908   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1909    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
1910   "
1911   {
1912     operands[3] = gen_highpart (SImode, operands[0]);
1913     operands[0] = gen_lowpart (SImode, operands[0]);
1914     operands[4] = gen_highpart (SImode, operands[1]);
1915     operands[1] = gen_lowpart (SImode, operands[1]);
1916     operands[5] = gen_highpart (SImode, operands[2]);
1917     operands[2] = gen_lowpart (SImode, operands[2]);
1918   }"
1919   [(set_attr "length" "8")
1920    (set_attr "predicable" "yes")]
1922   
1923 (define_insn_and_split "*anddi_notzesidi_di"
1924   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1925         (and:DI (not:DI (zero_extend:DI
1926                          (match_operand:SI 2 "s_register_operand" "r,r")))
1927                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1928   "TARGET_ARM"
1929   "@
1930    bic%?\\t%Q0, %Q1, %2
1931    #"
1932   ; (not (zero_extend ...)) allows us to just copy the high word from
1933   ; operand1 to operand0.
1934   "TARGET_ARM
1935    && reload_completed
1936    && operands[0] != operands[1]"
1937   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1938    (set (match_dup 3) (match_dup 4))]
1939   "
1940   {
1941     operands[3] = gen_highpart (SImode, operands[0]);
1942     operands[0] = gen_lowpart (SImode, operands[0]);
1943     operands[4] = gen_highpart (SImode, operands[1]);
1944     operands[1] = gen_lowpart (SImode, operands[1]);
1945   }"
1946   [(set_attr "length" "4,8")
1947    (set_attr "predicable" "yes")]
1949   
1950 (define_insn_and_split "*anddi_notsesidi_di"
1951   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1952         (and:DI (not:DI (sign_extend:DI
1953                          (match_operand:SI 2 "s_register_operand" "r,r")))
1954                 (match_operand:DI 1 "s_register_operand" "0,r")))]
1955   "TARGET_ARM"
1956   "#"
1957   "TARGET_ARM && reload_completed"
1958   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1959    (set (match_dup 3) (and:SI (not:SI
1960                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
1961                                (match_dup 4)))]
1962   "
1963   {
1964     operands[3] = gen_highpart (SImode, operands[0]);
1965     operands[0] = gen_lowpart (SImode, operands[0]);
1966     operands[4] = gen_highpart (SImode, operands[1]);
1967     operands[1] = gen_lowpart (SImode, operands[1]);
1968   }"
1969   [(set_attr "length" "8")
1970    (set_attr "predicable" "yes")]
1972   
1973 (define_insn "andsi_notsi_si"
1974   [(set (match_operand:SI 0 "s_register_operand" "=r")
1975         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1976                 (match_operand:SI 1 "s_register_operand" "r")))]
1977   "TARGET_ARM"
1978   "bic%?\\t%0, %1, %2"
1979   [(set_attr "predicable" "yes")]
1982 (define_insn "bicsi3"
1983   [(set (match_operand:SI                 0 "register_operand" "=l")
1984         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
1985                 (match_operand:SI         2 "register_operand" "0")))]
1986   "TARGET_THUMB"
1987   "bic\\t%0, %0, %1"
1988   [(set_attr "length" "2")]
1991 (define_insn "andsi_not_shiftsi_si"
1992   [(set (match_operand:SI 0 "s_register_operand" "=r")
1993         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
1994                          [(match_operand:SI 2 "s_register_operand" "r")
1995                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
1996                 (match_operand:SI 1 "s_register_operand" "r")))]
1997   "TARGET_ARM"
1998   "bic%?\\t%0, %1, %2%S4"
1999   [(set_attr "predicable" "yes")
2000    (set_attr "shift" "2")
2001    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2002                       (const_string "alu_shift")
2003                       (const_string "alu_shift_reg")))]
2006 (define_insn "*andsi_notsi_si_compare0"
2007   [(set (reg:CC_NOOV CC_REGNUM)
2008         (compare:CC_NOOV
2009          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2010                  (match_operand:SI 1 "s_register_operand" "r"))
2011          (const_int 0)))
2012    (set (match_operand:SI 0 "s_register_operand" "=r")
2013         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2014   "TARGET_ARM"
2015   "bic%?s\\t%0, %1, %2"
2016   [(set_attr "conds" "set")]
2019 (define_insn "*andsi_notsi_si_compare0_scratch"
2020   [(set (reg:CC_NOOV CC_REGNUM)
2021         (compare:CC_NOOV
2022          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2023                  (match_operand:SI 1 "s_register_operand" "r"))
2024          (const_int 0)))
2025    (clobber (match_scratch:SI 0 "=r"))]
2026   "TARGET_ARM"
2027   "bic%?s\\t%0, %1, %2"
2028   [(set_attr "conds" "set")]
2031 (define_insn "iordi3"
2032   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2033         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2034                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2035   "TARGET_ARM && ! TARGET_IWMMXT"
2036   "#"
2037   [(set_attr "length" "8")
2038    (set_attr "predicable" "yes")]
2041 (define_insn "*iordi_zesidi_di"
2042   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2043         (ior:DI (zero_extend:DI
2044                  (match_operand:SI 2 "s_register_operand" "r,r"))
2045                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2046   "TARGET_ARM"
2047   "@
2048    orr%?\\t%Q0, %Q1, %2
2049    #"
2050   [(set_attr "length" "4,8")
2051    (set_attr "predicable" "yes")]
2054 (define_insn "*iordi_sesidi_di"
2055   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2056         (ior:DI (sign_extend:DI
2057                  (match_operand:SI 2 "s_register_operand" "r,r"))
2058                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2059   "TARGET_ARM"
2060   "#"
2061   [(set_attr "length" "8")
2062    (set_attr "predicable" "yes")]
2065 (define_expand "iorsi3"
2066   [(set (match_operand:SI         0 "s_register_operand" "")
2067         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2068                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2069   "TARGET_EITHER"
2070   "
2071   if (GET_CODE (operands[2]) == CONST_INT)
2072     {
2073       if (TARGET_ARM)
2074         {
2075           arm_split_constant (IOR, SImode, NULL_RTX,
2076                               INTVAL (operands[2]), operands[0], operands[1],
2077                               (no_new_pseudos
2078                               ? 0 : preserve_subexpressions_p ()));
2079           DONE;
2080         }
2081       else /* TARGET_THUMB */
2082         operands [2] = force_reg (SImode, operands [2]);
2083     }
2084   "
2087 (define_insn_and_split "*arm_iorsi3"
2088   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2089         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2090                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2091   "TARGET_ARM"
2092   "@
2093    orr%?\\t%0, %1, %2
2094    #"
2095   "TARGET_ARM
2096    && GET_CODE (operands[2]) == CONST_INT
2097    && !const_ok_for_arm (INTVAL (operands[2]))"
2098   [(clobber (const_int 0))]
2099   "
2100   arm_split_constant (IOR, SImode, curr_insn, 
2101                       INTVAL (operands[2]), operands[0], operands[1], 0);
2102   DONE;
2103   "
2104   [(set_attr "length" "4,16")
2105    (set_attr "predicable" "yes")]
2108 (define_insn "*thumb_iorsi3"
2109   [(set (match_operand:SI         0 "register_operand" "=l")
2110         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2111                 (match_operand:SI 2 "register_operand" "l")))]
2112   "TARGET_THUMB"
2113   "orr\\t%0, %0, %2"
2114   [(set_attr "length" "2")]
2117 (define_peephole2
2118   [(match_scratch:SI 3 "r")
2119    (set (match_operand:SI         0 "s_register_operand" "")
2120         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2121                 (match_operand:SI 2 "const_int_operand" "")))]
2122   "TARGET_ARM
2123    && !const_ok_for_arm (INTVAL (operands[2]))
2124    && const_ok_for_arm (~INTVAL (operands[2]))"
2125   [(set (match_dup 3) (match_dup 2))
2126    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2127   ""
2130 (define_insn "*iorsi3_compare0"
2131   [(set (reg:CC_NOOV CC_REGNUM)
2132         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2133                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2134                          (const_int 0)))
2135    (set (match_operand:SI 0 "s_register_operand" "=r")
2136         (ior:SI (match_dup 1) (match_dup 2)))]
2137   "TARGET_ARM"
2138   "orr%?s\\t%0, %1, %2"
2139   [(set_attr "conds" "set")]
2142 (define_insn "*iorsi3_compare0_scratch"
2143   [(set (reg:CC_NOOV CC_REGNUM)
2144         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2145                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2146                          (const_int 0)))
2147    (clobber (match_scratch:SI 0 "=r"))]
2148   "TARGET_ARM"
2149   "orr%?s\\t%0, %1, %2"
2150   [(set_attr "conds" "set")]
2153 (define_insn "xordi3"
2154   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2155         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2156                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2157   "TARGET_ARM && !TARGET_IWMMXT"
2158   "#"
2159   [(set_attr "length" "8")
2160    (set_attr "predicable" "yes")]
2163 (define_insn "*xordi_zesidi_di"
2164   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2165         (xor:DI (zero_extend:DI
2166                  (match_operand:SI 2 "s_register_operand" "r,r"))
2167                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2168   "TARGET_ARM"
2169   "@
2170    eor%?\\t%Q0, %Q1, %2
2171    #"
2172   [(set_attr "length" "4,8")
2173    (set_attr "predicable" "yes")]
2176 (define_insn "*xordi_sesidi_di"
2177   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2178         (xor:DI (sign_extend:DI
2179                  (match_operand:SI 2 "s_register_operand" "r,r"))
2180                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2181   "TARGET_ARM"
2182   "#"
2183   [(set_attr "length" "8")
2184    (set_attr "predicable" "yes")]
2187 (define_expand "xorsi3"
2188   [(set (match_operand:SI         0 "s_register_operand" "")
2189         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2190                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2191   "TARGET_EITHER"
2192   "if (TARGET_THUMB)
2193      if (GET_CODE (operands[2]) == CONST_INT)
2194        operands[2] = force_reg (SImode, operands[2]);
2195   "
2198 (define_insn "*arm_xorsi3"
2199   [(set (match_operand:SI         0 "s_register_operand" "=r")
2200         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2201                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2202   "TARGET_ARM"
2203   "eor%?\\t%0, %1, %2"
2204   [(set_attr "predicable" "yes")]
2207 (define_insn "*thumb_xorsi3"
2208   [(set (match_operand:SI         0 "register_operand" "=l")
2209         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2210                 (match_operand:SI 2 "register_operand" "l")))]
2211   "TARGET_THUMB"
2212   "eor\\t%0, %0, %2"
2213   [(set_attr "length" "2")]
2216 (define_insn "*xorsi3_compare0"
2217   [(set (reg:CC_NOOV CC_REGNUM)
2218         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2219                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2220                          (const_int 0)))
2221    (set (match_operand:SI 0 "s_register_operand" "=r")
2222         (xor:SI (match_dup 1) (match_dup 2)))]
2223   "TARGET_ARM"
2224   "eor%?s\\t%0, %1, %2"
2225   [(set_attr "conds" "set")]
2228 (define_insn "*xorsi3_compare0_scratch"
2229   [(set (reg:CC_NOOV CC_REGNUM)
2230         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2231                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2232                          (const_int 0)))]
2233   "TARGET_ARM"
2234   "teq%?\\t%0, %1"
2235   [(set_attr "conds" "set")]
2238 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2239 ; (NOT D) we can sometimes merge the final NOT into one of the following
2240 ; insns.
2242 (define_split
2243   [(set (match_operand:SI 0 "s_register_operand" "")
2244         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2245                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2246                 (match_operand:SI 3 "arm_rhs_operand" "")))
2247    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2248   "TARGET_ARM"
2249   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2250                               (not:SI (match_dup 3))))
2251    (set (match_dup 0) (not:SI (match_dup 4)))]
2252   ""
2255 (define_insn "*andsi_iorsi3_notsi"
2256   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2257         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2258                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2259                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2260   "TARGET_ARM"
2261   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2262   [(set_attr "length" "8")
2263    (set_attr "predicable" "yes")]
2266 (define_split
2267   [(set (match_operand:SI 0 "s_register_operand" "")
2268         (match_operator:SI 1 "logical_binary_operator"
2269          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2270                            (match_operand:SI 3 "const_int_operand" "")
2271                            (match_operand:SI 4 "const_int_operand" ""))
2272           (match_operator:SI 9 "logical_binary_operator"
2273            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2274                          (match_operand:SI 6 "const_int_operand" ""))
2275             (match_operand:SI 7 "s_register_operand" "")])]))
2276    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2277   "TARGET_ARM
2278    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2279    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2280   [(set (match_dup 8)
2281         (match_op_dup 1
2282          [(ashift:SI (match_dup 2) (match_dup 4))
2283           (match_dup 5)]))
2284    (set (match_dup 0)
2285         (match_op_dup 1
2286          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2287           (match_dup 7)]))]
2288   "
2289   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2292 (define_split
2293   [(set (match_operand:SI 0 "s_register_operand" "")
2294         (match_operator:SI 1 "logical_binary_operator"
2295          [(match_operator:SI 9 "logical_binary_operator"
2296            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2297                          (match_operand:SI 6 "const_int_operand" ""))
2298             (match_operand:SI 7 "s_register_operand" "")])
2299           (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2300                            (match_operand:SI 3 "const_int_operand" "")
2301                            (match_operand:SI 4 "const_int_operand" ""))]))
2302    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2303   "TARGET_ARM
2304    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2305    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2306   [(set (match_dup 8)
2307         (match_op_dup 1
2308          [(ashift:SI (match_dup 2) (match_dup 4))
2309           (match_dup 5)]))
2310    (set (match_dup 0)
2311         (match_op_dup 1
2312          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2313           (match_dup 7)]))]
2314   "
2315   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2318 (define_split
2319   [(set (match_operand:SI 0 "s_register_operand" "")
2320         (match_operator:SI 1 "logical_binary_operator"
2321          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2322                            (match_operand:SI 3 "const_int_operand" "")
2323                            (match_operand:SI 4 "const_int_operand" ""))
2324           (match_operator:SI 9 "logical_binary_operator"
2325            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2326                          (match_operand:SI 6 "const_int_operand" ""))
2327             (match_operand:SI 7 "s_register_operand" "")])]))
2328    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2329   "TARGET_ARM
2330    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2331    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2332   [(set (match_dup 8)
2333         (match_op_dup 1
2334          [(ashift:SI (match_dup 2) (match_dup 4))
2335           (match_dup 5)]))
2336    (set (match_dup 0)
2337         (match_op_dup 1
2338          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2339           (match_dup 7)]))]
2340   "
2341   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2344 (define_split
2345   [(set (match_operand:SI 0 "s_register_operand" "")
2346         (match_operator:SI 1 "logical_binary_operator"
2347          [(match_operator:SI 9 "logical_binary_operator"
2348            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2349                          (match_operand:SI 6 "const_int_operand" ""))
2350             (match_operand:SI 7 "s_register_operand" "")])
2351           (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2352                            (match_operand:SI 3 "const_int_operand" "")
2353                            (match_operand:SI 4 "const_int_operand" ""))]))
2354    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2355   "TARGET_ARM
2356    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2357    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2358   [(set (match_dup 8)
2359         (match_op_dup 1
2360          [(ashift:SI (match_dup 2) (match_dup 4))
2361           (match_dup 5)]))
2362    (set (match_dup 0)
2363         (match_op_dup 1
2364          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2365           (match_dup 7)]))]
2366   "
2367   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2371 ;; Minimum and maximum insns
2373 (define_insn "smaxsi3"
2374   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2375         (smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2376                  (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2377    (clobber (reg:CC CC_REGNUM))]
2378   "TARGET_ARM"
2379   "@
2380    cmp\\t%1, %2\;movlt\\t%0, %2
2381    cmp\\t%1, %2\;movge\\t%0, %1
2382    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2383   [(set_attr "conds" "clob")
2384    (set_attr "length" "8,8,12")]
2387 (define_insn "sminsi3"
2388   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2389         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2390                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2391    (clobber (reg:CC CC_REGNUM))]
2392   "TARGET_ARM"
2393   "@
2394    cmp\\t%1, %2\;movge\\t%0, %2
2395    cmp\\t%1, %2\;movlt\\t%0, %1
2396    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2397   [(set_attr "conds" "clob")
2398    (set_attr "length" "8,8,12")]
2401 (define_insn "umaxsi3"
2402   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2403         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2404                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2405    (clobber (reg:CC CC_REGNUM))]
2406   "TARGET_ARM"
2407   "@
2408    cmp\\t%1, %2\;movcc\\t%0, %2
2409    cmp\\t%1, %2\;movcs\\t%0, %1
2410    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2411   [(set_attr "conds" "clob")
2412    (set_attr "length" "8,8,12")]
2415 (define_insn "uminsi3"
2416   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2417         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2418                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2419    (clobber (reg:CC CC_REGNUM))]
2420   "TARGET_ARM"
2421   "@
2422    cmp\\t%1, %2\;movcs\\t%0, %2
2423    cmp\\t%1, %2\;movcc\\t%0, %1
2424    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2425   [(set_attr "conds" "clob")
2426    (set_attr "length" "8,8,12")]
2429 (define_insn "*store_minmaxsi"
2430   [(set (match_operand:SI 0 "memory_operand" "=m")
2431         (match_operator:SI 3 "minmax_operator"
2432          [(match_operand:SI 1 "s_register_operand" "r")
2433           (match_operand:SI 2 "s_register_operand" "r")]))
2434    (clobber (reg:CC CC_REGNUM))]
2435   "TARGET_ARM"
2436   "*
2437   operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2438                                 operands[1], operands[2]);
2439   output_asm_insn (\"cmp\\t%1, %2\", operands);
2440   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2441   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2442   return \"\";
2443   "
2444   [(set_attr "conds" "clob")
2445    (set_attr "length" "12")
2446    (set_attr "type" "store1")]
2449 ; Reject the frame pointer in operand[1], since reloading this after
2450 ; it has been eliminated can cause carnage.
2451 (define_insn "*minmax_arithsi"
2452   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2453         (match_operator:SI 4 "shiftable_operator"
2454          [(match_operator:SI 5 "minmax_operator"
2455            [(match_operand:SI 2 "s_register_operand" "r,r")
2456             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2457           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2458    (clobber (reg:CC CC_REGNUM))]
2459   "TARGET_ARM
2460    && (GET_CODE (operands[1]) != REG
2461        || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2462            && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2463   "*
2464   {
2465     enum rtx_code code = GET_CODE (operands[4]);
2467     operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2468                                   operands[2], operands[3]);
2469     output_asm_insn (\"cmp\\t%2, %3\", operands);
2470     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2471     if (which_alternative != 0 || operands[3] != const0_rtx
2472         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2473       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2474     return \"\";
2475   }"
2476   [(set_attr "conds" "clob")
2477    (set_attr "length" "12")]
2481 ;; Shift and rotation insns
2483 (define_expand "ashldi3"
2484   [(set (match_operand:DI            0 "s_register_operand" "")
2485         (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2486                    (match_operand:SI 2 "reg_or_int_operand" "")))]
2487   "TARGET_ARM"
2488   "
2489   if (GET_CODE (operands[2]) == CONST_INT)
2490     {
2491       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2492         {
2493           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2494           DONE;
2495         }
2496         /* Ideally we shouldn't fail here if we could know that operands[1] 
2497            ends up already living in an iwmmxt register. Otherwise it's
2498            cheaper to have the alternate code being generated than moving
2499            values to iwmmxt regs and back.  */
2500         FAIL;
2501     }
2502   else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2503     FAIL;
2504   "
2507 (define_insn "arm_ashldi3_1bit"
2508   [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
2509         (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2510                    (const_int 1)))
2511    (clobber (reg:CC CC_REGNUM))]
2512   "TARGET_ARM"
2513   "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2514   [(set_attr "conds" "clob")
2515    (set_attr "length" "8")]
2518 (define_expand "ashlsi3"
2519   [(set (match_operand:SI            0 "s_register_operand" "")
2520         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2521                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2522   "TARGET_EITHER"
2523   "
2524   if (GET_CODE (operands[2]) == CONST_INT
2525       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2526     {
2527       emit_insn (gen_movsi (operands[0], const0_rtx));
2528       DONE;
2529     }
2530   "
2533 (define_insn "*thumb_ashlsi3"
2534   [(set (match_operand:SI            0 "register_operand" "=l,l")
2535         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2536                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2537   "TARGET_THUMB"
2538   "lsl\\t%0, %1, %2"
2539   [(set_attr "length" "2")]
2542 (define_expand "ashrdi3"
2543   [(set (match_operand:DI              0 "s_register_operand" "")
2544         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2545                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2546   "TARGET_ARM"
2547   "
2548   if (GET_CODE (operands[2]) == CONST_INT)
2549     {
2550       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2551         {
2552           emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2553           DONE;
2554         }
2555         /* Ideally we shouldn't fail here if we could know that operands[1] 
2556            ends up already living in an iwmmxt register. Otherwise it's
2557            cheaper to have the alternate code being generated than moving
2558            values to iwmmxt regs and back.  */
2559         FAIL;
2560     }
2561   else if (!TARGET_REALLY_IWMMXT)
2562     FAIL;
2563   "
2566 (define_insn "arm_ashrdi3_1bit"
2567   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2568         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2569                      (const_int 1)))
2570    (clobber (reg:CC CC_REGNUM))]
2571   "TARGET_ARM"
2572   "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2573   [(set_attr "conds" "clob")
2574    (set_attr "length" "8")]
2577 (define_expand "ashrsi3"
2578   [(set (match_operand:SI              0 "s_register_operand" "")
2579         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2580                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2581   "TARGET_EITHER"
2582   "
2583   if (GET_CODE (operands[2]) == CONST_INT
2584       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2585     operands[2] = GEN_INT (31);
2586   "
2589 (define_insn "*thumb_ashrsi3"
2590   [(set (match_operand:SI              0 "register_operand" "=l,l")
2591         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2592                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2593   "TARGET_THUMB"
2594   "asr\\t%0, %1, %2"
2595   [(set_attr "length" "2")]
2598 (define_expand "lshrdi3"
2599   [(set (match_operand:DI              0 "s_register_operand" "")
2600         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2601                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2602   "TARGET_ARM"
2603   "
2604   if (GET_CODE (operands[2]) == CONST_INT)
2605     {
2606       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2607         {
2608           emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2609           DONE;
2610         }
2611         /* Ideally we shouldn't fail here if we could know that operands[1] 
2612            ends up already living in an iwmmxt register. Otherwise it's
2613            cheaper to have the alternate code being generated than moving
2614            values to iwmmxt regs and back.  */
2615         FAIL;
2616     }
2617   else if (!TARGET_REALLY_IWMMXT)
2618     FAIL;
2619   "
2622 (define_insn "arm_lshrdi3_1bit"
2623   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2624         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2625                      (const_int 1)))
2626    (clobber (reg:CC CC_REGNUM))]
2627   "TARGET_ARM"
2628   "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2629   [(set_attr "conds" "clob")
2630    (set_attr "length" "8")]
2633 (define_expand "lshrsi3"
2634   [(set (match_operand:SI              0 "s_register_operand" "")
2635         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2636                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2637   "TARGET_EITHER"
2638   "
2639   if (GET_CODE (operands[2]) == CONST_INT
2640       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2641     {
2642       emit_insn (gen_movsi (operands[0], const0_rtx));
2643       DONE;
2644     }
2645   "
2648 (define_insn "*thumb_lshrsi3"
2649   [(set (match_operand:SI              0 "register_operand" "=l,l")
2650         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2651                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2652   "TARGET_THUMB"
2653   "lsr\\t%0, %1, %2"
2654   [(set_attr "length" "2")]
2657 (define_expand "rotlsi3"
2658   [(set (match_operand:SI              0 "s_register_operand" "")
2659         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2660                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2661   "TARGET_ARM"
2662   "
2663   if (GET_CODE (operands[2]) == CONST_INT)
2664     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2665   else
2666     {
2667       rtx reg = gen_reg_rtx (SImode);
2668       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2669       operands[2] = reg;
2670     }
2671   "
2674 (define_expand "rotrsi3"
2675   [(set (match_operand:SI              0 "s_register_operand" "")
2676         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2677                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2678   "TARGET_EITHER"
2679   "
2680   if (TARGET_ARM)
2681     {
2682       if (GET_CODE (operands[2]) == CONST_INT
2683           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2684         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2685     }
2686   else /* TARGET_THUMB */
2687     {
2688       if (GET_CODE (operands [2]) == CONST_INT)
2689         operands [2] = force_reg (SImode, operands[2]);
2690     }
2691   "
2694 (define_insn "*thumb_rotrsi3"
2695   [(set (match_operand:SI              0 "register_operand" "=l")
2696         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2697                      (match_operand:SI 2 "register_operand" "l")))]
2698   "TARGET_THUMB"
2699   "ror\\t%0, %0, %2"
2700   [(set_attr "length" "2")]
2703 (define_insn "*arm_shiftsi3"
2704   [(set (match_operand:SI   0 "s_register_operand" "=r")
2705         (match_operator:SI  3 "shift_operator"
2706          [(match_operand:SI 1 "s_register_operand"  "r")
2707           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2708   "TARGET_ARM"
2709   "mov%?\\t%0, %1%S3"
2710   [(set_attr "predicable" "yes")
2711    (set_attr "shift" "1")
2712    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2713                       (const_string "alu_shift")
2714                       (const_string "alu_shift_reg")))]
2717 (define_insn "*shiftsi3_compare0"
2718   [(set (reg:CC_NOOV CC_REGNUM)
2719         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2720                           [(match_operand:SI 1 "s_register_operand" "r")
2721                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2722                          (const_int 0)))
2723    (set (match_operand:SI 0 "s_register_operand" "=r")
2724         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2725   "TARGET_ARM"
2726   "mov%?s\\t%0, %1%S3"
2727   [(set_attr "conds" "set")
2728    (set_attr "shift" "1")
2729    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2730                       (const_string "alu_shift")
2731                       (const_string "alu_shift_reg")))]
2734 (define_insn "*shiftsi3_compare0_scratch"
2735   [(set (reg:CC_NOOV CC_REGNUM)
2736         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2737                           [(match_operand:SI 1 "s_register_operand" "r")
2738                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2739                          (const_int 0)))
2740    (clobber (match_scratch:SI 0 "=r"))]
2741   "TARGET_ARM"
2742   "mov%?s\\t%0, %1%S3"
2743   [(set_attr "conds" "set")
2744    (set_attr "shift" "1")]
2747 (define_insn "*notsi_shiftsi"
2748   [(set (match_operand:SI 0 "s_register_operand" "=r")
2749         (not:SI (match_operator:SI 3 "shift_operator"
2750                  [(match_operand:SI 1 "s_register_operand" "r")
2751                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2752   "TARGET_ARM"
2753   "mvn%?\\t%0, %1%S3"
2754   [(set_attr "predicable" "yes")
2755    (set_attr "shift" "1")
2756    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2757                       (const_string "alu_shift")
2758                       (const_string "alu_shift_reg")))]
2761 (define_insn "*notsi_shiftsi_compare0"
2762   [(set (reg:CC_NOOV CC_REGNUM)
2763         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2764                           [(match_operand:SI 1 "s_register_operand" "r")
2765                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2766                          (const_int 0)))
2767    (set (match_operand:SI 0 "s_register_operand" "=r")
2768         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2769   "TARGET_ARM"
2770   "mvn%?s\\t%0, %1%S3"
2771   [(set_attr "conds" "set")
2772    (set_attr "shift" "1")
2773    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2774                       (const_string "alu_shift")
2775                       (const_string "alu_shift_reg")))]
2778 (define_insn "*not_shiftsi_compare0_scratch"
2779   [(set (reg:CC_NOOV CC_REGNUM)
2780         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2781                           [(match_operand:SI 1 "s_register_operand" "r")
2782                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2783                          (const_int 0)))
2784    (clobber (match_scratch:SI 0 "=r"))]
2785   "TARGET_ARM"
2786   "mvn%?s\\t%0, %1%S3"
2787   [(set_attr "conds" "set")
2788    (set_attr "shift" "1")
2789    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2790                       (const_string "alu_shift")
2791                       (const_string "alu_shift_reg")))]
2794 ;; We don't really have extzv, but defining this using shifts helps
2795 ;; to reduce register pressure later on.
2797 (define_expand "extzv"
2798   [(set (match_dup 4)
2799         (ashift:SI (match_operand:SI   1 "register_operand" "")
2800                    (match_operand:SI   2 "const_int_operand" "")))
2801    (set (match_operand:SI              0 "register_operand" "")
2802         (lshiftrt:SI (match_dup 4)
2803                      (match_operand:SI 3 "const_int_operand" "")))]
2804   "TARGET_THUMB"
2805   "
2806   {
2807     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2808     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2809     
2810     operands[3] = GEN_INT (rshift);
2811     
2812     if (lshift == 0)
2813       {
2814         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2815         DONE;
2816       }
2817       
2818     operands[2] = GEN_INT (lshift);
2819     operands[4] = gen_reg_rtx (SImode);
2820   }"
2824 ;; Unary arithmetic insns
2826 (define_expand "negdi2"
2827  [(parallel
2828    [(set (match_operand:DI          0 "s_register_operand" "")
2829           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2830     (clobber (reg:CC CC_REGNUM))])]
2831   "TARGET_EITHER"
2832   "
2833   if (TARGET_THUMB)
2834     {
2835       if (GET_CODE (operands[1]) != REG)
2836         operands[1] = force_reg (SImode, operands[1]);
2837      }
2838   "
2841 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2842 ;; The second alternative is to allow the common case of a *full* overlap.
2843 (define_insn "*arm_negdi2"
2844   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2845         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2846    (clobber (reg:CC CC_REGNUM))]
2847   "TARGET_ARM"
2848   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2849   [(set_attr "conds" "clob")
2850    (set_attr "length" "8")]
2853 (define_insn "*thumb_negdi2"
2854   [(set (match_operand:DI         0 "register_operand" "=&l")
2855         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
2856    (clobber (reg:CC CC_REGNUM))]
2857   "TARGET_THUMB"
2858   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2859   [(set_attr "length" "6")]
2862 (define_expand "negsi2"
2863   [(set (match_operand:SI         0 "s_register_operand" "")
2864         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2865   "TARGET_EITHER"
2866   ""
2869 (define_insn "*arm_negsi2"
2870   [(set (match_operand:SI         0 "s_register_operand" "=r")
2871         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2872   "TARGET_ARM"
2873   "rsb%?\\t%0, %1, #0"
2874   [(set_attr "predicable" "yes")]
2877 (define_insn "*thumb_negsi2"
2878   [(set (match_operand:SI         0 "register_operand" "=l")
2879         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2880   "TARGET_THUMB"
2881   "neg\\t%0, %1"
2882   [(set_attr "length" "2")]
2885 (define_expand "negsf2"
2886   [(set (match_operand:SF         0 "s_register_operand" "")
2887         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2888   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2889   ""
2892 (define_expand "negdf2"
2893   [(set (match_operand:DF         0 "s_register_operand" "")
2894         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2895   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2896   "")
2898 ;; abssi2 doesn't really clobber the condition codes if a different register
2899 ;; is being set.  To keep things simple, assume during rtl manipulations that
2900 ;; it does, but tell the final scan operator the truth.  Similarly for
2901 ;; (neg (abs...))
2903 (define_expand "abssi2"
2904   [(parallel
2905     [(set (match_operand:SI         0 "s_register_operand" "")
2906           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
2907      (clobber (reg:CC CC_REGNUM))])]
2908   "TARGET_ARM"
2909   "")
2911 (define_insn "*arm_abssi2"
2912   [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
2913         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2914    (clobber (reg:CC CC_REGNUM))]
2915   "TARGET_ARM"
2916   "@
2917    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2918    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2919   [(set_attr "conds" "clob,*")
2920    (set_attr "shift" "1")
2921    ;; predicable can't be set based on the variant, so left as no
2922    (set_attr "length" "8")]
2925 (define_insn "*neg_abssi2"
2926   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2927         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2928    (clobber (reg:CC CC_REGNUM))]
2929   "TARGET_ARM"
2930   "@
2931    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2932    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2933   [(set_attr "conds" "clob,*")
2934    (set_attr "shift" "1")
2935    ;; predicable can't be set based on the variant, so left as no
2936    (set_attr "length" "8")]
2939 (define_expand "abssf2"
2940   [(set (match_operand:SF         0 "s_register_operand" "")
2941         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
2942   "TARGET_ARM && TARGET_HARD_FLOAT"
2943   "")
2945 (define_expand "absdf2"
2946   [(set (match_operand:DF         0 "s_register_operand" "")
2947         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
2948   "TARGET_ARM && TARGET_HARD_FLOAT"
2949   "")
2951 (define_expand "sqrtsf2"
2952   [(set (match_operand:SF 0 "s_register_operand" "")
2953         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
2954   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
2955   "")
2957 (define_expand "sqrtdf2"
2958   [(set (match_operand:DF 0 "s_register_operand" "")
2959         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
2960   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
2961   "")
2963 (define_insn_and_split "one_cmpldi2"
2964   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2965         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2966   "TARGET_ARM"
2967   "#"
2968   "TARGET_ARM && reload_completed"
2969   [(set (match_dup 0) (not:SI (match_dup 1)))
2970    (set (match_dup 2) (not:SI (match_dup 3)))]
2971   "
2972   {
2973     operands[2] = gen_highpart (SImode, operands[0]);
2974     operands[0] = gen_lowpart (SImode, operands[0]);
2975     operands[3] = gen_highpart (SImode, operands[1]);
2976     operands[1] = gen_lowpart (SImode, operands[1]);
2977   }"
2978   [(set_attr "length" "8")
2979    (set_attr "predicable" "yes")]
2982 (define_expand "one_cmplsi2"
2983   [(set (match_operand:SI         0 "s_register_operand" "")
2984         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
2985   "TARGET_EITHER"
2986   ""
2989 (define_insn "*arm_one_cmplsi2"
2990   [(set (match_operand:SI         0 "s_register_operand" "=r")
2991         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
2992   "TARGET_ARM"
2993   "mvn%?\\t%0, %1"
2994   [(set_attr "predicable" "yes")]
2997 (define_insn "*thumb_one_cmplsi2"
2998   [(set (match_operand:SI         0 "register_operand" "=l")
2999         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3000   "TARGET_THUMB"
3001   "mvn\\t%0, %1"
3002   [(set_attr "length" "2")]
3005 (define_insn "*notsi_compare0"
3006   [(set (reg:CC_NOOV CC_REGNUM)
3007         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3008                          (const_int 0)))
3009    (set (match_operand:SI 0 "s_register_operand" "=r")
3010         (not:SI (match_dup 1)))]
3011   "TARGET_ARM"
3012   "mvn%?s\\t%0, %1"
3013   [(set_attr "conds" "set")]
3016 (define_insn "*notsi_compare0_scratch"
3017   [(set (reg:CC_NOOV CC_REGNUM)
3018         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3019                          (const_int 0)))
3020    (clobber (match_scratch:SI 0 "=r"))]
3021   "TARGET_ARM"
3022   "mvn%?s\\t%0, %1"
3023   [(set_attr "conds" "set")]
3026 ;; Fixed <--> Floating conversion insns
3028 (define_expand "floatsisf2"
3029   [(set (match_operand:SF           0 "s_register_operand" "")
3030         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3031   "TARGET_ARM && TARGET_HARD_FLOAT"
3032   "
3033   if (TARGET_MAVERICK)
3034     {
3035       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3036       DONE;
3037     }
3040 (define_expand "floatsidf2"
3041   [(set (match_operand:DF           0 "s_register_operand" "")
3042         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3043   "TARGET_ARM && TARGET_HARD_FLOAT"
3044   "
3045   if (TARGET_MAVERICK)
3046     {
3047       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3048       DONE;
3049     }
3052 (define_expand "fix_truncsfsi2"
3053   [(set (match_operand:SI         0 "s_register_operand" "")
3054         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3055   "TARGET_ARM && TARGET_HARD_FLOAT"
3056   "
3057   if (TARGET_MAVERICK)
3058     {
3059       if (!cirrus_fp_register (operands[0], SImode))
3060         operands[0] = force_reg (SImode, operands[0]);
3061       if (!cirrus_fp_register (operands[1], SFmode))
3062         operands[1] = force_reg (SFmode, operands[0]);
3063       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3064       DONE;
3065     }
3068 (define_expand "fix_truncdfsi2"
3069   [(set (match_operand:SI         0 "s_register_operand" "")
3070         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3071   "TARGET_ARM && TARGET_HARD_FLOAT"
3072   "
3073   if (TARGET_MAVERICK)
3074     {
3075       if (!cirrus_fp_register (operands[1], DFmode))
3076         operands[1] = force_reg (DFmode, operands[0]);
3077       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3078       DONE;
3079     }
3082 ;; Truncation insns
3084 (define_expand "truncdfsf2"
3085   [(set (match_operand:SF  0 "s_register_operand" "")
3086         (float_truncate:SF
3087          (match_operand:DF 1 "s_register_operand" "")))]
3088   "TARGET_ARM && TARGET_HARD_FLOAT"
3089   ""
3092 ;; Zero and sign extension instructions.
3094 (define_insn "zero_extendsidi2"
3095   [(set (match_operand:DI 0 "s_register_operand" "=r")
3096         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3097   "TARGET_ARM"
3098   "*
3099     if (REGNO (operands[1])
3100         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3101       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3102     return \"mov%?\\t%R0, #0\";
3103   "
3104   [(set_attr "length" "8")
3105    (set_attr "predicable" "yes")]
3108 (define_insn "zero_extendqidi2"
3109   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3110         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3111   "TARGET_ARM"
3112   "@
3113    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3114    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3115   [(set_attr "length" "8")
3116    (set_attr "predicable" "yes")
3117    (set_attr "type" "*,load_byte")
3118    (set_attr "pool_range" "*,4092")
3119    (set_attr "neg_pool_range" "*,4084")]
3122 (define_insn "extendsidi2"
3123   [(set (match_operand:DI 0 "s_register_operand" "=r")
3124         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3125   "TARGET_ARM"
3126   "*
3127     if (REGNO (operands[1])
3128         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3129       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3130     return \"mov%?\\t%R0, %Q0, asr #31\";
3131   "
3132   [(set_attr "length" "8")
3133    (set_attr "shift" "1")
3134    (set_attr "predicable" "yes")]
3137 (define_expand "zero_extendhisi2"
3138   [(set (match_dup 2)
3139         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3140                    (const_int 16)))
3141    (set (match_operand:SI 0 "s_register_operand" "")
3142         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3143   "TARGET_EITHER"
3144   "
3145   {
3146     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3147       {
3148        /* Note: We do not have to worry about TARGET_MMU_TRAPS
3149           here because the insn below will generate an LDRH instruction
3150           rather than an LDR instruction, so we cannot get an unaligned
3151           word access.  */
3152         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3153                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3154         DONE;
3155       }
3157     if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3158       {
3159         emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3160         DONE;
3161       }
3163     if (!s_register_operand (operands[1], HImode))
3164       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3166     if (arm_arch6)
3167       {
3168         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3169                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3170         DONE;
3171       }
3173     operands[1] = gen_lowpart (SImode, operands[1]);
3174     operands[2] = gen_reg_rtx (SImode);
3175   }"
3178 (define_insn "*thumb_zero_extendhisi2"
3179   [(set (match_operand:SI 0 "register_operand" "=l")
3180         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3181   "TARGET_THUMB && !arm_arch6"
3182   "*
3183   rtx mem = XEXP (operands[1], 0);
3185   if (GET_CODE (mem) == CONST)
3186     mem = XEXP (mem, 0);
3187     
3188   if (GET_CODE (mem) == LABEL_REF)
3189     return \"ldr\\t%0, %1\";
3190     
3191   if (GET_CODE (mem) == PLUS)
3192     {
3193       rtx a = XEXP (mem, 0);
3194       rtx b = XEXP (mem, 1);
3196       /* This can happen due to bugs in reload.  */
3197       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3198         {
3199           rtx ops[2];
3200           ops[0] = operands[0];
3201           ops[1] = a;
3202       
3203           output_asm_insn (\"mov        %0, %1\", ops);
3205           XEXP (mem, 0) = operands[0];
3206        }
3208       else if (   GET_CODE (a) == LABEL_REF
3209                && GET_CODE (b) == CONST_INT)
3210         return \"ldr\\t%0, %1\";
3211     }
3212     
3213   return \"ldrh\\t%0, %1\";
3214   "
3215   [(set_attr "length" "4")
3216    (set_attr "type" "load_byte")
3217    (set_attr "pool_range" "60")]
3220 (define_insn "*thumb_zero_extendhisi2_v6"
3221   [(set (match_operand:SI 0 "register_operand" "=l,l")
3222         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3223   "TARGET_THUMB && arm_arch6"
3224   "*
3225   rtx mem;
3227   if (which_alternative == 0)
3228     return \"uxth\\t%0, %1\";
3230   mem = XEXP (operands[1], 0);
3232   if (GET_CODE (mem) == CONST)
3233     mem = XEXP (mem, 0);
3234     
3235   if (GET_CODE (mem) == LABEL_REF)
3236     return \"ldr\\t%0, %1\";
3237     
3238   if (GET_CODE (mem) == PLUS)
3239     {
3240       rtx a = XEXP (mem, 0);
3241       rtx b = XEXP (mem, 1);
3243       /* This can happen due to bugs in reload.  */
3244       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3245         {
3246           rtx ops[2];
3247           ops[0] = operands[0];
3248           ops[1] = a;
3249       
3250           output_asm_insn (\"mov        %0, %1\", ops);
3252           XEXP (mem, 0) = operands[0];
3253        }
3255       else if (   GET_CODE (a) == LABEL_REF
3256                && GET_CODE (b) == CONST_INT)
3257         return \"ldr\\t%0, %1\";
3258     }
3259     
3260   return \"ldrh\\t%0, %1\";
3261   "
3262   [(set_attr "length" "2,4")
3263    (set_attr "type" "alu_shift,load_byte")
3264    (set_attr "pool_range" "*,60")]
3267 (define_insn "*arm_zero_extendhisi2"
3268   [(set (match_operand:SI 0 "s_register_operand" "=r")
3269         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3270   "TARGET_ARM && arm_arch4 && !arm_arch6"
3271   "ldr%?h\\t%0, %1"
3272   [(set_attr "type" "load_byte")
3273    (set_attr "predicable" "yes")
3274    (set_attr "pool_range" "256")
3275    (set_attr "neg_pool_range" "244")]
3278 (define_insn "*arm_zero_extendhisi2_v6"
3279   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3280         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3281   "TARGET_ARM && arm_arch6"
3282   "@
3283    uxth%?\\t%0, %1
3284    ldr%?h\\t%0, %1"
3285   [(set_attr "type" "alu_shift,load_byte")
3286    (set_attr "predicable" "yes")
3287    (set_attr "pool_range" "*,256")
3288    (set_attr "neg_pool_range" "*,244")]
3291 (define_insn "*arm_zero_extendhisi2addsi"
3292   [(set (match_operand:SI 0 "s_register_operand" "=r")
3293         (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3294                  (match_operand:SI 2 "s_register_operand" "r")))]
3295   "TARGET_ARM && arm_arch6"
3296   "uxtah%?\\t%0, %2, %1"
3297   [(set_attr "type" "alu_shift")
3298    (set_attr "predicable" "yes")]
3301 (define_split
3302   [(set (match_operand:SI 0 "s_register_operand" "")
3303         (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3304    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3305   "TARGET_ARM && (!arm_arch4)"
3306   [(set (match_dup 2) (match_dup 1))
3307    (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3308   "
3309   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3310     FAIL;
3311   "
3314 (define_split
3315   [(set (match_operand:SI 0 "s_register_operand" "")
3316         (match_operator:SI 3 "shiftable_operator"
3317          [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3318           (match_operand:SI 4 "s_register_operand" "")]))
3319    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3320   "TARGET_ARM && (!arm_arch4)"
3321   [(set (match_dup 2) (match_dup 1))
3322    (set (match_dup 0)
3323         (match_op_dup 3
3324          [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3325   "
3326   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3327     FAIL;
3328   "
3331 (define_expand "zero_extendqisi2"
3332   [(set (match_operand:SI 0 "s_register_operand" "")
3333         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3334   "TARGET_EITHER"
3335   "
3336   if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3337     {
3338       if (TARGET_ARM)
3339         {
3340           emit_insn (gen_andsi3 (operands[0],
3341                                  gen_lowpart (SImode, operands[1]),
3342                                  GEN_INT (255)));
3343         }
3344       else /* TARGET_THUMB */
3345         {
3346           rtx temp = gen_reg_rtx (SImode);
3347           rtx ops[3];
3348           
3349           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3350           operands[1] = gen_lowpart (SImode, operands[1]);
3352           ops[0] = temp;
3353           ops[1] = operands[1];
3354           ops[2] = GEN_INT (24);
3356           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3357                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3358           
3359           ops[0] = operands[0];
3360           ops[1] = temp;
3361           ops[2] = GEN_INT (24);
3363           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3364                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3365         }
3366       DONE;
3367     }
3368   "
3371 (define_insn "*thumb_zero_extendqisi2"
3372   [(set (match_operand:SI 0 "register_operand" "=l")
3373         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3374   "TARGET_THUMB && !arm_arch6"
3375   "ldrb\\t%0, %1"
3376   [(set_attr "length" "2")
3377    (set_attr "type" "load_byte")
3378    (set_attr "pool_range" "32")]
3381 (define_insn "*thumb_zero_extendqisi2_v6"
3382   [(set (match_operand:SI 0 "register_operand" "=l,l")
3383         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3384   "TARGET_THUMB && arm_arch6"
3385   "@
3386    uxtb\\t%0, %1
3387    ldrb\\t%0, %1"
3388   [(set_attr "length" "2,2")
3389    (set_attr "type" "alu_shift,load_byte")
3390    (set_attr "pool_range" "*,32")]
3393 (define_insn "*arm_zero_extendqisi2"
3394   [(set (match_operand:SI 0 "s_register_operand" "=r")
3395         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3396   "TARGET_ARM && !arm_arch6"
3397   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3398   [(set_attr "type" "load_byte")
3399    (set_attr "predicable" "yes")
3400    (set_attr "pool_range" "4096")
3401    (set_attr "neg_pool_range" "4084")]
3404 (define_insn "*arm_zero_extendqisi2_v6"
3405   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3406         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3407   "TARGET_ARM && arm_arch6"
3408   "@
3409    uxtb%?\\t%0, %1
3410    ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3411   [(set_attr "type" "alu_shift,load_byte")
3412    (set_attr "predicable" "yes")
3413    (set_attr "pool_range" "*,4096")
3414    (set_attr "neg_pool_range" "*,4084")]
3417 (define_insn "*arm_zero_extendqisi2addsi"
3418   [(set (match_operand:SI 0 "s_register_operand" "=r")
3419         (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3420                  (match_operand:SI 2 "s_register_operand" "r")))]
3421   "TARGET_ARM && arm_arch6"
3422   "uxtab%?\\t%0, %2, %1"
3423   [(set_attr "predicable" "yes")
3424    (set_attr "type" "alu_shift")]
3427 (define_split
3428   [(set (match_operand:SI 0 "s_register_operand" "")
3429         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3430    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3431   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3432   [(set (match_dup 2) (match_dup 1))
3433    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3434   ""
3437 (define_insn "*compareqi_eq0"
3438   [(set (reg:CC_Z CC_REGNUM)
3439         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3440                          (const_int 0)))]
3441   "TARGET_ARM"
3442   "tst\\t%0, #255"
3443   [(set_attr "conds" "set")]
3446 (define_expand "extendhisi2"
3447   [(set (match_dup 2)
3448         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3449                    (const_int 16)))
3450    (set (match_operand:SI 0 "s_register_operand" "")
3451         (ashiftrt:SI (match_dup 2)
3452                      (const_int 16)))]
3453   "TARGET_EITHER"
3454   "
3455   {
3456     if (GET_CODE (operands[1]) == MEM)
3457       {
3458         if (TARGET_THUMB)
3459           {
3460             emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3461             DONE;
3462           }
3463         else if (arm_arch4)
3464           {
3465             /* Note: We do not have to worry about TARGET_MMU_TRAPS
3466                here because the insn below will generate an LDRH instruction
3467                rather than an LDR instruction, so we cannot get an unaligned
3468                word access.  */
3469             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3470                        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3471             DONE;
3472           }
3473       }
3475     if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3476       {
3477         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3478         DONE;
3479       }
3481     if (!s_register_operand (operands[1], HImode))
3482       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3484     if (arm_arch6)
3485       {
3486         if (TARGET_THUMB)
3487           emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3488         else
3489           emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3490                      gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3492         DONE;
3493       }
3495     operands[1] = gen_lowpart (SImode, operands[1]);
3496     operands[2] = gen_reg_rtx (SImode);
3497   }"
3500 (define_insn "thumb_extendhisi2"
3501   [(set (match_operand:SI 0 "register_operand" "=l")
3502         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3503    (clobber (match_scratch:SI 2 "=&l"))]
3504   "TARGET_THUMB && !arm_arch6"
3505   "*
3506   {
3507     rtx ops[4];
3508     rtx mem = XEXP (operands[1], 0);
3510     /* This code used to try to use 'V', and fix the address only if it was
3511        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3512        range of QImode offsets, and offsettable_address_p does a QImode
3513        address check.  */
3514        
3515     if (GET_CODE (mem) == CONST)
3516       mem = XEXP (mem, 0);
3517     
3518     if (GET_CODE (mem) == LABEL_REF)
3519       return \"ldr\\t%0, %1\";
3520     
3521     if (GET_CODE (mem) == PLUS)
3522       {
3523         rtx a = XEXP (mem, 0);
3524         rtx b = XEXP (mem, 1);
3526         if (GET_CODE (a) == LABEL_REF
3527             && GET_CODE (b) == CONST_INT)
3528           return \"ldr\\t%0, %1\";
3530         if (GET_CODE (b) == REG)
3531           return \"ldrsh\\t%0, %1\";
3532           
3533         ops[1] = a;
3534         ops[2] = b;
3535       }
3536     else
3537       {
3538         ops[1] = mem;
3539         ops[2] = const0_rtx;
3540       }
3541       
3542     if (GET_CODE (ops[1]) != REG)
3543       {
3544         debug_rtx (ops[1]);
3545         abort ();
3546       }
3548     ops[0] = operands[0];
3549     ops[3] = operands[2];
3550     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3551     return \"\";
3552   }"
3553   [(set_attr "length" "4")
3554    (set_attr "type" "load_byte")
3555    (set_attr "pool_range" "1020")]
3558 ;; We used to have an early-clobber on the scratch register here.
3559 ;; However, there's a bug somewhere in reload which means that this
3560 ;; can be partially ignored during spill allocation if the memory
3561 ;; address also needs reloading; this causes an abort later on when
3562 ;; we try to verify the operands.  Fortunately, we don't really need
3563 ;; the early-clobber: we can always use operand 0 if operand 2
3564 ;; overlaps the address.
3565 (define_insn "*thumb_extendhisi2_insn_v6"
3566   [(set (match_operand:SI 0 "register_operand" "=l,l")
3567         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3568    (clobber (match_scratch:SI 2 "=X,l"))]
3569   "TARGET_THUMB && arm_arch6"
3570   "*
3571   {
3572     rtx ops[4];
3573     rtx mem;
3575     if (which_alternative == 0)
3576       return \"sxth\\t%0, %1\";
3578     mem = XEXP (operands[1], 0);
3580     /* This code used to try to use 'V', and fix the address only if it was
3581        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3582        range of QImode offsets, and offsettable_address_p does a QImode
3583        address check.  */
3584        
3585     if (GET_CODE (mem) == CONST)
3586       mem = XEXP (mem, 0);
3587     
3588     if (GET_CODE (mem) == LABEL_REF)
3589       return \"ldr\\t%0, %1\";
3590     
3591     if (GET_CODE (mem) == PLUS)
3592       {
3593         rtx a = XEXP (mem, 0);
3594         rtx b = XEXP (mem, 1);
3596         if (GET_CODE (a) == LABEL_REF
3597             && GET_CODE (b) == CONST_INT)
3598           return \"ldr\\t%0, %1\";
3600         if (GET_CODE (b) == REG)
3601           return \"ldrsh\\t%0, %1\";
3602           
3603         ops[1] = a;
3604         ops[2] = b;
3605       }
3606     else
3607       {
3608         ops[1] = mem;
3609         ops[2] = const0_rtx;
3610       }
3611       
3612     if (GET_CODE (ops[1]) != REG)
3613       {
3614         debug_rtx (ops[1]);
3615         abort ();
3616       }
3618     ops[0] = operands[0];
3619     if (reg_mentioned_p (operands[2], ops[1]))
3620       ops[3] = ops[0];
3621     else
3622       ops[3] = operands[2];
3623     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3624     return \"\";
3625   }"
3626   [(set_attr "length" "2,4")
3627    (set_attr "type" "alu_shift,load_byte")
3628    (set_attr "pool_range" "*,1020")]
3631 (define_expand "extendhisi2_mem"
3632   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3633    (set (match_dup 3)
3634         (zero_extend:SI (match_dup 7)))
3635    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3636    (set (match_operand:SI 0 "" "")
3637         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3638   "TARGET_ARM"
3639   "
3640   {
3641     rtx mem1, mem2;
3642     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3644     mem1 = gen_rtx_MEM (QImode, addr);
3645     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3646     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3647     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3648     operands[0] = gen_lowpart (SImode, operands[0]);
3649     operands[1] = mem1;
3650     operands[2] = gen_reg_rtx (SImode);
3651     operands[3] = gen_reg_rtx (SImode);
3652     operands[6] = gen_reg_rtx (SImode);
3653     operands[7] = mem2;
3655     if (BYTES_BIG_ENDIAN)
3656       {
3657         operands[4] = operands[2];
3658         operands[5] = operands[3];
3659       }
3660     else
3661       {
3662         operands[4] = operands[3];
3663         operands[5] = operands[2];
3664       }
3665   }"
3668 (define_insn "*arm_extendhisi2"
3669   [(set (match_operand:SI 0 "s_register_operand" "=r")
3670         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3671   "TARGET_ARM && arm_arch4 && !arm_arch6"
3672   "ldr%?sh\\t%0, %1"
3673   [(set_attr "type" "load_byte")
3674    (set_attr "predicable" "yes")
3675    (set_attr "pool_range" "256")
3676    (set_attr "neg_pool_range" "244")]
3679 (define_insn "*arm_extendhisi2_v6"
3680   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3681         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3682   "TARGET_ARM && arm_arch6"
3683   "@
3684    sxth%?\\t%0, %1
3685    ldr%?sh\\t%0, %1"
3686   [(set_attr "type" "alu_shift,load_byte")
3687    (set_attr "predicable" "yes")
3688    (set_attr "pool_range" "*,256")
3689    (set_attr "neg_pool_range" "*,244")]
3692 (define_insn "*arm_extendhisi2addsi"
3693   [(set (match_operand:SI 0 "s_register_operand" "=r")
3694         (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3695                  (match_operand:SI 2 "s_register_operand" "r")))]
3696   "TARGET_ARM && arm_arch6"
3697   "sxtah%?\\t%0, %2, %1"
3700 (define_split
3701   [(set (match_operand:SI                 0 "s_register_operand" "")
3702         (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3703    (clobber (match_operand:SI             2 "s_register_operand" ""))]
3704   "TARGET_ARM && (!arm_arch4)"
3705   [(set (match_dup 2) (match_dup 1))
3706    (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3707   "
3708   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3709     FAIL;
3710   "
3713 (define_split
3714   [(set (match_operand:SI                   0 "s_register_operand" "")
3715         (match_operator:SI                  3 "shiftable_operator"
3716          [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3717           (match_operand:SI                 4 "s_register_operand" "")]))
3718    (clobber (match_operand:SI               2 "s_register_operand" ""))]
3719   "TARGET_ARM && (!arm_arch4)"
3720   [(set (match_dup 2) (match_dup 1))
3721    (set (match_dup 0)
3722         (match_op_dup 3
3723          [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3724   "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3725      FAIL;
3726   "
3729 (define_expand "extendqihi2"
3730   [(set (match_dup 2)
3731         (ashift:SI (match_operand:QI 1 "general_operand" "")
3732                    (const_int 24)))
3733    (set (match_operand:HI 0 "s_register_operand" "")
3734         (ashiftrt:SI (match_dup 2)
3735                      (const_int 24)))]
3736   "TARGET_ARM"
3737   "
3738   {
3739     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3740       {
3741         emit_insn (gen_rtx_SET (VOIDmode,
3742                                 operands[0],
3743                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3744         DONE;
3745       }
3746     if (!s_register_operand (operands[1], QImode))
3747       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3748     operands[0] = gen_lowpart (SImode, operands[0]);
3749     operands[1] = gen_lowpart (SImode, operands[1]);
3750     operands[2] = gen_reg_rtx (SImode);
3751   }"
3754 (define_insn "*extendqihi_insn"
3755   [(set (match_operand:HI 0 "s_register_operand" "=r")
3756         (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3757   "TARGET_ARM && arm_arch4"
3758   "ldr%?sb\\t%0, %1"
3759   [(set_attr "type" "load_byte")
3760    (set_attr "predicable" "yes")
3761    (set_attr "pool_range" "256")
3762    (set_attr "neg_pool_range" "244")]
3765 (define_expand "extendqisi2"
3766   [(set (match_dup 2)
3767         (ashift:SI (match_operand:QI 1 "general_operand" "")
3768                    (const_int 24)))
3769    (set (match_operand:SI 0 "s_register_operand" "")
3770         (ashiftrt:SI (match_dup 2)
3771                      (const_int 24)))]
3772   "TARGET_EITHER"
3773   "
3774   {
3775     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3776       {
3777         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3778                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3779         DONE;
3780       }
3782     if (!s_register_operand (operands[1], QImode))
3783       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3785     if (arm_arch6)
3786       {
3787         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3788                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3789         DONE;
3790       }
3792     operands[1] = gen_lowpart (SImode, operands[1]);
3793     operands[2] = gen_reg_rtx (SImode);
3794   }"
3797 (define_insn "*arm_extendqisi"
3798   [(set (match_operand:SI 0 "s_register_operand" "=r")
3799         (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3800   "TARGET_ARM && arm_arch4 && !arm_arch6"
3801   "ldr%?sb\\t%0, %1"
3802   [(set_attr "type" "load_byte")
3803    (set_attr "predicable" "yes")
3804    (set_attr "pool_range" "256")
3805    (set_attr "neg_pool_range" "244")]
3808 (define_insn "*arm_extendqisi_v6"
3809   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3810         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3811   "TARGET_ARM && arm_arch6"
3812   "@
3813    sxtb%?\\t%0, %1
3814    ldr%?sb\\t%0, %1"
3815   [(set_attr "type" "alu_shift,load_byte")
3816    (set_attr "predicable" "yes")
3817    (set_attr "pool_range" "*,256")
3818    (set_attr "neg_pool_range" "*,244")]
3821 (define_insn "*arm_extendqisi2addsi"
3822   [(set (match_operand:SI 0 "s_register_operand" "=r")
3823         (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3824                  (match_operand:SI 2 "s_register_operand" "r")))]
3825   "TARGET_ARM && arm_arch6"
3826   "sxtab%?\\t%0, %2, %1"
3827   [(set_attr "type" "alu_shift")
3828    (set_attr "predicable" "yes")]
3831 (define_insn "*thumb_extendqisi2"
3832   [(set (match_operand:SI 0 "register_operand" "=l,l")
3833         (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3834   "TARGET_THUMB && !arm_arch6"
3835   "*
3836   {
3837     rtx ops[3];
3838     rtx mem = XEXP (operands[1], 0);
3839     
3840     if (GET_CODE (mem) == CONST)
3841       mem = XEXP (mem, 0);
3842     
3843     if (GET_CODE (mem) == LABEL_REF)
3844       return \"ldr\\t%0, %1\";
3846     if (GET_CODE (mem) == PLUS
3847         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3848       return \"ldr\\t%0, %1\";
3849       
3850     if (which_alternative == 0)
3851       return \"ldrsb\\t%0, %1\";
3852       
3853     ops[0] = operands[0];
3854     
3855     if (GET_CODE (mem) == PLUS)
3856       {
3857         rtx a = XEXP (mem, 0);
3858         rtx b = XEXP (mem, 1);
3859         
3860         ops[1] = a;
3861         ops[2] = b;
3863         if (GET_CODE (a) == REG)
3864           {
3865             if (GET_CODE (b) == REG)
3866               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3867             else if (REGNO (a) == REGNO (ops[0]))
3868               {
3869                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3870                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3871                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3872               }
3873             else
3874               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3875           }
3876         else if (GET_CODE (b) != REG)
3877           abort ();
3878         else
3879           {
3880             if (REGNO (b) == REGNO (ops[0]))
3881               {
3882                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3883                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3884                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3885               }
3886             else
3887               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3888           }
3889       }
3890     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3891       {
3892         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3893         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3894         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3895       }
3896     else
3897       {
3898         ops[1] = mem;
3899         ops[2] = const0_rtx;
3900         
3901         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3902       }
3903     return \"\";
3904   }"
3905   [(set_attr "length" "2,6")
3906    (set_attr "type" "load_byte,load_byte")
3907    (set_attr "pool_range" "32,32")]
3910 (define_insn "*thumb_extendqisi2_v6"
3911   [(set (match_operand:SI 0 "register_operand" "=l,l,l")
3912         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
3913   "TARGET_THUMB && arm_arch6"
3914   "*
3915   {
3916     rtx ops[3];
3917     rtx mem;
3919     if (which_alternative == 0)
3920       return \"sxtb\\t%0, %1\";
3922     mem = XEXP (operands[1], 0);
3923     
3924     if (GET_CODE (mem) == CONST)
3925       mem = XEXP (mem, 0);
3926     
3927     if (GET_CODE (mem) == LABEL_REF)
3928       return \"ldr\\t%0, %1\";
3930     if (GET_CODE (mem) == PLUS
3931         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3932       return \"ldr\\t%0, %1\";
3933       
3934     if (which_alternative == 0)
3935       return \"ldrsb\\t%0, %1\";
3936       
3937     ops[0] = operands[0];
3938     
3939     if (GET_CODE (mem) == PLUS)
3940       {
3941         rtx a = XEXP (mem, 0);
3942         rtx b = XEXP (mem, 1);
3943         
3944         ops[1] = a;
3945         ops[2] = b;
3947         if (GET_CODE (a) == REG)
3948           {
3949             if (GET_CODE (b) == REG)
3950               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3951             else if (REGNO (a) == REGNO (ops[0]))
3952               {
3953                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3954                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
3955               }
3956             else
3957               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3958           }
3959         else if (GET_CODE (b) != REG)
3960           abort ();
3961         else
3962           {
3963             if (REGNO (b) == REGNO (ops[0]))
3964               {
3965                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3966                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
3967               }
3968             else
3969               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3970           }
3971       }
3972     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3973       {
3974         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3975         output_asm_insn (\"sxtb\\t%0, %0\", ops);
3976       }
3977     else
3978       {
3979         ops[1] = mem;
3980         ops[2] = const0_rtx;
3981         
3982         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3983       }
3984     return \"\";
3985   }"
3986   [(set_attr "length" "2,2,4")
3987    (set_attr "type" "alu_shift,load_byte,load_byte")
3988    (set_attr "pool_range" "*,32,32")]
3991 (define_expand "extendsfdf2"
3992   [(set (match_operand:DF                  0 "s_register_operand" "")
3993         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
3994   "TARGET_ARM && TARGET_HARD_FLOAT"
3995   ""
3998 ;; Move insns (including loads and stores)
4000 ;; XXX Just some ideas about movti.
4001 ;; I don't think these are a good idea on the arm, there just aren't enough
4002 ;; registers
4003 ;;(define_expand "loadti"
4004 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
4005 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
4006 ;;  "" "")
4008 ;;(define_expand "storeti"
4009 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4010 ;;      (match_operand:TI 1 "s_register_operand" ""))]
4011 ;;  "" "")
4013 ;;(define_expand "movti"
4014 ;;  [(set (match_operand:TI 0 "general_operand" "")
4015 ;;      (match_operand:TI 1 "general_operand" ""))]
4016 ;;  ""
4017 ;;  "
4019 ;;  rtx insn;
4021 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4022 ;;    operands[1] = copy_to_reg (operands[1]);
4023 ;;  if (GET_CODE (operands[0]) == MEM)
4024 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4025 ;;  else if (GET_CODE (operands[1]) == MEM)
4026 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4027 ;;  else
4028 ;;    FAIL;
4030 ;;  emit_insn (insn);
4031 ;;  DONE;
4032 ;;}")
4034 ;; Recognize garbage generated above.
4036 ;;(define_insn ""
4037 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4038 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4039 ;;  ""
4040 ;;  "*
4041 ;;  {
4042 ;;    register mem = (which_alternative < 3);
4043 ;;    register const char *template;
4045 ;;    operands[mem] = XEXP (operands[mem], 0);
4046 ;;    switch (which_alternative)
4047 ;;      {
4048 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4049 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
4050 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
4051 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
4052 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
4053 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
4054 ;;      }
4055 ;;    output_asm_insn (template, operands);
4056 ;;    return \"\";
4057 ;;  }")
4059 (define_expand "movdi"
4060   [(set (match_operand:DI 0 "general_operand" "")
4061         (match_operand:DI 1 "general_operand" ""))]
4062   "TARGET_EITHER"
4063   "
4064   if (TARGET_THUMB)
4065     {
4066       if (!no_new_pseudos)
4067         {
4068           if (GET_CODE (operands[0]) != REG)
4069             operands[1] = force_reg (DImode, operands[1]);
4070         }
4071     }
4072   "
4075 (define_insn "*arm_movdi"
4076   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
4077         (match_operand:DI 1 "di_operand"              "rIK,mi,r"))]
4078   "TARGET_ARM
4079   && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4080   && !TARGET_IWMMXT"
4081   "*
4082   return (output_move_double (operands));
4083   "
4084   [(set_attr "length" "8")
4085    (set_attr "type" "*,load2,store2")
4086    (set_attr "pool_range" "*,1020,*")
4087    (set_attr "neg_pool_range" "*,1008,*")]
4090 ;;; ??? This should have alternatives for constants.
4091 ;;; ??? This was originally identical to the movdf_insn pattern.
4092 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4093 ;;; thumb_reorg with a memory reference.
4094 (define_insn "*thumb_movdi_insn"
4095   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4096         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
4097   "TARGET_THUMB
4098    && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4099    && (   register_operand (operands[0], DImode)
4100        || register_operand (operands[1], DImode))"
4101   "*
4102   {
4103   switch (which_alternative)
4104     {
4105     default:
4106     case 0:
4107       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4108         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
4109       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
4110     case 1:
4111       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4112     case 2:
4113       operands[1] = GEN_INT (- INTVAL (operands[1]));
4114       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4115     case 3:
4116       return \"ldmia\\t%1, {%0, %H0}\";
4117     case 4:
4118       return \"stmia\\t%0, {%1, %H1}\";
4119     case 5:
4120       return thumb_load_double_from_address (operands);
4121     case 6:
4122       operands[2] = gen_rtx_MEM (SImode,
4123                              plus_constant (XEXP (operands[0], 0), 4));
4124       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4125       return \"\";
4126     case 7:
4127       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4128         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4129       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4130     }
4131   }"
4132   [(set_attr "length" "4,4,6,2,2,6,4,4")
4133    (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4134    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4137 (define_expand "movsi"
4138   [(set (match_operand:SI 0 "general_operand" "")
4139         (match_operand:SI 1 "general_operand" ""))]
4140   "TARGET_EITHER"
4141   "
4142   if (TARGET_ARM)
4143     {
4144       /* Everything except mem = const or mem = mem can be done easily.  */
4145       if (GET_CODE (operands[0]) == MEM)
4146         operands[1] = force_reg (SImode, operands[1]);
4147       if (arm_general_register_operand (operands[0], SImode)
4148           && GET_CODE (operands[1]) == CONST_INT
4149           && !(const_ok_for_arm (INTVAL (operands[1]))
4150                || const_ok_for_arm (~INTVAL (operands[1]))))
4151         {
4152            arm_split_constant (SET, SImode, NULL_RTX,
4153                                INTVAL (operands[1]), operands[0], NULL_RTX,
4154                               (no_new_pseudos ? 0
4155                                : preserve_subexpressions_p ()));
4156           DONE;
4157         }
4158     }
4159   else /* TARGET_THUMB....  */
4160     {
4161       if (!no_new_pseudos)
4162         {
4163           if (GET_CODE (operands[0]) != REG)
4164             operands[1] = force_reg (SImode, operands[1]);
4165         }
4166     }
4167     
4168   if (flag_pic
4169       && (CONSTANT_P (operands[1])
4170          || symbol_mentioned_p (operands[1])
4171          || label_mentioned_p (operands[1])))
4172     operands[1] = legitimize_pic_address (operands[1], SImode,
4173                                           (no_new_pseudos ? operands[0] : 0));
4174   "
4177 (define_insn "*arm_movsi_insn"
4178   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4179         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
4180   "TARGET_ARM && ! TARGET_IWMMXT
4181    && !(TARGET_HARD_FLOAT && TARGET_VFP)
4182    && (   register_operand (operands[0], SImode)
4183        || register_operand (operands[1], SImode))"
4184   "@
4185    mov%?\\t%0, %1
4186    mvn%?\\t%0, #%B1
4187    ldr%?\\t%0, %1
4188    str%?\\t%1, %0"
4189   [(set_attr "type" "*,*,load1,store1")
4190    (set_attr "predicable" "yes")
4191    (set_attr "pool_range" "*,*,4096,*")
4192    (set_attr "neg_pool_range" "*,*,4084,*")]
4195 (define_split
4196   [(set (match_operand:SI 0 "arm_general_register_operand" "")
4197         (match_operand:SI 1 "const_int_operand" ""))]
4198   "TARGET_ARM
4199   && (!(const_ok_for_arm (INTVAL (operands[1]))
4200         || const_ok_for_arm (~INTVAL (operands[1]))))"
4201   [(clobber (const_int 0))]
4202   "
4203   arm_split_constant (SET, SImode, NULL_RTX, 
4204                       INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4205   DONE;
4206   "
4209 (define_insn "*thumb_movsi_insn"
4210   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4211         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4212   "TARGET_THUMB
4213    && (   register_operand (operands[0], SImode) 
4214        || register_operand (operands[1], SImode))"
4215   "@
4216    mov  %0, %1
4217    mov  %0, %1
4218    #
4219    #
4220    ldmia\\t%1, {%0}
4221    stmia\\t%0, {%1}
4222    ldr\\t%0, %1
4223    str\\t%1, %0
4224    mov\\t%0, %1"
4225   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4226    (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4227    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4230 (define_split 
4231   [(set (match_operand:SI 0 "register_operand" "")
4232         (match_operand:SI 1 "const_int_operand" ""))]
4233   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4234   [(set (match_dup 0) (match_dup 1))
4235    (set (match_dup 0) (neg:SI (match_dup 0)))]
4236   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4239 (define_split 
4240   [(set (match_operand:SI 0 "register_operand" "")
4241         (match_operand:SI 1 "const_int_operand" ""))]
4242   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4243   [(set (match_dup 0) (match_dup 1))
4244    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4245   "
4246   {
4247     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4248     unsigned HOST_WIDE_INT mask = 0xff;
4249     int i;
4250     
4251     for (i = 0; i < 25; i++)
4252       if ((val & (mask << i)) == val)
4253         break;
4255     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4256     if (i == 0)
4257       FAIL;
4259     operands[1] = GEN_INT (val >> i);
4260     operands[2] = GEN_INT (i);
4261   }"
4264 ;; When generating pic, we need to load the symbol offset into a register.
4265 ;; So that the optimizer does not confuse this with a normal symbol load
4266 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
4267 ;; since that is the only type of relocation we can use.
4269 ;; The rather odd constraints on the following are to force reload to leave
4270 ;; the insn alone, and to force the minipool generation pass to then move
4271 ;; the GOT symbol to memory.
4273 (define_insn "pic_load_addr_arm"
4274   [(set (match_operand:SI 0 "s_register_operand" "=r")
4275         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4276   "TARGET_ARM && flag_pic"
4277   "ldr%?\\t%0, %1"
4278   [(set_attr "type" "load1")
4279    (set (attr "pool_range")     (const_int 4096))
4280    (set (attr "neg_pool_range") (const_int 4084))]
4283 (define_insn "pic_load_addr_thumb"
4284   [(set (match_operand:SI 0 "s_register_operand" "=l")
4285         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4286   "TARGET_THUMB && flag_pic"
4287   "ldr\\t%0, %1"
4288   [(set_attr "type" "load1")
4289    (set (attr "pool_range") (const_int 1024))]
4292 ;; This variant is used for AOF assembly, since it needs to mention the
4293 ;; pic register in the rtl.
4294 (define_expand "pic_load_addr_based"
4295   [(set (match_operand:SI 0 "s_register_operand" "")
4296         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4297   "TARGET_ARM && flag_pic"
4298   "operands[2] = pic_offset_table_rtx;"
4301 (define_insn "*pic_load_addr_based_insn"
4302   [(set (match_operand:SI 0 "s_register_operand" "=r")
4303         (unspec:SI [(match_operand 1 "" "")
4304                     (match_operand 2 "s_register_operand" "r")]
4305                    UNSPEC_PIC_SYM))]
4306   "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4307   "*
4308 #ifdef AOF_ASSEMBLER
4309   operands[1] = aof_pic_entry (operands[1]);
4310 #endif
4311   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4312   return \"\";
4313   "
4314   [(set_attr "type" "load1")
4315    (set (attr "pool_range")
4316         (if_then_else (eq_attr "is_thumb" "yes")
4317                       (const_int 1024)
4318                       (const_int 4096)))
4319    (set (attr "neg_pool_range")
4320         (if_then_else (eq_attr "is_thumb" "yes")
4321                       (const_int 0)
4322                       (const_int 4084)))]
4325 (define_insn "pic_add_dot_plus_four"
4326   [(set (match_operand:SI 0 "register_operand" "+r")
4327         (unspec:SI [(plus:SI (match_dup 0)
4328                              (const (plus:SI (pc) (const_int 4))))]
4329                    UNSPEC_PIC_BASE))
4330    (use (label_ref (match_operand 1 "" "")))]
4331   "TARGET_THUMB && flag_pic"
4332   "*
4333   (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4334                              CODE_LABEL_NUMBER (operands[1]));
4335   return \"add\\t%0, %|pc\";
4336   "
4337   [(set_attr "length" "2")]
4340 (define_insn "pic_add_dot_plus_eight"
4341   [(set (match_operand:SI 0 "register_operand" "+r")
4342         (unspec:SI [(plus:SI (match_dup 0)
4343                              (const (plus:SI (pc) (const_int 8))))]
4344                    UNSPEC_PIC_BASE))
4345    (use (label_ref (match_operand 1 "" "")))]
4346   "TARGET_ARM && flag_pic"
4347   "*
4348     (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4349                                CODE_LABEL_NUMBER (operands[1]));
4350     return \"add%?\\t%0, %|pc, %0\";
4351   "
4352   [(set_attr "predicable" "yes")]
4355 (define_expand "builtin_setjmp_receiver"
4356   [(label_ref (match_operand 0 "" ""))]
4357   "flag_pic"
4358   "
4360   arm_finalize_pic (0);
4361   DONE;
4364 ;; If copying one reg to another we can set the condition codes according to
4365 ;; its value.  Such a move is common after a return from subroutine and the
4366 ;; result is being tested against zero.
4368 (define_insn "*movsi_compare0"
4369   [(set (reg:CC CC_REGNUM)
4370         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4371                     (const_int 0)))
4372    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4373         (match_dup 1))]
4374   "TARGET_ARM"
4375   "@
4376    cmp%?\\t%0, #0
4377    sub%?s\\t%0, %1, #0"
4378   [(set_attr "conds" "set")]
4381 ;; Subroutine to store a half word from a register into memory.
4382 ;; Operand 0 is the source register (HImode)
4383 ;; Operand 1 is the destination address in a register (SImode)
4385 ;; In both this routine and the next, we must be careful not to spill
4386 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4387 ;; can generate unrecognizable rtl.
4389 (define_expand "storehi"
4390   [;; store the low byte
4391    (set (match_operand 1 "" "") (match_dup 3))
4392    ;; extract the high byte
4393    (set (match_dup 2)
4394         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4395    ;; store the high byte
4396    (set (match_dup 4) (match_dup 5))]
4397   "TARGET_ARM"
4398   "
4399   {
4400     rtx op1 = operands[1];
4401     rtx addr = XEXP (op1, 0);
4402     enum rtx_code code = GET_CODE (addr);
4404     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4405         || code == MINUS)
4406       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4408     operands[4] = adjust_address (op1, QImode, 1);
4409     operands[1] = adjust_address (operands[1], QImode, 0);
4410     operands[3] = gen_lowpart (QImode, operands[0]);
4411     operands[0] = gen_lowpart (SImode, operands[0]);
4412     operands[2] = gen_reg_rtx (SImode);
4413     operands[5] = gen_lowpart (QImode, operands[2]);
4414   }"
4417 (define_expand "storehi_bigend"
4418   [(set (match_dup 4) (match_dup 3))
4419    (set (match_dup 2)
4420         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4421    (set (match_operand 1 "" "") (match_dup 5))]
4422   "TARGET_ARM"
4423   "
4424   {
4425     rtx op1 = operands[1];
4426     rtx addr = XEXP (op1, 0);
4427     enum rtx_code code = GET_CODE (addr);
4429     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4430         || code == MINUS)
4431       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4433     operands[4] = adjust_address (op1, QImode, 1);
4434     operands[1] = adjust_address (operands[1], QImode, 0);
4435     operands[3] = gen_lowpart (QImode, operands[0]);
4436     operands[0] = gen_lowpart (SImode, operands[0]);
4437     operands[2] = gen_reg_rtx (SImode);
4438     operands[5] = gen_lowpart (QImode, operands[2]);
4439   }"
4442 ;; Subroutine to store a half word integer constant into memory.
4443 (define_expand "storeinthi"
4444   [(set (match_operand 0 "" "")
4445         (match_operand 1 "" ""))
4446    (set (match_dup 3) (match_dup 2))]
4447   "TARGET_ARM"
4448   "
4449   {
4450     HOST_WIDE_INT value = INTVAL (operands[1]);
4451     rtx addr = XEXP (operands[0], 0);
4452     rtx op0 = operands[0];
4453     enum rtx_code code = GET_CODE (addr);
4455     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4456         || code == MINUS)
4457       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4459     operands[1] = gen_reg_rtx (SImode);
4460     if (BYTES_BIG_ENDIAN)
4461       {
4462         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4463         if ((value & 255) == ((value >> 8) & 255))
4464           operands[2] = operands[1];
4465         else
4466           {
4467             operands[2] = gen_reg_rtx (SImode);
4468             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4469           }
4470       }
4471     else
4472       {
4473         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4474         if ((value & 255) == ((value >> 8) & 255))
4475           operands[2] = operands[1];
4476         else
4477           {
4478             operands[2] = gen_reg_rtx (SImode);
4479             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4480           }
4481       }
4483     operands[3] = adjust_address (op0, QImode, 1);
4484     operands[0] = adjust_address (operands[0], QImode, 0);
4485     operands[2] = gen_lowpart (QImode, operands[2]);
4486     operands[1] = gen_lowpart (QImode, operands[1]);
4487   }"
4490 (define_expand "storehi_single_op"
4491   [(set (match_operand:HI 0 "memory_operand" "")
4492         (match_operand:HI 1 "general_operand" ""))]
4493   "TARGET_ARM && arm_arch4"
4494   "
4495   if (!s_register_operand (operands[1], HImode))
4496     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4497   "
4500 (define_expand "movhi"
4501   [(set (match_operand:HI 0 "general_operand" "")
4502         (match_operand:HI 1 "general_operand" ""))]
4503   "TARGET_EITHER"
4504   "
4505   if (TARGET_ARM)
4506     {
4507       if (!no_new_pseudos)
4508         {
4509           if (GET_CODE (operands[0]) == MEM)
4510             {
4511               if (arm_arch4)
4512                 {
4513                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4514                   DONE;
4515                 }
4516               if (GET_CODE (operands[1]) == CONST_INT)
4517                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4518               else
4519                 {
4520                   if (GET_CODE (operands[1]) == MEM)
4521                     operands[1] = force_reg (HImode, operands[1]);
4522                   if (BYTES_BIG_ENDIAN)
4523                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4524                   else
4525                    emit_insn (gen_storehi (operands[1], operands[0]));
4526                 }
4527               DONE;
4528             }
4529           /* Sign extend a constant, and keep it in an SImode reg.  */
4530           else if (GET_CODE (operands[1]) == CONST_INT)
4531             {
4532               rtx reg = gen_reg_rtx (SImode);
4533               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4535               /* If the constant is already valid, leave it alone.  */
4536               if (!const_ok_for_arm (val))
4537                 {
4538                   /* If setting all the top bits will make the constant 
4539                      loadable in a single instruction, then set them.  
4540                      Otherwise, sign extend the number.  */
4542                   if (const_ok_for_arm (~(val | ~0xffff)))
4543                     val |= ~0xffff;
4544                   else if (val & 0x8000)
4545                     val |= ~0xffff;
4546                 }
4548               emit_insn (gen_movsi (reg, GEN_INT (val)));
4549               operands[1] = gen_lowpart (HImode, reg);
4550             }
4551           else if (arm_arch4 && !no_new_pseudos && optimize > 0
4552                    && GET_CODE (operands[1]) == MEM)
4553             {
4554               rtx reg = gen_reg_rtx (SImode);
4556               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4557               operands[1] = gen_lowpart (HImode, reg);
4558             }
4559           else if (!arm_arch4)
4560             {
4561              /* Note: We do not have to worry about TARGET_MMU_TRAPS
4562                 for v4 and up architectures because LDRH instructions will
4563                 be used to access the HI values, and these cannot generate
4564                 unaligned word access faults in the MMU.  */
4565               if (GET_CODE (operands[1]) == MEM)
4566                 {
4567                   if (TARGET_MMU_TRAPS)
4568                     {
4569                       rtx base;
4570                       rtx offset = const0_rtx;
4571                       rtx reg = gen_reg_rtx (SImode);
4573                       if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4574                            || (GET_CODE (base) == PLUS
4575                                && (GET_CODE (offset = XEXP (base, 1))
4576                                    == CONST_INT)
4577                                && ((INTVAL(offset) & 1) != 1)
4578                                && GET_CODE (base = XEXP (base, 0)) == REG))
4579                           && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4580                         {
4581                           HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4582                           rtx new;
4584                           new = gen_rtx_MEM (SImode,
4585                                              plus_constant (base, new_offset));
4586                           MEM_COPY_ATTRIBUTES (new, operands[1]);
4587                           emit_insn (gen_movsi (reg, new));
4588                           if (((INTVAL (offset) & 2) != 0)
4589                               ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4590                             {
4591                               rtx reg2 = gen_reg_rtx (SImode);
4593                               emit_insn (gen_lshrsi3 (reg2, reg,
4594                                          GEN_INT (16)));
4595                               reg = reg2;
4596                             }
4597                         }
4598                       else
4599                         emit_insn (gen_movhi_bytes (reg, operands[1]));
4601                       operands[1] = gen_lowpart (HImode, reg);
4602                     }
4603                   else if (BYTES_BIG_ENDIAN)
4604                     {
4605                       rtx base;
4606                       rtx offset = const0_rtx;
4608                       if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4609                            || (GET_CODE (base) == PLUS
4610                               && (GET_CODE (offset = XEXP (base, 1))
4611                                   == CONST_INT)
4612                               && GET_CODE (base = XEXP (base, 0)) == REG))
4613                           && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4614                         {
4615                           rtx reg = gen_reg_rtx (SImode);
4616                           rtx new;
4618                           if ((INTVAL (offset) & 2) == 2)
4619                             {
4620                               HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4621                               new = gen_rtx_MEM (SImode,
4622                                                  plus_constant (base,
4623                                                                 new_offset));
4624                               MEM_COPY_ATTRIBUTES (new, operands[1]);
4625                               emit_insn (gen_movsi (reg, new));
4626                             }
4627                           else
4628                             {
4629                               new = gen_rtx_MEM (SImode,
4630                                                  XEXP (operands[1], 0));
4631                               MEM_COPY_ATTRIBUTES (new, operands[1]);
4632                               emit_insn (gen_rotated_loadsi (reg, new));
4633                             }
4635                           operands[1] = gen_lowpart (HImode, reg);
4636                         }
4637                       else
4638                         {
4639                           emit_insn (gen_movhi_bigend (operands[0],
4640                                                        operands[1]));
4641                           DONE;
4642                         }
4643                     }
4644                }
4645            }
4646         }
4647       /* Handle loading a large integer during reload.  */
4648       else if (GET_CODE (operands[1]) == CONST_INT
4649                && !const_ok_for_arm (INTVAL (operands[1]))
4650                && !const_ok_for_arm (~INTVAL (operands[1])))
4651         {
4652           /* Writing a constant to memory needs a scratch, which should
4653              be handled with SECONDARY_RELOADs.  */
4654           if (GET_CODE (operands[0]) != REG)
4655             abort ();
4657           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4658           emit_insn (gen_movsi (operands[0], operands[1]));
4659           DONE;
4660        }
4661     }
4662   else /* TARGET_THUMB */
4663     {
4664       if (!no_new_pseudos)
4665         {
4666           if (GET_CODE (operands[0]) != REG)
4667             operands[1] = force_reg (HImode, operands[1]);
4669           /* ??? We shouldn't really get invalid addresses here, but this can
4670              happen if we are passed a SP (never OK for HImode/QImode) or 
4671              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4672              HImode/QImode) relative address.  */
4673           /* ??? This should perhaps be fixed elsewhere, for instance, in
4674              fixup_stack_1, by checking for other kinds of invalid addresses,
4675              e.g. a bare reference to a virtual register.  This may confuse the
4676              alpha though, which must handle this case differently.  */
4677           if (GET_CODE (operands[0]) == MEM
4678               && !memory_address_p (GET_MODE (operands[0]),
4679                                     XEXP (operands[0], 0)))
4680             operands[0]
4681               = replace_equiv_address (operands[0],
4682                                        copy_to_reg (XEXP (operands[0], 0)));
4683    
4684           if (GET_CODE (operands[1]) == MEM
4685               && !memory_address_p (GET_MODE (operands[1]),
4686                                     XEXP (operands[1], 0)))
4687             operands[1]
4688               = replace_equiv_address (operands[1],
4689                                        copy_to_reg (XEXP (operands[1], 0)));
4690         }
4691       /* Handle loading a large integer during reload.  */
4692       else if (GET_CODE (operands[1]) == CONST_INT
4693                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4694         {
4695           /* Writing a constant to memory needs a scratch, which should
4696              be handled with SECONDARY_RELOADs.  */
4697           if (GET_CODE (operands[0]) != REG)
4698             abort ();
4700           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4701           emit_insn (gen_movsi (operands[0], operands[1]));
4702           DONE;
4703         }
4704     }
4705   "
4708 (define_insn "*thumb_movhi_insn"
4709   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4710         (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
4711   "TARGET_THUMB
4712    && (   register_operand (operands[0], HImode)
4713        || register_operand (operands[1], HImode))"
4714   "*
4715   switch (which_alternative)
4716     {
4717     case 0: return \"add        %0, %1, #0\";
4718     case 2: return \"strh       %1, %0\";
4719     case 3: return \"mov        %0, %1\";
4720     case 4: return \"mov        %0, %1\";
4721     case 5: return \"mov        %0, %1\";
4722     default: abort ();
4723     case 1:
4724       /* The stack pointer can end up being taken as an index register.
4725           Catch this case here and deal with it.  */
4726       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4727           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4728           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4729         {
4730           rtx ops[2];
4731           ops[0] = operands[0];
4732           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4733       
4734           output_asm_insn (\"mov        %0, %1\", ops);
4736           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4737     
4738         }
4739       return \"ldrh     %0, %1\";
4740     }"
4741   [(set_attr "length" "2,4,2,2,2,2")
4742    (set_attr "type" "*,load1,store1,*,*,*")]
4746 (define_insn "rotated_loadsi"
4747   [(set (match_operand:SI            0 "s_register_operand"        "=r")
4748         (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4749                    (const_int 16)))]
4750   "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4751   "*
4752   {
4753     rtx ops[2];
4755     ops[0] = operands[0];
4756     ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4757     output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4758     return \"\";
4759   }"
4760   [(set_attr "type" "load1")
4761    (set_attr "predicable" "yes")]
4764 (define_expand "movhi_bytes"
4765   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4766    (set (match_dup 3)
4767         (zero_extend:SI (match_dup 6)))
4768    (set (match_operand:SI 0 "" "")
4769          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4770   "TARGET_ARM"
4771   "
4772   {
4773     rtx mem1, mem2;
4774     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4776     mem1 = gen_rtx_MEM (QImode, addr);
4777     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4778     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4779     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4780     operands[0] = gen_lowpart (SImode, operands[0]);
4781     operands[1] = mem1;
4782     operands[2] = gen_reg_rtx (SImode);
4783     operands[3] = gen_reg_rtx (SImode);
4784     operands[6] = mem2;
4786     if (BYTES_BIG_ENDIAN)
4787       {
4788         operands[4] = operands[2];
4789         operands[5] = operands[3];
4790       }
4791     else
4792       {
4793         operands[4] = operands[3];
4794         operands[5] = operands[2];
4795       }
4796   }"
4799 (define_expand "movhi_bigend"
4800   [(set (match_dup 2)
4801         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4802                    (const_int 16)))
4803    (set (match_dup 3)
4804         (ashiftrt:SI (match_dup 2) (const_int 16)))
4805    (set (match_operand:HI 0 "s_register_operand" "")
4806         (match_dup 4))]
4807   "TARGET_ARM"
4808   "
4809   operands[2] = gen_reg_rtx (SImode);
4810   operands[3] = gen_reg_rtx (SImode);
4811   operands[4] = gen_lowpart (HImode, operands[3]);
4812   "
4815 ;; Pattern to recognize insn generated default case above
4816 (define_insn "*movhi_insn_arch4"
4817   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4818         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4819   "TARGET_ARM
4820    && arm_arch4
4821    && (GET_CODE (operands[1]) != CONST_INT
4822        || const_ok_for_arm (INTVAL (operands[1]))
4823        || const_ok_for_arm (~INTVAL (operands[1])))"
4824   "@
4825    mov%?\\t%0, %1\\t%@ movhi
4826    mvn%?\\t%0, #%B1\\t%@ movhi
4827    str%?h\\t%1, %0\\t%@ movhi 
4828    ldr%?h\\t%0, %1\\t%@ movhi"
4829   [(set_attr "type" "*,*,store1,load1")
4830    (set_attr "predicable" "yes")
4831    (set_attr "pool_range" "*,*,*,256")
4832    (set_attr "neg_pool_range" "*,*,*,244")]
4835 (define_insn "*movhi_insn_littleend"
4836   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4837         (match_operand:HI 1 "general_operand"  "rI,K,m"))]
4838   "TARGET_ARM
4839    && !arm_arch4
4840    && !BYTES_BIG_ENDIAN
4841    && !TARGET_MMU_TRAPS
4842    && (GET_CODE (operands[1]) != CONST_INT
4843        || const_ok_for_arm (INTVAL (operands[1]))
4844        || const_ok_for_arm (~INTVAL (operands[1])))"
4845   "@
4846    mov%?\\t%0, %1\\t%@ movhi
4847    mvn%?\\t%0, #%B1\\t%@ movhi
4848    ldr%?\\t%0, %1\\t%@ movhi"
4849   [(set_attr "type" "*,*,load1")
4850    (set_attr "predicable" "yes")
4851    (set_attr "pool_range" "4096")
4852    (set_attr "neg_pool_range" "4084")]
4855 (define_insn "*movhi_insn_bigend"
4856   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4857         (match_operand:HI 1 "general_operand"    "rI,K,m"))]
4858   "TARGET_ARM
4859    && !arm_arch4
4860    && BYTES_BIG_ENDIAN
4861    && !TARGET_MMU_TRAPS
4862    && (GET_CODE (operands[1]) != CONST_INT
4863        || const_ok_for_arm (INTVAL (operands[1]))
4864        || const_ok_for_arm (~INTVAL (operands[1])))"
4865   "@
4866    mov%?\\t%0, %1\\t%@ movhi
4867    mvn%?\\t%0, #%B1\\t%@ movhi
4868    ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4869   [(set_attr "type" "*,*,load1")
4870    (set_attr "predicable" "yes")
4871    (set_attr "length" "4,4,8")
4872    (set_attr "pool_range" "*,*,4092")
4873    (set_attr "neg_pool_range" "*,*,4084")]
4876 (define_insn "*loadhi_si_bigend"
4877   [(set (match_operand:SI                       0 "s_register_operand" "=r")
4878         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand"      "m") 0)
4879                    (const_int 16)))]
4880   "TARGET_ARM
4881    && BYTES_BIG_ENDIAN
4882    && !TARGET_MMU_TRAPS"
4883   "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4884   [(set_attr "type" "load1")
4885    (set_attr "predicable" "yes")
4886    (set_attr "pool_range" "4096")
4887    (set_attr "neg_pool_range" "4084")]
4890 (define_insn "*movhi_bytes"
4891   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4892         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4893   "TARGET_ARM && TARGET_MMU_TRAPS"
4894   "@
4895    mov%?\\t%0, %1\\t%@ movhi
4896    mvn%?\\t%0, #%B1\\t%@ movhi"
4897   [(set_attr "predicable" "yes")]
4900 (define_insn "thumb_movhi_clobber"
4901   [(set (match_operand:HI     0 "memory_operand"   "=m")
4902         (match_operand:HI     1 "register_operand" "l"))
4903    (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4904   "TARGET_THUMB"
4905   "*
4906   abort ();"
4908         
4909 ;; We use a DImode scratch because we may occasionally need an additional
4910 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4911 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4912 (define_expand "reload_outhi"
4913   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4914               (match_operand:HI 1 "s_register_operand"        "r")
4915               (match_operand:DI 2 "s_register_operand"        "=&l")])]
4916   "TARGET_EITHER"
4917   "if (TARGET_ARM)
4918      arm_reload_out_hi (operands);
4919    else
4920      thumb_reload_out_hi (operands);
4921   DONE;
4922   "
4925 (define_expand "reload_inhi"
4926   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4927               (match_operand:HI 1 "arm_reload_memory_operand" "o")
4928               (match_operand:DI 2 "s_register_operand" "=&r")])]
4929   "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4930   "
4931   if (TARGET_ARM)
4932     arm_reload_in_hi (operands);
4933   else
4934     thumb_reload_out_hi (operands);
4935   DONE;
4938 (define_expand "movqi"
4939   [(set (match_operand:QI 0 "general_operand" "")
4940         (match_operand:QI 1 "general_operand" ""))]
4941   "TARGET_EITHER"
4942   "
4943   if (TARGET_ARM)
4944     {
4945       /* Everything except mem = const or mem = mem can be done easily */
4947       if (!no_new_pseudos)
4948         {
4949           if (GET_CODE (operands[1]) == CONST_INT)
4950             {
4951               rtx reg = gen_reg_rtx (SImode);
4953               emit_insn (gen_movsi (reg, operands[1]));
4954               operands[1] = gen_lowpart (QImode, reg);
4955             }
4956           if (GET_CODE (operands[1]) == MEM && optimize > 0)
4957             {
4958               rtx reg = gen_reg_rtx (SImode);
4960               emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4961               operands[1] = gen_lowpart (QImode, reg);
4962             }
4963           if (GET_CODE (operands[0]) == MEM)
4964             operands[1] = force_reg (QImode, operands[1]);
4965         }
4966     }
4967   else /* TARGET_THUMB */
4968     {
4969       if (!no_new_pseudos)
4970         {
4971           if (GET_CODE (operands[0]) != REG)
4972             operands[1] = force_reg (QImode, operands[1]);
4974           /* ??? We shouldn't really get invalid addresses here, but this can
4975              happen if we are passed a SP (never OK for HImode/QImode) or
4976              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4977              HImode/QImode) relative address.  */
4978           /* ??? This should perhaps be fixed elsewhere, for instance, in
4979              fixup_stack_1, by checking for other kinds of invalid addresses,
4980              e.g. a bare reference to a virtual register.  This may confuse the
4981              alpha though, which must handle this case differently.  */
4982           if (GET_CODE (operands[0]) == MEM
4983               && !memory_address_p (GET_MODE (operands[0]),
4984                                      XEXP (operands[0], 0)))
4985             operands[0]
4986               = replace_equiv_address (operands[0],
4987                                        copy_to_reg (XEXP (operands[0], 0)));
4988           if (GET_CODE (operands[1]) == MEM
4989               && !memory_address_p (GET_MODE (operands[1]),
4990                                     XEXP (operands[1], 0)))
4991              operands[1]
4992                = replace_equiv_address (operands[1],
4993                                         copy_to_reg (XEXP (operands[1], 0)));
4994         }
4995       /* Handle loading a large integer during reload.  */
4996       else if (GET_CODE (operands[1]) == CONST_INT
4997                && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4998         {
4999           /* Writing a constant to memory needs a scratch, which should
5000              be handled with SECONDARY_RELOADs.  */
5001           if (GET_CODE (operands[0]) != REG)
5002             abort ();
5004           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5005           emit_insn (gen_movsi (operands[0], operands[1]));
5006           DONE;
5007        }
5008     }
5009   "
5013 (define_insn "*arm_movqi_insn"
5014   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5015         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5016   "TARGET_ARM
5017    && (   register_operand (operands[0], QImode)
5018        || register_operand (operands[1], QImode))"
5019   "@
5020    mov%?\\t%0, %1
5021    mvn%?\\t%0, #%B1
5022    ldr%?b\\t%0, %1
5023    str%?b\\t%1, %0"
5024   [(set_attr "type" "*,*,load1,store1")
5025    (set_attr "predicable" "yes")]
5028 (define_insn "*thumb_movqi_insn"
5029   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5030         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
5031   "TARGET_THUMB
5032    && (   register_operand (operands[0], QImode)
5033        || register_operand (operands[1], QImode))"
5034   "@
5035    add\\t%0, %1, #0
5036    ldrb\\t%0, %1
5037    strb\\t%1, %0
5038    mov\\t%0, %1
5039    mov\\t%0, %1
5040    mov\\t%0, %1"
5041   [(set_attr "length" "2")
5042    (set_attr "type" "*,load1,store1,*,*,*")
5043    (set_attr "pool_range" "*,32,*,*,*,*")]
5046 (define_expand "movsf"
5047   [(set (match_operand:SF 0 "general_operand" "")
5048         (match_operand:SF 1 "general_operand" ""))]
5049   "TARGET_EITHER"
5050   "
5051   if (TARGET_ARM)
5052     {
5053       if (GET_CODE (operands[0]) == MEM)
5054         operands[1] = force_reg (SFmode, operands[1]);
5055     }
5056   else /* TARGET_THUMB */
5057     {
5058       if (!no_new_pseudos)
5059         {
5060            if (GET_CODE (operands[0]) != REG)
5061              operands[1] = force_reg (SFmode, operands[1]);
5062         }
5063     }
5064   "
5067 (define_split
5068   [(set (match_operand:SF 0 "nonimmediate_operand" "")
5069         (match_operand:SF 1 "immediate_operand" ""))]
5070   "TARGET_ARM
5071    && !(TARGET_HARD_FLOAT && TARGET_FPA)
5072    && reload_completed
5073    && GET_CODE (operands[1]) == CONST_DOUBLE"
5074   [(set (match_dup 2) (match_dup 3))]
5075   "
5076   operands[2] = gen_lowpart (SImode, operands[0]);
5077   operands[3] = gen_lowpart (SImode, operands[1]);
5078   if (operands[2] == 0 || operands[3] == 0)
5079     FAIL;
5080   "
5083 (define_insn "*arm_movsf_soft_insn"
5084   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5085         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
5086   "TARGET_ARM
5087    && TARGET_SOFT_FLOAT
5088    && (GET_CODE (operands[0]) != MEM
5089        || register_operand (operands[1], SFmode))"
5090   "@
5091    mov%?\\t%0, %1
5092    ldr%?\\t%0, %1\\t%@ float
5093    str%?\\t%1, %0\\t%@ float"
5094   [(set_attr "length" "4,4,4")
5095    (set_attr "predicable" "yes")
5096    (set_attr "type" "*,load1,store1")
5097    (set_attr "pool_range" "*,4096,*")
5098    (set_attr "neg_pool_range" "*,4084,*")]
5101 ;;; ??? This should have alternatives for constants.
5102 (define_insn "*thumb_movsf_insn"
5103   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5104         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5105   "TARGET_THUMB
5106    && (   register_operand (operands[0], SFmode) 
5107        || register_operand (operands[1], SFmode))"
5108   "@
5109    add\\t%0, %1, #0
5110    ldmia\\t%1, {%0}
5111    stmia\\t%0, {%1}
5112    ldr\\t%0, %1
5113    str\\t%1, %0
5114    mov\\t%0, %1
5115    mov\\t%0, %1"
5116   [(set_attr "length" "2")
5117    (set_attr "type" "*,load1,store1,load1,store1,*,*")
5118    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5121 (define_expand "movdf"
5122   [(set (match_operand:DF 0 "general_operand" "")
5123         (match_operand:DF 1 "general_operand" ""))]
5124   "TARGET_EITHER"
5125   "
5126   if (TARGET_ARM)
5127     {
5128       if (GET_CODE (operands[0]) == MEM)
5129         operands[1] = force_reg (DFmode, operands[1]);
5130     }
5131   else /* TARGET_THUMB */
5132     {
5133       if (!no_new_pseudos)
5134         {
5135           if (GET_CODE (operands[0]) != REG)
5136             operands[1] = force_reg (DFmode, operands[1]);
5137         }
5138     }
5139   "
5142 ;; Reloading a df mode value stored in integer regs to memory can require a
5143 ;; scratch reg.
5144 (define_expand "reload_outdf"
5145   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5146    (match_operand:DF 1 "s_register_operand" "r")
5147    (match_operand:SI 2 "s_register_operand" "=&r")]
5148   "TARGET_ARM"
5149   "
5150   {
5151     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5153     if (code == REG)
5154       operands[2] = XEXP (operands[0], 0);
5155     else if (code == POST_INC || code == PRE_DEC)
5156       {
5157         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5158         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5159         emit_insn (gen_movdi (operands[0], operands[1]));
5160         DONE;
5161       }
5162     else if (code == PRE_INC)
5163       {
5164         rtx reg = XEXP (XEXP (operands[0], 0), 0);
5166         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5167         operands[2] = reg;
5168       }
5169     else if (code == POST_DEC)
5170       operands[2] = XEXP (XEXP (operands[0], 0), 0);
5171     else
5172       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5173                              XEXP (XEXP (operands[0], 0), 1)));
5175     emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5176                             operands[1]));
5178     if (code == POST_DEC)
5179       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5181     DONE;
5182   }"
5185 (define_insn "*movdf_soft_insn"
5186   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
5187         (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
5188   "TARGET_ARM && TARGET_SOFT_FLOAT
5189   "
5190   "* return output_move_double (operands);"
5191   [(set_attr "length" "8,8,8")
5192    (set_attr "type" "*,load2,store2")
5193    (set_attr "pool_range" "1020")
5194    (set_attr "neg_pool_range" "1008")]
5197 ;;; ??? This should have alternatives for constants.
5198 ;;; ??? This was originally identical to the movdi_insn pattern.
5199 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5200 ;;; thumb_reorg with a memory reference.
5201 (define_insn "*thumb_movdf_insn"
5202   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5203         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5204   "TARGET_THUMB
5205    && (   register_operand (operands[0], DFmode)
5206        || register_operand (operands[1], DFmode))"
5207   "*
5208   switch (which_alternative)
5209     {
5210     default:
5211     case 0:
5212       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5213         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5214       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5215     case 1:
5216       return \"ldmia\\t%1, {%0, %H0}\";
5217     case 2:
5218       return \"stmia\\t%0, {%1, %H1}\";
5219     case 3:
5220       return thumb_load_double_from_address (operands);
5221     case 4:
5222       operands[2] = gen_rtx_MEM (SImode,
5223                                  plus_constant (XEXP (operands[0], 0), 4));
5224       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5225       return \"\";
5226     case 5:
5227       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5228         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5229       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5230     }
5231   "
5232   [(set_attr "length" "4,2,2,6,4,4")
5233    (set_attr "type" "*,load2,store2,load2,store2,*")
5234    (set_attr "pool_range" "*,*,*,1020,*,*")]
5237 ;; Vector Moves
5238 (define_expand "movv2si"
5239   [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5240         (match_operand:V2SI 1 "general_operand" ""))]
5241   "TARGET_REALLY_IWMMXT"
5245 (define_expand "movv4hi"
5246   [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5247         (match_operand:V4HI 1 "general_operand" ""))]
5248   "TARGET_REALLY_IWMMXT"
5252 (define_expand "movv8qi"
5253   [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5254         (match_operand:V8QI 1 "general_operand" ""))]
5255   "TARGET_REALLY_IWMMXT"
5260 ;; load- and store-multiple insns
5261 ;; The arm can load/store any set of registers, provided that they are in
5262 ;; ascending order; but that is beyond GCC so stick with what it knows.
5264 (define_expand "load_multiple"
5265   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5266                           (match_operand:SI 1 "" ""))
5267                      (use (match_operand:SI 2 "" ""))])]
5268   "TARGET_ARM"
5269   "
5270   /* Support only fixed point registers.  */
5271   if (GET_CODE (operands[2]) != CONST_INT
5272       || INTVAL (operands[2]) > 14
5273       || INTVAL (operands[2]) < 2
5274       || GET_CODE (operands[1]) != MEM
5275       || GET_CODE (operands[0]) != REG
5276       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5277       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5278     FAIL;
5280   operands[3]
5281     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5282                              force_reg (SImode, XEXP (operands[1], 0)),
5283                              TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5284                              MEM_IN_STRUCT_P(operands[1]),
5285                              MEM_SCALAR_P (operands[1]));
5286   "
5289 ;; Load multiple with write-back
5291 (define_insn "*ldmsi_postinc4"
5292   [(match_parallel 0 "load_multiple_operation"
5293     [(set (match_operand:SI 1 "s_register_operand" "=r")
5294           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5295                    (const_int 16)))
5296      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5297           (mem:SI (match_dup 2)))
5298      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5299           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5300      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5301           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5302      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5303           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5304   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5305   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5306   [(set_attr "type" "load4")
5307    (set_attr "predicable" "yes")]
5310 (define_insn "*ldmsi_postinc3"
5311   [(match_parallel 0 "load_multiple_operation"
5312     [(set (match_operand:SI 1 "s_register_operand" "=r")
5313           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5314                    (const_int 12)))
5315      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5316           (mem:SI (match_dup 2)))
5317      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5318           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5319      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5320           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5321   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5322   "ldm%?ia\\t%1!, {%3, %4, %5}"
5323   [(set_attr "type" "load3")
5324    (set_attr "predicable" "yes")]
5327 (define_insn "*ldmsi_postinc2"
5328   [(match_parallel 0 "load_multiple_operation"
5329     [(set (match_operand:SI 1 "s_register_operand" "=r")
5330           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5331                    (const_int 8)))
5332      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5333           (mem:SI (match_dup 2)))
5334      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5335           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5336   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5337   "ldm%?ia\\t%1!, {%3, %4}"
5338   [(set_attr "type" "load2")
5339    (set_attr "predicable" "yes")]
5342 ;; Ordinary load multiple
5344 (define_insn "*ldmsi4"
5345   [(match_parallel 0 "load_multiple_operation"
5346     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5347           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5348      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5349           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5350      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5351           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5352      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5353           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5354   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5355   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5356   [(set_attr "type" "load4")
5357    (set_attr "predicable" "yes")]
5360 (define_insn "*ldmsi3"
5361   [(match_parallel 0 "load_multiple_operation"
5362     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5363           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5364      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5365           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5366      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5367           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5368   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5369   "ldm%?ia\\t%1, {%2, %3, %4}"
5370   [(set_attr "type" "load3")
5371    (set_attr "predicable" "yes")]
5374 (define_insn "*ldmsi2"
5375   [(match_parallel 0 "load_multiple_operation"
5376     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5377           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5378      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5379           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5380   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5381   "ldm%?ia\\t%1, {%2, %3}"
5382   [(set_attr "type" "load2")
5383    (set_attr "predicable" "yes")]
5386 (define_expand "store_multiple"
5387   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5388                           (match_operand:SI 1 "" ""))
5389                      (use (match_operand:SI 2 "" ""))])]
5390   "TARGET_ARM"
5391   "
5392   /* Support only fixed point registers.  */
5393   if (GET_CODE (operands[2]) != CONST_INT
5394       || INTVAL (operands[2]) > 14
5395       || INTVAL (operands[2]) < 2
5396       || GET_CODE (operands[1]) != REG
5397       || GET_CODE (operands[0]) != MEM
5398       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5399       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5400     FAIL;
5402   operands[3]
5403     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5404                               force_reg (SImode, XEXP (operands[0], 0)),
5405                               TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5406                               MEM_IN_STRUCT_P(operands[0]), 
5407                               MEM_SCALAR_P (operands[0]));
5408   "
5411 ;; Store multiple with write-back
5413 (define_insn "*stmsi_postinc4"
5414   [(match_parallel 0 "store_multiple_operation"
5415     [(set (match_operand:SI 1 "s_register_operand" "=r")
5416           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5417                    (const_int 16)))
5418      (set (mem:SI (match_dup 2))
5419           (match_operand:SI 3 "arm_hard_register_operand" ""))
5420      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5421           (match_operand:SI 4 "arm_hard_register_operand" ""))
5422      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5423           (match_operand:SI 5 "arm_hard_register_operand" ""))
5424      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5425           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5426   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5427   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5428   [(set_attr "predicable" "yes")
5429    (set_attr "type" "store4")]
5432 (define_insn "*stmsi_postinc3"
5433   [(match_parallel 0 "store_multiple_operation"
5434     [(set (match_operand:SI 1 "s_register_operand" "=r")
5435           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5436                    (const_int 12)))
5437      (set (mem:SI (match_dup 2))
5438           (match_operand:SI 3 "arm_hard_register_operand" ""))
5439      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5440           (match_operand:SI 4 "arm_hard_register_operand" ""))
5441      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5442           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5443   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5444   "stm%?ia\\t%1!, {%3, %4, %5}"
5445   [(set_attr "predicable" "yes")
5446    (set_attr "type" "store3")]
5449 (define_insn "*stmsi_postinc2"
5450   [(match_parallel 0 "store_multiple_operation"
5451     [(set (match_operand:SI 1 "s_register_operand" "=r")
5452           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5453                    (const_int 8)))
5454      (set (mem:SI (match_dup 2))
5455           (match_operand:SI 3 "arm_hard_register_operand" ""))
5456      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5457           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5458   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5459   "stm%?ia\\t%1!, {%3, %4}"
5460   [(set_attr "predicable" "yes")
5461    (set_attr "type" "store2")]
5464 ;; Ordinary store multiple
5466 (define_insn "*stmsi4"
5467   [(match_parallel 0 "store_multiple_operation"
5468     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5469           (match_operand:SI 2 "arm_hard_register_operand" ""))
5470      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5471           (match_operand:SI 3 "arm_hard_register_operand" ""))
5472      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5473           (match_operand:SI 4 "arm_hard_register_operand" ""))
5474      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5475           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5476   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5477   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5478   [(set_attr "predicable" "yes")
5479    (set_attr "type" "store4")]
5482 (define_insn "*stmsi3"
5483   [(match_parallel 0 "store_multiple_operation"
5484     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5485           (match_operand:SI 2 "arm_hard_register_operand" ""))
5486      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5487           (match_operand:SI 3 "arm_hard_register_operand" ""))
5488      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5489           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5490   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5491   "stm%?ia\\t%1, {%2, %3, %4}"
5492   [(set_attr "predicable" "yes")
5493    (set_attr "type" "store3")]
5496 (define_insn "*stmsi2"
5497   [(match_parallel 0 "store_multiple_operation"
5498     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5499           (match_operand:SI 2 "arm_hard_register_operand" ""))
5500      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5501           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5502   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5503   "stm%?ia\\t%1, {%2, %3}"
5504   [(set_attr "predicable" "yes")
5505    (set_attr "type" "store2")]
5508 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5509 ;; We could let this apply for blocks of less than this, but it clobbers so
5510 ;; many registers that there is then probably a better way.
5512 (define_expand "movstrqi"
5513   [(match_operand:BLK 0 "general_operand" "")
5514    (match_operand:BLK 1 "general_operand" "")
5515    (match_operand:SI 2 "const_int_operand" "")
5516    (match_operand:SI 3 "const_int_operand" "")]
5517   "TARGET_EITHER"
5518   "
5519   if (TARGET_ARM)
5520     {
5521       if (arm_gen_movstrqi (operands))
5522         DONE;
5523       FAIL;
5524     }
5525   else /* TARGET_THUMB */
5526     {
5527       if (   INTVAL (operands[3]) != 4
5528           || INTVAL (operands[2]) > 48)
5529         FAIL;
5531       thumb_expand_movstrqi (operands);
5532       DONE;
5533     }
5534   "
5537 ;; Thumb block-move insns
5539 (define_insn "movmem12b"
5540   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5541         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5542    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5543         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5544    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5545         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5546    (set (match_operand:SI 0 "register_operand" "=l")
5547         (plus:SI (match_dup 2) (const_int 12)))
5548    (set (match_operand:SI 1 "register_operand" "=l")
5549         (plus:SI (match_dup 3) (const_int 12)))
5550    (clobber (match_scratch:SI 4 "=&l"))
5551    (clobber (match_scratch:SI 5 "=&l"))
5552    (clobber (match_scratch:SI 6 "=&l"))]
5553   "TARGET_THUMB"
5554   "* return thumb_output_move_mem_multiple (3, operands);"
5555   [(set_attr "length" "4")
5556    ; This isn't entirely accurate...  It loads as well, but in terms of
5557    ; scheduling the following insn it is better to consider it as a store
5558    (set_attr "type" "store3")]
5561 (define_insn "movmem8b"
5562   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5563         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5564    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5565         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5566    (set (match_operand:SI 0 "register_operand" "=l")
5567         (plus:SI (match_dup 2) (const_int 8)))
5568    (set (match_operand:SI 1 "register_operand" "=l")
5569         (plus:SI (match_dup 3) (const_int 8)))
5570    (clobber (match_scratch:SI 4 "=&l"))
5571    (clobber (match_scratch:SI 5 "=&l"))]
5572   "TARGET_THUMB"
5573   "* return thumb_output_move_mem_multiple (2, operands);"
5574   [(set_attr "length" "4")
5575    ; This isn't entirely accurate...  It loads as well, but in terms of
5576    ; scheduling the following insn it is better to consider it as a store
5577    (set_attr "type" "store2")]
5582 ;; Compare & branch insns
5583 ;; The range calculations are based as follows:
5584 ;; For forward branches, the address calculation returns the address of
5585 ;; the next instruction.  This is 2 beyond the branch instruction.
5586 ;; For backward branches, the address calculation returns the address of
5587 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5588 ;; instruction for the shortest sequence, and 4 before the branch instruction
5589 ;; if we have to jump around an unconditional branch.
5590 ;; To the basic branch range the PC offset must be added (this is +4).
5591 ;; So for forward branches we have 
5592 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5593 ;; And for backward branches we have 
5594 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5596 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5597 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5599 (define_expand "cbranchsi4"
5600   [(set (pc) (if_then_else
5601               (match_operator 0 "arm_comparison_operator"
5602                [(match_operand:SI 1 "s_register_operand" "")
5603                 (match_operand:SI 2 "nonmemory_operand" "")])
5604               (label_ref (match_operand 3 "" ""))
5605               (pc)))]
5606   "TARGET_THUMB"
5607   "
5608   if (thumb_cmpneg_operand (operands[2], SImode))
5609     {
5610       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5611                                               operands[3], operands[0]));
5612       DONE;
5613     }
5614   if (!thumb_cmp_operand (operands[2], SImode))
5615     operands[2] = force_reg (SImode, operands[2]);
5616   ")
5618 (define_insn "*cbranchsi4_insn"
5619   [(set (pc) (if_then_else
5620               (match_operator 0 "arm_comparison_operator"
5621                [(match_operand:SI 1 "s_register_operand" "l,*h")
5622                 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5623               (label_ref (match_operand 3 "" ""))
5624               (pc)))]
5625   "TARGET_THUMB"
5626   "*
5627   output_asm_insn (\"cmp\\t%1, %2\", operands);
5629   switch (get_attr_length (insn))
5630     {
5631     case 4:  return \"b%d0\\t%l3\";
5632     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5633     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5634     }
5635   "
5636   [(set (attr "far_jump")
5637         (if_then_else
5638             (eq_attr "length" "8")
5639             (const_string "yes")
5640             (const_string "no")))
5641    (set (attr "length") 
5642         (if_then_else
5643             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5644                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5645             (const_int 4)
5646             (if_then_else
5647                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5648                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5649                 (const_int 6)
5650                 (const_int 8))))]
5653 (define_insn "cbranchsi4_scratch"
5654   [(set (pc) (if_then_else
5655               (match_operator 4 "arm_comparison_operator"
5656                [(match_operand:SI 1 "s_register_operand" "l,0")
5657                 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5658               (label_ref (match_operand 3 "" ""))
5659               (pc)))
5660    (clobber (match_scratch:SI 0 "=l,l"))]
5661   "TARGET_THUMB"
5662   "*
5663   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5665   switch (get_attr_length (insn))
5666     {
5667     case 4:  return \"b%d4\\t%l3\";
5668     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5669     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5670     }
5671   "
5672   [(set (attr "far_jump")
5673         (if_then_else
5674             (eq_attr "length" "8")
5675             (const_string "yes")
5676             (const_string "no")))
5677    (set (attr "length") 
5678         (if_then_else
5679             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5680                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5681             (const_int 4)
5682             (if_then_else
5683                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5684                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5685                 (const_int 6)
5686                 (const_int 8))))]
5688 (define_insn "*movsi_cbranchsi4"
5689   [(set (pc)
5690         (if_then_else
5691          (match_operator 3 "arm_comparison_operator"
5692           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5693            (const_int 0)])
5694          (label_ref (match_operand 2 "" ""))
5695          (pc)))
5696    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5697         (match_dup 1))]
5698   "TARGET_THUMB"
5699   "*{
5700   if (which_alternative == 0)
5701     output_asm_insn (\"cmp\t%0, #0\", operands);
5702   else if (which_alternative == 1)
5703     output_asm_insn (\"sub\t%0, %1, #0\", operands);
5704   else
5705     {
5706       output_asm_insn (\"cmp\t%1, #0\", operands);
5707       if (which_alternative == 2)
5708         output_asm_insn (\"mov\t%0, %1\", operands);
5709       else
5710         output_asm_insn (\"str\t%1, %0\", operands);
5711     }
5712   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5713     {
5714     case 4:  return \"b%d3\\t%l2\";
5715     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5716     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5717     }
5718   }"
5719   [(set (attr "far_jump")
5720         (if_then_else
5721             (ior (and (gt (symbol_ref ("which_alternative"))
5722                           (const_int 1))
5723                       (eq_attr "length" "8"))
5724                  (eq_attr "length" "10"))
5725             (const_string "yes")
5726             (const_string "no")))
5727    (set (attr "length")
5728      (if_then_else
5729        (le (symbol_ref ("which_alternative"))
5730                        (const_int 1))
5731        (if_then_else
5732          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5733               (le (minus (match_dup 2) (pc)) (const_int 256)))
5734          (const_int 4)
5735          (if_then_else
5736            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5737                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5738            (const_int 6)
5739            (const_int 8)))
5740        (if_then_else
5741          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5742               (le (minus (match_dup 2) (pc)) (const_int 256)))
5743          (const_int 6)
5744          (if_then_else
5745            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5746                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5747            (const_int 8)
5748            (const_int 10)))))]
5751 (define_insn "*negated_cbranchsi4"
5752   [(set (pc)
5753         (if_then_else
5754          (match_operator 0 "arm_comparison_operator"
5755           [(match_operand:SI 1 "s_register_operand" "l")
5756            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5757          (label_ref (match_operand 3 "" ""))
5758          (pc)))]
5759   "TARGET_THUMB"
5760   "*
5761   output_asm_insn (\"cmn\\t%1, %2\", operands);
5762   switch (get_attr_length (insn))
5763     {
5764     case 4:  return \"b%d0\\t%l3\";
5765     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5766     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5767     }
5768   "
5769   [(set (attr "far_jump")
5770         (if_then_else
5771             (eq_attr "length" "8")
5772             (const_string "yes")
5773             (const_string "no")))
5774    (set (attr "length") 
5775         (if_then_else
5776             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5777                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5778             (const_int 4)
5779             (if_then_else
5780                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5781                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5782                 (const_int 6)
5783                 (const_int 8))))]
5786 (define_insn "*tbit_cbranch"
5787   [(set (pc)
5788         (if_then_else
5789          (match_operator 0 "equality_operator"
5790           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5791                             (const_int 1)
5792                             (match_operand:SI 2 "const_int_operand" "i"))
5793            (const_int 0)])
5794          (label_ref (match_operand 3 "" ""))
5795          (pc)))
5796    (clobber (match_scratch:SI 4 "=l"))]
5797   "TARGET_THUMB"
5798   "*
5799   {
5800   rtx op[3];
5801   op[0] = operands[4];
5802   op[1] = operands[1];
5803   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5805   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5806   switch (get_attr_length (insn))
5807     {
5808     case 4:  return \"b%d0\\t%l3\";
5809     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5810     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5811     }
5812   }"
5813   [(set (attr "far_jump")
5814         (if_then_else
5815             (eq_attr "length" "8")
5816             (const_string "yes")
5817             (const_string "no")))
5818    (set (attr "length") 
5819         (if_then_else
5820             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5821                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5822             (const_int 4)
5823             (if_then_else
5824                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5825                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5826                 (const_int 6)
5827                 (const_int 8))))]
5829   
5830 (define_insn "*tstsi3_cbranch"
5831   [(set (pc)
5832         (if_then_else
5833          (match_operator 3 "equality_operator"
5834           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5835                    (match_operand:SI 1 "s_register_operand" "l"))
5836            (const_int 0)])
5837          (label_ref (match_operand 2 "" ""))
5838          (pc)))]
5839   "TARGET_THUMB"
5840   "*
5841   {
5842   output_asm_insn (\"tst\\t%0, %1\", operands);
5843   switch (get_attr_length (insn))
5844     {
5845     case 4:  return \"b%d3\\t%l2\";
5846     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5847     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5848     }
5849   }"
5850   [(set (attr "far_jump")
5851         (if_then_else
5852             (eq_attr "length" "8")
5853             (const_string "yes")
5854             (const_string "no")))
5855    (set (attr "length") 
5856         (if_then_else
5857             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5858                  (le (minus (match_dup 2) (pc)) (const_int 256)))
5859             (const_int 4)
5860             (if_then_else
5861                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5862                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
5863                 (const_int 6)
5864                 (const_int 8))))]
5866   
5867 (define_insn "*andsi3_cbranch"
5868   [(set (pc)
5869         (if_then_else
5870          (match_operator 5 "equality_operator"
5871           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5872                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5873            (const_int 0)])
5874          (label_ref (match_operand 4 "" ""))
5875          (pc)))
5876    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5877         (and:SI (match_dup 2) (match_dup 3)))
5878    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5879   "TARGET_THUMB"
5880   "*
5881   {
5882   if (which_alternative == 0)
5883     output_asm_insn (\"and\\t%0, %3\", operands);
5884   else if (which_alternative == 1)
5885     {
5886       output_asm_insn (\"and\\t%1, %3\", operands);
5887       output_asm_insn (\"mov\\t%0, %1\", operands);
5888     }
5889   else
5890     {
5891       output_asm_insn (\"and\\t%1, %3\", operands);
5892       output_asm_insn (\"str\\t%1, %0\", operands);
5893     }
5895   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5896     {
5897     case 4:  return \"b%d5\\t%l4\";
5898     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5899     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5900     }
5901   }"
5902   [(set (attr "far_jump")
5903         (if_then_else
5904             (ior (and (eq (symbol_ref ("which_alternative"))
5905                           (const_int 0))
5906                       (eq_attr "length" "8"))
5907                  (eq_attr "length" "10"))
5908             (const_string "yes")
5909             (const_string "no")))
5910    (set (attr "length")
5911      (if_then_else
5912        (eq (symbol_ref ("which_alternative"))
5913                        (const_int 0))
5914        (if_then_else
5915          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5916               (le (minus (match_dup 4) (pc)) (const_int 256)))
5917          (const_int 4)
5918          (if_then_else
5919            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5920                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5921            (const_int 6)
5922            (const_int 8)))
5923        (if_then_else
5924          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5925               (le (minus (match_dup 4) (pc)) (const_int 256)))
5926          (const_int 6)
5927          (if_then_else
5928            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5929                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5930            (const_int 8)
5931            (const_int 10)))))]
5934 (define_insn "*orrsi3_cbranch_scratch"
5935   [(set (pc)
5936         (if_then_else
5937          (match_operator 4 "equality_operator"
5938           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
5939                    (match_operand:SI 2 "s_register_operand" "l"))
5940            (const_int 0)])
5941          (label_ref (match_operand 3 "" ""))
5942          (pc)))
5943    (clobber (match_scratch:SI 0 "=l"))]
5944   "TARGET_THUMB"
5945   "*
5946   {
5947   output_asm_insn (\"orr\\t%0, %2\", operands);
5948   switch (get_attr_length (insn))
5949     {
5950     case 4:  return \"b%d4\\t%l3\";
5951     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5952     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5953     }
5954   }"
5955   [(set (attr "far_jump")
5956         (if_then_else
5957             (eq_attr "length" "8")
5958             (const_string "yes")
5959             (const_string "no")))
5960    (set (attr "length") 
5961         (if_then_else
5962             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5963                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5964             (const_int 4)
5965             (if_then_else
5966                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5967                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5968                 (const_int 6)
5969                 (const_int 8))))]
5971   
5972 (define_insn "*orrsi3_cbranch"
5973   [(set (pc)
5974         (if_then_else
5975          (match_operator 5 "equality_operator"
5976           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5977                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5978            (const_int 0)])
5979          (label_ref (match_operand 4 "" ""))
5980          (pc)))
5981    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5982         (ior:SI (match_dup 2) (match_dup 3)))
5983    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5984   "TARGET_THUMB"
5985   "*
5986   {
5987   if (which_alternative == 0)
5988     output_asm_insn (\"orr\\t%0, %3\", operands);
5989   else if (which_alternative == 1)
5990     {
5991       output_asm_insn (\"orr\\t%1, %3\", operands);
5992       output_asm_insn (\"mov\\t%0, %1\", operands);
5993     }
5994   else
5995     {
5996       output_asm_insn (\"orr\\t%1, %3\", operands);
5997       output_asm_insn (\"str\\t%1, %0\", operands);
5998     }
6000   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6001     {
6002     case 4:  return \"b%d5\\t%l4\";
6003     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6004     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6005     }
6006   }"
6007   [(set (attr "far_jump")
6008         (if_then_else
6009             (ior (and (eq (symbol_ref ("which_alternative"))
6010                           (const_int 0))
6011                       (eq_attr "length" "8"))
6012                  (eq_attr "length" "10"))
6013             (const_string "yes")
6014             (const_string "no")))
6015    (set (attr "length")
6016      (if_then_else
6017        (eq (symbol_ref ("which_alternative"))
6018                        (const_int 0))
6019        (if_then_else
6020          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6021               (le (minus (match_dup 4) (pc)) (const_int 256)))
6022          (const_int 4)
6023          (if_then_else
6024            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6025                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6026            (const_int 6)
6027            (const_int 8)))
6028        (if_then_else
6029          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6030               (le (minus (match_dup 4) (pc)) (const_int 256)))
6031          (const_int 6)
6032          (if_then_else
6033            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6034                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6035            (const_int 8)
6036            (const_int 10)))))]
6039 (define_insn "*xorsi3_cbranch_scratch"
6040   [(set (pc)
6041         (if_then_else
6042          (match_operator 4 "equality_operator"
6043           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6044                    (match_operand:SI 2 "s_register_operand" "l"))
6045            (const_int 0)])
6046          (label_ref (match_operand 3 "" ""))
6047          (pc)))
6048    (clobber (match_scratch:SI 0 "=l"))]
6049   "TARGET_THUMB"
6050   "*
6051   {
6052   output_asm_insn (\"eor\\t%0, %2\", operands);
6053   switch (get_attr_length (insn))
6054     {
6055     case 4:  return \"b%d4\\t%l3\";
6056     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6057     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6058     }
6059   }"
6060   [(set (attr "far_jump")
6061         (if_then_else
6062             (eq_attr "length" "8")
6063             (const_string "yes")
6064             (const_string "no")))
6065    (set (attr "length") 
6066         (if_then_else
6067             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6068                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6069             (const_int 4)
6070             (if_then_else
6071                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6072                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6073                 (const_int 6)
6074                 (const_int 8))))]
6076   
6077 (define_insn "*xorsi3_cbranch"
6078   [(set (pc)
6079         (if_then_else
6080          (match_operator 5 "equality_operator"
6081           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6082                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6083            (const_int 0)])
6084          (label_ref (match_operand 4 "" ""))
6085          (pc)))
6086    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6087         (xor:SI (match_dup 2) (match_dup 3)))
6088    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6089   "TARGET_THUMB"
6090   "*
6091   {
6092   if (which_alternative == 0)
6093     output_asm_insn (\"eor\\t%0, %3\", operands);
6094   else if (which_alternative == 1)
6095     {
6096       output_asm_insn (\"eor\\t%1, %3\", operands);
6097       output_asm_insn (\"mov\\t%0, %1\", operands);
6098     }
6099   else
6100     {
6101       output_asm_insn (\"eor\\t%1, %3\", operands);
6102       output_asm_insn (\"str\\t%1, %0\", operands);
6103     }
6105   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6106     {
6107     case 4:  return \"b%d5\\t%l4\";
6108     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6109     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6110     }
6111   }"
6112   [(set (attr "far_jump")
6113         (if_then_else
6114             (ior (and (eq (symbol_ref ("which_alternative"))
6115                           (const_int 0))
6116                       (eq_attr "length" "8"))
6117                  (eq_attr "length" "10"))
6118             (const_string "yes")
6119             (const_string "no")))
6120    (set (attr "length")
6121      (if_then_else
6122        (eq (symbol_ref ("which_alternative"))
6123                        (const_int 0))
6124        (if_then_else
6125          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6126               (le (minus (match_dup 4) (pc)) (const_int 256)))
6127          (const_int 4)
6128          (if_then_else
6129            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6130                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6131            (const_int 6)
6132            (const_int 8)))
6133        (if_then_else
6134          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6135               (le (minus (match_dup 4) (pc)) (const_int 256)))
6136          (const_int 6)
6137          (if_then_else
6138            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6139                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6140            (const_int 8)
6141            (const_int 10)))))]
6144 (define_insn "*bicsi3_cbranch_scratch"
6145   [(set (pc)
6146         (if_then_else
6147          (match_operator 4 "equality_operator"
6148           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6149                    (match_operand:SI 1 "s_register_operand" "0"))
6150            (const_int 0)])
6151          (label_ref (match_operand 3 "" ""))
6152          (pc)))
6153    (clobber (match_scratch:SI 0 "=l"))]
6154   "TARGET_THUMB"
6155   "*
6156   {
6157   output_asm_insn (\"bic\\t%0, %2\", operands);
6158   switch (get_attr_length (insn))
6159     {
6160     case 4:  return \"b%d4\\t%l3\";
6161     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6162     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6163     }
6164   }"
6165   [(set (attr "far_jump")
6166         (if_then_else
6167             (eq_attr "length" "8")
6168             (const_string "yes")
6169             (const_string "no")))
6170    (set (attr "length") 
6171         (if_then_else
6172             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6173                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6174             (const_int 4)
6175             (if_then_else
6176                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6177                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6178                 (const_int 6)
6179                 (const_int 8))))]
6181   
6182 (define_insn "*bicsi3_cbranch"
6183   [(set (pc)
6184         (if_then_else
6185          (match_operator 5 "equality_operator"
6186           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6187                    (match_operand:SI 2 "s_register_operand" "0,1,1,1"))
6188            (const_int 0)])
6189          (label_ref (match_operand 4 "" ""))
6190          (pc)))
6191    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6192         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6193    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6194   "TARGET_THUMB"
6195   "*
6196   {
6197   if (which_alternative == 0)
6198     output_asm_insn (\"bic\\t%0, %3\", operands);
6199   else if (which_alternative == 1)
6200     {
6201       output_asm_insn (\"bic\\t%1, %3\", operands);
6202       output_asm_insn (\"mov\\t%0, %1\", operands);
6203     }
6204   else
6205     {
6206       output_asm_insn (\"bic\\t%1, %3\", operands);
6207       output_asm_insn (\"str\\t%1, %0\", operands);
6208     }
6210   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6211     {
6212     case 4:  return \"b%d5\\t%l4\";
6213     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6214     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6215     }
6216   }"
6217   [(set (attr "far_jump")
6218         (if_then_else
6219             (ior (and (eq (symbol_ref ("which_alternative"))
6220                           (const_int 0))
6221                       (eq_attr "length" "8"))
6222                  (eq_attr "length" "10"))
6223             (const_string "yes")
6224             (const_string "no")))
6225    (set (attr "length")
6226      (if_then_else
6227        (eq (symbol_ref ("which_alternative"))
6228                        (const_int 0))
6229        (if_then_else
6230          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6231               (le (minus (match_dup 4) (pc)) (const_int 256)))
6232          (const_int 4)
6233          (if_then_else
6234            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6235                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6236            (const_int 6)
6237            (const_int 8)))
6238        (if_then_else
6239          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6240               (le (minus (match_dup 4) (pc)) (const_int 256)))
6241          (const_int 6)
6242          (if_then_else
6243            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6244                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6245            (const_int 8)
6246            (const_int 10)))))]
6249 (define_insn "*cbranchne_decr1"
6250   [(set (pc)
6251         (if_then_else (match_operator 3 "equality_operator"
6252                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6253                         (const_int 0)])
6254                       (label_ref (match_operand 4 "" ""))
6255                       (pc)))
6256    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6257         (plus:SI (match_dup 2) (const_int -1)))
6258    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6259   "TARGET_THUMB"
6260   "*
6261    {
6262      rtx cond[2];
6263      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6264                                 ? GEU : LTU),
6265                                VOIDmode, operands[2], const1_rtx);
6266      cond[1] = operands[4];
6268      if (which_alternative == 0)
6269        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6270      else if (which_alternative == 1)
6271        {
6272          /* We must provide an alternative for a hi reg because reload 
6273             cannot handle output reloads on a jump instruction, but we
6274             can't subtract into that.  Fortunately a mov from lo to hi
6275             does not clobber the condition codes.  */
6276          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6277          output_asm_insn (\"mov\\t%0, %1\", operands);
6278        }
6279      else
6280        {
6281          /* Similarly, but the target is memory.  */
6282          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6283          output_asm_insn (\"str\\t%1, %0\", operands);
6284        }
6286      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6287        {
6288          case 4:
6289            output_asm_insn (\"b%d0\\t%l1\", cond);
6290            return \"\";
6291          case 6:
6292            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6293            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6294          default:
6295            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6296            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6297        }
6298    }
6299   "
6300   [(set (attr "far_jump")
6301         (if_then_else
6302             (ior (and (eq (symbol_ref ("which_alternative"))
6303                           (const_int 0))
6304                       (eq_attr "length" "8"))
6305                  (eq_attr "length" "10"))
6306             (const_string "yes")
6307             (const_string "no")))
6308    (set_attr_alternative "length"
6309       [
6310        ;; Alternative 0
6311        (if_then_else
6312          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6313               (le (minus (match_dup 4) (pc)) (const_int 256)))
6314          (const_int 4)
6315          (if_then_else
6316            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6317                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6318            (const_int 6)
6319            (const_int 8)))
6320        ;; Alternative 1
6321        (if_then_else
6322          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6323               (le (minus (match_dup 4) (pc)) (const_int 256)))
6324          (const_int 6)
6325          (if_then_else
6326            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6327                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6328            (const_int 8)
6329            (const_int 10)))
6330        ;; Alternative 2
6331        (if_then_else
6332          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6333               (le (minus (match_dup 4) (pc)) (const_int 256)))
6334          (const_int 6)
6335          (if_then_else
6336            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6337                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6338            (const_int 8)
6339            (const_int 10)))
6340        ;; Alternative 3
6341        (if_then_else
6342          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6343               (le (minus (match_dup 4) (pc)) (const_int 256)))
6344          (const_int 6)
6345          (if_then_else
6346            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6347                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6348            (const_int 8)
6349            (const_int 10)))])]
6352 (define_insn "*addsi3_cbranch"
6353   [(set (pc)
6354         (if_then_else
6355          (match_operator 4 "comparison_operator"
6356           [(plus:SI
6357             (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6358             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6359            (const_int 0)])
6360          (label_ref (match_operand 5 "" ""))
6361          (pc)))
6362    (set
6363     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6364     (plus:SI (match_dup 2) (match_dup 3)))
6365    (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6366   "TARGET_THUMB
6367    && (GET_CODE (operands[4]) == EQ
6368        || GET_CODE (operands[4]) == NE
6369        || GET_CODE (operands[4]) == GE
6370        || GET_CODE (operands[4]) == LT)"
6371   "*
6372    {
6373      rtx cond[3];
6375      
6376      cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6377      cond[1] = operands[2];
6378      cond[2] = operands[3];
6380      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6381        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6382      else
6383        output_asm_insn (\"add\\t%0, %1, %2\", cond);
6385      if (which_alternative >= 3
6386          && which_alternative < 4)
6387        output_asm_insn (\"mov\\t%0, %1\", operands);
6388      else if (which_alternative >= 4)
6389        output_asm_insn (\"str\\t%1, %0\", operands);
6391      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6392        {
6393          case 4:
6394            return \"b%d4\\t%l5\";
6395          case 6:
6396            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6397          default:
6398            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6399        }
6400    }
6401   "
6402   [(set (attr "far_jump")
6403         (if_then_else
6404             (ior (and (lt (symbol_ref ("which_alternative"))
6405                           (const_int 3))
6406                       (eq_attr "length" "8"))
6407                  (eq_attr "length" "10"))
6408             (const_string "yes")
6409             (const_string "no")))
6410    (set (attr "length")
6411      (if_then_else
6412        (lt (symbol_ref ("which_alternative"))
6413                        (const_int 3))
6414        (if_then_else
6415          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6416               (le (minus (match_dup 5) (pc)) (const_int 256)))
6417          (const_int 4)
6418          (if_then_else
6419            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6420                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6421            (const_int 6)
6422            (const_int 8)))
6423        (if_then_else
6424          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6425               (le (minus (match_dup 5) (pc)) (const_int 256)))
6426          (const_int 6)
6427          (if_then_else
6428            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6429                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6430            (const_int 8)
6431            (const_int 10)))))]
6434 (define_insn "*addsi3_cbranch_scratch"
6435   [(set (pc)
6436         (if_then_else
6437          (match_operator 3 "comparison_operator"
6438           [(plus:SI
6439             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6440             (match_operand:SI 2 "reg_or_int_operand" "J,l,I,L"))
6441            (const_int 0)])
6442          (label_ref (match_operand 4 "" ""))
6443          (pc)))
6444    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6445   "TARGET_THUMB
6446    && (GET_CODE (operands[3]) == EQ
6447        || GET_CODE (operands[3]) == NE
6448        || GET_CODE (operands[3]) == GE
6449        || GET_CODE (operands[3]) == LT)"
6450   "*
6451    {
6452      switch (which_alternative)
6453        {
6454        case 0:
6455          output_asm_insn (\"cmp\t%1, #%n2\", operands);
6456          break;
6457        case 1:
6458          output_asm_insn (\"cmn\t%1, %2\", operands);
6459          break;
6460        case 3:
6461          output_asm_insn (\"add\t%0, %1, %2\", operands);
6462          break;
6463        case 4:
6464          output_asm_insn (\"add\t%0, %0, %2\", operands);
6465          break;
6466        }
6468      switch (get_attr_length (insn))
6469        {
6470          case 4:
6471            return \"b%d3\\t%l4\";
6472          case 6:
6473            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6474          default:
6475            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6476        }
6477    }
6478   "
6479   [(set (attr "far_jump")
6480         (if_then_else
6481             (eq_attr "length" "8")
6482             (const_string "yes")
6483             (const_string "no")))
6484    (set (attr "length")
6485        (if_then_else
6486          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6487               (le (minus (match_dup 4) (pc)) (const_int 256)))
6488          (const_int 4)
6489          (if_then_else
6490            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6491                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6492            (const_int 6)
6493            (const_int 8))))]
6496 (define_insn "*subsi3_cbranch"
6497   [(set (pc)
6498         (if_then_else
6499          (match_operator 4 "comparison_operator"
6500           [(minus:SI
6501             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6502             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6503            (const_int 0)])
6504          (label_ref (match_operand 5 "" ""))
6505          (pc)))
6506    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6507         (minus:SI (match_dup 2) (match_dup 3)))
6508    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6509   "TARGET_THUMB
6510    && (GET_CODE (operands[4]) == EQ
6511        || GET_CODE (operands[4]) == NE
6512        || GET_CODE (operands[4]) == GE
6513        || GET_CODE (operands[4]) == LT)"
6514   "*
6515    {
6516      if (which_alternative == 0)
6517        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6518      else if (which_alternative == 1)
6519        {
6520          /* We must provide an alternative for a hi reg because reload 
6521             cannot handle output reloads on a jump instruction, but we
6522             can't subtract into that.  Fortunately a mov from lo to hi
6523             does not clobber the condition codes.  */
6524          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6525          output_asm_insn (\"mov\\t%0, %1\", operands);
6526        }
6527      else
6528        {
6529          /* Similarly, but the target is memory.  */
6530          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6531          output_asm_insn (\"str\\t%1, %0\", operands);
6532        }
6534      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6535        {
6536          case 4:
6537            return \"b%d4\\t%l5\";
6538          case 6:
6539            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6540          default:
6541            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6542        }
6543    }
6544   "
6545   [(set (attr "far_jump")
6546         (if_then_else
6547             (ior (and (eq (symbol_ref ("which_alternative"))
6548                           (const_int 0))
6549                       (eq_attr "length" "8"))
6550                  (eq_attr "length" "10"))
6551             (const_string "yes")
6552             (const_string "no")))
6553    (set (attr "length")
6554      (if_then_else
6555        (eq (symbol_ref ("which_alternative"))
6556                        (const_int 0))
6557        (if_then_else
6558          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6559               (le (minus (match_dup 5) (pc)) (const_int 256)))
6560          (const_int 4)
6561          (if_then_else
6562            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6563                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6564            (const_int 6)
6565            (const_int 8)))
6566        (if_then_else
6567          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6568               (le (minus (match_dup 5) (pc)) (const_int 256)))
6569          (const_int 6)
6570          (if_then_else
6571            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6572                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6573            (const_int 8)
6574            (const_int 10)))))]
6577 (define_insn "*subsi3_cbranch_scratch"
6578   [(set (pc)
6579         (if_then_else
6580          (match_operator 0 "arm_comparison_operator"
6581           [(minus:SI (match_operand:SI 1 "register_operand" "l")
6582                      (match_operand:SI 2 "nonmemory_operand" "l"))
6583            (const_int 0)])
6584          (label_ref (match_operand 3 "" ""))
6585          (pc)))]
6586   "TARGET_THUMB
6587    && (GET_CODE (operands[0]) == EQ
6588        || GET_CODE (operands[0]) == NE
6589        || GET_CODE (operands[0]) == GE
6590        || GET_CODE (operands[0]) == LT)"
6591   "*
6592   output_asm_insn (\"cmp\\t%1, %2\", operands);
6593   switch (get_attr_length (insn))
6594     {
6595     case 4:  return \"b%d0\\t%l3\";
6596     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6597     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6598     }
6599   "
6600   [(set (attr "far_jump")
6601         (if_then_else
6602             (eq_attr "length" "8")
6603             (const_string "yes")
6604             (const_string "no")))
6605    (set (attr "length") 
6606         (if_then_else
6607             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6608                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6609             (const_int 4)
6610             (if_then_else
6611                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6612                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6613                 (const_int 6)
6614                 (const_int 8))))]
6617 ;; Comparison and test insns
6619 (define_expand "cmpsi"
6620   [(match_operand:SI 0 "s_register_operand" "")
6621    (match_operand:SI 1 "arm_add_operand" "")]
6622   "TARGET_ARM"
6623   "{
6624     arm_compare_op0 = operands[0];
6625     arm_compare_op1 = operands[1];
6626     DONE;
6627   }"
6630 (define_expand "cmpsf"
6631   [(match_operand:SF 0 "s_register_operand" "")
6632    (match_operand:SF 1 "arm_float_compare_operand" "")]
6633   "TARGET_ARM && TARGET_HARD_FLOAT"
6634   "
6635   arm_compare_op0 = operands[0];
6636   arm_compare_op1 = operands[1];
6637   DONE;
6638   "
6641 (define_expand "cmpdf"
6642   [(match_operand:DF 0 "s_register_operand" "")
6643    (match_operand:DF 1 "arm_float_compare_operand" "")]
6644   "TARGET_ARM && TARGET_HARD_FLOAT"
6645   "
6646   arm_compare_op0 = operands[0];
6647   arm_compare_op1 = operands[1];
6648   DONE;
6649   "
6652 (define_insn "*arm_cmpsi_insn"
6653   [(set (reg:CC CC_REGNUM)
6654         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6655                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
6656   "TARGET_ARM"
6657   "@
6658    cmp%?\\t%0, %1
6659    cmn%?\\t%0, #%n1"
6660   [(set_attr "conds" "set")]
6663 (define_insn "*cmpsi_shiftsi"
6664   [(set (reg:CC CC_REGNUM)
6665         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
6666                     (match_operator:SI  3 "shift_operator"
6667                      [(match_operand:SI 1 "s_register_operand" "r")
6668                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
6669   "TARGET_ARM"
6670   "cmp%?\\t%0, %1%S3"
6671   [(set_attr "conds" "set")
6672    (set_attr "shift" "1")
6673    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6674                       (const_string "alu_shift")
6675                       (const_string "alu_shift_reg")))]
6678 (define_insn "*cmpsi_shiftsi_swp"
6679   [(set (reg:CC_SWP CC_REGNUM)
6680         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6681                          [(match_operand:SI 1 "s_register_operand" "r")
6682                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
6683                         (match_operand:SI 0 "s_register_operand" "r")))]
6684   "TARGET_ARM"
6685   "cmp%?\\t%0, %1%S3"
6686   [(set_attr "conds" "set")
6687    (set_attr "shift" "1")
6688    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6689                       (const_string "alu_shift")
6690                       (const_string "alu_shift_reg")))]
6693 (define_insn "*cmpsi_neg_shiftsi"
6694   [(set (reg:CC CC_REGNUM)
6695         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6696                     (neg:SI (match_operator:SI 3 "shift_operator"
6697                              [(match_operand:SI 1 "s_register_operand" "r")
6698                               (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
6699   "TARGET_ARM"
6700   "cmn%?\\t%0, %1%S3"
6701   [(set_attr "conds" "set")
6702    (set_attr "shift" "1")
6703    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6704                       (const_string "alu_shift")
6705                       (const_string "alu_shift_reg")))]
6708 ;; Cirrus SF compare instruction
6709 (define_insn "*cirrus_cmpsf"
6710   [(set (reg:CCFP CC_REGNUM)
6711         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6712                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
6713   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6714   "cfcmps%?\\tr15, %V0, %V1"
6715   [(set_attr "type"   "mav_farith")
6716    (set_attr "cirrus" "compare")]
6719 ;; Cirrus DF compare instruction
6720 (define_insn "*cirrus_cmpdf"
6721   [(set (reg:CCFP CC_REGNUM)
6722         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6723                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
6724   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6725   "cfcmpd%?\\tr15, %V0, %V1"
6726   [(set_attr "type"   "mav_farith")
6727    (set_attr "cirrus" "compare")]
6730 ;; Cirrus DI compare instruction
6731 (define_expand "cmpdi"
6732   [(match_operand:DI 0 "cirrus_fp_register" "")
6733    (match_operand:DI 1 "cirrus_fp_register" "")]
6734   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6735   "{
6736      arm_compare_op0 = operands[0];
6737      arm_compare_op1 = operands[1];
6738      DONE;
6739    }")
6741 (define_insn "*cirrus_cmpdi"
6742   [(set (reg:CC CC_REGNUM)
6743         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6744                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
6745   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6746   "cfcmp64%?\\tr15, %V0, %V1"
6747   [(set_attr "type"   "mav_farith")
6748    (set_attr "cirrus" "compare")]
6751 ; This insn allows redundant compares to be removed by cse, nothing should
6752 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6753 ; is deleted later on. The match_dup will match the mode here, so that
6754 ; mode changes of the condition codes aren't lost by this even though we don't
6755 ; specify what they are.
6757 (define_insn "*deleted_compare"
6758   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6759   "TARGET_ARM"
6760   "\\t%@ deleted compare"
6761   [(set_attr "conds" "set")
6762    (set_attr "length" "0")]
6766 ;; Conditional branch insns
6768 (define_expand "beq"
6769   [(set (pc)
6770         (if_then_else (eq (match_dup 1) (const_int 0))
6771                       (label_ref (match_operand 0 "" ""))
6772                       (pc)))]
6773   "TARGET_ARM"
6774   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6777 (define_expand "bne"
6778   [(set (pc)
6779         (if_then_else (ne (match_dup 1) (const_int 0))
6780                       (label_ref (match_operand 0 "" ""))
6781                       (pc)))]
6782   "TARGET_ARM"
6783   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6786 (define_expand "bgt"
6787   [(set (pc)
6788         (if_then_else (gt (match_dup 1) (const_int 0))
6789                       (label_ref (match_operand 0 "" ""))
6790                       (pc)))]
6791   "TARGET_ARM"
6792   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6795 (define_expand "ble"
6796   [(set (pc)
6797         (if_then_else (le (match_dup 1) (const_int 0))
6798                       (label_ref (match_operand 0 "" ""))
6799                       (pc)))]
6800   "TARGET_ARM"
6801   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6804 (define_expand "bge"
6805   [(set (pc)
6806         (if_then_else (ge (match_dup 1) (const_int 0))
6807                       (label_ref (match_operand 0 "" ""))
6808                       (pc)))]
6809   "TARGET_ARM"
6810   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6813 (define_expand "blt"
6814   [(set (pc)
6815         (if_then_else (lt (match_dup 1) (const_int 0))
6816                       (label_ref (match_operand 0 "" ""))
6817                       (pc)))]
6818   "TARGET_ARM"
6819   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6822 (define_expand "bgtu"
6823   [(set (pc)
6824         (if_then_else (gtu (match_dup 1) (const_int 0))
6825                       (label_ref (match_operand 0 "" ""))
6826                       (pc)))]
6827   "TARGET_ARM"
6828   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6831 (define_expand "bleu"
6832   [(set (pc)
6833         (if_then_else (leu (match_dup 1) (const_int 0))
6834                       (label_ref (match_operand 0 "" ""))
6835                       (pc)))]
6836   "TARGET_ARM"
6837   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6840 (define_expand "bgeu"
6841   [(set (pc)
6842         (if_then_else (geu (match_dup 1) (const_int 0))
6843                       (label_ref (match_operand 0 "" ""))
6844                       (pc)))]
6845   "TARGET_ARM"
6846   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6849 (define_expand "bltu"
6850   [(set (pc)
6851         (if_then_else (ltu (match_dup 1) (const_int 0))
6852                       (label_ref (match_operand 0 "" ""))
6853                       (pc)))]
6854   "TARGET_ARM"
6855   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6858 (define_expand "bunordered"
6859   [(set (pc)
6860         (if_then_else (unordered (match_dup 1) (const_int 0))
6861                       (label_ref (match_operand 0 "" ""))
6862                       (pc)))]
6863   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6864   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6865                                       arm_compare_op1);"
6868 (define_expand "bordered"
6869   [(set (pc)
6870         (if_then_else (ordered (match_dup 1) (const_int 0))
6871                       (label_ref (match_operand 0 "" ""))
6872                       (pc)))]
6873   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6874   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6875                                       arm_compare_op1);"
6878 (define_expand "bungt"
6879   [(set (pc)
6880         (if_then_else (ungt (match_dup 1) (const_int 0))
6881                       (label_ref (match_operand 0 "" ""))
6882                       (pc)))]
6883   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6884   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
6887 (define_expand "bunlt"
6888   [(set (pc)
6889         (if_then_else (unlt (match_dup 1) (const_int 0))
6890                       (label_ref (match_operand 0 "" ""))
6891                       (pc)))]
6892   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6893   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
6896 (define_expand "bunge"
6897   [(set (pc)
6898         (if_then_else (unge (match_dup 1) (const_int 0))
6899                       (label_ref (match_operand 0 "" ""))
6900                       (pc)))]
6901   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6902   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
6905 (define_expand "bunle"
6906   [(set (pc)
6907         (if_then_else (unle (match_dup 1) (const_int 0))
6908                       (label_ref (match_operand 0 "" ""))
6909                       (pc)))]
6910   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6911   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
6914 ;; The following two patterns need two branch instructions, since there is
6915 ;; no single instruction that will handle all cases.
6916 (define_expand "buneq"
6917   [(set (pc)
6918         (if_then_else (uneq (match_dup 1) (const_int 0))
6919                       (label_ref (match_operand 0 "" ""))
6920                       (pc)))]
6921   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6922   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6925 (define_expand "bltgt"
6926   [(set (pc)
6927         (if_then_else (ltgt (match_dup 1) (const_int 0))
6928                       (label_ref (match_operand 0 "" ""))
6929                       (pc)))]
6930   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6931   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6935 ;; Patterns to match conditional branch insns.
6938 ; Special pattern to match UNEQ.
6939 (define_insn "*arm_buneq"
6940   [(set (pc)
6941         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6942                       (label_ref (match_operand 0 "" ""))
6943                       (pc)))]
6944   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6945   "*
6946   if (arm_ccfsm_state != 0)
6947     abort ();
6949   return \"bvs\\t%l0\;beq\\t%l0\";
6950   "
6951   [(set_attr "conds" "jump_clob")
6952    (set_attr "length" "8")]
6955 ; Special pattern to match LTGT.
6956 (define_insn "*arm_bltgt"
6957   [(set (pc)
6958         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6959                       (label_ref (match_operand 0 "" ""))
6960                       (pc)))]
6961   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6962   "*
6963   if (arm_ccfsm_state != 0)
6964     abort ();
6966   return \"bmi\\t%l0\;bgt\\t%l0\";
6967   "
6968   [(set_attr "conds" "jump_clob")
6969    (set_attr "length" "8")]
6972 (define_insn "*arm_cond_branch"
6973   [(set (pc)
6974         (if_then_else (match_operator 1 "arm_comparison_operator"
6975                        [(match_operand 2 "cc_register" "") (const_int 0)])
6976                       (label_ref (match_operand 0 "" ""))
6977                       (pc)))]
6978   "TARGET_ARM"
6979   "*
6980   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6981     {
6982       arm_ccfsm_state += 2;
6983       return \"\";
6984     }
6985   return \"b%d1\\t%l0\";
6986   "
6987   [(set_attr "conds" "use")
6988    (set_attr "type" "branch")]
6991 ; Special pattern to match reversed UNEQ.
6992 (define_insn "*arm_buneq_reversed"
6993   [(set (pc)
6994         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6995                       (pc)
6996                       (label_ref (match_operand 0 "" ""))))]
6997   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6998   "*
6999   if (arm_ccfsm_state != 0)
7000     abort ();
7002   return \"bmi\\t%l0\;bgt\\t%l0\";
7003   "
7004   [(set_attr "conds" "jump_clob")
7005    (set_attr "length" "8")]
7008 ; Special pattern to match reversed LTGT.
7009 (define_insn "*arm_bltgt_reversed"
7010   [(set (pc)
7011         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7012                       (pc)
7013                       (label_ref (match_operand 0 "" ""))))]
7014   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7015   "*
7016   if (arm_ccfsm_state != 0)
7017     abort ();
7019   return \"bvs\\t%l0\;beq\\t%l0\";
7020   "
7021   [(set_attr "conds" "jump_clob")
7022    (set_attr "length" "8")]
7025 (define_insn "*arm_cond_branch_reversed"
7026   [(set (pc)
7027         (if_then_else (match_operator 1 "arm_comparison_operator"
7028                        [(match_operand 2 "cc_register" "") (const_int 0)])
7029                       (pc)
7030                       (label_ref (match_operand 0 "" ""))))]
7031   "TARGET_ARM"
7032   "*
7033   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7034     {
7035       arm_ccfsm_state += 2;
7036       return \"\";
7037     }
7038   return \"b%D1\\t%l0\";
7039   "
7040   [(set_attr "conds" "use")
7041    (set_attr "type" "branch")]
7046 ; scc insns
7048 (define_expand "seq"
7049   [(set (match_operand:SI 0 "s_register_operand" "")
7050         (eq:SI (match_dup 1) (const_int 0)))]
7051   "TARGET_ARM"
7052   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7055 (define_expand "sne"
7056   [(set (match_operand:SI 0 "s_register_operand" "")
7057         (ne:SI (match_dup 1) (const_int 0)))]
7058   "TARGET_ARM"
7059   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7062 (define_expand "sgt"
7063   [(set (match_operand:SI 0 "s_register_operand" "")
7064         (gt:SI (match_dup 1) (const_int 0)))]
7065   "TARGET_ARM"
7066   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7069 (define_expand "sle"
7070   [(set (match_operand:SI 0 "s_register_operand" "")
7071         (le:SI (match_dup 1) (const_int 0)))]
7072   "TARGET_ARM"
7073   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7076 (define_expand "sge"
7077   [(set (match_operand:SI 0 "s_register_operand" "")
7078         (ge:SI (match_dup 1) (const_int 0)))]
7079   "TARGET_ARM"
7080   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7083 (define_expand "slt"
7084   [(set (match_operand:SI 0 "s_register_operand" "")
7085         (lt:SI (match_dup 1) (const_int 0)))]
7086   "TARGET_ARM"
7087   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7090 (define_expand "sgtu"
7091   [(set (match_operand:SI 0 "s_register_operand" "")
7092         (gtu:SI (match_dup 1) (const_int 0)))]
7093   "TARGET_ARM"
7094   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7097 (define_expand "sleu"
7098   [(set (match_operand:SI 0 "s_register_operand" "")
7099         (leu:SI (match_dup 1) (const_int 0)))]
7100   "TARGET_ARM"
7101   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7104 (define_expand "sgeu"
7105   [(set (match_operand:SI 0 "s_register_operand" "")
7106         (geu:SI (match_dup 1) (const_int 0)))]
7107   "TARGET_ARM"
7108   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7111 (define_expand "sltu"
7112   [(set (match_operand:SI 0 "s_register_operand" "")
7113         (ltu:SI (match_dup 1) (const_int 0)))]
7114   "TARGET_ARM"
7115   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7118 (define_expand "sunordered"
7119   [(set (match_operand:SI 0 "s_register_operand" "")
7120         (unordered:SI (match_dup 1) (const_int 0)))]
7121   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7122   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7123                                       arm_compare_op1);"
7126 (define_expand "sordered"
7127   [(set (match_operand:SI 0 "s_register_operand" "")
7128         (ordered:SI (match_dup 1) (const_int 0)))]
7129   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7130   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7131                                       arm_compare_op1);"
7134 (define_expand "sungt"
7135   [(set (match_operand:SI 0 "s_register_operand" "")
7136         (ungt:SI (match_dup 1) (const_int 0)))]
7137   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7138   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7139                                       arm_compare_op1);"
7142 (define_expand "sunge"
7143   [(set (match_operand:SI 0 "s_register_operand" "")
7144         (unge:SI (match_dup 1) (const_int 0)))]
7145   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7146   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7147                                       arm_compare_op1);"
7150 (define_expand "sunlt"
7151   [(set (match_operand:SI 0 "s_register_operand" "")
7152         (unlt:SI (match_dup 1) (const_int 0)))]
7153   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7154   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7155                                       arm_compare_op1);"
7158 (define_expand "sunle"
7159   [(set (match_operand:SI 0 "s_register_operand" "")
7160         (unle:SI (match_dup 1) (const_int 0)))]
7161   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7162   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7163                                       arm_compare_op1);"
7166 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7167 ;;; simple ARM instructions. 
7169 ; (define_expand "suneq"
7170 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7171 ;       (uneq:SI (match_dup 1) (const_int 0)))]
7172 ;   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7173 ;   "abort ();"
7174 ; )
7176 ; (define_expand "sltgt"
7177 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7178 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
7179 ;   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7180 ;   "abort ();"
7181 ; )
7183 (define_insn "*mov_scc"
7184   [(set (match_operand:SI 0 "s_register_operand" "=r")
7185         (match_operator:SI 1 "arm_comparison_operator"
7186          [(match_operand 2 "cc_register" "") (const_int 0)]))]
7187   "TARGET_ARM"
7188   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7189   [(set_attr "conds" "use")
7190    (set_attr "length" "8")]
7193 (define_insn "*mov_negscc"
7194   [(set (match_operand:SI 0 "s_register_operand" "=r")
7195         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7196                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7197   "TARGET_ARM"
7198   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7199   [(set_attr "conds" "use")
7200    (set_attr "length" "8")]
7203 (define_insn "*mov_notscc"
7204   [(set (match_operand:SI 0 "s_register_operand" "=r")
7205         (not:SI (match_operator:SI 1 "arm_comparison_operator"
7206                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7207   "TARGET_ARM"
7208   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7209   [(set_attr "conds" "use")
7210    (set_attr "length" "8")]
7214 ;; Conditional move insns
7216 (define_expand "movsicc"
7217   [(set (match_operand:SI 0 "s_register_operand" "")
7218         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7219                          (match_operand:SI 2 "arm_not_operand" "")
7220                          (match_operand:SI 3 "arm_not_operand" "")))]
7221   "TARGET_ARM"
7222   "
7223   {
7224     enum rtx_code code = GET_CODE (operands[1]);
7225     rtx ccreg;
7227     if (code == UNEQ || code == LTGT)
7228       FAIL;
7230     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7231     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7232   }"
7235 (define_expand "movsfcc"
7236   [(set (match_operand:SF 0 "s_register_operand" "")
7237         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7238                          (match_operand:SF 2 "s_register_operand" "")
7239                          (match_operand:SF 3 "nonmemory_operand" "")))]
7240   "TARGET_ARM"
7241   "
7242   {
7243     enum rtx_code code = GET_CODE (operands[1]);
7244     rtx ccreg;
7246     if (code == UNEQ || code == LTGT)
7247       FAIL;
7249     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
7250        Otherwise, ensure it is a valid FP add operand */
7251     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7252         || (!arm_float_add_operand (operands[3], SFmode)))
7253       operands[3] = force_reg (SFmode, operands[3]);
7255     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7256     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7257   }"
7260 (define_expand "movdfcc"
7261   [(set (match_operand:DF 0 "s_register_operand" "")
7262         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7263                          (match_operand:DF 2 "s_register_operand" "")
7264                          (match_operand:DF 3 "arm_float_add_operand" "")))]
7265   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7266   "
7267   {
7268     enum rtx_code code = GET_CODE (operands[1]);
7269     rtx ccreg;
7271     if (code == UNEQ || code == LTGT)
7272       FAIL;
7274     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7275     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7276   }"
7279 (define_insn "*movsicc_insn"
7280   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7281         (if_then_else:SI
7282          (match_operator 3 "arm_comparison_operator"
7283           [(match_operand 4 "cc_register" "") (const_int 0)])
7284          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7285          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7286   "TARGET_ARM"
7287   "@
7288    mov%D3\\t%0, %2
7289    mvn%D3\\t%0, #%B2
7290    mov%d3\\t%0, %1
7291    mvn%d3\\t%0, #%B1
7292    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7293    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7294    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7295    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7296   [(set_attr "length" "4,4,4,4,8,8,8,8")
7297    (set_attr "conds" "use")]
7300 (define_insn "*movsfcc_soft_insn"
7301   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7302         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7303                           [(match_operand 4 "cc_register" "") (const_int 0)])
7304                          (match_operand:SF 1 "s_register_operand" "0,r")
7305                          (match_operand:SF 2 "s_register_operand" "r,0")))]
7306   "TARGET_ARM && TARGET_SOFT_FLOAT"
7307   "@
7308    mov%D3\\t%0, %2
7309    mov%d3\\t%0, %1"
7310   [(set_attr "conds" "use")]
7314 ;; Jump and linkage insns
7316 (define_expand "jump"
7317   [(set (pc)
7318         (label_ref (match_operand 0 "" "")))]
7319   "TARGET_EITHER"
7320   ""
7323 (define_insn "*arm_jump"
7324   [(set (pc)
7325         (label_ref (match_operand 0 "" "")))]
7326   "TARGET_ARM"
7327   "*
7328   {
7329     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7330       {
7331         arm_ccfsm_state += 2;
7332         return \"\";
7333       }
7334     return \"b%?\\t%l0\";
7335   }
7336   "
7337   [(set_attr "predicable" "yes")]
7340 (define_insn "*thumb_jump"
7341   [(set (pc)
7342         (label_ref (match_operand 0 "" "")))]
7343   "TARGET_THUMB"
7344   "*
7345   if (get_attr_length (insn) == 2)
7346     return \"b\\t%l0\";
7347   return \"bl\\t%l0\\t%@ far jump\";
7348   "
7349   [(set (attr "far_jump")
7350         (if_then_else
7351             (eq_attr "length" "4")
7352             (const_string "yes")
7353             (const_string "no")))
7354    (set (attr "length") 
7355         (if_then_else
7356             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7357                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
7358             (const_int 2)
7359             (const_int 4)))]
7362 (define_expand "call"
7363   [(parallel [(call (match_operand 0 "memory_operand" "")
7364                     (match_operand 1 "general_operand" ""))
7365               (use (match_operand 2 "" ""))
7366               (clobber (reg:SI LR_REGNUM))])]
7367   "TARGET_EITHER"
7368   "
7369   {
7370     rtx callee;
7371     
7372     /* In an untyped call, we can get NULL for operand 2.  */
7373     if (operands[2] == NULL_RTX)
7374       operands[2] = const0_rtx;
7375       
7376     /* This is to decide if we should generate indirect calls by loading the
7377        32 bit address of the callee into a register before performing the
7378        branch and link.  operand[2] encodes the long_call/short_call
7379        attribute of the function being called.  This attribute is set whenever
7380        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7381        is used, and the short_call attribute can also be set if function is
7382        declared as static or if it has already been defined in the current
7383        compilation unit.  See arm.c and arm.h for info about this.  The third
7384        parameter to arm_is_longcall_p is used to tell it which pattern
7385        invoked it.  */
7386     callee  = XEXP (operands[0], 0);
7387     
7388     if (GET_CODE (callee) != REG
7389        && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7390       XEXP (operands[0], 0) = force_reg (Pmode, callee);
7391   }"
7394 (define_insn "*call_reg"
7395   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7396          (match_operand 1 "" ""))
7397    (use (match_operand 2 "" ""))
7398    (clobber (reg:SI LR_REGNUM))]
7399   "TARGET_ARM"
7400   "*
7401   return output_call (operands);
7402   "
7403   ;; length is worst case, normally it is only two
7404   [(set_attr "length" "12")
7405    (set_attr "type" "call")]
7408 (define_insn "*call_mem"
7409   [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7410          (match_operand 1 "" ""))
7411    (use (match_operand 2 "" ""))
7412    (clobber (reg:SI LR_REGNUM))]
7413   "TARGET_ARM"
7414   "*
7415   return output_call_mem (operands);
7416   "
7417   [(set_attr "length" "12")
7418    (set_attr "type" "call")]
7421 (define_insn "*call_indirect"
7422   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7423          (match_operand 1 "" ""))
7424    (use (match_operand 2 "" ""))
7425    (clobber (reg:SI LR_REGNUM))]
7426   "TARGET_THUMB"
7427   "*
7428   {
7429     if (TARGET_CALLER_INTERWORKING)
7430       return \"bl\\t%__interwork_call_via_%0\";
7431     else
7432       return \"bl\\t%__call_via_%0\";
7433   }"
7434   [(set_attr "type" "call")]
7437 (define_insn "*call_value_indirect"
7438   [(set (match_operand 0 "" "")
7439         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7440               (match_operand 2 "" "")))
7441    (use (match_operand 3 "" ""))
7442    (clobber (reg:SI LR_REGNUM))]
7443   "TARGET_THUMB"
7444   "*
7445   {
7446     if (TARGET_CALLER_INTERWORKING)
7447       return \"bl\\t%__interwork_call_via_%1\";
7448     else
7449       return \"bl\\t%__call_via_%1\";
7450   }"
7451   [(set_attr "type" "call")]
7454 (define_expand "call_value"
7455   [(parallel [(set (match_operand       0 "" "")
7456                    (call (match_operand 1 "memory_operand" "")
7457                          (match_operand 2 "general_operand" "")))
7458               (use (match_operand 3 "" ""))
7459               (clobber (reg:SI LR_REGNUM))])]
7460   "TARGET_EITHER"
7461   "
7462   {
7463     rtx callee = XEXP (operands[1], 0);
7464     
7465     /* In an untyped call, we can get NULL for operand 2.  */
7466     if (operands[3] == 0)
7467       operands[3] = const0_rtx;
7468       
7469     /* See the comment in define_expand \"call\".  */
7470     if (GET_CODE (callee) != REG
7471         && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7472       XEXP (operands[1], 0) = force_reg (Pmode, callee);
7473   }"
7476 (define_insn "*call_value_reg"
7477   [(set (match_operand 0 "" "")
7478         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7479               (match_operand 2 "" "")))
7480    (use (match_operand 3 "" ""))
7481    (clobber (reg:SI LR_REGNUM))]
7482   "TARGET_ARM"
7483   "*
7484   return output_call (&operands[1]);
7485   "
7486   [(set_attr "length" "12")
7487    (set_attr "type" "call")]
7490 (define_insn "*call_value_mem"
7491   [(set (match_operand 0 "" "")
7492         (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7493               (match_operand 2 "" "")))
7494    (use (match_operand 3 "" ""))
7495    (clobber (reg:SI LR_REGNUM))]
7496   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7497   "*
7498   return output_call_mem (&operands[1]);
7499   "
7500   [(set_attr "length" "12")
7501    (set_attr "type" "call")]
7504 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7505 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7507 (define_insn "*call_symbol"
7508   [(call (mem:SI (match_operand:SI 0 "" ""))
7509          (match_operand 1 "" ""))
7510    (use (match_operand 2 "" ""))
7511    (clobber (reg:SI LR_REGNUM))]
7512   "TARGET_ARM
7513    && (GET_CODE (operands[0]) == SYMBOL_REF)
7514    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7515   "*
7516   {
7517     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7518   }"
7519   [(set_attr "type" "call")]
7522 (define_insn "*call_value_symbol"
7523   [(set (match_operand 0 "s_register_operand" "")
7524         (call (mem:SI (match_operand:SI 1 "" ""))
7525         (match_operand:SI 2 "" "")))
7526    (use (match_operand 3 "" ""))
7527    (clobber (reg:SI LR_REGNUM))]
7528   "TARGET_ARM
7529    && (GET_CODE (operands[1]) == SYMBOL_REF)
7530    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7531   "*
7532   {
7533     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7534   }"
7535   [(set_attr "type" "call")]
7538 (define_insn "*call_insn"
7539   [(call (mem:SI (match_operand:SI 0 "" ""))
7540          (match_operand:SI 1 "" ""))
7541    (use (match_operand 2 "" ""))
7542    (clobber (reg:SI LR_REGNUM))]
7543   "TARGET_THUMB
7544    && GET_CODE (operands[0]) == SYMBOL_REF
7545    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7546   "bl\\t%a0"
7547   [(set_attr "length" "4")
7548    (set_attr "type" "call")]
7551 (define_insn "*call_value_insn"
7552   [(set (match_operand 0 "register_operand" "")
7553         (call (mem:SI (match_operand 1 "" ""))
7554               (match_operand 2 "" "")))
7555    (use (match_operand 3 "" ""))
7556    (clobber (reg:SI LR_REGNUM))]
7557   "TARGET_THUMB
7558    && GET_CODE (operands[1]) == SYMBOL_REF
7559    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7560   "bl\\t%a1"
7561   [(set_attr "length" "4")
7562    (set_attr "type" "call")]
7565 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7566 (define_expand "sibcall"
7567   [(parallel [(call (match_operand 0 "memory_operand" "")
7568                     (match_operand 1 "general_operand" ""))
7569               (return)
7570               (use (match_operand 2 "" ""))])]
7571   "TARGET_ARM"
7572   "
7573   {
7574     if (operands[2] == NULL_RTX)
7575       operands[2] = const0_rtx;
7576   }"
7579 (define_expand "sibcall_value"
7580   [(parallel [(set (match_operand 0 "register_operand" "")
7581                    (call (match_operand 1 "memory_operand" "")
7582                          (match_operand 2 "general_operand" "")))
7583               (return)
7584               (use (match_operand 3 "" ""))])]
7585   "TARGET_ARM"
7586   "
7587   {
7588     if (operands[3] == NULL_RTX)
7589       operands[3] = const0_rtx;
7590   }"
7593 (define_insn "*sibcall_insn"
7594  [(call (mem:SI (match_operand:SI 0 "" "X"))
7595         (match_operand 1 "" ""))
7596   (return)
7597   (use (match_operand 2 "" ""))]
7598   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7599   "*
7600   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7601   "
7602   [(set_attr "type" "call")]
7605 (define_insn "*sibcall_value_insn"
7606  [(set (match_operand 0 "s_register_operand" "")
7607        (call (mem:SI (match_operand:SI 1 "" "X"))
7608              (match_operand 2 "" "")))
7609   (return)
7610   (use (match_operand 3 "" ""))]
7611   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7612   "*
7613   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7614   "
7615   [(set_attr "type" "call")]
7618 ;; Often the return insn will be the same as loading from memory, so set attr
7619 (define_insn "return"
7620   [(return)]
7621   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7622   "*
7623   {
7624     if (arm_ccfsm_state == 2)
7625       {
7626         arm_ccfsm_state += 2;
7627         return \"\";
7628       }
7629     return output_return_instruction (const_true_rtx, TRUE, FALSE);
7630   }"
7631   [(set_attr "type" "load1")
7632    (set_attr "length" "12")
7633    (set_attr "predicable" "yes")]
7636 (define_insn "*cond_return"
7637   [(set (pc)
7638         (if_then_else (match_operator 0 "arm_comparison_operator"
7639                        [(match_operand 1 "cc_register" "") (const_int 0)])
7640                       (return)
7641                       (pc)))]
7642   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7643   "*
7644   {
7645     if (arm_ccfsm_state == 2)
7646       {
7647         arm_ccfsm_state += 2;
7648         return \"\";
7649       }
7650     return output_return_instruction (operands[0], TRUE, FALSE);
7651   }"
7652   [(set_attr "conds" "use")
7653    (set_attr "length" "12")
7654    (set_attr "type" "load1")]
7657 (define_insn "*cond_return_inverted"
7658   [(set (pc)
7659         (if_then_else (match_operator 0 "arm_comparison_operator"
7660                        [(match_operand 1 "cc_register" "") (const_int 0)])
7661                       (pc)
7662                       (return)))]
7663   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7664   "*
7665   {
7666     if (arm_ccfsm_state == 2)
7667       {
7668         arm_ccfsm_state += 2;
7669         return \"\";
7670       }
7671     return output_return_instruction (operands[0], TRUE, TRUE);
7672   }"
7673   [(set_attr "conds" "use")
7674    (set_attr "type" "load1")]
7677 ;; Generate a sequence of instructions to determine if the processor is
7678 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7679 ;; mask.
7681 (define_expand "return_addr_mask"
7682   [(set (match_dup 1)
7683       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7684                        (const_int 0)))
7685    (set (match_operand:SI 0 "s_register_operand" "")
7686       (if_then_else:SI (eq (match_dup 1) (const_int 0))
7687                        (const_int -1)
7688                        (const_int 67108860)))] ; 0x03fffffc
7689   "TARGET_ARM"
7690   "
7691   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7692   ")
7694 (define_insn "*check_arch2"
7695   [(set (match_operand:CC_NOOV 0 "cc_register" "")
7696       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7697                        (const_int 0)))]
7698   "TARGET_ARM"
7699   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7700   [(set_attr "length" "8")
7701    (set_attr "conds" "set")]
7704 ;; Call subroutine returning any type.
7706 (define_expand "untyped_call"
7707   [(parallel [(call (match_operand 0 "" "")
7708                     (const_int 0))
7709               (match_operand 1 "" "")
7710               (match_operand 2 "" "")])]
7711   "TARGET_ARM"
7712   "
7713   {
7714     int i;
7716     emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
7718     for (i = 0; i < XVECLEN (operands[2], 0); i++)
7719       {
7720         rtx set = XVECEXP (operands[2], 0, i);
7722         emit_move_insn (SET_DEST (set), SET_SRC (set));
7723       }
7725     /* The optimizer does not know that the call sets the function value
7726        registers we stored in the result block.  We avoid problems by
7727        claiming that all hard registers are used and clobbered at this
7728        point.  */
7729     emit_insn (gen_blockage ());
7731     DONE;
7732   }"
7735 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7736 ;; all of memory.  This blocks insns from being moved across this point.
7738 (define_insn "blockage"
7739   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
7740   "TARGET_EITHER"
7741   ""
7742   [(set_attr "length" "0")
7743    (set_attr "type" "block")]
7746 (define_expand "casesi"
7747   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
7748    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
7749    (match_operand:SI 2 "const_int_operand" "")  ; total range
7750    (match_operand:SI 3 "" "")                   ; table label
7751    (match_operand:SI 4 "" "")]                  ; Out of range label
7752   "TARGET_ARM"
7753   "
7754   {
7755     rtx reg;
7756     if (operands[1] != const0_rtx)
7757       {
7758         reg = gen_reg_rtx (SImode);
7760         emit_insn (gen_addsi3 (reg, operands[0],
7761                                GEN_INT (-INTVAL (operands[1]))));
7762         operands[0] = reg;
7763       }
7765     if (!const_ok_for_arm (INTVAL (operands[2])))
7766       operands[2] = force_reg (SImode, operands[2]);
7768     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
7769                                          operands[4]));
7770     DONE;
7771   }"
7774 ;; The USE in this pattern is needed to tell flow analysis that this is
7775 ;; a CASESI insn.  It has no other purpose.
7776 (define_insn "casesi_internal"
7777   [(parallel [(set (pc)
7778                (if_then_else
7779                 (leu (match_operand:SI 0 "s_register_operand" "r")
7780                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
7781                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
7782                                  (label_ref (match_operand 2 "" ""))))
7783                 (label_ref (match_operand 3 "" ""))))
7784               (clobber (reg:CC CC_REGNUM))
7785               (use (label_ref (match_dup 2)))])]
7786   "TARGET_ARM"
7787   "*
7788     if (flag_pic)
7789       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
7790     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
7791   "
7792   [(set_attr "conds" "clob")
7793    (set_attr "length" "12")]
7796 (define_expand "indirect_jump"
7797   [(set (pc)
7798         (match_operand:SI 0 "s_register_operand" ""))]
7799   "TARGET_EITHER"
7800   ""
7803 (define_insn "*arm_indirect_jump"
7804   [(set (pc)
7805         (match_operand:SI 0 "s_register_operand" "r"))]
7806   "TARGET_ARM"
7807   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
7808   [(set_attr "predicable" "yes")]
7811 ;; Although not supported by the define_expand above,
7812 ;; cse/combine may generate this form.
7813 (define_insn "*load_indirect_jump"
7814   [(set (pc)
7815         (match_operand:SI 0 "memory_operand" "m"))]
7816   "TARGET_ARM"
7817   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
7818   [(set_attr "type" "load1")
7819    (set_attr "pool_range" "4096")
7820    (set_attr "neg_pool_range" "4084")
7821    (set_attr "predicable" "yes")]
7824 (define_insn "*thumb_indirect_jump"
7825   [(set (pc)
7826         (match_operand:SI 0 "register_operand" "l*r"))]
7827   "TARGET_THUMB"
7828   "mov\\tpc, %0"
7829   [(set_attr "conds" "clob")
7830    (set_attr "length" "2")]
7834 ;; Misc insns
7836 (define_insn "nop"
7837   [(const_int 0)]
7838   "TARGET_EITHER"
7839   "*
7840   if (TARGET_ARM)
7841     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
7842   return  \"mov\\tr8, r8\";
7843   "
7844   [(set (attr "length")
7845         (if_then_else (eq_attr "is_thumb" "yes")
7846                       (const_int 2)
7847                       (const_int 4)))]
7851 ;; Patterns to allow combination of arithmetic, cond code and shifts
7853 (define_insn "*arith_shiftsi"
7854   [(set (match_operand:SI 0 "s_register_operand" "=r")
7855         (match_operator:SI 1 "shiftable_operator"
7856           [(match_operator:SI 3 "shift_operator"
7857              [(match_operand:SI 4 "s_register_operand" "r")
7858               (match_operand:SI 5 "reg_or_int_operand" "rI")])
7859            (match_operand:SI 2 "s_register_operand" "r")]))]
7860   "TARGET_ARM"
7861   "%i1%?\\t%0, %2, %4%S3"
7862   [(set_attr "predicable" "yes")
7863    (set_attr "shift" "4")
7864    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7865                       (const_string "alu_shift")
7866                       (const_string "alu_shift_reg")))]
7869 (define_split
7870   [(set (match_operand:SI 0 "s_register_operand" "")
7871         (match_operator:SI 1 "shiftable_operator"
7872          [(match_operator:SI 2 "shiftable_operator"
7873            [(match_operator:SI 3 "shift_operator"
7874              [(match_operand:SI 4 "s_register_operand" "")
7875               (match_operand:SI 5 "reg_or_int_operand" "")])
7876             (match_operand:SI 6 "s_register_operand" "")])
7877           (match_operand:SI 7 "arm_rhs_operand" "")]))
7878    (clobber (match_operand:SI 8 "s_register_operand" ""))]
7879   "TARGET_ARM"
7880   [(set (match_dup 8)
7881         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7882                          (match_dup 6)]))
7883    (set (match_dup 0)
7884         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
7885   "")
7887 (define_insn "*arith_shiftsi_compare0"
7888   [(set (reg:CC_NOOV CC_REGNUM)
7889         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7890                           [(match_operator:SI 3 "shift_operator"
7891                             [(match_operand:SI 4 "s_register_operand" "r")
7892                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
7893                            (match_operand:SI 2 "s_register_operand" "r")])
7894                          (const_int 0)))
7895    (set (match_operand:SI 0 "s_register_operand" "=r")
7896         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7897                          (match_dup 2)]))]
7898   "TARGET_ARM"
7899   "%i1%?s\\t%0, %2, %4%S3"
7900   [(set_attr "conds" "set")
7901    (set_attr "shift" "4")
7902    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7903                       (const_string "alu_shift")
7904                       (const_string "alu_shift_reg")))]
7907 (define_insn "*arith_shiftsi_compare0_scratch"
7908   [(set (reg:CC_NOOV CC_REGNUM)
7909         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7910                           [(match_operator:SI 3 "shift_operator"
7911                             [(match_operand:SI 4 "s_register_operand" "r")
7912                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
7913                            (match_operand:SI 2 "s_register_operand" "r")])
7914                          (const_int 0)))
7915    (clobber (match_scratch:SI 0 "=r"))]
7916   "TARGET_ARM"
7917   "%i1%?s\\t%0, %2, %4%S3"
7918   [(set_attr "conds" "set")
7919    (set_attr "shift" "4")
7920    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7921                       (const_string "alu_shift")
7922                       (const_string "alu_shift_reg")))]
7925 (define_insn "*sub_shiftsi"
7926   [(set (match_operand:SI 0 "s_register_operand" "=r")
7927         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7928                   (match_operator:SI 2 "shift_operator"
7929                    [(match_operand:SI 3 "s_register_operand" "r")
7930                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
7931   "TARGET_ARM"
7932   "sub%?\\t%0, %1, %3%S2"
7933   [(set_attr "predicable" "yes")
7934    (set_attr "shift" "3")
7935    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7936                       (const_string "alu_shift")
7937                       (const_string "alu_shift_reg")))]
7940 (define_insn "*sub_shiftsi_compare0"
7941   [(set (reg:CC_NOOV CC_REGNUM)
7942         (compare:CC_NOOV
7943          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7944                    (match_operator:SI 2 "shift_operator"
7945                     [(match_operand:SI 3 "s_register_operand" "r")
7946                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7947          (const_int 0)))
7948    (set (match_operand:SI 0 "s_register_operand" "=r")
7949         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7950                                                  (match_dup 4)])))]
7951   "TARGET_ARM"
7952   "sub%?s\\t%0, %1, %3%S2"
7953   [(set_attr "conds" "set")
7954    (set_attr "shift" "3")
7955    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7956                       (const_string "alu_shift")
7957                       (const_string "alu_shift_reg")))]
7960 (define_insn "*sub_shiftsi_compare0_scratch"
7961   [(set (reg:CC_NOOV CC_REGNUM)
7962         (compare:CC_NOOV
7963          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7964                    (match_operator:SI 2 "shift_operator"
7965                     [(match_operand:SI 3 "s_register_operand" "r")
7966                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7967          (const_int 0)))
7968    (clobber (match_scratch:SI 0 "=r"))]
7969   "TARGET_ARM"
7970   "sub%?s\\t%0, %1, %3%S2"
7971   [(set_attr "conds" "set")
7972    (set_attr "shift" "3")
7973    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7974                       (const_string "alu_shift")
7975                       (const_string "alu_shift_reg")))]
7980 (define_insn "*and_scc"
7981   [(set (match_operand:SI 0 "s_register_operand" "=r")
7982         (and:SI (match_operator:SI 1 "arm_comparison_operator"
7983                  [(match_operand 3 "cc_register" "") (const_int 0)])
7984                 (match_operand:SI 2 "s_register_operand" "r")))]
7985   "TARGET_ARM"
7986   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
7987   [(set_attr "conds" "use")
7988    (set_attr "length" "8")]
7991 (define_insn "*ior_scc"
7992   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7993         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
7994                  [(match_operand 3 "cc_register" "") (const_int 0)])
7995                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
7996   "TARGET_ARM"
7997   "@
7998    orr%d2\\t%0, %1, #1
7999    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8000   [(set_attr "conds" "use")
8001    (set_attr "length" "4,8")]
8004 (define_insn "*compare_scc"
8005   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8006         (match_operator:SI 1 "arm_comparison_operator"
8007          [(match_operand:SI 2 "s_register_operand" "r,r")
8008           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8009    (clobber (reg:CC CC_REGNUM))]
8010   "TARGET_ARM"
8011   "*
8012     if (operands[3] == const0_rtx)
8013       {
8014         if (GET_CODE (operands[1]) == LT)
8015           return \"mov\\t%0, %2, lsr #31\";
8017         if (GET_CODE (operands[1]) == GE)
8018           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8020         if (GET_CODE (operands[1]) == EQ)
8021           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8022       }
8024     if (GET_CODE (operands[1]) == NE)
8025       {
8026         if (which_alternative == 1)
8027           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8028         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8029       }
8030     if (which_alternative == 1)
8031       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8032     else
8033       output_asm_insn (\"cmp\\t%2, %3\", operands);
8034     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8035   "
8036   [(set_attr "conds" "clob")
8037    (set_attr "length" "12")]
8040 (define_insn "*cond_move"
8041   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8042         (if_then_else:SI (match_operator 3 "equality_operator"
8043                           [(match_operator 4 "arm_comparison_operator"
8044                             [(match_operand 5 "cc_register" "") (const_int 0)])
8045                            (const_int 0)])
8046                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8047                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8048   "TARGET_ARM"
8049   "*
8050     if (GET_CODE (operands[3]) == NE)
8051       {
8052         if (which_alternative != 1)
8053           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8054         if (which_alternative != 0)
8055           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8056         return \"\";
8057       }
8058     if (which_alternative != 0)
8059       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8060     if (which_alternative != 1)
8061       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8062     return \"\";
8063   "
8064   [(set_attr "conds" "use")
8065    (set_attr "length" "4,4,8")]
8068 (define_insn "*cond_arith"
8069   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8070         (match_operator:SI 5 "shiftable_operator" 
8071          [(match_operator:SI 4 "arm_comparison_operator"
8072            [(match_operand:SI 2 "s_register_operand" "r,r")
8073             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8074           (match_operand:SI 1 "s_register_operand" "0,?r")]))
8075    (clobber (reg:CC CC_REGNUM))]
8076   "TARGET_ARM"
8077   "*
8078     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8079       return \"%i5\\t%0, %1, %2, lsr #31\";
8081     output_asm_insn (\"cmp\\t%2, %3\", operands);
8082     if (GET_CODE (operands[5]) == AND)
8083       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8084     else if (GET_CODE (operands[5]) == MINUS)
8085       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8086     else if (which_alternative != 0)
8087       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8088     return \"%i5%d4\\t%0, %1, #1\";
8089   "
8090   [(set_attr "conds" "clob")
8091    (set_attr "length" "12")]
8094 (define_insn "*cond_sub"
8095   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8096         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8097                   (match_operator:SI 4 "arm_comparison_operator"
8098                    [(match_operand:SI 2 "s_register_operand" "r,r")
8099                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8100    (clobber (reg:CC CC_REGNUM))]
8101   "TARGET_ARM"
8102   "*
8103     output_asm_insn (\"cmp\\t%2, %3\", operands);
8104     if (which_alternative != 0)
8105       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8106     return \"sub%d4\\t%0, %1, #1\";
8107   "
8108   [(set_attr "conds" "clob")
8109    (set_attr "length" "8,12")]
8112 (define_insn "*cmp_ite0"
8113   [(set (match_operand 6 "dominant_cc_register" "")
8114         (compare
8115          (if_then_else:SI
8116           (match_operator 4 "arm_comparison_operator"
8117            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8118             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8119           (match_operator:SI 5 "arm_comparison_operator"
8120            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8121             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8122           (const_int 0))
8123          (const_int 0)))]
8124   "TARGET_ARM"
8125   "*
8126   {
8127     static const char * const opcodes[4][2] =
8128     {
8129       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8130        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8131       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8132        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8133       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8134        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8135       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8136        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8137     };
8138     int swap =
8139       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8141     return opcodes[which_alternative][swap];
8142   }"
8143   [(set_attr "conds" "set")
8144    (set_attr "length" "8")]
8147 (define_insn "*cmp_ite1"
8148   [(set (match_operand 6 "dominant_cc_register" "")
8149         (compare
8150          (if_then_else:SI
8151           (match_operator 4 "arm_comparison_operator"
8152            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8153             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8154           (match_operator:SI 5 "arm_comparison_operator"
8155            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8156             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8157           (const_int 1))
8158          (const_int 0)))]
8159   "TARGET_ARM"
8160   "*
8161   {
8162     static const char * const opcodes[4][2] =
8163     {
8164       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8165        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8166       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8167        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8168       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8169        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8170       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8171        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8172     };
8173     int swap =
8174       comparison_dominates_p (GET_CODE (operands[5]),
8175                               reverse_condition (GET_CODE (operands[4])));
8177     return opcodes[which_alternative][swap];
8178   }"
8179   [(set_attr "conds" "set")
8180    (set_attr "length" "8")]
8183 (define_insn "*cmp_and"
8184   [(set (match_operand 6 "dominant_cc_register" "")
8185         (compare
8186          (and:SI
8187           (match_operator 4 "arm_comparison_operator"
8188            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8189             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8190           (match_operator:SI 5 "arm_comparison_operator"
8191            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8192             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8193          (const_int 0)))]
8194   "TARGET_ARM"
8195   "*
8196   {
8197     static const char *const opcodes[4][2] =
8198     {
8199       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8200        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8201       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8202        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8203       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8204        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8205       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8206        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8207     };
8208     int swap =
8209       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8211     return opcodes[which_alternative][swap];
8212   }"
8213   [(set_attr "conds" "set")
8214    (set_attr "predicable" "no")
8215    (set_attr "length" "8")]
8218 (define_insn "*cmp_ior"
8219   [(set (match_operand 6 "dominant_cc_register" "")
8220         (compare
8221          (ior:SI
8222           (match_operator 4 "arm_comparison_operator"
8223            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8224             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8225           (match_operator:SI 5 "arm_comparison_operator"
8226            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8227             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8228          (const_int 0)))]
8229   "TARGET_ARM"
8230   "*
8232   static const char *const opcodes[4][2] =
8233   {
8234     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8235      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8236     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8237      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8238     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8239      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8240     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8241      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8242   };
8243   int swap =
8244     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8246   return opcodes[which_alternative][swap];
8249   [(set_attr "conds" "set")
8250    (set_attr "length" "8")]
8253 (define_insn_and_split "*ior_scc_scc"
8254   [(set (match_operand:SI 0 "s_register_operand" "=r")
8255         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8256                  [(match_operand:SI 1 "s_register_operand" "r")
8257                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8258                 (match_operator:SI 6 "arm_comparison_operator"
8259                  [(match_operand:SI 4 "s_register_operand" "r")
8260                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8261    (clobber (reg:CC CC_REGNUM))]
8262   "TARGET_ARM
8263    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8264        != CCmode)"
8265   "#"
8266   "TARGET_ARM && reload_completed"
8267   [(set (match_dup 7)
8268         (compare
8269          (ior:SI
8270           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8271           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8272          (const_int 0)))
8273    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8274   "operands[7]
8275      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8276                                                   DOM_CC_X_OR_Y),
8277                     CC_REGNUM);"
8278   [(set_attr "conds" "clob")
8279    (set_attr "length" "16")])
8281 ; If the above pattern is followed by a CMP insn, then the compare is 
8282 ; redundant, since we can rework the conditional instruction that follows.
8283 (define_insn_and_split "*ior_scc_scc_cmp"
8284   [(set (match_operand 0 "dominant_cc_register" "")
8285         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8286                           [(match_operand:SI 1 "s_register_operand" "r")
8287                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8288                          (match_operator:SI 6 "arm_comparison_operator"
8289                           [(match_operand:SI 4 "s_register_operand" "r")
8290                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8291                  (const_int 0)))
8292    (set (match_operand:SI 7 "s_register_operand" "=r")
8293         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8294                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8295   "TARGET_ARM"
8296   "#"
8297   "TARGET_ARM && reload_completed"
8298   [(set (match_dup 0)
8299         (compare
8300          (ior:SI
8301           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8302           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8303          (const_int 0)))
8304    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8305   ""
8306   [(set_attr "conds" "set")
8307    (set_attr "length" "16")])
8309 (define_insn_and_split "*and_scc_scc"
8310   [(set (match_operand:SI 0 "s_register_operand" "=r")
8311         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8312                  [(match_operand:SI 1 "s_register_operand" "r")
8313                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8314                 (match_operator:SI 6 "arm_comparison_operator"
8315                  [(match_operand:SI 4 "s_register_operand" "r")
8316                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8317    (clobber (reg:CC CC_REGNUM))]
8318   "TARGET_ARM
8319    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8320        != CCmode)"
8321   "#"
8322   "TARGET_ARM && reload_completed
8323    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8324        != CCmode)"
8325   [(set (match_dup 7)
8326         (compare
8327          (and:SI
8328           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8329           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8330          (const_int 0)))
8331    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8332   "operands[7]
8333      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8334                                                   DOM_CC_X_AND_Y),
8335                     CC_REGNUM);"
8336   [(set_attr "conds" "clob")
8337    (set_attr "length" "16")])
8339 ; If the above pattern is followed by a CMP insn, then the compare is 
8340 ; redundant, since we can rework the conditional instruction that follows.
8341 (define_insn_and_split "*and_scc_scc_cmp"
8342   [(set (match_operand 0 "dominant_cc_register" "")
8343         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8344                           [(match_operand:SI 1 "s_register_operand" "r")
8345                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8346                          (match_operator:SI 6 "arm_comparison_operator"
8347                           [(match_operand:SI 4 "s_register_operand" "r")
8348                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8349                  (const_int 0)))
8350    (set (match_operand:SI 7 "s_register_operand" "=r")
8351         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8352                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8353   "TARGET_ARM"
8354   "#"
8355   "TARGET_ARM && reload_completed"
8356   [(set (match_dup 0)
8357         (compare
8358          (and:SI
8359           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8360           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8361          (const_int 0)))
8362    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8363   ""
8364   [(set_attr "conds" "set")
8365    (set_attr "length" "16")])
8367 ;; If there is no dominance in the comparison, then we can still save an
8368 ;; instruction in the AND case, since we can know that the second compare
8369 ;; need only zero the value if false (if true, then the value is already
8370 ;; correct).
8371 (define_insn_and_split "*and_scc_scc_nodom"
8372   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8373         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8374                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
8375                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8376                 (match_operator:SI 6 "arm_comparison_operator"
8377                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
8378                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8379    (clobber (reg:CC CC_REGNUM))]
8380   "TARGET_ARM
8381    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8382        == CCmode)"
8383   "#"
8384   "TARGET_ARM && reload_completed"
8385   [(parallel [(set (match_dup 0)
8386                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8387               (clobber (reg:CC CC_REGNUM))])
8388    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8389    (set (match_dup 0)
8390         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8391                          (match_dup 0)
8392                          (const_int 0)))]
8393   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8394                                               operands[4], operands[5]),
8395                               CC_REGNUM);
8396    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8397                                   operands[5]);"
8398   [(set_attr "conds" "clob")
8399    (set_attr "length" "20")])
8401 (define_split
8402   [(set (reg:CC_NOOV CC_REGNUM)
8403         (compare:CC_NOOV (ior:SI
8404                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8405                                   (const_int 1))
8406                           (match_operator:SI 1 "comparison_operator"
8407                            [(match_operand:SI 2 "s_register_operand" "")
8408                             (match_operand:SI 3 "arm_add_operand" "")]))
8409                          (const_int 0)))
8410    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8411   "TARGET_ARM"
8412   [(set (match_dup 4)
8413         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8414                 (match_dup 0)))
8415    (set (reg:CC_NOOV CC_REGNUM)
8416         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8417                          (const_int 0)))]
8418   "")
8420 (define_split
8421   [(set (reg:CC_NOOV CC_REGNUM)
8422         (compare:CC_NOOV (ior:SI
8423                           (match_operator:SI 1 "comparison_operator"
8424                            [(match_operand:SI 2 "s_register_operand" "")
8425                             (match_operand:SI 3 "arm_add_operand" "")])
8426                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8427                                   (const_int 1)))
8428                          (const_int 0)))
8429    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8430   "TARGET_ARM"
8431   [(set (match_dup 4)
8432         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8433                 (match_dup 0)))
8434    (set (reg:CC_NOOV CC_REGNUM)
8435         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8436                          (const_int 0)))]
8437   "")
8439 (define_insn "*negscc"
8440   [(set (match_operand:SI 0 "s_register_operand" "=r")
8441         (neg:SI (match_operator 3 "arm_comparison_operator"
8442                  [(match_operand:SI 1 "s_register_operand" "r")
8443                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8444    (clobber (reg:CC CC_REGNUM))]
8445   "TARGET_ARM"
8446   "*
8447   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8448     return \"mov\\t%0, %1, asr #31\";
8450   if (GET_CODE (operands[3]) == NE)
8451     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8453   if (GET_CODE (operands[3]) == GT)
8454     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8456   output_asm_insn (\"cmp\\t%1, %2\", operands);
8457   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8458   return \"mvn%d3\\t%0, #0\";
8459   "
8460   [(set_attr "conds" "clob")
8461    (set_attr "length" "12")]
8464 (define_insn "movcond"
8465   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8466         (if_then_else:SI
8467          (match_operator 5 "arm_comparison_operator"
8468           [(match_operand:SI 3 "s_register_operand" "r,r,r")
8469            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8470          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8471          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8472    (clobber (reg:CC CC_REGNUM))]
8473   "TARGET_ARM"
8474   "*
8475   if (GET_CODE (operands[5]) == LT
8476       && (operands[4] == const0_rtx))
8477     {
8478       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8479         {
8480           if (operands[2] == const0_rtx)
8481             return \"and\\t%0, %1, %3, asr #31\";
8482           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8483         }
8484       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8485         {
8486           if (operands[1] == const0_rtx)
8487             return \"bic\\t%0, %2, %3, asr #31\";
8488           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8489         }
8490       /* The only case that falls through to here is when both ops 1 & 2
8491          are constants.  */
8492     }
8494   if (GET_CODE (operands[5]) == GE
8495       && (operands[4] == const0_rtx))
8496     {
8497       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8498         {
8499           if (operands[2] == const0_rtx)
8500             return \"bic\\t%0, %1, %3, asr #31\";
8501           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8502         }
8503       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8504         {
8505           if (operands[1] == const0_rtx)
8506             return \"and\\t%0, %2, %3, asr #31\";
8507           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8508         }
8509       /* The only case that falls through to here is when both ops 1 & 2
8510          are constants.  */
8511     }
8512   if (GET_CODE (operands[4]) == CONST_INT
8513       && !const_ok_for_arm (INTVAL (operands[4])))
8514     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8515   else
8516     output_asm_insn (\"cmp\\t%3, %4\", operands);
8517   if (which_alternative != 0)
8518     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8519   if (which_alternative != 1)
8520     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8521   return \"\";
8522   "
8523   [(set_attr "conds" "clob")
8524    (set_attr "length" "8,8,12")]
8527 (define_insn "*ifcompare_plus_move"
8528   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8529         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8530                           [(match_operand:SI 4 "s_register_operand" "r,r")
8531                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8532                          (plus:SI
8533                           (match_operand:SI 2 "s_register_operand" "r,r")
8534                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8535                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8536    (clobber (reg:CC CC_REGNUM))]
8537   "TARGET_ARM"
8538   "#"
8539   [(set_attr "conds" "clob")
8540    (set_attr "length" "8,12")]
8543 (define_insn "*if_plus_move"
8544   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8545         (if_then_else:SI
8546          (match_operator 4 "arm_comparison_operator"
8547           [(match_operand 5 "cc_register" "") (const_int 0)])
8548          (plus:SI
8549           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8550           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8551          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8552   "TARGET_ARM"
8553   "@
8554    add%d4\\t%0, %2, %3
8555    sub%d4\\t%0, %2, #%n3
8556    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8557    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8558   [(set_attr "conds" "use")
8559    (set_attr "length" "4,4,8,8")
8560    (set_attr "type" "*,*,*,*")]
8563 (define_insn "*ifcompare_move_plus"
8564   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8565         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8566                           [(match_operand:SI 4 "s_register_operand" "r,r")
8567                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8568                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8569                          (plus:SI
8570                           (match_operand:SI 2 "s_register_operand" "r,r")
8571                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8572    (clobber (reg:CC CC_REGNUM))]
8573   "TARGET_ARM"
8574   "#"
8575   [(set_attr "conds" "clob")
8576    (set_attr "length" "8,12")]
8579 (define_insn "*if_move_plus"
8580   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8581         (if_then_else:SI
8582          (match_operator 4 "arm_comparison_operator"
8583           [(match_operand 5 "cc_register" "") (const_int 0)])
8584          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8585          (plus:SI
8586           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8587           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8588   "TARGET_ARM"
8589   "@
8590    add%D4\\t%0, %2, %3
8591    sub%D4\\t%0, %2, #%n3
8592    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8593    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8594   [(set_attr "conds" "use")
8595    (set_attr "length" "4,4,8,8")
8596    (set_attr "type" "*,*,*,*")]
8599 (define_insn "*ifcompare_arith_arith"
8600   [(set (match_operand:SI 0 "s_register_operand" "=r")
8601         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8602                           [(match_operand:SI 5 "s_register_operand" "r")
8603                            (match_operand:SI 6 "arm_add_operand" "rIL")])
8604                          (match_operator:SI 8 "shiftable_operator"
8605                           [(match_operand:SI 1 "s_register_operand" "r")
8606                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8607                          (match_operator:SI 7 "shiftable_operator"
8608                           [(match_operand:SI 3 "s_register_operand" "r")
8609                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8610    (clobber (reg:CC CC_REGNUM))]
8611   "TARGET_ARM"
8612   "#"
8613   [(set_attr "conds" "clob")
8614    (set_attr "length" "12")]
8617 (define_insn "*if_arith_arith"
8618   [(set (match_operand:SI 0 "s_register_operand" "=r")
8619         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8620                           [(match_operand 8 "cc_register" "") (const_int 0)])
8621                          (match_operator:SI 6 "shiftable_operator"
8622                           [(match_operand:SI 1 "s_register_operand" "r")
8623                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8624                          (match_operator:SI 7 "shiftable_operator"
8625                           [(match_operand:SI 3 "s_register_operand" "r")
8626                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8627   "TARGET_ARM"
8628   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8629   [(set_attr "conds" "use")
8630    (set_attr "length" "8")]
8633 (define_insn "*ifcompare_arith_move"
8634   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8635         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8636                           [(match_operand:SI 2 "s_register_operand" "r,r")
8637                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8638                          (match_operator:SI 7 "shiftable_operator"
8639                           [(match_operand:SI 4 "s_register_operand" "r,r")
8640                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8641                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8642    (clobber (reg:CC CC_REGNUM))]
8643   "TARGET_ARM"
8644   "*
8645   /* If we have an operation where (op x 0) is the identity operation and
8646      the conditional operator is LT or GE and we are comparing against zero and
8647      everything is in registers then we can do this in two instructions.  */
8648   if (operands[3] == const0_rtx
8649       && GET_CODE (operands[7]) != AND
8650       && GET_CODE (operands[5]) == REG
8651       && GET_CODE (operands[1]) == REG 
8652       && REGNO (operands[1]) == REGNO (operands[4])
8653       && REGNO (operands[4]) != REGNO (operands[0]))
8654     {
8655       if (GET_CODE (operands[6]) == LT)
8656         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8657       else if (GET_CODE (operands[6]) == GE)
8658         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8659     }
8660   if (GET_CODE (operands[3]) == CONST_INT
8661       && !const_ok_for_arm (INTVAL (operands[3])))
8662     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8663   else
8664     output_asm_insn (\"cmp\\t%2, %3\", operands);
8665   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8666   if (which_alternative != 0)
8667     return \"mov%D6\\t%0, %1\";
8668   return \"\";
8669   "
8670   [(set_attr "conds" "clob")
8671    (set_attr "length" "8,12")]
8674 (define_insn "*if_arith_move"
8675   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8676         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8677                           [(match_operand 6 "cc_register" "") (const_int 0)])
8678                          (match_operator:SI 5 "shiftable_operator"
8679                           [(match_operand:SI 2 "s_register_operand" "r,r")
8680                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8681                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8682   "TARGET_ARM"
8683   "@
8684    %I5%d4\\t%0, %2, %3
8685    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8686   [(set_attr "conds" "use")
8687    (set_attr "length" "4,8")
8688    (set_attr "type" "*,*")]
8691 (define_insn "*ifcompare_move_arith"
8692   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8693         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8694                           [(match_operand:SI 4 "s_register_operand" "r,r")
8695                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8696                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8697                          (match_operator:SI 7 "shiftable_operator"
8698                           [(match_operand:SI 2 "s_register_operand" "r,r")
8699                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8700    (clobber (reg:CC CC_REGNUM))]
8701   "TARGET_ARM"
8702   "*
8703   /* If we have an operation where (op x 0) is the identity operation and
8704      the conditional operator is LT or GE and we are comparing against zero and
8705      everything is in registers then we can do this in two instructions */
8706   if (operands[5] == const0_rtx
8707       && GET_CODE (operands[7]) != AND
8708       && GET_CODE (operands[3]) == REG
8709       && GET_CODE (operands[1]) == REG 
8710       && REGNO (operands[1]) == REGNO (operands[2])
8711       && REGNO (operands[2]) != REGNO (operands[0]))
8712     {
8713       if (GET_CODE (operands[6]) == GE)
8714         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8715       else if (GET_CODE (operands[6]) == LT)
8716         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8717     }
8719   if (GET_CODE (operands[5]) == CONST_INT
8720       && !const_ok_for_arm (INTVAL (operands[5])))
8721     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
8722   else
8723     output_asm_insn (\"cmp\\t%4, %5\", operands);
8725   if (which_alternative != 0)
8726     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
8727   return \"%I7%D6\\t%0, %2, %3\";
8728   "
8729   [(set_attr "conds" "clob")
8730    (set_attr "length" "8,12")]
8733 (define_insn "*if_move_arith"
8734   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8735         (if_then_else:SI
8736          (match_operator 4 "arm_comparison_operator"
8737           [(match_operand 6 "cc_register" "") (const_int 0)])
8738          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8739          (match_operator:SI 5 "shiftable_operator"
8740           [(match_operand:SI 2 "s_register_operand" "r,r")
8741            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
8742   "TARGET_ARM"
8743   "@
8744    %I5%D4\\t%0, %2, %3
8745    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8746   [(set_attr "conds" "use")
8747    (set_attr "length" "4,8")
8748    (set_attr "type" "*,*")]
8751 (define_insn "*ifcompare_move_not"
8752   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8753         (if_then_else:SI
8754          (match_operator 5 "arm_comparison_operator"
8755           [(match_operand:SI 3 "s_register_operand" "r,r")
8756            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8757          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8758          (not:SI
8759           (match_operand:SI 2 "s_register_operand" "r,r"))))
8760    (clobber (reg:CC CC_REGNUM))]
8761   "TARGET_ARM"
8762   "#"
8763   [(set_attr "conds" "clob")
8764    (set_attr "length" "8,12")]
8767 (define_insn "*if_move_not"
8768   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8769         (if_then_else:SI
8770          (match_operator 4 "arm_comparison_operator"
8771           [(match_operand 3 "cc_register" "") (const_int 0)])
8772          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8773          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8774   "TARGET_ARM"
8775   "@
8776    mvn%D4\\t%0, %2
8777    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
8778    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8779   [(set_attr "conds" "use")
8780    (set_attr "length" "4,8,8")]
8783 (define_insn "*ifcompare_not_move"
8784   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8785         (if_then_else:SI 
8786          (match_operator 5 "arm_comparison_operator"
8787           [(match_operand:SI 3 "s_register_operand" "r,r")
8788            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8789          (not:SI
8790           (match_operand:SI 2 "s_register_operand" "r,r"))
8791          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8792    (clobber (reg:CC CC_REGNUM))]
8793   "TARGET_ARM"
8794   "#"
8795   [(set_attr "conds" "clob")
8796    (set_attr "length" "8,12")]
8799 (define_insn "*if_not_move"
8800   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8801         (if_then_else:SI
8802          (match_operator 4 "arm_comparison_operator"
8803           [(match_operand 3 "cc_register" "") (const_int 0)])
8804          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8805          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8806   "TARGET_ARM"
8807   "@
8808    mvn%d4\\t%0, %2
8809    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
8810    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8811   [(set_attr "conds" "use")
8812    (set_attr "length" "4,8,8")]
8815 (define_insn "*ifcompare_shift_move"
8816   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8817         (if_then_else:SI
8818          (match_operator 6 "arm_comparison_operator"
8819           [(match_operand:SI 4 "s_register_operand" "r,r")
8820            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8821          (match_operator:SI 7 "shift_operator"
8822           [(match_operand:SI 2 "s_register_operand" "r,r")
8823            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
8824          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8825    (clobber (reg:CC CC_REGNUM))]
8826   "TARGET_ARM"
8827   "#"
8828   [(set_attr "conds" "clob")
8829    (set_attr "length" "8,12")]
8832 (define_insn "*if_shift_move"
8833   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8834         (if_then_else:SI
8835          (match_operator 5 "arm_comparison_operator"
8836           [(match_operand 6 "cc_register" "") (const_int 0)])
8837          (match_operator:SI 4 "shift_operator"
8838           [(match_operand:SI 2 "s_register_operand" "r,r,r")
8839            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
8840          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8841   "TARGET_ARM"
8842   "@
8843    mov%d5\\t%0, %2%S4
8844    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
8845    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8846   [(set_attr "conds" "use")
8847    (set_attr "shift" "2")
8848    (set_attr "length" "4,8,8")
8849    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
8850                       (const_string "alu_shift")
8851                       (const_string "alu_shift_reg")))]
8854 (define_insn "*ifcompare_move_shift"
8855   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8856         (if_then_else:SI
8857          (match_operator 6 "arm_comparison_operator"
8858           [(match_operand:SI 4 "s_register_operand" "r,r")
8859            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8860          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8861          (match_operator:SI 7 "shift_operator"
8862           [(match_operand:SI 2 "s_register_operand" "r,r")
8863            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
8864    (clobber (reg:CC CC_REGNUM))]
8865   "TARGET_ARM"
8866   "#"
8867   [(set_attr "conds" "clob")
8868    (set_attr "length" "8,12")]
8871 (define_insn "*if_move_shift"
8872   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8873         (if_then_else:SI
8874          (match_operator 5 "arm_comparison_operator"
8875           [(match_operand 6 "cc_register" "") (const_int 0)])
8876          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8877          (match_operator:SI 4 "shift_operator"
8878           [(match_operand:SI 2 "s_register_operand" "r,r,r")
8879            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
8880   "TARGET_ARM"
8881   "@
8882    mov%D5\\t%0, %2%S4
8883    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
8884    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8885   [(set_attr "conds" "use")
8886    (set_attr "shift" "2")
8887    (set_attr "length" "4,8,8")
8888    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
8889                       (const_string "alu_shift")
8890                       (const_string "alu_shift_reg")))]
8893 (define_insn "*ifcompare_shift_shift"
8894   [(set (match_operand:SI 0 "s_register_operand" "=r")
8895         (if_then_else:SI
8896          (match_operator 7 "arm_comparison_operator"
8897           [(match_operand:SI 5 "s_register_operand" "r")
8898            (match_operand:SI 6 "arm_add_operand" "rIL")])
8899          (match_operator:SI 8 "shift_operator"
8900           [(match_operand:SI 1 "s_register_operand" "r")
8901            (match_operand:SI 2 "arm_rhs_operand" "rM")])
8902          (match_operator:SI 9 "shift_operator"
8903           [(match_operand:SI 3 "s_register_operand" "r")
8904            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
8905    (clobber (reg:CC CC_REGNUM))]
8906   "TARGET_ARM"
8907   "#"
8908   [(set_attr "conds" "clob")
8909    (set_attr "length" "12")]
8912 (define_insn "*if_shift_shift"
8913   [(set (match_operand:SI 0 "s_register_operand" "=r")
8914         (if_then_else:SI
8915          (match_operator 5 "arm_comparison_operator"
8916           [(match_operand 8 "cc_register" "") (const_int 0)])
8917          (match_operator:SI 6 "shift_operator"
8918           [(match_operand:SI 1 "s_register_operand" "r")
8919            (match_operand:SI 2 "arm_rhs_operand" "rM")])
8920          (match_operator:SI 7 "shift_operator"
8921           [(match_operand:SI 3 "s_register_operand" "r")
8922            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
8923   "TARGET_ARM"
8924   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8925   [(set_attr "conds" "use")
8926    (set_attr "shift" "1")
8927    (set_attr "length" "8")
8928    (set (attr "type") (if_then_else
8929                         (and (match_operand 2 "const_int_operand" "")
8930                              (match_operand 4 "const_int_operand" ""))
8931                       (const_string "alu_shift")
8932                       (const_string "alu_shift_reg")))]
8935 (define_insn "*ifcompare_not_arith"
8936   [(set (match_operand:SI 0 "s_register_operand" "=r")
8937         (if_then_else:SI
8938          (match_operator 6 "arm_comparison_operator"
8939           [(match_operand:SI 4 "s_register_operand" "r")
8940            (match_operand:SI 5 "arm_add_operand" "rIL")])
8941          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8942          (match_operator:SI 7 "shiftable_operator"
8943           [(match_operand:SI 2 "s_register_operand" "r")
8944            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
8945    (clobber (reg:CC CC_REGNUM))]
8946   "TARGET_ARM"
8947   "#"
8948   [(set_attr "conds" "clob")
8949    (set_attr "length" "12")]
8952 (define_insn "*if_not_arith"
8953   [(set (match_operand:SI 0 "s_register_operand" "=r")
8954         (if_then_else:SI
8955          (match_operator 5 "arm_comparison_operator"
8956           [(match_operand 4 "cc_register" "") (const_int 0)])
8957          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8958          (match_operator:SI 6 "shiftable_operator"
8959           [(match_operand:SI 2 "s_register_operand" "r")
8960            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
8961   "TARGET_ARM"
8962   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8963   [(set_attr "conds" "use")
8964    (set_attr "length" "8")]
8967 (define_insn "*ifcompare_arith_not"
8968   [(set (match_operand:SI 0 "s_register_operand" "=r")
8969         (if_then_else:SI
8970          (match_operator 6 "arm_comparison_operator"
8971           [(match_operand:SI 4 "s_register_operand" "r")
8972            (match_operand:SI 5 "arm_add_operand" "rIL")])
8973          (match_operator:SI 7 "shiftable_operator"
8974           [(match_operand:SI 2 "s_register_operand" "r")
8975            (match_operand:SI 3 "arm_rhs_operand" "rI")])
8976          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
8977    (clobber (reg:CC CC_REGNUM))]
8978   "TARGET_ARM"
8979   "#"
8980   [(set_attr "conds" "clob")
8981    (set_attr "length" "12")]
8984 (define_insn "*if_arith_not"
8985   [(set (match_operand:SI 0 "s_register_operand" "=r")
8986         (if_then_else:SI
8987          (match_operator 5 "arm_comparison_operator"
8988           [(match_operand 4 "cc_register" "") (const_int 0)])
8989          (match_operator:SI 6 "shiftable_operator"
8990           [(match_operand:SI 2 "s_register_operand" "r")
8991            (match_operand:SI 3 "arm_rhs_operand" "rI")])
8992          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
8993   "TARGET_ARM"
8994   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8995   [(set_attr "conds" "use")
8996    (set_attr "length" "8")]
8999 (define_insn "*ifcompare_neg_move"
9000   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9001         (if_then_else:SI
9002          (match_operator 5 "arm_comparison_operator"
9003           [(match_operand:SI 3 "s_register_operand" "r,r")
9004            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9005          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9006          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9007    (clobber (reg:CC CC_REGNUM))]
9008   "TARGET_ARM"
9009   "#"
9010   [(set_attr "conds" "clob")
9011    (set_attr "length" "8,12")]
9014 (define_insn "*if_neg_move"
9015   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9016         (if_then_else:SI
9017          (match_operator 4 "arm_comparison_operator"
9018           [(match_operand 3 "cc_register" "") (const_int 0)])
9019          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9020          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9021   "TARGET_ARM"
9022   "@
9023    rsb%d4\\t%0, %2, #0
9024    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9025    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9026   [(set_attr "conds" "use")
9027    (set_attr "length" "4,8,8")]
9030 (define_insn "*ifcompare_move_neg"
9031   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9032         (if_then_else:SI
9033          (match_operator 5 "arm_comparison_operator"
9034           [(match_operand:SI 3 "s_register_operand" "r,r")
9035            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9036          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9037          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9038    (clobber (reg:CC CC_REGNUM))]
9039   "TARGET_ARM"
9040   "#"
9041   [(set_attr "conds" "clob")
9042    (set_attr "length" "8,12")]
9045 (define_insn "*if_move_neg"
9046   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9047         (if_then_else:SI
9048          (match_operator 4 "arm_comparison_operator"
9049           [(match_operand 3 "cc_register" "") (const_int 0)])
9050          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9051          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9052   "TARGET_ARM"
9053   "@
9054    rsb%D4\\t%0, %2, #0
9055    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9056    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9057   [(set_attr "conds" "use")
9058    (set_attr "length" "4,8,8")]
9061 (define_insn "*arith_adjacentmem"
9062   [(set (match_operand:SI 0 "s_register_operand" "=r")
9063         (match_operator:SI 1 "shiftable_operator"
9064          [(match_operand:SI 2 "memory_operand" "m")
9065           (match_operand:SI 3 "memory_operand" "m")]))
9066    (clobber (match_scratch:SI 4 "=r"))]
9067   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9068   "*
9069   {
9070     rtx ldm[3];
9071     rtx arith[4];
9072     int val1 = 0, val2 = 0;
9074     if (REGNO (operands[0]) > REGNO (operands[4]))
9075       {
9076         ldm[1] = operands[4];
9077         ldm[2] = operands[0];
9078       }
9079     else
9080       {
9081         ldm[1] = operands[0];
9082         ldm[2] = operands[4];
9083       }
9084     if (GET_CODE (XEXP (operands[2], 0)) != REG)
9085       val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
9086     if (GET_CODE (XEXP (operands[3], 0)) != REG)
9087       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9088     arith[0] = operands[0];
9089     arith[3] = operands[1];
9090     if (val1 < val2)
9091       {
9092         arith[1] = ldm[1];
9093         arith[2] = ldm[2];
9094       }
9095     else
9096       {
9097         arith[1] = ldm[2];
9098         arith[2] = ldm[1];
9099       }
9100    if (val1 && val2)
9101       {
9102         rtx ops[3];
9103         ldm[0] = ops[0] = operands[4];
9104         ops[1] = XEXP (XEXP (operands[2], 0), 0);
9105         ops[2] = XEXP (XEXP (operands[2], 0), 1);
9106         output_add_immediate (ops);
9107         if (val1 < val2)
9108           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9109         else
9110           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9111       }
9112     else if (val1)
9113       {
9114         ldm[0] = XEXP (operands[3], 0);
9115         if (val1 < val2)
9116           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9117         else
9118           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9119       }
9120     else
9121       {
9122         ldm[0] = XEXP (operands[2], 0);
9123         if (val1 < val2)
9124           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9125         else
9126           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9127       }
9128     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9129     return \"\";
9130   }"
9131   [(set_attr "length" "12")
9132    (set_attr "predicable" "yes")
9133    (set_attr "type" "load1")]
9136 ;; the arm can support extended pre-inc instructions
9138 ;; In all these cases, we use operands 0 and 1 for the register being
9139 ;; incremented because those are the operands that local-alloc will
9140 ;; tie and these are the pair most likely to be tieable (and the ones
9141 ;; that will benefit the most).
9143 ;; We reject the frame pointer if it occurs anywhere in these patterns since
9144 ;; elimination will cause too many headaches.
9146 (define_insn "*strqi_preinc"
9147   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9148                          (match_operand:SI 2 "index_operand" "rJ")))
9149         (match_operand:QI 3 "s_register_operand" "r"))
9150    (set (match_operand:SI 0 "s_register_operand" "=r")
9151         (plus:SI (match_dup 1) (match_dup 2)))]
9152   "TARGET_ARM
9153    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9154    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9155    && (GET_CODE (operands[2]) != REG
9156        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9157   "str%?b\\t%3, [%0, %2]!"
9158   [(set_attr "type" "store1")
9159    (set_attr "predicable" "yes")]
9162 (define_insn "*strqi_predec"
9163   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9164                           (match_operand:SI 2 "s_register_operand" "r")))
9165         (match_operand:QI 3 "s_register_operand" "r"))
9166    (set (match_operand:SI 0 "s_register_operand" "=r")
9167         (minus:SI (match_dup 1) (match_dup 2)))]
9168   "TARGET_ARM
9169    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9170    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9171    && (GET_CODE (operands[2]) != REG
9172        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9173   "str%?b\\t%3, [%0, -%2]!"
9174   [(set_attr "type" "store1")
9175    (set_attr "predicable" "yes")]
9178 (define_insn "*loadqi_preinc"
9179   [(set (match_operand:QI 3 "s_register_operand" "=r")
9180         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9181                          (match_operand:SI 2 "index_operand" "rJ"))))
9182    (set (match_operand:SI 0 "s_register_operand" "=r")
9183         (plus:SI (match_dup 1) (match_dup 2)))]
9184   "TARGET_ARM
9185    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9186    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9187    && (GET_CODE (operands[2]) != REG
9188        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9189   "ldr%?b\\t%3, [%0, %2]!"
9190   [(set_attr "type" "load_byte")
9191    (set_attr "predicable" "yes")]
9194 (define_insn "*loadqi_predec"
9195   [(set (match_operand:QI 3 "s_register_operand" "=r")
9196         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9197                           (match_operand:SI 2 "s_register_operand" "r"))))
9198    (set (match_operand:SI 0 "s_register_operand" "=r")
9199         (minus:SI (match_dup 1) (match_dup 2)))]
9200   "TARGET_ARM
9201    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9202    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9203    && (GET_CODE (operands[2]) != REG
9204        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9205   "ldr%?b\\t%3, [%0, -%2]!"
9206   [(set_attr "type" "load_byte")
9207    (set_attr "predicable" "yes")]
9210 (define_insn "*loadqisi_preinc"
9211   [(set (match_operand:SI 3 "s_register_operand" "=r")
9212         (zero_extend:SI
9213          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9214                           (match_operand:SI 2 "index_operand" "rJ")))))
9215    (set (match_operand:SI 0 "s_register_operand" "=r")
9216         (plus:SI (match_dup 1) (match_dup 2)))]
9217   "TARGET_ARM
9218    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9219    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9220    && (GET_CODE (operands[2]) != REG
9221        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9222   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
9223   [(set_attr "type" "load_byte")
9224    (set_attr "predicable" "yes")]
9227 (define_insn "*loadqisi_predec"
9228   [(set (match_operand:SI 3 "s_register_operand" "=r")
9229         (zero_extend:SI
9230          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9231                            (match_operand:SI 2 "s_register_operand" "r")))))
9232    (set (match_operand:SI 0 "s_register_operand" "=r")
9233         (minus:SI (match_dup 1) (match_dup 2)))]
9234   "TARGET_ARM
9235    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9236    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9237    && (GET_CODE (operands[2]) != REG
9238        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9239   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
9240   [(set_attr "type" "load_byte")
9241    (set_attr "predicable" "yes")]
9244 (define_insn "*strsi_preinc"
9245   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9246                          (match_operand:SI 2 "index_operand" "rJ")))
9247         (match_operand:SI 3 "s_register_operand" "r"))
9248    (set (match_operand:SI 0 "s_register_operand" "=r")
9249         (plus:SI (match_dup 1) (match_dup 2)))]
9250   "TARGET_ARM
9251    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9252    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9253    && (GET_CODE (operands[2]) != REG
9254        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9255   "str%?\\t%3, [%0, %2]!"
9256   [(set_attr "type" "store1")
9257    (set_attr "predicable" "yes")]
9260 (define_insn "*strsi_predec"
9261   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9262                           (match_operand:SI 2 "s_register_operand" "r")))
9263         (match_operand:SI 3 "s_register_operand" "r"))
9264    (set (match_operand:SI 0 "s_register_operand" "=r")
9265         (minus:SI (match_dup 1) (match_dup 2)))]
9266   "TARGET_ARM
9267    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9268    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9269    && (GET_CODE (operands[2]) != REG
9270        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9271   "str%?\\t%3, [%0, -%2]!"
9272   [(set_attr "type" "store1")
9273    (set_attr "predicable" "yes")]
9276 (define_insn "*loadsi_preinc"
9277   [(set (match_operand:SI 3 "s_register_operand" "=r")
9278         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9279                          (match_operand:SI 2 "index_operand" "rJ"))))
9280    (set (match_operand:SI 0 "s_register_operand" "=r")
9281         (plus:SI (match_dup 1) (match_dup 2)))]
9282   "TARGET_ARM
9283    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9284    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9285    && (GET_CODE (operands[2]) != REG
9286        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9287   "ldr%?\\t%3, [%0, %2]!"
9288   [(set_attr "type" "load1")
9289    (set_attr "predicable" "yes")]
9292 (define_insn "*loadsi_predec"
9293   [(set (match_operand:SI 3 "s_register_operand" "=r")
9294         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9295                           (match_operand:SI 2 "s_register_operand" "r"))))
9296    (set (match_operand:SI 0 "s_register_operand" "=r")
9297         (minus:SI (match_dup 1) (match_dup 2)))]
9298   "TARGET_ARM
9299    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9300    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9301    && (GET_CODE (operands[2]) != REG
9302        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9303   "ldr%?\\t%3, [%0, -%2]!"
9304   [(set_attr "type" "load1")
9305    (set_attr "predicable" "yes")]
9308 (define_insn "*loadhi_preinc"
9309   [(set (match_operand:HI 3 "s_register_operand" "=r")
9310         (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9311                          (match_operand:SI 2 "index_operand" "rJ"))))
9312    (set (match_operand:SI 0 "s_register_operand" "=r")
9313         (plus:SI (match_dup 1) (match_dup 2)))]
9314   "TARGET_ARM
9315    && !BYTES_BIG_ENDIAN
9316    && !TARGET_MMU_TRAPS
9317    && !arm_arch4
9318    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9319    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9320    && (GET_CODE (operands[2]) != REG
9321        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9322   "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
9323   [(set_attr "type" "load_byte")
9324    (set_attr "predicable" "yes")]
9327 (define_insn "*loadhi_predec"
9328   [(set (match_operand:HI 3 "s_register_operand" "=r")
9329         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9330                           (match_operand:SI 2 "s_register_operand" "r"))))
9331    (set (match_operand:SI 0 "s_register_operand" "=r")
9332         (minus:SI (match_dup 1) (match_dup 2)))]
9333   "TARGET_ARM
9334    && !BYTES_BIG_ENDIAN
9335    && !TARGET_MMU_TRAPS
9336    && !arm_arch4
9337    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9338    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9339    && (GET_CODE (operands[2]) != REG
9340        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9341   "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
9342   [(set_attr "type" "load_byte")
9343    (set_attr "predicable" "yes")]
9346 (define_insn "*strqi_shiftpreinc"
9347   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9348                           [(match_operand:SI 3 "s_register_operand" "r")
9349                            (match_operand:SI 4 "const_shift_operand" "n")])
9350                          (match_operand:SI 1 "s_register_operand" "0")))
9351         (match_operand:QI 5 "s_register_operand" "r"))
9352    (set (match_operand:SI 0 "s_register_operand" "=r")
9353         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9354                  (match_dup 1)))]
9355   "TARGET_ARM
9356    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9357    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9358    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9359   "str%?b\\t%5, [%0, %3%S2]!"
9360   [(set_attr "type" "store1")
9361    (set_attr "predicable" "yes")]
9364 (define_insn "*strqi_shiftpredec"
9365   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9366                           (match_operator:SI 2 "shift_operator"
9367                            [(match_operand:SI 3 "s_register_operand" "r")
9368                             (match_operand:SI 4 "const_shift_operand" "n")])))
9369         (match_operand:QI 5 "s_register_operand" "r"))
9370    (set (match_operand:SI 0 "s_register_operand" "=r")
9371         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9372                                                  (match_dup 4)])))]
9373   "TARGET_ARM
9374    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9375    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9376    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9377   "str%?b\\t%5, [%0, -%3%S2]!"
9378   [(set_attr "type" "store1")
9379    (set_attr "predicable" "yes")]
9382 (define_insn "*loadqi_shiftpreinc"
9383   [(set (match_operand:QI 5 "s_register_operand" "=r")
9384         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9385                           [(match_operand:SI 3 "s_register_operand" "r")
9386                            (match_operand:SI 4 "const_shift_operand" "n")])
9387                          (match_operand:SI 1 "s_register_operand" "0"))))
9388    (set (match_operand:SI 0 "s_register_operand" "=r")
9389         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9390                  (match_dup 1)))]
9391   "TARGET_ARM
9392    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9393    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9394    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9395   "ldr%?b\\t%5, [%0, %3%S2]!"
9396   [(set_attr "type" "load_byte")
9397    (set_attr "predicable" "yes")]
9400 (define_insn "*loadqi_shiftpredec"
9401   [(set (match_operand:QI 5 "s_register_operand" "=r")
9402         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9403                           (match_operator:SI 2 "shift_operator"
9404                            [(match_operand:SI 3 "s_register_operand" "r")
9405                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9406    (set (match_operand:SI 0 "s_register_operand" "=r")
9407         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9408                                                  (match_dup 4)])))]
9409   "TARGET_ARM
9410    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9411    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9412    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9413   "ldr%?b\\t%5, [%0, -%3%S2]!"
9414   [(set_attr "type" "load_byte")
9415    (set_attr "predicable" "yes")]
9418 (define_insn "*strsi_shiftpreinc"
9419   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9420                           [(match_operand:SI 3 "s_register_operand" "r")
9421                            (match_operand:SI 4 "const_shift_operand" "n")])
9422                          (match_operand:SI 1 "s_register_operand" "0")))
9423         (match_operand:SI 5 "s_register_operand" "r"))
9424    (set (match_operand:SI 0 "s_register_operand" "=r")
9425         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9426                  (match_dup 1)))]
9427   "TARGET_ARM
9428    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9429    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9430    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9431   "str%?\\t%5, [%0, %3%S2]!"
9432   [(set_attr "type" "store1")
9433    (set_attr "predicable" "yes")]
9436 (define_insn "*strsi_shiftpredec"
9437   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9438                           (match_operator:SI 2 "shift_operator"
9439                            [(match_operand:SI 3 "s_register_operand" "r")
9440                             (match_operand:SI 4 "const_shift_operand" "n")])))
9441         (match_operand:SI 5 "s_register_operand" "r"))
9442    (set (match_operand:SI 0 "s_register_operand" "=r")
9443         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9444                                                  (match_dup 4)])))]
9445   "TARGET_ARM
9446    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9447    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9448    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9449   "str%?\\t%5, [%0, -%3%S2]!"
9450   [(set_attr "type" "store1")
9451    (set_attr "predicable" "yes")]
9454 (define_insn "*loadsi_shiftpreinc"
9455   [(set (match_operand:SI 5 "s_register_operand" "=r")
9456         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9457                           [(match_operand:SI 3 "s_register_operand" "r")
9458                            (match_operand:SI 4 "const_shift_operand" "n")])
9459                          (match_operand:SI 1 "s_register_operand" "0"))))
9460    (set (match_operand:SI 0 "s_register_operand" "=r")
9461         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9462                  (match_dup 1)))]
9463   "TARGET_ARM
9464    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9465    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9466    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9467   "ldr%?\\t%5, [%0, %3%S2]!"
9468   [(set_attr "type" "load1")
9469    (set_attr "predicable" "yes")]
9472 (define_insn "*loadsi_shiftpredec"
9473   [(set (match_operand:SI 5 "s_register_operand" "=r")
9474         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9475                           (match_operator:SI 2 "shift_operator"
9476                            [(match_operand:SI 3 "s_register_operand" "r")
9477                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9478    (set (match_operand:SI 0 "s_register_operand" "=r")
9479         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9480                                                  (match_dup 4)])))]
9481   "TARGET_ARM
9482    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9483    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9484    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9485   "ldr%?\\t%5, [%0, -%3%S2]!"
9486   [(set_attr "type" "load1")
9487    (set_attr "predicable" "yes")])
9489 (define_insn "*loadhi_shiftpreinc"
9490   [(set (match_operand:HI 5 "s_register_operand" "=r")
9491         (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
9492                           [(match_operand:SI 3 "s_register_operand" "r")
9493                            (match_operand:SI 4 "const_shift_operand" "n")])
9494                          (match_operand:SI 1 "s_register_operand" "0"))))
9495    (set (match_operand:SI 0 "s_register_operand" "=r")
9496         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9497                  (match_dup 1)))]
9498   "TARGET_ARM
9499    && !BYTES_BIG_ENDIAN
9500    && !TARGET_MMU_TRAPS
9501    && !arm_arch4
9502    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9503    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9504    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9505   "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
9506   [(set_attr "type" "load_byte")
9507    (set_attr "predicable" "yes")]
9510 (define_insn "*loadhi_shiftpredec"
9511   [(set (match_operand:HI 5 "s_register_operand" "=r")
9512         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9513                           (match_operator:SI 2 "shift_operator"
9514                            [(match_operand:SI 3 "s_register_operand" "r")
9515                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9516    (set (match_operand:SI 0 "s_register_operand" "=r")
9517         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9518                                                  (match_dup 4)])))]
9519   "TARGET_ARM
9520    && !BYTES_BIG_ENDIAN
9521    && !TARGET_MMU_TRAPS
9522    && !arm_arch4
9523    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9524    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9525    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9526   "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
9527   [(set_attr "type" "load_byte")
9528    (set_attr "predicable" "yes")]
9531 ; It can also support extended post-inc expressions, but combine doesn't
9532 ; try these....
9533 ; It doesn't seem worth adding peepholes for anything but the most common
9534 ; cases since, unlike combine, the increment must immediately follow the load
9535 ; for this pattern to match.
9536 ; We must watch to see that the source/destination register isn't also the
9537 ; same as the base address register, and that if the index is a register,
9538 ; that it is not the same as the base address register.  In such cases the
9539 ; instruction that we would generate would have UNPREDICTABLE behavior so 
9540 ; we cannot use it.
9542 (define_peephole
9543   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9544         (match_operand:QI 2 "s_register_operand" "r"))
9545    (set (match_dup 0)
9546         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9547   "TARGET_ARM
9548    && (REGNO (operands[2]) != REGNO (operands[0]))
9549    && (GET_CODE (operands[1]) != REG
9550        || (REGNO (operands[1]) != REGNO (operands[0])))"
9551   "str%?b\\t%2, [%0], %1"
9554 (define_peephole
9555   [(set (match_operand:QI 0 "s_register_operand" "=r")
9556         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9557    (set (match_dup 1)
9558         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9559   "TARGET_ARM
9560    && REGNO (operands[0]) != REGNO(operands[1])
9561    && (GET_CODE (operands[2]) != REG
9562        || REGNO(operands[0]) != REGNO (operands[2]))"
9563   "ldr%?b\\t%0, [%1], %2"
9566 (define_peephole
9567   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9568         (match_operand:SI 2 "s_register_operand" "r"))
9569    (set (match_dup 0)
9570         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9571   "TARGET_ARM
9572    && (REGNO (operands[2]) != REGNO (operands[0]))
9573    && (GET_CODE (operands[1]) != REG
9574        || (REGNO (operands[1]) != REGNO (operands[0])))"
9575   "str%?\\t%2, [%0], %1"
9578 (define_peephole
9579   [(set (match_operand:HI 0 "s_register_operand" "=r")
9580         (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
9581    (set (match_dup 1)
9582         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9583   "TARGET_ARM
9584    && !BYTES_BIG_ENDIAN
9585    && !TARGET_MMU_TRAPS
9586    && !arm_arch4
9587    && REGNO (operands[0]) != REGNO(operands[1])
9588    && (GET_CODE (operands[2]) != REG
9589        || REGNO(operands[0]) != REGNO (operands[2]))"
9590   "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
9593 (define_peephole
9594   [(set (match_operand:SI 0 "s_register_operand" "=r")
9595         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9596    (set (match_dup 1)
9597         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9598   "TARGET_ARM
9599    && REGNO (operands[0]) != REGNO(operands[1])
9600    && (GET_CODE (operands[2]) != REG
9601        || REGNO(operands[0]) != REGNO (operands[2]))"
9602   "ldr%?\\t%0, [%1], %2"
9605 (define_peephole
9606   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9607                          (match_operand:SI 1 "index_operand" "rJ")))
9608         (match_operand:QI 2 "s_register_operand" "r"))
9609    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
9610   "TARGET_ARM
9611    && (REGNO (operands[2]) != REGNO (operands[0]))
9612    && (GET_CODE (operands[1]) != REG
9613        || (REGNO (operands[1]) != REGNO (operands[0])))"
9614   "str%?b\\t%2, [%0, %1]!"
9617 (define_peephole
9618   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9619                           [(match_operand:SI 0 "s_register_operand" "r")
9620                            (match_operand:SI 1 "const_int_operand" "n")])
9621                          (match_operand:SI 2 "s_register_operand" "+r")))
9622         (match_operand:QI 3 "s_register_operand" "r"))
9623    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9624                                (match_dup 2)))]
9625   "TARGET_ARM
9626    && (REGNO (operands[3]) != REGNO (operands[2]))
9627    && (REGNO (operands[0]) != REGNO (operands[2]))"
9628   "str%?b\\t%3, [%2, %0%S4]!"
9631 ; This pattern is never tried by combine, so do it as a peephole
9633 (define_peephole2
9634   [(set (match_operand:SI 0 "s_register_operand" "")
9635         (match_operand:SI 1 "s_register_operand" ""))
9636    (set (reg:CC CC_REGNUM)
9637         (compare:CC (match_dup 1) (const_int 0)))]
9638   "TARGET_ARM
9639    && (!(TARGET_HARD_FLOAT && TARGET_MAVERICK)
9640        || (!cirrus_fp_register (operands[0], SImode)
9641            && !cirrus_fp_register (operands[1], SImode)))
9642   "
9643   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9644               (set (match_dup 0) (match_dup 1))])]
9645   ""
9648 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9649 ; reversed, check that the memory references aren't volatile.
9651 (define_peephole
9652   [(set (match_operand:SI 0 "s_register_operand" "=r")
9653         (match_operand:SI 4 "memory_operand" "m"))
9654    (set (match_operand:SI 1 "s_register_operand" "=r")
9655         (match_operand:SI 5 "memory_operand" "m"))
9656    (set (match_operand:SI 2 "s_register_operand" "=r")
9657         (match_operand:SI 6 "memory_operand" "m"))
9658    (set (match_operand:SI 3 "s_register_operand" "=r")
9659         (match_operand:SI 7 "memory_operand" "m"))]
9660   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9661   "*
9662   return emit_ldm_seq (operands, 4);
9663   "
9666 (define_peephole
9667   [(set (match_operand:SI 0 "s_register_operand" "=r")
9668         (match_operand:SI 3 "memory_operand" "m"))
9669    (set (match_operand:SI 1 "s_register_operand" "=r")
9670         (match_operand:SI 4 "memory_operand" "m"))
9671    (set (match_operand:SI 2 "s_register_operand" "=r")
9672         (match_operand:SI 5 "memory_operand" "m"))]
9673   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9674   "*
9675   return emit_ldm_seq (operands, 3);
9676   "
9679 (define_peephole
9680   [(set (match_operand:SI 0 "s_register_operand" "=r")
9681         (match_operand:SI 2 "memory_operand" "m"))
9682    (set (match_operand:SI 1 "s_register_operand" "=r")
9683         (match_operand:SI 3 "memory_operand" "m"))]
9684   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9685   "*
9686   return emit_ldm_seq (operands, 2);
9687   "
9690 (define_peephole
9691   [(set (match_operand:SI 4 "memory_operand" "=m")
9692         (match_operand:SI 0 "s_register_operand" "r"))
9693    (set (match_operand:SI 5 "memory_operand" "=m")
9694         (match_operand:SI 1 "s_register_operand" "r"))
9695    (set (match_operand:SI 6 "memory_operand" "=m")
9696         (match_operand:SI 2 "s_register_operand" "r"))
9697    (set (match_operand:SI 7 "memory_operand" "=m")
9698         (match_operand:SI 3 "s_register_operand" "r"))]
9699   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9700   "*
9701   return emit_stm_seq (operands, 4);
9702   "
9705 (define_peephole
9706   [(set (match_operand:SI 3 "memory_operand" "=m")
9707         (match_operand:SI 0 "s_register_operand" "r"))
9708    (set (match_operand:SI 4 "memory_operand" "=m")
9709         (match_operand:SI 1 "s_register_operand" "r"))
9710    (set (match_operand:SI 5 "memory_operand" "=m")
9711         (match_operand:SI 2 "s_register_operand" "r"))]
9712   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9713   "*
9714   return emit_stm_seq (operands, 3);
9715   "
9718 (define_peephole
9719   [(set (match_operand:SI 2 "memory_operand" "=m")
9720         (match_operand:SI 0 "s_register_operand" "r"))
9721    (set (match_operand:SI 3 "memory_operand" "=m")
9722         (match_operand:SI 1 "s_register_operand" "r"))]
9723   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9724   "*
9725   return emit_stm_seq (operands, 2);
9726   "
9729 (define_split
9730   [(set (match_operand:SI 0 "s_register_operand" "")
9731         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9732                        (const_int 0))
9733                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9734                          [(match_operand:SI 3 "s_register_operand" "")
9735                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
9736    (clobber (match_operand:SI 5 "s_register_operand" ""))]
9737   "TARGET_ARM"
9738   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9739    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9740                               (match_dup 5)))]
9741   ""
9744 ;; This split can be used because CC_Z mode implies that the following
9745 ;; branch will be an equality, or an unsigned inequality, so the sign
9746 ;; extension is not needed.
9748 (define_split
9749   [(set (reg:CC_Z CC_REGNUM)
9750         (compare:CC_Z
9751          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9752                     (const_int 24))
9753          (match_operand 1 "const_int_operand" "")))
9754    (clobber (match_scratch:SI 2 ""))]
9755   "TARGET_ARM
9756    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9757        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9758   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9759    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9760   "
9761   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9762   "
9765 (define_expand "prologue"
9766   [(clobber (const_int 0))]
9767   "TARGET_EITHER"
9768   "if (TARGET_ARM)
9769      arm_expand_prologue ();
9770    else
9771      thumb_expand_prologue ();
9772   DONE;
9773   "
9776 (define_expand "epilogue"
9777   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9778   "TARGET_EITHER"
9779   "
9780   if (TARGET_THUMB)
9781     thumb_expand_epilogue ();
9782   else if (USE_RETURN_INSN (FALSE))
9783     {
9784       emit_jump_insn (gen_return ());
9785       DONE;
9786     }
9787   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9788         gen_rtvec (1,
9789                 gen_rtx_RETURN (VOIDmode)),
9790         VUNSPEC_EPILOGUE));
9791   DONE;
9792   "
9795 ;; Note - although unspec_volatile's USE all hard registers,
9796 ;; USEs are ignored after relaod has completed.  Thus we need
9797 ;; to add an unspec of the link register to ensure that flow
9798 ;; does not think that it is unused by the sibcall branch that
9799 ;; will replace the standard function epilogue.
9800 (define_insn "sibcall_epilogue"
9801   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9802               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9803   "TARGET_ARM"
9804   "*
9805   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9806     return output_return_instruction (const_true_rtx, FALSE, FALSE);
9807   return arm_output_epilogue (next_nonnote_insn (insn));
9808   "
9809 ;; Length is absolute worst case
9810   [(set_attr "length" "44")
9811    (set_attr "type" "block")
9812    ;; We don't clobber the conditions, but the potential length of this
9813    ;; operation is sufficient to make conditionalizing the sequence 
9814    ;; unlikely to be profitable.
9815    (set_attr "conds" "clob")]
9818 (define_insn "*epilogue_insns"
9819   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9820   "TARGET_EITHER"
9821   "*
9822   if (TARGET_ARM)
9823     return arm_output_epilogue (NULL);
9824   else /* TARGET_THUMB */
9825     return thumb_unexpanded_epilogue ();
9826   "
9827   ; Length is absolute worst case
9828   [(set_attr "length" "44")
9829    (set_attr "type" "block")
9830    ;; We don't clobber the conditions, but the potential length of this
9831    ;; operation is sufficient to make conditionalizing the sequence 
9832    ;; unlikely to be profitable.
9833    (set_attr "conds" "clob")]
9836 (define_expand "eh_epilogue"
9837   [(use (match_operand:SI 0 "register_operand" ""))
9838    (use (match_operand:SI 1 "register_operand" ""))
9839    (use (match_operand:SI 2 "register_operand" ""))]
9840   "TARGET_EITHER"
9841   "
9842   {
9843     cfun->machine->eh_epilogue_sp_ofs = operands[1];
9844     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9845       {
9846         rtx ra = gen_rtx_REG (Pmode, 2);
9848         emit_move_insn (ra, operands[2]);
9849         operands[2] = ra;
9850       }
9851     /* This is a hack -- we may have crystalized the function type too
9852        early.  */
9853     cfun->machine->func_type = 0;
9854   }"
9857 ;; This split is only used during output to reduce the number of patterns
9858 ;; that need assembler instructions adding to them.  We allowed the setting
9859 ;; of the conditions to be implicit during rtl generation so that
9860 ;; the conditional compare patterns would work.  However this conflicts to
9861 ;; some extent with the conditional data operations, so we have to split them
9862 ;; up again here.
9864 (define_split
9865   [(set (match_operand:SI 0 "s_register_operand" "")
9866         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9867                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9868                          (match_dup 0)
9869                          (match_operand 4 "" "")))
9870    (clobber (reg:CC CC_REGNUM))]
9871   "TARGET_ARM && reload_completed"
9872   [(set (match_dup 5) (match_dup 6))
9873    (cond_exec (match_dup 7)
9874               (set (match_dup 0) (match_dup 4)))]
9875   "
9876   {
9877     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9878                                              operands[2], operands[3]);
9879     enum rtx_code rc = GET_CODE (operands[1]);
9881     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9882     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9883     if (mode == CCFPmode || mode == CCFPEmode)
9884       rc = reverse_condition_maybe_unordered (rc);
9885     else
9886       rc = reverse_condition (rc);
9888     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9889   }"
9892 (define_split
9893   [(set (match_operand:SI 0 "s_register_operand" "")
9894         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9895                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9896                          (match_operand 4 "" "")
9897                          (match_dup 0)))
9898    (clobber (reg:CC CC_REGNUM))]
9899   "TARGET_ARM && reload_completed"
9900   [(set (match_dup 5) (match_dup 6))
9901    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9902               (set (match_dup 0) (match_dup 4)))]
9903   "
9904   {
9905     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9906                                              operands[2], operands[3]);
9908     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9909     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9910   }"
9913 (define_split
9914   [(set (match_operand:SI 0 "s_register_operand" "")
9915         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9916                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9917                          (match_operand 4 "" "")
9918                          (match_operand 5 "" "")))
9919    (clobber (reg:CC CC_REGNUM))]
9920   "TARGET_ARM && reload_completed"
9921   [(set (match_dup 6) (match_dup 7))
9922    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9923               (set (match_dup 0) (match_dup 4)))
9924    (cond_exec (match_dup 8)
9925               (set (match_dup 0) (match_dup 5)))]
9926   "
9927   {
9928     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9929                                              operands[2], operands[3]);
9930     enum rtx_code rc = GET_CODE (operands[1]);
9932     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9933     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9934     if (mode == CCFPmode || mode == CCFPEmode)
9935       rc = reverse_condition_maybe_unordered (rc);
9936     else
9937       rc = reverse_condition (rc);
9939     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9940   }"
9943 (define_split
9944   [(set (match_operand:SI 0 "s_register_operand" "")
9945         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9946                           [(match_operand:SI 2 "s_register_operand" "")
9947                            (match_operand:SI 3 "arm_add_operand" "")])
9948                          (match_operand:SI 4 "arm_rhs_operand" "")
9949                          (not:SI
9950                           (match_operand:SI 5 "s_register_operand" ""))))
9951    (clobber (reg:CC CC_REGNUM))]
9952   "TARGET_ARM && reload_completed"
9953   [(set (match_dup 6) (match_dup 7))
9954    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9955               (set (match_dup 0) (match_dup 4)))
9956    (cond_exec (match_dup 8)
9957               (set (match_dup 0) (not:SI (match_dup 5))))]
9958   "
9959   {
9960     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9961                                              operands[2], operands[3]);
9962     enum rtx_code rc = GET_CODE (operands[1]);
9964     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9965     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9966     if (mode == CCFPmode || mode == CCFPEmode)
9967       rc = reverse_condition_maybe_unordered (rc);
9968     else
9969       rc = reverse_condition (rc);
9971     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9972   }"
9975 (define_insn "*cond_move_not"
9976   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9977         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9978                           [(match_operand 3 "cc_register" "") (const_int 0)])
9979                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9980                          (not:SI
9981                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
9982   "TARGET_ARM"
9983   "@
9984    mvn%D4\\t%0, %2
9985    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
9986   [(set_attr "conds" "use")
9987    (set_attr "length" "4,8")]
9990 ;; The next two patterns occur when an AND operation is followed by a
9991 ;; scc insn sequence 
9993 (define_insn "*sign_extract_onebit"
9994   [(set (match_operand:SI 0 "s_register_operand" "=r")
9995         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9996                          (const_int 1)
9997                          (match_operand:SI 2 "const_int_operand" "n")))
9998     (clobber (reg:CC CC_REGNUM))]
9999   "TARGET_ARM"
10000   "*
10001     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10002     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10003     return \"mvnne\\t%0, #0\";
10004   "
10005   [(set_attr "conds" "clob")
10006    (set_attr "length" "8")]
10009 (define_insn "*not_signextract_onebit"
10010   [(set (match_operand:SI 0 "s_register_operand" "=r")
10011         (not:SI
10012          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10013                           (const_int 1)
10014                           (match_operand:SI 2 "const_int_operand" "n"))))
10015    (clobber (reg:CC CC_REGNUM))]
10016   "TARGET_ARM"
10017   "*
10018     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10019     output_asm_insn (\"tst\\t%1, %2\", operands);
10020     output_asm_insn (\"mvneq\\t%0, #0\", operands);
10021     return \"movne\\t%0, #0\";
10022   "
10023   [(set_attr "conds" "clob")
10024    (set_attr "length" "12")]
10027 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
10028 ;; expressions.  For simplicity, the first register is also in the unspec
10029 ;; part.
10030 (define_insn "*push_multi"
10031   [(match_parallel 2 "multi_register_push"
10032     [(set (match_operand:BLK 0 "memory_operand" "=m")
10033           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
10034                       UNSPEC_PUSH_MULT))])]
10035   "TARGET_ARM"
10036   "*
10037   {
10038     int num_saves = XVECLEN (operands[2], 0);
10039      
10040     /* For the StrongARM at least it is faster to
10041        use STR to store only a single register.  */
10042     if (num_saves == 1)
10043       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10044     else
10045       {
10046         int i;
10047         char pattern[100];
10049         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10051         for (i = 1; i < num_saves; i++)
10052           {
10053             strcat (pattern, \", %|\");
10054             strcat (pattern,
10055                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10056           }
10058         strcat (pattern, \"}\");
10059         output_asm_insn (pattern, operands);
10060       }
10062     return \"\";
10063   }"
10064   [(set_attr "type" "store4")]
10067 (define_insn "stack_tie"
10068   [(set (mem:BLK (scratch))
10069         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
10070                      (match_operand:SI 1 "s_register_operand" "r")]
10071                     UNSPEC_PRLG_STK))]
10072   ""
10073   ""
10074   [(set_attr "length" "0")]
10077 ;; Similarly for the floating point registers
10078 (define_insn "*push_fp_multi"
10079   [(match_parallel 2 "multi_register_push"
10080     [(set (match_operand:BLK 0 "memory_operand" "=m")
10081           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10082                       UNSPEC_PUSH_MULT))])]
10083   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
10084   "*
10085   {
10086     char pattern[100];
10088     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10089     output_asm_insn (pattern, operands);
10090     return \"\";
10091   }"
10092   [(set_attr "type" "f_store")]
10095 ;; Special patterns for dealing with the constant pool
10097 (define_insn "align_4"
10098   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10099   "TARGET_EITHER"
10100   "*
10101   assemble_align (32);
10102   return \"\";
10103   "
10106 (define_insn "align_8"
10107   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10108   "TARGET_EITHER"
10109   "*
10110   assemble_align (64);
10111   return \"\";
10112   "
10115 (define_insn "consttable_end"
10116   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10117   "TARGET_EITHER"
10118   "*
10119   making_const_table = FALSE;
10120   return \"\";
10121   "
10124 (define_insn "consttable_1"
10125   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10126   "TARGET_THUMB"
10127   "*
10128   making_const_table = TRUE;
10129   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10130   assemble_zeros (3);
10131   return \"\";
10132   "
10133   [(set_attr "length" "4")]
10136 (define_insn "consttable_2"
10137   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10138   "TARGET_THUMB"
10139   "*
10140   making_const_table = TRUE;
10141   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10142   assemble_zeros (2);
10143   return \"\";
10144   "
10145   [(set_attr "length" "4")]
10148 (define_insn "consttable_4"
10149   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10150   "TARGET_EITHER"
10151   "*
10152   {
10153     making_const_table = TRUE;
10154     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10155       {
10156       case MODE_FLOAT:
10157       {
10158         REAL_VALUE_TYPE r;
10159         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10160         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10161         break;
10162       }
10163       default:
10164         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
10165         break;
10166       }
10167     return \"\";
10168   }"
10169   [(set_attr "length" "4")]
10172 (define_insn "consttable_8"
10173   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10174   "TARGET_EITHER"
10175   "*
10176   {
10177     making_const_table = TRUE;
10178     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10179       {
10180        case MODE_FLOAT:
10181         {
10182           REAL_VALUE_TYPE r;
10183           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10184           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10185           break;
10186         }
10187       default:
10188         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10189         break;
10190       }
10191     return \"\";
10192   }"
10193   [(set_attr "length" "8")]
10196 ;; Miscellaneous Thumb patterns
10198 (define_expand "tablejump"
10199   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10200               (use (label_ref (match_operand 1 "" "")))])]
10201   "TARGET_THUMB"
10202   "
10203   if (flag_pic)
10204     {
10205       /* Hopefully, CSE will eliminate this copy.  */
10206       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10207       rtx reg2 = gen_reg_rtx (SImode);
10209       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10210       operands[0] = reg2;
10211     }
10212   "
10215 (define_insn "*thumb_tablejump"
10216   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10217    (use (label_ref (match_operand 1 "" "")))]
10218   "TARGET_THUMB"
10219   "mov\\t%|pc, %0"
10220   [(set_attr "length" "2")]
10223 ;; V5 Instructions,
10225 (define_insn "clzsi2"
10226   [(set (match_operand:SI 0 "s_register_operand" "=r")
10227         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10228   "TARGET_ARM && arm_arch5"
10229   "clz%?\\t%0, %1"
10230   [(set_attr "predicable" "yes")])
10232 (define_expand "ffssi2"
10233   [(set (match_operand:SI 0 "s_register_operand" "")
10234         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10235   "TARGET_ARM && arm_arch5"
10236   "
10237   {
10238     rtx t1, t2, t3;
10240     t1 = gen_reg_rtx (SImode);
10241     t2 = gen_reg_rtx (SImode);
10242     t3 = gen_reg_rtx (SImode);
10244     emit_insn (gen_negsi2 (t1, operands[1]));
10245     emit_insn (gen_andsi3 (t2, operands[1], t1));
10246     emit_insn (gen_clzsi2 (t3, t2));
10247     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10248     DONE;
10249   }"
10252 (define_expand "ctzsi2"
10253   [(set (match_operand:SI 0 "s_register_operand" "")
10254         (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10255   "TARGET_ARM && arm_arch5"
10256   "
10257   {
10258     rtx t1, t2, t3;
10260     t1 = gen_reg_rtx (SImode);
10261     t2 = gen_reg_rtx (SImode);
10262     t3 = gen_reg_rtx (SImode);
10264     emit_insn (gen_negsi2 (t1, operands[1]));
10265     emit_insn (gen_andsi3 (t2, operands[1], t1));
10266     emit_insn (gen_clzsi2 (t3, t2));
10267     emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10268     DONE;
10269   }"
10272 ;; V5E instructions.
10274 (define_insn "prefetch"
10275   [(prefetch (match_operand:SI 0 "address_operand" "p")
10276              (match_operand:SI 1 "" "")
10277              (match_operand:SI 2 "" ""))]
10278   "TARGET_ARM && arm_arch5e"
10279   "pld\\t%a0")
10281 ;; General predication pattern
10283 (define_cond_exec
10284   [(match_operator 0 "arm_comparison_operator"
10285     [(match_operand 1 "cc_register" "")
10286      (const_int 0)])]
10287   "TARGET_ARM"
10288   ""
10291 (define_insn "prologue_use"
10292   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10293   ""
10294   "%@ %0 needed for prologue"
10297 ;; Load the FPA co-processor patterns
10298 (include "fpa.md")
10299 ;; Load the Maverick co-processor patterns
10300 (include "cirrus.md")
10301 ;; Load the Intel Wireless Multimedia Extension patterns
10302 (include "iwmmxt.md")
10303 ;; Load the VFP co-processor patterns
10304 (include "vfp.md")