* rtl.h (MEM_READONLY_P): Replace RTX_UNCHANGING_P.
[official-gcc.git] / gcc / config / arm / arm.md
blob6346960330dfe296ddefda47a07f3db1ffdae620
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    (VUNSPEC_EH_RETURN 20); Use to overrite the return address for exception
121                          ; handling.
122   ]
125 ;;---------------------------------------------------------------------------
126 ;; Attributes
128 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
129 ; generating ARM code.  This is used to control the length of some insn
130 ; patterns that share the same RTL in both ARM and Thumb code.
131 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
133 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
134 ; scheduling decisions for the load unit and the multiplier.
135 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
137 ; IS_XSCALE is set to 'yes' when compiling for XScale.
138 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
140 ;; Operand number of an input operand that is shifted.  Zero if the
141 ;; given instruction does not shift one of its input operands.
142 (define_attr "shift" "" (const_int 0))
144 ; Floating Point Unit.  If we only have floating point emulation, then there
145 ; is no point in scheduling the floating point insns.  (Well, for best
146 ; performance we should try and group them together).
147 (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
148   (const (symbol_ref "arm_fpu_attr")))
150 ; LENGTH of an instruction (in bytes)
151 (define_attr "length" "" (const_int 4))
153 ; POOL_RANGE is how far away from a constant pool entry that this insn
154 ; can be placed.  If the distance is zero, then this insn will never
155 ; reference the pool.
156 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
157 ; before its address.
158 (define_attr "pool_range" "" (const_int 0))
159 (define_attr "neg_pool_range" "" (const_int 0))
161 ; An assembler sequence may clobber the condition codes without us knowing.
162 ; If such an insn references the pool, then we have no way of knowing how,
163 ; so use the most conservative value for pool_range.
164 (define_asm_attributes
165  [(set_attr "conds" "clob")
166   (set_attr "length" "4")
167   (set_attr "pool_range" "250")])
169 ;; The instruction used to implement a particular pattern.  This
170 ;; information is used by pipeline descriptions to provide accurate
171 ;; scheduling information.
173 (define_attr "insn"
174         "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"
175         (const_string "other"))
177 ; TYPE attribute is used to detect floating point instructions which, if
178 ; running on a co-processor can run in parallel with other, basic instructions
179 ; If write-buffer scheduling is enabled then it can also be used in the
180 ; scheduling of writes.
182 ; Classification of each insn
183 ; alu           any alu  instruction that doesn't hit memory or fp
184 ;               regs or have a shifted source operand
185 ; alu_shift     any data instruction that doesn't hit memory or fp
186 ;               regs, but has a source operand shifted by a constant
187 ; alu_shift_reg any data instruction that doesn't hit memory or fp
188 ;               regs, but has a source operand shifted by a register value
189 ; mult          a multiply instruction
190 ; block         blockage insn, this blocks all functional units
191 ; float         a floating point arithmetic operation (subject to expansion)
192 ; fdivd         DFmode floating point division
193 ; fdivs         SFmode floating point division
194 ; fmul          Floating point multiply
195 ; ffmul         Fast floating point multiply
196 ; farith        Floating point arithmetic (4 cycle)
197 ; ffarith       Fast floating point arithmetic (2 cycle)
198 ; float_em      a floating point arithmetic operation that is normally emulated
199 ;               even on a machine with an fpa.
200 ; f_load        a floating point load from memory
201 ; f_store       a floating point store to memory
202 ; f_mem_r       a transfer of a floating point register to a real reg via mem
203 ; r_mem_f       the reverse of f_mem_r
204 ; f_2_r         fast transfer float to arm (no memory needed)
205 ; r_2_f         fast transfer arm to float
206 ; branch        a branch
207 ; call          a subroutine call
208 ; load_byte     load byte(s) from memory to arm registers
209 ; load1         load 1 word from memory to arm registers
210 ; load2         load 2 words from memory to arm registers
211 ; load3         load 3 words from memory to arm registers
212 ; load4         load 4 words from memory to arm registers
213 ; store         store 1 word to memory from arm registers
214 ; store2        store 2 words
215 ; store3        store 3 words
216 ; store4        store 4 (or more) words
217 ;  Additions for Cirrus Maverick co-processor:
218 ; mav_farith    Floating point arithmetic (4 cycle)
219 ; mav_dmult     Double multiplies (7 cycle)
221 (define_attr "type"
222         "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" 
223         (if_then_else 
224          (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
225          (const_string "mult")
226          (const_string "alu")))
228 ; Load scheduling, set from the arm_ld_sched variable
229 ; initialized by arm_override_options() 
230 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
232 ; condition codes: this one is used by final_prescan_insn to speed up
233 ; conditionalizing instructions.  It saves having to scan the rtl to see if
234 ; it uses or alters the condition codes.
236 ; USE means that the condition codes are used by the insn in the process of
237 ;   outputting code, this means (at present) that we can't use the insn in
238 ;   inlined branches
240 ; SET means that the purpose of the insn is to set the condition codes in a
241 ;   well defined manner.
243 ; CLOB means that the condition codes are altered in an undefined manner, if
244 ;   they are altered at all
246 ; JUMP_CLOB is used when the condition cannot be represented by a single
247 ;   instruction (UNEQ and LTGT).  These cannot be predicated.
249 ; NOCOND means that the condition codes are neither altered nor affect the
250 ;   output of this insn
252 (define_attr "conds" "use,set,clob,jump_clob,nocond"
253         (if_then_else (eq_attr "type" "call")
254          (const_string "clob")
255          (const_string "nocond")))
257 ; Predicable means that the insn can be conditionally executed based on
258 ; an automatically added predicate (additional patterns are generated by 
259 ; gen...).  We default to 'no' because no Thumb patterns match this rule
260 ; and not all ARM patterns do.
261 (define_attr "predicable" "no,yes" (const_string "no"))
263 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
264 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
265 ; suffer blockages enough to warrant modelling this (and it can adversely
266 ; affect the schedule).
267 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
269 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
270 ; to stall the processor.  Used with model_wbuf above.
271 (define_attr "write_conflict" "no,yes"
272   (if_then_else (eq_attr "type"
273                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
274                 (const_string "yes")
275                 (const_string "no")))
277 ; Classify the insns into those that take one cycle and those that take more
278 ; than one on the main cpu execution unit.
279 (define_attr "core_cycles" "single,multi"
280   (if_then_else (eq_attr "type"
281                  "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
282                 (const_string "single")
283                 (const_string "multi")))
285 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
286 ;; distant label.  Only applicable to Thumb code.
287 (define_attr "far_jump" "yes,no" (const_string "no"))
289 ;;---------------------------------------------------------------------------
290 ;; Pipeline descriptions
292 ;; Processor type.  This is created automatically from arm-cores.def.
293 (include "arm-tune.md")
295 ;; True if the generic scheduling description should be used.
297 (define_attr "generic_sched" "yes,no"
298         (if_then_else 
299          (eq_attr "tune" "arm926ejs,arm1026ejs,arm1136js,arm1136jfs") 
300          (const_string "no")
301          (const_string "yes")))
302         
303 (include "arm-generic.md")
304 (include "arm926ejs.md")
305 (include "arm1026ejs.md")
306 (include "arm1136jfs.md")
309 ;;---------------------------------------------------------------------------
310 ;; Insn patterns
312 ;; Addition insns.
314 ;; Note: For DImode insns, there is normally no reason why operands should
315 ;; not be in the same register, what we don't want is for something being
316 ;; written to partially overlap something that is an input.
317 ;; Cirrus 64bit additions should not be split because we have a native
318 ;; 64bit addition instructions.
320 (define_expand "adddi3"
321  [(parallel
322    [(set (match_operand:DI           0 "s_register_operand" "")
323           (plus:DI (match_operand:DI 1 "s_register_operand" "")
324                    (match_operand:DI 2 "s_register_operand" "")))
325     (clobber (reg:CC CC_REGNUM))])]
326   "TARGET_EITHER"
327   "
328   if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
329     {
330       if (!cirrus_fp_register (operands[0], DImode))
331         operands[0] = force_reg (DImode, operands[0]);
332       if (!cirrus_fp_register (operands[1], DImode))
333         operands[1] = force_reg (DImode, operands[1]);
334       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
335       DONE;
336     }
338   if (TARGET_THUMB)
339     {
340       if (GET_CODE (operands[1]) != REG)
341         operands[1] = force_reg (SImode, operands[1]);
342       if (GET_CODE (operands[2]) != REG)
343         operands[2] = force_reg (SImode, operands[2]);
344      }
345   "
348 (define_insn "*thumb_adddi3"
349   [(set (match_operand:DI          0 "register_operand" "=l")
350         (plus:DI (match_operand:DI 1 "register_operand" "%0")
351                  (match_operand:DI 2 "register_operand" "l")))
352    (clobber (reg:CC CC_REGNUM))
353   ]
354   "TARGET_THUMB"
355   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
356   [(set_attr "length" "4")]
359 (define_insn_and_split "*arm_adddi3"
360   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
361         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
362                  (match_operand:DI 2 "s_register_operand" "r,  0")))
363    (clobber (reg:CC CC_REGNUM))]
364   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
365   "#"
366   "TARGET_ARM && reload_completed"
367   [(parallel [(set (reg:CC_C CC_REGNUM)
368                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
369                                  (match_dup 1)))
370               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
371    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
372                                (plus:SI (match_dup 4) (match_dup 5))))]
373   "
374   {
375     operands[3] = gen_highpart (SImode, operands[0]);
376     operands[0] = gen_lowpart (SImode, operands[0]);
377     operands[4] = gen_highpart (SImode, operands[1]);
378     operands[1] = gen_lowpart (SImode, operands[1]);
379     operands[5] = gen_highpart (SImode, operands[2]);
380     operands[2] = gen_lowpart (SImode, operands[2]);
381   }"
382   [(set_attr "conds" "clob")
383    (set_attr "length" "8")]
386 (define_insn_and_split "*adddi_sesidi_di"
387   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
388         (plus:DI (sign_extend:DI
389                   (match_operand:SI 2 "s_register_operand" "r,r"))
390                  (match_operand:DI 1 "s_register_operand" "r,0")))
391    (clobber (reg:CC CC_REGNUM))]
392   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
393   "#"
394   "TARGET_ARM && reload_completed"
395   [(parallel [(set (reg:CC_C CC_REGNUM)
396                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
397                                  (match_dup 1)))
398               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
399    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
400                                (plus:SI (ashiftrt:SI (match_dup 2)
401                                                      (const_int 31))
402                                         (match_dup 4))))]
403   "
404   {
405     operands[3] = gen_highpart (SImode, operands[0]);
406     operands[0] = gen_lowpart (SImode, operands[0]);
407     operands[4] = gen_highpart (SImode, operands[1]);
408     operands[1] = gen_lowpart (SImode, operands[1]);
409     operands[2] = gen_lowpart (SImode, operands[2]);
410   }"
411   [(set_attr "conds" "clob")
412    (set_attr "length" "8")]
415 (define_insn_and_split "*adddi_zesidi_di"
416   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
417         (plus:DI (zero_extend:DI
418                   (match_operand:SI 2 "s_register_operand" "r,r"))
419                  (match_operand:DI 1 "s_register_operand" "r,0")))
420    (clobber (reg:CC CC_REGNUM))]
421   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
422   "#"
423   "TARGET_ARM && reload_completed"
424   [(parallel [(set (reg:CC_C CC_REGNUM)
425                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
426                                  (match_dup 1)))
427               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
428    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
429                                (plus:SI (match_dup 4) (const_int 0))))]
430   "
431   {
432     operands[3] = gen_highpart (SImode, operands[0]);
433     operands[0] = gen_lowpart (SImode, operands[0]);
434     operands[4] = gen_highpart (SImode, operands[1]);
435     operands[1] = gen_lowpart (SImode, operands[1]);
436     operands[2] = gen_lowpart (SImode, operands[2]);
437   }"
438   [(set_attr "conds" "clob")
439    (set_attr "length" "8")]
442 (define_expand "addsi3"
443   [(set (match_operand:SI          0 "s_register_operand" "")
444         (plus:SI (match_operand:SI 1 "s_register_operand" "")
445                  (match_operand:SI 2 "reg_or_int_operand" "")))]
446   "TARGET_EITHER"
447   "
448   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
449     {
450       arm_split_constant (PLUS, SImode, NULL_RTX,
451                           INTVAL (operands[2]), operands[0], operands[1],
452                           optimize && !no_new_pseudos);
453       DONE;
454     }
455   "
458 ; If there is a scratch available, this will be faster than synthesizing the
459 ; addition.
460 (define_peephole2
461   [(match_scratch:SI 3 "r")
462    (set (match_operand:SI          0 "arm_general_register_operand" "")
463         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
464                  (match_operand:SI 2 "const_int_operand"  "")))]
465   "TARGET_ARM &&
466    !(const_ok_for_arm (INTVAL (operands[2]))
467      || const_ok_for_arm (-INTVAL (operands[2])))
468     && const_ok_for_arm (~INTVAL (operands[2]))"
469   [(set (match_dup 3) (match_dup 2))
470    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
471   ""
474 (define_insn_and_split "*arm_addsi3"
475   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
476         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
477                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
478   "TARGET_ARM"
479   "@
480    add%?\\t%0, %1, %2
481    sub%?\\t%0, %1, #%n2
482    #"
483   "TARGET_ARM &&
484    GET_CODE (operands[2]) == CONST_INT
485    && !(const_ok_for_arm (INTVAL (operands[2]))
486         || const_ok_for_arm (-INTVAL (operands[2])))"
487   [(clobber (const_int 0))]
488   "
489   arm_split_constant (PLUS, SImode, curr_insn,
490                       INTVAL (operands[2]), operands[0],
491                       operands[1], 0);
492   DONE;
493   "
494   [(set_attr "length" "4,4,16")
495    (set_attr "predicable" "yes")]
498 ;; Register group 'k' is a single register group containing only the stack
499 ;; register.  Trying to reload it will always fail catastrophically,
500 ;; so never allow those alternatives to match if reloading is needed.
502 (define_insn "*thumb_addsi3"
503   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
504         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
505                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
506   "TARGET_THUMB"
507   "*
508    static const char * const asms[] = 
509    {
510      \"add\\t%0, %0, %2\",
511      \"sub\\t%0, %0, #%n2\",
512      \"add\\t%0, %1, %2\",
513      \"add\\t%0, %0, %2\",
514      \"add\\t%0, %0, %2\",
515      \"add\\t%0, %1, %2\",
516      \"add\\t%0, %1, %2\"
517    };
518    if ((which_alternative == 2 || which_alternative == 6)
519        && GET_CODE (operands[2]) == CONST_INT
520        && INTVAL (operands[2]) < 0)
521      return \"sub\\t%0, %1, #%n2\";
522    return asms[which_alternative];
523   "
524   [(set_attr "length" "2")]
527 ;; Reloading and elimination of the frame pointer can
528 ;; sometimes cause this optimization to be missed.
529 (define_peephole2
530   [(set (match_operand:SI 0 "arm_general_register_operand" "")
531         (match_operand:SI 1 "const_int_operand" ""))
532    (set (match_dup 0)
533         (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
534   "TARGET_THUMB
535    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
536    && (INTVAL (operands[1]) & 3) == 0"
537   [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
538   ""
541 (define_insn "*addsi3_compare0"
542   [(set (reg:CC_NOOV CC_REGNUM)
543         (compare:CC_NOOV
544          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
545                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
546          (const_int 0)))
547    (set (match_operand:SI 0 "s_register_operand" "=r,r")
548         (plus:SI (match_dup 1) (match_dup 2)))]
549   "TARGET_ARM"
550   "@
551    add%?s\\t%0, %1, %2
552    sub%?s\\t%0, %1, #%n2"
553   [(set_attr "conds" "set")]
556 (define_insn "*addsi3_compare0_scratch"
557   [(set (reg:CC_NOOV CC_REGNUM)
558         (compare:CC_NOOV
559          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
560                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
561          (const_int 0)))]
562   "TARGET_ARM"
563   "@
564    cmn%?\\t%0, %1
565    cmp%?\\t%0, #%n1"
566   [(set_attr "conds" "set")]
569 ;; These patterns are the same ones as the two regular addsi3_compare0
570 ;; patterns, except we write them slightly different - the combiner
571 ;; tends to generate them this way.
572 (define_insn "*addsi3_compare0_for_combiner"
573   [(set (reg:CC CC_REGNUM)
574         (compare:CC
575          (match_operand:SI 1 "s_register_operand" "r,r")
576          (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
577    (set (match_operand:SI 0 "s_register_operand" "=r,r")
578         (plus:SI (match_dup 1) (match_dup 2)))]
579   "TARGET_ARM"
580   "@
581    add%?s\\t%0, %1, %2
582    sub%?s\\t%0, %1, #%n2"
583   [(set_attr "conds" "set")]
586 (define_insn "*addsi3_compare0_scratch_for_combiner"
587   [(set (reg:CC CC_REGNUM)
588         (compare:CC
589          (match_operand:SI 0 "s_register_operand" "r,r")
590          (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
591   "TARGET_ARM"
592   "@
593    cmn%?\\t%0, %1
594    cmp%?\\t%0, #%n1"
595   [(set_attr "conds" "set")]
598 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
599 ;; addend is a constant.
600 (define_insn "*cmpsi2_addneg"
601   [(set (reg:CC CC_REGNUM)
602         (compare:CC
603          (match_operand:SI 1 "s_register_operand" "r,r")
604          (match_operand:SI 2 "arm_addimm_operand" "I,L")))
605    (set (match_operand:SI 0 "s_register_operand" "=r,r")
606         (plus:SI (match_dup 1)
607                  (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
608   "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
609   "@
610    sub%?s\\t%0, %1, %2
611    add%?s\\t%0, %1, #%n2"
612   [(set_attr "conds" "set")]
615 ;; Convert the sequence
616 ;;  sub  rd, rn, #1
617 ;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
618 ;;  bne  dest
619 ;; into
620 ;;  subs rd, rn, #1
621 ;;  bcs  dest   ((unsigned)rn >= 1)
622 ;; similarly for the beq variant using bcc.
623 ;; This is a common looping idiom (while (n--))
624 (define_peephole2
625   [(set (match_operand:SI 0 "arm_general_register_operand" "")
626         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
627                  (const_int -1)))
628    (set (match_operand 2 "cc_register" "")
629         (compare (match_dup 0) (const_int -1)))
630    (set (pc)
631         (if_then_else (match_operator 3 "equality_operator"
632                        [(match_dup 2) (const_int 0)])
633                       (match_operand 4 "" "")
634                       (match_operand 5 "" "")))]
635   "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
636   [(parallel[
637     (set (match_dup 2)
638          (compare:CC
639           (match_dup 1) (const_int 1)))
640     (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
641    (set (pc)
642         (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
643                       (match_dup 4)
644                       (match_dup 5)))]
645   "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
646    operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
647                                   ? GEU : LTU),
648                                  VOIDmode, 
649                                  operands[2], const0_rtx);"
652 ;; The next four insns work because they compare the result with one of
653 ;; the operands, and we know that the use of the condition code is
654 ;; either GEU or LTU, so we can use the carry flag from the addition
655 ;; instead of doing the compare a second time.
656 (define_insn "*addsi3_compare_op1"
657   [(set (reg:CC_C CC_REGNUM)
658         (compare:CC_C
659          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
660                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
661          (match_dup 1)))
662    (set (match_operand:SI 0 "s_register_operand" "=r,r")
663         (plus:SI (match_dup 1) (match_dup 2)))]
664   "TARGET_ARM"
665   "@
666    add%?s\\t%0, %1, %2
667    sub%?s\\t%0, %1, #%n2"
668   [(set_attr "conds" "set")]
671 (define_insn "*addsi3_compare_op2"
672   [(set (reg:CC_C CC_REGNUM)
673         (compare:CC_C
674          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
675                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
676          (match_dup 2)))
677    (set (match_operand:SI 0 "s_register_operand" "=r,r")
678         (plus:SI (match_dup 1) (match_dup 2)))]
679   "TARGET_ARM"
680   "@
681    add%?s\\t%0, %1, %2
682    sub%?s\\t%0, %1, #%n2"
683   [(set_attr "conds" "set")]
686 (define_insn "*compare_addsi2_op0"
687   [(set (reg:CC_C CC_REGNUM)
688         (compare:CC_C
689          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
690                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
691          (match_dup 0)))]
692   "TARGET_ARM"
693   "@
694    cmn%?\\t%0, %1
695    cmp%?\\t%0, #%n1"
696   [(set_attr "conds" "set")]
699 (define_insn "*compare_addsi2_op1"
700   [(set (reg:CC_C CC_REGNUM)
701         (compare:CC_C
702          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
703                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
704          (match_dup 1)))]
705   "TARGET_ARM"
706   "@
707    cmn%?\\t%0, %1
708    cmp%?\\t%0, #%n1"
709   [(set_attr "conds" "set")]
712 (define_insn "*addsi3_carryin"
713   [(set (match_operand:SI 0 "s_register_operand" "=r")
714         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
715                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
716                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
717   "TARGET_ARM"
718   "adc%?\\t%0, %1, %2"
719   [(set_attr "conds" "use")]
722 (define_insn "*addsi3_carryin_shift"
723   [(set (match_operand:SI 0 "s_register_operand" "=r")
724         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
725                  (plus:SI
726                    (match_operator:SI 2 "shift_operator"
727                       [(match_operand:SI 3 "s_register_operand" "r")
728                        (match_operand:SI 4 "reg_or_int_operand" "rM")])
729                     (match_operand:SI 1 "s_register_operand" "r"))))]
730   "TARGET_ARM"
731   "adc%?\\t%0, %1, %3%S2"
732   [(set_attr "conds" "use")
733    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
734                       (const_string "alu_shift")
735                       (const_string "alu_shift_reg")))]
738 (define_insn "*addsi3_carryin_alt1"
739   [(set (match_operand:SI 0 "s_register_operand" "=r")
740         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
741                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
742                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
743   "TARGET_ARM"
744   "adc%?\\t%0, %1, %2"
745   [(set_attr "conds" "use")]
748 (define_insn "*addsi3_carryin_alt2"
749   [(set (match_operand:SI 0 "s_register_operand" "=r")
750         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
751                           (match_operand:SI 1 "s_register_operand" "r"))
752                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
753   "TARGET_ARM"
754   "adc%?\\t%0, %1, %2"
755   [(set_attr "conds" "use")]
758 (define_insn "*addsi3_carryin_alt3"
759   [(set (match_operand:SI 0 "s_register_operand" "=r")
760         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
761                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
762                  (match_operand:SI 1 "s_register_operand" "r")))]
763   "TARGET_ARM"
764   "adc%?\\t%0, %1, %2"
765   [(set_attr "conds" "use")]
768 (define_insn "incscc"
769   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
770         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
771                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
772                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
773   "TARGET_ARM"
774   "@
775   add%d2\\t%0, %1, #1
776   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
777   [(set_attr "conds" "use")
778    (set_attr "length" "4,8")]
781 ; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
782 (define_split
783   [(set (match_operand:SI 0 "s_register_operand" "")
784         (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
785                             (match_operand:SI 2 "s_register_operand" ""))
786                  (const_int -1)))
787    (clobber (match_operand:SI 3 "s_register_operand" ""))]
788   "TARGET_ARM"
789   [(set (match_dup 3) (match_dup 1))
790    (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
791   "
792   operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
795 (define_expand "addsf3"
796   [(set (match_operand:SF          0 "s_register_operand" "")
797         (plus:SF (match_operand:SF 1 "s_register_operand" "")
798                  (match_operand:SF 2 "arm_float_add_operand" "")))]
799   "TARGET_ARM && TARGET_HARD_FLOAT"
800   "
801   if (TARGET_MAVERICK
802       && !cirrus_fp_register (operands[2], SFmode))
803     operands[2] = force_reg (SFmode, operands[2]);
806 (define_expand "adddf3"
807   [(set (match_operand:DF          0 "s_register_operand" "")
808         (plus:DF (match_operand:DF 1 "s_register_operand" "")
809                  (match_operand:DF 2 "arm_float_add_operand" "")))]
810   "TARGET_ARM && TARGET_HARD_FLOAT"
811   "
812   if (TARGET_MAVERICK
813       && !cirrus_fp_register (operands[2], DFmode))
814     operands[2] = force_reg (DFmode, operands[2]);
817 (define_expand "subdi3"
818  [(parallel
819    [(set (match_operand:DI            0 "s_register_operand" "")
820           (minus:DI (match_operand:DI 1 "s_register_operand" "")
821                     (match_operand:DI 2 "s_register_operand" "")))
822     (clobber (reg:CC CC_REGNUM))])]
823   "TARGET_EITHER"
824   "
825   if (TARGET_HARD_FLOAT && TARGET_MAVERICK
826       && TARGET_ARM
827       && cirrus_fp_register (operands[0], DImode)
828       && cirrus_fp_register (operands[1], DImode))
829     {
830       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
831       DONE;
832     }
834   if (TARGET_THUMB)
835     {
836       if (GET_CODE (operands[1]) != REG)
837         operands[1] = force_reg (SImode, operands[1]);
838       if (GET_CODE (operands[2]) != REG)
839         operands[2] = force_reg (SImode, operands[2]);
840      }  
841   "
844 (define_insn "*arm_subdi3"
845   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
846         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
847                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
848    (clobber (reg:CC CC_REGNUM))]
849   "TARGET_ARM"
850   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
851   [(set_attr "conds" "clob")
852    (set_attr "length" "8")]
855 (define_insn "*thumb_subdi3"
856   [(set (match_operand:DI           0 "register_operand" "=l")
857         (minus:DI (match_operand:DI 1 "register_operand"  "0")
858                   (match_operand:DI 2 "register_operand"  "l")))
859    (clobber (reg:CC CC_REGNUM))]
860   "TARGET_THUMB"
861   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
862   [(set_attr "length" "4")]
865 (define_insn "*subdi_di_zesidi"
866   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
867         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
868                   (zero_extend:DI
869                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
870    (clobber (reg:CC CC_REGNUM))]
871   "TARGET_ARM"
872   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
873   [(set_attr "conds" "clob")
874    (set_attr "length" "8")]
877 (define_insn "*subdi_di_sesidi"
878   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
879         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
880                   (sign_extend:DI
881                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
882    (clobber (reg:CC CC_REGNUM))]
883   "TARGET_ARM"
884   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
885   [(set_attr "conds" "clob")
886    (set_attr "length" "8")]
889 (define_insn "*subdi_zesidi_di"
890   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
891         (minus:DI (zero_extend:DI
892                    (match_operand:SI 2 "s_register_operand"  "r,r"))
893                   (match_operand:DI  1 "s_register_operand" "?r,0")))
894    (clobber (reg:CC CC_REGNUM))]
895   "TARGET_ARM"
896   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
897   [(set_attr "conds" "clob")
898    (set_attr "length" "8")]
901 (define_insn "*subdi_sesidi_di"
902   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
903         (minus:DI (sign_extend:DI
904                    (match_operand:SI 2 "s_register_operand"   "r,r"))
905                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
906    (clobber (reg:CC CC_REGNUM))]
907   "TARGET_ARM"
908   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
909   [(set_attr "conds" "clob")
910    (set_attr "length" "8")]
913 (define_insn "*subdi_zesidi_zesidi"
914   [(set (match_operand:DI            0 "s_register_operand" "=r")
915         (minus:DI (zero_extend:DI
916                    (match_operand:SI 1 "s_register_operand"  "r"))
917                   (zero_extend:DI
918                    (match_operand:SI 2 "s_register_operand"  "r"))))
919    (clobber (reg:CC CC_REGNUM))]
920   "TARGET_ARM"
921   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
922   [(set_attr "conds" "clob")
923    (set_attr "length" "8")]
926 (define_expand "subsi3"
927   [(set (match_operand:SI           0 "s_register_operand" "")
928         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
929                   (match_operand:SI 2 "s_register_operand" "")))]
930   "TARGET_EITHER"
931   "
932   if (GET_CODE (operands[1]) == CONST_INT)
933     {
934       if (TARGET_ARM)
935         {
936           arm_split_constant (MINUS, SImode, NULL_RTX,
937                               INTVAL (operands[1]), operands[0],
938                               operands[2], optimize && !no_new_pseudos);
939           DONE;
940         }
941       else /* TARGET_THUMB */
942         operands[1] = force_reg (SImode, operands[1]);
943     }
944   "
947 (define_insn "*thumb_subsi3_insn"
948   [(set (match_operand:SI           0 "register_operand" "=l")
949         (minus:SI (match_operand:SI 1 "register_operand" "l")
950                   (match_operand:SI 2 "register_operand" "l")))]
951   "TARGET_THUMB"
952   "sub\\t%0, %1, %2"
953   [(set_attr "length" "2")]
956 (define_insn_and_split "*arm_subsi3_insn"
957   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
958         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
959                   (match_operand:SI 2 "s_register_operand" "r,r")))]
960   "TARGET_ARM"
961   "@
962    rsb%?\\t%0, %2, %1
963    #"
964   "TARGET_ARM
965    && GET_CODE (operands[1]) == CONST_INT
966    && !const_ok_for_arm (INTVAL (operands[1]))"
967   [(clobber (const_int 0))]
968   "
969   arm_split_constant (MINUS, SImode, curr_insn,
970                       INTVAL (operands[1]), operands[0], operands[2], 0);
971   DONE;
972   "
973   [(set_attr "length" "4,16")
974    (set_attr "predicable" "yes")]
977 (define_peephole2
978   [(match_scratch:SI 3 "r")
979    (set (match_operand:SI 0 "arm_general_register_operand" "")
980         (minus:SI (match_operand:SI 1 "const_int_operand" "")
981                   (match_operand:SI 2 "arm_general_register_operand" "")))]
982   "TARGET_ARM
983    && !const_ok_for_arm (INTVAL (operands[1]))
984    && const_ok_for_arm (~INTVAL (operands[1]))"
985   [(set (match_dup 3) (match_dup 1))
986    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
987   ""
990 (define_insn "*subsi3_compare0"
991   [(set (reg:CC_NOOV CC_REGNUM)
992         (compare:CC_NOOV
993          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
994                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
995          (const_int 0)))
996    (set (match_operand:SI 0 "s_register_operand" "=r,r")
997         (minus:SI (match_dup 1) (match_dup 2)))]
998   "TARGET_ARM"
999   "@
1000    sub%?s\\t%0, %1, %2
1001    rsb%?s\\t%0, %2, %1"
1002   [(set_attr "conds" "set")]
1005 (define_insn "decscc"
1006   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1007         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1008                   (match_operator:SI 2 "arm_comparison_operator"
1009                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1010   "TARGET_ARM"
1011   "@
1012    sub%d2\\t%0, %1, #1
1013    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1014   [(set_attr "conds" "use")
1015    (set_attr "length" "*,8")]
1018 (define_expand "subsf3"
1019   [(set (match_operand:SF           0 "s_register_operand" "")
1020         (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1021                   (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1022   "TARGET_ARM && TARGET_HARD_FLOAT"
1023   "
1024   if (TARGET_MAVERICK)
1025     {
1026       if (!cirrus_fp_register (operands[1], SFmode))
1027         operands[1] = force_reg (SFmode, operands[1]);
1028       if (!cirrus_fp_register (operands[2], SFmode))
1029         operands[2] = force_reg (SFmode, operands[2]);
1030     }
1033 (define_expand "subdf3"
1034   [(set (match_operand:DF           0 "s_register_operand" "")
1035         (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1036                   (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1037   "TARGET_ARM && TARGET_HARD_FLOAT"
1038   "
1039   if (TARGET_MAVERICK)
1040     {
1041        if (!cirrus_fp_register (operands[1], DFmode))
1042          operands[1] = force_reg (DFmode, operands[1]);
1043        if (!cirrus_fp_register (operands[2], DFmode))
1044          operands[2] = force_reg (DFmode, operands[2]);
1045     }
1049 ;; Multiplication insns
1051 (define_expand "mulsi3"
1052   [(set (match_operand:SI          0 "s_register_operand" "")
1053         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1054                  (match_operand:SI 1 "s_register_operand" "")))]
1055   "TARGET_EITHER"
1056   ""
1059 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1060 (define_insn "*arm_mulsi3"
1061   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1062         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1063                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1064   "TARGET_ARM"
1065   "mul%?\\t%0, %2, %1"
1066   [(set_attr "insn" "mul")
1067    (set_attr "predicable" "yes")]
1070 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1071 ; 1 and 2; are the same, because reload will make operand 0 match 
1072 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1073 ; this by adding another alternative to match this case, and then `reload' 
1074 ; it ourselves.  This alternative must come first.
1075 (define_insn "*thumb_mulsi3"
1076   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1077         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1078                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1079   "TARGET_THUMB"
1080   "*
1081   if (which_alternative < 2)
1082     return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1083   else
1084     return \"mul\\t%0, %0, %2\";
1085   "
1086   [(set_attr "length" "4,4,2")
1087    (set_attr "insn" "mul")]
1090 (define_insn "*mulsi3_compare0"
1091   [(set (reg:CC_NOOV CC_REGNUM)
1092         (compare:CC_NOOV (mult:SI
1093                           (match_operand:SI 2 "s_register_operand" "r,r")
1094                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1095                          (const_int 0)))
1096    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1097         (mult:SI (match_dup 2) (match_dup 1)))]
1098   "TARGET_ARM && !arm_arch_xscale"
1099   "mul%?s\\t%0, %2, %1"
1100   [(set_attr "conds" "set")
1101    (set_attr "insn" "muls")]
1104 (define_insn "*mulsi_compare0_scratch"
1105   [(set (reg:CC_NOOV CC_REGNUM)
1106         (compare:CC_NOOV (mult:SI
1107                           (match_operand:SI 2 "s_register_operand" "r,r")
1108                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1109                          (const_int 0)))
1110    (clobber (match_scratch:SI 0 "=&r,&r"))]
1111   "TARGET_ARM && !arm_arch_xscale"
1112   "mul%?s\\t%0, %2, %1"
1113   [(set_attr "conds" "set")
1114    (set_attr "insn" "muls")]
1117 ;; Unnamed templates to match MLA instruction.
1119 (define_insn "*mulsi3addsi"
1120   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1121         (plus:SI
1122           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1123                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1124           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1125   "TARGET_ARM"
1126   "mla%?\\t%0, %2, %1, %3"
1127   [(set_attr "insn" "mla")
1128    (set_attr "predicable" "yes")]
1131 (define_insn "*mulsi3addsi_compare0"
1132   [(set (reg:CC_NOOV CC_REGNUM)
1133         (compare:CC_NOOV
1134          (plus:SI (mult:SI
1135                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1136                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1137                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1138          (const_int 0)))
1139    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1140         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1141                  (match_dup 3)))]
1142   "TARGET_ARM && !arm_arch_xscale"
1143   "mla%?s\\t%0, %2, %1, %3"
1144   [(set_attr "conds" "set")
1145    (set_attr "insn" "mlas")]
1148 (define_insn "*mulsi3addsi_compare0_scratch"
1149   [(set (reg:CC_NOOV CC_REGNUM)
1150         (compare:CC_NOOV
1151          (plus:SI (mult:SI
1152                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1153                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1154                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1155          (const_int 0)))
1156    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1157   "TARGET_ARM && !arm_arch_xscale"
1158   "mla%?s\\t%0, %2, %1, %3"
1159   [(set_attr "conds" "set")
1160    (set_attr "insn" "mlas")]
1163 ;; Unnamed template to match long long multiply-accumulate (smlal)
1165 (define_insn "*mulsidi3adddi"
1166   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1167         (plus:DI
1168          (mult:DI
1169           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1170           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1171          (match_operand:DI 1 "s_register_operand" "0")))]
1172   "TARGET_ARM && arm_arch3m"
1173   "smlal%?\\t%Q0, %R0, %3, %2"
1174   [(set_attr "insn" "smlal")
1175    (set_attr "predicable" "yes")]
1178 (define_insn "mulsidi3"
1179   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1180         (mult:DI
1181          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1182          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1183   "TARGET_ARM && arm_arch3m"
1184   "smull%?\\t%Q0, %R0, %1, %2"
1185   [(set_attr "insn" "smull")
1186    (set_attr "predicable" "yes")]
1189 (define_insn "umulsidi3"
1190   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1191         (mult:DI
1192          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1193          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1194   "TARGET_ARM && arm_arch3m"
1195   "umull%?\\t%Q0, %R0, %1, %2"
1196   [(set_attr "insn" "umull")
1197    (set_attr "predicable" "yes")]
1200 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1202 (define_insn "*umulsidi3adddi"
1203   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1204         (plus:DI
1205          (mult:DI
1206           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1207           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1208          (match_operand:DI 1 "s_register_operand" "0")))]
1209   "TARGET_ARM && arm_arch3m"
1210   "umlal%?\\t%Q0, %R0, %3, %2"
1211   [(set_attr "insn" "umlal")
1212    (set_attr "predicable" "yes")]
1215 (define_insn "smulsi3_highpart"
1216   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1217         (truncate:SI
1218          (lshiftrt:DI
1219           (mult:DI
1220            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1221            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1222           (const_int 32))))
1223    (clobber (match_scratch:SI 3 "=&r,&r"))]
1224   "TARGET_ARM && arm_arch3m"
1225   "smull%?\\t%3, %0, %2, %1"
1226   [(set_attr "insn" "smull")
1227    (set_attr "predicable" "yes")]
1230 (define_insn "umulsi3_highpart"
1231   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1232         (truncate:SI
1233          (lshiftrt:DI
1234           (mult:DI
1235            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1236            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1237           (const_int 32))))
1238    (clobber (match_scratch:SI 3 "=&r,&r"))]
1239   "TARGET_ARM && arm_arch3m"
1240   "umull%?\\t%3, %0, %2, %1"
1241   [(set_attr "insn" "umull")
1242    (set_attr "predicable" "yes")]
1245 (define_insn "mulhisi3"
1246   [(set (match_operand:SI 0 "s_register_operand" "=r")
1247         (mult:SI (sign_extend:SI
1248                   (match_operand:HI 1 "s_register_operand" "%r"))
1249                  (sign_extend:SI
1250                   (match_operand:HI 2 "s_register_operand" "r"))))]
1251   "TARGET_ARM && arm_arch5e"
1252   "smulbb%?\\t%0, %1, %2"
1253   [(set_attr "insn" "smulxy")
1254    (set_attr "predicable" "yes")]
1257 (define_insn "*mulhisi3tb"
1258   [(set (match_operand:SI 0 "s_register_operand" "=r")
1259         (mult:SI (ashiftrt:SI
1260                   (match_operand:SI 1 "s_register_operand" "r")
1261                   (const_int 16))
1262                  (sign_extend:SI
1263                   (match_operand:HI 2 "s_register_operand" "r"))))]
1264   "TARGET_ARM && arm_arch5e"
1265   "smultb%?\\t%0, %1, %2"
1266   [(set_attr "insn" "smulxy")
1267    (set_attr "predicable" "yes")]
1270 (define_insn "*mulhisi3bt"
1271   [(set (match_operand:SI 0 "s_register_operand" "=r")
1272         (mult:SI (sign_extend:SI
1273                   (match_operand:HI 1 "s_register_operand" "r"))
1274                  (ashiftrt:SI
1275                   (match_operand:SI 2 "s_register_operand" "r")
1276                   (const_int 16))))]
1277   "TARGET_ARM && arm_arch5e"
1278   "smulbt%?\\t%0, %1, %2"
1279   [(set_attr "insn" "smulxy")
1280    (set_attr "predicable" "yes")]
1283 (define_insn "*mulhisi3tt"
1284   [(set (match_operand:SI 0 "s_register_operand" "=r")
1285         (mult:SI (ashiftrt:SI
1286                   (match_operand:SI 1 "s_register_operand" "r")
1287                   (const_int 16))
1288                  (ashiftrt:SI
1289                   (match_operand:SI 2 "s_register_operand" "r")
1290                   (const_int 16))))]
1291   "TARGET_ARM && arm_arch5e"
1292   "smultt%?\\t%0, %1, %2"
1293   [(set_attr "insn" "smulxy")
1294    (set_attr "predicable" "yes")]
1297 (define_insn "*mulhisi3addsi"
1298   [(set (match_operand:SI 0 "s_register_operand" "=r")
1299         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1300                  (mult:SI (sign_extend:SI
1301                            (match_operand:HI 2 "s_register_operand" "%r"))
1302                           (sign_extend:SI
1303                            (match_operand:HI 3 "s_register_operand" "r")))))]
1304   "TARGET_ARM && arm_arch5e"
1305   "smlabb%?\\t%0, %2, %3, %1"
1306   [(set_attr "insn" "smlaxy")
1307    (set_attr "predicable" "yes")]
1310 (define_insn "*mulhidi3adddi"
1311   [(set (match_operand:DI 0 "s_register_operand" "=r")
1312         (plus:DI
1313           (match_operand:DI 1 "s_register_operand" "0")
1314           (mult:DI (sign_extend:DI
1315                     (match_operand:HI 2 "s_register_operand" "%r"))
1316                    (sign_extend:DI
1317                     (match_operand:HI 3 "s_register_operand" "r")))))]
1318   "TARGET_ARM && arm_arch5e"
1319   "smlalbb%?\\t%Q0, %R0, %2, %3"
1320   [(set_attr "insn" "smlalxy")
1321    (set_attr "predicable" "yes")])
1323 (define_expand "mulsf3"
1324   [(set (match_operand:SF          0 "s_register_operand" "")
1325         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1326                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1327   "TARGET_ARM && TARGET_HARD_FLOAT"
1328   "
1329   if (TARGET_MAVERICK
1330       && !cirrus_fp_register (operands[2], SFmode))
1331     operands[2] = force_reg (SFmode, operands[2]);
1334 (define_expand "muldf3"
1335   [(set (match_operand:DF          0 "s_register_operand" "")
1336         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1337                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1338   "TARGET_ARM && TARGET_HARD_FLOAT"
1339   "
1340   if (TARGET_MAVERICK
1341       && !cirrus_fp_register (operands[2], DFmode))
1342     operands[2] = force_reg (DFmode, operands[2]);
1345 ;; Division insns
1347 (define_expand "divsf3"
1348   [(set (match_operand:SF 0 "s_register_operand" "")
1349         (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1350                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1351   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1352   "")
1354 (define_expand "divdf3"
1355   [(set (match_operand:DF 0 "s_register_operand" "")
1356         (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1357                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1358   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1359   "")
1361 ;; Modulo insns
1363 (define_expand "modsf3"
1364   [(set (match_operand:SF 0 "s_register_operand" "")
1365         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1366                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1367   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1368   "")
1370 (define_expand "moddf3"
1371   [(set (match_operand:DF 0 "s_register_operand" "")
1372         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1373                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1374   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1375   "")
1377 ;; Boolean and,ior,xor insns
1379 ;; Split up double word logical operations
1381 ;; Split up simple DImode logical operations.  Simply perform the logical
1382 ;; operation on the upper and lower halves of the registers.
1383 (define_split
1384   [(set (match_operand:DI 0 "s_register_operand" "")
1385         (match_operator:DI 6 "logical_binary_operator"
1386           [(match_operand:DI 1 "s_register_operand" "")
1387            (match_operand:DI 2 "s_register_operand" "")]))]
1388   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1389   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1390    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1391   "
1392   {
1393     operands[3] = gen_highpart (SImode, operands[0]);
1394     operands[0] = gen_lowpart (SImode, operands[0]);
1395     operands[4] = gen_highpart (SImode, operands[1]);
1396     operands[1] = gen_lowpart (SImode, operands[1]);
1397     operands[5] = gen_highpart (SImode, operands[2]);
1398     operands[2] = gen_lowpart (SImode, operands[2]);
1399   }"
1402 (define_split
1403   [(set (match_operand:DI 0 "s_register_operand" "")
1404         (match_operator:DI 6 "logical_binary_operator"
1405           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1406            (match_operand:DI 1 "s_register_operand" "")]))]
1407   "TARGET_ARM && reload_completed"
1408   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1409    (set (match_dup 3) (match_op_dup:SI 6
1410                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1411                          (match_dup 4)]))]
1412   "
1413   {
1414     operands[3] = gen_highpart (SImode, operands[0]);
1415     operands[0] = gen_lowpart (SImode, operands[0]);
1416     operands[4] = gen_highpart (SImode, operands[1]);
1417     operands[1] = gen_lowpart (SImode, operands[1]);
1418     operands[5] = gen_highpart (SImode, operands[2]);
1419     operands[2] = gen_lowpart (SImode, operands[2]);
1420   }"
1423 ;; The zero extend of operand 2 means we can just copy the high part of
1424 ;; operand1 into operand0.
1425 (define_split
1426   [(set (match_operand:DI 0 "s_register_operand" "")
1427         (ior:DI
1428           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1429           (match_operand:DI 1 "s_register_operand" "")))]
1430   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1431   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1432    (set (match_dup 3) (match_dup 4))]
1433   "
1434   {
1435     operands[4] = gen_highpart (SImode, operands[1]);
1436     operands[3] = gen_highpart (SImode, operands[0]);
1437     operands[0] = gen_lowpart (SImode, operands[0]);
1438     operands[1] = gen_lowpart (SImode, operands[1]);
1439   }"
1442 ;; The zero extend of operand 2 means we can just copy the high part of
1443 ;; operand1 into operand0.
1444 (define_split
1445   [(set (match_operand:DI 0 "s_register_operand" "")
1446         (xor:DI
1447           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1448           (match_operand:DI 1 "s_register_operand" "")))]
1449   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1450   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1451    (set (match_dup 3) (match_dup 4))]
1452   "
1453   {
1454     operands[4] = gen_highpart (SImode, operands[1]);
1455     operands[3] = gen_highpart (SImode, operands[0]);
1456     operands[0] = gen_lowpart (SImode, operands[0]);
1457     operands[1] = gen_lowpart (SImode, operands[1]);
1458   }"
1461 (define_insn "anddi3"
1462   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1463         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1464                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1465   "TARGET_ARM && ! TARGET_IWMMXT"
1466   "#"
1467   [(set_attr "length" "8")]
1470 (define_insn_and_split "*anddi_zesidi_di"
1471   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1472         (and:DI (zero_extend:DI
1473                  (match_operand:SI 2 "s_register_operand" "r,r"))
1474                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1475   "TARGET_ARM"
1476   "#"
1477   "TARGET_ARM && reload_completed"
1478   ; The zero extend of operand 2 clears the high word of the output
1479   ; operand.
1480   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1481    (set (match_dup 3) (const_int 0))]
1482   "
1483   {
1484     operands[3] = gen_highpart (SImode, operands[0]);
1485     operands[0] = gen_lowpart (SImode, operands[0]);
1486     operands[1] = gen_lowpart (SImode, operands[1]);
1487   }"
1488   [(set_attr "length" "8")]
1491 (define_insn "*anddi_sesdi_di"
1492   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1493         (and:DI (sign_extend:DI
1494                  (match_operand:SI 2 "s_register_operand" "r,r"))
1495                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1496   "TARGET_ARM"
1497   "#"
1498   [(set_attr "length" "8")]
1501 (define_expand "andsi3"
1502   [(set (match_operand:SI         0 "s_register_operand" "")
1503         (and:SI (match_operand:SI 1 "s_register_operand" "")
1504                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1505   "TARGET_EITHER"
1506   "
1507   if (TARGET_ARM)
1508     {
1509       if (GET_CODE (operands[2]) == CONST_INT)
1510         {
1511           arm_split_constant (AND, SImode, NULL_RTX,
1512                               INTVAL (operands[2]), operands[0],
1513                               operands[1], optimize && !no_new_pseudos);
1515           DONE;
1516         }
1517     }
1518   else /* TARGET_THUMB */
1519     {
1520       if (GET_CODE (operands[2]) != CONST_INT)
1521         operands[2] = force_reg (SImode, operands[2]);
1522       else
1523         {
1524           int i;
1525           
1526           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1527             {
1528               operands[2] = force_reg (SImode,
1529                                        GEN_INT (~INTVAL (operands[2])));
1530               
1531               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1532               
1533               DONE;
1534             }
1536           for (i = 9; i <= 31; i++)
1537             {
1538               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1539                 {
1540                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1541                                         const0_rtx));
1542                   DONE;
1543                 }
1544               else if ((((HOST_WIDE_INT) 1) << i) - 1
1545                        == ~INTVAL (operands[2]))
1546                 {
1547                   rtx shift = GEN_INT (i);
1548                   rtx reg = gen_reg_rtx (SImode);
1549                 
1550                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1551                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1552                   
1553                   DONE;
1554                 }
1555             }
1557           operands[2] = force_reg (SImode, operands[2]);
1558         }
1559     }
1560   "
1563 (define_insn_and_split "*arm_andsi3_insn"
1564   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1565         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1566                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1567   "TARGET_ARM"
1568   "@
1569    and%?\\t%0, %1, %2
1570    bic%?\\t%0, %1, #%B2
1571    #"
1572   "TARGET_ARM
1573    && GET_CODE (operands[2]) == CONST_INT
1574    && !(const_ok_for_arm (INTVAL (operands[2]))
1575         || const_ok_for_arm (~INTVAL (operands[2])))"
1576   [(clobber (const_int 0))]
1577   "
1578   arm_split_constant  (AND, SImode, curr_insn, 
1579                        INTVAL (operands[2]), operands[0], operands[1], 0);
1580   DONE;
1581   "
1582   [(set_attr "length" "4,4,16")
1583    (set_attr "predicable" "yes")]
1586 (define_insn "*thumb_andsi3_insn"
1587   [(set (match_operand:SI         0 "register_operand" "=l")
1588         (and:SI (match_operand:SI 1 "register_operand" "%0")
1589                 (match_operand:SI 2 "register_operand" "l")))]
1590   "TARGET_THUMB"
1591   "and\\t%0, %0, %2"
1592   [(set_attr "length" "2")]
1595 (define_insn "*andsi3_compare0"
1596   [(set (reg:CC_NOOV CC_REGNUM)
1597         (compare:CC_NOOV
1598          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1599                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1600          (const_int 0)))
1601    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1602         (and:SI (match_dup 1) (match_dup 2)))]
1603   "TARGET_ARM"
1604   "@
1605    and%?s\\t%0, %1, %2
1606    bic%?s\\t%0, %1, #%B2"
1607   [(set_attr "conds" "set")]
1610 (define_insn "*andsi3_compare0_scratch"
1611   [(set (reg:CC_NOOV CC_REGNUM)
1612         (compare:CC_NOOV
1613          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1614                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1615          (const_int 0)))
1616    (clobber (match_scratch:SI 2 "=X,r"))]
1617   "TARGET_ARM"
1618   "@
1619    tst%?\\t%0, %1
1620    bic%?s\\t%2, %0, #%B1"
1621   [(set_attr "conds" "set")]
1624 (define_insn "*zeroextractsi_compare0_scratch"
1625   [(set (reg:CC_NOOV CC_REGNUM)
1626         (compare:CC_NOOV (zero_extract:SI
1627                           (match_operand:SI 0 "s_register_operand" "r")
1628                           (match_operand 1 "const_int_operand" "n")
1629                           (match_operand 2 "const_int_operand" "n"))
1630                          (const_int 0)))]
1631   "TARGET_ARM
1632   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1633       && INTVAL (operands[1]) > 0 
1634       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1635       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1636   "*
1637   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1638                          << INTVAL (operands[2]));
1639   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1640   return \"\";
1641   "
1642   [(set_attr "conds" "set")]
1645 (define_insn_and_split "*ne_zeroextractsi"
1646   [(set (match_operand:SI 0 "s_register_operand" "=r")
1647         (ne:SI (zero_extract:SI
1648                 (match_operand:SI 1 "s_register_operand" "r")
1649                 (match_operand:SI 2 "const_int_operand" "n")
1650                 (match_operand:SI 3 "const_int_operand" "n"))
1651                (const_int 0)))
1652    (clobber (reg:CC CC_REGNUM))]
1653   "TARGET_ARM
1654    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1655        && INTVAL (operands[2]) > 0 
1656        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1657        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1658   "#"
1659   "TARGET_ARM
1660    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1661        && INTVAL (operands[2]) > 0 
1662        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1663        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1664   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1665                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1666                                     (const_int 0)))
1667               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1668    (set (match_dup 0)
1669         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1670                          (match_dup 0) (const_int 1)))]
1671   "
1672   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1673                          << INTVAL (operands[3])); 
1674   "
1675   [(set_attr "conds" "clob")
1676    (set_attr "length" "8")]
1679 (define_insn_and_split "*ne_zeroextractsi_shifted"
1680   [(set (match_operand:SI 0 "s_register_operand" "=r")
1681         (ne:SI (zero_extract:SI
1682                 (match_operand:SI 1 "s_register_operand" "r")
1683                 (match_operand:SI 2 "const_int_operand" "n")
1684                 (const_int 0))
1685                (const_int 0)))
1686    (clobber (reg:CC CC_REGNUM))]
1687   "TARGET_ARM"
1688   "#"
1689   "TARGET_ARM"
1690   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1691                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1692                                     (const_int 0)))
1693               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1694    (set (match_dup 0)
1695         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1696                          (match_dup 0) (const_int 1)))]
1697   "
1698   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1699   "
1700   [(set_attr "conds" "clob")
1701    (set_attr "length" "8")]
1704 (define_insn_and_split "*ite_ne_zeroextractsi"
1705   [(set (match_operand:SI 0 "s_register_operand" "=r")
1706         (if_then_else:SI (ne (zero_extract:SI
1707                               (match_operand:SI 1 "s_register_operand" "r")
1708                               (match_operand:SI 2 "const_int_operand" "n")
1709                               (match_operand:SI 3 "const_int_operand" "n"))
1710                              (const_int 0))
1711                          (match_operand:SI 4 "arm_not_operand" "rIK")
1712                          (const_int 0)))
1713    (clobber (reg:CC CC_REGNUM))]
1714   "TARGET_ARM
1715    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1716        && INTVAL (operands[2]) > 0 
1717        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1718        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1719    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1720   "#"
1721   "TARGET_ARM
1722    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1723        && INTVAL (operands[2]) > 0 
1724        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1725        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1726    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1727   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1728                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1729                                     (const_int 0)))
1730               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1731    (set (match_dup 0)
1732         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1733                          (match_dup 0) (match_dup 4)))]
1734   "
1735   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1736                          << INTVAL (operands[3])); 
1737   "
1738   [(set_attr "conds" "clob")
1739    (set_attr "length" "8")]
1742 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1743   [(set (match_operand:SI 0 "s_register_operand" "=r")
1744         (if_then_else:SI (ne (zero_extract:SI
1745                               (match_operand:SI 1 "s_register_operand" "r")
1746                               (match_operand:SI 2 "const_int_operand" "n")
1747                               (const_int 0))
1748                              (const_int 0))
1749                          (match_operand:SI 3 "arm_not_operand" "rIK")
1750                          (const_int 0)))
1751    (clobber (reg:CC CC_REGNUM))]
1752   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1753   "#"
1754   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1755   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1756                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1757                                     (const_int 0)))
1758               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1759    (set (match_dup 0)
1760         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1761                          (match_dup 0) (match_dup 3)))]
1762   "
1763   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1764   "
1765   [(set_attr "conds" "clob")
1766    (set_attr "length" "8")]
1769 (define_split
1770   [(set (match_operand:SI 0 "s_register_operand" "")
1771         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1772                          (match_operand:SI 2 "const_int_operand" "")
1773                          (match_operand:SI 3 "const_int_operand" "")))
1774    (clobber (match_operand:SI 4 "s_register_operand" ""))]
1775   "TARGET_THUMB"
1776   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1777    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1778   "{
1779      HOST_WIDE_INT temp = INTVAL (operands[2]);
1781      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1782      operands[3] = GEN_INT (32 - temp);
1783    }"
1786 (define_split
1787   [(set (match_operand:SI 0 "s_register_operand" "")
1788         (match_operator:SI 1 "shiftable_operator"
1789          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1790                            (match_operand:SI 3 "const_int_operand" "")
1791                            (match_operand:SI 4 "const_int_operand" ""))
1792           (match_operand:SI 5 "s_register_operand" "")]))
1793    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1794   "TARGET_ARM"
1795   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1796    (set (match_dup 0)
1797         (match_op_dup 1
1798          [(lshiftrt:SI (match_dup 6) (match_dup 4))
1799           (match_dup 5)]))]
1800   "{
1801      HOST_WIDE_INT temp = INTVAL (operands[3]);
1803      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1804      operands[4] = GEN_INT (32 - temp);
1805    }"
1807   
1808 (define_split
1809   [(set (match_operand:SI 0 "s_register_operand" "")
1810         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1811                          (match_operand:SI 2 "const_int_operand" "")
1812                          (match_operand:SI 3 "const_int_operand" "")))]
1813   "TARGET_THUMB"
1814   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1815    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1816   "{
1817      HOST_WIDE_INT temp = INTVAL (operands[2]);
1819      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1820      operands[3] = GEN_INT (32 - temp);
1821    }"
1824 (define_split
1825   [(set (match_operand:SI 0 "s_register_operand" "")
1826         (match_operator:SI 1 "shiftable_operator"
1827          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1828                            (match_operand:SI 3 "const_int_operand" "")
1829                            (match_operand:SI 4 "const_int_operand" ""))
1830           (match_operand:SI 5 "s_register_operand" "")]))
1831    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1832   "TARGET_ARM"
1833   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1834    (set (match_dup 0)
1835         (match_op_dup 1
1836          [(ashiftrt:SI (match_dup 6) (match_dup 4))
1837           (match_dup 5)]))]
1838   "{
1839      HOST_WIDE_INT temp = INTVAL (operands[3]);
1841      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1842      operands[4] = GEN_INT (32 - temp);
1843    }"
1845   
1846 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1847 ;;; represented by the bitfield, then this will produce incorrect results.
1848 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1849 ;;; which have a real bit-field insert instruction, the truncation happens
1850 ;;; in the bit-field insert instruction itself.  Since arm does not have a
1851 ;;; bit-field insert instruction, we would have to emit code here to truncate
1852 ;;; the value before we insert.  This loses some of the advantage of having
1853 ;;; this insv pattern, so this pattern needs to be reevalutated.
1855 (define_expand "insv"
1856   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1857                          (match_operand:SI 1 "general_operand" "")
1858                          (match_operand:SI 2 "general_operand" ""))
1859         (match_operand:SI 3 "reg_or_int_operand" ""))]
1860   "TARGET_ARM"
1861   "
1862   {
1863     int start_bit = INTVAL (operands[2]);
1864     int width = INTVAL (operands[1]);
1865     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1866     rtx target, subtarget;
1868     target = operands[0];
1869     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1870        subreg as the final target.  */
1871     if (GET_CODE (target) == SUBREG)
1872       {
1873         subtarget = gen_reg_rtx (SImode);
1874         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1875             < GET_MODE_SIZE (SImode))
1876           target = SUBREG_REG (target);
1877       }
1878     else
1879       subtarget = target;    
1881     if (GET_CODE (operands[3]) == CONST_INT)
1882       {
1883         /* Since we are inserting a known constant, we may be able to
1884            reduce the number of bits that we have to clear so that
1885            the mask becomes simple.  */
1886         /* ??? This code does not check to see if the new mask is actually
1887            simpler.  It may not be.  */
1888         rtx op1 = gen_reg_rtx (SImode);
1889         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1890            start of this pattern.  */
1891         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1892         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1894         emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1895         emit_insn (gen_iorsi3 (subtarget, op1,
1896                                GEN_INT (op3_value << start_bit)));
1897       }
1898     else if (start_bit == 0
1899              && !(const_ok_for_arm (mask)
1900                   || const_ok_for_arm (~mask)))
1901       {
1902         /* A Trick, since we are setting the bottom bits in the word,
1903            we can shift operand[3] up, operand[0] down, OR them together
1904            and rotate the result back again.  This takes 3 insns, and
1905            the third might be mergeable into another op.  */
1906         /* The shift up copes with the possibility that operand[3] is
1907            wider than the bitfield.  */
1908         rtx op0 = gen_reg_rtx (SImode);
1909         rtx op1 = gen_reg_rtx (SImode);
1911         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1912         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1913         emit_insn (gen_iorsi3  (op1, op1, op0));
1914         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1915       }
1916     else if ((width + start_bit == 32)
1917              && !(const_ok_for_arm (mask)
1918                   || const_ok_for_arm (~mask)))
1919       {
1920         /* Similar trick, but slightly less efficient.  */
1922         rtx op0 = gen_reg_rtx (SImode);
1923         rtx op1 = gen_reg_rtx (SImode);
1925         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1926         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1927         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1928         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1929       }
1930     else
1931       {
1932         rtx op0 = GEN_INT (mask);
1933         rtx op1 = gen_reg_rtx (SImode);
1934         rtx op2 = gen_reg_rtx (SImode);
1936         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1937           {
1938             rtx tmp = gen_reg_rtx (SImode);
1940             emit_insn (gen_movsi (tmp, op0));
1941             op0 = tmp;
1942           }
1944         /* Mask out any bits in operand[3] that are not needed.  */
1945            emit_insn (gen_andsi3 (op1, operands[3], op0));
1947         if (GET_CODE (op0) == CONST_INT
1948             && (const_ok_for_arm (mask << start_bit)
1949                 || const_ok_for_arm (~(mask << start_bit))))
1950           {
1951             op0 = GEN_INT (~(mask << start_bit));
1952             emit_insn (gen_andsi3 (op2, operands[0], op0));
1953           }
1954         else
1955           {
1956             if (GET_CODE (op0) == CONST_INT)
1957               {
1958                 rtx tmp = gen_reg_rtx (SImode);
1960                 emit_insn (gen_movsi (tmp, op0));
1961                 op0 = tmp;
1962               }
1964             if (start_bit != 0)
1965               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1966             
1967             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1968           }
1970         if (start_bit != 0)
1971           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1973         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1974       }
1976     if (subtarget != target)
1977       {
1978         /* If TARGET is still a SUBREG, then it must be wider than a word,
1979            so we must be careful only to set the subword we were asked to.  */
1980         if (GET_CODE (target) == SUBREG)
1981           emit_move_insn (target, subtarget);
1982         else
1983           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1984       }
1986     DONE;
1987   }"
1990 ; constants for op 2 will never be given to these patterns.
1991 (define_insn_and_split "*anddi_notdi_di"
1992   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1993         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1994                 (match_operand:DI 2 "s_register_operand" "0,r")))]
1995   "TARGET_ARM"
1996   "#"
1997   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1998   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1999    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2000   "
2001   {
2002     operands[3] = gen_highpart (SImode, operands[0]);
2003     operands[0] = gen_lowpart (SImode, operands[0]);
2004     operands[4] = gen_highpart (SImode, operands[1]);
2005     operands[1] = gen_lowpart (SImode, operands[1]);
2006     operands[5] = gen_highpart (SImode, operands[2]);
2007     operands[2] = gen_lowpart (SImode, operands[2]);
2008   }"
2009   [(set_attr "length" "8")
2010    (set_attr "predicable" "yes")]
2012   
2013 (define_insn_and_split "*anddi_notzesidi_di"
2014   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2015         (and:DI (not:DI (zero_extend:DI
2016                          (match_operand:SI 2 "s_register_operand" "r,r")))
2017                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2018   "TARGET_ARM"
2019   "@
2020    bic%?\\t%Q0, %Q1, %2
2021    #"
2022   ; (not (zero_extend ...)) allows us to just copy the high word from
2023   ; operand1 to operand0.
2024   "TARGET_ARM
2025    && reload_completed
2026    && operands[0] != operands[1]"
2027   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2028    (set (match_dup 3) (match_dup 4))]
2029   "
2030   {
2031     operands[3] = gen_highpart (SImode, operands[0]);
2032     operands[0] = gen_lowpart (SImode, operands[0]);
2033     operands[4] = gen_highpart (SImode, operands[1]);
2034     operands[1] = gen_lowpart (SImode, operands[1]);
2035   }"
2036   [(set_attr "length" "4,8")
2037    (set_attr "predicable" "yes")]
2039   
2040 (define_insn_and_split "*anddi_notsesidi_di"
2041   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2042         (and:DI (not:DI (sign_extend:DI
2043                          (match_operand:SI 2 "s_register_operand" "r,r")))
2044                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2045   "TARGET_ARM"
2046   "#"
2047   "TARGET_ARM && reload_completed"
2048   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2049    (set (match_dup 3) (and:SI (not:SI
2050                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2051                                (match_dup 4)))]
2052   "
2053   {
2054     operands[3] = gen_highpart (SImode, operands[0]);
2055     operands[0] = gen_lowpart (SImode, operands[0]);
2056     operands[4] = gen_highpart (SImode, operands[1]);
2057     operands[1] = gen_lowpart (SImode, operands[1]);
2058   }"
2059   [(set_attr "length" "8")
2060    (set_attr "predicable" "yes")]
2062   
2063 (define_insn "andsi_notsi_si"
2064   [(set (match_operand:SI 0 "s_register_operand" "=r")
2065         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2066                 (match_operand:SI 1 "s_register_operand" "r")))]
2067   "TARGET_ARM"
2068   "bic%?\\t%0, %1, %2"
2069   [(set_attr "predicable" "yes")]
2072 (define_insn "bicsi3"
2073   [(set (match_operand:SI                 0 "register_operand" "=l")
2074         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2075                 (match_operand:SI         2 "register_operand" "0")))]
2076   "TARGET_THUMB"
2077   "bic\\t%0, %0, %1"
2078   [(set_attr "length" "2")]
2081 (define_insn "andsi_not_shiftsi_si"
2082   [(set (match_operand:SI 0 "s_register_operand" "=r")
2083         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2084                          [(match_operand:SI 2 "s_register_operand" "r")
2085                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2086                 (match_operand:SI 1 "s_register_operand" "r")))]
2087   "TARGET_ARM"
2088   "bic%?\\t%0, %1, %2%S4"
2089   [(set_attr "predicable" "yes")
2090    (set_attr "shift" "2")
2091    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2092                       (const_string "alu_shift")
2093                       (const_string "alu_shift_reg")))]
2096 (define_insn "*andsi_notsi_si_compare0"
2097   [(set (reg:CC_NOOV CC_REGNUM)
2098         (compare:CC_NOOV
2099          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2100                  (match_operand:SI 1 "s_register_operand" "r"))
2101          (const_int 0)))
2102    (set (match_operand:SI 0 "s_register_operand" "=r")
2103         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2104   "TARGET_ARM"
2105   "bic%?s\\t%0, %1, %2"
2106   [(set_attr "conds" "set")]
2109 (define_insn "*andsi_notsi_si_compare0_scratch"
2110   [(set (reg:CC_NOOV CC_REGNUM)
2111         (compare:CC_NOOV
2112          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2113                  (match_operand:SI 1 "s_register_operand" "r"))
2114          (const_int 0)))
2115    (clobber (match_scratch:SI 0 "=r"))]
2116   "TARGET_ARM"
2117   "bic%?s\\t%0, %1, %2"
2118   [(set_attr "conds" "set")]
2121 (define_insn "iordi3"
2122   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2123         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2124                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2125   "TARGET_ARM && ! TARGET_IWMMXT"
2126   "#"
2127   [(set_attr "length" "8")
2128    (set_attr "predicable" "yes")]
2131 (define_insn "*iordi_zesidi_di"
2132   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2133         (ior:DI (zero_extend:DI
2134                  (match_operand:SI 2 "s_register_operand" "r,r"))
2135                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2136   "TARGET_ARM"
2137   "@
2138    orr%?\\t%Q0, %Q1, %2
2139    #"
2140   [(set_attr "length" "4,8")
2141    (set_attr "predicable" "yes")]
2144 (define_insn "*iordi_sesidi_di"
2145   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2146         (ior:DI (sign_extend:DI
2147                  (match_operand:SI 2 "s_register_operand" "r,r"))
2148                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2149   "TARGET_ARM"
2150   "#"
2151   [(set_attr "length" "8")
2152    (set_attr "predicable" "yes")]
2155 (define_expand "iorsi3"
2156   [(set (match_operand:SI         0 "s_register_operand" "")
2157         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2158                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2159   "TARGET_EITHER"
2160   "
2161   if (GET_CODE (operands[2]) == CONST_INT)
2162     {
2163       if (TARGET_ARM)
2164         {
2165           arm_split_constant (IOR, SImode, NULL_RTX,
2166                               INTVAL (operands[2]), operands[0], operands[1],
2167                               optimize && !no_new_pseudos);
2168           DONE;
2169         }
2170       else /* TARGET_THUMB */
2171         operands [2] = force_reg (SImode, operands [2]);
2172     }
2173   "
2176 (define_insn_and_split "*arm_iorsi3"
2177   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2178         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2179                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2180   "TARGET_ARM"
2181   "@
2182    orr%?\\t%0, %1, %2
2183    #"
2184   "TARGET_ARM
2185    && GET_CODE (operands[2]) == CONST_INT
2186    && !const_ok_for_arm (INTVAL (operands[2]))"
2187   [(clobber (const_int 0))]
2188   "
2189   arm_split_constant (IOR, SImode, curr_insn, 
2190                       INTVAL (operands[2]), operands[0], operands[1], 0);
2191   DONE;
2192   "
2193   [(set_attr "length" "4,16")
2194    (set_attr "predicable" "yes")]
2197 (define_insn "*thumb_iorsi3"
2198   [(set (match_operand:SI         0 "register_operand" "=l")
2199         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2200                 (match_operand:SI 2 "register_operand" "l")))]
2201   "TARGET_THUMB"
2202   "orr\\t%0, %0, %2"
2203   [(set_attr "length" "2")]
2206 (define_peephole2
2207   [(match_scratch:SI 3 "r")
2208    (set (match_operand:SI 0 "arm_general_register_operand" "")
2209         (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2210                 (match_operand:SI 2 "const_int_operand" "")))]
2211   "TARGET_ARM
2212    && !const_ok_for_arm (INTVAL (operands[2]))
2213    && const_ok_for_arm (~INTVAL (operands[2]))"
2214   [(set (match_dup 3) (match_dup 2))
2215    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2216   ""
2219 (define_insn "*iorsi3_compare0"
2220   [(set (reg:CC_NOOV CC_REGNUM)
2221         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2222                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2223                          (const_int 0)))
2224    (set (match_operand:SI 0 "s_register_operand" "=r")
2225         (ior:SI (match_dup 1) (match_dup 2)))]
2226   "TARGET_ARM"
2227   "orr%?s\\t%0, %1, %2"
2228   [(set_attr "conds" "set")]
2231 (define_insn "*iorsi3_compare0_scratch"
2232   [(set (reg:CC_NOOV CC_REGNUM)
2233         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2234                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2235                          (const_int 0)))
2236    (clobber (match_scratch:SI 0 "=r"))]
2237   "TARGET_ARM"
2238   "orr%?s\\t%0, %1, %2"
2239   [(set_attr "conds" "set")]
2242 (define_insn "xordi3"
2243   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2244         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2245                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2246   "TARGET_ARM && !TARGET_IWMMXT"
2247   "#"
2248   [(set_attr "length" "8")
2249    (set_attr "predicable" "yes")]
2252 (define_insn "*xordi_zesidi_di"
2253   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2254         (xor:DI (zero_extend:DI
2255                  (match_operand:SI 2 "s_register_operand" "r,r"))
2256                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2257   "TARGET_ARM"
2258   "@
2259    eor%?\\t%Q0, %Q1, %2
2260    #"
2261   [(set_attr "length" "4,8")
2262    (set_attr "predicable" "yes")]
2265 (define_insn "*xordi_sesidi_di"
2266   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2267         (xor:DI (sign_extend:DI
2268                  (match_operand:SI 2 "s_register_operand" "r,r"))
2269                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2270   "TARGET_ARM"
2271   "#"
2272   [(set_attr "length" "8")
2273    (set_attr "predicable" "yes")]
2276 (define_expand "xorsi3"
2277   [(set (match_operand:SI         0 "s_register_operand" "")
2278         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2279                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2280   "TARGET_EITHER"
2281   "if (TARGET_THUMB)
2282      if (GET_CODE (operands[2]) == CONST_INT)
2283        operands[2] = force_reg (SImode, operands[2]);
2284   "
2287 (define_insn "*arm_xorsi3"
2288   [(set (match_operand:SI         0 "s_register_operand" "=r")
2289         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2290                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2291   "TARGET_ARM"
2292   "eor%?\\t%0, %1, %2"
2293   [(set_attr "predicable" "yes")]
2296 (define_insn "*thumb_xorsi3"
2297   [(set (match_operand:SI         0 "register_operand" "=l")
2298         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2299                 (match_operand:SI 2 "register_operand" "l")))]
2300   "TARGET_THUMB"
2301   "eor\\t%0, %0, %2"
2302   [(set_attr "length" "2")]
2305 (define_insn "*xorsi3_compare0"
2306   [(set (reg:CC_NOOV CC_REGNUM)
2307         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2308                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2309                          (const_int 0)))
2310    (set (match_operand:SI 0 "s_register_operand" "=r")
2311         (xor:SI (match_dup 1) (match_dup 2)))]
2312   "TARGET_ARM"
2313   "eor%?s\\t%0, %1, %2"
2314   [(set_attr "conds" "set")]
2317 (define_insn "*xorsi3_compare0_scratch"
2318   [(set (reg:CC_NOOV CC_REGNUM)
2319         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2320                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2321                          (const_int 0)))]
2322   "TARGET_ARM"
2323   "teq%?\\t%0, %1"
2324   [(set_attr "conds" "set")]
2327 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2328 ; (NOT D) we can sometimes merge the final NOT into one of the following
2329 ; insns.
2331 (define_split
2332   [(set (match_operand:SI 0 "s_register_operand" "")
2333         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2334                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2335                 (match_operand:SI 3 "arm_rhs_operand" "")))
2336    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2337   "TARGET_ARM"
2338   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2339                               (not:SI (match_dup 3))))
2340    (set (match_dup 0) (not:SI (match_dup 4)))]
2341   ""
2344 (define_insn "*andsi_iorsi3_notsi"
2345   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2346         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2347                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2348                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2349   "TARGET_ARM"
2350   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2351   [(set_attr "length" "8")
2352    (set_attr "predicable" "yes")]
2355 (define_split
2356   [(set (match_operand:SI 0 "s_register_operand" "")
2357         (match_operator:SI 1 "logical_binary_operator"
2358          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2359                            (match_operand:SI 3 "const_int_operand" "")
2360                            (match_operand:SI 4 "const_int_operand" ""))
2361           (match_operator:SI 9 "logical_binary_operator"
2362            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2363                          (match_operand:SI 6 "const_int_operand" ""))
2364             (match_operand:SI 7 "s_register_operand" "")])]))
2365    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2366   "TARGET_ARM
2367    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2368    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2369   [(set (match_dup 8)
2370         (match_op_dup 1
2371          [(ashift:SI (match_dup 2) (match_dup 4))
2372           (match_dup 5)]))
2373    (set (match_dup 0)
2374         (match_op_dup 1
2375          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2376           (match_dup 7)]))]
2377   "
2378   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2381 (define_split
2382   [(set (match_operand:SI 0 "s_register_operand" "")
2383         (match_operator:SI 1 "logical_binary_operator"
2384          [(match_operator:SI 9 "logical_binary_operator"
2385            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2386                          (match_operand:SI 6 "const_int_operand" ""))
2387             (match_operand:SI 7 "s_register_operand" "")])
2388           (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2389                            (match_operand:SI 3 "const_int_operand" "")
2390                            (match_operand:SI 4 "const_int_operand" ""))]))
2391    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2392   "TARGET_ARM
2393    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2394    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2395   [(set (match_dup 8)
2396         (match_op_dup 1
2397          [(ashift:SI (match_dup 2) (match_dup 4))
2398           (match_dup 5)]))
2399    (set (match_dup 0)
2400         (match_op_dup 1
2401          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2402           (match_dup 7)]))]
2403   "
2404   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2407 (define_split
2408   [(set (match_operand:SI 0 "s_register_operand" "")
2409         (match_operator:SI 1 "logical_binary_operator"
2410          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2411                            (match_operand:SI 3 "const_int_operand" "")
2412                            (match_operand:SI 4 "const_int_operand" ""))
2413           (match_operator:SI 9 "logical_binary_operator"
2414            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2415                          (match_operand:SI 6 "const_int_operand" ""))
2416             (match_operand:SI 7 "s_register_operand" "")])]))
2417    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2418   "TARGET_ARM
2419    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2420    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2421   [(set (match_dup 8)
2422         (match_op_dup 1
2423          [(ashift:SI (match_dup 2) (match_dup 4))
2424           (match_dup 5)]))
2425    (set (match_dup 0)
2426         (match_op_dup 1
2427          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2428           (match_dup 7)]))]
2429   "
2430   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2433 (define_split
2434   [(set (match_operand:SI 0 "s_register_operand" "")
2435         (match_operator:SI 1 "logical_binary_operator"
2436          [(match_operator:SI 9 "logical_binary_operator"
2437            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2438                          (match_operand:SI 6 "const_int_operand" ""))
2439             (match_operand:SI 7 "s_register_operand" "")])
2440           (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2441                            (match_operand:SI 3 "const_int_operand" "")
2442                            (match_operand:SI 4 "const_int_operand" ""))]))
2443    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2444   "TARGET_ARM
2445    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2446    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2447   [(set (match_dup 8)
2448         (match_op_dup 1
2449          [(ashift:SI (match_dup 2) (match_dup 4))
2450           (match_dup 5)]))
2451    (set (match_dup 0)
2452         (match_op_dup 1
2453          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2454           (match_dup 7)]))]
2455   "
2456   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2460 ;; Minimum and maximum insns
2462 (define_insn "smaxsi3"
2463   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2464         (smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2465                  (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2466    (clobber (reg:CC CC_REGNUM))]
2467   "TARGET_ARM"
2468   "@
2469    cmp\\t%1, %2\;movlt\\t%0, %2
2470    cmp\\t%1, %2\;movge\\t%0, %1
2471    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2472   [(set_attr "conds" "clob")
2473    (set_attr "length" "8,8,12")]
2476 (define_insn "sminsi3"
2477   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2478         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2479                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2480    (clobber (reg:CC CC_REGNUM))]
2481   "TARGET_ARM"
2482   "@
2483    cmp\\t%1, %2\;movge\\t%0, %2
2484    cmp\\t%1, %2\;movlt\\t%0, %1
2485    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2486   [(set_attr "conds" "clob")
2487    (set_attr "length" "8,8,12")]
2490 (define_insn "umaxsi3"
2491   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2492         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2493                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2494    (clobber (reg:CC CC_REGNUM))]
2495   "TARGET_ARM"
2496   "@
2497    cmp\\t%1, %2\;movcc\\t%0, %2
2498    cmp\\t%1, %2\;movcs\\t%0, %1
2499    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2500   [(set_attr "conds" "clob")
2501    (set_attr "length" "8,8,12")]
2504 (define_insn "uminsi3"
2505   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2506         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2507                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2508    (clobber (reg:CC CC_REGNUM))]
2509   "TARGET_ARM"
2510   "@
2511    cmp\\t%1, %2\;movcs\\t%0, %2
2512    cmp\\t%1, %2\;movcc\\t%0, %1
2513    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2514   [(set_attr "conds" "clob")
2515    (set_attr "length" "8,8,12")]
2518 (define_insn "*store_minmaxsi"
2519   [(set (match_operand:SI 0 "memory_operand" "=m")
2520         (match_operator:SI 3 "minmax_operator"
2521          [(match_operand:SI 1 "s_register_operand" "r")
2522           (match_operand:SI 2 "s_register_operand" "r")]))
2523    (clobber (reg:CC CC_REGNUM))]
2524   "TARGET_ARM"
2525   "*
2526   operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2527                                 operands[1], operands[2]);
2528   output_asm_insn (\"cmp\\t%1, %2\", operands);
2529   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2530   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2531   return \"\";
2532   "
2533   [(set_attr "conds" "clob")
2534    (set_attr "length" "12")
2535    (set_attr "type" "store1")]
2538 ; Reject the frame pointer in operand[1], since reloading this after
2539 ; it has been eliminated can cause carnage.
2540 (define_insn "*minmax_arithsi"
2541   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2542         (match_operator:SI 4 "shiftable_operator"
2543          [(match_operator:SI 5 "minmax_operator"
2544            [(match_operand:SI 2 "s_register_operand" "r,r")
2545             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2546           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2547    (clobber (reg:CC CC_REGNUM))]
2548   "TARGET_ARM
2549    && (GET_CODE (operands[1]) != REG
2550        || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2551            && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2552   "*
2553   {
2554     enum rtx_code code = GET_CODE (operands[4]);
2556     operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2557                                   operands[2], operands[3]);
2558     output_asm_insn (\"cmp\\t%2, %3\", operands);
2559     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2560     if (which_alternative != 0 || operands[3] != const0_rtx
2561         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2562       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2563     return \"\";
2564   }"
2565   [(set_attr "conds" "clob")
2566    (set_attr "length" "12")]
2570 ;; Shift and rotation insns
2572 (define_expand "ashldi3"
2573   [(set (match_operand:DI            0 "s_register_operand" "")
2574         (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2575                    (match_operand:SI 2 "reg_or_int_operand" "")))]
2576   "TARGET_ARM"
2577   "
2578   if (GET_CODE (operands[2]) == CONST_INT)
2579     {
2580       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2581         {
2582           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2583           DONE;
2584         }
2585         /* Ideally we shouldn't fail here if we could know that operands[1] 
2586            ends up already living in an iwmmxt register. Otherwise it's
2587            cheaper to have the alternate code being generated than moving
2588            values to iwmmxt regs and back.  */
2589         FAIL;
2590     }
2591   else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2592     FAIL;
2593   "
2596 (define_insn "arm_ashldi3_1bit"
2597   [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
2598         (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2599                    (const_int 1)))
2600    (clobber (reg:CC CC_REGNUM))]
2601   "TARGET_ARM"
2602   "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2603   [(set_attr "conds" "clob")
2604    (set_attr "length" "8")]
2607 (define_expand "ashlsi3"
2608   [(set (match_operand:SI            0 "s_register_operand" "")
2609         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2610                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2611   "TARGET_EITHER"
2612   "
2613   if (GET_CODE (operands[2]) == CONST_INT
2614       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2615     {
2616       emit_insn (gen_movsi (operands[0], const0_rtx));
2617       DONE;
2618     }
2619   "
2622 (define_insn "*thumb_ashlsi3"
2623   [(set (match_operand:SI            0 "register_operand" "=l,l")
2624         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2625                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2626   "TARGET_THUMB"
2627   "lsl\\t%0, %1, %2"
2628   [(set_attr "length" "2")]
2631 (define_expand "ashrdi3"
2632   [(set (match_operand:DI              0 "s_register_operand" "")
2633         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2634                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2635   "TARGET_ARM"
2636   "
2637   if (GET_CODE (operands[2]) == CONST_INT)
2638     {
2639       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2640         {
2641           emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2642           DONE;
2643         }
2644         /* Ideally we shouldn't fail here if we could know that operands[1] 
2645            ends up already living in an iwmmxt register. Otherwise it's
2646            cheaper to have the alternate code being generated than moving
2647            values to iwmmxt regs and back.  */
2648         FAIL;
2649     }
2650   else if (!TARGET_REALLY_IWMMXT)
2651     FAIL;
2652   "
2655 (define_insn "arm_ashrdi3_1bit"
2656   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2657         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2658                      (const_int 1)))
2659    (clobber (reg:CC CC_REGNUM))]
2660   "TARGET_ARM"
2661   "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2662   [(set_attr "conds" "clob")
2663    (set_attr "length" "8")]
2666 (define_expand "ashrsi3"
2667   [(set (match_operand:SI              0 "s_register_operand" "")
2668         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2669                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2670   "TARGET_EITHER"
2671   "
2672   if (GET_CODE (operands[2]) == CONST_INT
2673       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2674     operands[2] = GEN_INT (31);
2675   "
2678 (define_insn "*thumb_ashrsi3"
2679   [(set (match_operand:SI              0 "register_operand" "=l,l")
2680         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2681                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2682   "TARGET_THUMB"
2683   "asr\\t%0, %1, %2"
2684   [(set_attr "length" "2")]
2687 (define_expand "lshrdi3"
2688   [(set (match_operand:DI              0 "s_register_operand" "")
2689         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2690                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2691   "TARGET_ARM"
2692   "
2693   if (GET_CODE (operands[2]) == CONST_INT)
2694     {
2695       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2696         {
2697           emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2698           DONE;
2699         }
2700         /* Ideally we shouldn't fail here if we could know that operands[1] 
2701            ends up already living in an iwmmxt register. Otherwise it's
2702            cheaper to have the alternate code being generated than moving
2703            values to iwmmxt regs and back.  */
2704         FAIL;
2705     }
2706   else if (!TARGET_REALLY_IWMMXT)
2707     FAIL;
2708   "
2711 (define_insn "arm_lshrdi3_1bit"
2712   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2713         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2714                      (const_int 1)))
2715    (clobber (reg:CC CC_REGNUM))]
2716   "TARGET_ARM"
2717   "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2718   [(set_attr "conds" "clob")
2719    (set_attr "length" "8")]
2722 (define_expand "lshrsi3"
2723   [(set (match_operand:SI              0 "s_register_operand" "")
2724         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2725                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2726   "TARGET_EITHER"
2727   "
2728   if (GET_CODE (operands[2]) == CONST_INT
2729       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2730     {
2731       emit_insn (gen_movsi (operands[0], const0_rtx));
2732       DONE;
2733     }
2734   "
2737 (define_insn "*thumb_lshrsi3"
2738   [(set (match_operand:SI              0 "register_operand" "=l,l")
2739         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2740                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2741   "TARGET_THUMB"
2742   "lsr\\t%0, %1, %2"
2743   [(set_attr "length" "2")]
2746 (define_expand "rotlsi3"
2747   [(set (match_operand:SI              0 "s_register_operand" "")
2748         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2749                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2750   "TARGET_ARM"
2751   "
2752   if (GET_CODE (operands[2]) == CONST_INT)
2753     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2754   else
2755     {
2756       rtx reg = gen_reg_rtx (SImode);
2757       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2758       operands[2] = reg;
2759     }
2760   "
2763 (define_expand "rotrsi3"
2764   [(set (match_operand:SI              0 "s_register_operand" "")
2765         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2766                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2767   "TARGET_EITHER"
2768   "
2769   if (TARGET_ARM)
2770     {
2771       if (GET_CODE (operands[2]) == CONST_INT
2772           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2773         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2774     }
2775   else /* TARGET_THUMB */
2776     {
2777       if (GET_CODE (operands [2]) == CONST_INT)
2778         operands [2] = force_reg (SImode, operands[2]);
2779     }
2780   "
2783 (define_insn "*thumb_rotrsi3"
2784   [(set (match_operand:SI              0 "register_operand" "=l")
2785         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2786                      (match_operand:SI 2 "register_operand" "l")))]
2787   "TARGET_THUMB"
2788   "ror\\t%0, %0, %2"
2789   [(set_attr "length" "2")]
2792 (define_insn "*arm_shiftsi3"
2793   [(set (match_operand:SI   0 "s_register_operand" "=r")
2794         (match_operator:SI  3 "shift_operator"
2795          [(match_operand:SI 1 "s_register_operand"  "r")
2796           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2797   "TARGET_ARM"
2798   "mov%?\\t%0, %1%S3"
2799   [(set_attr "predicable" "yes")
2800    (set_attr "shift" "1")
2801    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2802                       (const_string "alu_shift")
2803                       (const_string "alu_shift_reg")))]
2806 (define_insn "*shiftsi3_compare0"
2807   [(set (reg:CC_NOOV CC_REGNUM)
2808         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2809                           [(match_operand:SI 1 "s_register_operand" "r")
2810                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2811                          (const_int 0)))
2812    (set (match_operand:SI 0 "s_register_operand" "=r")
2813         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2814   "TARGET_ARM"
2815   "mov%?s\\t%0, %1%S3"
2816   [(set_attr "conds" "set")
2817    (set_attr "shift" "1")
2818    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2819                       (const_string "alu_shift")
2820                       (const_string "alu_shift_reg")))]
2823 (define_insn "*shiftsi3_compare0_scratch"
2824   [(set (reg:CC_NOOV CC_REGNUM)
2825         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2826                           [(match_operand:SI 1 "s_register_operand" "r")
2827                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2828                          (const_int 0)))
2829    (clobber (match_scratch:SI 0 "=r"))]
2830   "TARGET_ARM"
2831   "mov%?s\\t%0, %1%S3"
2832   [(set_attr "conds" "set")
2833    (set_attr "shift" "1")]
2836 (define_insn "*notsi_shiftsi"
2837   [(set (match_operand:SI 0 "s_register_operand" "=r")
2838         (not:SI (match_operator:SI 3 "shift_operator"
2839                  [(match_operand:SI 1 "s_register_operand" "r")
2840                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2841   "TARGET_ARM"
2842   "mvn%?\\t%0, %1%S3"
2843   [(set_attr "predicable" "yes")
2844    (set_attr "shift" "1")
2845    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2846                       (const_string "alu_shift")
2847                       (const_string "alu_shift_reg")))]
2850 (define_insn "*notsi_shiftsi_compare0"
2851   [(set (reg:CC_NOOV CC_REGNUM)
2852         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2853                           [(match_operand:SI 1 "s_register_operand" "r")
2854                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2855                          (const_int 0)))
2856    (set (match_operand:SI 0 "s_register_operand" "=r")
2857         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2858   "TARGET_ARM"
2859   "mvn%?s\\t%0, %1%S3"
2860   [(set_attr "conds" "set")
2861    (set_attr "shift" "1")
2862    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2863                       (const_string "alu_shift")
2864                       (const_string "alu_shift_reg")))]
2867 (define_insn "*not_shiftsi_compare0_scratch"
2868   [(set (reg:CC_NOOV CC_REGNUM)
2869         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2870                           [(match_operand:SI 1 "s_register_operand" "r")
2871                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2872                          (const_int 0)))
2873    (clobber (match_scratch:SI 0 "=r"))]
2874   "TARGET_ARM"
2875   "mvn%?s\\t%0, %1%S3"
2876   [(set_attr "conds" "set")
2877    (set_attr "shift" "1")
2878    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2879                       (const_string "alu_shift")
2880                       (const_string "alu_shift_reg")))]
2883 ;; We don't really have extzv, but defining this using shifts helps
2884 ;; to reduce register pressure later on.
2886 (define_expand "extzv"
2887   [(set (match_dup 4)
2888         (ashift:SI (match_operand:SI   1 "register_operand" "")
2889                    (match_operand:SI   2 "const_int_operand" "")))
2890    (set (match_operand:SI              0 "register_operand" "")
2891         (lshiftrt:SI (match_dup 4)
2892                      (match_operand:SI 3 "const_int_operand" "")))]
2893   "TARGET_THUMB"
2894   "
2895   {
2896     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2897     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2898     
2899     operands[3] = GEN_INT (rshift);
2900     
2901     if (lshift == 0)
2902       {
2903         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2904         DONE;
2905       }
2906       
2907     operands[2] = GEN_INT (lshift);
2908     operands[4] = gen_reg_rtx (SImode);
2909   }"
2913 ;; Unary arithmetic insns
2915 (define_expand "negdi2"
2916  [(parallel
2917    [(set (match_operand:DI          0 "s_register_operand" "")
2918           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2919     (clobber (reg:CC CC_REGNUM))])]
2920   "TARGET_EITHER"
2921   "
2922   if (TARGET_THUMB)
2923     {
2924       if (GET_CODE (operands[1]) != REG)
2925         operands[1] = force_reg (SImode, operands[1]);
2926      }
2927   "
2930 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2931 ;; The second alternative is to allow the common case of a *full* overlap.
2932 (define_insn "*arm_negdi2"
2933   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2934         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2935    (clobber (reg:CC CC_REGNUM))]
2936   "TARGET_ARM"
2937   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2938   [(set_attr "conds" "clob")
2939    (set_attr "length" "8")]
2942 (define_insn "*thumb_negdi2"
2943   [(set (match_operand:DI         0 "register_operand" "=&l")
2944         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
2945    (clobber (reg:CC CC_REGNUM))]
2946   "TARGET_THUMB"
2947   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2948   [(set_attr "length" "6")]
2951 (define_expand "negsi2"
2952   [(set (match_operand:SI         0 "s_register_operand" "")
2953         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2954   "TARGET_EITHER"
2955   ""
2958 (define_insn "*arm_negsi2"
2959   [(set (match_operand:SI         0 "s_register_operand" "=r")
2960         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2961   "TARGET_ARM"
2962   "rsb%?\\t%0, %1, #0"
2963   [(set_attr "predicable" "yes")]
2966 (define_insn "*thumb_negsi2"
2967   [(set (match_operand:SI         0 "register_operand" "=l")
2968         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2969   "TARGET_THUMB"
2970   "neg\\t%0, %1"
2971   [(set_attr "length" "2")]
2974 (define_expand "negsf2"
2975   [(set (match_operand:SF         0 "s_register_operand" "")
2976         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2977   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2978   ""
2981 (define_expand "negdf2"
2982   [(set (match_operand:DF         0 "s_register_operand" "")
2983         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2984   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2985   "")
2987 ;; abssi2 doesn't really clobber the condition codes if a different register
2988 ;; is being set.  To keep things simple, assume during rtl manipulations that
2989 ;; it does, but tell the final scan operator the truth.  Similarly for
2990 ;; (neg (abs...))
2992 (define_expand "abssi2"
2993   [(parallel
2994     [(set (match_operand:SI         0 "s_register_operand" "")
2995           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
2996      (clobber (reg:CC CC_REGNUM))])]
2997   "TARGET_ARM"
2998   "")
3000 (define_insn "*arm_abssi2"
3001   [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
3002         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3003    (clobber (reg:CC CC_REGNUM))]
3004   "TARGET_ARM"
3005   "@
3006    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3007    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3008   [(set_attr "conds" "clob,*")
3009    (set_attr "shift" "1")
3010    ;; predicable can't be set based on the variant, so left as no
3011    (set_attr "length" "8")]
3014 (define_insn "*neg_abssi2"
3015   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3016         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3017    (clobber (reg:CC CC_REGNUM))]
3018   "TARGET_ARM"
3019   "@
3020    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3021    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3022   [(set_attr "conds" "clob,*")
3023    (set_attr "shift" "1")
3024    ;; predicable can't be set based on the variant, so left as no
3025    (set_attr "length" "8")]
3028 (define_expand "abssf2"
3029   [(set (match_operand:SF         0 "s_register_operand" "")
3030         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3031   "TARGET_ARM && TARGET_HARD_FLOAT"
3032   "")
3034 (define_expand "absdf2"
3035   [(set (match_operand:DF         0 "s_register_operand" "")
3036         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3037   "TARGET_ARM && TARGET_HARD_FLOAT"
3038   "")
3040 (define_expand "sqrtsf2"
3041   [(set (match_operand:SF 0 "s_register_operand" "")
3042         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3043   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3044   "")
3046 (define_expand "sqrtdf2"
3047   [(set (match_operand:DF 0 "s_register_operand" "")
3048         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3049   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3050   "")
3052 (define_insn_and_split "one_cmpldi2"
3053   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3054         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3055   "TARGET_ARM"
3056   "#"
3057   "TARGET_ARM && reload_completed"
3058   [(set (match_dup 0) (not:SI (match_dup 1)))
3059    (set (match_dup 2) (not:SI (match_dup 3)))]
3060   "
3061   {
3062     operands[2] = gen_highpart (SImode, operands[0]);
3063     operands[0] = gen_lowpart (SImode, operands[0]);
3064     operands[3] = gen_highpart (SImode, operands[1]);
3065     operands[1] = gen_lowpart (SImode, operands[1]);
3066   }"
3067   [(set_attr "length" "8")
3068    (set_attr "predicable" "yes")]
3071 (define_expand "one_cmplsi2"
3072   [(set (match_operand:SI         0 "s_register_operand" "")
3073         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3074   "TARGET_EITHER"
3075   ""
3078 (define_insn "*arm_one_cmplsi2"
3079   [(set (match_operand:SI         0 "s_register_operand" "=r")
3080         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3081   "TARGET_ARM"
3082   "mvn%?\\t%0, %1"
3083   [(set_attr "predicable" "yes")]
3086 (define_insn "*thumb_one_cmplsi2"
3087   [(set (match_operand:SI         0 "register_operand" "=l")
3088         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3089   "TARGET_THUMB"
3090   "mvn\\t%0, %1"
3091   [(set_attr "length" "2")]
3094 (define_insn "*notsi_compare0"
3095   [(set (reg:CC_NOOV CC_REGNUM)
3096         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3097                          (const_int 0)))
3098    (set (match_operand:SI 0 "s_register_operand" "=r")
3099         (not:SI (match_dup 1)))]
3100   "TARGET_ARM"
3101   "mvn%?s\\t%0, %1"
3102   [(set_attr "conds" "set")]
3105 (define_insn "*notsi_compare0_scratch"
3106   [(set (reg:CC_NOOV CC_REGNUM)
3107         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3108                          (const_int 0)))
3109    (clobber (match_scratch:SI 0 "=r"))]
3110   "TARGET_ARM"
3111   "mvn%?s\\t%0, %1"
3112   [(set_attr "conds" "set")]
3115 ;; Fixed <--> Floating conversion insns
3117 (define_expand "floatsisf2"
3118   [(set (match_operand:SF           0 "s_register_operand" "")
3119         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3120   "TARGET_ARM && TARGET_HARD_FLOAT"
3121   "
3122   if (TARGET_MAVERICK)
3123     {
3124       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3125       DONE;
3126     }
3129 (define_expand "floatsidf2"
3130   [(set (match_operand:DF           0 "s_register_operand" "")
3131         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3132   "TARGET_ARM && TARGET_HARD_FLOAT"
3133   "
3134   if (TARGET_MAVERICK)
3135     {
3136       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3137       DONE;
3138     }
3141 (define_expand "fix_truncsfsi2"
3142   [(set (match_operand:SI         0 "s_register_operand" "")
3143         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3144   "TARGET_ARM && TARGET_HARD_FLOAT"
3145   "
3146   if (TARGET_MAVERICK)
3147     {
3148       if (!cirrus_fp_register (operands[0], SImode))
3149         operands[0] = force_reg (SImode, operands[0]);
3150       if (!cirrus_fp_register (operands[1], SFmode))
3151         operands[1] = force_reg (SFmode, operands[0]);
3152       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3153       DONE;
3154     }
3157 (define_expand "fix_truncdfsi2"
3158   [(set (match_operand:SI         0 "s_register_operand" "")
3159         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3160   "TARGET_ARM && TARGET_HARD_FLOAT"
3161   "
3162   if (TARGET_MAVERICK)
3163     {
3164       if (!cirrus_fp_register (operands[1], DFmode))
3165         operands[1] = force_reg (DFmode, operands[0]);
3166       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3167       DONE;
3168     }
3171 ;; Truncation insns
3173 (define_expand "truncdfsf2"
3174   [(set (match_operand:SF  0 "s_register_operand" "")
3175         (float_truncate:SF
3176          (match_operand:DF 1 "s_register_operand" "")))]
3177   "TARGET_ARM && TARGET_HARD_FLOAT"
3178   ""
3181 ;; Zero and sign extension instructions.
3183 (define_insn "zero_extendsidi2"
3184   [(set (match_operand:DI 0 "s_register_operand" "=r")
3185         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3186   "TARGET_ARM"
3187   "*
3188     if (REGNO (operands[1])
3189         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3190       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3191     return \"mov%?\\t%R0, #0\";
3192   "
3193   [(set_attr "length" "8")
3194    (set_attr "predicable" "yes")]
3197 (define_insn "zero_extendqidi2"
3198   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3199         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3200   "TARGET_ARM"
3201   "@
3202    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3203    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3204   [(set_attr "length" "8")
3205    (set_attr "predicable" "yes")
3206    (set_attr "type" "*,load_byte")
3207    (set_attr "pool_range" "*,4092")
3208    (set_attr "neg_pool_range" "*,4084")]
3211 (define_insn "extendsidi2"
3212   [(set (match_operand:DI 0 "s_register_operand" "=r")
3213         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3214   "TARGET_ARM"
3215   "*
3216     if (REGNO (operands[1])
3217         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3218       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3219     return \"mov%?\\t%R0, %Q0, asr #31\";
3220   "
3221   [(set_attr "length" "8")
3222    (set_attr "shift" "1")
3223    (set_attr "predicable" "yes")]
3226 (define_expand "zero_extendhisi2"
3227   [(set (match_dup 2)
3228         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3229                    (const_int 16)))
3230    (set (match_operand:SI 0 "s_register_operand" "")
3231         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3232   "TARGET_EITHER"
3233   "
3234   {
3235     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3236       {
3237         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3238                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3239         DONE;
3240       }
3242     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3243       {
3244         emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3245         DONE;
3246       }
3248     if (!s_register_operand (operands[1], HImode))
3249       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3251     if (arm_arch6)
3252       {
3253         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3254                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3255         DONE;
3256       }
3258     operands[1] = gen_lowpart (SImode, operands[1]);
3259     operands[2] = gen_reg_rtx (SImode);
3260   }"
3263 (define_insn "*thumb_zero_extendhisi2"
3264   [(set (match_operand:SI 0 "register_operand" "=l")
3265         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3266   "TARGET_THUMB && !arm_arch6"
3267   "*
3268   rtx mem = XEXP (operands[1], 0);
3270   if (GET_CODE (mem) == CONST)
3271     mem = XEXP (mem, 0);
3272     
3273   if (GET_CODE (mem) == LABEL_REF)
3274     return \"ldr\\t%0, %1\";
3275     
3276   if (GET_CODE (mem) == PLUS)
3277     {
3278       rtx a = XEXP (mem, 0);
3279       rtx b = XEXP (mem, 1);
3281       /* This can happen due to bugs in reload.  */
3282       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3283         {
3284           rtx ops[2];
3285           ops[0] = operands[0];
3286           ops[1] = a;
3287       
3288           output_asm_insn (\"mov        %0, %1\", ops);
3290           XEXP (mem, 0) = operands[0];
3291        }
3293       else if (   GET_CODE (a) == LABEL_REF
3294                && GET_CODE (b) == CONST_INT)
3295         return \"ldr\\t%0, %1\";
3296     }
3297     
3298   return \"ldrh\\t%0, %1\";
3299   "
3300   [(set_attr "length" "4")
3301    (set_attr "type" "load_byte")
3302    (set_attr "pool_range" "60")]
3305 (define_insn "*thumb_zero_extendhisi2_v6"
3306   [(set (match_operand:SI 0 "register_operand" "=l,l")
3307         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3308   "TARGET_THUMB && arm_arch6"
3309   "*
3310   rtx mem;
3312   if (which_alternative == 0)
3313     return \"uxth\\t%0, %1\";
3315   mem = XEXP (operands[1], 0);
3317   if (GET_CODE (mem) == CONST)
3318     mem = XEXP (mem, 0);
3319     
3320   if (GET_CODE (mem) == LABEL_REF)
3321     return \"ldr\\t%0, %1\";
3322     
3323   if (GET_CODE (mem) == PLUS)
3324     {
3325       rtx a = XEXP (mem, 0);
3326       rtx b = XEXP (mem, 1);
3328       /* This can happen due to bugs in reload.  */
3329       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3330         {
3331           rtx ops[2];
3332           ops[0] = operands[0];
3333           ops[1] = a;
3334       
3335           output_asm_insn (\"mov        %0, %1\", ops);
3337           XEXP (mem, 0) = operands[0];
3338        }
3340       else if (   GET_CODE (a) == LABEL_REF
3341                && GET_CODE (b) == CONST_INT)
3342         return \"ldr\\t%0, %1\";
3343     }
3344     
3345   return \"ldrh\\t%0, %1\";
3346   "
3347   [(set_attr "length" "2,4")
3348    (set_attr "type" "alu_shift,load_byte")
3349    (set_attr "pool_range" "*,60")]
3352 (define_insn "*arm_zero_extendhisi2"
3353   [(set (match_operand:SI 0 "s_register_operand" "=r")
3354         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3355   "TARGET_ARM && arm_arch4 && !arm_arch6"
3356   "ldr%?h\\t%0, %1"
3357   [(set_attr "type" "load_byte")
3358    (set_attr "predicable" "yes")
3359    (set_attr "pool_range" "256")
3360    (set_attr "neg_pool_range" "244")]
3363 (define_insn "*arm_zero_extendhisi2_v6"
3364   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3365         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3366   "TARGET_ARM && arm_arch6"
3367   "@
3368    uxth%?\\t%0, %1
3369    ldr%?h\\t%0, %1"
3370   [(set_attr "type" "alu_shift,load_byte")
3371    (set_attr "predicable" "yes")
3372    (set_attr "pool_range" "*,256")
3373    (set_attr "neg_pool_range" "*,244")]
3376 (define_insn "*arm_zero_extendhisi2addsi"
3377   [(set (match_operand:SI 0 "s_register_operand" "=r")
3378         (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3379                  (match_operand:SI 2 "s_register_operand" "r")))]
3380   "TARGET_ARM && arm_arch6"
3381   "uxtah%?\\t%0, %2, %1"
3382   [(set_attr "type" "alu_shift")
3383    (set_attr "predicable" "yes")]
3386 (define_split
3387   [(set (match_operand:SI 0 "s_register_operand" "")
3388         (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3389    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3390   "TARGET_ARM && (!arm_arch4)"
3391   [(set (match_dup 2) (match_dup 1))
3392    (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3393   "
3394   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3395     FAIL;
3396   "
3399 (define_split
3400   [(set (match_operand:SI 0 "s_register_operand" "")
3401         (match_operator:SI 3 "shiftable_operator"
3402          [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3403           (match_operand:SI 4 "s_register_operand" "")]))
3404    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3405   "TARGET_ARM && (!arm_arch4)"
3406   [(set (match_dup 2) (match_dup 1))
3407    (set (match_dup 0)
3408         (match_op_dup 3
3409          [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3410   "
3411   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3412     FAIL;
3413   "
3416 (define_expand "zero_extendqisi2"
3417   [(set (match_operand:SI 0 "s_register_operand" "")
3418         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3419   "TARGET_EITHER"
3420   "
3421   if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3422     {
3423       if (TARGET_ARM)
3424         {
3425           emit_insn (gen_andsi3 (operands[0],
3426                                  gen_lowpart (SImode, operands[1]),
3427                                  GEN_INT (255)));
3428         }
3429       else /* TARGET_THUMB */
3430         {
3431           rtx temp = gen_reg_rtx (SImode);
3432           rtx ops[3];
3433           
3434           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3435           operands[1] = gen_lowpart (SImode, operands[1]);
3437           ops[0] = temp;
3438           ops[1] = operands[1];
3439           ops[2] = GEN_INT (24);
3441           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3442                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3443           
3444           ops[0] = operands[0];
3445           ops[1] = temp;
3446           ops[2] = GEN_INT (24);
3448           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3449                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3450         }
3451       DONE;
3452     }
3453   "
3456 (define_insn "*thumb_zero_extendqisi2"
3457   [(set (match_operand:SI 0 "register_operand" "=l")
3458         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3459   "TARGET_THUMB && !arm_arch6"
3460   "ldrb\\t%0, %1"
3461   [(set_attr "length" "2")
3462    (set_attr "type" "load_byte")
3463    (set_attr "pool_range" "32")]
3466 (define_insn "*thumb_zero_extendqisi2_v6"
3467   [(set (match_operand:SI 0 "register_operand" "=l,l")
3468         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3469   "TARGET_THUMB && arm_arch6"
3470   "@
3471    uxtb\\t%0, %1
3472    ldrb\\t%0, %1"
3473   [(set_attr "length" "2,2")
3474    (set_attr "type" "alu_shift,load_byte")
3475    (set_attr "pool_range" "*,32")]
3478 (define_insn "*arm_zero_extendqisi2"
3479   [(set (match_operand:SI 0 "s_register_operand" "=r")
3480         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3481   "TARGET_ARM && !arm_arch6"
3482   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3483   [(set_attr "type" "load_byte")
3484    (set_attr "predicable" "yes")
3485    (set_attr "pool_range" "4096")
3486    (set_attr "neg_pool_range" "4084")]
3489 (define_insn "*arm_zero_extendqisi2_v6"
3490   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3491         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3492   "TARGET_ARM && arm_arch6"
3493   "@
3494    uxtb%?\\t%0, %1
3495    ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3496   [(set_attr "type" "alu_shift,load_byte")
3497    (set_attr "predicable" "yes")
3498    (set_attr "pool_range" "*,4096")
3499    (set_attr "neg_pool_range" "*,4084")]
3502 (define_insn "*arm_zero_extendqisi2addsi"
3503   [(set (match_operand:SI 0 "s_register_operand" "=r")
3504         (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3505                  (match_operand:SI 2 "s_register_operand" "r")))]
3506   "TARGET_ARM && arm_arch6"
3507   "uxtab%?\\t%0, %2, %1"
3508   [(set_attr "predicable" "yes")
3509    (set_attr "type" "alu_shift")]
3512 (define_split
3513   [(set (match_operand:SI 0 "s_register_operand" "")
3514         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3515    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3516   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3517   [(set (match_dup 2) (match_dup 1))
3518    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3519   ""
3522 (define_insn "*compareqi_eq0"
3523   [(set (reg:CC_Z CC_REGNUM)
3524         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3525                          (const_int 0)))]
3526   "TARGET_ARM"
3527   "tst\\t%0, #255"
3528   [(set_attr "conds" "set")]
3531 (define_expand "extendhisi2"
3532   [(set (match_dup 2)
3533         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3534                    (const_int 16)))
3535    (set (match_operand:SI 0 "s_register_operand" "")
3536         (ashiftrt:SI (match_dup 2)
3537                      (const_int 16)))]
3538   "TARGET_EITHER"
3539   "
3540   {
3541     if (GET_CODE (operands[1]) == MEM)
3542       {
3543         if (TARGET_THUMB)
3544           {
3545             emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3546             DONE;
3547           }
3548         else if (arm_arch4)
3549           {
3550             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3551                        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3552             DONE;
3553           }
3554       }
3556     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3557       {
3558         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3559         DONE;
3560       }
3562     if (!s_register_operand (operands[1], HImode))
3563       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3565     if (arm_arch6)
3566       {
3567         if (TARGET_THUMB)
3568           emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3569         else
3570           emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3571                      gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3573         DONE;
3574       }
3576     operands[1] = gen_lowpart (SImode, operands[1]);
3577     operands[2] = gen_reg_rtx (SImode);
3578   }"
3581 (define_insn "thumb_extendhisi2"
3582   [(set (match_operand:SI 0 "register_operand" "=l")
3583         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3584    (clobber (match_scratch:SI 2 "=&l"))]
3585   "TARGET_THUMB && !arm_arch6"
3586   "*
3587   {
3588     rtx ops[4];
3589     rtx mem = XEXP (operands[1], 0);
3591     /* This code used to try to use 'V', and fix the address only if it was
3592        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3593        range of QImode offsets, and offsettable_address_p does a QImode
3594        address check.  */
3595        
3596     if (GET_CODE (mem) == CONST)
3597       mem = XEXP (mem, 0);
3598     
3599     if (GET_CODE (mem) == LABEL_REF)
3600       return \"ldr\\t%0, %1\";
3601     
3602     if (GET_CODE (mem) == PLUS)
3603       {
3604         rtx a = XEXP (mem, 0);
3605         rtx b = XEXP (mem, 1);
3607         if (GET_CODE (a) == LABEL_REF
3608             && GET_CODE (b) == CONST_INT)
3609           return \"ldr\\t%0, %1\";
3611         if (GET_CODE (b) == REG)
3612           return \"ldrsh\\t%0, %1\";
3613           
3614         ops[1] = a;
3615         ops[2] = b;
3616       }
3617     else
3618       {
3619         ops[1] = mem;
3620         ops[2] = const0_rtx;
3621       }
3622       
3623     if (GET_CODE (ops[1]) != REG)
3624       {
3625         debug_rtx (ops[1]);
3626         abort ();
3627       }
3629     ops[0] = operands[0];
3630     ops[3] = operands[2];
3631     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3632     return \"\";
3633   }"
3634   [(set_attr "length" "4")
3635    (set_attr "type" "load_byte")
3636    (set_attr "pool_range" "1020")]
3639 ;; We used to have an early-clobber on the scratch register here.
3640 ;; However, there's a bug somewhere in reload which means that this
3641 ;; can be partially ignored during spill allocation if the memory
3642 ;; address also needs reloading; this causes an abort later on when
3643 ;; we try to verify the operands.  Fortunately, we don't really need
3644 ;; the early-clobber: we can always use operand 0 if operand 2
3645 ;; overlaps the address.
3646 (define_insn "*thumb_extendhisi2_insn_v6"
3647   [(set (match_operand:SI 0 "register_operand" "=l,l")
3648         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3649    (clobber (match_scratch:SI 2 "=X,l"))]
3650   "TARGET_THUMB && arm_arch6"
3651   "*
3652   {
3653     rtx ops[4];
3654     rtx mem;
3656     if (which_alternative == 0)
3657       return \"sxth\\t%0, %1\";
3659     mem = XEXP (operands[1], 0);
3661     /* This code used to try to use 'V', and fix the address only if it was
3662        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3663        range of QImode offsets, and offsettable_address_p does a QImode
3664        address check.  */
3665        
3666     if (GET_CODE (mem) == CONST)
3667       mem = XEXP (mem, 0);
3668     
3669     if (GET_CODE (mem) == LABEL_REF)
3670       return \"ldr\\t%0, %1\";
3671     
3672     if (GET_CODE (mem) == PLUS)
3673       {
3674         rtx a = XEXP (mem, 0);
3675         rtx b = XEXP (mem, 1);
3677         if (GET_CODE (a) == LABEL_REF
3678             && GET_CODE (b) == CONST_INT)
3679           return \"ldr\\t%0, %1\";
3681         if (GET_CODE (b) == REG)
3682           return \"ldrsh\\t%0, %1\";
3683           
3684         ops[1] = a;
3685         ops[2] = b;
3686       }
3687     else
3688       {
3689         ops[1] = mem;
3690         ops[2] = const0_rtx;
3691       }
3692       
3693     if (GET_CODE (ops[1]) != REG)
3694       {
3695         debug_rtx (ops[1]);
3696         abort ();
3697       }
3699     ops[0] = operands[0];
3700     if (reg_mentioned_p (operands[2], ops[1]))
3701       ops[3] = ops[0];
3702     else
3703       ops[3] = operands[2];
3704     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3705     return \"\";
3706   }"
3707   [(set_attr "length" "2,4")
3708    (set_attr "type" "alu_shift,load_byte")
3709    (set_attr "pool_range" "*,1020")]
3712 (define_expand "extendhisi2_mem"
3713   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3714    (set (match_dup 3)
3715         (zero_extend:SI (match_dup 7)))
3716    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3717    (set (match_operand:SI 0 "" "")
3718         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3719   "TARGET_ARM"
3720   "
3721   {
3722     rtx mem1, mem2;
3723     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3725     mem1 = gen_rtx_MEM (QImode, addr);
3726     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3727     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3728     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3729     operands[0] = gen_lowpart (SImode, operands[0]);
3730     operands[1] = mem1;
3731     operands[2] = gen_reg_rtx (SImode);
3732     operands[3] = gen_reg_rtx (SImode);
3733     operands[6] = gen_reg_rtx (SImode);
3734     operands[7] = mem2;
3736     if (BYTES_BIG_ENDIAN)
3737       {
3738         operands[4] = operands[2];
3739         operands[5] = operands[3];
3740       }
3741     else
3742       {
3743         operands[4] = operands[3];
3744         operands[5] = operands[2];
3745       }
3746   }"
3749 (define_insn "*arm_extendhisi2"
3750   [(set (match_operand:SI 0 "s_register_operand" "=r")
3751         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3752   "TARGET_ARM && arm_arch4 && !arm_arch6"
3753   "ldr%?sh\\t%0, %1"
3754   [(set_attr "type" "load_byte")
3755    (set_attr "predicable" "yes")
3756    (set_attr "pool_range" "256")
3757    (set_attr "neg_pool_range" "244")]
3760 (define_insn "*arm_extendhisi2_v6"
3761   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3762         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3763   "TARGET_ARM && arm_arch6"
3764   "@
3765    sxth%?\\t%0, %1
3766    ldr%?sh\\t%0, %1"
3767   [(set_attr "type" "alu_shift,load_byte")
3768    (set_attr "predicable" "yes")
3769    (set_attr "pool_range" "*,256")
3770    (set_attr "neg_pool_range" "*,244")]
3773 (define_insn "*arm_extendhisi2addsi"
3774   [(set (match_operand:SI 0 "s_register_operand" "=r")
3775         (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3776                  (match_operand:SI 2 "s_register_operand" "r")))]
3777   "TARGET_ARM && arm_arch6"
3778   "sxtah%?\\t%0, %2, %1"
3781 (define_split
3782   [(set (match_operand:SI                 0 "s_register_operand" "")
3783         (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3784    (clobber (match_operand:SI             2 "s_register_operand" ""))]
3785   "TARGET_ARM && (!arm_arch4)"
3786   [(set (match_dup 2) (match_dup 1))
3787    (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3788   "
3789   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3790     FAIL;
3791   "
3794 (define_split
3795   [(set (match_operand:SI                   0 "s_register_operand" "")
3796         (match_operator:SI                  3 "shiftable_operator"
3797          [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3798           (match_operand:SI                 4 "s_register_operand" "")]))
3799    (clobber (match_operand:SI               2 "s_register_operand" ""))]
3800   "TARGET_ARM && (!arm_arch4)"
3801   [(set (match_dup 2) (match_dup 1))
3802    (set (match_dup 0)
3803         (match_op_dup 3
3804          [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3805   "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3806      FAIL;
3807   "
3810 (define_expand "extendqihi2"
3811   [(set (match_dup 2)
3812         (ashift:SI (match_operand:QI 1 "general_operand" "")
3813                    (const_int 24)))
3814    (set (match_operand:HI 0 "s_register_operand" "")
3815         (ashiftrt:SI (match_dup 2)
3816                      (const_int 24)))]
3817   "TARGET_ARM"
3818   "
3819   {
3820     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3821       {
3822         emit_insn (gen_rtx_SET (VOIDmode,
3823                                 operands[0],
3824                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3825         DONE;
3826       }
3827     if (!s_register_operand (operands[1], QImode))
3828       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3829     operands[0] = gen_lowpart (SImode, operands[0]);
3830     operands[1] = gen_lowpart (SImode, operands[1]);
3831     operands[2] = gen_reg_rtx (SImode);
3832   }"
3835 (define_insn "*extendqihi_insn"
3836   [(set (match_operand:HI 0 "s_register_operand" "=r")
3837         (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3838   "TARGET_ARM && arm_arch4"
3839   "ldr%?sb\\t%0, %1"
3840   [(set_attr "type" "load_byte")
3841    (set_attr "predicable" "yes")
3842    (set_attr "pool_range" "256")
3843    (set_attr "neg_pool_range" "244")]
3846 (define_expand "extendqisi2"
3847   [(set (match_dup 2)
3848         (ashift:SI (match_operand:QI 1 "general_operand" "")
3849                    (const_int 24)))
3850    (set (match_operand:SI 0 "s_register_operand" "")
3851         (ashiftrt:SI (match_dup 2)
3852                      (const_int 24)))]
3853   "TARGET_EITHER"
3854   "
3855   {
3856     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3857       {
3858         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3859                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3860         DONE;
3861       }
3863     if (!s_register_operand (operands[1], QImode))
3864       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3866     if (arm_arch6)
3867       {
3868         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3869                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3870         DONE;
3871       }
3873     operands[1] = gen_lowpart (SImode, operands[1]);
3874     operands[2] = gen_reg_rtx (SImode);
3875   }"
3878 (define_insn "*arm_extendqisi"
3879   [(set (match_operand:SI 0 "s_register_operand" "=r")
3880         (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3881   "TARGET_ARM && arm_arch4 && !arm_arch6"
3882   "ldr%?sb\\t%0, %1"
3883   [(set_attr "type" "load_byte")
3884    (set_attr "predicable" "yes")
3885    (set_attr "pool_range" "256")
3886    (set_attr "neg_pool_range" "244")]
3889 (define_insn "*arm_extendqisi_v6"
3890   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3891         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3892   "TARGET_ARM && arm_arch6"
3893   "@
3894    sxtb%?\\t%0, %1
3895    ldr%?sb\\t%0, %1"
3896   [(set_attr "type" "alu_shift,load_byte")
3897    (set_attr "predicable" "yes")
3898    (set_attr "pool_range" "*,256")
3899    (set_attr "neg_pool_range" "*,244")]
3902 (define_insn "*arm_extendqisi2addsi"
3903   [(set (match_operand:SI 0 "s_register_operand" "=r")
3904         (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3905                  (match_operand:SI 2 "s_register_operand" "r")))]
3906   "TARGET_ARM && arm_arch6"
3907   "sxtab%?\\t%0, %2, %1"
3908   [(set_attr "type" "alu_shift")
3909    (set_attr "predicable" "yes")]
3912 (define_insn "*thumb_extendqisi2"
3913   [(set (match_operand:SI 0 "register_operand" "=l,l")
3914         (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3915   "TARGET_THUMB && !arm_arch6"
3916   "*
3917   {
3918     rtx ops[3];
3919     rtx mem = XEXP (operands[1], 0);
3920     
3921     if (GET_CODE (mem) == CONST)
3922       mem = XEXP (mem, 0);
3923     
3924     if (GET_CODE (mem) == LABEL_REF)
3925       return \"ldr\\t%0, %1\";
3927     if (GET_CODE (mem) == PLUS
3928         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3929       return \"ldr\\t%0, %1\";
3930       
3931     if (which_alternative == 0)
3932       return \"ldrsb\\t%0, %1\";
3933       
3934     ops[0] = operands[0];
3935     
3936     if (GET_CODE (mem) == PLUS)
3937       {
3938         rtx a = XEXP (mem, 0);
3939         rtx b = XEXP (mem, 1);
3940         
3941         ops[1] = a;
3942         ops[2] = b;
3944         if (GET_CODE (a) == REG)
3945           {
3946             if (GET_CODE (b) == REG)
3947               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3948             else if (REGNO (a) == REGNO (ops[0]))
3949               {
3950                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3951                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3952                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3953               }
3954             else
3955               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3956           }
3957         else if (GET_CODE (b) != REG)
3958           abort ();
3959         else
3960           {
3961             if (REGNO (b) == REGNO (ops[0]))
3962               {
3963                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3964                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3965                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3966               }
3967             else
3968               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3969           }
3970       }
3971     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3972       {
3973         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3974         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3975         output_asm_insn (\"asr\\t%0, %0, #24\", 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,6")
3987    (set_attr "type" "load_byte,load_byte")
3988    (set_attr "pool_range" "32,32")]
3991 (define_insn "*thumb_extendqisi2_v6"
3992   [(set (match_operand:SI 0 "register_operand" "=l,l,l")
3993         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
3994   "TARGET_THUMB && arm_arch6"
3995   "*
3996   {
3997     rtx ops[3];
3998     rtx mem;
4000     if (which_alternative == 0)
4001       return \"sxtb\\t%0, %1\";
4003     mem = XEXP (operands[1], 0);
4004     
4005     if (GET_CODE (mem) == CONST)
4006       mem = XEXP (mem, 0);
4007     
4008     if (GET_CODE (mem) == LABEL_REF)
4009       return \"ldr\\t%0, %1\";
4011     if (GET_CODE (mem) == PLUS
4012         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4013       return \"ldr\\t%0, %1\";
4014       
4015     if (which_alternative == 0)
4016       return \"ldrsb\\t%0, %1\";
4017       
4018     ops[0] = operands[0];
4019     
4020     if (GET_CODE (mem) == PLUS)
4021       {
4022         rtx a = XEXP (mem, 0);
4023         rtx b = XEXP (mem, 1);
4024         
4025         ops[1] = a;
4026         ops[2] = b;
4028         if (GET_CODE (a) == REG)
4029           {
4030             if (GET_CODE (b) == REG)
4031               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4032             else if (REGNO (a) == REGNO (ops[0]))
4033               {
4034                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4035                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4036               }
4037             else
4038               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4039           }
4040         else if (GET_CODE (b) != REG)
4041           abort ();
4042         else
4043           {
4044             if (REGNO (b) == REGNO (ops[0]))
4045               {
4046                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4047                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4048               }
4049             else
4050               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4051           }
4052       }
4053     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4054       {
4055         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4056         output_asm_insn (\"sxtb\\t%0, %0\", ops);
4057       }
4058     else
4059       {
4060         ops[1] = mem;
4061         ops[2] = const0_rtx;
4062         
4063         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4064       }
4065     return \"\";
4066   }"
4067   [(set_attr "length" "2,2,4")
4068    (set_attr "type" "alu_shift,load_byte,load_byte")
4069    (set_attr "pool_range" "*,32,32")]
4072 (define_expand "extendsfdf2"
4073   [(set (match_operand:DF                  0 "s_register_operand" "")
4074         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
4075   "TARGET_ARM && TARGET_HARD_FLOAT"
4076   ""
4079 ;; Move insns (including loads and stores)
4081 ;; XXX Just some ideas about movti.
4082 ;; I don't think these are a good idea on the arm, there just aren't enough
4083 ;; registers
4084 ;;(define_expand "loadti"
4085 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
4086 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
4087 ;;  "" "")
4089 ;;(define_expand "storeti"
4090 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4091 ;;      (match_operand:TI 1 "s_register_operand" ""))]
4092 ;;  "" "")
4094 ;;(define_expand "movti"
4095 ;;  [(set (match_operand:TI 0 "general_operand" "")
4096 ;;      (match_operand:TI 1 "general_operand" ""))]
4097 ;;  ""
4098 ;;  "
4100 ;;  rtx insn;
4102 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4103 ;;    operands[1] = copy_to_reg (operands[1]);
4104 ;;  if (GET_CODE (operands[0]) == MEM)
4105 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4106 ;;  else if (GET_CODE (operands[1]) == MEM)
4107 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4108 ;;  else
4109 ;;    FAIL;
4111 ;;  emit_insn (insn);
4112 ;;  DONE;
4113 ;;}")
4115 ;; Recognize garbage generated above.
4117 ;;(define_insn ""
4118 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4119 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4120 ;;  ""
4121 ;;  "*
4122 ;;  {
4123 ;;    register mem = (which_alternative < 3);
4124 ;;    register const char *template;
4126 ;;    operands[mem] = XEXP (operands[mem], 0);
4127 ;;    switch (which_alternative)
4128 ;;      {
4129 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4130 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
4131 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
4132 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
4133 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
4134 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
4135 ;;      }
4136 ;;    output_asm_insn (template, operands);
4137 ;;    return \"\";
4138 ;;  }")
4140 (define_expand "movdi"
4141   [(set (match_operand:DI 0 "general_operand" "")
4142         (match_operand:DI 1 "general_operand" ""))]
4143   "TARGET_EITHER"
4144   "
4145   if (TARGET_THUMB)
4146     {
4147       if (!no_new_pseudos)
4148         {
4149           if (GET_CODE (operands[0]) != REG)
4150             operands[1] = force_reg (DImode, operands[1]);
4151         }
4152     }
4153   "
4156 (define_insn "*arm_movdi"
4157   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r ,m")
4158         (match_operand:DI 1 "di_operand"              "rIK,mi,r"))]
4159   "TARGET_ARM
4160   && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4161   && !TARGET_IWMMXT"
4162   "*
4163   return (output_move_double (operands));
4164   "
4165   [(set_attr "length" "8")
4166    (set_attr "type" "*,load2,store2")
4167    (set_attr "pool_range" "*,1020,*")
4168    (set_attr "neg_pool_range" "*,1008,*")]
4171 ;; We can't actually do base+index doubleword loads if the index and
4172 ;; destination overlap.  Split here so that we at least have chance to
4173 ;; schedule.
4174 (define_split
4175   [(set (match_operand:DI 0 "s_register_operand" "")
4176         (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4177                          (match_operand:SI 2 "s_register_operand" ""))))]
4178   "TARGET_LDRD
4179   && reg_overlap_mentioned_p (operands[0], operands[1])
4180   && reg_overlap_mentioned_p (operands[0], operands[2])"
4181   [(set (match_dup 4)
4182         (plus:SI (match_dup 1)
4183                  (match_dup 2)))
4184    (set (match_dup 0)
4185         (mem:DI (match_dup 4)))]
4186   "
4187   operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4188   "
4191 ;;; ??? This should have alternatives for constants.
4192 ;;; ??? This was originally identical to the movdf_insn pattern.
4193 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4194 ;;; thumb_reorg with a memory reference.
4195 (define_insn "*thumb_movdi_insn"
4196   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4197         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
4198   "TARGET_THUMB
4199    && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4200    && (   register_operand (operands[0], DImode)
4201        || register_operand (operands[1], DImode))"
4202   "*
4203   {
4204   switch (which_alternative)
4205     {
4206     default:
4207     case 0:
4208       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4209         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
4210       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
4211     case 1:
4212       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4213     case 2:
4214       operands[1] = GEN_INT (- INTVAL (operands[1]));
4215       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4216     case 3:
4217       return \"ldmia\\t%1, {%0, %H0}\";
4218     case 4:
4219       return \"stmia\\t%0, {%1, %H1}\";
4220     case 5:
4221       return thumb_load_double_from_address (operands);
4222     case 6:
4223       operands[2] = gen_rtx_MEM (SImode,
4224                              plus_constant (XEXP (operands[0], 0), 4));
4225       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4226       return \"\";
4227     case 7:
4228       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4229         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4230       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4231     }
4232   }"
4233   [(set_attr "length" "4,4,6,2,2,6,4,4")
4234    (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4235    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4238 (define_expand "movsi"
4239   [(set (match_operand:SI 0 "general_operand" "")
4240         (match_operand:SI 1 "general_operand" ""))]
4241   "TARGET_EITHER"
4242   "
4243   if (TARGET_ARM)
4244     {
4245       /* Everything except mem = const or mem = mem can be done easily.  */
4246       if (GET_CODE (operands[0]) == MEM)
4247         operands[1] = force_reg (SImode, operands[1]);
4248       if (arm_general_register_operand (operands[0], SImode)
4249           && GET_CODE (operands[1]) == CONST_INT
4250           && !(const_ok_for_arm (INTVAL (operands[1]))
4251                || const_ok_for_arm (~INTVAL (operands[1]))))
4252         {
4253            arm_split_constant (SET, SImode, NULL_RTX,
4254                                INTVAL (operands[1]), operands[0], NULL_RTX,
4255                                optimize && !no_new_pseudos);
4256           DONE;
4257         }
4258     }
4259   else /* TARGET_THUMB....  */
4260     {
4261       if (!no_new_pseudos)
4262         {
4263           if (GET_CODE (operands[0]) != REG)
4264             operands[1] = force_reg (SImode, operands[1]);
4265         }
4266     }
4267     
4268   if (flag_pic
4269       && (CONSTANT_P (operands[1])
4270          || symbol_mentioned_p (operands[1])
4271          || label_mentioned_p (operands[1])))
4272     operands[1] = legitimize_pic_address (operands[1], SImode,
4273                                           (no_new_pseudos ? operands[0] : 0));
4274   "
4277 (define_insn "*arm_movsi_insn"
4278   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4279         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
4280   "TARGET_ARM && ! TARGET_IWMMXT
4281    && !(TARGET_HARD_FLOAT && TARGET_VFP)
4282    && (   register_operand (operands[0], SImode)
4283        || register_operand (operands[1], SImode))"
4284   "@
4285    mov%?\\t%0, %1
4286    mvn%?\\t%0, #%B1
4287    ldr%?\\t%0, %1
4288    str%?\\t%1, %0"
4289   [(set_attr "type" "*,*,load1,store1")
4290    (set_attr "predicable" "yes")
4291    (set_attr "pool_range" "*,*,4096,*")
4292    (set_attr "neg_pool_range" "*,*,4084,*")]
4295 (define_split
4296   [(set (match_operand:SI 0 "arm_general_register_operand" "")
4297         (match_operand:SI 1 "const_int_operand" ""))]
4298   "TARGET_ARM
4299   && (!(const_ok_for_arm (INTVAL (operands[1]))
4300         || const_ok_for_arm (~INTVAL (operands[1]))))"
4301   [(clobber (const_int 0))]
4302   "
4303   arm_split_constant (SET, SImode, NULL_RTX, 
4304                       INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4305   DONE;
4306   "
4309 (define_insn "*thumb_movsi_insn"
4310   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4311         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4312   "TARGET_THUMB
4313    && (   register_operand (operands[0], SImode) 
4314        || register_operand (operands[1], SImode))"
4315   "@
4316    mov  %0, %1
4317    mov  %0, %1
4318    #
4319    #
4320    ldmia\\t%1, {%0}
4321    stmia\\t%0, {%1}
4322    ldr\\t%0, %1
4323    str\\t%1, %0
4324    mov\\t%0, %1"
4325   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4326    (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4327    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4330 (define_split 
4331   [(set (match_operand:SI 0 "register_operand" "")
4332         (match_operand:SI 1 "const_int_operand" ""))]
4333   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4334   [(set (match_dup 0) (match_dup 1))
4335    (set (match_dup 0) (neg:SI (match_dup 0)))]
4336   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4339 (define_split 
4340   [(set (match_operand:SI 0 "register_operand" "")
4341         (match_operand:SI 1 "const_int_operand" ""))]
4342   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4343   [(set (match_dup 0) (match_dup 1))
4344    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4345   "
4346   {
4347     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4348     unsigned HOST_WIDE_INT mask = 0xff;
4349     int i;
4350     
4351     for (i = 0; i < 25; i++)
4352       if ((val & (mask << i)) == val)
4353         break;
4355     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4356     if (i == 0)
4357       FAIL;
4359     operands[1] = GEN_INT (val >> i);
4360     operands[2] = GEN_INT (i);
4361   }"
4364 ;; When generating pic, we need to load the symbol offset into a register.
4365 ;; So that the optimizer does not confuse this with a normal symbol load
4366 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
4367 ;; since that is the only type of relocation we can use.
4369 ;; The rather odd constraints on the following are to force reload to leave
4370 ;; the insn alone, and to force the minipool generation pass to then move
4371 ;; the GOT symbol to memory.
4373 (define_insn "pic_load_addr_arm"
4374   [(set (match_operand:SI 0 "s_register_operand" "=r")
4375         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4376   "TARGET_ARM && flag_pic"
4377   "ldr%?\\t%0, %1"
4378   [(set_attr "type" "load1")
4379    (set (attr "pool_range")     (const_int 4096))
4380    (set (attr "neg_pool_range") (const_int 4084))]
4383 (define_insn "pic_load_addr_thumb"
4384   [(set (match_operand:SI 0 "s_register_operand" "=l")
4385         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4386   "TARGET_THUMB && flag_pic"
4387   "ldr\\t%0, %1"
4388   [(set_attr "type" "load1")
4389    (set (attr "pool_range") (const_int 1024))]
4392 ;; This variant is used for AOF assembly, since it needs to mention the
4393 ;; pic register in the rtl.
4394 (define_expand "pic_load_addr_based"
4395   [(set (match_operand:SI 0 "s_register_operand" "")
4396         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4397   "TARGET_ARM && flag_pic"
4398   "operands[2] = pic_offset_table_rtx;"
4401 (define_insn "*pic_load_addr_based_insn"
4402   [(set (match_operand:SI 0 "s_register_operand" "=r")
4403         (unspec:SI [(match_operand 1 "" "")
4404                     (match_operand 2 "s_register_operand" "r")]
4405                    UNSPEC_PIC_SYM))]
4406   "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4407   "*
4408 #ifdef AOF_ASSEMBLER
4409   operands[1] = aof_pic_entry (operands[1]);
4410 #endif
4411   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4412   return \"\";
4413   "
4414   [(set_attr "type" "load1")
4415    (set (attr "pool_range")
4416         (if_then_else (eq_attr "is_thumb" "yes")
4417                       (const_int 1024)
4418                       (const_int 4096)))
4419    (set (attr "neg_pool_range")
4420         (if_then_else (eq_attr "is_thumb" "yes")
4421                       (const_int 0)
4422                       (const_int 4084)))]
4425 (define_insn "pic_add_dot_plus_four"
4426   [(set (match_operand:SI 0 "register_operand" "+r")
4427         (unspec:SI [(plus:SI (match_dup 0)
4428                              (const (plus:SI (pc) (const_int 4))))]
4429                    UNSPEC_PIC_BASE))
4430    (use (label_ref (match_operand 1 "" "")))]
4431   "TARGET_THUMB && flag_pic"
4432   "*
4433   (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4434                              CODE_LABEL_NUMBER (operands[1]));
4435   return \"add\\t%0, %|pc\";
4436   "
4437   [(set_attr "length" "2")]
4440 (define_insn "pic_add_dot_plus_eight"
4441   [(set (match_operand:SI 0 "register_operand" "+r")
4442         (unspec:SI [(plus:SI (match_dup 0)
4443                              (const (plus:SI (pc) (const_int 8))))]
4444                    UNSPEC_PIC_BASE))
4445    (use (label_ref (match_operand 1 "" "")))]
4446   "TARGET_ARM && flag_pic"
4447   "*
4448     (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4449                                CODE_LABEL_NUMBER (operands[1]));
4450     return \"add%?\\t%0, %|pc, %0\";
4451   "
4452   [(set_attr "predicable" "yes")]
4455 (define_expand "builtin_setjmp_receiver"
4456   [(label_ref (match_operand 0 "" ""))]
4457   "flag_pic"
4458   "
4460   arm_load_pic_register ();
4461   DONE;
4464 ;; If copying one reg to another we can set the condition codes according to
4465 ;; its value.  Such a move is common after a return from subroutine and the
4466 ;; result is being tested against zero.
4468 (define_insn "*movsi_compare0"
4469   [(set (reg:CC CC_REGNUM)
4470         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4471                     (const_int 0)))
4472    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4473         (match_dup 1))]
4474   "TARGET_ARM"
4475   "@
4476    cmp%?\\t%0, #0
4477    sub%?s\\t%0, %1, #0"
4478   [(set_attr "conds" "set")]
4481 ;; Subroutine to store a half word from a register into memory.
4482 ;; Operand 0 is the source register (HImode)
4483 ;; Operand 1 is the destination address in a register (SImode)
4485 ;; In both this routine and the next, we must be careful not to spill
4486 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4487 ;; can generate unrecognizable rtl.
4489 (define_expand "storehi"
4490   [;; store the low byte
4491    (set (match_operand 1 "" "") (match_dup 3))
4492    ;; extract the high byte
4493    (set (match_dup 2)
4494         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4495    ;; store the high byte
4496    (set (match_dup 4) (match_dup 5))]
4497   "TARGET_ARM"
4498   "
4499   {
4500     rtx op1 = operands[1];
4501     rtx addr = XEXP (op1, 0);
4502     enum rtx_code code = GET_CODE (addr);
4504     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4505         || code == MINUS)
4506       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4508     operands[4] = adjust_address (op1, QImode, 1);
4509     operands[1] = adjust_address (operands[1], QImode, 0);
4510     operands[3] = gen_lowpart (QImode, operands[0]);
4511     operands[0] = gen_lowpart (SImode, operands[0]);
4512     operands[2] = gen_reg_rtx (SImode);
4513     operands[5] = gen_lowpart (QImode, operands[2]);
4514   }"
4517 (define_expand "storehi_bigend"
4518   [(set (match_dup 4) (match_dup 3))
4519    (set (match_dup 2)
4520         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4521    (set (match_operand 1 "" "") (match_dup 5))]
4522   "TARGET_ARM"
4523   "
4524   {
4525     rtx op1 = operands[1];
4526     rtx addr = XEXP (op1, 0);
4527     enum rtx_code code = GET_CODE (addr);
4529     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4530         || code == MINUS)
4531       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4533     operands[4] = adjust_address (op1, QImode, 1);
4534     operands[1] = adjust_address (operands[1], QImode, 0);
4535     operands[3] = gen_lowpart (QImode, operands[0]);
4536     operands[0] = gen_lowpart (SImode, operands[0]);
4537     operands[2] = gen_reg_rtx (SImode);
4538     operands[5] = gen_lowpart (QImode, operands[2]);
4539   }"
4542 ;; Subroutine to store a half word integer constant into memory.
4543 (define_expand "storeinthi"
4544   [(set (match_operand 0 "" "")
4545         (match_operand 1 "" ""))
4546    (set (match_dup 3) (match_dup 2))]
4547   "TARGET_ARM"
4548   "
4549   {
4550     HOST_WIDE_INT value = INTVAL (operands[1]);
4551     rtx addr = XEXP (operands[0], 0);
4552     rtx op0 = operands[0];
4553     enum rtx_code code = GET_CODE (addr);
4555     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4556         || code == MINUS)
4557       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4559     operands[1] = gen_reg_rtx (SImode);
4560     if (BYTES_BIG_ENDIAN)
4561       {
4562         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4563         if ((value & 255) == ((value >> 8) & 255))
4564           operands[2] = operands[1];
4565         else
4566           {
4567             operands[2] = gen_reg_rtx (SImode);
4568             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4569           }
4570       }
4571     else
4572       {
4573         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4574         if ((value & 255) == ((value >> 8) & 255))
4575           operands[2] = operands[1];
4576         else
4577           {
4578             operands[2] = gen_reg_rtx (SImode);
4579             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4580           }
4581       }
4583     operands[3] = adjust_address (op0, QImode, 1);
4584     operands[0] = adjust_address (operands[0], QImode, 0);
4585     operands[2] = gen_lowpart (QImode, operands[2]);
4586     operands[1] = gen_lowpart (QImode, operands[1]);
4587   }"
4590 (define_expand "storehi_single_op"
4591   [(set (match_operand:HI 0 "memory_operand" "")
4592         (match_operand:HI 1 "general_operand" ""))]
4593   "TARGET_ARM && arm_arch4"
4594   "
4595   if (!s_register_operand (operands[1], HImode))
4596     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4597   "
4600 (define_expand "movhi"
4601   [(set (match_operand:HI 0 "general_operand" "")
4602         (match_operand:HI 1 "general_operand" ""))]
4603   "TARGET_EITHER"
4604   "
4605   if (TARGET_ARM)
4606     {
4607       if (!no_new_pseudos)
4608         {
4609           if (GET_CODE (operands[0]) == MEM)
4610             {
4611               if (arm_arch4)
4612                 {
4613                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4614                   DONE;
4615                 }
4616               if (GET_CODE (operands[1]) == CONST_INT)
4617                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4618               else
4619                 {
4620                   if (GET_CODE (operands[1]) == MEM)
4621                     operands[1] = force_reg (HImode, operands[1]);
4622                   if (BYTES_BIG_ENDIAN)
4623                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4624                   else
4625                    emit_insn (gen_storehi (operands[1], operands[0]));
4626                 }
4627               DONE;
4628             }
4629           /* Sign extend a constant, and keep it in an SImode reg.  */
4630           else if (GET_CODE (operands[1]) == CONST_INT)
4631             {
4632               rtx reg = gen_reg_rtx (SImode);
4633               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4635               /* If the constant is already valid, leave it alone.  */
4636               if (!const_ok_for_arm (val))
4637                 {
4638                   /* If setting all the top bits will make the constant 
4639                      loadable in a single instruction, then set them.  
4640                      Otherwise, sign extend the number.  */
4642                   if (const_ok_for_arm (~(val | ~0xffff)))
4643                     val |= ~0xffff;
4644                   else if (val & 0x8000)
4645                     val |= ~0xffff;
4646                 }
4648               emit_insn (gen_movsi (reg, GEN_INT (val)));
4649               operands[1] = gen_lowpart (HImode, reg);
4650             }
4651           else if (arm_arch4 && optimize && !no_new_pseudos
4652                    && GET_CODE (operands[1]) == MEM)
4653             {
4654               rtx reg = gen_reg_rtx (SImode);
4656               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4657               operands[1] = gen_lowpart (HImode, reg);
4658             }
4659           else if (!arm_arch4)
4660             {
4661               if (GET_CODE (operands[1]) == MEM)
4662                 {
4663                   rtx base;
4664                   rtx offset = const0_rtx;
4665                   rtx reg = gen_reg_rtx (SImode);
4667                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4668                        || (GET_CODE (base) == PLUS
4669                            && (GET_CODE (offset = XEXP (base, 1))
4670                                == CONST_INT)
4671                            && ((INTVAL(offset) & 1) != 1)
4672                            && GET_CODE (base = XEXP (base, 0)) == REG))
4673                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4674                     {
4675                       HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4676                       rtx new;
4678                       new = gen_rtx_MEM (SImode,
4679                                          plus_constant (base, new_offset));
4680                       MEM_COPY_ATTRIBUTES (new, operands[1]);
4681                       emit_insn (gen_movsi (reg, new));
4682                       if (((INTVAL (offset) & 2) != 0)
4683                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4684                         {
4685                           rtx reg2 = gen_reg_rtx (SImode);
4687                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4688                           reg = reg2;
4689                         }
4690                     }
4691                   else
4692                     emit_insn (gen_movhi_bytes (reg, operands[1]));
4694                   operands[1] = gen_lowpart (HImode, reg);
4695                }
4696            }
4697         }
4698       /* Handle loading a large integer during reload.  */
4699       else if (GET_CODE (operands[1]) == CONST_INT
4700                && !const_ok_for_arm (INTVAL (operands[1]))
4701                && !const_ok_for_arm (~INTVAL (operands[1])))
4702         {
4703           /* Writing a constant to memory needs a scratch, which should
4704              be handled with SECONDARY_RELOADs.  */
4705           if (GET_CODE (operands[0]) != REG)
4706             abort ();
4708           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4709           emit_insn (gen_movsi (operands[0], operands[1]));
4710           DONE;
4711        }
4712     }
4713   else /* TARGET_THUMB */
4714     {
4715       if (!no_new_pseudos)
4716         {
4717           if (GET_CODE (operands[0]) != REG)
4718             operands[1] = force_reg (HImode, operands[1]);
4720           /* ??? We shouldn't really get invalid addresses here, but this can
4721              happen if we are passed a SP (never OK for HImode/QImode) or 
4722              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4723              HImode/QImode) relative address.  */
4724           /* ??? This should perhaps be fixed elsewhere, for instance, in
4725              fixup_stack_1, by checking for other kinds of invalid addresses,
4726              e.g. a bare reference to a virtual register.  This may confuse the
4727              alpha though, which must handle this case differently.  */
4728           if (GET_CODE (operands[0]) == MEM
4729               && !memory_address_p (GET_MODE (operands[0]),
4730                                     XEXP (operands[0], 0)))
4731             operands[0]
4732               = replace_equiv_address (operands[0],
4733                                        copy_to_reg (XEXP (operands[0], 0)));
4734    
4735           if (GET_CODE (operands[1]) == MEM
4736               && !memory_address_p (GET_MODE (operands[1]),
4737                                     XEXP (operands[1], 0)))
4738             operands[1]
4739               = replace_equiv_address (operands[1],
4740                                        copy_to_reg (XEXP (operands[1], 0)));
4741         }
4742       /* Handle loading a large integer during reload.  */
4743       else if (GET_CODE (operands[1]) == CONST_INT
4744                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4745         {
4746           /* Writing a constant to memory needs a scratch, which should
4747              be handled with SECONDARY_RELOADs.  */
4748           if (GET_CODE (operands[0]) != REG)
4749             abort ();
4751           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4752           emit_insn (gen_movsi (operands[0], operands[1]));
4753           DONE;
4754         }
4755     }
4756   "
4759 (define_insn "*thumb_movhi_insn"
4760   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4761         (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
4762   "TARGET_THUMB
4763    && (   register_operand (operands[0], HImode)
4764        || register_operand (operands[1], HImode))"
4765   "*
4766   switch (which_alternative)
4767     {
4768     case 0: return \"add        %0, %1, #0\";
4769     case 2: return \"strh       %1, %0\";
4770     case 3: return \"mov        %0, %1\";
4771     case 4: return \"mov        %0, %1\";
4772     case 5: return \"mov        %0, %1\";
4773     default: abort ();
4774     case 1:
4775       /* The stack pointer can end up being taken as an index register.
4776           Catch this case here and deal with it.  */
4777       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4778           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4779           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4780         {
4781           rtx ops[2];
4782           ops[0] = operands[0];
4783           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4784       
4785           output_asm_insn (\"mov        %0, %1\", ops);
4787           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4788     
4789         }
4790       return \"ldrh     %0, %1\";
4791     }"
4792   [(set_attr "length" "2,4,2,2,2,2")
4793    (set_attr "type" "*,load1,store1,*,*,*")]
4797 (define_expand "movhi_bytes"
4798   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4799    (set (match_dup 3)
4800         (zero_extend:SI (match_dup 6)))
4801    (set (match_operand:SI 0 "" "")
4802          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4803   "TARGET_ARM"
4804   "
4805   {
4806     rtx mem1, mem2;
4807     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4809     mem1 = gen_rtx_MEM (QImode, addr);
4810     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4811     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4812     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4813     operands[0] = gen_lowpart (SImode, operands[0]);
4814     operands[1] = mem1;
4815     operands[2] = gen_reg_rtx (SImode);
4816     operands[3] = gen_reg_rtx (SImode);
4817     operands[6] = mem2;
4819     if (BYTES_BIG_ENDIAN)
4820       {
4821         operands[4] = operands[2];
4822         operands[5] = operands[3];
4823       }
4824     else
4825       {
4826         operands[4] = operands[3];
4827         operands[5] = operands[2];
4828       }
4829   }"
4832 (define_expand "movhi_bigend"
4833   [(set (match_dup 2)
4834         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4835                    (const_int 16)))
4836    (set (match_dup 3)
4837         (ashiftrt:SI (match_dup 2) (const_int 16)))
4838    (set (match_operand:HI 0 "s_register_operand" "")
4839         (match_dup 4))]
4840   "TARGET_ARM"
4841   "
4842   operands[2] = gen_reg_rtx (SImode);
4843   operands[3] = gen_reg_rtx (SImode);
4844   operands[4] = gen_lowpart (HImode, operands[3]);
4845   "
4848 ;; Pattern to recognize insn generated default case above
4849 (define_insn "*movhi_insn_arch4"
4850   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4851         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4852   "TARGET_ARM
4853    && arm_arch4
4854    && (GET_CODE (operands[1]) != CONST_INT
4855        || const_ok_for_arm (INTVAL (operands[1]))
4856        || const_ok_for_arm (~INTVAL (operands[1])))"
4857   "@
4858    mov%?\\t%0, %1\\t%@ movhi
4859    mvn%?\\t%0, #%B1\\t%@ movhi
4860    str%?h\\t%1, %0\\t%@ movhi 
4861    ldr%?h\\t%0, %1\\t%@ movhi"
4862   [(set_attr "type" "*,*,store1,load1")
4863    (set_attr "predicable" "yes")
4864    (set_attr "pool_range" "*,*,*,256")
4865    (set_attr "neg_pool_range" "*,*,*,244")]
4868 (define_insn "*movhi_bytes"
4869   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4870         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4871   "TARGET_ARM"
4872   "@
4873    mov%?\\t%0, %1\\t%@ movhi
4874    mvn%?\\t%0, #%B1\\t%@ movhi"
4875   [(set_attr "predicable" "yes")]
4878 (define_insn "thumb_movhi_clobber"
4879   [(set (match_operand:HI     0 "memory_operand"   "=m")
4880         (match_operand:HI     1 "register_operand" "l"))
4881    (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4882   "TARGET_THUMB"
4883   "*
4884   abort ();"
4886         
4887 ;; We use a DImode scratch because we may occasionally need an additional
4888 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4889 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4890 (define_expand "reload_outhi"
4891   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4892               (match_operand:HI 1 "s_register_operand"        "r")
4893               (match_operand:DI 2 "s_register_operand"        "=&l")])]
4894   "TARGET_EITHER"
4895   "if (TARGET_ARM)
4896      arm_reload_out_hi (operands);
4897    else
4898      thumb_reload_out_hi (operands);
4899   DONE;
4900   "
4903 (define_expand "reload_inhi"
4904   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4905               (match_operand:HI 1 "arm_reload_memory_operand" "o")
4906               (match_operand:DI 2 "s_register_operand" "=&r")])]
4907   "TARGET_EITHER"
4908   "
4909   if (TARGET_ARM)
4910     arm_reload_in_hi (operands);
4911   else
4912     thumb_reload_out_hi (operands);
4913   DONE;
4916 (define_expand "movqi"
4917   [(set (match_operand:QI 0 "general_operand" "")
4918         (match_operand:QI 1 "general_operand" ""))]
4919   "TARGET_EITHER"
4920   "
4921   if (TARGET_ARM)
4922     {
4923       /* Everything except mem = const or mem = mem can be done easily */
4925       if (!no_new_pseudos)
4926         {
4927           if (GET_CODE (operands[1]) == CONST_INT)
4928             {
4929               rtx reg = gen_reg_rtx (SImode);
4931               emit_insn (gen_movsi (reg, operands[1]));
4932               operands[1] = gen_lowpart (QImode, reg);
4933             }
4934           if (GET_CODE (operands[1]) == MEM && optimize > 0)
4935             {
4936               rtx reg = gen_reg_rtx (SImode);
4938               emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4939               operands[1] = gen_lowpart (QImode, reg);
4940             }
4941           if (GET_CODE (operands[0]) == MEM)
4942             operands[1] = force_reg (QImode, operands[1]);
4943         }
4944     }
4945   else /* TARGET_THUMB */
4946     {
4947       if (!no_new_pseudos)
4948         {
4949           if (GET_CODE (operands[0]) != REG)
4950             operands[1] = force_reg (QImode, operands[1]);
4952           /* ??? We shouldn't really get invalid addresses here, but this can
4953              happen if we are passed a SP (never OK for HImode/QImode) or
4954              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4955              HImode/QImode) relative address.  */
4956           /* ??? This should perhaps be fixed elsewhere, for instance, in
4957              fixup_stack_1, by checking for other kinds of invalid addresses,
4958              e.g. a bare reference to a virtual register.  This may confuse the
4959              alpha though, which must handle this case differently.  */
4960           if (GET_CODE (operands[0]) == MEM
4961               && !memory_address_p (GET_MODE (operands[0]),
4962                                      XEXP (operands[0], 0)))
4963             operands[0]
4964               = replace_equiv_address (operands[0],
4965                                        copy_to_reg (XEXP (operands[0], 0)));
4966           if (GET_CODE (operands[1]) == MEM
4967               && !memory_address_p (GET_MODE (operands[1]),
4968                                     XEXP (operands[1], 0)))
4969              operands[1]
4970                = replace_equiv_address (operands[1],
4971                                         copy_to_reg (XEXP (operands[1], 0)));
4972         }
4973       /* Handle loading a large integer during reload.  */
4974       else if (GET_CODE (operands[1]) == CONST_INT
4975                && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4976         {
4977           /* Writing a constant to memory needs a scratch, which should
4978              be handled with SECONDARY_RELOADs.  */
4979           if (GET_CODE (operands[0]) != REG)
4980             abort ();
4982           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4983           emit_insn (gen_movsi (operands[0], operands[1]));
4984           DONE;
4985        }
4986     }
4987   "
4991 (define_insn "*arm_movqi_insn"
4992   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4993         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4994   "TARGET_ARM
4995    && (   register_operand (operands[0], QImode)
4996        || register_operand (operands[1], QImode))"
4997   "@
4998    mov%?\\t%0, %1
4999    mvn%?\\t%0, #%B1
5000    ldr%?b\\t%0, %1
5001    str%?b\\t%1, %0"
5002   [(set_attr "type" "*,*,load1,store1")
5003    (set_attr "predicable" "yes")]
5006 (define_insn "*thumb_movqi_insn"
5007   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5008         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
5009   "TARGET_THUMB
5010    && (   register_operand (operands[0], QImode)
5011        || register_operand (operands[1], QImode))"
5012   "@
5013    add\\t%0, %1, #0
5014    ldrb\\t%0, %1
5015    strb\\t%1, %0
5016    mov\\t%0, %1
5017    mov\\t%0, %1
5018    mov\\t%0, %1"
5019   [(set_attr "length" "2")
5020    (set_attr "type" "*,load1,store1,*,*,*")
5021    (set_attr "pool_range" "*,32,*,*,*,*")]
5024 (define_expand "movsf"
5025   [(set (match_operand:SF 0 "general_operand" "")
5026         (match_operand:SF 1 "general_operand" ""))]
5027   "TARGET_EITHER"
5028   "
5029   if (TARGET_ARM)
5030     {
5031       if (GET_CODE (operands[0]) == MEM)
5032         operands[1] = force_reg (SFmode, operands[1]);
5033     }
5034   else /* TARGET_THUMB */
5035     {
5036       if (!no_new_pseudos)
5037         {
5038            if (GET_CODE (operands[0]) != REG)
5039              operands[1] = force_reg (SFmode, operands[1]);
5040         }
5041     }
5042   "
5045 (define_split
5046   [(set (match_operand:SF 0 "nonimmediate_operand" "")
5047         (match_operand:SF 1 "immediate_operand" ""))]
5048   "TARGET_ARM
5049    && !(TARGET_HARD_FLOAT && TARGET_FPA)
5050    && reload_completed
5051    && GET_CODE (operands[1]) == CONST_DOUBLE"
5052   [(set (match_dup 2) (match_dup 3))]
5053   "
5054   operands[2] = gen_lowpart (SImode, operands[0]);
5055   operands[3] = gen_lowpart (SImode, operands[1]);
5056   if (operands[2] == 0 || operands[3] == 0)
5057     FAIL;
5058   "
5061 (define_insn "*arm_movsf_soft_insn"
5062   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5063         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
5064   "TARGET_ARM
5065    && TARGET_SOFT_FLOAT
5066    && (GET_CODE (operands[0]) != MEM
5067        || register_operand (operands[1], SFmode))"
5068   "@
5069    mov%?\\t%0, %1
5070    ldr%?\\t%0, %1\\t%@ float
5071    str%?\\t%1, %0\\t%@ float"
5072   [(set_attr "length" "4,4,4")
5073    (set_attr "predicable" "yes")
5074    (set_attr "type" "*,load1,store1")
5075    (set_attr "pool_range" "*,4096,*")
5076    (set_attr "neg_pool_range" "*,4084,*")]
5079 ;;; ??? This should have alternatives for constants.
5080 (define_insn "*thumb_movsf_insn"
5081   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5082         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5083   "TARGET_THUMB
5084    && (   register_operand (operands[0], SFmode) 
5085        || register_operand (operands[1], SFmode))"
5086   "@
5087    add\\t%0, %1, #0
5088    ldmia\\t%1, {%0}
5089    stmia\\t%0, {%1}
5090    ldr\\t%0, %1
5091    str\\t%1, %0
5092    mov\\t%0, %1
5093    mov\\t%0, %1"
5094   [(set_attr "length" "2")
5095    (set_attr "type" "*,load1,store1,load1,store1,*,*")
5096    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5099 (define_expand "movdf"
5100   [(set (match_operand:DF 0 "general_operand" "")
5101         (match_operand:DF 1 "general_operand" ""))]
5102   "TARGET_EITHER"
5103   "
5104   if (TARGET_ARM)
5105     {
5106       if (GET_CODE (operands[0]) == MEM)
5107         operands[1] = force_reg (DFmode, operands[1]);
5108     }
5109   else /* TARGET_THUMB */
5110     {
5111       if (!no_new_pseudos)
5112         {
5113           if (GET_CODE (operands[0]) != REG)
5114             operands[1] = force_reg (DFmode, operands[1]);
5115         }
5116     }
5117   "
5120 ;; Reloading a df mode value stored in integer regs to memory can require a
5121 ;; scratch reg.
5122 (define_expand "reload_outdf"
5123   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5124    (match_operand:DF 1 "s_register_operand" "r")
5125    (match_operand:SI 2 "s_register_operand" "=&r")]
5126   "TARGET_ARM"
5127   "
5128   {
5129     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5131     if (code == REG)
5132       operands[2] = XEXP (operands[0], 0);
5133     else if (code == POST_INC || code == PRE_DEC)
5134       {
5135         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5136         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5137         emit_insn (gen_movdi (operands[0], operands[1]));
5138         DONE;
5139       }
5140     else if (code == PRE_INC)
5141       {
5142         rtx reg = XEXP (XEXP (operands[0], 0), 0);
5144         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5145         operands[2] = reg;
5146       }
5147     else if (code == POST_DEC)
5148       operands[2] = XEXP (XEXP (operands[0], 0), 0);
5149     else
5150       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5151                              XEXP (XEXP (operands[0], 0), 1)));
5153     emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5154                             operands[1]));
5156     if (code == POST_DEC)
5157       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5159     DONE;
5160   }"
5163 (define_insn "*movdf_soft_insn"
5164   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
5165         (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
5166   "TARGET_ARM && TARGET_SOFT_FLOAT
5167   "
5168   "* return output_move_double (operands);"
5169   [(set_attr "length" "8,8,8")
5170    (set_attr "type" "*,load2,store2")
5171    (set_attr "pool_range" "1020")
5172    (set_attr "neg_pool_range" "1008")]
5175 ;;; ??? This should have alternatives for constants.
5176 ;;; ??? This was originally identical to the movdi_insn pattern.
5177 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5178 ;;; thumb_reorg with a memory reference.
5179 (define_insn "*thumb_movdf_insn"
5180   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5181         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5182   "TARGET_THUMB
5183    && (   register_operand (operands[0], DFmode)
5184        || register_operand (operands[1], DFmode))"
5185   "*
5186   switch (which_alternative)
5187     {
5188     default:
5189     case 0:
5190       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5191         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5192       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5193     case 1:
5194       return \"ldmia\\t%1, {%0, %H0}\";
5195     case 2:
5196       return \"stmia\\t%0, {%1, %H1}\";
5197     case 3:
5198       return thumb_load_double_from_address (operands);
5199     case 4:
5200       operands[2] = gen_rtx_MEM (SImode,
5201                                  plus_constant (XEXP (operands[0], 0), 4));
5202       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5203       return \"\";
5204     case 5:
5205       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5206         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5207       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5208     }
5209   "
5210   [(set_attr "length" "4,2,2,6,4,4")
5211    (set_attr "type" "*,load2,store2,load2,store2,*")
5212    (set_attr "pool_range" "*,*,*,1020,*,*")]
5215 ;; Vector Moves
5216 (define_expand "movv2si"
5217   [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5218         (match_operand:V2SI 1 "general_operand" ""))]
5219   "TARGET_REALLY_IWMMXT"
5223 (define_expand "movv4hi"
5224   [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5225         (match_operand:V4HI 1 "general_operand" ""))]
5226   "TARGET_REALLY_IWMMXT"
5230 (define_expand "movv8qi"
5231   [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5232         (match_operand:V8QI 1 "general_operand" ""))]
5233   "TARGET_REALLY_IWMMXT"
5238 ;; load- and store-multiple insns
5239 ;; The arm can load/store any set of registers, provided that they are in
5240 ;; ascending order; but that is beyond GCC so stick with what it knows.
5242 (define_expand "load_multiple"
5243   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5244                           (match_operand:SI 1 "" ""))
5245                      (use (match_operand:SI 2 "" ""))])]
5246   "TARGET_ARM"
5247   "
5248   /* Support only fixed point registers.  */
5249   if (GET_CODE (operands[2]) != CONST_INT
5250       || INTVAL (operands[2]) > 14
5251       || INTVAL (operands[2]) < 2
5252       || GET_CODE (operands[1]) != MEM
5253       || GET_CODE (operands[0]) != REG
5254       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5255       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5256     FAIL;
5258   operands[3]
5259     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5260                              force_reg (SImode, XEXP (operands[1], 0)),
5261                              TRUE, FALSE, MEM_READONLY_P (operands[1]),
5262                              MEM_IN_STRUCT_P (operands[1]),
5263                              MEM_SCALAR_P (operands[1]));
5264   "
5267 ;; Load multiple with write-back
5269 (define_insn "*ldmsi_postinc4"
5270   [(match_parallel 0 "load_multiple_operation"
5271     [(set (match_operand:SI 1 "s_register_operand" "=r")
5272           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5273                    (const_int 16)))
5274      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5275           (mem:SI (match_dup 2)))
5276      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5277           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5278      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5279           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5280      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5281           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5282   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5283   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5284   [(set_attr "type" "load4")
5285    (set_attr "predicable" "yes")]
5288 (define_insn "*ldmsi_postinc3"
5289   [(match_parallel 0 "load_multiple_operation"
5290     [(set (match_operand:SI 1 "s_register_operand" "=r")
5291           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5292                    (const_int 12)))
5293      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5294           (mem:SI (match_dup 2)))
5295      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5296           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5297      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5298           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5299   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5300   "ldm%?ia\\t%1!, {%3, %4, %5}"
5301   [(set_attr "type" "load3")
5302    (set_attr "predicable" "yes")]
5305 (define_insn "*ldmsi_postinc2"
5306   [(match_parallel 0 "load_multiple_operation"
5307     [(set (match_operand:SI 1 "s_register_operand" "=r")
5308           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5309                    (const_int 8)))
5310      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5311           (mem:SI (match_dup 2)))
5312      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5313           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5314   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5315   "ldm%?ia\\t%1!, {%3, %4}"
5316   [(set_attr "type" "load2")
5317    (set_attr "predicable" "yes")]
5320 ;; Ordinary load multiple
5322 (define_insn "*ldmsi4"
5323   [(match_parallel 0 "load_multiple_operation"
5324     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5325           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5326      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5327           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5328      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5329           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5330      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5331           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5332   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5333   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5334   [(set_attr "type" "load4")
5335    (set_attr "predicable" "yes")]
5338 (define_insn "*ldmsi3"
5339   [(match_parallel 0 "load_multiple_operation"
5340     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5341           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5342      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5343           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5344      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5345           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5346   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5347   "ldm%?ia\\t%1, {%2, %3, %4}"
5348   [(set_attr "type" "load3")
5349    (set_attr "predicable" "yes")]
5352 (define_insn "*ldmsi2"
5353   [(match_parallel 0 "load_multiple_operation"
5354     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5355           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5356      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5357           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5358   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5359   "ldm%?ia\\t%1, {%2, %3}"
5360   [(set_attr "type" "load2")
5361    (set_attr "predicable" "yes")]
5364 (define_expand "store_multiple"
5365   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5366                           (match_operand:SI 1 "" ""))
5367                      (use (match_operand:SI 2 "" ""))])]
5368   "TARGET_ARM"
5369   "
5370   /* Support only fixed point registers.  */
5371   if (GET_CODE (operands[2]) != CONST_INT
5372       || INTVAL (operands[2]) > 14
5373       || INTVAL (operands[2]) < 2
5374       || GET_CODE (operands[1]) != REG
5375       || GET_CODE (operands[0]) != MEM
5376       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5377       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5378     FAIL;
5380   operands[3]
5381     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5382                               force_reg (SImode, XEXP (operands[0], 0)),
5383                               TRUE, FALSE, MEM_READONLY_P (operands[0]),
5384                               MEM_IN_STRUCT_P (operands[0]), 
5385                               MEM_SCALAR_P (operands[0]));
5386   "
5389 ;; Store multiple with write-back
5391 (define_insn "*stmsi_postinc4"
5392   [(match_parallel 0 "store_multiple_operation"
5393     [(set (match_operand:SI 1 "s_register_operand" "=r")
5394           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5395                    (const_int 16)))
5396      (set (mem:SI (match_dup 2))
5397           (match_operand:SI 3 "arm_hard_register_operand" ""))
5398      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5399           (match_operand:SI 4 "arm_hard_register_operand" ""))
5400      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5401           (match_operand:SI 5 "arm_hard_register_operand" ""))
5402      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5403           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5404   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5405   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5406   [(set_attr "predicable" "yes")
5407    (set_attr "type" "store4")]
5410 (define_insn "*stmsi_postinc3"
5411   [(match_parallel 0 "store_multiple_operation"
5412     [(set (match_operand:SI 1 "s_register_operand" "=r")
5413           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5414                    (const_int 12)))
5415      (set (mem:SI (match_dup 2))
5416           (match_operand:SI 3 "arm_hard_register_operand" ""))
5417      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5418           (match_operand:SI 4 "arm_hard_register_operand" ""))
5419      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5420           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5421   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5422   "stm%?ia\\t%1!, {%3, %4, %5}"
5423   [(set_attr "predicable" "yes")
5424    (set_attr "type" "store3")]
5427 (define_insn "*stmsi_postinc2"
5428   [(match_parallel 0 "store_multiple_operation"
5429     [(set (match_operand:SI 1 "s_register_operand" "=r")
5430           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5431                    (const_int 8)))
5432      (set (mem:SI (match_dup 2))
5433           (match_operand:SI 3 "arm_hard_register_operand" ""))
5434      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5435           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5436   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5437   "stm%?ia\\t%1!, {%3, %4}"
5438   [(set_attr "predicable" "yes")
5439    (set_attr "type" "store2")]
5442 ;; Ordinary store multiple
5444 (define_insn "*stmsi4"
5445   [(match_parallel 0 "store_multiple_operation"
5446     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5447           (match_operand:SI 2 "arm_hard_register_operand" ""))
5448      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5449           (match_operand:SI 3 "arm_hard_register_operand" ""))
5450      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5451           (match_operand:SI 4 "arm_hard_register_operand" ""))
5452      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5453           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5454   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5455   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5456   [(set_attr "predicable" "yes")
5457    (set_attr "type" "store4")]
5460 (define_insn "*stmsi3"
5461   [(match_parallel 0 "store_multiple_operation"
5462     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5463           (match_operand:SI 2 "arm_hard_register_operand" ""))
5464      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5465           (match_operand:SI 3 "arm_hard_register_operand" ""))
5466      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5467           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5468   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5469   "stm%?ia\\t%1, {%2, %3, %4}"
5470   [(set_attr "predicable" "yes")
5471    (set_attr "type" "store3")]
5474 (define_insn "*stmsi2"
5475   [(match_parallel 0 "store_multiple_operation"
5476     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5477           (match_operand:SI 2 "arm_hard_register_operand" ""))
5478      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5479           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5480   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5481   "stm%?ia\\t%1, {%2, %3}"
5482   [(set_attr "predicable" "yes")
5483    (set_attr "type" "store2")]
5486 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5487 ;; We could let this apply for blocks of less than this, but it clobbers so
5488 ;; many registers that there is then probably a better way.
5490 (define_expand "movmemqi"
5491   [(match_operand:BLK 0 "general_operand" "")
5492    (match_operand:BLK 1 "general_operand" "")
5493    (match_operand:SI 2 "const_int_operand" "")
5494    (match_operand:SI 3 "const_int_operand" "")]
5495   "TARGET_EITHER"
5496   "
5497   if (TARGET_ARM)
5498     {
5499       if (arm_gen_movmemqi (operands))
5500         DONE;
5501       FAIL;
5502     }
5503   else /* TARGET_THUMB */
5504     {
5505       if (   INTVAL (operands[3]) != 4
5506           || INTVAL (operands[2]) > 48)
5507         FAIL;
5509       thumb_expand_movmemqi (operands);
5510       DONE;
5511     }
5512   "
5515 ;; Thumb block-move insns
5517 (define_insn "movmem12b"
5518   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5519         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5520    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5521         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5522    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5523         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5524    (set (match_operand:SI 0 "register_operand" "=l")
5525         (plus:SI (match_dup 2) (const_int 12)))
5526    (set (match_operand:SI 1 "register_operand" "=l")
5527         (plus:SI (match_dup 3) (const_int 12)))
5528    (clobber (match_scratch:SI 4 "=&l"))
5529    (clobber (match_scratch:SI 5 "=&l"))
5530    (clobber (match_scratch:SI 6 "=&l"))]
5531   "TARGET_THUMB"
5532   "* return thumb_output_move_mem_multiple (3, operands);"
5533   [(set_attr "length" "4")
5534    ; This isn't entirely accurate...  It loads as well, but in terms of
5535    ; scheduling the following insn it is better to consider it as a store
5536    (set_attr "type" "store3")]
5539 (define_insn "movmem8b"
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 (match_operand:SI 0 "register_operand" "=l")
5545         (plus:SI (match_dup 2) (const_int 8)))
5546    (set (match_operand:SI 1 "register_operand" "=l")
5547         (plus:SI (match_dup 3) (const_int 8)))
5548    (clobber (match_scratch:SI 4 "=&l"))
5549    (clobber (match_scratch:SI 5 "=&l"))]
5550   "TARGET_THUMB"
5551   "* return thumb_output_move_mem_multiple (2, operands);"
5552   [(set_attr "length" "4")
5553    ; This isn't entirely accurate...  It loads as well, but in terms of
5554    ; scheduling the following insn it is better to consider it as a store
5555    (set_attr "type" "store2")]
5560 ;; Compare & branch insns
5561 ;; The range calculations are based as follows:
5562 ;; For forward branches, the address calculation returns the address of
5563 ;; the next instruction.  This is 2 beyond the branch instruction.
5564 ;; For backward branches, the address calculation returns the address of
5565 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5566 ;; instruction for the shortest sequence, and 4 before the branch instruction
5567 ;; if we have to jump around an unconditional branch.
5568 ;; To the basic branch range the PC offset must be added (this is +4).
5569 ;; So for forward branches we have 
5570 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5571 ;; And for backward branches we have 
5572 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5574 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5575 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5577 (define_expand "cbranchsi4"
5578   [(set (pc) (if_then_else
5579               (match_operator 0 "arm_comparison_operator"
5580                [(match_operand:SI 1 "s_register_operand" "")
5581                 (match_operand:SI 2 "nonmemory_operand" "")])
5582               (label_ref (match_operand 3 "" ""))
5583               (pc)))]
5584   "TARGET_THUMB"
5585   "
5586   if (thumb_cmpneg_operand (operands[2], SImode))
5587     {
5588       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5589                                               operands[3], operands[0]));
5590       DONE;
5591     }
5592   if (!thumb_cmp_operand (operands[2], SImode))
5593     operands[2] = force_reg (SImode, operands[2]);
5594   ")
5596 (define_insn "*cbranchsi4_insn"
5597   [(set (pc) (if_then_else
5598               (match_operator 0 "arm_comparison_operator"
5599                [(match_operand:SI 1 "s_register_operand" "l,*h")
5600                 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5601               (label_ref (match_operand 3 "" ""))
5602               (pc)))]
5603   "TARGET_THUMB"
5604   "*
5605   output_asm_insn (\"cmp\\t%1, %2\", operands);
5607   switch (get_attr_length (insn))
5608     {
5609     case 4:  return \"b%d0\\t%l3\";
5610     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5611     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5612     }
5613   "
5614   [(set (attr "far_jump")
5615         (if_then_else
5616             (eq_attr "length" "8")
5617             (const_string "yes")
5618             (const_string "no")))
5619    (set (attr "length") 
5620         (if_then_else
5621             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5622                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5623             (const_int 4)
5624             (if_then_else
5625                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5626                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5627                 (const_int 6)
5628                 (const_int 8))))]
5631 (define_insn "cbranchsi4_scratch"
5632   [(set (pc) (if_then_else
5633               (match_operator 4 "arm_comparison_operator"
5634                [(match_operand:SI 1 "s_register_operand" "l,0")
5635                 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5636               (label_ref (match_operand 3 "" ""))
5637               (pc)))
5638    (clobber (match_scratch:SI 0 "=l,l"))]
5639   "TARGET_THUMB"
5640   "*
5641   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5643   switch (get_attr_length (insn))
5644     {
5645     case 4:  return \"b%d4\\t%l3\";
5646     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5647     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5648     }
5649   "
5650   [(set (attr "far_jump")
5651         (if_then_else
5652             (eq_attr "length" "8")
5653             (const_string "yes")
5654             (const_string "no")))
5655    (set (attr "length") 
5656         (if_then_else
5657             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5658                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5659             (const_int 4)
5660             (if_then_else
5661                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5662                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5663                 (const_int 6)
5664                 (const_int 8))))]
5666 (define_insn "*movsi_cbranchsi4"
5667   [(set (pc)
5668         (if_then_else
5669          (match_operator 3 "arm_comparison_operator"
5670           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5671            (const_int 0)])
5672          (label_ref (match_operand 2 "" ""))
5673          (pc)))
5674    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5675         (match_dup 1))]
5676   "TARGET_THUMB"
5677   "*{
5678   if (which_alternative == 0)
5679     output_asm_insn (\"cmp\t%0, #0\", operands);
5680   else if (which_alternative == 1)
5681     output_asm_insn (\"sub\t%0, %1, #0\", operands);
5682   else
5683     {
5684       output_asm_insn (\"cmp\t%1, #0\", operands);
5685       if (which_alternative == 2)
5686         output_asm_insn (\"mov\t%0, %1\", operands);
5687       else
5688         output_asm_insn (\"str\t%1, %0\", operands);
5689     }
5690   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5691     {
5692     case 4:  return \"b%d3\\t%l2\";
5693     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5694     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5695     }
5696   }"
5697   [(set (attr "far_jump")
5698         (if_then_else
5699             (ior (and (gt (symbol_ref ("which_alternative"))
5700                           (const_int 1))
5701                       (eq_attr "length" "8"))
5702                  (eq_attr "length" "10"))
5703             (const_string "yes")
5704             (const_string "no")))
5705    (set (attr "length")
5706      (if_then_else
5707        (le (symbol_ref ("which_alternative"))
5708                        (const_int 1))
5709        (if_then_else
5710          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5711               (le (minus (match_dup 2) (pc)) (const_int 256)))
5712          (const_int 4)
5713          (if_then_else
5714            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5715                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5716            (const_int 6)
5717            (const_int 8)))
5718        (if_then_else
5719          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5720               (le (minus (match_dup 2) (pc)) (const_int 256)))
5721          (const_int 6)
5722          (if_then_else
5723            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5724                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5725            (const_int 8)
5726            (const_int 10)))))]
5729 (define_insn "*negated_cbranchsi4"
5730   [(set (pc)
5731         (if_then_else
5732          (match_operator 0 "arm_comparison_operator"
5733           [(match_operand:SI 1 "s_register_operand" "l")
5734            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5735          (label_ref (match_operand 3 "" ""))
5736          (pc)))]
5737   "TARGET_THUMB"
5738   "*
5739   output_asm_insn (\"cmn\\t%1, %2\", operands);
5740   switch (get_attr_length (insn))
5741     {
5742     case 4:  return \"b%d0\\t%l3\";
5743     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5744     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5745     }
5746   "
5747   [(set (attr "far_jump")
5748         (if_then_else
5749             (eq_attr "length" "8")
5750             (const_string "yes")
5751             (const_string "no")))
5752    (set (attr "length") 
5753         (if_then_else
5754             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5755                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5756             (const_int 4)
5757             (if_then_else
5758                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5759                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5760                 (const_int 6)
5761                 (const_int 8))))]
5764 (define_insn "*tbit_cbranch"
5765   [(set (pc)
5766         (if_then_else
5767          (match_operator 0 "equality_operator"
5768           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5769                             (const_int 1)
5770                             (match_operand:SI 2 "const_int_operand" "i"))
5771            (const_int 0)])
5772          (label_ref (match_operand 3 "" ""))
5773          (pc)))
5774    (clobber (match_scratch:SI 4 "=l"))]
5775   "TARGET_THUMB"
5776   "*
5777   {
5778   rtx op[3];
5779   op[0] = operands[4];
5780   op[1] = operands[1];
5781   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5783   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5784   switch (get_attr_length (insn))
5785     {
5786     case 4:  return \"b%d0\\t%l3\";
5787     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5788     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5789     }
5790   }"
5791   [(set (attr "far_jump")
5792         (if_then_else
5793             (eq_attr "length" "8")
5794             (const_string "yes")
5795             (const_string "no")))
5796    (set (attr "length") 
5797         (if_then_else
5798             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5799                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5800             (const_int 4)
5801             (if_then_else
5802                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5803                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5804                 (const_int 6)
5805                 (const_int 8))))]
5807   
5808 (define_insn "*tstsi3_cbranch"
5809   [(set (pc)
5810         (if_then_else
5811          (match_operator 3 "equality_operator"
5812           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5813                    (match_operand:SI 1 "s_register_operand" "l"))
5814            (const_int 0)])
5815          (label_ref (match_operand 2 "" ""))
5816          (pc)))]
5817   "TARGET_THUMB"
5818   "*
5819   {
5820   output_asm_insn (\"tst\\t%0, %1\", operands);
5821   switch (get_attr_length (insn))
5822     {
5823     case 4:  return \"b%d3\\t%l2\";
5824     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5825     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5826     }
5827   }"
5828   [(set (attr "far_jump")
5829         (if_then_else
5830             (eq_attr "length" "8")
5831             (const_string "yes")
5832             (const_string "no")))
5833    (set (attr "length") 
5834         (if_then_else
5835             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5836                  (le (minus (match_dup 2) (pc)) (const_int 256)))
5837             (const_int 4)
5838             (if_then_else
5839                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5840                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
5841                 (const_int 6)
5842                 (const_int 8))))]
5844   
5845 (define_insn "*andsi3_cbranch"
5846   [(set (pc)
5847         (if_then_else
5848          (match_operator 5 "equality_operator"
5849           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5850                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5851            (const_int 0)])
5852          (label_ref (match_operand 4 "" ""))
5853          (pc)))
5854    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5855         (and:SI (match_dup 2) (match_dup 3)))
5856    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5857   "TARGET_THUMB"
5858   "*
5859   {
5860   if (which_alternative == 0)
5861     output_asm_insn (\"and\\t%0, %3\", operands);
5862   else if (which_alternative == 1)
5863     {
5864       output_asm_insn (\"and\\t%1, %3\", operands);
5865       output_asm_insn (\"mov\\t%0, %1\", operands);
5866     }
5867   else
5868     {
5869       output_asm_insn (\"and\\t%1, %3\", operands);
5870       output_asm_insn (\"str\\t%1, %0\", operands);
5871     }
5873   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5874     {
5875     case 4:  return \"b%d5\\t%l4\";
5876     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5877     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5878     }
5879   }"
5880   [(set (attr "far_jump")
5881         (if_then_else
5882             (ior (and (eq (symbol_ref ("which_alternative"))
5883                           (const_int 0))
5884                       (eq_attr "length" "8"))
5885                  (eq_attr "length" "10"))
5886             (const_string "yes")
5887             (const_string "no")))
5888    (set (attr "length")
5889      (if_then_else
5890        (eq (symbol_ref ("which_alternative"))
5891                        (const_int 0))
5892        (if_then_else
5893          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5894               (le (minus (match_dup 4) (pc)) (const_int 256)))
5895          (const_int 4)
5896          (if_then_else
5897            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5898                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5899            (const_int 6)
5900            (const_int 8)))
5901        (if_then_else
5902          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5903               (le (minus (match_dup 4) (pc)) (const_int 256)))
5904          (const_int 6)
5905          (if_then_else
5906            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5907                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5908            (const_int 8)
5909            (const_int 10)))))]
5912 (define_insn "*orrsi3_cbranch_scratch"
5913   [(set (pc)
5914         (if_then_else
5915          (match_operator 4 "equality_operator"
5916           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
5917                    (match_operand:SI 2 "s_register_operand" "l"))
5918            (const_int 0)])
5919          (label_ref (match_operand 3 "" ""))
5920          (pc)))
5921    (clobber (match_scratch:SI 0 "=l"))]
5922   "TARGET_THUMB"
5923   "*
5924   {
5925   output_asm_insn (\"orr\\t%0, %2\", operands);
5926   switch (get_attr_length (insn))
5927     {
5928     case 4:  return \"b%d4\\t%l3\";
5929     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5930     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5931     }
5932   }"
5933   [(set (attr "far_jump")
5934         (if_then_else
5935             (eq_attr "length" "8")
5936             (const_string "yes")
5937             (const_string "no")))
5938    (set (attr "length") 
5939         (if_then_else
5940             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5941                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5942             (const_int 4)
5943             (if_then_else
5944                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5945                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5946                 (const_int 6)
5947                 (const_int 8))))]
5949   
5950 (define_insn "*orrsi3_cbranch"
5951   [(set (pc)
5952         (if_then_else
5953          (match_operator 5 "equality_operator"
5954           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5955                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5956            (const_int 0)])
5957          (label_ref (match_operand 4 "" ""))
5958          (pc)))
5959    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5960         (ior:SI (match_dup 2) (match_dup 3)))
5961    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5962   "TARGET_THUMB"
5963   "*
5964   {
5965   if (which_alternative == 0)
5966     output_asm_insn (\"orr\\t%0, %3\", operands);
5967   else if (which_alternative == 1)
5968     {
5969       output_asm_insn (\"orr\\t%1, %3\", operands);
5970       output_asm_insn (\"mov\\t%0, %1\", operands);
5971     }
5972   else
5973     {
5974       output_asm_insn (\"orr\\t%1, %3\", operands);
5975       output_asm_insn (\"str\\t%1, %0\", operands);
5976     }
5978   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5979     {
5980     case 4:  return \"b%d5\\t%l4\";
5981     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5982     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5983     }
5984   }"
5985   [(set (attr "far_jump")
5986         (if_then_else
5987             (ior (and (eq (symbol_ref ("which_alternative"))
5988                           (const_int 0))
5989                       (eq_attr "length" "8"))
5990                  (eq_attr "length" "10"))
5991             (const_string "yes")
5992             (const_string "no")))
5993    (set (attr "length")
5994      (if_then_else
5995        (eq (symbol_ref ("which_alternative"))
5996                        (const_int 0))
5997        (if_then_else
5998          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5999               (le (minus (match_dup 4) (pc)) (const_int 256)))
6000          (const_int 4)
6001          (if_then_else
6002            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6003                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6004            (const_int 6)
6005            (const_int 8)))
6006        (if_then_else
6007          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6008               (le (minus (match_dup 4) (pc)) (const_int 256)))
6009          (const_int 6)
6010          (if_then_else
6011            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6012                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6013            (const_int 8)
6014            (const_int 10)))))]
6017 (define_insn "*xorsi3_cbranch_scratch"
6018   [(set (pc)
6019         (if_then_else
6020          (match_operator 4 "equality_operator"
6021           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6022                    (match_operand:SI 2 "s_register_operand" "l"))
6023            (const_int 0)])
6024          (label_ref (match_operand 3 "" ""))
6025          (pc)))
6026    (clobber (match_scratch:SI 0 "=l"))]
6027   "TARGET_THUMB"
6028   "*
6029   {
6030   output_asm_insn (\"eor\\t%0, %2\", operands);
6031   switch (get_attr_length (insn))
6032     {
6033     case 4:  return \"b%d4\\t%l3\";
6034     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6035     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6036     }
6037   }"
6038   [(set (attr "far_jump")
6039         (if_then_else
6040             (eq_attr "length" "8")
6041             (const_string "yes")
6042             (const_string "no")))
6043    (set (attr "length") 
6044         (if_then_else
6045             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6046                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6047             (const_int 4)
6048             (if_then_else
6049                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6050                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6051                 (const_int 6)
6052                 (const_int 8))))]
6054   
6055 (define_insn "*xorsi3_cbranch"
6056   [(set (pc)
6057         (if_then_else
6058          (match_operator 5 "equality_operator"
6059           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6060                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6061            (const_int 0)])
6062          (label_ref (match_operand 4 "" ""))
6063          (pc)))
6064    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6065         (xor:SI (match_dup 2) (match_dup 3)))
6066    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6067   "TARGET_THUMB"
6068   "*
6069   {
6070   if (which_alternative == 0)
6071     output_asm_insn (\"eor\\t%0, %3\", operands);
6072   else if (which_alternative == 1)
6073     {
6074       output_asm_insn (\"eor\\t%1, %3\", operands);
6075       output_asm_insn (\"mov\\t%0, %1\", operands);
6076     }
6077   else
6078     {
6079       output_asm_insn (\"eor\\t%1, %3\", operands);
6080       output_asm_insn (\"str\\t%1, %0\", operands);
6081     }
6083   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6084     {
6085     case 4:  return \"b%d5\\t%l4\";
6086     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6087     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6088     }
6089   }"
6090   [(set (attr "far_jump")
6091         (if_then_else
6092             (ior (and (eq (symbol_ref ("which_alternative"))
6093                           (const_int 0))
6094                       (eq_attr "length" "8"))
6095                  (eq_attr "length" "10"))
6096             (const_string "yes")
6097             (const_string "no")))
6098    (set (attr "length")
6099      (if_then_else
6100        (eq (symbol_ref ("which_alternative"))
6101                        (const_int 0))
6102        (if_then_else
6103          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6104               (le (minus (match_dup 4) (pc)) (const_int 256)))
6105          (const_int 4)
6106          (if_then_else
6107            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6108                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6109            (const_int 6)
6110            (const_int 8)))
6111        (if_then_else
6112          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6113               (le (minus (match_dup 4) (pc)) (const_int 256)))
6114          (const_int 6)
6115          (if_then_else
6116            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6117                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6118            (const_int 8)
6119            (const_int 10)))))]
6122 (define_insn "*bicsi3_cbranch_scratch"
6123   [(set (pc)
6124         (if_then_else
6125          (match_operator 4 "equality_operator"
6126           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6127                    (match_operand:SI 1 "s_register_operand" "0"))
6128            (const_int 0)])
6129          (label_ref (match_operand 3 "" ""))
6130          (pc)))
6131    (clobber (match_scratch:SI 0 "=l"))]
6132   "TARGET_THUMB"
6133   "*
6134   {
6135   output_asm_insn (\"bic\\t%0, %2\", operands);
6136   switch (get_attr_length (insn))
6137     {
6138     case 4:  return \"b%d4\\t%l3\";
6139     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6140     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6141     }
6142   }"
6143   [(set (attr "far_jump")
6144         (if_then_else
6145             (eq_attr "length" "8")
6146             (const_string "yes")
6147             (const_string "no")))
6148    (set (attr "length") 
6149         (if_then_else
6150             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6151                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6152             (const_int 4)
6153             (if_then_else
6154                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6155                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6156                 (const_int 6)
6157                 (const_int 8))))]
6159   
6160 (define_insn "*bicsi3_cbranch"
6161   [(set (pc)
6162         (if_then_else
6163          (match_operator 5 "equality_operator"
6164           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6165                    (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6166            (const_int 0)])
6167          (label_ref (match_operand 4 "" ""))
6168          (pc)))
6169    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6170         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6171    (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6172   "TARGET_THUMB"
6173   "*
6174   {
6175   if (which_alternative == 0)
6176     output_asm_insn (\"bic\\t%0, %3\", operands);
6177   else if (which_alternative <= 2)
6178     {
6179       output_asm_insn (\"bic\\t%1, %3\", operands);
6180       /* It's ok if OP0 is a lo-reg, even though the mov will set the
6181          conditions again, since we're only testing for equality.  */
6182       output_asm_insn (\"mov\\t%0, %1\", operands);
6183     }
6184   else
6185     {
6186       output_asm_insn (\"bic\\t%1, %3\", operands);
6187       output_asm_insn (\"str\\t%1, %0\", operands);
6188     }
6190   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6191     {
6192     case 4:  return \"b%d5\\t%l4\";
6193     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6194     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6195     }
6196   }"
6197   [(set (attr "far_jump")
6198         (if_then_else
6199             (ior (and (eq (symbol_ref ("which_alternative"))
6200                           (const_int 0))
6201                       (eq_attr "length" "8"))
6202                  (eq_attr "length" "10"))
6203             (const_string "yes")
6204             (const_string "no")))
6205    (set (attr "length")
6206      (if_then_else
6207        (eq (symbol_ref ("which_alternative"))
6208                        (const_int 0))
6209        (if_then_else
6210          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6211               (le (minus (match_dup 4) (pc)) (const_int 256)))
6212          (const_int 4)
6213          (if_then_else
6214            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6215                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6216            (const_int 6)
6217            (const_int 8)))
6218        (if_then_else
6219          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6220               (le (minus (match_dup 4) (pc)) (const_int 256)))
6221          (const_int 6)
6222          (if_then_else
6223            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6224                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6225            (const_int 8)
6226            (const_int 10)))))]
6229 (define_insn "*cbranchne_decr1"
6230   [(set (pc)
6231         (if_then_else (match_operator 3 "equality_operator"
6232                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6233                         (const_int 0)])
6234                       (label_ref (match_operand 4 "" ""))
6235                       (pc)))
6236    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6237         (plus:SI (match_dup 2) (const_int -1)))
6238    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6239   "TARGET_THUMB"
6240   "*
6241    {
6242      rtx cond[2];
6243      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6244                                 ? GEU : LTU),
6245                                VOIDmode, operands[2], const1_rtx);
6246      cond[1] = operands[4];
6248      if (which_alternative == 0)
6249        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6250      else if (which_alternative == 1)
6251        {
6252          /* We must provide an alternative for a hi reg because reload 
6253             cannot handle output reloads on a jump instruction, but we
6254             can't subtract into that.  Fortunately a mov from lo to hi
6255             does not clobber the condition codes.  */
6256          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6257          output_asm_insn (\"mov\\t%0, %1\", operands);
6258        }
6259      else
6260        {
6261          /* Similarly, but the target is memory.  */
6262          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6263          output_asm_insn (\"str\\t%1, %0\", operands);
6264        }
6266      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6267        {
6268          case 4:
6269            output_asm_insn (\"b%d0\\t%l1\", cond);
6270            return \"\";
6271          case 6:
6272            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6273            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6274          default:
6275            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6276            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6277        }
6278    }
6279   "
6280   [(set (attr "far_jump")
6281         (if_then_else
6282             (ior (and (eq (symbol_ref ("which_alternative"))
6283                           (const_int 0))
6284                       (eq_attr "length" "8"))
6285                  (eq_attr "length" "10"))
6286             (const_string "yes")
6287             (const_string "no")))
6288    (set_attr_alternative "length"
6289       [
6290        ;; Alternative 0
6291        (if_then_else
6292          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6293               (le (minus (match_dup 4) (pc)) (const_int 256)))
6294          (const_int 4)
6295          (if_then_else
6296            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6297                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6298            (const_int 6)
6299            (const_int 8)))
6300        ;; Alternative 1
6301        (if_then_else
6302          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6303               (le (minus (match_dup 4) (pc)) (const_int 256)))
6304          (const_int 6)
6305          (if_then_else
6306            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6307                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6308            (const_int 8)
6309            (const_int 10)))
6310        ;; Alternative 2
6311        (if_then_else
6312          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6313               (le (minus (match_dup 4) (pc)) (const_int 256)))
6314          (const_int 6)
6315          (if_then_else
6316            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6317                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6318            (const_int 8)
6319            (const_int 10)))
6320        ;; Alternative 3
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)))])]
6332 (define_insn "*addsi3_cbranch"
6333   [(set (pc)
6334         (if_then_else
6335          (match_operator 4 "comparison_operator"
6336           [(plus:SI
6337             (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6338             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6339            (const_int 0)])
6340          (label_ref (match_operand 5 "" ""))
6341          (pc)))
6342    (set
6343     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6344     (plus:SI (match_dup 2) (match_dup 3)))
6345    (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6346   "TARGET_THUMB
6347    && (GET_CODE (operands[4]) == EQ
6348        || GET_CODE (operands[4]) == NE
6349        || GET_CODE (operands[4]) == GE
6350        || GET_CODE (operands[4]) == LT)"
6351   "*
6352    {
6353      rtx cond[3];
6355      
6356      cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6357      cond[1] = operands[2];
6358      cond[2] = operands[3];
6360      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6361        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6362      else
6363        output_asm_insn (\"add\\t%0, %1, %2\", cond);
6365      if (which_alternative >= 3
6366          && which_alternative < 4)
6367        output_asm_insn (\"mov\\t%0, %1\", operands);
6368      else if (which_alternative >= 4)
6369        output_asm_insn (\"str\\t%1, %0\", operands);
6371      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6372        {
6373          case 4:
6374            return \"b%d4\\t%l5\";
6375          case 6:
6376            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6377          default:
6378            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6379        }
6380    }
6381   "
6382   [(set (attr "far_jump")
6383         (if_then_else
6384             (ior (and (lt (symbol_ref ("which_alternative"))
6385                           (const_int 3))
6386                       (eq_attr "length" "8"))
6387                  (eq_attr "length" "10"))
6388             (const_string "yes")
6389             (const_string "no")))
6390    (set (attr "length")
6391      (if_then_else
6392        (lt (symbol_ref ("which_alternative"))
6393                        (const_int 3))
6394        (if_then_else
6395          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6396               (le (minus (match_dup 5) (pc)) (const_int 256)))
6397          (const_int 4)
6398          (if_then_else
6399            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6400                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6401            (const_int 6)
6402            (const_int 8)))
6403        (if_then_else
6404          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6405               (le (minus (match_dup 5) (pc)) (const_int 256)))
6406          (const_int 6)
6407          (if_then_else
6408            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6409                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6410            (const_int 8)
6411            (const_int 10)))))]
6414 (define_insn "*addsi3_cbranch_scratch"
6415   [(set (pc)
6416         (if_then_else
6417          (match_operator 3 "comparison_operator"
6418           [(plus:SI
6419             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6420             (match_operand:SI 2 "reg_or_int_operand" "J,l,I,L"))
6421            (const_int 0)])
6422          (label_ref (match_operand 4 "" ""))
6423          (pc)))
6424    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6425   "TARGET_THUMB
6426    && (GET_CODE (operands[3]) == EQ
6427        || GET_CODE (operands[3]) == NE
6428        || GET_CODE (operands[3]) == GE
6429        || GET_CODE (operands[3]) == LT)"
6430   "*
6431    {
6432      switch (which_alternative)
6433        {
6434        case 0:
6435          output_asm_insn (\"cmp\t%1, #%n2\", operands);
6436          break;
6437        case 1:
6438          output_asm_insn (\"cmn\t%1, %2\", operands);
6439          break;
6440        case 2:
6441          output_asm_insn (\"add\t%0, %1, %2\", operands);
6442          break;
6443        case 3:
6444          output_asm_insn (\"add\t%0, %0, %2\", operands);
6445          break;
6446        }
6448      switch (get_attr_length (insn))
6449        {
6450          case 4:
6451            return \"b%d3\\t%l4\";
6452          case 6:
6453            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6454          default:
6455            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6456        }
6457    }
6458   "
6459   [(set (attr "far_jump")
6460         (if_then_else
6461             (eq_attr "length" "8")
6462             (const_string "yes")
6463             (const_string "no")))
6464    (set (attr "length")
6465        (if_then_else
6466          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6467               (le (minus (match_dup 4) (pc)) (const_int 256)))
6468          (const_int 4)
6469          (if_then_else
6470            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6471                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6472            (const_int 6)
6473            (const_int 8))))]
6476 (define_insn "*subsi3_cbranch"
6477   [(set (pc)
6478         (if_then_else
6479          (match_operator 4 "comparison_operator"
6480           [(minus:SI
6481             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6482             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6483            (const_int 0)])
6484          (label_ref (match_operand 5 "" ""))
6485          (pc)))
6486    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6487         (minus:SI (match_dup 2) (match_dup 3)))
6488    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6489   "TARGET_THUMB
6490    && (GET_CODE (operands[4]) == EQ
6491        || GET_CODE (operands[4]) == NE
6492        || GET_CODE (operands[4]) == GE
6493        || GET_CODE (operands[4]) == LT)"
6494   "*
6495    {
6496      if (which_alternative == 0)
6497        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6498      else if (which_alternative == 1)
6499        {
6500          /* We must provide an alternative for a hi reg because reload 
6501             cannot handle output reloads on a jump instruction, but we
6502             can't subtract into that.  Fortunately a mov from lo to hi
6503             does not clobber the condition codes.  */
6504          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6505          output_asm_insn (\"mov\\t%0, %1\", operands);
6506        }
6507      else
6508        {
6509          /* Similarly, but the target is memory.  */
6510          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6511          output_asm_insn (\"str\\t%1, %0\", operands);
6512        }
6514      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6515        {
6516          case 4:
6517            return \"b%d4\\t%l5\";
6518          case 6:
6519            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6520          default:
6521            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6522        }
6523    }
6524   "
6525   [(set (attr "far_jump")
6526         (if_then_else
6527             (ior (and (eq (symbol_ref ("which_alternative"))
6528                           (const_int 0))
6529                       (eq_attr "length" "8"))
6530                  (eq_attr "length" "10"))
6531             (const_string "yes")
6532             (const_string "no")))
6533    (set (attr "length")
6534      (if_then_else
6535        (eq (symbol_ref ("which_alternative"))
6536                        (const_int 0))
6537        (if_then_else
6538          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6539               (le (minus (match_dup 5) (pc)) (const_int 256)))
6540          (const_int 4)
6541          (if_then_else
6542            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6543                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6544            (const_int 6)
6545            (const_int 8)))
6546        (if_then_else
6547          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6548               (le (minus (match_dup 5) (pc)) (const_int 256)))
6549          (const_int 6)
6550          (if_then_else
6551            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6552                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6553            (const_int 8)
6554            (const_int 10)))))]
6557 (define_insn "*subsi3_cbranch_scratch"
6558   [(set (pc)
6559         (if_then_else
6560          (match_operator 0 "arm_comparison_operator"
6561           [(minus:SI (match_operand:SI 1 "register_operand" "l")
6562                      (match_operand:SI 2 "nonmemory_operand" "l"))
6563            (const_int 0)])
6564          (label_ref (match_operand 3 "" ""))
6565          (pc)))]
6566   "TARGET_THUMB
6567    && (GET_CODE (operands[0]) == EQ
6568        || GET_CODE (operands[0]) == NE
6569        || GET_CODE (operands[0]) == GE
6570        || GET_CODE (operands[0]) == LT)"
6571   "*
6572   output_asm_insn (\"cmp\\t%1, %2\", operands);
6573   switch (get_attr_length (insn))
6574     {
6575     case 4:  return \"b%d0\\t%l3\";
6576     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6577     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6578     }
6579   "
6580   [(set (attr "far_jump")
6581         (if_then_else
6582             (eq_attr "length" "8")
6583             (const_string "yes")
6584             (const_string "no")))
6585    (set (attr "length") 
6586         (if_then_else
6587             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6588                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6589             (const_int 4)
6590             (if_then_else
6591                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6592                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6593                 (const_int 6)
6594                 (const_int 8))))]
6597 ;; Comparison and test insns
6599 (define_expand "cmpsi"
6600   [(match_operand:SI 0 "s_register_operand" "")
6601    (match_operand:SI 1 "arm_add_operand" "")]
6602   "TARGET_ARM"
6603   "{
6604     arm_compare_op0 = operands[0];
6605     arm_compare_op1 = operands[1];
6606     DONE;
6607   }"
6610 (define_expand "cmpsf"
6611   [(match_operand:SF 0 "s_register_operand" "")
6612    (match_operand:SF 1 "arm_float_compare_operand" "")]
6613   "TARGET_ARM && TARGET_HARD_FLOAT"
6614   "
6615   arm_compare_op0 = operands[0];
6616   arm_compare_op1 = operands[1];
6617   DONE;
6618   "
6621 (define_expand "cmpdf"
6622   [(match_operand:DF 0 "s_register_operand" "")
6623    (match_operand:DF 1 "arm_float_compare_operand" "")]
6624   "TARGET_ARM && TARGET_HARD_FLOAT"
6625   "
6626   arm_compare_op0 = operands[0];
6627   arm_compare_op1 = operands[1];
6628   DONE;
6629   "
6632 (define_insn "*arm_cmpsi_insn"
6633   [(set (reg:CC CC_REGNUM)
6634         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6635                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
6636   "TARGET_ARM"
6637   "@
6638    cmp%?\\t%0, %1
6639    cmn%?\\t%0, #%n1"
6640   [(set_attr "conds" "set")]
6643 (define_insn "*cmpsi_shiftsi"
6644   [(set (reg:CC CC_REGNUM)
6645         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
6646                     (match_operator:SI  3 "shift_operator"
6647                      [(match_operand:SI 1 "s_register_operand" "r")
6648                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
6649   "TARGET_ARM"
6650   "cmp%?\\t%0, %1%S3"
6651   [(set_attr "conds" "set")
6652    (set_attr "shift" "1")
6653    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6654                       (const_string "alu_shift")
6655                       (const_string "alu_shift_reg")))]
6658 (define_insn "*cmpsi_shiftsi_swp"
6659   [(set (reg:CC_SWP CC_REGNUM)
6660         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6661                          [(match_operand:SI 1 "s_register_operand" "r")
6662                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
6663                         (match_operand:SI 0 "s_register_operand" "r")))]
6664   "TARGET_ARM"
6665   "cmp%?\\t%0, %1%S3"
6666   [(set_attr "conds" "set")
6667    (set_attr "shift" "1")
6668    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6669                       (const_string "alu_shift")
6670                       (const_string "alu_shift_reg")))]
6673 (define_insn "*cmpsi_neg_shiftsi"
6674   [(set (reg:CC CC_REGNUM)
6675         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6676                     (neg:SI (match_operator:SI 3 "shift_operator"
6677                              [(match_operand:SI 1 "s_register_operand" "r")
6678                               (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
6679   "TARGET_ARM"
6680   "cmn%?\\t%0, %1%S3"
6681   [(set_attr "conds" "set")
6682    (set_attr "shift" "1")
6683    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6684                       (const_string "alu_shift")
6685                       (const_string "alu_shift_reg")))]
6688 ;; Cirrus SF compare instruction
6689 (define_insn "*cirrus_cmpsf"
6690   [(set (reg:CCFP CC_REGNUM)
6691         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6692                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
6693   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6694   "cfcmps%?\\tr15, %V0, %V1"
6695   [(set_attr "type"   "mav_farith")
6696    (set_attr "cirrus" "compare")]
6699 ;; Cirrus DF compare instruction
6700 (define_insn "*cirrus_cmpdf"
6701   [(set (reg:CCFP CC_REGNUM)
6702         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6703                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
6704   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6705   "cfcmpd%?\\tr15, %V0, %V1"
6706   [(set_attr "type"   "mav_farith")
6707    (set_attr "cirrus" "compare")]
6710 ;; Cirrus DI compare instruction
6711 (define_expand "cmpdi"
6712   [(match_operand:DI 0 "cirrus_fp_register" "")
6713    (match_operand:DI 1 "cirrus_fp_register" "")]
6714   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6715   "{
6716      arm_compare_op0 = operands[0];
6717      arm_compare_op1 = operands[1];
6718      DONE;
6719    }")
6721 (define_insn "*cirrus_cmpdi"
6722   [(set (reg:CC CC_REGNUM)
6723         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6724                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
6725   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6726   "cfcmp64%?\\tr15, %V0, %V1"
6727   [(set_attr "type"   "mav_farith")
6728    (set_attr "cirrus" "compare")]
6731 ; This insn allows redundant compares to be removed by cse, nothing should
6732 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6733 ; is deleted later on. The match_dup will match the mode here, so that
6734 ; mode changes of the condition codes aren't lost by this even though we don't
6735 ; specify what they are.
6737 (define_insn "*deleted_compare"
6738   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6739   "TARGET_ARM"
6740   "\\t%@ deleted compare"
6741   [(set_attr "conds" "set")
6742    (set_attr "length" "0")]
6746 ;; Conditional branch insns
6748 (define_expand "beq"
6749   [(set (pc)
6750         (if_then_else (eq (match_dup 1) (const_int 0))
6751                       (label_ref (match_operand 0 "" ""))
6752                       (pc)))]
6753   "TARGET_ARM"
6754   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6757 (define_expand "bne"
6758   [(set (pc)
6759         (if_then_else (ne (match_dup 1) (const_int 0))
6760                       (label_ref (match_operand 0 "" ""))
6761                       (pc)))]
6762   "TARGET_ARM"
6763   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6766 (define_expand "bgt"
6767   [(set (pc)
6768         (if_then_else (gt (match_dup 1) (const_int 0))
6769                       (label_ref (match_operand 0 "" ""))
6770                       (pc)))]
6771   "TARGET_ARM"
6772   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6775 (define_expand "ble"
6776   [(set (pc)
6777         (if_then_else (le (match_dup 1) (const_int 0))
6778                       (label_ref (match_operand 0 "" ""))
6779                       (pc)))]
6780   "TARGET_ARM"
6781   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6784 (define_expand "bge"
6785   [(set (pc)
6786         (if_then_else (ge (match_dup 1) (const_int 0))
6787                       (label_ref (match_operand 0 "" ""))
6788                       (pc)))]
6789   "TARGET_ARM"
6790   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6793 (define_expand "blt"
6794   [(set (pc)
6795         (if_then_else (lt (match_dup 1) (const_int 0))
6796                       (label_ref (match_operand 0 "" ""))
6797                       (pc)))]
6798   "TARGET_ARM"
6799   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6802 (define_expand "bgtu"
6803   [(set (pc)
6804         (if_then_else (gtu (match_dup 1) (const_int 0))
6805                       (label_ref (match_operand 0 "" ""))
6806                       (pc)))]
6807   "TARGET_ARM"
6808   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6811 (define_expand "bleu"
6812   [(set (pc)
6813         (if_then_else (leu (match_dup 1) (const_int 0))
6814                       (label_ref (match_operand 0 "" ""))
6815                       (pc)))]
6816   "TARGET_ARM"
6817   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6820 (define_expand "bgeu"
6821   [(set (pc)
6822         (if_then_else (geu (match_dup 1) (const_int 0))
6823                       (label_ref (match_operand 0 "" ""))
6824                       (pc)))]
6825   "TARGET_ARM"
6826   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6829 (define_expand "bltu"
6830   [(set (pc)
6831         (if_then_else (ltu (match_dup 1) (const_int 0))
6832                       (label_ref (match_operand 0 "" ""))
6833                       (pc)))]
6834   "TARGET_ARM"
6835   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6838 (define_expand "bunordered"
6839   [(set (pc)
6840         (if_then_else (unordered (match_dup 1) (const_int 0))
6841                       (label_ref (match_operand 0 "" ""))
6842                       (pc)))]
6843   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6844   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6845                                       arm_compare_op1);"
6848 (define_expand "bordered"
6849   [(set (pc)
6850         (if_then_else (ordered (match_dup 1) (const_int 0))
6851                       (label_ref (match_operand 0 "" ""))
6852                       (pc)))]
6853   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6854   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6855                                       arm_compare_op1);"
6858 (define_expand "bungt"
6859   [(set (pc)
6860         (if_then_else (ungt (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 (UNGT, arm_compare_op0, arm_compare_op1);"
6867 (define_expand "bunlt"
6868   [(set (pc)
6869         (if_then_else (unlt (match_dup 1) (const_int 0))
6870                       (label_ref (match_operand 0 "" ""))
6871                       (pc)))]
6872   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6873   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
6876 (define_expand "bunge"
6877   [(set (pc)
6878         (if_then_else (unge (match_dup 1) (const_int 0))
6879                       (label_ref (match_operand 0 "" ""))
6880                       (pc)))]
6881   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6882   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
6885 (define_expand "bunle"
6886   [(set (pc)
6887         (if_then_else (unle (match_dup 1) (const_int 0))
6888                       (label_ref (match_operand 0 "" ""))
6889                       (pc)))]
6890   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6891   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
6894 ;; The following two patterns need two branch instructions, since there is
6895 ;; no single instruction that will handle all cases.
6896 (define_expand "buneq"
6897   [(set (pc)
6898         (if_then_else (uneq (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 (UNEQ, arm_compare_op0, arm_compare_op1);"
6905 (define_expand "bltgt"
6906   [(set (pc)
6907         (if_then_else (ltgt (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 (LTGT, arm_compare_op0, arm_compare_op1);"
6915 ;; Patterns to match conditional branch insns.
6918 ; Special pattern to match UNEQ.
6919 (define_insn "*arm_buneq"
6920   [(set (pc)
6921         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6922                       (label_ref (match_operand 0 "" ""))
6923                       (pc)))]
6924   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6925   "*
6926   if (arm_ccfsm_state != 0)
6927     abort ();
6929   return \"bvs\\t%l0\;beq\\t%l0\";
6930   "
6931   [(set_attr "conds" "jump_clob")
6932    (set_attr "length" "8")]
6935 ; Special pattern to match LTGT.
6936 (define_insn "*arm_bltgt"
6937   [(set (pc)
6938         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6939                       (label_ref (match_operand 0 "" ""))
6940                       (pc)))]
6941   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6942   "*
6943   if (arm_ccfsm_state != 0)
6944     abort ();
6946   return \"bmi\\t%l0\;bgt\\t%l0\";
6947   "
6948   [(set_attr "conds" "jump_clob")
6949    (set_attr "length" "8")]
6952 (define_insn "*arm_cond_branch"
6953   [(set (pc)
6954         (if_then_else (match_operator 1 "arm_comparison_operator"
6955                        [(match_operand 2 "cc_register" "") (const_int 0)])
6956                       (label_ref (match_operand 0 "" ""))
6957                       (pc)))]
6958   "TARGET_ARM"
6959   "*
6960   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6961     {
6962       arm_ccfsm_state += 2;
6963       return \"\";
6964     }
6965   return \"b%d1\\t%l0\";
6966   "
6967   [(set_attr "conds" "use")
6968    (set_attr "type" "branch")]
6971 ; Special pattern to match reversed UNEQ.
6972 (define_insn "*arm_buneq_reversed"
6973   [(set (pc)
6974         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6975                       (pc)
6976                       (label_ref (match_operand 0 "" ""))))]
6977   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6978   "*
6979   if (arm_ccfsm_state != 0)
6980     abort ();
6982   return \"bmi\\t%l0\;bgt\\t%l0\";
6983   "
6984   [(set_attr "conds" "jump_clob")
6985    (set_attr "length" "8")]
6988 ; Special pattern to match reversed LTGT.
6989 (define_insn "*arm_bltgt_reversed"
6990   [(set (pc)
6991         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6992                       (pc)
6993                       (label_ref (match_operand 0 "" ""))))]
6994   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6995   "*
6996   if (arm_ccfsm_state != 0)
6997     abort ();
6999   return \"bvs\\t%l0\;beq\\t%l0\";
7000   "
7001   [(set_attr "conds" "jump_clob")
7002    (set_attr "length" "8")]
7005 (define_insn "*arm_cond_branch_reversed"
7006   [(set (pc)
7007         (if_then_else (match_operator 1 "arm_comparison_operator"
7008                        [(match_operand 2 "cc_register" "") (const_int 0)])
7009                       (pc)
7010                       (label_ref (match_operand 0 "" ""))))]
7011   "TARGET_ARM"
7012   "*
7013   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7014     {
7015       arm_ccfsm_state += 2;
7016       return \"\";
7017     }
7018   return \"b%D1\\t%l0\";
7019   "
7020   [(set_attr "conds" "use")
7021    (set_attr "type" "branch")]
7026 ; scc insns
7028 (define_expand "seq"
7029   [(set (match_operand:SI 0 "s_register_operand" "")
7030         (eq:SI (match_dup 1) (const_int 0)))]
7031   "TARGET_ARM"
7032   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7035 (define_expand "sne"
7036   [(set (match_operand:SI 0 "s_register_operand" "")
7037         (ne:SI (match_dup 1) (const_int 0)))]
7038   "TARGET_ARM"
7039   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7042 (define_expand "sgt"
7043   [(set (match_operand:SI 0 "s_register_operand" "")
7044         (gt:SI (match_dup 1) (const_int 0)))]
7045   "TARGET_ARM"
7046   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7049 (define_expand "sle"
7050   [(set (match_operand:SI 0 "s_register_operand" "")
7051         (le:SI (match_dup 1) (const_int 0)))]
7052   "TARGET_ARM"
7053   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7056 (define_expand "sge"
7057   [(set (match_operand:SI 0 "s_register_operand" "")
7058         (ge:SI (match_dup 1) (const_int 0)))]
7059   "TARGET_ARM"
7060   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7063 (define_expand "slt"
7064   [(set (match_operand:SI 0 "s_register_operand" "")
7065         (lt:SI (match_dup 1) (const_int 0)))]
7066   "TARGET_ARM"
7067   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7070 (define_expand "sgtu"
7071   [(set (match_operand:SI 0 "s_register_operand" "")
7072         (gtu:SI (match_dup 1) (const_int 0)))]
7073   "TARGET_ARM"
7074   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7077 (define_expand "sleu"
7078   [(set (match_operand:SI 0 "s_register_operand" "")
7079         (leu:SI (match_dup 1) (const_int 0)))]
7080   "TARGET_ARM"
7081   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7084 (define_expand "sgeu"
7085   [(set (match_operand:SI 0 "s_register_operand" "")
7086         (geu:SI (match_dup 1) (const_int 0)))]
7087   "TARGET_ARM"
7088   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7091 (define_expand "sltu"
7092   [(set (match_operand:SI 0 "s_register_operand" "")
7093         (ltu:SI (match_dup 1) (const_int 0)))]
7094   "TARGET_ARM"
7095   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7098 (define_expand "sunordered"
7099   [(set (match_operand:SI 0 "s_register_operand" "")
7100         (unordered:SI (match_dup 1) (const_int 0)))]
7101   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7102   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7103                                       arm_compare_op1);"
7106 (define_expand "sordered"
7107   [(set (match_operand:SI 0 "s_register_operand" "")
7108         (ordered:SI (match_dup 1) (const_int 0)))]
7109   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7110   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7111                                       arm_compare_op1);"
7114 (define_expand "sungt"
7115   [(set (match_operand:SI 0 "s_register_operand" "")
7116         (ungt:SI (match_dup 1) (const_int 0)))]
7117   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7118   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7119                                       arm_compare_op1);"
7122 (define_expand "sunge"
7123   [(set (match_operand:SI 0 "s_register_operand" "")
7124         (unge:SI (match_dup 1) (const_int 0)))]
7125   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7126   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7127                                       arm_compare_op1);"
7130 (define_expand "sunlt"
7131   [(set (match_operand:SI 0 "s_register_operand" "")
7132         (unlt:SI (match_dup 1) (const_int 0)))]
7133   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7134   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7135                                       arm_compare_op1);"
7138 (define_expand "sunle"
7139   [(set (match_operand:SI 0 "s_register_operand" "")
7140         (unle:SI (match_dup 1) (const_int 0)))]
7141   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7142   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7143                                       arm_compare_op1);"
7146 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7147 ;;; simple ARM instructions. 
7149 ; (define_expand "suneq"
7150 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7151 ;       (uneq:SI (match_dup 1) (const_int 0)))]
7152 ;   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7153 ;   "abort ();"
7154 ; )
7156 ; (define_expand "sltgt"
7157 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7158 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
7159 ;   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7160 ;   "abort ();"
7161 ; )
7163 (define_insn "*mov_scc"
7164   [(set (match_operand:SI 0 "s_register_operand" "=r")
7165         (match_operator:SI 1 "arm_comparison_operator"
7166          [(match_operand 2 "cc_register" "") (const_int 0)]))]
7167   "TARGET_ARM"
7168   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7169   [(set_attr "conds" "use")
7170    (set_attr "length" "8")]
7173 (define_insn "*mov_negscc"
7174   [(set (match_operand:SI 0 "s_register_operand" "=r")
7175         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7176                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7177   "TARGET_ARM"
7178   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7179   [(set_attr "conds" "use")
7180    (set_attr "length" "8")]
7183 (define_insn "*mov_notscc"
7184   [(set (match_operand:SI 0 "s_register_operand" "=r")
7185         (not:SI (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\;mvn%d1\\t%0, #1"
7189   [(set_attr "conds" "use")
7190    (set_attr "length" "8")]
7194 ;; Conditional move insns
7196 (define_expand "movsicc"
7197   [(set (match_operand:SI 0 "s_register_operand" "")
7198         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7199                          (match_operand:SI 2 "arm_not_operand" "")
7200                          (match_operand:SI 3 "arm_not_operand" "")))]
7201   "TARGET_ARM"
7202   "
7203   {
7204     enum rtx_code code = GET_CODE (operands[1]);
7205     rtx ccreg;
7207     if (code == UNEQ || code == LTGT)
7208       FAIL;
7210     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7211     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7212   }"
7215 (define_expand "movsfcc"
7216   [(set (match_operand:SF 0 "s_register_operand" "")
7217         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7218                          (match_operand:SF 2 "s_register_operand" "")
7219                          (match_operand:SF 3 "nonmemory_operand" "")))]
7220   "TARGET_ARM"
7221   "
7222   {
7223     enum rtx_code code = GET_CODE (operands[1]);
7224     rtx ccreg;
7226     if (code == UNEQ || code == LTGT)
7227       FAIL;
7229     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
7230        Otherwise, ensure it is a valid FP add operand */
7231     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7232         || (!arm_float_add_operand (operands[3], SFmode)))
7233       operands[3] = force_reg (SFmode, operands[3]);
7235     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7236     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7237   }"
7240 (define_expand "movdfcc"
7241   [(set (match_operand:DF 0 "s_register_operand" "")
7242         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7243                          (match_operand:DF 2 "s_register_operand" "")
7244                          (match_operand:DF 3 "arm_float_add_operand" "")))]
7245   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7246   "
7247   {
7248     enum rtx_code code = GET_CODE (operands[1]);
7249     rtx ccreg;
7251     if (code == UNEQ || code == LTGT)
7252       FAIL;
7254     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7255     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7256   }"
7259 (define_insn "*movsicc_insn"
7260   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7261         (if_then_else:SI
7262          (match_operator 3 "arm_comparison_operator"
7263           [(match_operand 4 "cc_register" "") (const_int 0)])
7264          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7265          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7266   "TARGET_ARM"
7267   "@
7268    mov%D3\\t%0, %2
7269    mvn%D3\\t%0, #%B2
7270    mov%d3\\t%0, %1
7271    mvn%d3\\t%0, #%B1
7272    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7273    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7274    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7275    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7276   [(set_attr "length" "4,4,4,4,8,8,8,8")
7277    (set_attr "conds" "use")]
7280 (define_insn "*movsfcc_soft_insn"
7281   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7282         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7283                           [(match_operand 4 "cc_register" "") (const_int 0)])
7284                          (match_operand:SF 1 "s_register_operand" "0,r")
7285                          (match_operand:SF 2 "s_register_operand" "r,0")))]
7286   "TARGET_ARM && TARGET_SOFT_FLOAT"
7287   "@
7288    mov%D3\\t%0, %2
7289    mov%d3\\t%0, %1"
7290   [(set_attr "conds" "use")]
7294 ;; Jump and linkage insns
7296 (define_expand "jump"
7297   [(set (pc)
7298         (label_ref (match_operand 0 "" "")))]
7299   "TARGET_EITHER"
7300   ""
7303 (define_insn "*arm_jump"
7304   [(set (pc)
7305         (label_ref (match_operand 0 "" "")))]
7306   "TARGET_ARM"
7307   "*
7308   {
7309     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7310       {
7311         arm_ccfsm_state += 2;
7312         return \"\";
7313       }
7314     return \"b%?\\t%l0\";
7315   }
7316   "
7317   [(set_attr "predicable" "yes")]
7320 (define_insn "*thumb_jump"
7321   [(set (pc)
7322         (label_ref (match_operand 0 "" "")))]
7323   "TARGET_THUMB"
7324   "*
7325   if (get_attr_length (insn) == 2)
7326     return \"b\\t%l0\";
7327   return \"bl\\t%l0\\t%@ far jump\";
7328   "
7329   [(set (attr "far_jump")
7330         (if_then_else
7331             (eq_attr "length" "4")
7332             (const_string "yes")
7333             (const_string "no")))
7334    (set (attr "length") 
7335         (if_then_else
7336             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7337                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
7338             (const_int 2)
7339             (const_int 4)))]
7342 (define_expand "call"
7343   [(parallel [(call (match_operand 0 "memory_operand" "")
7344                     (match_operand 1 "general_operand" ""))
7345               (use (match_operand 2 "" ""))
7346               (clobber (reg:SI LR_REGNUM))])]
7347   "TARGET_EITHER"
7348   "
7349   {
7350     rtx callee;
7351     
7352     /* In an untyped call, we can get NULL for operand 2.  */
7353     if (operands[2] == NULL_RTX)
7354       operands[2] = const0_rtx;
7355       
7356     /* This is to decide if we should generate indirect calls by loading the
7357        32 bit address of the callee into a register before performing the
7358        branch and link.  operand[2] encodes the long_call/short_call
7359        attribute of the function being called.  This attribute is set whenever
7360        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7361        is used, and the short_call attribute can also be set if function is
7362        declared as static or if it has already been defined in the current
7363        compilation unit.  See arm.c and arm.h for info about this.  The third
7364        parameter to arm_is_longcall_p is used to tell it which pattern
7365        invoked it.  */
7366     callee  = XEXP (operands[0], 0);
7367     
7368     if (GET_CODE (callee) != REG
7369        && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7370       XEXP (operands[0], 0) = force_reg (Pmode, callee);
7371   }"
7374 (define_insn "*call_reg_armv5"
7375   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7376          (match_operand 1 "" ""))
7377    (use (match_operand 2 "" ""))
7378    (clobber (reg:SI LR_REGNUM))]
7379   "TARGET_ARM && arm_arch5"
7380   "blx%?\\t%0"
7381   [(set_attr "type" "call")]
7384 (define_insn "*call_reg_arm"
7385   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7386          (match_operand 1 "" ""))
7387    (use (match_operand 2 "" ""))
7388    (clobber (reg:SI LR_REGNUM))]
7389   "TARGET_ARM && !arm_arch5"
7390   "*
7391   return output_call (operands);
7392   "
7393   ;; length is worst case, normally it is only two
7394   [(set_attr "length" "12")
7395    (set_attr "type" "call")]
7398 (define_insn "*call_mem"
7399   [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7400          (match_operand 1 "" ""))
7401    (use (match_operand 2 "" ""))
7402    (clobber (reg:SI LR_REGNUM))]
7403   "TARGET_ARM"
7404   "*
7405   return output_call_mem (operands);
7406   "
7407   [(set_attr "length" "12")
7408    (set_attr "type" "call")]
7411 (define_insn "*call_reg_thumb_v5"
7412   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7413          (match_operand 1 "" ""))
7414    (use (match_operand 2 "" ""))
7415    (clobber (reg:SI LR_REGNUM))]
7416   "TARGET_THUMB && arm_arch5"
7417   "blx\\t%0"
7418   [(set_attr "length" "2")
7419    (set_attr "type" "call")]
7422 (define_insn "*call_reg_thumb"
7423   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7424          (match_operand 1 "" ""))
7425    (use (match_operand 2 "" ""))
7426    (clobber (reg:SI LR_REGNUM))]
7427   "TARGET_THUMB && !arm_arch5"
7428   "*
7429   {
7430     if (TARGET_CALLER_INTERWORKING)
7431       return \"bl\\t%__interwork_call_via_%0\";
7432     else
7433       return \"bl\\t%__call_via_%0\";
7434   }"
7435   [(set_attr "type" "call")]
7438 (define_expand "call_value"
7439   [(parallel [(set (match_operand       0 "" "")
7440                    (call (match_operand 1 "memory_operand" "")
7441                          (match_operand 2 "general_operand" "")))
7442               (use (match_operand 3 "" ""))
7443               (clobber (reg:SI LR_REGNUM))])]
7444   "TARGET_EITHER"
7445   "
7446   {
7447     rtx callee = XEXP (operands[1], 0);
7448     
7449     /* In an untyped call, we can get NULL for operand 2.  */
7450     if (operands[3] == 0)
7451       operands[3] = const0_rtx;
7452       
7453     /* See the comment in define_expand \"call\".  */
7454     if (GET_CODE (callee) != REG
7455         && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7456       XEXP (operands[1], 0) = force_reg (Pmode, callee);
7457   }"
7460 (define_insn "*call_value_reg_armv5"
7461   [(set (match_operand 0 "" "")
7462         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7463               (match_operand 2 "" "")))
7464    (use (match_operand 3 "" ""))
7465    (clobber (reg:SI LR_REGNUM))]
7466   "TARGET_ARM && arm_arch5"
7467   "blx%?\\t%1"
7468   [(set_attr "type" "call")]
7471 (define_insn "*call_value_reg_arm"
7472   [(set (match_operand 0 "" "")
7473         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7474               (match_operand 2 "" "")))
7475    (use (match_operand 3 "" ""))
7476    (clobber (reg:SI LR_REGNUM))]
7477   "TARGET_ARM && !arm_arch5"
7478   "*
7479   return output_call (&operands[1]);
7480   "
7481   [(set_attr "length" "12")
7482    (set_attr "type" "call")]
7485 (define_insn "*call_value_mem"
7486   [(set (match_operand 0 "" "")
7487         (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7488               (match_operand 2 "" "")))
7489    (use (match_operand 3 "" ""))
7490    (clobber (reg:SI LR_REGNUM))]
7491   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7492   "*
7493   return output_call_mem (&operands[1]);
7494   "
7495   [(set_attr "length" "12")
7496    (set_attr "type" "call")]
7499 (define_insn "*call_value_reg_thumb_v5"
7500   [(set (match_operand 0 "" "")
7501         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7502               (match_operand 2 "" "")))
7503    (use (match_operand 3 "" ""))
7504    (clobber (reg:SI LR_REGNUM))]
7505   "TARGET_THUMB && arm_arch5"
7506   "blx\\t%1"
7507   [(set_attr "length" "2")
7508    (set_attr "type" "call")]
7511 (define_insn "*call_value_reg_thumb"
7512   [(set (match_operand 0 "" "")
7513         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7514               (match_operand 2 "" "")))
7515    (use (match_operand 3 "" ""))
7516    (clobber (reg:SI LR_REGNUM))]
7517   "TARGET_THUMB && !arm_arch5"
7518   "*
7519   {
7520     if (TARGET_CALLER_INTERWORKING)
7521       return \"bl\\t%__interwork_call_via_%1\";
7522     else
7523       return \"bl\\t%__call_via_%1\";
7524   }"
7525   [(set_attr "type" "call")]
7528 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7529 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7531 (define_insn "*call_symbol"
7532   [(call (mem:SI (match_operand:SI 0 "" ""))
7533          (match_operand 1 "" ""))
7534    (use (match_operand 2 "" ""))
7535    (clobber (reg:SI LR_REGNUM))]
7536   "TARGET_ARM
7537    && (GET_CODE (operands[0]) == SYMBOL_REF)
7538    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7539   "*
7540   {
7541     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7542   }"
7543   [(set_attr "type" "call")]
7546 (define_insn "*call_value_symbol"
7547   [(set (match_operand 0 "s_register_operand" "")
7548         (call (mem:SI (match_operand:SI 1 "" ""))
7549         (match_operand:SI 2 "" "")))
7550    (use (match_operand 3 "" ""))
7551    (clobber (reg:SI LR_REGNUM))]
7552   "TARGET_ARM
7553    && (GET_CODE (operands[1]) == SYMBOL_REF)
7554    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7555   "*
7556   {
7557     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7558   }"
7559   [(set_attr "type" "call")]
7562 (define_insn "*call_insn"
7563   [(call (mem:SI (match_operand:SI 0 "" ""))
7564          (match_operand:SI 1 "" ""))
7565    (use (match_operand 2 "" ""))
7566    (clobber (reg:SI LR_REGNUM))]
7567   "TARGET_THUMB
7568    && GET_CODE (operands[0]) == SYMBOL_REF
7569    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7570   "bl\\t%a0"
7571   [(set_attr "length" "4")
7572    (set_attr "type" "call")]
7575 (define_insn "*call_value_insn"
7576   [(set (match_operand 0 "register_operand" "")
7577         (call (mem:SI (match_operand 1 "" ""))
7578               (match_operand 2 "" "")))
7579    (use (match_operand 3 "" ""))
7580    (clobber (reg:SI LR_REGNUM))]
7581   "TARGET_THUMB
7582    && GET_CODE (operands[1]) == SYMBOL_REF
7583    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7584   "bl\\t%a1"
7585   [(set_attr "length" "4")
7586    (set_attr "type" "call")]
7589 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7590 (define_expand "sibcall"
7591   [(parallel [(call (match_operand 0 "memory_operand" "")
7592                     (match_operand 1 "general_operand" ""))
7593               (return)
7594               (use (match_operand 2 "" ""))])]
7595   "TARGET_ARM"
7596   "
7597   {
7598     if (operands[2] == NULL_RTX)
7599       operands[2] = const0_rtx;
7600   }"
7603 (define_expand "sibcall_value"
7604   [(parallel [(set (match_operand 0 "register_operand" "")
7605                    (call (match_operand 1 "memory_operand" "")
7606                          (match_operand 2 "general_operand" "")))
7607               (return)
7608               (use (match_operand 3 "" ""))])]
7609   "TARGET_ARM"
7610   "
7611   {
7612     if (operands[3] == NULL_RTX)
7613       operands[3] = const0_rtx;
7614   }"
7617 (define_insn "*sibcall_insn"
7618  [(call (mem:SI (match_operand:SI 0 "" "X"))
7619         (match_operand 1 "" ""))
7620   (return)
7621   (use (match_operand 2 "" ""))]
7622   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7623   "*
7624   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7625   "
7626   [(set_attr "type" "call")]
7629 (define_insn "*sibcall_value_insn"
7630  [(set (match_operand 0 "s_register_operand" "")
7631        (call (mem:SI (match_operand:SI 1 "" "X"))
7632              (match_operand 2 "" "")))
7633   (return)
7634   (use (match_operand 3 "" ""))]
7635   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7636   "*
7637   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7638   "
7639   [(set_attr "type" "call")]
7642 ;; Often the return insn will be the same as loading from memory, so set attr
7643 (define_insn "return"
7644   [(return)]
7645   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7646   "*
7647   {
7648     if (arm_ccfsm_state == 2)
7649       {
7650         arm_ccfsm_state += 2;
7651         return \"\";
7652       }
7653     return output_return_instruction (const_true_rtx, TRUE, FALSE);
7654   }"
7655   [(set_attr "type" "load1")
7656    (set_attr "length" "12")
7657    (set_attr "predicable" "yes")]
7660 (define_insn "*cond_return"
7661   [(set (pc)
7662         (if_then_else (match_operator 0 "arm_comparison_operator"
7663                        [(match_operand 1 "cc_register" "") (const_int 0)])
7664                       (return)
7665                       (pc)))]
7666   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7667   "*
7668   {
7669     if (arm_ccfsm_state == 2)
7670       {
7671         arm_ccfsm_state += 2;
7672         return \"\";
7673       }
7674     return output_return_instruction (operands[0], TRUE, FALSE);
7675   }"
7676   [(set_attr "conds" "use")
7677    (set_attr "length" "12")
7678    (set_attr "type" "load1")]
7681 (define_insn "*cond_return_inverted"
7682   [(set (pc)
7683         (if_then_else (match_operator 0 "arm_comparison_operator"
7684                        [(match_operand 1 "cc_register" "") (const_int 0)])
7685                       (pc)
7686                       (return)))]
7687   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7688   "*
7689   {
7690     if (arm_ccfsm_state == 2)
7691       {
7692         arm_ccfsm_state += 2;
7693         return \"\";
7694       }
7695     return output_return_instruction (operands[0], TRUE, TRUE);
7696   }"
7697   [(set_attr "conds" "use")
7698    (set_attr "length" "12")
7699    (set_attr "type" "load1")]
7702 ;; Generate a sequence of instructions to determine if the processor is
7703 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7704 ;; mask.
7706 (define_expand "return_addr_mask"
7707   [(set (match_dup 1)
7708       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7709                        (const_int 0)))
7710    (set (match_operand:SI 0 "s_register_operand" "")
7711       (if_then_else:SI (eq (match_dup 1) (const_int 0))
7712                        (const_int -1)
7713                        (const_int 67108860)))] ; 0x03fffffc
7714   "TARGET_ARM"
7715   "
7716   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7717   ")
7719 (define_insn "*check_arch2"
7720   [(set (match_operand:CC_NOOV 0 "cc_register" "")
7721       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7722                        (const_int 0)))]
7723   "TARGET_ARM"
7724   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7725   [(set_attr "length" "8")
7726    (set_attr "conds" "set")]
7729 ;; Call subroutine returning any type.
7731 (define_expand "untyped_call"
7732   [(parallel [(call (match_operand 0 "" "")
7733                     (const_int 0))
7734               (match_operand 1 "" "")
7735               (match_operand 2 "" "")])]
7736   "TARGET_ARM"
7737   "
7738   {
7739     int i;
7741     emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
7743     for (i = 0; i < XVECLEN (operands[2], 0); i++)
7744       {
7745         rtx set = XVECEXP (operands[2], 0, i);
7747         emit_move_insn (SET_DEST (set), SET_SRC (set));
7748       }
7750     /* The optimizer does not know that the call sets the function value
7751        registers we stored in the result block.  We avoid problems by
7752        claiming that all hard registers are used and clobbered at this
7753        point.  */
7754     emit_insn (gen_blockage ());
7756     DONE;
7757   }"
7760 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7761 ;; all of memory.  This blocks insns from being moved across this point.
7763 (define_insn "blockage"
7764   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
7765   "TARGET_EITHER"
7766   ""
7767   [(set_attr "length" "0")
7768    (set_attr "type" "block")]
7771 (define_expand "casesi"
7772   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
7773    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
7774    (match_operand:SI 2 "const_int_operand" "")  ; total range
7775    (match_operand:SI 3 "" "")                   ; table label
7776    (match_operand:SI 4 "" "")]                  ; Out of range label
7777   "TARGET_ARM"
7778   "
7779   {
7780     rtx reg;
7781     if (operands[1] != const0_rtx)
7782       {
7783         reg = gen_reg_rtx (SImode);
7785         emit_insn (gen_addsi3 (reg, operands[0],
7786                                GEN_INT (-INTVAL (operands[1]))));
7787         operands[0] = reg;
7788       }
7790     if (!const_ok_for_arm (INTVAL (operands[2])))
7791       operands[2] = force_reg (SImode, operands[2]);
7793     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
7794                                          operands[4]));
7795     DONE;
7796   }"
7799 ;; The USE in this pattern is needed to tell flow analysis that this is
7800 ;; a CASESI insn.  It has no other purpose.
7801 (define_insn "casesi_internal"
7802   [(parallel [(set (pc)
7803                (if_then_else
7804                 (leu (match_operand:SI 0 "s_register_operand" "r")
7805                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
7806                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
7807                                  (label_ref (match_operand 2 "" ""))))
7808                 (label_ref (match_operand 3 "" ""))))
7809               (clobber (reg:CC CC_REGNUM))
7810               (use (label_ref (match_dup 2)))])]
7811   "TARGET_ARM"
7812   "*
7813     if (flag_pic)
7814       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
7815     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
7816   "
7817   [(set_attr "conds" "clob")
7818    (set_attr "length" "12")]
7821 (define_expand "indirect_jump"
7822   [(set (pc)
7823         (match_operand:SI 0 "s_register_operand" ""))]
7824   "TARGET_EITHER"
7825   ""
7828 ;; NB Never uses BX.
7829 (define_insn "*arm_indirect_jump"
7830   [(set (pc)
7831         (match_operand:SI 0 "s_register_operand" "r"))]
7832   "TARGET_ARM"
7833   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
7834   [(set_attr "predicable" "yes")]
7837 (define_insn "*load_indirect_jump"
7838   [(set (pc)
7839         (match_operand:SI 0 "memory_operand" "m"))]
7840   "TARGET_ARM"
7841   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
7842   [(set_attr "type" "load1")
7843    (set_attr "pool_range" "4096")
7844    (set_attr "neg_pool_range" "4084")
7845    (set_attr "predicable" "yes")]
7848 ;; NB Never uses BX.
7849 (define_insn "*thumb_indirect_jump"
7850   [(set (pc)
7851         (match_operand:SI 0 "register_operand" "l*r"))]
7852   "TARGET_THUMB"
7853   "mov\\tpc, %0"
7854   [(set_attr "conds" "clob")
7855    (set_attr "length" "2")]
7859 ;; Misc insns
7861 (define_insn "nop"
7862   [(const_int 0)]
7863   "TARGET_EITHER"
7864   "*
7865   if (TARGET_ARM)
7866     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
7867   return  \"mov\\tr8, r8\";
7868   "
7869   [(set (attr "length")
7870         (if_then_else (eq_attr "is_thumb" "yes")
7871                       (const_int 2)
7872                       (const_int 4)))]
7876 ;; Patterns to allow combination of arithmetic, cond code and shifts
7878 (define_insn "*arith_shiftsi"
7879   [(set (match_operand:SI 0 "s_register_operand" "=r")
7880         (match_operator:SI 1 "shiftable_operator"
7881           [(match_operator:SI 3 "shift_operator"
7882              [(match_operand:SI 4 "s_register_operand" "r")
7883               (match_operand:SI 5 "reg_or_int_operand" "rI")])
7884            (match_operand:SI 2 "s_register_operand" "r")]))]
7885   "TARGET_ARM"
7886   "%i1%?\\t%0, %2, %4%S3"
7887   [(set_attr "predicable" "yes")
7888    (set_attr "shift" "4")
7889    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7890                       (const_string "alu_shift")
7891                       (const_string "alu_shift_reg")))]
7894 (define_split
7895   [(set (match_operand:SI 0 "s_register_operand" "")
7896         (match_operator:SI 1 "shiftable_operator"
7897          [(match_operator:SI 2 "shiftable_operator"
7898            [(match_operator:SI 3 "shift_operator"
7899              [(match_operand:SI 4 "s_register_operand" "")
7900               (match_operand:SI 5 "reg_or_int_operand" "")])
7901             (match_operand:SI 6 "s_register_operand" "")])
7902           (match_operand:SI 7 "arm_rhs_operand" "")]))
7903    (clobber (match_operand:SI 8 "s_register_operand" ""))]
7904   "TARGET_ARM"
7905   [(set (match_dup 8)
7906         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7907                          (match_dup 6)]))
7908    (set (match_dup 0)
7909         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
7910   "")
7912 (define_insn "*arith_shiftsi_compare0"
7913   [(set (reg:CC_NOOV CC_REGNUM)
7914         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7915                           [(match_operator:SI 3 "shift_operator"
7916                             [(match_operand:SI 4 "s_register_operand" "r")
7917                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
7918                            (match_operand:SI 2 "s_register_operand" "r")])
7919                          (const_int 0)))
7920    (set (match_operand:SI 0 "s_register_operand" "=r")
7921         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7922                          (match_dup 2)]))]
7923   "TARGET_ARM"
7924   "%i1%?s\\t%0, %2, %4%S3"
7925   [(set_attr "conds" "set")
7926    (set_attr "shift" "4")
7927    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7928                       (const_string "alu_shift")
7929                       (const_string "alu_shift_reg")))]
7932 (define_insn "*arith_shiftsi_compare0_scratch"
7933   [(set (reg:CC_NOOV CC_REGNUM)
7934         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7935                           [(match_operator:SI 3 "shift_operator"
7936                             [(match_operand:SI 4 "s_register_operand" "r")
7937                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
7938                            (match_operand:SI 2 "s_register_operand" "r")])
7939                          (const_int 0)))
7940    (clobber (match_scratch:SI 0 "=r"))]
7941   "TARGET_ARM"
7942   "%i1%?s\\t%0, %2, %4%S3"
7943   [(set_attr "conds" "set")
7944    (set_attr "shift" "4")
7945    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7946                       (const_string "alu_shift")
7947                       (const_string "alu_shift_reg")))]
7950 (define_insn "*sub_shiftsi"
7951   [(set (match_operand:SI 0 "s_register_operand" "=r")
7952         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7953                   (match_operator:SI 2 "shift_operator"
7954                    [(match_operand:SI 3 "s_register_operand" "r")
7955                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
7956   "TARGET_ARM"
7957   "sub%?\\t%0, %1, %3%S2"
7958   [(set_attr "predicable" "yes")
7959    (set_attr "shift" "3")
7960    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7961                       (const_string "alu_shift")
7962                       (const_string "alu_shift_reg")))]
7965 (define_insn "*sub_shiftsi_compare0"
7966   [(set (reg:CC_NOOV CC_REGNUM)
7967         (compare:CC_NOOV
7968          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7969                    (match_operator:SI 2 "shift_operator"
7970                     [(match_operand:SI 3 "s_register_operand" "r")
7971                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7972          (const_int 0)))
7973    (set (match_operand:SI 0 "s_register_operand" "=r")
7974         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7975                                                  (match_dup 4)])))]
7976   "TARGET_ARM"
7977   "sub%?s\\t%0, %1, %3%S2"
7978   [(set_attr "conds" "set")
7979    (set_attr "shift" "3")
7980    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7981                       (const_string "alu_shift")
7982                       (const_string "alu_shift_reg")))]
7985 (define_insn "*sub_shiftsi_compare0_scratch"
7986   [(set (reg:CC_NOOV CC_REGNUM)
7987         (compare:CC_NOOV
7988          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7989                    (match_operator:SI 2 "shift_operator"
7990                     [(match_operand:SI 3 "s_register_operand" "r")
7991                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7992          (const_int 0)))
7993    (clobber (match_scratch:SI 0 "=r"))]
7994   "TARGET_ARM"
7995   "sub%?s\\t%0, %1, %3%S2"
7996   [(set_attr "conds" "set")
7997    (set_attr "shift" "3")
7998    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7999                       (const_string "alu_shift")
8000                       (const_string "alu_shift_reg")))]
8005 (define_insn "*and_scc"
8006   [(set (match_operand:SI 0 "s_register_operand" "=r")
8007         (and:SI (match_operator:SI 1 "arm_comparison_operator"
8008                  [(match_operand 3 "cc_register" "") (const_int 0)])
8009                 (match_operand:SI 2 "s_register_operand" "r")))]
8010   "TARGET_ARM"
8011   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8012   [(set_attr "conds" "use")
8013    (set_attr "length" "8")]
8016 (define_insn "*ior_scc"
8017   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8018         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8019                  [(match_operand 3 "cc_register" "") (const_int 0)])
8020                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8021   "TARGET_ARM"
8022   "@
8023    orr%d2\\t%0, %1, #1
8024    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8025   [(set_attr "conds" "use")
8026    (set_attr "length" "4,8")]
8029 (define_insn "*compare_scc"
8030   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8031         (match_operator:SI 1 "arm_comparison_operator"
8032          [(match_operand:SI 2 "s_register_operand" "r,r")
8033           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8034    (clobber (reg:CC CC_REGNUM))]
8035   "TARGET_ARM"
8036   "*
8037     if (operands[3] == const0_rtx)
8038       {
8039         if (GET_CODE (operands[1]) == LT)
8040           return \"mov\\t%0, %2, lsr #31\";
8042         if (GET_CODE (operands[1]) == GE)
8043           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8045         if (GET_CODE (operands[1]) == EQ)
8046           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8047       }
8049     if (GET_CODE (operands[1]) == NE)
8050       {
8051         if (which_alternative == 1)
8052           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8053         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8054       }
8055     if (which_alternative == 1)
8056       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8057     else
8058       output_asm_insn (\"cmp\\t%2, %3\", operands);
8059     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8060   "
8061   [(set_attr "conds" "clob")
8062    (set_attr "length" "12")]
8065 (define_insn "*cond_move"
8066   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8067         (if_then_else:SI (match_operator 3 "equality_operator"
8068                           [(match_operator 4 "arm_comparison_operator"
8069                             [(match_operand 5 "cc_register" "") (const_int 0)])
8070                            (const_int 0)])
8071                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8072                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8073   "TARGET_ARM"
8074   "*
8075     if (GET_CODE (operands[3]) == NE)
8076       {
8077         if (which_alternative != 1)
8078           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8079         if (which_alternative != 0)
8080           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8081         return \"\";
8082       }
8083     if (which_alternative != 0)
8084       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8085     if (which_alternative != 1)
8086       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8087     return \"\";
8088   "
8089   [(set_attr "conds" "use")
8090    (set_attr "length" "4,4,8")]
8093 (define_insn "*cond_arith"
8094   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8095         (match_operator:SI 5 "shiftable_operator" 
8096          [(match_operator:SI 4 "arm_comparison_operator"
8097            [(match_operand:SI 2 "s_register_operand" "r,r")
8098             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8099           (match_operand:SI 1 "s_register_operand" "0,?r")]))
8100    (clobber (reg:CC CC_REGNUM))]
8101   "TARGET_ARM"
8102   "*
8103     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8104       return \"%i5\\t%0, %1, %2, lsr #31\";
8106     output_asm_insn (\"cmp\\t%2, %3\", operands);
8107     if (GET_CODE (operands[5]) == AND)
8108       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8109     else if (GET_CODE (operands[5]) == MINUS)
8110       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8111     else if (which_alternative != 0)
8112       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8113     return \"%i5%d4\\t%0, %1, #1\";
8114   "
8115   [(set_attr "conds" "clob")
8116    (set_attr "length" "12")]
8119 (define_insn "*cond_sub"
8120   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8121         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8122                   (match_operator:SI 4 "arm_comparison_operator"
8123                    [(match_operand:SI 2 "s_register_operand" "r,r")
8124                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8125    (clobber (reg:CC CC_REGNUM))]
8126   "TARGET_ARM"
8127   "*
8128     output_asm_insn (\"cmp\\t%2, %3\", operands);
8129     if (which_alternative != 0)
8130       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8131     return \"sub%d4\\t%0, %1, #1\";
8132   "
8133   [(set_attr "conds" "clob")
8134    (set_attr "length" "8,12")]
8137 (define_insn "*cmp_ite0"
8138   [(set (match_operand 6 "dominant_cc_register" "")
8139         (compare
8140          (if_then_else:SI
8141           (match_operator 4 "arm_comparison_operator"
8142            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8143             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8144           (match_operator:SI 5 "arm_comparison_operator"
8145            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8146             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8147           (const_int 0))
8148          (const_int 0)))]
8149   "TARGET_ARM"
8150   "*
8151   {
8152     static const char * const opcodes[4][2] =
8153     {
8154       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8155        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8156       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8157        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8158       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8159        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8160       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8161        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8162     };
8163     int swap =
8164       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8166     return opcodes[which_alternative][swap];
8167   }"
8168   [(set_attr "conds" "set")
8169    (set_attr "length" "8")]
8172 (define_insn "*cmp_ite1"
8173   [(set (match_operand 6 "dominant_cc_register" "")
8174         (compare
8175          (if_then_else:SI
8176           (match_operator 4 "arm_comparison_operator"
8177            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8178             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8179           (match_operator:SI 5 "arm_comparison_operator"
8180            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8181             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8182           (const_int 1))
8183          (const_int 0)))]
8184   "TARGET_ARM"
8185   "*
8186   {
8187     static const char * const opcodes[4][2] =
8188     {
8189       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8190        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8191       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8192        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8193       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8194        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8195       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8196        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8197     };
8198     int swap =
8199       comparison_dominates_p (GET_CODE (operands[5]),
8200                               reverse_condition (GET_CODE (operands[4])));
8202     return opcodes[which_alternative][swap];
8203   }"
8204   [(set_attr "conds" "set")
8205    (set_attr "length" "8")]
8208 (define_insn "*cmp_and"
8209   [(set (match_operand 6 "dominant_cc_register" "")
8210         (compare
8211          (and:SI
8212           (match_operator 4 "arm_comparison_operator"
8213            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8214             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8215           (match_operator:SI 5 "arm_comparison_operator"
8216            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8217             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8218          (const_int 0)))]
8219   "TARGET_ARM"
8220   "*
8221   {
8222     static const char *const opcodes[4][2] =
8223     {
8224       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8225        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8226       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8227        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8228       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8229        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8230       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8231        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8232     };
8233     int swap =
8234       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8236     return opcodes[which_alternative][swap];
8237   }"
8238   [(set_attr "conds" "set")
8239    (set_attr "predicable" "no")
8240    (set_attr "length" "8")]
8243 (define_insn "*cmp_ior"
8244   [(set (match_operand 6 "dominant_cc_register" "")
8245         (compare
8246          (ior:SI
8247           (match_operator 4 "arm_comparison_operator"
8248            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8249             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8250           (match_operator:SI 5 "arm_comparison_operator"
8251            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8252             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8253          (const_int 0)))]
8254   "TARGET_ARM"
8255   "*
8257   static const char *const opcodes[4][2] =
8258   {
8259     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8260      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8261     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8262      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8263     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8264      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8265     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8266      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8267   };
8268   int swap =
8269     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8271   return opcodes[which_alternative][swap];
8274   [(set_attr "conds" "set")
8275    (set_attr "length" "8")]
8278 (define_insn_and_split "*ior_scc_scc"
8279   [(set (match_operand:SI 0 "s_register_operand" "=r")
8280         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8281                  [(match_operand:SI 1 "s_register_operand" "r")
8282                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8283                 (match_operator:SI 6 "arm_comparison_operator"
8284                  [(match_operand:SI 4 "s_register_operand" "r")
8285                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8286    (clobber (reg:CC CC_REGNUM))]
8287   "TARGET_ARM
8288    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8289        != CCmode)"
8290   "#"
8291   "TARGET_ARM && reload_completed"
8292   [(set (match_dup 7)
8293         (compare
8294          (ior:SI
8295           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8296           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8297          (const_int 0)))
8298    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8299   "operands[7]
8300      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8301                                                   DOM_CC_X_OR_Y),
8302                     CC_REGNUM);"
8303   [(set_attr "conds" "clob")
8304    (set_attr "length" "16")])
8306 ; If the above pattern is followed by a CMP insn, then the compare is 
8307 ; redundant, since we can rework the conditional instruction that follows.
8308 (define_insn_and_split "*ior_scc_scc_cmp"
8309   [(set (match_operand 0 "dominant_cc_register" "")
8310         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8311                           [(match_operand:SI 1 "s_register_operand" "r")
8312                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8313                          (match_operator:SI 6 "arm_comparison_operator"
8314                           [(match_operand:SI 4 "s_register_operand" "r")
8315                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8316                  (const_int 0)))
8317    (set (match_operand:SI 7 "s_register_operand" "=r")
8318         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8319                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8320   "TARGET_ARM"
8321   "#"
8322   "TARGET_ARM && reload_completed"
8323   [(set (match_dup 0)
8324         (compare
8325          (ior:SI
8326           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8327           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8328          (const_int 0)))
8329    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8330   ""
8331   [(set_attr "conds" "set")
8332    (set_attr "length" "16")])
8334 (define_insn_and_split "*and_scc_scc"
8335   [(set (match_operand:SI 0 "s_register_operand" "=r")
8336         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8337                  [(match_operand:SI 1 "s_register_operand" "r")
8338                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8339                 (match_operator:SI 6 "arm_comparison_operator"
8340                  [(match_operand:SI 4 "s_register_operand" "r")
8341                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8342    (clobber (reg:CC CC_REGNUM))]
8343   "TARGET_ARM
8344    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8345        != CCmode)"
8346   "#"
8347   "TARGET_ARM && reload_completed
8348    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8349        != CCmode)"
8350   [(set (match_dup 7)
8351         (compare
8352          (and:SI
8353           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8354           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8355          (const_int 0)))
8356    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8357   "operands[7]
8358      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8359                                                   DOM_CC_X_AND_Y),
8360                     CC_REGNUM);"
8361   [(set_attr "conds" "clob")
8362    (set_attr "length" "16")])
8364 ; If the above pattern is followed by a CMP insn, then the compare is 
8365 ; redundant, since we can rework the conditional instruction that follows.
8366 (define_insn_and_split "*and_scc_scc_cmp"
8367   [(set (match_operand 0 "dominant_cc_register" "")
8368         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8369                           [(match_operand:SI 1 "s_register_operand" "r")
8370                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8371                          (match_operator:SI 6 "arm_comparison_operator"
8372                           [(match_operand:SI 4 "s_register_operand" "r")
8373                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8374                  (const_int 0)))
8375    (set (match_operand:SI 7 "s_register_operand" "=r")
8376         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8377                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8378   "TARGET_ARM"
8379   "#"
8380   "TARGET_ARM && reload_completed"
8381   [(set (match_dup 0)
8382         (compare
8383          (and:SI
8384           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8385           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8386          (const_int 0)))
8387    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8388   ""
8389   [(set_attr "conds" "set")
8390    (set_attr "length" "16")])
8392 ;; If there is no dominance in the comparison, then we can still save an
8393 ;; instruction in the AND case, since we can know that the second compare
8394 ;; need only zero the value if false (if true, then the value is already
8395 ;; correct).
8396 (define_insn_and_split "*and_scc_scc_nodom"
8397   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8398         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8399                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
8400                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8401                 (match_operator:SI 6 "arm_comparison_operator"
8402                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
8403                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8404    (clobber (reg:CC CC_REGNUM))]
8405   "TARGET_ARM
8406    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8407        == CCmode)"
8408   "#"
8409   "TARGET_ARM && reload_completed"
8410   [(parallel [(set (match_dup 0)
8411                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8412               (clobber (reg:CC CC_REGNUM))])
8413    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8414    (set (match_dup 0)
8415         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8416                          (match_dup 0)
8417                          (const_int 0)))]
8418   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8419                                               operands[4], operands[5]),
8420                               CC_REGNUM);
8421    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8422                                   operands[5]);"
8423   [(set_attr "conds" "clob")
8424    (set_attr "length" "20")])
8426 (define_split
8427   [(set (reg:CC_NOOV CC_REGNUM)
8428         (compare:CC_NOOV (ior:SI
8429                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8430                                   (const_int 1))
8431                           (match_operator:SI 1 "comparison_operator"
8432                            [(match_operand:SI 2 "s_register_operand" "")
8433                             (match_operand:SI 3 "arm_add_operand" "")]))
8434                          (const_int 0)))
8435    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8436   "TARGET_ARM"
8437   [(set (match_dup 4)
8438         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8439                 (match_dup 0)))
8440    (set (reg:CC_NOOV CC_REGNUM)
8441         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8442                          (const_int 0)))]
8443   "")
8445 (define_split
8446   [(set (reg:CC_NOOV CC_REGNUM)
8447         (compare:CC_NOOV (ior:SI
8448                           (match_operator:SI 1 "comparison_operator"
8449                            [(match_operand:SI 2 "s_register_operand" "")
8450                             (match_operand:SI 3 "arm_add_operand" "")])
8451                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8452                                   (const_int 1)))
8453                          (const_int 0)))
8454    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8455   "TARGET_ARM"
8456   [(set (match_dup 4)
8457         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8458                 (match_dup 0)))
8459    (set (reg:CC_NOOV CC_REGNUM)
8460         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8461                          (const_int 0)))]
8462   "")
8464 (define_insn "*negscc"
8465   [(set (match_operand:SI 0 "s_register_operand" "=r")
8466         (neg:SI (match_operator 3 "arm_comparison_operator"
8467                  [(match_operand:SI 1 "s_register_operand" "r")
8468                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8469    (clobber (reg:CC CC_REGNUM))]
8470   "TARGET_ARM"
8471   "*
8472   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8473     return \"mov\\t%0, %1, asr #31\";
8475   if (GET_CODE (operands[3]) == NE)
8476     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8478   if (GET_CODE (operands[3]) == GT)
8479     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8481   output_asm_insn (\"cmp\\t%1, %2\", operands);
8482   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8483   return \"mvn%d3\\t%0, #0\";
8484   "
8485   [(set_attr "conds" "clob")
8486    (set_attr "length" "12")]
8489 (define_insn "movcond"
8490   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8491         (if_then_else:SI
8492          (match_operator 5 "arm_comparison_operator"
8493           [(match_operand:SI 3 "s_register_operand" "r,r,r")
8494            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8495          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8496          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8497    (clobber (reg:CC CC_REGNUM))]
8498   "TARGET_ARM"
8499   "*
8500   if (GET_CODE (operands[5]) == LT
8501       && (operands[4] == const0_rtx))
8502     {
8503       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8504         {
8505           if (operands[2] == const0_rtx)
8506             return \"and\\t%0, %1, %3, asr #31\";
8507           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8508         }
8509       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8510         {
8511           if (operands[1] == const0_rtx)
8512             return \"bic\\t%0, %2, %3, asr #31\";
8513           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8514         }
8515       /* The only case that falls through to here is when both ops 1 & 2
8516          are constants.  */
8517     }
8519   if (GET_CODE (operands[5]) == GE
8520       && (operands[4] == const0_rtx))
8521     {
8522       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8523         {
8524           if (operands[2] == const0_rtx)
8525             return \"bic\\t%0, %1, %3, asr #31\";
8526           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8527         }
8528       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8529         {
8530           if (operands[1] == const0_rtx)
8531             return \"and\\t%0, %2, %3, asr #31\";
8532           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8533         }
8534       /* The only case that falls through to here is when both ops 1 & 2
8535          are constants.  */
8536     }
8537   if (GET_CODE (operands[4]) == CONST_INT
8538       && !const_ok_for_arm (INTVAL (operands[4])))
8539     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8540   else
8541     output_asm_insn (\"cmp\\t%3, %4\", operands);
8542   if (which_alternative != 0)
8543     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8544   if (which_alternative != 1)
8545     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8546   return \"\";
8547   "
8548   [(set_attr "conds" "clob")
8549    (set_attr "length" "8,8,12")]
8552 (define_insn "*ifcompare_plus_move"
8553   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8554         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8555                           [(match_operand:SI 4 "s_register_operand" "r,r")
8556                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8557                          (plus:SI
8558                           (match_operand:SI 2 "s_register_operand" "r,r")
8559                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8560                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8561    (clobber (reg:CC CC_REGNUM))]
8562   "TARGET_ARM"
8563   "#"
8564   [(set_attr "conds" "clob")
8565    (set_attr "length" "8,12")]
8568 (define_insn "*if_plus_move"
8569   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8570         (if_then_else:SI
8571          (match_operator 4 "arm_comparison_operator"
8572           [(match_operand 5 "cc_register" "") (const_int 0)])
8573          (plus:SI
8574           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8575           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8576          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8577   "TARGET_ARM"
8578   "@
8579    add%d4\\t%0, %2, %3
8580    sub%d4\\t%0, %2, #%n3
8581    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8582    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8583   [(set_attr "conds" "use")
8584    (set_attr "length" "4,4,8,8")
8585    (set_attr "type" "*,*,*,*")]
8588 (define_insn "*ifcompare_move_plus"
8589   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8590         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8591                           [(match_operand:SI 4 "s_register_operand" "r,r")
8592                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8593                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8594                          (plus:SI
8595                           (match_operand:SI 2 "s_register_operand" "r,r")
8596                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8597    (clobber (reg:CC CC_REGNUM))]
8598   "TARGET_ARM"
8599   "#"
8600   [(set_attr "conds" "clob")
8601    (set_attr "length" "8,12")]
8604 (define_insn "*if_move_plus"
8605   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8606         (if_then_else:SI
8607          (match_operator 4 "arm_comparison_operator"
8608           [(match_operand 5 "cc_register" "") (const_int 0)])
8609          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8610          (plus:SI
8611           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8612           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8613   "TARGET_ARM"
8614   "@
8615    add%D4\\t%0, %2, %3
8616    sub%D4\\t%0, %2, #%n3
8617    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8618    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8619   [(set_attr "conds" "use")
8620    (set_attr "length" "4,4,8,8")
8621    (set_attr "type" "*,*,*,*")]
8624 (define_insn "*ifcompare_arith_arith"
8625   [(set (match_operand:SI 0 "s_register_operand" "=r")
8626         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8627                           [(match_operand:SI 5 "s_register_operand" "r")
8628                            (match_operand:SI 6 "arm_add_operand" "rIL")])
8629                          (match_operator:SI 8 "shiftable_operator"
8630                           [(match_operand:SI 1 "s_register_operand" "r")
8631                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8632                          (match_operator:SI 7 "shiftable_operator"
8633                           [(match_operand:SI 3 "s_register_operand" "r")
8634                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8635    (clobber (reg:CC CC_REGNUM))]
8636   "TARGET_ARM"
8637   "#"
8638   [(set_attr "conds" "clob")
8639    (set_attr "length" "12")]
8642 (define_insn "*if_arith_arith"
8643   [(set (match_operand:SI 0 "s_register_operand" "=r")
8644         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8645                           [(match_operand 8 "cc_register" "") (const_int 0)])
8646                          (match_operator:SI 6 "shiftable_operator"
8647                           [(match_operand:SI 1 "s_register_operand" "r")
8648                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8649                          (match_operator:SI 7 "shiftable_operator"
8650                           [(match_operand:SI 3 "s_register_operand" "r")
8651                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8652   "TARGET_ARM"
8653   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8654   [(set_attr "conds" "use")
8655    (set_attr "length" "8")]
8658 (define_insn "*ifcompare_arith_move"
8659   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8660         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8661                           [(match_operand:SI 2 "s_register_operand" "r,r")
8662                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8663                          (match_operator:SI 7 "shiftable_operator"
8664                           [(match_operand:SI 4 "s_register_operand" "r,r")
8665                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8666                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8667    (clobber (reg:CC CC_REGNUM))]
8668   "TARGET_ARM"
8669   "*
8670   /* If we have an operation where (op x 0) is the identity operation and
8671      the conditional operator is LT or GE and we are comparing against zero and
8672      everything is in registers then we can do this in two instructions.  */
8673   if (operands[3] == const0_rtx
8674       && GET_CODE (operands[7]) != AND
8675       && GET_CODE (operands[5]) == REG
8676       && GET_CODE (operands[1]) == REG 
8677       && REGNO (operands[1]) == REGNO (operands[4])
8678       && REGNO (operands[4]) != REGNO (operands[0]))
8679     {
8680       if (GET_CODE (operands[6]) == LT)
8681         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8682       else if (GET_CODE (operands[6]) == GE)
8683         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8684     }
8685   if (GET_CODE (operands[3]) == CONST_INT
8686       && !const_ok_for_arm (INTVAL (operands[3])))
8687     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8688   else
8689     output_asm_insn (\"cmp\\t%2, %3\", operands);
8690   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8691   if (which_alternative != 0)
8692     return \"mov%D6\\t%0, %1\";
8693   return \"\";
8694   "
8695   [(set_attr "conds" "clob")
8696    (set_attr "length" "8,12")]
8699 (define_insn "*if_arith_move"
8700   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8701         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8702                           [(match_operand 6 "cc_register" "") (const_int 0)])
8703                          (match_operator:SI 5 "shiftable_operator"
8704                           [(match_operand:SI 2 "s_register_operand" "r,r")
8705                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8706                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8707   "TARGET_ARM"
8708   "@
8709    %I5%d4\\t%0, %2, %3
8710    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8711   [(set_attr "conds" "use")
8712    (set_attr "length" "4,8")
8713    (set_attr "type" "*,*")]
8716 (define_insn "*ifcompare_move_arith"
8717   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8718         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8719                           [(match_operand:SI 4 "s_register_operand" "r,r")
8720                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8721                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8722                          (match_operator:SI 7 "shiftable_operator"
8723                           [(match_operand:SI 2 "s_register_operand" "r,r")
8724                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8725    (clobber (reg:CC CC_REGNUM))]
8726   "TARGET_ARM"
8727   "*
8728   /* If we have an operation where (op x 0) is the identity operation and
8729      the conditional operator is LT or GE and we are comparing against zero and
8730      everything is in registers then we can do this in two instructions */
8731   if (operands[5] == const0_rtx
8732       && GET_CODE (operands[7]) != AND
8733       && GET_CODE (operands[3]) == REG
8734       && GET_CODE (operands[1]) == REG 
8735       && REGNO (operands[1]) == REGNO (operands[2])
8736       && REGNO (operands[2]) != REGNO (operands[0]))
8737     {
8738       if (GET_CODE (operands[6]) == GE)
8739         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8740       else if (GET_CODE (operands[6]) == LT)
8741         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8742     }
8744   if (GET_CODE (operands[5]) == CONST_INT
8745       && !const_ok_for_arm (INTVAL (operands[5])))
8746     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
8747   else
8748     output_asm_insn (\"cmp\\t%4, %5\", operands);
8750   if (which_alternative != 0)
8751     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
8752   return \"%I7%D6\\t%0, %2, %3\";
8753   "
8754   [(set_attr "conds" "clob")
8755    (set_attr "length" "8,12")]
8758 (define_insn "*if_move_arith"
8759   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8760         (if_then_else:SI
8761          (match_operator 4 "arm_comparison_operator"
8762           [(match_operand 6 "cc_register" "") (const_int 0)])
8763          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8764          (match_operator:SI 5 "shiftable_operator"
8765           [(match_operand:SI 2 "s_register_operand" "r,r")
8766            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
8767   "TARGET_ARM"
8768   "@
8769    %I5%D4\\t%0, %2, %3
8770    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8771   [(set_attr "conds" "use")
8772    (set_attr "length" "4,8")
8773    (set_attr "type" "*,*")]
8776 (define_insn "*ifcompare_move_not"
8777   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8778         (if_then_else:SI
8779          (match_operator 5 "arm_comparison_operator"
8780           [(match_operand:SI 3 "s_register_operand" "r,r")
8781            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8782          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8783          (not:SI
8784           (match_operand:SI 2 "s_register_operand" "r,r"))))
8785    (clobber (reg:CC CC_REGNUM))]
8786   "TARGET_ARM"
8787   "#"
8788   [(set_attr "conds" "clob")
8789    (set_attr "length" "8,12")]
8792 (define_insn "*if_move_not"
8793   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8794         (if_then_else:SI
8795          (match_operator 4 "arm_comparison_operator"
8796           [(match_operand 3 "cc_register" "") (const_int 0)])
8797          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8798          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8799   "TARGET_ARM"
8800   "@
8801    mvn%D4\\t%0, %2
8802    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
8803    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8804   [(set_attr "conds" "use")
8805    (set_attr "length" "4,8,8")]
8808 (define_insn "*ifcompare_not_move"
8809   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8810         (if_then_else:SI 
8811          (match_operator 5 "arm_comparison_operator"
8812           [(match_operand:SI 3 "s_register_operand" "r,r")
8813            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8814          (not:SI
8815           (match_operand:SI 2 "s_register_operand" "r,r"))
8816          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8817    (clobber (reg:CC CC_REGNUM))]
8818   "TARGET_ARM"
8819   "#"
8820   [(set_attr "conds" "clob")
8821    (set_attr "length" "8,12")]
8824 (define_insn "*if_not_move"
8825   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8826         (if_then_else:SI
8827          (match_operator 4 "arm_comparison_operator"
8828           [(match_operand 3 "cc_register" "") (const_int 0)])
8829          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8830          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8831   "TARGET_ARM"
8832   "@
8833    mvn%d4\\t%0, %2
8834    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
8835    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8836   [(set_attr "conds" "use")
8837    (set_attr "length" "4,8,8")]
8840 (define_insn "*ifcompare_shift_move"
8841   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8842         (if_then_else:SI
8843          (match_operator 6 "arm_comparison_operator"
8844           [(match_operand:SI 4 "s_register_operand" "r,r")
8845            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8846          (match_operator:SI 7 "shift_operator"
8847           [(match_operand:SI 2 "s_register_operand" "r,r")
8848            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
8849          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8850    (clobber (reg:CC CC_REGNUM))]
8851   "TARGET_ARM"
8852   "#"
8853   [(set_attr "conds" "clob")
8854    (set_attr "length" "8,12")]
8857 (define_insn "*if_shift_move"
8858   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8859         (if_then_else:SI
8860          (match_operator 5 "arm_comparison_operator"
8861           [(match_operand 6 "cc_register" "") (const_int 0)])
8862          (match_operator:SI 4 "shift_operator"
8863           [(match_operand:SI 2 "s_register_operand" "r,r,r")
8864            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
8865          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8866   "TARGET_ARM"
8867   "@
8868    mov%d5\\t%0, %2%S4
8869    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
8870    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8871   [(set_attr "conds" "use")
8872    (set_attr "shift" "2")
8873    (set_attr "length" "4,8,8")
8874    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
8875                       (const_string "alu_shift")
8876                       (const_string "alu_shift_reg")))]
8879 (define_insn "*ifcompare_move_shift"
8880   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8881         (if_then_else:SI
8882          (match_operator 6 "arm_comparison_operator"
8883           [(match_operand:SI 4 "s_register_operand" "r,r")
8884            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8885          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8886          (match_operator:SI 7 "shift_operator"
8887           [(match_operand:SI 2 "s_register_operand" "r,r")
8888            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
8889    (clobber (reg:CC CC_REGNUM))]
8890   "TARGET_ARM"
8891   "#"
8892   [(set_attr "conds" "clob")
8893    (set_attr "length" "8,12")]
8896 (define_insn "*if_move_shift"
8897   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8898         (if_then_else:SI
8899          (match_operator 5 "arm_comparison_operator"
8900           [(match_operand 6 "cc_register" "") (const_int 0)])
8901          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8902          (match_operator:SI 4 "shift_operator"
8903           [(match_operand:SI 2 "s_register_operand" "r,r,r")
8904            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
8905   "TARGET_ARM"
8906   "@
8907    mov%D5\\t%0, %2%S4
8908    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
8909    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8910   [(set_attr "conds" "use")
8911    (set_attr "shift" "2")
8912    (set_attr "length" "4,8,8")
8913    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
8914                       (const_string "alu_shift")
8915                       (const_string "alu_shift_reg")))]
8918 (define_insn "*ifcompare_shift_shift"
8919   [(set (match_operand:SI 0 "s_register_operand" "=r")
8920         (if_then_else:SI
8921          (match_operator 7 "arm_comparison_operator"
8922           [(match_operand:SI 5 "s_register_operand" "r")
8923            (match_operand:SI 6 "arm_add_operand" "rIL")])
8924          (match_operator:SI 8 "shift_operator"
8925           [(match_operand:SI 1 "s_register_operand" "r")
8926            (match_operand:SI 2 "arm_rhs_operand" "rM")])
8927          (match_operator:SI 9 "shift_operator"
8928           [(match_operand:SI 3 "s_register_operand" "r")
8929            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
8930    (clobber (reg:CC CC_REGNUM))]
8931   "TARGET_ARM"
8932   "#"
8933   [(set_attr "conds" "clob")
8934    (set_attr "length" "12")]
8937 (define_insn "*if_shift_shift"
8938   [(set (match_operand:SI 0 "s_register_operand" "=r")
8939         (if_then_else:SI
8940          (match_operator 5 "arm_comparison_operator"
8941           [(match_operand 8 "cc_register" "") (const_int 0)])
8942          (match_operator:SI 6 "shift_operator"
8943           [(match_operand:SI 1 "s_register_operand" "r")
8944            (match_operand:SI 2 "arm_rhs_operand" "rM")])
8945          (match_operator:SI 7 "shift_operator"
8946           [(match_operand:SI 3 "s_register_operand" "r")
8947            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
8948   "TARGET_ARM"
8949   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8950   [(set_attr "conds" "use")
8951    (set_attr "shift" "1")
8952    (set_attr "length" "8")
8953    (set (attr "type") (if_then_else
8954                         (and (match_operand 2 "const_int_operand" "")
8955                              (match_operand 4 "const_int_operand" ""))
8956                       (const_string "alu_shift")
8957                       (const_string "alu_shift_reg")))]
8960 (define_insn "*ifcompare_not_arith"
8961   [(set (match_operand:SI 0 "s_register_operand" "=r")
8962         (if_then_else:SI
8963          (match_operator 6 "arm_comparison_operator"
8964           [(match_operand:SI 4 "s_register_operand" "r")
8965            (match_operand:SI 5 "arm_add_operand" "rIL")])
8966          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8967          (match_operator:SI 7 "shiftable_operator"
8968           [(match_operand:SI 2 "s_register_operand" "r")
8969            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
8970    (clobber (reg:CC CC_REGNUM))]
8971   "TARGET_ARM"
8972   "#"
8973   [(set_attr "conds" "clob")
8974    (set_attr "length" "12")]
8977 (define_insn "*if_not_arith"
8978   [(set (match_operand:SI 0 "s_register_operand" "=r")
8979         (if_then_else:SI
8980          (match_operator 5 "arm_comparison_operator"
8981           [(match_operand 4 "cc_register" "") (const_int 0)])
8982          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8983          (match_operator:SI 6 "shiftable_operator"
8984           [(match_operand:SI 2 "s_register_operand" "r")
8985            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
8986   "TARGET_ARM"
8987   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8988   [(set_attr "conds" "use")
8989    (set_attr "length" "8")]
8992 (define_insn "*ifcompare_arith_not"
8993   [(set (match_operand:SI 0 "s_register_operand" "=r")
8994         (if_then_else:SI
8995          (match_operator 6 "arm_comparison_operator"
8996           [(match_operand:SI 4 "s_register_operand" "r")
8997            (match_operand:SI 5 "arm_add_operand" "rIL")])
8998          (match_operator:SI 7 "shiftable_operator"
8999           [(match_operand:SI 2 "s_register_operand" "r")
9000            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9001          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9002    (clobber (reg:CC CC_REGNUM))]
9003   "TARGET_ARM"
9004   "#"
9005   [(set_attr "conds" "clob")
9006    (set_attr "length" "12")]
9009 (define_insn "*if_arith_not"
9010   [(set (match_operand:SI 0 "s_register_operand" "=r")
9011         (if_then_else:SI
9012          (match_operator 5 "arm_comparison_operator"
9013           [(match_operand 4 "cc_register" "") (const_int 0)])
9014          (match_operator:SI 6 "shiftable_operator"
9015           [(match_operand:SI 2 "s_register_operand" "r")
9016            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9017          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9018   "TARGET_ARM"
9019   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9020   [(set_attr "conds" "use")
9021    (set_attr "length" "8")]
9024 (define_insn "*ifcompare_neg_move"
9025   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9026         (if_then_else:SI
9027          (match_operator 5 "arm_comparison_operator"
9028           [(match_operand:SI 3 "s_register_operand" "r,r")
9029            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9030          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9031          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9032    (clobber (reg:CC CC_REGNUM))]
9033   "TARGET_ARM"
9034   "#"
9035   [(set_attr "conds" "clob")
9036    (set_attr "length" "8,12")]
9039 (define_insn "*if_neg_move"
9040   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9041         (if_then_else:SI
9042          (match_operator 4 "arm_comparison_operator"
9043           [(match_operand 3 "cc_register" "") (const_int 0)])
9044          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9045          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9046   "TARGET_ARM"
9047   "@
9048    rsb%d4\\t%0, %2, #0
9049    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9050    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9051   [(set_attr "conds" "use")
9052    (set_attr "length" "4,8,8")]
9055 (define_insn "*ifcompare_move_neg"
9056   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9057         (if_then_else:SI
9058          (match_operator 5 "arm_comparison_operator"
9059           [(match_operand:SI 3 "s_register_operand" "r,r")
9060            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9061          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9062          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9063    (clobber (reg:CC CC_REGNUM))]
9064   "TARGET_ARM"
9065   "#"
9066   [(set_attr "conds" "clob")
9067    (set_attr "length" "8,12")]
9070 (define_insn "*if_move_neg"
9071   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9072         (if_then_else:SI
9073          (match_operator 4 "arm_comparison_operator"
9074           [(match_operand 3 "cc_register" "") (const_int 0)])
9075          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9076          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9077   "TARGET_ARM"
9078   "@
9079    rsb%D4\\t%0, %2, #0
9080    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9081    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9082   [(set_attr "conds" "use")
9083    (set_attr "length" "4,8,8")]
9086 (define_insn "*arith_adjacentmem"
9087   [(set (match_operand:SI 0 "s_register_operand" "=r")
9088         (match_operator:SI 1 "shiftable_operator"
9089          [(match_operand:SI 2 "memory_operand" "m")
9090           (match_operand:SI 3 "memory_operand" "m")]))
9091    (clobber (match_scratch:SI 4 "=r"))]
9092   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9093   "*
9094   {
9095     rtx ldm[3];
9096     rtx arith[4];
9097     int val1 = 0, val2 = 0;
9099     if (REGNO (operands[0]) > REGNO (operands[4]))
9100       {
9101         ldm[1] = operands[4];
9102         ldm[2] = operands[0];
9103       }
9104     else
9105       {
9106         ldm[1] = operands[0];
9107         ldm[2] = operands[4];
9108       }
9109     if (GET_CODE (XEXP (operands[2], 0)) != REG)
9110       val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
9111     if (GET_CODE (XEXP (operands[3], 0)) != REG)
9112       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9113     arith[0] = operands[0];
9114     arith[3] = operands[1];
9115     if (val1 < val2)
9116       {
9117         arith[1] = ldm[1];
9118         arith[2] = ldm[2];
9119       }
9120     else
9121       {
9122         arith[1] = ldm[2];
9123         arith[2] = ldm[1];
9124       }
9125    if (val1 && val2)
9126       {
9127         rtx ops[3];
9128         ldm[0] = ops[0] = operands[4];
9129         ops[1] = XEXP (XEXP (operands[2], 0), 0);
9130         ops[2] = XEXP (XEXP (operands[2], 0), 1);
9131         output_add_immediate (ops);
9132         if (val1 < val2)
9133           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9134         else
9135           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9136       }
9137     else if (val1)
9138       {
9139         ldm[0] = XEXP (operands[3], 0);
9140         if (val1 < val2)
9141           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9142         else
9143           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9144       }
9145     else
9146       {
9147         ldm[0] = XEXP (operands[2], 0);
9148         if (val1 < val2)
9149           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9150         else
9151           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9152       }
9153     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9154     return \"\";
9155   }"
9156   [(set_attr "length" "12")
9157    (set_attr "predicable" "yes")
9158    (set_attr "type" "load1")]
9161 ;; the arm can support extended pre-inc instructions
9163 ;; In all these cases, we use operands 0 and 1 for the register being
9164 ;; incremented because those are the operands that local-alloc will
9165 ;; tie and these are the pair most likely to be tieable (and the ones
9166 ;; that will benefit the most).
9168 ;; We reject the frame pointer if it occurs anywhere in these patterns since
9169 ;; elimination will cause too many headaches.
9171 (define_insn "*strqi_preinc"
9172   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9173                          (match_operand:SI 2 "index_operand" "rJ")))
9174         (match_operand:QI 3 "s_register_operand" "r"))
9175    (set (match_operand:SI 0 "s_register_operand" "=r")
9176         (plus:SI (match_dup 1) (match_dup 2)))]
9177   "TARGET_ARM
9178    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9179    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9180    && (GET_CODE (operands[2]) != REG
9181        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9182   "str%?b\\t%3, [%0, %2]!"
9183   [(set_attr "type" "store1")
9184    (set_attr "predicable" "yes")]
9187 (define_insn "*strqi_predec"
9188   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9189                           (match_operand:SI 2 "s_register_operand" "r")))
9190         (match_operand:QI 3 "s_register_operand" "r"))
9191    (set (match_operand:SI 0 "s_register_operand" "=r")
9192         (minus:SI (match_dup 1) (match_dup 2)))]
9193   "TARGET_ARM
9194    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9195    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9196    && (GET_CODE (operands[2]) != REG
9197        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9198   "str%?b\\t%3, [%0, -%2]!"
9199   [(set_attr "type" "store1")
9200    (set_attr "predicable" "yes")]
9203 (define_insn "*loadqi_preinc"
9204   [(set (match_operand:QI 3 "s_register_operand" "=r")
9205         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9206                          (match_operand:SI 2 "index_operand" "rJ"))))
9207    (set (match_operand:SI 0 "s_register_operand" "=r")
9208         (plus:SI (match_dup 1) (match_dup 2)))]
9209   "TARGET_ARM
9210    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9211    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9212    && (GET_CODE (operands[2]) != REG
9213        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9214   "ldr%?b\\t%3, [%0, %2]!"
9215   [(set_attr "type" "load_byte")
9216    (set_attr "predicable" "yes")]
9219 (define_insn "*loadqi_predec"
9220   [(set (match_operand:QI 3 "s_register_operand" "=r")
9221         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9222                           (match_operand:SI 2 "s_register_operand" "r"))))
9223    (set (match_operand:SI 0 "s_register_operand" "=r")
9224         (minus:SI (match_dup 1) (match_dup 2)))]
9225   "TARGET_ARM
9226    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9227    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9228    && (GET_CODE (operands[2]) != REG
9229        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9230   "ldr%?b\\t%3, [%0, -%2]!"
9231   [(set_attr "type" "load_byte")
9232    (set_attr "predicable" "yes")]
9235 (define_insn "*loadqisi_preinc"
9236   [(set (match_operand:SI 3 "s_register_operand" "=r")
9237         (zero_extend:SI
9238          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9239                           (match_operand:SI 2 "index_operand" "rJ")))))
9240    (set (match_operand:SI 0 "s_register_operand" "=r")
9241         (plus:SI (match_dup 1) (match_dup 2)))]
9242   "TARGET_ARM
9243    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9244    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9245    && (GET_CODE (operands[2]) != REG
9246        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9247   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
9248   [(set_attr "type" "load_byte")
9249    (set_attr "predicable" "yes")]
9252 (define_insn "*loadqisi_predec"
9253   [(set (match_operand:SI 3 "s_register_operand" "=r")
9254         (zero_extend:SI
9255          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9256                            (match_operand:SI 2 "s_register_operand" "r")))))
9257    (set (match_operand:SI 0 "s_register_operand" "=r")
9258         (minus:SI (match_dup 1) (match_dup 2)))]
9259   "TARGET_ARM
9260    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9261    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9262    && (GET_CODE (operands[2]) != REG
9263        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9264   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
9265   [(set_attr "type" "load_byte")
9266    (set_attr "predicable" "yes")]
9269 (define_insn "*strsi_preinc"
9270   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9271                          (match_operand:SI 2 "index_operand" "rJ")))
9272         (match_operand:SI 3 "s_register_operand" "r"))
9273    (set (match_operand:SI 0 "s_register_operand" "=r")
9274         (plus:SI (match_dup 1) (match_dup 2)))]
9275   "TARGET_ARM
9276    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9277    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9278    && (GET_CODE (operands[2]) != REG
9279        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9280   "str%?\\t%3, [%0, %2]!"
9281   [(set_attr "type" "store1")
9282    (set_attr "predicable" "yes")]
9285 (define_insn "*strsi_predec"
9286   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9287                           (match_operand:SI 2 "s_register_operand" "r")))
9288         (match_operand:SI 3 "s_register_operand" "r"))
9289    (set (match_operand:SI 0 "s_register_operand" "=r")
9290         (minus:SI (match_dup 1) (match_dup 2)))]
9291   "TARGET_ARM
9292    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9293    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9294    && (GET_CODE (operands[2]) != REG
9295        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9296   "str%?\\t%3, [%0, -%2]!"
9297   [(set_attr "type" "store1")
9298    (set_attr "predicable" "yes")]
9301 (define_insn "*loadsi_preinc"
9302   [(set (match_operand:SI 3 "s_register_operand" "=r")
9303         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9304                          (match_operand:SI 2 "index_operand" "rJ"))))
9305    (set (match_operand:SI 0 "s_register_operand" "=r")
9306         (plus:SI (match_dup 1) (match_dup 2)))]
9307   "TARGET_ARM
9308    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9309    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9310    && (GET_CODE (operands[2]) != REG
9311        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9312   "ldr%?\\t%3, [%0, %2]!"
9313   [(set_attr "type" "load1")
9314    (set_attr "predicable" "yes")]
9317 (define_insn "*loadsi_predec"
9318   [(set (match_operand:SI 3 "s_register_operand" "=r")
9319         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9320                           (match_operand:SI 2 "s_register_operand" "r"))))
9321    (set (match_operand:SI 0 "s_register_operand" "=r")
9322         (minus:SI (match_dup 1) (match_dup 2)))]
9323   "TARGET_ARM
9324    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9325    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9326    && (GET_CODE (operands[2]) != REG
9327        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9328   "ldr%?\\t%3, [%0, -%2]!"
9329   [(set_attr "type" "load1")
9330    (set_attr "predicable" "yes")]
9333 (define_insn "*strqi_shiftpreinc"
9334   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9335                           [(match_operand:SI 3 "s_register_operand" "r")
9336                            (match_operand:SI 4 "const_shift_operand" "n")])
9337                          (match_operand:SI 1 "s_register_operand" "0")))
9338         (match_operand:QI 5 "s_register_operand" "r"))
9339    (set (match_operand:SI 0 "s_register_operand" "=r")
9340         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9341                  (match_dup 1)))]
9342   "TARGET_ARM
9343    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9344    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9345    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9346   "str%?b\\t%5, [%0, %3%S2]!"
9347   [(set_attr "type" "store1")
9348    (set_attr "predicable" "yes")]
9351 (define_insn "*strqi_shiftpredec"
9352   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9353                           (match_operator:SI 2 "shift_operator"
9354                            [(match_operand:SI 3 "s_register_operand" "r")
9355                             (match_operand:SI 4 "const_shift_operand" "n")])))
9356         (match_operand:QI 5 "s_register_operand" "r"))
9357    (set (match_operand:SI 0 "s_register_operand" "=r")
9358         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9359                                                  (match_dup 4)])))]
9360   "TARGET_ARM
9361    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9362    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9363    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9364   "str%?b\\t%5, [%0, -%3%S2]!"
9365   [(set_attr "type" "store1")
9366    (set_attr "predicable" "yes")]
9369 (define_insn "*loadqi_shiftpreinc"
9370   [(set (match_operand:QI 5 "s_register_operand" "=r")
9371         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9372                           [(match_operand:SI 3 "s_register_operand" "r")
9373                            (match_operand:SI 4 "const_shift_operand" "n")])
9374                          (match_operand:SI 1 "s_register_operand" "0"))))
9375    (set (match_operand:SI 0 "s_register_operand" "=r")
9376         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9377                  (match_dup 1)))]
9378   "TARGET_ARM
9379    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9380    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9381    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9382   "ldr%?b\\t%5, [%0, %3%S2]!"
9383   [(set_attr "type" "load_byte")
9384    (set_attr "predicable" "yes")]
9387 (define_insn "*loadqi_shiftpredec"
9388   [(set (match_operand:QI 5 "s_register_operand" "=r")
9389         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9390                           (match_operator:SI 2 "shift_operator"
9391                            [(match_operand:SI 3 "s_register_operand" "r")
9392                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9393    (set (match_operand:SI 0 "s_register_operand" "=r")
9394         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9395                                                  (match_dup 4)])))]
9396   "TARGET_ARM
9397    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9398    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9399    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9400   "ldr%?b\\t%5, [%0, -%3%S2]!"
9401   [(set_attr "type" "load_byte")
9402    (set_attr "predicable" "yes")]
9405 (define_insn "*strsi_shiftpreinc"
9406   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9407                           [(match_operand:SI 3 "s_register_operand" "r")
9408                            (match_operand:SI 4 "const_shift_operand" "n")])
9409                          (match_operand:SI 1 "s_register_operand" "0")))
9410         (match_operand:SI 5 "s_register_operand" "r"))
9411    (set (match_operand:SI 0 "s_register_operand" "=r")
9412         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9413                  (match_dup 1)))]
9414   "TARGET_ARM
9415    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9416    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9417    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9418   "str%?\\t%5, [%0, %3%S2]!"
9419   [(set_attr "type" "store1")
9420    (set_attr "predicable" "yes")]
9423 (define_insn "*strsi_shiftpredec"
9424   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9425                           (match_operator:SI 2 "shift_operator"
9426                            [(match_operand:SI 3 "s_register_operand" "r")
9427                             (match_operand:SI 4 "const_shift_operand" "n")])))
9428         (match_operand:SI 5 "s_register_operand" "r"))
9429    (set (match_operand:SI 0 "s_register_operand" "=r")
9430         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9431                                                  (match_dup 4)])))]
9432   "TARGET_ARM
9433    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9434    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9435    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9436   "str%?\\t%5, [%0, -%3%S2]!"
9437   [(set_attr "type" "store1")
9438    (set_attr "predicable" "yes")]
9441 (define_insn "*loadsi_shiftpreinc"
9442   [(set (match_operand:SI 5 "s_register_operand" "=r")
9443         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9444                           [(match_operand:SI 3 "s_register_operand" "r")
9445                            (match_operand:SI 4 "const_shift_operand" "n")])
9446                          (match_operand:SI 1 "s_register_operand" "0"))))
9447    (set (match_operand:SI 0 "s_register_operand" "=r")
9448         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9449                  (match_dup 1)))]
9450   "TARGET_ARM
9451    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9452    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9453    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9454   "ldr%?\\t%5, [%0, %3%S2]!"
9455   [(set_attr "type" "load1")
9456    (set_attr "predicable" "yes")]
9459 (define_insn "*loadsi_shiftpredec"
9460   [(set (match_operand:SI 5 "s_register_operand" "=r")
9461         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9462                           (match_operator:SI 2 "shift_operator"
9463                            [(match_operand:SI 3 "s_register_operand" "r")
9464                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9465    (set (match_operand:SI 0 "s_register_operand" "=r")
9466         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9467                                                  (match_dup 4)])))]
9468   "TARGET_ARM
9469    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9470    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9471    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9472   "ldr%?\\t%5, [%0, -%3%S2]!"
9473   [(set_attr "type" "load1")
9474    (set_attr "predicable" "yes")])
9476 ; It can also support extended post-inc expressions, but combine doesn't
9477 ; try these....
9478 ; It doesn't seem worth adding peepholes for anything but the most common
9479 ; cases since, unlike combine, the increment must immediately follow the load
9480 ; for this pattern to match.
9481 ; We must watch to see that the source/destination register isn't also the
9482 ; same as the base address register, and that if the index is a register,
9483 ; that it is not the same as the base address register.  In such cases the
9484 ; instruction that we would generate would have UNPREDICTABLE behavior so 
9485 ; we cannot use it.
9487 (define_peephole
9488   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9489         (match_operand:QI 2 "s_register_operand" "r"))
9490    (set (match_dup 0)
9491         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9492   "TARGET_ARM
9493    && (REGNO (operands[2]) != REGNO (operands[0]))
9494    && (GET_CODE (operands[1]) != REG
9495        || (REGNO (operands[1]) != REGNO (operands[0])))"
9496   "str%?b\\t%2, [%0], %1"
9499 (define_peephole
9500   [(set (match_operand:QI 0 "s_register_operand" "=r")
9501         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9502    (set (match_dup 1)
9503         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9504   "TARGET_ARM
9505    && REGNO (operands[0]) != REGNO(operands[1])
9506    && (GET_CODE (operands[2]) != REG
9507        || REGNO(operands[0]) != REGNO (operands[2]))"
9508   "ldr%?b\\t%0, [%1], %2"
9511 (define_peephole
9512   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9513         (match_operand:SI 2 "s_register_operand" "r"))
9514    (set (match_dup 0)
9515         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9516   "TARGET_ARM
9517    && (REGNO (operands[2]) != REGNO (operands[0]))
9518    && (GET_CODE (operands[1]) != REG
9519        || (REGNO (operands[1]) != REGNO (operands[0])))"
9520   "str%?\\t%2, [%0], %1"
9523 (define_peephole
9524   [(set (match_operand:SI 0 "s_register_operand" "=r")
9525         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9526    (set (match_dup 1)
9527         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9528   "TARGET_ARM
9529    && REGNO (operands[0]) != REGNO(operands[1])
9530    && (GET_CODE (operands[2]) != REG
9531        || REGNO(operands[0]) != REGNO (operands[2]))"
9532   "ldr%?\\t%0, [%1], %2"
9535 (define_peephole
9536   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9537                          (match_operand:SI 1 "index_operand" "rJ")))
9538         (match_operand:QI 2 "s_register_operand" "r"))
9539    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
9540   "TARGET_ARM
9541    && (REGNO (operands[2]) != REGNO (operands[0]))
9542    && (GET_CODE (operands[1]) != REG
9543        || (REGNO (operands[1]) != REGNO (operands[0])))"
9544   "str%?b\\t%2, [%0, %1]!"
9547 (define_peephole
9548   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9549                           [(match_operand:SI 0 "s_register_operand" "r")
9550                            (match_operand:SI 1 "const_int_operand" "n")])
9551                          (match_operand:SI 2 "s_register_operand" "+r")))
9552         (match_operand:QI 3 "s_register_operand" "r"))
9553    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9554                                (match_dup 2)))]
9555   "TARGET_ARM
9556    && (REGNO (operands[3]) != REGNO (operands[2]))
9557    && (REGNO (operands[0]) != REGNO (operands[2]))"
9558   "str%?b\\t%3, [%2, %0%S4]!"
9561 ; This pattern is never tried by combine, so do it as a peephole
9563 (define_peephole2
9564   [(set (match_operand:SI 0 "arm_general_register_operand" "")
9565         (match_operand:SI 1 "arm_general_register_operand" ""))
9566    (set (reg:CC CC_REGNUM)
9567         (compare:CC (match_dup 1) (const_int 0)))]
9568   "TARGET_ARM"
9569   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9570               (set (match_dup 0) (match_dup 1))])]
9571   ""
9574 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9575 ; reversed, check that the memory references aren't volatile.
9577 (define_peephole
9578   [(set (match_operand:SI 0 "s_register_operand" "=r")
9579         (match_operand:SI 4 "memory_operand" "m"))
9580    (set (match_operand:SI 1 "s_register_operand" "=r")
9581         (match_operand:SI 5 "memory_operand" "m"))
9582    (set (match_operand:SI 2 "s_register_operand" "=r")
9583         (match_operand:SI 6 "memory_operand" "m"))
9584    (set (match_operand:SI 3 "s_register_operand" "=r")
9585         (match_operand:SI 7 "memory_operand" "m"))]
9586   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9587   "*
9588   return emit_ldm_seq (operands, 4);
9589   "
9592 (define_peephole
9593   [(set (match_operand:SI 0 "s_register_operand" "=r")
9594         (match_operand:SI 3 "memory_operand" "m"))
9595    (set (match_operand:SI 1 "s_register_operand" "=r")
9596         (match_operand:SI 4 "memory_operand" "m"))
9597    (set (match_operand:SI 2 "s_register_operand" "=r")
9598         (match_operand:SI 5 "memory_operand" "m"))]
9599   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9600   "*
9601   return emit_ldm_seq (operands, 3);
9602   "
9605 (define_peephole
9606   [(set (match_operand:SI 0 "s_register_operand" "=r")
9607         (match_operand:SI 2 "memory_operand" "m"))
9608    (set (match_operand:SI 1 "s_register_operand" "=r")
9609         (match_operand:SI 3 "memory_operand" "m"))]
9610   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9611   "*
9612   return emit_ldm_seq (operands, 2);
9613   "
9616 (define_peephole
9617   [(set (match_operand:SI 4 "memory_operand" "=m")
9618         (match_operand:SI 0 "s_register_operand" "r"))
9619    (set (match_operand:SI 5 "memory_operand" "=m")
9620         (match_operand:SI 1 "s_register_operand" "r"))
9621    (set (match_operand:SI 6 "memory_operand" "=m")
9622         (match_operand:SI 2 "s_register_operand" "r"))
9623    (set (match_operand:SI 7 "memory_operand" "=m")
9624         (match_operand:SI 3 "s_register_operand" "r"))]
9625   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9626   "*
9627   return emit_stm_seq (operands, 4);
9628   "
9631 (define_peephole
9632   [(set (match_operand:SI 3 "memory_operand" "=m")
9633         (match_operand:SI 0 "s_register_operand" "r"))
9634    (set (match_operand:SI 4 "memory_operand" "=m")
9635         (match_operand:SI 1 "s_register_operand" "r"))
9636    (set (match_operand:SI 5 "memory_operand" "=m")
9637         (match_operand:SI 2 "s_register_operand" "r"))]
9638   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9639   "*
9640   return emit_stm_seq (operands, 3);
9641   "
9644 (define_peephole
9645   [(set (match_operand:SI 2 "memory_operand" "=m")
9646         (match_operand:SI 0 "s_register_operand" "r"))
9647    (set (match_operand:SI 3 "memory_operand" "=m")
9648         (match_operand:SI 1 "s_register_operand" "r"))]
9649   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9650   "*
9651   return emit_stm_seq (operands, 2);
9652   "
9655 (define_split
9656   [(set (match_operand:SI 0 "s_register_operand" "")
9657         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9658                        (const_int 0))
9659                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9660                          [(match_operand:SI 3 "s_register_operand" "")
9661                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
9662    (clobber (match_operand:SI 5 "s_register_operand" ""))]
9663   "TARGET_ARM"
9664   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9665    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9666                               (match_dup 5)))]
9667   ""
9670 ;; This split can be used because CC_Z mode implies that the following
9671 ;; branch will be an equality, or an unsigned inequality, so the sign
9672 ;; extension is not needed.
9674 (define_split
9675   [(set (reg:CC_Z CC_REGNUM)
9676         (compare:CC_Z
9677          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9678                     (const_int 24))
9679          (match_operand 1 "const_int_operand" "")))
9680    (clobber (match_scratch:SI 2 ""))]
9681   "TARGET_ARM
9682    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9683        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9684   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9685    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9686   "
9687   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9688   "
9691 (define_expand "prologue"
9692   [(clobber (const_int 0))]
9693   "TARGET_EITHER"
9694   "if (TARGET_ARM)
9695      arm_expand_prologue ();
9696    else
9697      thumb_expand_prologue ();
9698   DONE;
9699   "
9702 (define_expand "epilogue"
9703   [(clobber (const_int 0))]
9704   "TARGET_EITHER"
9705   "
9706   if (current_function_calls_eh_return)
9707     emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
9708   if (TARGET_THUMB)
9709     thumb_expand_epilogue ();
9710   else if (USE_RETURN_INSN (FALSE))
9711     {
9712       emit_jump_insn (gen_return ());
9713       DONE;
9714     }
9715   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9716         gen_rtvec (1,
9717                 gen_rtx_RETURN (VOIDmode)),
9718         VUNSPEC_EPILOGUE));
9719   DONE;
9720   "
9723 ;; Note - although unspec_volatile's USE all hard registers,
9724 ;; USEs are ignored after relaod has completed.  Thus we need
9725 ;; to add an unspec of the link register to ensure that flow
9726 ;; does not think that it is unused by the sibcall branch that
9727 ;; will replace the standard function epilogue.
9728 (define_insn "sibcall_epilogue"
9729   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9730               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9731   "TARGET_ARM"
9732   "*
9733   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9734     return output_return_instruction (const_true_rtx, FALSE, FALSE);
9735   return arm_output_epilogue (next_nonnote_insn (insn));
9736   "
9737 ;; Length is absolute worst case
9738   [(set_attr "length" "44")
9739    (set_attr "type" "block")
9740    ;; We don't clobber the conditions, but the potential length of this
9741    ;; operation is sufficient to make conditionalizing the sequence 
9742    ;; unlikely to be profitable.
9743    (set_attr "conds" "clob")]
9746 (define_insn "*epilogue_insns"
9747   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9748   "TARGET_EITHER"
9749   "*
9750   if (TARGET_ARM)
9751     return arm_output_epilogue (NULL);
9752   else /* TARGET_THUMB */
9753     return thumb_unexpanded_epilogue ();
9754   "
9755   ; Length is absolute worst case
9756   [(set_attr "length" "44")
9757    (set_attr "type" "block")
9758    ;; We don't clobber the conditions, but the potential length of this
9759    ;; operation is sufficient to make conditionalizing the sequence 
9760    ;; unlikely to be profitable.
9761    (set_attr "conds" "clob")]
9764 (define_expand "eh_epilogue"
9765   [(use (match_operand:SI 0 "register_operand" ""))
9766    (use (match_operand:SI 1 "register_operand" ""))
9767    (use (match_operand:SI 2 "register_operand" ""))]
9768   "TARGET_EITHER"
9769   "
9770   {
9771     cfun->machine->eh_epilogue_sp_ofs = operands[1];
9772     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9773       {
9774         rtx ra = gen_rtx_REG (Pmode, 2);
9776         emit_move_insn (ra, operands[2]);
9777         operands[2] = ra;
9778       }
9779     /* This is a hack -- we may have crystalized the function type too
9780        early.  */
9781     cfun->machine->func_type = 0;
9782   }"
9785 ;; This split is only used during output to reduce the number of patterns
9786 ;; that need assembler instructions adding to them.  We allowed the setting
9787 ;; of the conditions to be implicit during rtl generation so that
9788 ;; the conditional compare patterns would work.  However this conflicts to
9789 ;; some extent with the conditional data operations, so we have to split them
9790 ;; up again here.
9792 (define_split
9793   [(set (match_operand:SI 0 "s_register_operand" "")
9794         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9795                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9796                          (match_dup 0)
9797                          (match_operand 4 "" "")))
9798    (clobber (reg:CC CC_REGNUM))]
9799   "TARGET_ARM && reload_completed"
9800   [(set (match_dup 5) (match_dup 6))
9801    (cond_exec (match_dup 7)
9802               (set (match_dup 0) (match_dup 4)))]
9803   "
9804   {
9805     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9806                                              operands[2], operands[3]);
9807     enum rtx_code rc = GET_CODE (operands[1]);
9809     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9810     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9811     if (mode == CCFPmode || mode == CCFPEmode)
9812       rc = reverse_condition_maybe_unordered (rc);
9813     else
9814       rc = reverse_condition (rc);
9816     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9817   }"
9820 (define_split
9821   [(set (match_operand:SI 0 "s_register_operand" "")
9822         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9823                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9824                          (match_operand 4 "" "")
9825                          (match_dup 0)))
9826    (clobber (reg:CC CC_REGNUM))]
9827   "TARGET_ARM && reload_completed"
9828   [(set (match_dup 5) (match_dup 6))
9829    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9830               (set (match_dup 0) (match_dup 4)))]
9831   "
9832   {
9833     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9834                                              operands[2], operands[3]);
9836     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9837     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9838   }"
9841 (define_split
9842   [(set (match_operand:SI 0 "s_register_operand" "")
9843         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9844                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9845                          (match_operand 4 "" "")
9846                          (match_operand 5 "" "")))
9847    (clobber (reg:CC CC_REGNUM))]
9848   "TARGET_ARM && reload_completed"
9849   [(set (match_dup 6) (match_dup 7))
9850    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9851               (set (match_dup 0) (match_dup 4)))
9852    (cond_exec (match_dup 8)
9853               (set (match_dup 0) (match_dup 5)))]
9854   "
9855   {
9856     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9857                                              operands[2], operands[3]);
9858     enum rtx_code rc = GET_CODE (operands[1]);
9860     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9861     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9862     if (mode == CCFPmode || mode == CCFPEmode)
9863       rc = reverse_condition_maybe_unordered (rc);
9864     else
9865       rc = reverse_condition (rc);
9867     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9868   }"
9871 (define_split
9872   [(set (match_operand:SI 0 "s_register_operand" "")
9873         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9874                           [(match_operand:SI 2 "s_register_operand" "")
9875                            (match_operand:SI 3 "arm_add_operand" "")])
9876                          (match_operand:SI 4 "arm_rhs_operand" "")
9877                          (not:SI
9878                           (match_operand:SI 5 "s_register_operand" ""))))
9879    (clobber (reg:CC CC_REGNUM))]
9880   "TARGET_ARM && reload_completed"
9881   [(set (match_dup 6) (match_dup 7))
9882    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9883               (set (match_dup 0) (match_dup 4)))
9884    (cond_exec (match_dup 8)
9885               (set (match_dup 0) (not:SI (match_dup 5))))]
9886   "
9887   {
9888     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9889                                              operands[2], operands[3]);
9890     enum rtx_code rc = GET_CODE (operands[1]);
9892     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9893     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9894     if (mode == CCFPmode || mode == CCFPEmode)
9895       rc = reverse_condition_maybe_unordered (rc);
9896     else
9897       rc = reverse_condition (rc);
9899     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9900   }"
9903 (define_insn "*cond_move_not"
9904   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9905         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9906                           [(match_operand 3 "cc_register" "") (const_int 0)])
9907                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9908                          (not:SI
9909                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
9910   "TARGET_ARM"
9911   "@
9912    mvn%D4\\t%0, %2
9913    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
9914   [(set_attr "conds" "use")
9915    (set_attr "length" "4,8")]
9918 ;; The next two patterns occur when an AND operation is followed by a
9919 ;; scc insn sequence 
9921 (define_insn "*sign_extract_onebit"
9922   [(set (match_operand:SI 0 "s_register_operand" "=r")
9923         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9924                          (const_int 1)
9925                          (match_operand:SI 2 "const_int_operand" "n")))
9926     (clobber (reg:CC CC_REGNUM))]
9927   "TARGET_ARM"
9928   "*
9929     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9930     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
9931     return \"mvnne\\t%0, #0\";
9932   "
9933   [(set_attr "conds" "clob")
9934    (set_attr "length" "8")]
9937 (define_insn "*not_signextract_onebit"
9938   [(set (match_operand:SI 0 "s_register_operand" "=r")
9939         (not:SI
9940          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9941                           (const_int 1)
9942                           (match_operand:SI 2 "const_int_operand" "n"))))
9943    (clobber (reg:CC CC_REGNUM))]
9944   "TARGET_ARM"
9945   "*
9946     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9947     output_asm_insn (\"tst\\t%1, %2\", operands);
9948     output_asm_insn (\"mvneq\\t%0, #0\", operands);
9949     return \"movne\\t%0, #0\";
9950   "
9951   [(set_attr "conds" "clob")
9952    (set_attr "length" "12")]
9955 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
9956 ;; expressions.  For simplicity, the first register is also in the unspec
9957 ;; part.
9958 (define_insn "*push_multi"
9959   [(match_parallel 2 "multi_register_push"
9960     [(set (match_operand:BLK 0 "memory_operand" "=m")
9961           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
9962                       UNSPEC_PUSH_MULT))])]
9963   "TARGET_ARM"
9964   "*
9965   {
9966     int num_saves = XVECLEN (operands[2], 0);
9967      
9968     /* For the StrongARM at least it is faster to
9969        use STR to store only a single register.  */
9970     if (num_saves == 1)
9971       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9972     else
9973       {
9974         int i;
9975         char pattern[100];
9977         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9979         for (i = 1; i < num_saves; i++)
9980           {
9981             strcat (pattern, \", %|\");
9982             strcat (pattern,
9983                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9984           }
9986         strcat (pattern, \"}\");
9987         output_asm_insn (pattern, operands);
9988       }
9990     return \"\";
9991   }"
9992   [(set_attr "type" "store4")]
9995 (define_insn "stack_tie"
9996   [(set (mem:BLK (scratch))
9997         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
9998                      (match_operand:SI 1 "s_register_operand" "r")]
9999                     UNSPEC_PRLG_STK))]
10000   ""
10001   ""
10002   [(set_attr "length" "0")]
10005 ;; Similarly for the floating point registers
10006 (define_insn "*push_fp_multi"
10007   [(match_parallel 2 "multi_register_push"
10008     [(set (match_operand:BLK 0 "memory_operand" "=m")
10009           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10010                       UNSPEC_PUSH_MULT))])]
10011   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
10012   "*
10013   {
10014     char pattern[100];
10016     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10017     output_asm_insn (pattern, operands);
10018     return \"\";
10019   }"
10020   [(set_attr "type" "f_store")]
10023 ;; Special patterns for dealing with the constant pool
10025 (define_insn "align_4"
10026   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10027   "TARGET_EITHER"
10028   "*
10029   assemble_align (32);
10030   return \"\";
10031   "
10034 (define_insn "align_8"
10035   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10036   "TARGET_EITHER"
10037   "*
10038   assemble_align (64);
10039   return \"\";
10040   "
10043 (define_insn "consttable_end"
10044   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10045   "TARGET_EITHER"
10046   "*
10047   making_const_table = FALSE;
10048   return \"\";
10049   "
10052 (define_insn "consttable_1"
10053   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10054   "TARGET_THUMB"
10055   "*
10056   making_const_table = TRUE;
10057   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10058   assemble_zeros (3);
10059   return \"\";
10060   "
10061   [(set_attr "length" "4")]
10064 (define_insn "consttable_2"
10065   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10066   "TARGET_THUMB"
10067   "*
10068   making_const_table = TRUE;
10069   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10070   assemble_zeros (2);
10071   return \"\";
10072   "
10073   [(set_attr "length" "4")]
10076 (define_insn "consttable_4"
10077   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10078   "TARGET_EITHER"
10079   "*
10080   {
10081     making_const_table = TRUE;
10082     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10083       {
10084       case MODE_FLOAT:
10085       {
10086         REAL_VALUE_TYPE r;
10087         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10088         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10089         break;
10090       }
10091       default:
10092         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
10093         break;
10094       }
10095     return \"\";
10096   }"
10097   [(set_attr "length" "4")]
10100 (define_insn "consttable_8"
10101   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10102   "TARGET_EITHER"
10103   "*
10104   {
10105     making_const_table = TRUE;
10106     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10107       {
10108        case MODE_FLOAT:
10109         {
10110           REAL_VALUE_TYPE r;
10111           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10112           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10113           break;
10114         }
10115       default:
10116         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10117         break;
10118       }
10119     return \"\";
10120   }"
10121   [(set_attr "length" "8")]
10124 ;; Miscellaneous Thumb patterns
10126 (define_expand "tablejump"
10127   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10128               (use (label_ref (match_operand 1 "" "")))])]
10129   "TARGET_THUMB"
10130   "
10131   if (flag_pic)
10132     {
10133       /* Hopefully, CSE will eliminate this copy.  */
10134       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10135       rtx reg2 = gen_reg_rtx (SImode);
10137       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10138       operands[0] = reg2;
10139     }
10140   "
10143 ;; NB never uses BX.
10144 (define_insn "*thumb_tablejump"
10145   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10146    (use (label_ref (match_operand 1 "" "")))]
10147   "TARGET_THUMB"
10148   "mov\\t%|pc, %0"
10149   [(set_attr "length" "2")]
10152 ;; V5 Instructions,
10154 (define_insn "clzsi2"
10155   [(set (match_operand:SI 0 "s_register_operand" "=r")
10156         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10157   "TARGET_ARM && arm_arch5"
10158   "clz%?\\t%0, %1"
10159   [(set_attr "predicable" "yes")])
10161 (define_expand "ffssi2"
10162   [(set (match_operand:SI 0 "s_register_operand" "")
10163         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10164   "TARGET_ARM && arm_arch5"
10165   "
10166   {
10167     rtx t1, t2, t3;
10169     t1 = gen_reg_rtx (SImode);
10170     t2 = gen_reg_rtx (SImode);
10171     t3 = gen_reg_rtx (SImode);
10173     emit_insn (gen_negsi2 (t1, operands[1]));
10174     emit_insn (gen_andsi3 (t2, operands[1], t1));
10175     emit_insn (gen_clzsi2 (t3, t2));
10176     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10177     DONE;
10178   }"
10181 (define_expand "ctzsi2"
10182   [(set (match_operand:SI 0 "s_register_operand" "")
10183         (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10184   "TARGET_ARM && arm_arch5"
10185   "
10186   {
10187     rtx t1, t2, t3;
10189     t1 = gen_reg_rtx (SImode);
10190     t2 = gen_reg_rtx (SImode);
10191     t3 = gen_reg_rtx (SImode);
10193     emit_insn (gen_negsi2 (t1, operands[1]));
10194     emit_insn (gen_andsi3 (t2, operands[1], t1));
10195     emit_insn (gen_clzsi2 (t3, t2));
10196     emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10197     DONE;
10198   }"
10201 ;; V5E instructions.
10203 (define_insn "prefetch"
10204   [(prefetch (match_operand:SI 0 "address_operand" "p")
10205              (match_operand:SI 1 "" "")
10206              (match_operand:SI 2 "" ""))]
10207   "TARGET_ARM && arm_arch5e"
10208   "pld\\t%a0")
10210 ;; General predication pattern
10212 (define_cond_exec
10213   [(match_operator 0 "arm_comparison_operator"
10214     [(match_operand 1 "cc_register" "")
10215      (const_int 0)])]
10216   "TARGET_ARM"
10217   ""
10220 (define_insn "prologue_use"
10221   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10222   ""
10223   "%@ %0 needed for prologue"
10227 ;; Patterns for exception handling
10229 (define_expand "eh_return"
10230   [(use (match_operand 0 "general_operand" ""))]
10231   "TARGET_EITHER"
10232   "
10233   {
10234     if (TARGET_ARM)
10235       emit_insn (gen_arm_eh_return (operands[0]));
10236     else
10237       emit_insn (gen_thumb_eh_return (operands[0]));
10238     DONE;
10239   }"
10241                                    
10242 ;; We can't expand this before we know where the link register is stored.
10243 (define_insn_and_split "arm_eh_return"
10244   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10245                     VUNSPEC_EH_RETURN)
10246    (clobber (match_scratch:SI 1 "=&r"))]
10247   "TARGET_ARM"
10248   "#"
10249   "&& reload_completed"
10250   [(const_int 0)]
10251   "
10252   {
10253     arm_set_return_address (operands[0], operands[1]);
10254     DONE;
10255   }"
10258 (define_insn_and_split "thumb_eh_return"
10259   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10260                     VUNSPEC_EH_RETURN)
10261    (clobber (match_scratch:SI 1 "=&l"))]
10262   "TARGET_THUMB"
10263   "#"
10264   "&& reload_completed"
10265   [(const_int 0)]
10266   "
10267   {
10268     thumb_set_return_address (operands[0], operands[1]);
10269     DONE;
10270   }"
10273 ;; Load the FPA co-processor patterns
10274 (include "fpa.md")
10275 ;; Load the Maverick co-processor patterns
10276 (include "cirrus.md")
10277 ;; Load the Intel Wireless Multimedia Extension patterns
10278 (include "iwmmxt.md")
10279 ;; Load the VFP co-processor patterns
10280 (include "vfp.md")